Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw a useful error when tailwindcss is used as a PostCSS plugin #14378

Merged
merged 9 commits into from
Sep 11, 2024
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Properly resolve `theme('someKey.DEFAULT')` when all `--some-key-*` keys have a suffix ([#14354](https://github.com/tailwindlabs/tailwindcss/pull/14354))
- Make sure tuple theme values in JS configs take precedence over `@theme default` values ([#14359](https://github.com/tailwindlabs/tailwindcss/pull/14359))

### Changed

- Improve the error message when the `tailwindcss` package is used as a PostCSS plugin ([#14378](https://github.com/tailwindlabs/tailwindcss/pull/14378))

## [4.0.0-alpha.23] - 2024-09-05

### Added
Expand Down
59 changes: 59 additions & 0 deletions integrations/postcss/core-as-postcss-plugin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { expect } from 'vitest'
import { css, js, json, test } from '../utils'

const variantConfig = {
string: {
'postcss.config.js': js`
module.exports = {
plugins: {
tailwindcss: {},
},
}
`,
},
ESM: {
'postcss.config.mjs': js`
import tailwindcss from 'tailwindcss'
export default {
plugins: [tailwindcss()],
}
`,
},
CJS: {
'postcss.config.cjs': js`
let tailwindcss = require('tailwindcss')
module.exports = {
plugins: [tailwindcss()],
}
`,
},
}

for (let variant of Object.keys(variantConfig)) {
test(
`can not use \`tailwindcss\` as a postcss module (${variant})`,
{
fs: {
...variantConfig[variant],
'package.json': json`
{
"dependencies": {
"postcss": "^8",
"postcss-cli": "^10",
"tailwindcss": "workspace:^"
}
}
`,
'src/index.css': css`@import 'tailwindcss';`,
},
},
async ({ exec }) => {
expect(
exec('pnpm postcss src/index.css --output dist/out.css', undefined, { ignoreStdErr: true }),
).rejects
.toThrowError(`It looks like you're trying to use the \`tailwindcss\` package as a PostCSS plugin. This is no longer possible since Tailwind CSS v4.

If you want to continue to use Tailwind CSS with PostCSS, please install \`@tailwindcss/postcss\` and change your PostCSS config file.`)
},
)
}
14 changes: 11 additions & 3 deletions integrations/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ interface ChildProcessOptions {
cwd?: string
}

interface ExecOptions {
ignoreStdErr?: boolean
}

interface TestConfig {
fs: {
[filePath: string]: string
}
}
interface TestContext {
root: string
exec(command: string, options?: ChildProcessOptions): Promise<string>
exec(command: string, options?: ChildProcessOptions, execOptions?: ExecOptions): Promise<string>
spawn(command: string, options?: ChildProcessOptions): Promise<SpawnedProcess>
getFreePort(): Promise<number>
fs: {
Expand Down Expand Up @@ -84,7 +88,11 @@ export function test(

let context = {
root,
async exec(command: string, childProcessOptions: ChildProcessOptions = {}) {
async exec(
command: string,
childProcessOptions: ChildProcessOptions = {},
execOptions: ExecOptions = {},
) {
let cwd = childProcessOptions.cwd ?? root
if (debug && cwd !== root) {
let relative = path.relative(root, cwd)
Expand All @@ -101,7 +109,7 @@ export function test(
},
(error, stdout, stderr) => {
if (error) {
console.error(stderr)
if (execOptions.ignoreStdErr !== true) console.error(stderr)
reject(error)
} else {
resolve(stdout.toString())
Expand Down
4 changes: 4 additions & 0 deletions packages/tailwindcss/src/compat/colors.cts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import colors from './colors.ts'

// This file exists so that `colors.ts` can be written one time but be
// compatible with both CJS and ESM. Without it we get a `.default` export when
// using `require` in CJS.

// @ts-ignore
export = colors
4 changes: 4 additions & 0 deletions packages/tailwindcss/src/compat/default-theme.cts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import defaultTheme from './default-theme.ts'

// This file exists so that `default-theme.ts` can be written one time but be
// compatible with both CJS and ESM. Without it we get a `.default` export when
// using `require` in CJS.

// @ts-ignore
export = defaultTheme
14 changes: 14 additions & 0 deletions packages/tailwindcss/src/index.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import postcssPlugin, * as tailwindcss from './index.ts'

// This file exists so that `index.ts` can be written one time but be
// compatible with both CJS and ESM. Without it we get a `.default` export when
// using `require` in CJS.

for (let key in tailwindcss) {
if (key === 'default') continue
// @ts-ignore
postcssPlugin[key] = tailwindcss[key]
}

// @ts-ignore
export = postcssPlugin
6 changes: 6 additions & 0 deletions packages/tailwindcss/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,9 @@ function getVersion() {
return version
}
}

export default function postcssPluginWarning() {
throw new Error(`It looks like you're trying to use the \`tailwindcss\` package as a PostCSS plugin. This is no longer possible since Tailwind CSS v4.

If you want to continue to use Tailwind CSS with PostCSS, please install \`@tailwindcss/postcss\` and change your PostCSS config file.`)
philipp-spiess marked this conversation as resolved.
Show resolved Hide resolved
}
10 changes: 2 additions & 8 deletions packages/tailwindcss/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import { defineConfig } from 'tsup'

export default defineConfig([
{
format: ['esm', 'cjs'],
minify: true,
dts: true,
entry: {
lib: 'src/index.ts',
},
},
{
format: ['esm'],
minify: true,
dts: true,
entry: {
lib: 'src/index.ts',
plugin: 'src/plugin.ts',
colors: 'src/compat/colors.ts',
'default-theme': 'src/compat/default-theme.ts',
Expand All @@ -25,6 +18,7 @@ export default defineConfig([
dts: true,
entry: {
plugin: 'src/plugin.cts',
lib: 'src/index.cts',
colors: 'src/compat/colors.cts',
'default-theme': 'src/compat/default-theme.cts',
},
Expand Down