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 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/expandTailwindAtRules.js b/src/lib/expandTailwindAtRules.js index 4b1c627088b8..a43d72d71994 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 @@ -144,6 +150,8 @@ function buildStylesheet(rules, context) { return returnValue } +export const DEFAULTS_LAYER = Symbol('defaults-layer') + export default function expandTailwindAtRules(context) { return (root) => { let layerNodes = { @@ -202,6 +210,7 @@ export default function expandTailwindAtRules(context) { env.DEBUG && console.timeEnd('Build stylesheet') let { + defaults: defaultNodes, base: baseNodes, components: componentNodes, utilities: utilityNodes, @@ -212,6 +221,13 @@ 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 + if (context.tailwindConfig[DEFAULTS_LAYER] !== false) { + 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 b242e8028808..721bd738a47c 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: 'defaults' }, rule]) + } + }, addComponents(components, options) { let defaultOptions = { respectPrefix: true, @@ -528,6 +550,7 @@ function registerPlugins(plugins, context) { let variantList = [] let variantMap = new Map() let offsets = { + defaults: 0n, base: 0n, components: 0n, utilities: 0n, @@ -555,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, @@ -566,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/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/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; diff --git a/tests/resolve-defaults-at-rules.test.js b/tests/resolve-defaults-at-rules.test.js index 997507790f02..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 = { @@ -695,3 +696,75 @@ 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 }, + [DEFAULTS_LAYER]: true, + } + + // 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 }, + [DEFAULTS_LAYER]: true, + } + + // 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); + } + `) + }) +}) 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}`, })