diff --git a/CHANGELOG.md b/CHANGELOG.md index bbe8c35dbcae..f6bd6023dac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Nothing yet! +## [3.1.2] - 2022-06-10 + +### Fixed + +- Ensure `\` is a valid arbitrary variant token ([#8576](https://github.com/tailwindlabs/tailwindcss/pull/8576)) +- Enable `postcss-import` in the CLI by default in watch mode ([#8574](https://github.com/tailwindlabs/tailwindcss/pull/8574), [#8580](https://github.com/tailwindlabs/tailwindcss/pull/8580)) + +## [3.1.1] - 2022-06-09 + +### Fixed + +- Fix candidate extractor regression ([#8558](https://github.com/tailwindlabs/tailwindcss/pull/8558)) +- Split `::backdrop` into separate defaults group ([#8567](https://github.com/tailwindlabs/tailwindcss/pull/8567)) +- Fix postcss plugin type ([#8564](https://github.com/tailwindlabs/tailwindcss/pull/8564)) +- Fix class detection in markdown code fences and slim templates ([#8569](https://github.com/tailwindlabs/tailwindcss/pull/8569)) + ## [3.1.0] - 2022-06-08 ### Fixed @@ -1952,7 +1968,9 @@ No release notes - Everything! -[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.0...HEAD +[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.2...HEAD +[3.1.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.1...v3.1.2 +[3.1.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.0...v3.1.1 [3.1.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.24...v3.1.0 [3.0.24]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.23...v3.0.24 [3.0.23]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.22...v3.0.23 diff --git a/integrations/tailwindcss-cli/tests/cli.test.js b/integrations/tailwindcss-cli/tests/cli.test.js index 414dd2f40639..9ebcd3012b91 100644 --- a/integrations/tailwindcss-cli/tests/cli.test.js +++ b/integrations/tailwindcss-cli/tests/cli.test.js @@ -5,7 +5,14 @@ let resolveToolRoot = require('../../resolve-tool-root') let version = require('../../../package.json').version -let { readOutputFile, writeInputFile, cleanupFile, fileExists, removeFile } = require('../../io')({ +let { + cleanupFile, + fileExists, + readOutputFile, + removeFile, + waitForOutputFileCreation, + writeInputFile, +} = require('../../io')({ output: 'dist', input: 'src', }) @@ -374,6 +381,39 @@ describe('Build command', () => { ) }) + test('postcss-import is supported by default in watch mode', async () => { + cleanupFile('src/test.css') + + await writeInputFile('index.html', html`
`) + await writeInputFile( + 'test.css', + css` + @import 'tailwindcss/base'; + @import 'tailwindcss/components'; + @import 'tailwindcss/utilities'; + @import './imported.css'; + ` + ) + + let runningProcess = $( + `${EXECUTABLE} --watch --input ./src/test.css --content ./src/index.html --output ./dist/main.css` + ) + + await waitForOutputFileCreation('main.css') + + expect(await readOutputFile('main.css')).toIncludeCss( + css` + @media (min-width: 768px) { + .md\:something-cool { + color: red; + } + } + ` + ) + + return runningProcess.stop() + }) + test('postcss-import is included when using a custom postcss configuration', async () => { cleanupFile('src/test.css') diff --git a/package-lock.json b/package-lock.json index 72ddeaf5d25f..1c71ffec7624 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tailwindcss", - "version": "3.1.0", + "version": "3.1.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "tailwindcss", - "version": "3.1.0", + "version": "3.1.2", "license": "MIT", "dependencies": { "arg": "^5.0.1", diff --git a/package.json b/package.json index c93d04285ad3..7c8e7ada3718 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tailwindcss", - "version": "3.1.0", + "version": "3.1.2", "description": "A utility-first CSS framework for rapidly building custom user interfaces.", "license": "MIT", "main": "lib/index.js", diff --git a/src/cli.js b/src/cli.js index 2c48af64514f..885f03399e5f 100644 --- a/src/cli.js +++ b/src/cli.js @@ -484,6 +484,45 @@ async function build() { return [beforePlugins, afterPlugins, config.options] } + function loadBuiltinPostcssPlugins() { + let postcss = loadPostcss() + let IMPORT_COMMENT = '__TAILWIND_RESTORE_IMPORT__: ' + return [ + [ + (root) => { + root.walkAtRules('import', (rule) => { + if (rule.params.slice(1).startsWith('tailwindcss/')) { + rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params })) + rule.remove() + } + }) + }, + (() => { + try { + return require('postcss-import') + } catch {} + + return lazyPostcssImport() + })(), + (root) => { + root.walkComments((rule) => { + if (rule.text.startsWith(IMPORT_COMMENT)) { + rule.after( + postcss.atRule({ + name: 'import', + params: rule.text.replace(IMPORT_COMMENT, ''), + }) + ) + rule.remove() + } + }) + }, + ], + [], + {}, + ] + } + function resolveConfig() { let config = configPath ? require(configPath) : {} @@ -568,44 +607,9 @@ async function build() { tailwindPlugin.postcss = true - let IMPORT_COMMENT = '__TAILWIND_RESTORE_IMPORT__: ' - let [beforePlugins, afterPlugins, postcssOptions] = includePostCss ? await loadPostCssPlugins() - : [ - [ - (root) => { - root.walkAtRules('import', (rule) => { - if (rule.params.slice(1).startsWith('tailwindcss/')) { - rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params })) - rule.remove() - } - }) - }, - (() => { - try { - return require('postcss-import') - } catch {} - - return lazyPostcssImport() - })(), - (root) => { - root.walkComments((rule) => { - if (rule.text.startsWith(IMPORT_COMMENT)) { - rule.after( - postcss.atRule({ - name: 'import', - params: rule.text.replace(IMPORT_COMMENT, ''), - }) - ) - rule.remove() - } - }) - }, - ], - [], - {}, - ] + : loadBuiltinPostcssPlugins() let plugins = [ ...beforePlugins, @@ -705,7 +709,9 @@ async function build() { return resolveConfig() } - let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [[], []] + let [beforePlugins, afterPlugins] = includePostCss + ? await loadPostCssPlugins() + : loadBuiltinPostcssPlugins() let plugins = [ ...beforePlugins, diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js index 973250ea4d5a..fa2cc92b8f17 100644 --- a/src/lib/defaultExtractor.js +++ b/src/lib/defaultExtractor.js @@ -25,7 +25,7 @@ function* buildRegExps(context) { let utility = regex.any([ // Arbitrary properties - /\[[^\s:'"]+:[^\s\]]+\]/, + /\[[^\s:'"`]+:[^\s\]]+\]/, // Utilities regex.pattern([ @@ -43,7 +43,7 @@ function* buildRegExps(context) { /(?![{([]])/, // optionally followed by an opacity modifier - /(?:\/[^\s'"\\$]*)?/, + /(?:\/[^\s'"`\\><$]*)?/, ]), regex.pattern([ @@ -54,11 +54,11 @@ function* buildRegExps(context) { /(?![{([]])/, // optionally followed by an opacity modifier - /(?:\/[^\s'"\\$]*)?/, + /(?:\/[^\s'"`\\$]*)?/, ]), // Normal values w/o quotes — may include an opacity modifier - /[-\/][^\s'"\\$={]*/, + /[-\/][^\s'"`\\$={><]*/, ]) ), ]), @@ -69,8 +69,8 @@ function* buildRegExps(context) { '((?=((', regex.any( [ - regex.pattern([/([^\s"'\[\\]+-)?\[[^\s"'\\]+\]/, separator]), - regex.pattern([/[^\s"'\[\\]+/, separator]), + regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]), + regex.pattern([/[^\s"'`\[\\]+/, separator]), ], true ), @@ -91,7 +91,7 @@ function* buildRegExps(context) { ]) // 5. Inner matches - // yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g + yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g } // We want to capture any "special" characters diff --git a/src/lib/evaluateTailwindFunctions.js b/src/lib/evaluateTailwindFunctions.js index 2b755394cbd0..4239d411cb17 100644 --- a/src/lib/evaluateTailwindFunctions.js +++ b/src/lib/evaluateTailwindFunctions.js @@ -162,7 +162,7 @@ let nodeTypePropertyMap = { export default function ({ tailwindConfig: config }) { let functions = { theme: (node, path, ...defaultValue) => { - let matches = path.match(/^([^\/\s]+)(?:\s*\/\s*([^\/\s]+))$/) + let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/) let alpha = undefined if (matches) { diff --git a/src/lib/resolveDefaultsAtRules.js b/src/lib/resolveDefaultsAtRules.js index 62cf03c54440..389ea4bacac7 100644 --- a/src/lib/resolveDefaultsAtRules.js +++ b/src/lib/resolveDefaultsAtRules.js @@ -91,56 +91,73 @@ export default function resolveDefaultsAtRules({ tailwindConfig }) { rule.remove() }) - for (let universal of universals) { - /** @type {Map>} */ - let selectorGroups = new Map() + if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) { + for (let universal of universals) { + /** @type {Map>} */ + let selectorGroups = new Map() + + let rules = variableNodeMap.get(universal.params) ?? [] + + for (let rule of rules) { + for (let selector of extractElementSelector(rule.selector)) { + // If selector contains a vendor prefix after a pseudo element or class, + // we consider them separately because merging the declarations into + // a single rule will cause browsers that do not understand the + // vendor prefix to throw out the whole rule + let selectorGroupName = + selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__' + + let selectors = selectorGroups.get(selectorGroupName) ?? new Set() + selectorGroups.set(selectorGroupName, selectors) + + selectors.add(selector) + } + } - let rules = variableNodeMap.get(universal.params) ?? [] + if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) { + if (selectorGroups.size === 0) { + universal.remove() + continue + } - for (let rule of rules) { - for (let selector of extractElementSelector(rule.selector)) { - // If selector contains a vendor prefix after a pseudo element or class, - // we consider them separately because merging the declarations into - // a single rule will cause browsers that do not understand the - // vendor prefix to throw out the whole rule - let selectorGroupName = - selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__' + for (let [, selectors] of selectorGroups) { + let universalRule = postcss.rule({ + source: universal.source, + }) - let selectors = selectorGroups.get(selectorGroupName) ?? new Set() - selectorGroups.set(selectorGroupName, selectors) + universalRule.selectors = [...selectors] - selectors.add(selector) + universalRule.append(universal.nodes.map((node) => node.clone())) + universal.before(universalRule) + } } - } - if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) { - if (selectorGroups.size === 0) { - universal.remove() - continue - } - - for (let [, selectors] of selectorGroups) { - let universalRule = postcss.rule({ - source: universal.source, - }) + universal.remove() + } + } else if (universals.size) { + let universalRule = postcss.rule({ + selectors: ['*', '::before', '::after'], + }) - universalRule.selectors = [...selectors] + for (let universal of universals) { + universalRule.append(universal.nodes) - universalRule.append(universal.nodes.map((node) => node.clone())) + if (!universalRule.parent) { universal.before(universalRule) } - } else { - let universalRule = postcss.rule({ - source: universal.source, - }) - universalRule.selectors = ['*', '::before', '::after', '::backdrop'] + if (!universalRule.source) { + universalRule.source = universal.source + } - universalRule.append(universal.nodes) - universal.before(universalRule) + universal.remove() } - universal.remove() + let backdropRule = universalRule.clone({ + selectors: ['::backdrop'], + }) + + universalRule.after(backdropRule) } } } diff --git a/tests/__snapshots__/source-maps.test.js.snap b/tests/__snapshots__/source-maps.test.js.snap index 32fc16e22b6a..e7aca966cd7e 100644 --- a/tests/__snapshots__/source-maps.test.js.snap +++ b/tests/__snapshots__/source-maps.test.js.snap @@ -309,5 +309,51 @@ Array [ "2:4-18 -> 407:2-27", "2:4 -> 408:2", "2:18 -> 409:0", + "2:4 -> 411:0", + "2:4-18 -> 412:2-26", + "2:4-18 -> 413:2-26", + "2:4-18 -> 414:2-21", + "2:4-18 -> 415:2-21", + "2:4-18 -> 416:2-16", + "2:4-18 -> 417:2-16", + "2:4-18 -> 418:2-16", + "2:4-18 -> 419:2-17", + "2:4-18 -> 420:2-17", + "2:4-18 -> 421:2-15", + "2:4-18 -> 422:2-15", + "2:4-18 -> 423:2-20", + "2:4-18 -> 424:2-40", + "2:4-18 -> 425:2-17", + "2:4-18 -> 426:2-22", + "2:4-18 -> 427:2-24", + "2:4-18 -> 428:2-25", + "2:4-18 -> 429:2-26", + "2:4-18 -> 430:2-20", + "2:4-18 -> 431:2-29", + "2:4-18 -> 432:2-30", + "2:4-18 -> 433:2-40", + "2:4-18 -> 434:2-36", + "2:4-18 -> 435:2-29", + "2:4-18 -> 436:2-24", + "2:4-18 -> 437:2-32", + "2:4-18 -> 438:2-14", + "2:4-18 -> 439:2-20", + "2:4-18 -> 440:2-18", + "2:4-18 -> 441:2-19", + "2:4-18 -> 442:2-20", + "2:4-18 -> 443:2-16", + "2:4-18 -> 444:2-18", + "2:4-18 -> 445:2-15", + "2:4-18 -> 446:2-21", + "2:4-18 -> 447:2-23", + "2:4-18 -> 448:2-29", + "2:4-18 -> 449:2-27", + "2:4-18 -> 450:2-28", + "2:4-18 -> 451:2-29", + "2:4-18 -> 452:2-25", + "2:4-18 -> 453:2-26", + "2:4-18 -> 454:2-27", + "2:4 -> 455:2", + "2:18 -> 456:0", ] `; diff --git a/tests/arbitrary-variants.test.js b/tests/arbitrary-variants.test.js index ffa4a70732d4..d0f7d85b5482 100644 --- a/tests/arbitrary-variants.test.js +++ b/tests/arbitrary-variants.test.js @@ -405,3 +405,91 @@ test('with @apply', () => { `) }) }) + +test('keeps escaped underscores', () => { + let config = { + content: [ + { + raw: '
', + }, + ], + corePlugins: { preflight: false }, + } + + let input = ` + @tailwind base; + @tailwind components; + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + ${defaults} + + .\[\&_\.foo\\_\\_bar\]\:underline .foo__bar { + text-decoration-line: underline; + } + `) + }) +}) + +test('keeps escaped underscores with multiple arbitrary variants', () => { + let config = { + content: [ + { + raw: '
', + }, + ], + corePlugins: { preflight: false }, + } + + let input = ` + @tailwind base; + @tailwind components; + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + ${defaults} + + .\[\&_\.foo\\_\\_bar\]\:\[\&_\.bar\\_\\_baz\]\:underline .bar__baz .foo__bar { + text-decoration-line: underline; + } + `) + }) +}) + +test('keeps escaped underscores in arbitrary variants mixed with normal variants', () => { + let config = { + content: [ + { + raw: ` +
+
+ `, + }, + ], + corePlugins: { preflight: false }, + } + + let input = ` + @tailwind base; + @tailwind components; + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + ${defaults} + + .\[\&_\.foo\\_\\_bar\]\:hover\:underline:hover .foo__bar { + text-decoration-line: underline; + } + + .hover\:\[\&_\.foo\\_\\_bar\]\:underline .foo__bar:hover { + text-decoration-line: underline; + } + `) + }) +}) diff --git a/tests/basic-usage.test.css b/tests/basic-usage.test.css index 187d31752e83..81781e635378 100644 --- a/tests/basic-usage.test.css +++ b/tests/basic-usage.test.css @@ -1,6 +1,51 @@ *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/basic-usage.test.js b/tests/basic-usage.test.js index 0abd091a7169..e72596615c84 100644 --- a/tests/basic-usage.test.js +++ b/tests/basic-usage.test.js @@ -149,56 +149,7 @@ test('default ring color can be a function', () => { return run(input, config).then((result) => { expect(result.css).toMatchFormattedCss(css` - *, - ::before, - ::after, - ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --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-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgba(var(--red), 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; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - } - + ${defaults({ defaultRingColor: 'rgba(var(--red), 0.5)' })} .ring { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); @@ -210,7 +161,7 @@ test('default ring color can be a function', () => { }) }) -it('fasly config values still work', () => { +it('falsy config values still work', () => { let config = { content: [{ raw: html`
` }], theme: { diff --git a/tests/collapse-adjacent-rules.test.css b/tests/collapse-adjacent-rules.test.css index e29c0d71a451..98f4625d74e5 100644 --- a/tests/collapse-adjacent-rules.test.css +++ b/tests/collapse-adjacent-rules.test.css @@ -9,7 +9,52 @@ } *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/default-extractor.test.js b/tests/default-extractor.test.js index 789f2eb5d685..75abf4caebfd 100644 --- a/tests/default-extractor.test.js +++ b/tests/default-extractor.test.js @@ -415,26 +415,56 @@ test('with single quotes array within template literal', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('pr-1.5') - expect(extractions).not.toContain('pr-1') }) test('with double quotes array within template literal', async () => { const extractions = defaultExtractor(`
`) expect(extractions).toContain('pr-1.5') - expect(extractions).not.toContain('pr-1') }) test('with single quotes array within function', async () => { const extractions = defaultExtractor(`document.body.classList.add(['pl-1.5'].join(" "));`) expect(extractions).toContain('pl-1.5') - expect(extractions).not.toContain('pl-1') }) test('with double quotes array within function', async () => { const extractions = defaultExtractor(`document.body.classList.add(["pl-1.5"].join(" "));`) expect(extractions).toContain('pl-1.5') - expect(extractions).not.toContain('pl-1') +}) + +test('with angle brackets', async () => { + const extractions = defaultExtractor( + `
test
` + ) + + expect(extractions).toContain('bg-blue-200') + expect(extractions).toContain('shadow-xl') + expect(extractions).not.toContain('>shadow-xl') + expect(extractions).not.toContain('shadow-xl<') +}) + +test('markdown code fences', async () => { + const extractions = defaultExtractor('') + + expect(extractions).toContain('font-bold') + expect(extractions).toContain('font-normal') + expect(extractions).not.toContain('.font-bold') + expect(extractions).not.toContain('.font-normal') +}) + +test('classes in slim templates', async () => { + const extractions = defaultExtractor(` + p.bg-red-500.text-sm + 'This is a paragraph + small.italic.text-gray-500 + '(Look mom, no closing tag!) + `) + + expect(extractions).toContain('bg-red-500') + expect(extractions).toContain('text-sm') + expect(extractions).toContain('italic') + expect(extractions).toContain('text-gray-500') }) diff --git a/tests/evaluateTailwindFunctions.test.js b/tests/evaluateTailwindFunctions.test.js index d14e95e85ce3..657cb35b5849 100644 --- a/tests/evaluateTailwindFunctions.test.js +++ b/tests/evaluateTailwindFunctions.test.js @@ -1024,3 +1024,34 @@ test('Theme function can extract alpha values for colors (8)', () => { expect(result.warnings().length).toBe(0) }) }) + +test('Theme functions can reference values with slashes in brackets', () => { + let input = css` + .foo1 { + color: theme(colors[a/b]); + } + .foo2 { + color: theme(colors[a/b]/50%); + } + ` + + let output = css` + .foo1 { + color: #000000; + } + .foo2 { + color: rgb(0 0 0 / 50%); + } + ` + + return runFull(input, { + theme: { + colors: { + 'a/b': '#000000', + }, + }, + }).then((result) => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) diff --git a/tests/import-syntax.test.css b/tests/import-syntax.test.css index d9de35ecca61..c01e767117d6 100644 --- a/tests/import-syntax.test.css +++ b/tests/import-syntax.test.css @@ -3,7 +3,52 @@ h1 { } *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/important-boolean.test.css b/tests/important-boolean.test.css index 7ffaacb2264a..8e2a865f39ee 100644 --- a/tests/important-boolean.test.css +++ b/tests/important-boolean.test.css @@ -1,6 +1,51 @@ *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/important-modifier-prefix.test.css b/tests/important-modifier-prefix.test.css index babc9354eed7..615d537b865f 100644 --- a/tests/important-modifier-prefix.test.css +++ b/tests/important-modifier-prefix.test.css @@ -1,6 +1,51 @@ *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/important-selector.test.css b/tests/important-selector.test.css index 32fd60e18507..7f15a668eeed 100644 --- a/tests/important-selector.test.css +++ b/tests/important-selector.test.css @@ -1,6 +1,51 @@ *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/kitchen-sink.test.css b/tests/kitchen-sink.test.css index 9883eb1c536c..2785325a8891 100644 --- a/tests/kitchen-sink.test.css +++ b/tests/kitchen-sink.test.css @@ -138,7 +138,52 @@ div { } *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/opacity.test.js b/tests/opacity.test.js index 38ea4ab44142..7215d14db332 100644 --- a/tests/opacity.test.js +++ b/tests/opacity.test.js @@ -728,3 +728,36 @@ it('should be possible to use inside arbitrary values', () => { `) }) }) + +it('Theme functions can reference values with slashes in brackets', () => { + let config = { + content: [ + { + raw: html`
`, + }, + ], + theme: { + colors: { + 'a/b': '#000000', + }, + extend: { + backgroundColor: ({ theme }) => ({ + foo1: theme('colors[a/b]'), + foo2: theme('colors[a/b]/50%'), + }), + }, + }, + } + + return run('@tailwind utilities', config).then((result) => { + expect(result.css).toMatchCss(css` + .bg-foo1 { + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); + } + .bg-foo2 { + background-color: rgb(0 0 0 / 50%); + } + `) + }) +}) diff --git a/tests/plugins/divide.test.js b/tests/plugins/divide.test.js index d56dbfa16fcc..e50ea4e4fc33 100644 --- a/tests/plugins/divide.test.js +++ b/tests/plugins/divide.test.js @@ -1,4 +1,4 @@ -import { run, html, css } from '../util/run' +import { run, html, css, defaults } from '../util/run' it('should add the divide styles for divide-y and a default border color', () => { let config = { @@ -8,55 +8,7 @@ it('should add the divide styles for divide-y and a default border color', () => return run('@tailwind base; @tailwind utilities;', config).then((result) => { expect(result.css).toMatchCss(css` - *, - ::before, - ::after, - ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --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-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --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; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - } + ${defaults} .divide-y > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; @@ -75,55 +27,7 @@ it('should add the divide styles for divide-x and a default border color', () => return run('@tailwind base; @tailwind utilities;', config).then((result) => { expect(result.css).toMatchCss(css` - *, - ::before, - ::after, - ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --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-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --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; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - } + ${defaults} .divide-x > :not([hidden]) ~ :not([hidden]) { --tw-divide-x-reverse: 0; @@ -142,55 +46,7 @@ it('should add the divide styles for divide-y-reverse and a default border color return run('@tailwind base; @tailwind utilities;', config).then((result) => { expect(result.css).toMatchCss(css` - *, - ::before, - ::after, - ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --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-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --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; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - } + ${defaults} .divide-y-reverse > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 1; @@ -207,55 +63,7 @@ it('should add the divide styles for divide-x-reverse and a default border color return run('@tailwind base; @tailwind utilities;', config).then((result) => { expect(result.css).toMatchCss(css` - *, - ::before, - ::after, - ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --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-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --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; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - } + ${defaults} .divide-x-reverse > :not([hidden]) ~ :not([hidden]) { --tw-divide-x-reverse: 1; @@ -272,55 +80,7 @@ it('should only inject the base styles once if we use divide and border at the s return run('@tailwind base; @tailwind utilities;', config).then((result) => { expect(result.css).toMatchCss(css` - *, - ::before, - ::after, - ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --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-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --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; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - } + ${defaults} .divide-y > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; diff --git a/tests/prefix.test.css b/tests/prefix.test.css index 10e75666618d..b749e1a9eec6 100644 --- a/tests/prefix.test.css +++ b/tests/prefix.test.css @@ -1,6 +1,51 @@ *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/resolve-defaults-at-rules.test.js b/tests/resolve-defaults-at-rules.test.js index d316a604ddc1..45f9872a03f4 100644 --- a/tests/resolve-defaults-at-rules.test.js +++ b/tests/resolve-defaults-at-rules.test.js @@ -16,7 +16,15 @@ test('basic utilities', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --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; + } ::backdrop { --tw-translate-x: 0; --tw-translate-y: 0; @@ -68,7 +76,15 @@ test('with pseudo-class variants', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --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; + } ::backdrop { --tw-translate-x: 0; --tw-translate-y: 0; @@ -118,7 +134,15 @@ test('with pseudo-element variants', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --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; + } ::backdrop { --tw-translate-x: 0; --tw-translate-y: 0; @@ -164,7 +188,15 @@ test('with multi-class variants', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --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; + } ::backdrop { --tw-translate-x: 0; --tw-translate-y: 0; @@ -210,7 +242,15 @@ test('with multi-class pseudo-element variants', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --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; + } ::backdrop { --tw-translate-x: 0; --tw-translate-y: 0; @@ -262,7 +302,15 @@ test('with multi-class pseudo-element and pseudo-class variants', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --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; + } ::backdrop { --tw-translate-x: 0; --tw-translate-y: 0; @@ -350,7 +398,15 @@ test('with apply', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --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; + } ::backdrop { --tw-translate-x: 0; --tw-translate-y: 0; @@ -547,7 +603,16 @@ test('with shadows', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --tw-ring-inset: ; + --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; + } ::backdrop { --tw-ring-inset: ; --tw-ring-offset-width: 0px; @@ -606,7 +671,15 @@ test('when no utilities that need the defaults are used', async () => { expect(result.css).toMatchFormattedCss(css` *, ::before, - ::after, + ::after { + --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; + } ::backdrop { --tw-translate-x: 0; --tw-translate-y: 0; diff --git a/tests/util/defaults.js b/tests/util/defaults.js index 061bcc854e98..bc65e2e8e646 100644 --- a/tests/util/defaults.js +++ b/tests/util/defaults.js @@ -9,7 +9,52 @@ export function defaults({ defaultRingColor = `rgb(59 130 246 / 0.5)` } = {}) { return css` *, ::before, - ::after, + ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: ${defaultRingColor}; + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + } ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/tests/variants.test.css b/tests/variants.test.css index 7debafd76e11..535ffa23177e 100644 --- a/tests/variants.test.css +++ b/tests/variants.test.css @@ -1,6 +1,51 @@ *, ::before, -::after, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --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-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --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; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} ::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; diff --git a/types/index.d.ts b/types/index.d.ts index 11bec63ff25b..131877e77868 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1 +1,7 @@ -export type { Config } from './config.d' +import { PluginCreator } from 'postcss' +import type { Config } from './config.d' + +declare const plugin: PluginCreator + +export { Config } +export default plugin