diff --git a/CHANGELOG.md b/CHANGELOG.md index 571cec88d..ec1c7ff37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Make sure tuple theme values in JS configs take precedence over `@theme default` values ([#14359](https://github.com/tailwindlabs/tailwindcss/pull/14359)) - Improve IntelliSense completions for `border` utilities ([#14370](https://github.com/tailwindlabs/tailwindcss/pull/14370)) +### 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 diff --git a/integrations/postcss/core-as-postcss-plugin.test.ts b/integrations/postcss/core-as-postcss-plugin.test.ts new file mode 100644 index 000000000..85779e7b2 --- /dev/null +++ b/integrations/postcss/core-as-postcss-plugin.test.ts @@ -0,0 +1,58 @@ +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 \`tailwindcss\` directly as a PostCSS plugin. The PostCSS plugin has moved to a separate package, so to continue using Tailwind CSS with PostCSS you'll need to install \`@tailwindcss/postcss\` and update your PostCSS configuration.`, + ) + }, + ) +} diff --git a/integrations/utils.ts b/integrations/utils.ts index e5f550c05..7530321d0 100644 --- a/integrations/utils.ts +++ b/integrations/utils.ts @@ -23,6 +23,10 @@ interface ChildProcessOptions { cwd?: string } +interface ExecOptions { + ignoreStdErr?: boolean +} + interface TestConfig { fs: { [filePath: string]: string @@ -30,7 +34,7 @@ interface TestConfig { } interface TestContext { root: string - exec(command: string, options?: ChildProcessOptions): Promise + exec(command: string, options?: ChildProcessOptions, execOptions?: ExecOptions): Promise spawn(command: string, options?: ChildProcessOptions): Promise getFreePort(): Promise fs: { @@ -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) @@ -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()) diff --git a/packages/tailwindcss/src/compat/colors.cts b/packages/tailwindcss/src/compat/colors.cts index b903bf39b..92cd2f66b 100644 --- a/packages/tailwindcss/src/compat/colors.cts +++ b/packages/tailwindcss/src/compat/colors.cts @@ -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 diff --git a/packages/tailwindcss/src/compat/default-theme.cts b/packages/tailwindcss/src/compat/default-theme.cts index 235d60252..aab00f357 100644 --- a/packages/tailwindcss/src/compat/default-theme.cts +++ b/packages/tailwindcss/src/compat/default-theme.cts @@ -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 diff --git a/packages/tailwindcss/src/index.cts b/packages/tailwindcss/src/index.cts new file mode 100644 index 000000000..fc4b691f9 --- /dev/null +++ b/packages/tailwindcss/src/index.cts @@ -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 diff --git a/packages/tailwindcss/src/index.ts b/packages/tailwindcss/src/index.ts index c3cd9e70c..277ef12ff 100644 --- a/packages/tailwindcss/src/index.ts +++ b/packages/tailwindcss/src/index.ts @@ -498,3 +498,9 @@ function getVersion() { return version } } + +export default function postcssPluginWarning() { + throw new Error( + `It looks like you're trying to use \`tailwindcss\` directly as a PostCSS plugin. The PostCSS plugin has moved to a separate package, so to continue using Tailwind CSS with PostCSS you'll need to install \`@tailwindcss/postcss\` and update your PostCSS configuration.`, + ) +} diff --git a/packages/tailwindcss/tsup.config.ts b/packages/tailwindcss/tsup.config.ts index 25803da45..1a8e23887 100644 --- a/packages/tailwindcss/tsup.config.ts +++ b/packages/tailwindcss/tsup.config.ts @@ -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', @@ -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', },