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