Fall back to the plugin base when PostCSS has no from option (#19980)
## Summary
`@tailwindcss/postcss` derives `inputBasePath` from `result.opts.from`:
```ts
let inputFile = result.opts.from ?? ''
let inputBasePath = path.dirname(path.resolve(inputFile))
```
When PostCSS calls the plugin without `from` (some bundlers, including
Turbopack, do this for certain CSS inputs), `inputFile` is `''`,
`path.resolve('')` returns `process.cwd()`, and `path.dirname(...)`
therefore returns the **parent of CWD**. The downstream `compileAst({
base: inputBasePath })` call then asks the resolver to find
`tailwindcss` from one level above the project root, which fails with:
```
Can't resolve 'tailwindcss' in '<parent of CWD>'
```
The plugin already computes `base = opts.base ?? process.cwd()` near the
top. Reusing that as the fallback gives a sensible default (CWD) and
respects an explicit `opts.base` when set.
```diff
-let inputBasePath = path.dirname(path.resolve(inputFile))
+let inputBasePath = inputFile
+ ? path.dirname(path.resolve(inputFile))
+ : base
```
## Test plan
Added a test in `packages/@tailwindcss-postcss/src/index.test.ts` that
processes `@import 'tailwindcss'` via `processor.process(input)` with no
`from` option. Before the fix, this throws `Error: Can't resolve
'tailwindcss' in '<parent of CWD>'`; after the fix, the import resolves
and the processor returns non-empty CSS.
I wasn't able to run the suite locally — `pnpm build` requires `cargo`
for `@tailwindcss/oxide` and I don't have a Rust toolchain set up — so
the test has been written to match existing conventions in
`index.test.ts` (vitest, plain
`postcss([tailwindcss({...})]).process(...)`), and I'm relying on CI to
verify.
---------
Co-authored-by: rebasecase <rebasecase@localhost>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This commit is contained in:
parent
3a890c3572
commit
bfb5732b0b
3 changed files with 12 additions and 1 deletions
|
|
@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Ensure `@plugin` resolves package JavaScript entries instead of browser CSS entries when using `@tailwindcss/vite` ([#19949](https://github.com/tailwindlabs/tailwindcss/pull/19949))
|
||||
- Fix relative `@import` and `@plugin` paths resolving from the wrong directory when using `@tailwindcss/vite` ([#19965](https://github.com/tailwindlabs/tailwindcss/pull/19965))
|
||||
- Ensure CSS files containing `@variant` are processed by `@tailwindcss/vite` ([#19966](https://github.com/tailwindlabs/tailwindcss/pull/19966))
|
||||
- Resolve imports relative to `base` when `result.opts.from` is not provided when using `@tailwindcss/postcss` ([#19980](https://github.com/tailwindlabs/tailwindcss/pull/19980))
|
||||
|
||||
## [4.2.4] - 2026-04-21
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,16 @@ describe('processing without specifying a base path', () => {
|
|||
})
|
||||
})
|
||||
|
||||
test('fallback to `base` directory when `result.opts.from` is not provided', async () => {
|
||||
let processor = postcss([
|
||||
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
|
||||
])
|
||||
|
||||
let result = await processor.process(`@import 'tailwindcss'`)
|
||||
|
||||
expect(result.css.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
describe('plugins', () => {
|
||||
test('local CJS plugin', async () => {
|
||||
let processor = postcss([
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
|
|||
}
|
||||
|
||||
let context = getContextFromCache(postcss, inputFile, opts)
|
||||
let inputBasePath = path.dirname(path.resolve(inputFile))
|
||||
let inputBasePath = inputFile ? path.dirname(path.resolve(inputFile)) : base
|
||||
|
||||
// Whether this is the first build or not, if it is, then we can
|
||||
// optimize the build by not creating the compiler until we need it.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue