diff --git a/CHANGELOG.md b/CHANGELOG.md index e2a7a270721b..a092073323a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Don't use pointer cursor on disabled buttons by default ([#5772](https://github.com/tailwindlabs/tailwindcss/pull/5772)) -- Improve `addVariant` API ([#5809](https://github.com/tailwindlabs/tailwindcss/pull/5809)) +- Set default content value in preflight instead of within each before/after utility ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820)) ### Added @@ -21,11 +21,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add all standard `cursor-*` values by default ([#5734](https://github.com/tailwindlabs/tailwindcss/pull/5734)) - Add `grow-*` and `shrink-*` utilities, deprecate `flex-grow-*` and `flex-shrink-*` ([#5733](https://github.com/tailwindlabs/tailwindcss/pull/5733)) - Add `text-decoration-color` utilities ([#5760](https://github.com/tailwindlabs/tailwindcss/pull/5760)) +- Add declarative `addVariant` syntax ([#5809](https://github.com/tailwindlabs/tailwindcss/pull/5809)) ### Fixed - Configure chokidar's `awaitWriteFinish` setting to avoid occasional stale builds on Windows ([#5774](https://github.com/tailwindlabs/tailwindcss/pull/5774)) - Fix CLI `--content` option ([#5775](https://github.com/tailwindlabs/tailwindcss/pull/5775)) +- Fix before/after utilities overriding custom content values at larger breakpoints ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820)) ## [3.0.0-alpha.1] - 2021-10-01 diff --git a/src/corePlugins.js b/src/corePlugins.js index aea6f31229c3..913f4226524c 100644 --- a/src/corePlugins.js +++ b/src/corePlugins.js @@ -22,37 +22,34 @@ export let variantPlugins = { addVariant('file', '&::file-selector-button') - // TODO: Use `addVariant('before', '*::before')` instead, once `content` - // fix is implemented. - addVariant('before', ({ format, withRule }) => { - format('&::before') - - withRule((rule) => { + addVariant('before', ({ container }) => { + container.walkRules((rule) => { let foundContent = false rule.walkDecls('content', () => { foundContent = true }) + if (!foundContent) { - rule.prepend(postcss.decl({ prop: 'content', value: '""' })) + rule.prepend(postcss.decl({ prop: 'content', value: 'var(--tw-content)' })) } }) - }) - // TODO: Use `addVariant('after', '*::after')` instead, once `content` - // fix is implemented. - addVariant('after', ({ format, withRule }) => { - format('&::after') + return '&::before' + }) - withRule((rule) => { + addVariant('after', ({ container }) => { + container.walkRules((rule) => { let foundContent = false rule.walkDecls('content', () => { foundContent = true }) if (!foundContent) { - rule.prepend(postcss.decl({ prop: 'content', value: '""' })) + rule.prepend(postcss.decl({ prop: 'content', value: 'var(--tw-content)' })) } }) + + return '&::after' }) }, @@ -112,22 +109,22 @@ export let variantPlugins = { }, directionVariants: ({ addVariant }) => { - addVariant('ltr', ({ format }) => { + addVariant('ltr', () => { log.warn('rtl-experimental', [ 'The RTL features in Tailwind CSS are currently in preview.', 'Preview features are not covered by semver, and may be improved in breaking ways at any time.', ]) - format('[dir="ltr"] &') + return '[dir="ltr"] &' }) - addVariant('rtl', ({ format }) => { + addVariant('rtl', () => { log.warn('rtl-experimental', [ 'The RTL features in Tailwind CSS are currently in preview.', 'Preview features are not covered by semver, and may be improved in breaking ways at any time.', ]) - format('[dir="rtl"] &') + return '[dir="rtl"] &' }) }, @@ -2265,5 +2262,7 @@ export let corePlugins = { { filterDefault: true } ), willChange: createUtilityPlugin('willChange', [['will-change', ['will-change']]]), - content: createUtilityPlugin('content'), + content: createUtilityPlugin('content', [ + ['content', ['--tw-content', ['content', 'var(--tw-content)']]], + ]), } diff --git a/src/css/preflight.css b/src/css/preflight.css index 51e94492a4f7..c4ee4437dd4b 100644 --- a/src/css/preflight.css +++ b/src/css/preflight.css @@ -12,6 +12,11 @@ border-color: currentColor; /* 2 */ } +::before, +::after { + --tw-content: ''; +} + /* 1. Use a consistent sensible line-height in all browsers. 2. Prevent adjustments of font size after orientation changes in iOS. diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js index a6d013a32342..5ca5027f97c8 100644 --- a/src/lib/generateRules.js +++ b/src/lib/generateRules.js @@ -143,26 +143,30 @@ function applyVariant(variant, matches, context) { } let ruleWithVariant = variantFunction({ + // Public API get container() { prepareBackup() return clone }, separator: context.tailwindConfig.separator, modifySelectors, + + // Private API for now wrap(wrapper) { let nodes = clone.nodes clone.removeAll() wrapper.append(nodes) clone.append(wrapper) }, - withRule(modify) { - clone.walkRules(modify) - }, format(selectorFormat) { collectedFormats.push(selectorFormat) }, }) + if (typeof ruleWithVariant === 'string') { + collectedFormats.push(ruleWithVariant) + } + if (ruleWithVariant === null) { continue } diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js index 8935e2e0f5b8..2cb40a9ae861 100644 --- a/src/lib/setupContextUtils.js +++ b/src/lib/setupContextUtils.js @@ -217,7 +217,10 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs addVariant(variantName, variantFunctions, options = {}) { variantFunctions = [].concat(variantFunctions).map((variantFunction) => { if (typeof variantFunction !== 'string') { - return variantFunction + // Safelist public API functions + return ({ modifySelectors, container, separator }) => { + return variantFunction({ modifySelectors, container, separator }) + } } variantFunction = variantFunction diff --git a/tests/arbitrary-values.test.css b/tests/arbitrary-values.test.css index ada975c32d1c..0ecb0c57e4de 100644 --- a/tests/arbitrary-values.test.css +++ b/tests/arbitrary-values.test.css @@ -1011,13 +1011,16 @@ will-change: var(--will-change); } .content-\[\'hello\'\] { - content: 'hello'; + --tw-content: 'hello'; + content: var(--tw-content); } .content-\[attr\(content-before\)\] { - content: attr(content-before); + --tw-content: attr(content-before); + content: var(--tw-content); } .content-\[\'\>\'\] { - content: '>'; + --tw-content: '>'; + content: var(--tw-content); } @media (min-width: 1024px) { .lg\:grid-cols-\[200px\2c repeat\(auto-fill\2c minmax\(15\%\2c 100px\)\)\2c 300px\] { diff --git a/tests/arbitrary-values.test.js b/tests/arbitrary-values.test.js index f824d05455f9..66d4b9a8fc2e 100644 --- a/tests/arbitrary-values.test.js +++ b/tests/arbitrary-values.test.js @@ -176,15 +176,18 @@ it('should convert _ to spaces', () => { } .content-\\[_hello_world_\\] { - content: hello world; + --tw-content: hello world; + content: var(--tw-content); } .content-\\[___abc____\\] { - content: abc; + --tw-content: abc; + content: var(--tw-content); } .content-\\[\\'__hello__world__\\'\\] { - content: ' hello world '; + --tw-content: ' hello world '; + content: var(--tw-content); } `) }) @@ -199,7 +202,8 @@ it('should not convert escaped underscores with spaces', () => { return run('@tailwind utilities', config).then((result) => { return expect(result.css).toMatchFormattedCss(css` .content-\[\'snake\\_case\'\] { - content: 'snake_case'; + --tw-content: 'snake_case'; + content: var(--tw-content); } `) }) diff --git a/tests/basic-usage.test.css b/tests/basic-usage.test.css index 535560916bba..93db9310ff6b 100644 --- a/tests/basic-usage.test.css +++ b/tests/basic-usage.test.css @@ -968,5 +968,6 @@ will-change: transform; } .content-none { - content: none; + --tw-content: none; + content: var(--tw-content); } diff --git a/tests/extractor-edge-cases.test.js b/tests/extractor-edge-cases.test.js index f94e31c12f52..95025fa7356f 100644 --- a/tests/extractor-edge-cases.test.js +++ b/tests/extractor-edge-cases.test.js @@ -22,7 +22,8 @@ test('arbitrary values with quotes', async () => { return run('@tailwind utilities', config).then((result) => { expect(result.css).toMatchFormattedCss(css` .content-\[\'hello\]\'\] { - content: 'hello]'; + --tw-content: 'hello]'; + content: var(--tw-content); } `) }) diff --git a/tests/resolve-defaults-at-rules.test.js b/tests/resolve-defaults-at-rules.test.js index 2e23ab1490e7..386547aecdf4 100644 --- a/tests/resolve-defaults-at-rules.test.js +++ b/tests/resolve-defaults-at-rules.test.js @@ -121,12 +121,12 @@ test('with pseudo-element variants', async () => { } /* --- */ .before\:scale-x-110::before { - content: ''; + content: var(--tw-content); --tw-scale-x: 1.1; transform: var(--tw-transform); } .after\:rotate-3::after { - content: ''; + content: var(--tw-content); --tw-rotate: 3deg; transform: var(--tw-transform); } @@ -205,12 +205,12 @@ test('with multi-class pseudo-element variants', async () => { } /* --- */ .group:hover .group-hover\:before\:scale-x-110::before { - content: ''; + content: var(--tw-content); --tw-scale-x: 1.1; transform: var(--tw-transform); } .peer:focus ~ .peer-focus\:after\:rotate-3::after { - content: ''; + content: var(--tw-content); --tw-rotate: 3deg; transform: var(--tw-transform); } @@ -253,12 +253,12 @@ test('with multi-class pseudo-element and pseudo-class variants', async () => { } /* --- */ .group:hover .group-hover\:hover\:before\:scale-x-110::before:hover { - content: ''; + content: var(--tw-content); --tw-scale-x: 1.1; transform: var(--tw-transform); } .peer:focus ~ .peer-focus\:focus\:after\:rotate-3::after:focus { - content: ''; + content: var(--tw-content); --tw-rotate: 3deg; transform: var(--tw-transform); } @@ -288,7 +288,6 @@ test('with apply', async () => { } .baz::before { - content: ''; @apply rotate-45; } @@ -351,13 +350,12 @@ test('with apply', async () => { transform: var(--tw-transform); } .bar::before { - content: ''; + content: var(--tw-content); --tw-scale-x: 1.1; --tw-scale-y: 1.1; transform: var(--tw-transform); } .baz::before { - content: ''; --tw-rotate: 45deg; transform: var(--tw-transform); } @@ -408,22 +406,18 @@ test('legacy pseudo-element syntax is supported', async () => { @tailwind utilities; .a:before { - content: ''; @apply rotate-45; } .b:after { - content: ''; @apply rotate-3; } .c:first-line { - content: ''; @apply rotate-1; } .d:first-letter { - content: ''; @apply rotate-6; } ` @@ -447,22 +441,18 @@ test('legacy pseudo-element syntax is supported', async () => { } /* --- */ .a:before { - content: ''; --tw-rotate: 45deg; transform: var(--tw-transform); } .b:after { - content: ''; --tw-rotate: 3deg; transform: var(--tw-transform); } .c:first-line { - content: ''; --tw-rotate: 1deg; transform: var(--tw-transform); } .d:first-letter { - content: ''; --tw-rotate: 6deg; transform: var(--tw-transform); } diff --git a/tests/variants.test.css b/tests/variants.test.css index 9814996d56e0..bb9a0faadbcb 100644 --- a/tests/variants.test.css +++ b/tests/variants.test.css @@ -165,20 +165,20 @@ color: rgb(255 255 255 / var(--tw-text-opacity)); } .before\:block::before { - content: ''; + content: var(--tw-content); display: block; } .before\:bg-red-500::before { - content: ''; + content: var(--tw-content); --tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity)); } .after\:flex::after { - content: ''; + content: var(--tw-content); display: flex; } .after\:uppercase::after { - content: ''; + content: var(--tw-content); text-transform: uppercase; } .first\:shadow-md:first-child { diff --git a/tests/variants.test.js b/tests/variants.test.js index 32c08b93ff13..bbe1e9bc041d 100644 --- a/tests/variants.test.js +++ b/tests/variants.test.js @@ -61,9 +61,7 @@ describe('custom advanced variants', () => { ], plugins: [ function ({ addVariant }) { - addVariant('prose-headings', ({ format }) => { - return format(':where(&) :is(h1, h2, h3, h4)') - }) + addVariant('prose-headings', ':where(&) :is(h1, h2, h3, h4)') }, ], } @@ -89,9 +87,7 @@ describe('custom advanced variants', () => { ], plugins: [ function ({ addVariant }) { - addVariant('prose-headings', ({ format }) => { - return format(':where(&) :is(h1, h2, h3, h4)') - }) + addVariant('prose-headings', ':where(&) :is(h1, h2, h3, h4)') }, ], } @@ -121,9 +117,7 @@ describe('custom advanced variants', () => { ], plugins: [ function ({ addVariant }) { - addVariant('prose-headings', ({ format }) => { - return format(':where(&) :is(h1, h2, h3, h4)') - }) + addVariant('prose-headings', ':where(&) :is(h1, h2, h3, h4)') }, ], }