diff --git a/src/featureFlags.js b/src/featureFlags.js index dc9f2d7c46e2..76dd3736843a 100644 --- a/src/featureFlags.js +++ b/src/featureFlags.js @@ -22,7 +22,6 @@ let featureFlags = { experimental: [ 'optimizeUniversalDefaults', 'generalizedModifiers', - // 'variantGrouping', ], } diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js index 6382ca7cf3dc..c56597e92e9e 100644 --- a/src/lib/defaultExtractor.js +++ b/src/lib/defaultExtractor.js @@ -21,7 +21,6 @@ export function defaultExtractor(context) { function* buildRegExps(context) { let separator = context.tailwindConfig.separator - let variantGroupingEnabled = flagEnabled(context.tailwindConfig, 'variantGrouping') let prefix = context.tailwindConfig.prefix !== '' ? regex.optional(regex.pattern([/-?/, regex.escape(context.tailwindConfig.prefix)])) @@ -103,15 +102,7 @@ function* buildRegExps(context) { prefix, - 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, + utility, ]) } diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js index 6ced76937f1a..475cbeff74ff 100644 --- a/src/lib/generateRules.js +++ b/src/lib/generateRules.js @@ -573,7 +573,7 @@ function* recordCandidates(matches, classCandidate) { } } -function* resolveMatches(candidate, context, original = candidate) { +function* resolveMatches(candidate, context) { let separator = context.tailwindConfig.separator let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse() let important = false @@ -583,15 +583,6 @@ function* resolveMatches(candidate, context, original = candidate) { classCandidate = classCandidate.slice(1) } - if (flagEnabled(context.tailwindConfig, 'variantGrouping')) { - if (classCandidate.startsWith('(') && classCandidate.endsWith(')')) { - let base = variants.slice().reverse().join(separator) - for (let part of splitAtTopLevelOnly(classCandidate.slice(1, -1), ',')) { - yield* resolveMatches(base + separator + part, context, original) - } - } - } - // TODO: Reintroduce this in ways that doesn't break on false positives // function sortAgainst(toSort, against) { // return toSort.slice().sort((a, z) => { @@ -780,7 +771,7 @@ function* resolveMatches(candidate, context, original = candidate) { match[1].raws.tailwind = { ...match[1].raws.tailwind, candidate } // Apply final format selector - match = applyFinalFormat(match, { context, candidate, original }) + match = applyFinalFormat(match, { context, candidate }) // Skip rules with invalid selectors // This will cause the candidate to be added to the "not class" @@ -794,7 +785,7 @@ function* resolveMatches(candidate, context, original = candidate) { } } -function applyFinalFormat(match, { context, candidate, original }) { +function applyFinalFormat(match, { context, candidate }) { if (!match[0].collectedFormats) { return match } diff --git a/tests/variant-grouping.test.skip.js b/tests/variant-grouping.test.skip.js deleted file mode 100644 index aba113783009..000000000000 --- a/tests/variant-grouping.test.skip.js +++ /dev/null @@ -1,280 +0,0 @@ -import { run, html, css } from './util/run' - -// TODO: Remove this once we enable this by default -it('should not generate nested selectors if the feature flag is not enabled', () => { - let config = { - content: [{ raw: html`
` }], - corePlugins: { preflight: false }, - plugins: [], - } - - let input = css` - @tailwind utilities; - ` - - return run(input, config).then((result) => { - expect(result.css).toMatchFormattedCss(css` - .italic { - font-style: italic; - } - .underline { - text-decoration-line: underline; - } - `) - }) -}) - -it('should be possible to group variants', () => { - 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 (min-width: 768px) { - .md\:\(underline\2c italic\) { - font-style: italic; - text-decoration-line: underline; - } - } - `) - }) -}) - -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', - content: [{ raw: html`
` }], - corePlugins: { preflight: false }, - plugins: [], - } - - let input = css` - @tailwind utilities; - ` - - return run(input, config).then((result) => { - expect(result.css).toMatchFormattedCss(css` - @media (min-width: 768px) { - @media (prefers-color-scheme: dark) { - .md\:dark\:\(underline\2c italic\) { - font-style: italic; - text-decoration-line: underline; - } - } - } - `) - }) -}) - -it('should be possible to group nested grouped variants', () => { - 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 (min-width: 768px) { - .md\:\(underline\2c italic\2c hover\:\(uppercase\2c font-bold\)\) { - font-style: italic; - text-decoration-line: underline; - } - .md\:\(underline\2c italic\2c hover\:\(uppercase\2c font-bold\)\):hover { - font-weight: 700; - text-transform: uppercase; - } - } - `) - }) -}) - -it('should be possible to use nested multiple grouped variants', () => { - 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 (min-width: 768px) { - .md\:\(text-black\2c dark\:\(text-white\2c hover\:focus\:text-gray-100\)\) { - --tw-text-opacity: 1; - color: rgb(0 0 0 / var(--tw-text-opacity)); - } - @media (prefers-color-scheme: dark) { - .md\:\(text-black\2c dark\:\(text-white\2c hover\:focus\:text-gray-100\)\) { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); - } - .md\:\(text-black\2c dark\:\(text-white\2c hover\:focus\:text-gray-100\)\):focus:hover { - --tw-text-opacity: 1; - color: rgb(243 244 246 / var(--tw-text-opacity)); - } - } - } - `) - }) -}) - -it('should be possible to mix and match nesting and different variant combinations', () => { - 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 (min-width: 768px) { - .md\:\[\&\>\*\]\:\(text-black\2c - dark\:\(text-white\2c - hover\:\[\@supports\(color\:green\)\]\:\[\&\:nth-child\(2n\=1\)\]\:text-gray-100\)\) - > * { - --tw-text-opacity: 1; - color: rgb(0 0 0 / var(--tw-text-opacity)); - } - @media (prefers-color-scheme: dark) { - .md\:\[\&\>\*\]\:\(text-black\2c - dark\:\(text-white\2c - hover\:\[\@supports\(color\:green\)\]\:\[\&\:nth-child\(2n\=1\)\]\:text-gray-100\)\) - > * { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); - } - @supports (color: green) { - .md\:\[\&\>\*\]\:\(text-black\2c - dark\:\(text-white\2c - hover\:\[\@supports\(color\:green\)\]\:\[\&\:nth-child\(2n\=1\)\]\:text-gray-100\)\):nth-child( - 2n=1 - ):hover - > * { - --tw-text-opacity: 1; - color: rgb(243 244 246 / var(--tw-text-opacity)); - } - } - } - } - `) - }) -}) - -it('should group with variants defined in external plugins', () => { - let config = { - experimental: 'all', - content: [ - { - raw: html` -
- `, - }, - ], - corePlugins: { preflight: false }, - plugins: [ - ({ addVariant }) => { - addVariant('ui-active', ['&[data-ui-state~="active"]', '[data-ui-state~="active"] &']) - addVariant('ui-selected', ['&[data-ui-state~="selected"]', '[data-ui-state~="selected"] &']) - }, - ], - } - - let input = css` - @tailwind utilities; - ` - - return run(input, config).then((result) => { - expect(result.css).toMatchFormattedCss(css` - .ui-active\:\(bg-black\2c text-white\)[data-ui-state~='active'] { - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); - } - [data-ui-state~='active'] .ui-active\:\(bg-black\2c text-white\) { - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); - } - .ui-selected\:\(bg-indigo-500\2c underline\)[data-ui-state~='selected'] { - --tw-bg-opacity: 1; - background-color: rgb(99 102 241 / var(--tw-bg-opacity)); - text-decoration-line: underline; - } - [data-ui-state~='selected'] .ui-selected\:\(bg-indigo-500\2c underline\) { - --tw-bg-opacity: 1; - background-color: rgb(99 102 241 / var(--tw-bg-opacity)); - text-decoration-line: underline; - } - `) - }) -})