Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Add `@tailwindcss/turbopack` package to run Tailwind CSS with Next.js ([20367](https://github.com/tailwindlabs/tailwindcss/pull/20367))
- Enhance TypeScript `PluginOptions` types with JSDoc documentation, default tags, and examples for `@tailwindcss/vite` and `@tailwindcss/postcss`

### Fixed

Expand Down
40 changes: 38 additions & 2 deletions packages/@tailwindcss-postcss/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,54 @@ export type PluginOptions = {
/**
* The base directory to scan for class candidates.
*
* Defaults to the current working directory.
* @default process.cwd()
*
* @example
* ```js
* export default {
* plugins: {
* '@tailwindcss/postcss': {
* base: './src',
* },
* },
* }
* ```
*/
base?: string

/**
* Optimize and minify the output CSS.
*
* @default true in production, false in development
*
* @example
* ```js
* export default {
* plugins: {
* '@tailwindcss/postcss': {
* optimize: { minify: true },
* },
* },
* }
* ```
*/
optimize?: boolean | { minify?: boolean }

/**
* Enable or disable asset URL rewriting.
*
* Defaults to `true`.
* @default true
*
* @example
* ```js
* export default {
* plugins: {
* '@tailwindcss/postcss': {
* transformAssetUrls: false,
* },
* },
* }
* ```
*/
transformAssetUrls?: boolean
}
Expand Down Expand Up @@ -375,3 +410,4 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
}

export default Object.assign(tailwindcss, { postcss: true }) as PluginCreator<PluginOptions>
export { tailwindcss }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Named export missing in CommonJS

In a CommonJS TypeScript project, import { tailwindcss } from '@tailwindcss/postcss' uses the package’s separate require entry. That entry exports only the function, not a tailwindcss property, so the new named import fails type-checking or resolves to undefined when required. The CommonJS entry needs to expose it too.

Knowledge Base Used: PostCSS plugin

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Named export loses creator type

The named and default exports refer to the same function at runtime, but only the default is typed as PluginCreator<PluginOptions>. The named export keeps the narrower function type, without the postcss: true marker, so TypeScript users cannot use it interchangeably with the default when registering a PostCSS plugin creator directly. Give both exports the same type.

Knowledge Base Used: PostCSS plugin

Comment on lines 412 to +413

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

cat packages/@tailwindcss-postcss/src/index.cts
cat packages/@tailwindcss-postcss/package.json
rg -n 'require\\(|from .@tailwindcss/postcss.|tailwindcss.*export|named export|export =|export \\{ tailwindcss' packages/@tailwindcss-postcss packages --glob '*.{ts,tsx,cts,mts,js,md,json}'

Repository: tailwindlabs/tailwindcss

Length of output: 1943


🏁 Script executed:

set -o pipefail
printf '%s\n' '--- PostCSS package files ---'
git ls-files packages/@tailwindcss-postcss
printf '%s\n' '--- PostCSS references and export expectations ---'
rg -n -F -e '@tailwindcss/postcss' -e 'tailwindcss' -e 'export =' -e 'export { tailwindcss }' packages/@tailwindcss-postcss packages --glob '*.{ts,tsx,cts,mts,js,md,json}' | head -240
printf '%s\n' '--- package entry patterns ---'
rg -n -F -e '"require"' -e '"import"' -e 'export =' packages --glob 'package.json' --glob '*.cts' --glob '*.ts' | head -240

Repository: tailwindlabs/tailwindcss

Length of output: 34233


🏁 Script executed:

set -o pipefail
printf '%s\n' '--- PostCSS README API examples ---'
sed -n '40,115p' packages/@tailwindcss-postcss/README.md
printf '%s\n' '--- PostCSS test imports and entry usage ---'
sed -n '1,30p' packages/@tailwindcss-postcss/src/index.test.ts
printf '%s\n' '--- PostCSS source export area ---'
sed -n '100,116p' packages/@tailwindcss-postcss/src/index.ts
sed -n '406,416p' packages/@tailwindcss-postcss/src/index.ts
printf '%s\n' '--- analogous core package exports ---'
sed -n '1,35p' packages/tailwindcss/src/index.ts
sed -n '1,22p' packages/tailwindcss/src/index.cts
sed -n '15,60p' packages/tailwindcss/package.json
printf '%s\n' '--- analogous plugin exports ---'
cat packages/tailwindcss/src/plugin.ts
cat packages/tailwindcss/src/plugin.cts

Repository: tailwindlabs/tailwindcss

Length of output: 8376


🏁 Script executed:

set -o pipefail
printf '%s\n' '--- exact PR diff ---'
git diff --unified=8 fa81d697fe572a10ac150d18964a093a7a874081 823d99541b313d90ad59ae0f5a13a010753885fc -- packages/@tailwindcss-postcss/src/index.ts packages/@tailwindcss-postcss/src/index.cts packages/@tailwindcss-postcss/package.json
printf '%s\n' '--- core ESM exports and CJS bridge ---'
rg -n -F -e 'export default' -e 'export {' -e 'for (let key in tailwindcss)' -e 'postcssPlugin[key]' packages/tailwindcss/src/index.ts packages/tailwindcss/src/index.cts
sed -n '1,28p' packages/tailwindcss/src/index.cts

Repository: tailwindlabs/tailwindcss

Length of output: 2810


Preserve the named export in the CommonJS entry.

src/index.ts now exports tailwindcss, but src/index.cts imports only the default and exposes it with export =. Therefore, require('@tailwindcss/postcss').tailwindcss is unavailable at runtime and in the CommonJS declaration. Copy the named exports as the core package does.

Suggested fix
-import tailwindcss from './index.ts'
+import postcssPlugin, * as tailwindcss from './index.ts'

 // This is used instead of `export default` to work around a bug in
 // `postcss-load-config`

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

18 changes: 18 additions & 0 deletions packages/@tailwindcss-vite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,21 @@ export default defineConfig({
],
})
```

### TypeScript Usage

When configuring Vite in TypeScript, `@tailwindcss/vite` provides both default and named exports, along with the `PluginOptions` type definition:

```ts
import tailwindcss, { type PluginOptions } from '@tailwindcss/vite'
import { defineConfig } from 'vite'

const options: PluginOptions = {
optimize: { minify: true },
}

export default defineConfig({
plugins: [tailwindcss(options)],
})
```

18 changes: 18 additions & 0 deletions packages/@tailwindcss-vite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ const INLINE_STYLE_ID_RE = /[?&]index=\d+\.css$/
export type PluginOptions = {
/**
* Optimize and minify the output CSS.
*
* @default true in production build, false in development
*
* @example
* ```ts
* import tailwindcss from '@tailwindcss/vite'
* import { defineConfig } from 'vite'
*
* export default defineConfig({
* plugins: [
* tailwindcss({
* optimize: { minify: true },
* }),
* ],
* })
* ```
Comment on lines +25 to +40

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

rg -n 'shouldOptimize|optimize\\(|generateBundle|transform\\(|apply:|command|NODE_ENV|cssMinify' packages/@tailwindcss-vite/src/index.ts
sed -n '70,115p' packages/@tailwindcss-vite/src/index.ts
sed -n '175,225p' packages/@tailwindcss-vite/src/index.ts
sed -n '260,315p' packages/@tailwindcss-vite/src/index.ts

Repository: tailwindlabs/tailwindcss

Length of output: 4959


Clarify the development default

The apply: 'serve' hook does not call optimize, but the apply: 'build' hook does. Since shouldOptimize remains true unless opts.optimize is set, a development-mode Vite build still optimizes CSS. The documentation should distinguish the development server from a development-mode build. The minify option controls minification separately.

Suggested fix
- * @default true in production build, false in development
+ * @default true during Vite builds, and false in the Vite development server
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
*
* @default true in production build, false in development
*
* @example
* ```ts
* import tailwindcss from '@tailwindcss/vite'
* import { defineConfig } from 'vite'
*
* export default defineConfig({
* plugins: [
* tailwindcss({
* optimize: { minify: true },
* }),
* ],
* })
* ```
*
* @default true during Vite builds, and false in the Vite development server
*
* @example
* ```ts
* import tailwindcss from '@tailwindcss/vite'
* import { defineConfig } from 'vite'
*
* export default defineConfig({
* plugins: [
* tailwindcss({
* optimize: { minify: true },
* }),
* ],
* })
* ```

*/
optimize?: boolean | { minify?: boolean }
}
Expand Down Expand Up @@ -541,3 +557,5 @@ class Root {
return false
}
}

export { tailwindcss }