From a785c93b54c770b65364a8c781761dd97ac684d5 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Wed, 29 Mar 2023 15:32:37 +0200
Subject: [PATCH 1/8] Try resolving `config.default` before `config` to ensure
the config file is resolved correctly (#10898)
* try to use `config.default` before using `config`
* update changelog
* add quick `SHOW_OUTPUT` toggle for integration tests
Setting this to `true` shows the output of the executed commands.
* add integration tests for `tailwind.config.ts` and `tailwind.config.js` with ESM syntax
---
CHANGELOG.md | 4 +-
integrations/execute.js | 8 ++
integrations/parcel/tests/integration.test.js | 133 +++++++++++++++++-
integrations/rollup/tests/integration.test.js | 116 ++++++++++++++-
.../tailwindcss-cli/tests/integration.test.js | 116 ++++++++++++++-
integrations/vite/tests/integration.test.js | 112 ++++++++++++++-
.../webpack-4/tests/integration.test.js | 117 ++++++++++++++-
.../webpack-5/tests/integration.test.js | 117 ++++++++++++++-
src/lib/load-config.ts | 14 +-
9 files changed, 719 insertions(+), 18 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 879ed210eea2..270fc089d6e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
-- Nothing yet!
+### Fixed
+
+- Try resolving `config.default` before `config` to ensure the config file is resolved correctly ([#10898](https://github.com/tailwindlabs/tailwindcss/pull/10898))
## [3.3.0] - 2023-03-27
diff --git a/integrations/execute.js b/integrations/execute.js
index f5ab2131804a..6c5f2036327d 100644
--- a/integrations/execute.js
+++ b/integrations/execute.js
@@ -3,6 +3,8 @@ let path = require('path')
let { spawn } = require('child_process')
let resolveToolRoot = require('./resolve-tool-root')
+let SHOW_OUTPUT = false
+
let runningProcessess = []
afterEach(() => {
@@ -92,6 +94,9 @@ module.exports = function $(command, options = {}) {
let combined = ''
child.stdout.on('data', (data) => {
+ if (SHOW_OUTPUT) {
+ console.log(data.toString())
+ }
stdoutMessages.push(data.toString())
notifyNextStdoutActor()
stdout += data
@@ -99,6 +104,9 @@ module.exports = function $(command, options = {}) {
})
child.stderr.on('data', (data) => {
+ if (SHOW_OUTPUT) {
+ console.error(data.toString())
+ }
stderrMessages.push(data.toString())
notifyNextStderrActor()
stderr += data
diff --git a/integrations/parcel/tests/integration.test.js b/integrations/parcel/tests/integration.test.js
index 0fc539f37eec..55e7f83a38b0 100644
--- a/integrations/parcel/tests/integration.test.js
+++ b/integrations/parcel/tests/integration.test.js
@@ -3,11 +3,12 @@ let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let {
- readOutputFile,
appendToInputFile,
- writeInputFile,
- waitForOutputFileCreation,
+ readOutputFile,
+ removeFile,
waitForOutputFileChange,
+ waitForOutputFileCreation,
+ writeInputFile,
} = require('../../io')({ output: 'dist', input: 'src' })
describe('static build', () => {
@@ -32,6 +33,132 @@ describe('static build', () => {
`
)
})
+
+ it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile(
+ 'index.html',
+ html`
+
+
+ `
+ )
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.js',
+ javascript`
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ }
+ `
+ )
+
+ await $('parcel build ./src/index.html --no-cache', {
+ env: { NODE_ENV: 'production' },
+ })
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
+
+ it('can use a tailwind.config.ts configuration file', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile(
+ 'index.html',
+ html`
+
+
+ `
+ )
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.ts',
+ javascript`
+ import type { Config } from 'tailwindcss'
+
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ } satisfies Config
+ `
+ )
+
+ await $('parcel build ./src/index.html --no-cache', {
+ env: { NODE_ENV: 'production' },
+ })
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
})
describe('watcher', () => {
diff --git a/integrations/rollup/tests/integration.test.js b/integrations/rollup/tests/integration.test.js
index 1daea888a875..dbbfcc8d11f1 100644
--- a/integrations/rollup/tests/integration.test.js
+++ b/integrations/rollup/tests/integration.test.js
@@ -2,7 +2,7 @@ let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
-let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
+let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({
output: 'dist',
input: 'src',
})
@@ -27,6 +27,120 @@ describe('static build', () => {
`
)
})
+
+ it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile('index.html', html``)
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.js',
+ javascript`
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ }
+ `
+ )
+
+ await $('rollup -c', {
+ env: { NODE_ENV: 'production' },
+ })
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile('index.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile('index.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
+
+ it('can use a tailwind.config.ts configuration file', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile('index.html', html``)
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.ts',
+ javascript`
+ import type { Config } from 'tailwindcss'
+
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ } satisfies Config
+ `
+ )
+
+ await $('rollup -c', {
+ env: { NODE_ENV: 'production' },
+ })
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile('index.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile('index.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
})
describe('watcher', () => {
diff --git a/integrations/tailwindcss-cli/tests/integration.test.js b/integrations/tailwindcss-cli/tests/integration.test.js
index ff8db20b8a2d..6efa9fdf5e44 100644
--- a/integrations/tailwindcss-cli/tests/integration.test.js
+++ b/integrations/tailwindcss-cli/tests/integration.test.js
@@ -3,7 +3,7 @@ let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
-let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
+let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({
output: 'dist',
input: 'src',
})
@@ -111,6 +111,120 @@ describe('static build', () => {
}
})
+ it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile('index.html', html``)
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.js',
+ javascript`
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ }
+ `
+ )
+
+ await $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css', {
+ env: { NODE_ENV: 'production' },
+ })
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
+
+ it('can use a tailwind.config.ts configuration file', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile('index.html', html``)
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.ts',
+ javascript`
+ import type { Config } from 'tailwindcss'
+
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ } satisfies Config
+ `
+ )
+
+ await $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css', {
+ env: { NODE_ENV: 'production' },
+ })
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
+
it('can read from a config file from an @config directive', async () => {
await writeInputFile('index.html', html``)
await writeInputFile(
diff --git a/integrations/vite/tests/integration.test.js b/integrations/vite/tests/integration.test.js
index 1e5cd2d3345e..a07a2a9a6efc 100644
--- a/integrations/vite/tests/integration.test.js
+++ b/integrations/vite/tests/integration.test.js
@@ -4,7 +4,7 @@ let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
-let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
+let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({
output: 'dist',
input: '.',
})
@@ -42,6 +42,116 @@ describe('static build', () => {
`
)
})
+
+ it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
+ await writeInputFile(
+ 'index.html',
+ html`
+
+
+ `
+ )
+ await removeFile('tailwind.config.js')
+ await writeInputFile(
+ 'tailwind.config.js',
+ javascript`
+ export default {
+ content: ['index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ }
+ `
+ )
+
+ await $('vite build', {
+ env: { NODE_ENV: 'production', NO_COLOR: '1' },
+ })
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
+
+ it('can use a tailwind.config.ts configuration file', async () => {
+ await writeInputFile(
+ 'index.html',
+ html`
+
+
+ `
+ )
+ await removeFile('tailwind.config.js')
+ await writeInputFile(
+ 'tailwind.config.ts',
+ javascript`
+ import type { Config } from 'tailwindcss'
+
+ export default {
+ content: ['index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ } satisfies Config
+ `
+ )
+
+ await $('vite build', {
+ env: { NODE_ENV: 'production', NO_COLOR: '1' },
+ })
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
})
describe('watcher', () => {
diff --git a/integrations/webpack-4/tests/integration.test.js b/integrations/webpack-4/tests/integration.test.js
index 6bbf3f879fcd..a666721bbdc1 100644
--- a/integrations/webpack-4/tests/integration.test.js
+++ b/integrations/webpack-4/tests/integration.test.js
@@ -3,11 +3,12 @@ let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let {
- readOutputFile,
appendToInputFile,
- writeInputFile,
- waitForOutputFileCreation,
+ readOutputFile,
+ removeFile,
waitForOutputFileChange,
+ waitForOutputFileCreation,
+ writeInputFile,
} = require('../../io')({ output: 'dist', input: 'src' })
describe('static build', () => {
@@ -24,6 +25,116 @@ describe('static build', () => {
`
)
})
+
+ it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile('index.html', html``)
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.js',
+ javascript`
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ }
+ `
+ )
+
+ await $('webpack --mode=production')
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
+
+ it('can use a tailwind.config.ts configuration file', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile('index.html', html``)
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.ts',
+ javascript`
+ import type { Config } from 'tailwindcss'
+
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ } satisfies Config
+ `
+ )
+
+ await $('webpack --mode=production')
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
})
describe('watcher', () => {
diff --git a/integrations/webpack-5/tests/integration.test.js b/integrations/webpack-5/tests/integration.test.js
index fde0d60c5364..ae493fbdbb66 100644
--- a/integrations/webpack-5/tests/integration.test.js
+++ b/integrations/webpack-5/tests/integration.test.js
@@ -3,11 +3,12 @@ let { css, html, javascript } = require('../../syntax')
let { env } = require('../../../lib/lib/sharedState')
let {
- readOutputFile,
appendToInputFile,
- writeInputFile,
- waitForOutputFileCreation,
+ readOutputFile,
+ removeFile,
waitForOutputFileChange,
+ waitForOutputFileCreation,
+ writeInputFile,
} = require('../../io')({ output: 'dist', input: 'src' })
describe('static build', () => {
@@ -24,6 +25,116 @@ describe('static build', () => {
`
)
})
+
+ it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile('index.html', html``)
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.js',
+ javascript`
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ }
+ `
+ )
+
+ await $('webpack --mode=production')
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
+
+ it('can use a tailwind.config.ts configuration file', async () => {
+ await removeFile('tailwind.config.js')
+ await writeInputFile('index.html', html``)
+ await writeInputFile(
+ 'index.css',
+ css`
+ @tailwind base;
+ @tailwind components;
+ @tailwind utilities;
+ `
+ )
+ await writeInputFile(
+ '../tailwind.config.ts',
+ javascript`
+ import type { Config } from 'tailwindcss'
+
+ export default {
+ content: ['./src/index.html'],
+ theme: {
+ extend: {
+ colors: {
+ primary: 'black',
+ },
+ },
+ },
+ corePlugins: {
+ preflight: false,
+ },
+ } satisfies Config
+ `
+ )
+
+ await $('webpack --mode=production')
+
+ if (!env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ --tw-bg-opacity: 1;
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
+ }
+ `
+ )
+ }
+
+ if (env.OXIDE) {
+ expect(await readOutputFile('main.css')).toIncludeCss(
+ css`
+ .bg-primary {
+ background-color: black;
+ }
+ `
+ )
+ }
+ })
})
describe('watcher', () => {
diff --git a/src/lib/load-config.ts b/src/lib/load-config.ts
index 89ce3a368d0b..645e8e1d55c4 100644
--- a/src/lib/load-config.ts
+++ b/src/lib/load-config.ts
@@ -19,9 +19,13 @@ function lazyJiti() {
}
export function loadConfig(path: string): Config {
- try {
- return path ? require(path) : {}
- } catch {
- return lazyJiti()(path)
- }
+ let config = (function () {
+ try {
+ return path ? require(path) : {}
+ } catch {
+ return lazyJiti()(path)
+ }
+ })()
+
+ return config.default ?? config
}
From 0ecc4642fc80f574f2dc7f0fe89884e392dc56c4 Mon Sep 17 00:00:00 2001
From: Jordan Pittman
Date: Wed, 29 Mar 2023 15:37:26 -0400
Subject: [PATCH 2/8] Pull pseudo elements outside of `:is` and `:has` when
using `@apply` (#10903)
* Pull pseudo elements outside of `:is` and `:has` when using `@apply`
* Update changelog
* Refactor
* Update important selector handling for :is and :has
* fixup
* fixup
* trigger CI
---------
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 1 +
src/lib/expandApplyAtRules.js | 12 +++++
src/util/applyImportantSelector.js | 34 ++++++++++-----
src/util/formatVariantSelector.js | 46 +++++++++++++++-----
tests/apply.test.js | 70 ++++++++++++++++++++++++++++++
tests/important-selector.test.js | 7 +++
6 files changed, 149 insertions(+), 21 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 270fc089d6e8..1fc7165535cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Try resolving `config.default` before `config` to ensure the config file is resolved correctly ([#10898](https://github.com/tailwindlabs/tailwindcss/pull/10898))
+- Pull pseudo elements outside of `:is` and `:has` when using `@apply` ([#10903](https://github.com/tailwindlabs/tailwindcss/pull/10903))
## [3.3.0] - 2023-03-27
diff --git a/src/lib/expandApplyAtRules.js b/src/lib/expandApplyAtRules.js
index cdcd0b5688c9..c6d53d80e29f 100644
--- a/src/lib/expandApplyAtRules.js
+++ b/src/lib/expandApplyAtRules.js
@@ -4,6 +4,7 @@ import parser from 'postcss-selector-parser'
import { resolveMatches } from './generateRules'
import escapeClassName from '../util/escapeClassName'
import { applyImportantSelector } from '../util/applyImportantSelector'
+import { collectPseudoElements, sortSelector } from '../util/formatVariantSelector.js'
/** @typedef {Map} ApplyCache */
@@ -562,6 +563,17 @@ function processApply(root, context, localCache) {
rule.walkDecls((d) => {
d.important = meta.important || important
})
+
+ // Move pseudo elements to the end of the selector (if necessary)
+ let selector = parser().astSync(rule.selector)
+ selector.each((sel) => {
+ let [pseudoElements] = collectPseudoElements(sel)
+ if (pseudoElements.length > 0) {
+ sel.nodes.push(...pseudoElements.sort(sortSelector))
+ }
+ })
+
+ rule.selector = selector.toString()
})
}
diff --git a/src/util/applyImportantSelector.js b/src/util/applyImportantSelector.js
index 69de63325c79..dbaf136cce20 100644
--- a/src/util/applyImportantSelector.js
+++ b/src/util/applyImportantSelector.js
@@ -1,19 +1,31 @@
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
+import parser from 'postcss-selector-parser'
+import { collectPseudoElements, sortSelector } from './formatVariantSelector.js'
export function applyImportantSelector(selector, important) {
- let matches = /^(.*?)(:before|:after|::[\w-]+)(\)*)$/g.exec(selector)
- if (!matches) return `${important} ${wrapWithIs(selector)}`
+ let sel = parser().astSync(selector)
- let [, before, pseudo, brackets] = matches
- return `${important} ${wrapWithIs(before + brackets)}${pseudo}`
-}
+ sel.each((sel) => {
+ // Wrap with :is if it's not already wrapped
+ let isWrapped =
+ sel.nodes[0].type === 'pseudo' &&
+ sel.nodes[0].value === ':is' &&
+ sel.nodes.every((node) => node.type !== 'combinator')
-function wrapWithIs(selector) {
- let parts = splitAtTopLevelOnly(selector, ' ')
+ if (!isWrapped) {
+ sel.nodes = [
+ parser.pseudo({
+ value: ':is',
+ nodes: [sel.clone()],
+ }),
+ ]
+ }
- if (parts.length === 1 && parts[0].startsWith(':is(') && parts[0].endsWith(')')) {
- return selector
- }
+ let [pseudoElements] = collectPseudoElements(sel)
+ if (pseudoElements.length > 0) {
+ sel.nodes.push(...pseudoElements.sort(sortSelector))
+ }
+ })
- return `:is(${selector})`
+ return `${important} ${sel.toString()}`
}
diff --git a/src/util/formatVariantSelector.js b/src/util/formatVariantSelector.js
index da5e2c78dfbc..8a1a3f50c1f8 100644
--- a/src/util/formatVariantSelector.js
+++ b/src/util/formatVariantSelector.js
@@ -246,9 +246,9 @@ export function finalizeSelector(current, formats, { context, candidate, base })
// Move pseudo elements to the end of the selector (if necessary)
selector.each((sel) => {
- let pseudoElements = collectPseudoElements(sel)
+ let [pseudoElements] = collectPseudoElements(sel)
if (pseudoElements.length > 0) {
- sel.nodes.push(pseudoElements.sort(sortSelector))
+ sel.nodes.push(...pseudoElements.sort(sortSelector))
}
})
@@ -351,23 +351,45 @@ let pseudoElementExceptions = [
* `::before:hover` doesn't work, which means that we can make it work for you by flipping the order.
*
* @param {Selector} selector
+ * @param {boolean} force
**/
-function collectPseudoElements(selector) {
+export function collectPseudoElements(selector, force = false) {
/** @type {Node[]} */
let nodes = []
+ let seenPseudoElement = null
- for (let node of selector.nodes) {
- if (isPseudoElement(node)) {
+ for (let node of [...selector.nodes]) {
+ if (isPseudoElement(node, force)) {
nodes.push(node)
selector.removeChild(node)
+ seenPseudoElement = node.value
+ } else if (seenPseudoElement !== null) {
+ if (pseudoElementExceptions.includes(seenPseudoElement) && isPseudoClass(node, force)) {
+ nodes.push(node)
+ selector.removeChild(node)
+ } else {
+ seenPseudoElement = null
+ }
}
if (node?.nodes) {
- nodes.push(...collectPseudoElements(node))
+ let hasPseudoElementRestrictions =
+ node.type === 'pseudo' && (node.value === ':is' || node.value === ':has')
+
+ let [collected, seenPseudoElementInSelector] = collectPseudoElements(
+ node,
+ force || hasPseudoElementRestrictions
+ )
+
+ if (seenPseudoElementInSelector) {
+ seenPseudoElement = seenPseudoElementInSelector
+ }
+
+ nodes.push(...collected)
}
}
- return nodes
+ return [nodes, seenPseudoElement]
}
// This will make sure to move pseudo's to the correct spot (the end for
@@ -380,7 +402,7 @@ function collectPseudoElements(selector) {
//
// `::before:hover` doesn't work, which means that we can make it work
// for you by flipping the order.
-function sortSelector(a, z) {
+export function sortSelector(a, z) {
// Both nodes are non-pseudo's so we can safely ignore them and keep
// them in the same order.
if (a.type !== 'pseudo' && z.type !== 'pseudo') {
@@ -404,9 +426,13 @@ function sortSelector(a, z) {
return isPseudoElement(a) - isPseudoElement(z)
}
-function isPseudoElement(node) {
+function isPseudoElement(node, force = false) {
if (node.type !== 'pseudo') return false
- if (pseudoElementExceptions.includes(node.value)) return false
+ if (pseudoElementExceptions.includes(node.value) && !force) return false
return node.value.startsWith('::') || pseudoElementsBC.includes(node.value)
}
+
+function isPseudoClass(node, force) {
+ return node.type === 'pseudo' && !isPseudoElement(node, force)
+}
diff --git a/tests/apply.test.js b/tests/apply.test.js
index f7fab7d70938..0ab9ec17567f 100644
--- a/tests/apply.test.js
+++ b/tests/apply.test.js
@@ -2357,4 +2357,74 @@ crosscheck(({ stable, oxide }) => {
`)
})
})
+
+ it('pseudo elements inside apply are moved outside of :is() or :has()', () => {
+ let config = {
+ darkMode: 'class',
+ content: [
+ {
+ raw: html` `,
+ },
+ ],
+ }
+
+ let input = css`
+ .foo::before {
+ @apply dark:bg-black/100;
+ }
+
+ .bar::before {
+ @apply rtl:dark:bg-black/100;
+ }
+
+ .baz::before {
+ @apply rtl:dark:hover:bg-black/100;
+ }
+
+ .qux::file-selector-button {
+ @apply rtl:dark:hover:bg-black/100;
+ }
+
+ .steve::before {
+ @apply rtl:hover:dark:bg-black/100;
+ }
+
+ .bob::file-selector-button {
+ @apply rtl:hover:dark:bg-black/100;
+ }
+
+ .foo::before {
+ @apply [:has([dir="rtl"]_&)]:hover:bg-black/100;
+ }
+
+ .bar::file-selector-button {
+ @apply [:has([dir="rtl"]_&)]:hover:bg-black/100;
+ }
+ `
+
+ return run(input, config).then((result) => {
+ expect(result.css).toMatchFormattedCss(css`
+ :is(.dark .foo)::before,
+ :is([dir='rtl'] :is(.dark .bar))::before,
+ :is([dir='rtl'] :is(.dark .baz:hover))::before {
+ background-color: #000;
+ }
+ :is([dir='rtl'] :is(.dark .qux))::file-selector-button:hover {
+ background-color: #000;
+ }
+ :is([dir='rtl'] :is(.dark .steve):hover):before {
+ background-color: #000;
+ }
+ :is([dir='rtl'] :is(.dark .bob))::file-selector-button:hover {
+ background-color: #000;
+ }
+ :has([dir='rtl'] .foo:hover):before {
+ background-color: #000;
+ }
+ :has([dir='rtl'] .bar)::file-selector-button:hover {
+ background-color: #000;
+ }
+ `)
+ })
+ })
})
diff --git a/tests/important-selector.test.js b/tests/important-selector.test.js
index 5c6515e43086..22edafb94dd1 100644
--- a/tests/important-selector.test.js
+++ b/tests/important-selector.test.js
@@ -21,6 +21,7 @@ crosscheck(({ stable, oxide }) => {
+
`,
},
],
@@ -155,6 +156,12 @@ crosscheck(({ stable, oxide }) => {
text-align: right;
}
}
+ #app
+ :is(
+ [dir='rtl'] :is(.dark .hover\:\[\&\:\:file-selector-button\]\:rtl\:dark\:bg-black\/100)
+ )::file-selector-button:hover {
+ background-color: #000;
+ }
`)
})
})
From 60c06dc293acd3d2d91fd5105b7bd5550684225a Mon Sep 17 00:00:00 2001
From: Joey Jan
Date: Wed, 29 Mar 2023 16:54:57 -0400
Subject: [PATCH 3/8] Update the types for the `safelist` config (#10901)
* Revert prepare of v3.3
* Revert "Revert prepare of v3.3"
This reverts commit 14d5a0a7c6d457a9b73fa1a9aca6ed41c46b27ad.
* update SafelistConfig type
I think this type was meant to be like this?
* format types
* update changelog
---------
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 1 +
types/config.d.ts | 7 +------
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1fc7165535cc..e73dc309a188 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Try resolving `config.default` before `config` to ensure the config file is resolved correctly ([#10898](https://github.com/tailwindlabs/tailwindcss/pull/10898))
- Pull pseudo elements outside of `:is` and `:has` when using `@apply` ([#10903](https://github.com/tailwindlabs/tailwindcss/pull/10903))
+- Update the types for the `safelist` config ([#10901](https://github.com/tailwindlabs/tailwindcss/pull/10901))
## [3.3.0] - 2023-03-27
diff --git a/types/config.d.ts b/types/config.d.ts
index 81e3c342db16..bb40c8b71a10 100644
--- a/types/config.d.ts
+++ b/types/config.d.ts
@@ -46,12 +46,7 @@ type PrefixConfig = string
type SeparatorConfig = string
// Safelist related config
-type SafelistConfig =
- | string[]
- | {
- pattern: RegExp
- variants?: string[]
- }[]
+type SafelistConfig = (string | { pattern: RegExp; variants?: string[] })[]
// Blocklist related config
type BlocklistConfig = string[]
From 3193dae61d201b6a80bf93e72652c5b59d529588 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Wed, 29 Mar 2023 23:03:37 +0200
Subject: [PATCH 4/8] ensure workflows run for the 3.3 branch
---
.github/workflows/ci-stable.yml | 2 +-
.github/workflows/ci.yml | 4 ++--
.github/workflows/integration-tests-oxide.yml | 4 ++--
.github/workflows/integration-tests-stable.yml | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/ci-stable.yml b/.github/workflows/ci-stable.yml
index e5807f50672c..60d6abb9a0c8 100644
--- a/.github/workflows/ci-stable.yml
+++ b/.github/workflows/ci-stable.yml
@@ -7,7 +7,7 @@ on:
push:
branches: [master]
pull_request:
- branches: [master]
+ branches: [master, 3.3]
permissions:
contents: read
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index fc17ba99dd0e..29b96700c8e8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,9 +2,9 @@ name: CI — Oxide
on:
push:
- branches: [master]
+ branches: [master, 3.3]
pull_request:
- branches: [master]
+ branches: [master, 3.3]
permissions:
contents: read
diff --git a/.github/workflows/integration-tests-oxide.yml b/.github/workflows/integration-tests-oxide.yml
index 27cd8f562417..b9b3e513d6f2 100644
--- a/.github/workflows/integration-tests-oxide.yml
+++ b/.github/workflows/integration-tests-oxide.yml
@@ -2,9 +2,9 @@ name: Integration Tests — Oxide
on:
push:
- branches: [master]
+ branches: [master, 3.3]
pull_request:
- branches: [master]
+ branches: [master, 3.3]
permissions:
contents: read
diff --git a/.github/workflows/integration-tests-stable.yml b/.github/workflows/integration-tests-stable.yml
index 547d20f1c283..86329d4044bd 100644
--- a/.github/workflows/integration-tests-stable.yml
+++ b/.github/workflows/integration-tests-stable.yml
@@ -2,9 +2,9 @@ name: Integration Tests — Stable
on:
push:
- branches: [master]
+ branches: [master, 3.3]
pull_request:
- branches: [master]
+ branches: [master, 3.3]
permissions:
contents: read
From 447384bcbe658d2cf72949c04d4a5d7954181e90 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Wed, 29 Mar 2023 23:05:19 +0200
Subject: [PATCH 5/8] cleanup unused import
---
src/util/applyImportantSelector.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/util/applyImportantSelector.js b/src/util/applyImportantSelector.js
index dbaf136cce20..d85efcad2fd0 100644
--- a/src/util/applyImportantSelector.js
+++ b/src/util/applyImportantSelector.js
@@ -1,4 +1,3 @@
-import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
import parser from 'postcss-selector-parser'
import { collectPseudoElements, sortSelector } from './formatVariantSelector.js'
From 9cd0301b0af16fb40acbe71443ab4d4f20346167 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Thu, 30 Mar 2023 18:42:38 +0200
Subject: [PATCH 6/8] Drop `@tailwindcss/line-clamp` warning (#10915)
* drop `@tailwindcss/line-clamp` check
This won't work in places where `require` calls are hoisted so that
they become static imports. This means that in some projects this
`require` call was breaking the full application even though it was
intentionally put in a try/catch block...
* update changelog
---
CHANGELOG.md | 1 +
src/util/normalizeConfig.js | 17 -----------------
2 files changed, 1 insertion(+), 17 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e73dc309a188..1b40827804e3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Try resolving `config.default` before `config` to ensure the config file is resolved correctly ([#10898](https://github.com/tailwindlabs/tailwindcss/pull/10898))
- Pull pseudo elements outside of `:is` and `:has` when using `@apply` ([#10903](https://github.com/tailwindlabs/tailwindcss/pull/10903))
- Update the types for the `safelist` config ([#10901](https://github.com/tailwindlabs/tailwindcss/pull/10901))
+- Drop `@tailwindcss/line-clamp` warning ([#10915](https://github.com/tailwindlabs/tailwindcss/pull/10915))
## [3.3.0] - 2023-03-27
diff --git a/src/util/normalizeConfig.js b/src/util/normalizeConfig.js
index 1c8c93db1c5d..7e1a592decda 100644
--- a/src/util/normalizeConfig.js
+++ b/src/util/normalizeConfig.js
@@ -297,22 +297,5 @@ export function normalizeConfig(config) {
}
}
- // Warn if the line-clamp plugin is installed
- if (config.plugins.length > 0) {
- let plugin
- try {
- plugin = require('@tailwindcss/line-clamp')
- } catch {}
-
- if (plugin && config.plugins.includes(plugin)) {
- log.warn('line-clamp-in-core', [
- 'As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.',
- 'Remove it from the `plugins` array in your configuration to eliminate this warning.',
- ])
-
- config.plugins = config.plugins.filter((p) => p !== plugin)
- }
- }
-
return config
}
From 474178055eb67336d7d4a158a394b048faa3cf10 Mon Sep 17 00:00:00 2001
From: Jordan Pittman
Date: Thu, 30 Mar 2023 15:06:17 -0400
Subject: [PATCH 7/8] Fix `@tailwindcss/line-clamp` warning (#10919)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* WIP
* Move warning to validateConfig
This only happens in setupTrackingContext outside of resolveConfig
* Use original dynamic require approach in `validateConfig`
The important thing is that this happens in Node-land only. It is outside of `resolveConfig` which is public and importable into user projects. That is the scenario that breaks because of static import hoisting.
* Don’t reference process when it might be undefined
The `resolveConfig` dep path is public which should not reference process. However, we have some behavior that changes based on env vars so we need to conditionalize it instead.
* Update changelog
* Formatting
* More formatting
* Update changelog
---------
Co-authored-by: Robin Malfait
Co-authored-by: Jonathan Reinink
---
CHANGELOG.md | 3 ++-
src/lib/sharedState.js | 21 +++++++++++++++------
src/util/validateConfig.js | 13 +++++++++++++
3 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b40827804e3..50b2fc77d717 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,7 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Try resolving `config.default` before `config` to ensure the config file is resolved correctly ([#10898](https://github.com/tailwindlabs/tailwindcss/pull/10898))
- Pull pseudo elements outside of `:is` and `:has` when using `@apply` ([#10903](https://github.com/tailwindlabs/tailwindcss/pull/10903))
- Update the types for the `safelist` config ([#10901](https://github.com/tailwindlabs/tailwindcss/pull/10901))
-- Drop `@tailwindcss/line-clamp` warning ([#10915](https://github.com/tailwindlabs/tailwindcss/pull/10915))
+- Fix `@tailwindcss/line-clamp` warning ([#10915](https://github.com/tailwindlabs/tailwindcss/pull/10915), [#10919](https://github.com/tailwindlabs/tailwindcss/pull/10919))
+- Fix `process` is not defined error ([#10919](https://github.com/tailwindlabs/tailwindcss/pull/10919))
## [3.3.0] - 2023-03-27
diff --git a/src/lib/sharedState.js b/src/lib/sharedState.js
index 736a5d8bcc64..1a4a8d5e5b17 100644
--- a/src/lib/sharedState.js
+++ b/src/lib/sharedState.js
@@ -1,12 +1,21 @@
import pkg from '../../package.json'
let OXIDE_DEFAULT_ENABLED = pkg.tailwindcss.engine === 'oxide'
-export const env = {
- NODE_ENV: process.env.NODE_ENV,
- DEBUG: resolveDebug(process.env.DEBUG),
- ENGINE: pkg.tailwindcss.engine,
- OXIDE: resolveBoolean(process.env.OXIDE, OXIDE_DEFAULT_ENABLED),
-}
+export const env =
+ typeof process !== 'undefined'
+ ? {
+ NODE_ENV: process.env.NODE_ENV,
+ DEBUG: resolveDebug(process.env.DEBUG),
+ ENGINE: pkg.tailwindcss.engine,
+ OXIDE: resolveBoolean(process.env.OXIDE, OXIDE_DEFAULT_ENABLED),
+ }
+ : {
+ NODE_ENV: 'production',
+ DEBUG: false,
+ ENGINE: pkg.tailwindcss.engine,
+ OXIDE: OXIDE_DEFAULT_ENABLED,
+ }
+
export const contextMap = new Map()
export const configContextMap = new Map()
export const contextSourcesMap = new Map()
diff --git a/src/util/validateConfig.js b/src/util/validateConfig.js
index 23b4627fbb54..8c22e445035b 100644
--- a/src/util/validateConfig.js
+++ b/src/util/validateConfig.js
@@ -9,5 +9,18 @@ export function validateConfig(config) {
])
}
+ // Warn if the line-clamp plugin is installed
+ try {
+ let plugin = require('@tailwindcss/line-clamp')
+ if (config.plugins.includes(plugin)) {
+ log.warn('line-clamp-in-core', [
+ 'As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.',
+ 'Remove it from the `plugins` array in your configuration to eliminate this warning.',
+ ])
+
+ config.plugins = config.plugins.filter((p) => p !== plugin)
+ }
+ } catch {}
+
return config
}
From 1e55b798d74baa5a50921668c4e3231175c74cd7 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Thu, 30 Mar 2023 18:43:25 +0200
Subject: [PATCH 8/8] 3.3.1
---
CHANGELOG.md | 7 ++++++-
package-lock.json | 4 ++--
package-lock.stable.json | 4 ++--
package.json | 2 +-
package.stable.json | 2 +-
5 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 50b2fc77d717..b654143f46d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+- Nothing yet!
+
+## [3.3.1] - 2023-03-30
+
### Fixed
- Try resolving `config.default` before `config` to ensure the config file is resolved correctly ([#10898](https://github.com/tailwindlabs/tailwindcss/pull/10898))
@@ -2217,7 +2221,8 @@ No release notes
- Everything!
-[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.0...HEAD
+[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.1...HEAD
+[3.3.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.0...v3.3.1
[3.3.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.7...v3.3.0
[3.2.7]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.6...v3.2.7
[3.2.6]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.5...v3.2.6
diff --git a/package-lock.json b/package-lock.json
index ed1615e6b1a1..10608712006b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "tailwindcss",
- "version": "3.3.0",
+ "version": "3.3.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "tailwindcss",
- "version": "3.3.0",
+ "version": "3.3.1",
"license": "MIT",
"workspaces": [
"integrations/*",
diff --git a/package-lock.stable.json b/package-lock.stable.json
index 1c419c1855ac..4fda6babf23b 100644
--- a/package-lock.stable.json
+++ b/package-lock.stable.json
@@ -1,12 +1,12 @@
{
"name": "tailwindcss",
- "version": "3.3.0",
+ "version": "3.3.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "tailwindcss",
- "version": "3.3.0",
+ "version": "3.3.1",
"license": "MIT",
"dependencies": {
"arg": "^5.0.2",
diff --git a/package.json b/package.json
index e2093e183061..6a240fd5c697 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "tailwindcss",
- "version": "3.3.0",
+ "version": "3.3.1",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.",
"license": "MIT",
"main": "lib/index.js",
diff --git a/package.stable.json b/package.stable.json
index 26cca2eea1f4..f758ded10e78 100644
--- a/package.stable.json
+++ b/package.stable.json
@@ -1,6 +1,6 @@
{
"name": "tailwindcss",
- "version": "3.3.0",
+ "version": "3.3.1",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.",
"license": "MIT",
"main": "lib/index.js",