From dfc7b6961a4329cab013c1bddf9ae282428d8b2d Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 13 Dec 2021 16:07:55 -0500 Subject: [PATCH 1/5] Switch to more declarative addDefaults API This preps us for introducing an implicitly included layer for defaults --- src/corePlugins.js | 206 ++++++++++++++++------------------- src/lib/setupContextUtils.js | 22 ++++ 2 files changed, 118 insertions(+), 110 deletions(-) diff --git a/src/corePlugins.js b/src/corePlugins.js index 31a959fd9f43..56a1f8edefb9 100644 --- a/src/corePlugins.js +++ b/src/corePlugins.js @@ -529,27 +529,26 @@ export let corePlugins = { { supportsNegativeValues: true } ), - transform: ({ addBase, addUtilities }) => { - addBase({ - '@defaults transform': { - '--tw-translate-x': '0', - '--tw-translate-y': '0', - '--tw-rotate': '0', - '--tw-skew-x': '0', - '--tw-skew-y': '0', - '--tw-scale-x': '1', - '--tw-scale-y': '1', - '--tw-transform': [ - 'translateX(var(--tw-translate-x))', - 'translateY(var(--tw-translate-y))', - 'rotate(var(--tw-rotate))', - 'skewX(var(--tw-skew-x))', - 'skewY(var(--tw-skew-y))', - 'scaleX(var(--tw-scale-x))', - 'scaleY(var(--tw-scale-y))', - ].join(' '), - }, + transform: ({ addDefaults, addUtilities }) => { + addDefaults('transform', { + '--tw-translate-x': '0', + '--tw-translate-y': '0', + '--tw-rotate': '0', + '--tw-skew-x': '0', + '--tw-skew-y': '0', + '--tw-scale-x': '1', + '--tw-scale-y': '1', + '--tw-transform': [ + 'translateX(var(--tw-translate-x))', + 'translateY(var(--tw-translate-y))', + 'rotate(var(--tw-rotate))', + 'skewX(var(--tw-skew-x))', + 'skewY(var(--tw-skew-y))', + 'scaleX(var(--tw-scale-x))', + 'scaleY(var(--tw-scale-y))', + ].join(' '), }) + addUtilities({ '.transform': { '@defaults transform': {}, transform: 'var(--tw-transform)' }, '.transform-cpu': { @@ -611,14 +610,12 @@ export let corePlugins = { cursor: createUtilityPlugin('cursor'), - touchAction: ({ addBase, addUtilities }) => { - addBase({ - '@defaults touch-action': { - '--tw-pan-x': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-pan-y': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-pinch-zoom': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-touch-action': 'var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)', - }, + touchAction: ({ addDefaults, addUtilities }) => { + addDefaults('touch-action', { + '--tw-pan-x': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-pan-y': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-pinch-zoom': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-touch-action': 'var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)', }) addUtilities({ @@ -681,11 +678,9 @@ export let corePlugins = { }) }, - scrollSnapType: ({ addUtilities, addBase }) => { - addBase({ - '@defaults scroll-snap-type': { - '--tw-scroll-snap-strictness': 'proximity', - }, + scrollSnapType: ({ addDefaults, addUtilities }) => { + addDefaults('scroll-snap-type', { + '--tw-scroll-snap-strictness': 'proximity', }) addUtilities({ @@ -1182,22 +1177,21 @@ export let corePlugins = { }) }, - borderColor: ({ addBase, matchUtilities, theme, corePlugins }) => { + borderColor: ({ addDefaults, matchUtilities, theme, corePlugins }) => { if (!corePlugins('borderOpacity')) { let value = theme('borderColor.DEFAULT', 'currentColor') - addBase({ - '@defaults border-width': { - 'border-color': toColorValue(value), - }, + addDefaults('border-width', { + 'border-color': toColorValue(value), }) } else { - addBase({ - '@defaults border-width': withAlphaVariable({ + addDefaults( + 'border-width', + withAlphaVariable({ color: theme('borderColor.DEFAULT', 'currentColor'), property: 'border-color', variable: '--tw-border-opacity', - }), - }) + }) + ) } matchUtilities( @@ -1823,14 +1817,12 @@ export let corePlugins = { `var(--tw-shadow)`, ].join(', ') - return function ({ matchUtilities, addBase, theme }) { - addBase({ - '@defaults box-shadow': { - '--tw-ring-offset-shadow': '0 0 #0000', - '--tw-ring-shadow': '0 0 #0000', - '--tw-shadow': '0 0 #0000', - '--tw-shadow-colored': '0 0 #0000', - }, + return function ({ matchUtilities, addDefaults, theme }) { + addDefaults(' box-shadow', { + '--tw-ring-offset-shadow': '0 0 #0000', + '--tw-ring-shadow': '0 0 #0000', + '--tw-shadow': '0 0 #0000', + '--tw-shadow-colored': '0 0 #0000', }) matchUtilities( @@ -1908,7 +1900,7 @@ export let corePlugins = { ) }, - ringWidth: ({ matchUtilities, addBase, addUtilities, theme }) => { + ringWidth: ({ matchUtilities, addDefaults, addUtilities, theme }) => { let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5') let ringColorDefault = withAlphaValue( theme('ringColor.DEFAULT'), @@ -1916,17 +1908,15 @@ export let corePlugins = { `rgb(147 197 253 / ${ringOpacityDefault})` ) - addBase({ - '@defaults ring-width': { - '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-ring-offset-width': theme('ringOffsetWidth.DEFAULT', '0px'), - '--tw-ring-offset-color': theme('ringOffsetColor.DEFAULT', '#fff'), - '--tw-ring-color': ringColorDefault, - '--tw-ring-offset-shadow': '0 0 #0000', - '--tw-ring-shadow': '0 0 #0000', - '--tw-shadow': '0 0 #0000', - '--tw-shadow-colored': '0 0 #0000', - }, + addDefaults('ring-width', { + '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-ring-offset-width': theme('ringOffsetWidth.DEFAULT', '0px'), + '--tw-ring-offset-color': theme('ringOffsetColor.DEFAULT', '#fff'), + '--tw-ring-color': ringColorDefault, + '--tw-ring-offset-shadow': '0 0 #0000', + '--tw-ring-shadow': '0 0 #0000', + '--tw-shadow': '0 0 #0000', + '--tw-shadow-colored': '0 0 #0000', }) matchUtilities( @@ -2133,30 +2123,28 @@ export let corePlugins = { ) }, - filter: ({ addBase, addUtilities }) => { - addBase({ - '@defaults filter': { - '--tw-blur': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-brightness': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-contrast': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-grayscale': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-hue-rotate': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-invert': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-saturate': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-sepia': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-drop-shadow': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-filter': [ - 'var(--tw-blur)', - 'var(--tw-brightness)', - 'var(--tw-contrast)', - 'var(--tw-grayscale)', - 'var(--tw-hue-rotate)', - 'var(--tw-invert)', - 'var(--tw-saturate)', - 'var(--tw-sepia)', - 'var(--tw-drop-shadow)', - ].join(' '), - }, + filter: ({ addDefaults, addUtilities }) => { + addDefaults('filter', { + '--tw-blur': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-brightness': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-contrast': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-grayscale': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-hue-rotate': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-invert': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-saturate': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-sepia': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-drop-shadow': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-filter': [ + 'var(--tw-blur)', + 'var(--tw-brightness)', + 'var(--tw-contrast)', + 'var(--tw-grayscale)', + 'var(--tw-hue-rotate)', + 'var(--tw-invert)', + 'var(--tw-saturate)', + 'var(--tw-sepia)', + 'var(--tw-drop-shadow)', + ].join(' '), }) addUtilities({ '.filter': { '@defaults filter': {}, filter: 'var(--tw-filter)' }, @@ -2299,30 +2287,28 @@ export let corePlugins = { ) }, - backdropFilter: ({ addBase, addUtilities }) => { - addBase({ - '@defaults backdrop-filter': { - '--tw-backdrop-blur': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-brightness': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-contrast': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-grayscale': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-hue-rotate': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-invert': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-opacity': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-saturate': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-sepia': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-backdrop-filter': [ - 'var(--tw-backdrop-blur)', - 'var(--tw-backdrop-brightness)', - 'var(--tw-backdrop-contrast)', - 'var(--tw-backdrop-grayscale)', - 'var(--tw-backdrop-hue-rotate)', - 'var(--tw-backdrop-invert)', - 'var(--tw-backdrop-opacity)', - 'var(--tw-backdrop-saturate)', - 'var(--tw-backdrop-sepia)', - ].join(' '), - }, + backdropFilter: ({ addDefaults, addUtilities }) => { + addDefaults('backdrop-filter', { + '--tw-backdrop-blur': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-brightness': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-contrast': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-grayscale': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-hue-rotate': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-invert': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-opacity': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-saturate': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-sepia': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-backdrop-filter': [ + 'var(--tw-backdrop-blur)', + 'var(--tw-backdrop-brightness)', + 'var(--tw-backdrop-contrast)', + 'var(--tw-backdrop-grayscale)', + 'var(--tw-backdrop-hue-rotate)', + 'var(--tw-backdrop-invert)', + 'var(--tw-backdrop-opacity)', + 'var(--tw-backdrop-saturate)', + 'var(--tw-backdrop-sepia)', + ].join(' '), }) addUtilities({ '.backdrop-filter': { diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js index b242e8028808..cc83f175a611 100644 --- a/src/lib/setupContextUtils.js +++ b/src/lib/setupContextUtils.js @@ -233,6 +233,28 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs .push([{ sort: offset, layer: 'base' }, rule]) } }, + /** + * @param {string} group + * @param {Record} declarations + */ + addDefaults(group, declarations) { + const groups = { + [`@defaults ${group}`]: declarations, + } + + for (let [identifier, rule] of withIdentifiers(groups)) { + let prefixedIdentifier = prefixIdentifier(identifier, {}) + let offset = offsets.base++ + + if (!context.candidateRuleMap.has(prefixedIdentifier)) { + context.candidateRuleMap.set(prefixedIdentifier, []) + } + + context.candidateRuleMap + .get(prefixedIdentifier) + .push([{ sort: offset, layer: 'base' }, rule]) + } + }, addComponents(components, options) { let defaultOptions = { respectPrefix: true, From 0a33917fa7a42638daf9bd0bf6c5e4521b79f789 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 13 Dec 2021 15:35:39 -0500 Subject: [PATCH 2/5] Move defaults to their own always-on layer Default's declarations are now processed and merged even when there is no tailwind base directive included in the stylesheet. Without this applying tailwind utilities in css modules would break if they relied on defaults rules. --- src/lib/expandTailwindAtRules.js | 12 +++++ src/lib/setupContextUtils.js | 15 +++--- tests/resolve-defaults-at-rules.test.js | 70 +++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/src/lib/expandTailwindAtRules.js b/src/lib/expandTailwindAtRules.js index 4b1c627088b8..26fda0ed0dcd 100644 --- a/src/lib/expandTailwindAtRules.js +++ b/src/lib/expandTailwindAtRules.js @@ -99,6 +99,7 @@ function buildStylesheet(rules, context) { let returnValue = { base: new Set(), + defaults: new Set(), components: new Set(), utilities: new Set(), variants: new Set(), @@ -125,6 +126,11 @@ function buildStylesheet(rules, context) { continue } + if (sort & context.layerOrder.defaults) { + returnValue.defaults.add(rule) + continue + } + if (sort & context.layerOrder.components) { returnValue.components.add(rule) continue @@ -202,6 +208,7 @@ export default function expandTailwindAtRules(context) { env.DEBUG && console.timeEnd('Build stylesheet') let { + defaults: defaultNodes, base: baseNodes, components: componentNodes, utilities: utilityNodes, @@ -212,6 +219,11 @@ export default function expandTailwindAtRules(context) { // Replace any Tailwind directives with generated CSS + // @defaults rules are unconditionally added first to ensure that + // using any utility that relies on defaults will work even when + // compiled in an isolated environment like CSS modules + root.prepend(cloneNodes([...defaultNodes], root.source)) + if (layerNodes.base) { layerNodes.base.before(cloneNodes([...baseNodes], layerNodes.base.source)) layerNodes.base.remove() diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js index cc83f175a611..721bd738a47c 100644 --- a/src/lib/setupContextUtils.js +++ b/src/lib/setupContextUtils.js @@ -252,7 +252,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs context.candidateRuleMap .get(prefixedIdentifier) - .push([{ sort: offset, layer: 'base' }, rule]) + .push([{ sort: offset, layer: 'defaults' }, rule]) } }, addComponents(components, options) { @@ -550,6 +550,7 @@ function registerPlugins(plugins, context) { let variantList = [] let variantMap = new Map() let offsets = { + defaults: 0n, base: 0n, components: 0n, utilities: 0n, @@ -577,6 +578,7 @@ function registerPlugins(plugins, context) { let highestOffset = ((args) => args.reduce((m, e) => (e > m ? e : m)))([ offsets.base, + offsets.defaults, offsets.components, offsets.utilities, offsets.user, @@ -588,13 +590,14 @@ function registerPlugins(plugins, context) { context.arbitraryPropertiesSort = ((1n << reservedBits) << 0n) - 1n context.layerOrder = { - base: (1n << reservedBits) << 0n, - components: (1n << reservedBits) << 1n, - utilities: (1n << reservedBits) << 2n, - user: (1n << reservedBits) << 3n, + defaults: (1n << reservedBits) << 0n, + base: (1n << reservedBits) << 1n, + components: (1n << reservedBits) << 2n, + utilities: (1n << reservedBits) << 3n, + user: (1n << reservedBits) << 4n, } - reservedBits += 4n + reservedBits += 5n let offset = 0 context.variantOrder = new Map( diff --git a/tests/resolve-defaults-at-rules.test.js b/tests/resolve-defaults-at-rules.test.js index 997507790f02..719ef82afd51 100644 --- a/tests/resolve-defaults-at-rules.test.js +++ b/tests/resolve-defaults-at-rules.test.js @@ -695,3 +695,73 @@ test('selectors are reduced to the lowest possible specificity', async () => { `) }) }) + +test('defaults without @tailwind base', () => { + let config = { + experimental: { optimizeUniversalDefaults: true }, + content: [{ raw: html`
` }], + corePlugins: { preflight: false }, + } + + // No @tailwind base directive means that we need to generate the defaults for each of the utility classes in that context + // These then get merged with the utilities generated by later passes but order is preserved + let input = css` + @tailwind components; + @tailwind utilities; + ` + + return run(input, config).then((result) => { + return expect(result.css).toMatchFormattedCss(css` + .scale-150 { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-scale-x: 1.5; + --tw-scale-y: 1.5; + transform: var(--tw-transform); + } + `) + }) +}) + +test('defaults and apply without @tailwind base', () => { + let config = { + experimental: { optimizeUniversalDefaults: true }, + content: [{ raw: html`
` }], + corePlugins: { preflight: false }, + } + + // No @tailwind base directive means that we need to generate the defaults for each of the utility classes in that context + // These then get merged with the utilities generated by later passes but order is preserved + let input = css` + @tailwind components; + @tailwind utilities; + + .my-card { + @apply scale-150; + } + ` + + return run(input, config).then((result) => { + return expect(result.css).toMatchFormattedCss(css` + .my-card { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-scale-x: 1.5; + --tw-scale-y: 1.5; + transform: var(--tw-transform); + } + `) + }) +}) From e463c3848ac3c7f83291c63402b764eb69dfb057 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 13 Dec 2021 17:10:58 -0500 Subject: [PATCH 3/5] Add private api to disable defaults layer for testing --- src/lib/expandTailwindAtRules.js | 7 ++- src/util/defaults.js | 6 +++ tests/kitchen-sink.test.css | 70 ++++++++++++------------- tests/resolve-defaults-at-rules.test.js | 3 ++ tests/util/run.js | 5 ++ 5 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/lib/expandTailwindAtRules.js b/src/lib/expandTailwindAtRules.js index 26fda0ed0dcd..7538a29fbc9f 100644 --- a/src/lib/expandTailwindAtRules.js +++ b/src/lib/expandTailwindAtRules.js @@ -150,6 +150,9 @@ function buildStylesheet(rules, context) { return returnValue } +// export const DEFAULTS_LAYER = Symbol('defaults-layer') +export const DEFAULTS_LAYER = '__defaults' + export default function expandTailwindAtRules(context) { return (root) => { let layerNodes = { @@ -222,7 +225,9 @@ export default function expandTailwindAtRules(context) { // @defaults rules are unconditionally added first to ensure that // using any utility that relies on defaults will work even when // compiled in an isolated environment like CSS modules - root.prepend(cloneNodes([...defaultNodes], root.source)) + if (context.tailwindConfig[DEFAULTS_LAYER] !== false) { + root.prepend(cloneNodes([...defaultNodes], root.source)) + } if (layerNodes.base) { layerNodes.base.before(cloneNodes([...baseNodes], layerNodes.base.source)) diff --git a/src/util/defaults.js b/src/util/defaults.js index 709387a684bf..1d4aa7b45cfd 100644 --- a/src/util/defaults.js +++ b/src/util/defaults.js @@ -5,6 +5,12 @@ export function defaults(target, ...sources) { target[k] = source[k] } } + + for (let k of Object.getOwnPropertySymbols(source)) { + if (!target?.hasOwnProperty?.(k)) { + target[k] = source[k] + } + } } return target diff --git a/tests/kitchen-sink.test.css b/tests/kitchen-sink.test.css index 729049b24f57..3392e500520d 100644 --- a/tests/kitchen-sink.test.css +++ b/tests/kitchen-sink.test.css @@ -1,3 +1,38 @@ +.scale-50, +.transform, +.hover\:scale-75 { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.shadow-sm, +.shadow-md, +.hover\:shadow-lg, +.md\:shadow-sm { + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; +} + +.focus\:ring-2 { + --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/); + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; +} .theme-test { font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', @@ -126,41 +161,6 @@ } } } -.scale-50, -.transform, -.hover\:scale-75 { - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) - rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) - scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.shadow-sm, -.shadow-md, -.hover\:shadow-lg, -.md\:shadow-sm { - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; -} - -.focus\:ring-2 { - --tw-ring-inset: var(--tw-empty, /*!*/ /*!*/); - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; -} h1 { font-size: 1.5rem; font-weight: 700; diff --git a/tests/resolve-defaults-at-rules.test.js b/tests/resolve-defaults-at-rules.test.js index 719ef82afd51..ee8b68d023a8 100644 --- a/tests/resolve-defaults-at-rules.test.js +++ b/tests/resolve-defaults-at-rules.test.js @@ -1,4 +1,5 @@ import { run, html, css } from './util/run' +import { DEFAULTS_LAYER } from '../src/lib/expandTailwindAtRules' test('basic utilities', async () => { let config = { @@ -701,6 +702,7 @@ test('defaults without @tailwind base', () => { experimental: { optimizeUniversalDefaults: true }, content: [{ raw: html`
` }], corePlugins: { preflight: false }, + [DEFAULTS_LAYER]: true, } // No @tailwind base directive means that we need to generate the defaults for each of the utility classes in that context @@ -734,6 +736,7 @@ test('defaults and apply without @tailwind base', () => { experimental: { optimizeUniversalDefaults: true }, content: [{ raw: html`
` }], corePlugins: { preflight: false }, + [DEFAULTS_LAYER]: true, } // No @tailwind base directive means that we need to generate the defaults for each of the utility classes in that context diff --git a/tests/util/run.js b/tests/util/run.js index 52893854041b..76a67ea1486d 100644 --- a/tests/util/run.js +++ b/tests/util/run.js @@ -1,10 +1,15 @@ import path from 'path' import postcss from 'postcss' import tailwind from '../../src' +import { DEFAULTS_LAYER } from '../../src/lib/expandTailwindAtRules' export function run(input, config, plugin = tailwind) { let { currentTestName } = expect.getState() + if (typeof config === 'object' && Object.keys(config).length > 0) { + config[DEFAULTS_LAYER] = config[DEFAULTS_LAYER] ?? input.includes('@tailwind base') + } + return postcss(plugin(config)).process(input, { from: `${path.resolve(__filename)}?test=${currentTestName}`, }) From 85e62d2204d7a035235ff8e402382048d7a0b37a Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Tue, 14 Dec 2021 16:18:47 +0100 Subject: [PATCH 4/5] use Symbol instead of __defaults magic string --- src/lib/expandTailwindAtRules.js | 3 +-- tests/raw-content.test.js | 10 +++------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/lib/expandTailwindAtRules.js b/src/lib/expandTailwindAtRules.js index 7538a29fbc9f..a43d72d71994 100644 --- a/src/lib/expandTailwindAtRules.js +++ b/src/lib/expandTailwindAtRules.js @@ -150,8 +150,7 @@ function buildStylesheet(rules, context) { return returnValue } -// export const DEFAULTS_LAYER = Symbol('defaults-layer') -export const DEFAULTS_LAYER = '__defaults' +export const DEFAULTS_LAYER = Symbol('defaults-layer') export default function expandTailwindAtRules(context) { return (root) => { diff --git a/tests/raw-content.test.js b/tests/raw-content.test.js index c24dba919ecd..5e4c54de9c67 100644 --- a/tests/raw-content.test.js +++ b/tests/raw-content.test.js @@ -3,10 +3,7 @@ import path from 'path' import { run, css } from './util/run' -beforeEach(() => jest.resetModules()) - -test('raw content', () => { - let tailwind = require('../src') +it('raw content', () => { let config = { content: [{ raw: fs.readFileSync(path.resolve(__dirname, './raw-content.test.html'), 'utf8') }], corePlugins: { preflight: false }, @@ -17,7 +14,7 @@ test('raw content', () => { @tailwind utilities; ` - return run(input, config, tailwind).then((result) => { + return run(input, config).then((result) => { let expectedPath = path.resolve(__dirname, './raw-content.test.css') let expected = fs.readFileSync(expectedPath, 'utf8') @@ -26,7 +23,6 @@ test('raw content', () => { }) test('raw content with extension', () => { - let tailwind = require('../src') let config = { content: { files: [ @@ -42,7 +38,7 @@ test('raw content with extension', () => { corePlugins: { preflight: false }, } - return run('@tailwind utilities', config, tailwind).then((result) => { + return run('@tailwind utilities', config).then((result) => { expect(result.css).toMatchFormattedCss(css` .invisible { visibility: hidden; From bde193d398409af2aa7927652d89d152a676dfa0 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 14 Dec 2021 12:19:10 -0500 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f595bf34e96..dec84f35f096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Don't output unparsable values ([#6469](https://github.com/tailwindlabs/tailwindcss/pull/6469)) - Fix text decoration utilities from overriding the new text decoration color/style/thickness utilities when used with a modifier ([#6378](https://github.com/tailwindlabs/tailwindcss/pull/6378)) +- Move defaults to their own always-on layer ([#6500](https://github.com/tailwindlabs/tailwindcss/pull/6500)) ## [3.0.2] - 2021-12-13