tailwindcss/packages/@tailwindcss-postcss
Robin Malfait 4255671c5f
Improve snapshot tests (#20013)
This PR improves the snapshot tests. At first, this looks like a very
silly PR, but I swear I have legit reasons for these changes:

First, there are a few places where we use `.toMatchInlineSnapshot()`
for tests where we expect that nothing is being generated. This is fine,
but the issue is that this means that if you're not careful, and if we
have a bug, then these snapshots could start producing something.
Updating these snapshots is _too_ easy. So instead, we convert them to
an explicit `.toEqual('')`

Next, I introduced a `pretty` helper function which is used behind the
scenes in the `compileCss(…)`, `run(…)`, and `optimizeCss(…)` test
helpers. It's very silly and simple, it either returns `''` when the
trimmed input is empty, or it will wrap the result in `\n…\n`. The
reason for this is because of how (inline) snapshots works in Vitest. A
snapshot result will be in double quotes, and inside backticks:
```ts
expect(result.css.trim()).toMatchInlineSnapshot(`
  "@layer utilities {
    .foo {
      color: #000;
    }

    .bar {
      color: red;
    }
  }"
`)
```
This CSS now starts with `"` and ends with `"`. While that is fine, it
starts to get annoying when we have merge conflicts when CSS changes
(this is what triggered me to make this PR because I ran into this a
dozen times already). Because the first and last CSS line also contain a
`"` that you have to keep into account.

Instead we now use `\n` around the output, which makes the tests look
like this:
```ts
expect(pretty(result.css)).toMatchInlineSnapshot(`
  "
  @layer utilities {
    .foo {
      color: #000;
    }

    .bar {
      color: red;
    }
  }
  "
`)
```

In a perfect world, I wish we could use something like:
```css
expect(pretty(result.css)).toMatchInlineSnapshot(css`
  @layer utilities {
    .foo {
      color: #000;
    }

    .bar {
      color: red;
    }
  }
`)
```

That way you are only dealing with CSS, nothing else. Most editors will
show syntax highlighting, and even prettier will do formatting on the
CSS to keep everything consistent.

Unfortunately this also causes issues because when prettier formats
this, then the input/output will not always match. We can solve that by
parsing both sides and compare the ASTs but that would make things
slower.

The biggest issue is that Vitest doesn't support this. You can use
custom serializers
https://vitest.dev/guide/snapshot.html#custom-snapshot-matchers and
domains https://vitest.dev/guide/snapshot.html#custom-snapshot-domain
but this has an annoying issue around escaping values.

When you use `css` it's typically implemented as `const css =
String.raw`, which means that you can write actual CSS instead of JS:
```ts
let input = css`
  .\[color:red\] {
    color: red;
  }
`
```

But vitest would double scape the `\`, which would make the snapshot
test fail:
```ts
let input = css`
  .\\[color:red\\] {
    color: red;
  }
`
```

**Edit**: It is possible with a custom snapshot environment! But this
still introduces some levels of indirection. We are also not really
testing the same thing anymore. Prettier will be formatting the CSS, we
rely on our own CSS parser / printer, which is fine but subtle bugs
could maybe be invisible or maybe it unlocks some hidden bugs, who
knows. Funnily enough, running tests with this new matcher also goes
from `23.60s` to `22.88s` (just 1 run comparison).
<img width="1227" height="897" alt="image"
src="https://github.com/user-attachments/assets/698a0c67-a1fc-46e3-ba5a-60e5873b32df"
/>

Long story short, simple `\n` and `\n` boundaries it is!

## Test plan

- Everything still works as expected.
- There are visual changes in tests, but no actual source code was
updated either so there can not be an accidental diff
2026-05-05 22:24:25 +02:00
..
src Improve snapshot tests (#20013) 2026-05-05 22:24:25 +02:00
package.json Bump dependencies (#19957) 2026-04-24 21:21:12 +02:00
README.md Fix issue around resolving paths in @tailwindcss/vite (#19947) 2026-04-21 14:11:46 +02:00
tsconfig.json Bump dependencies (#19957) 2026-04-24 21:21:12 +02:00
tsup.config.ts Resolve @import in core (#14446) 2024-09-23 17:05:55 +02:00

Tailwind CSS

A utility-first CSS framework for rapidly building custom user interfaces.

Build Status Total Downloads Latest Release License


Documentation

For full documentation, visit tailwindcss.com.

Community

For help, discussion about best practices, or feature ideas:

Discuss Tailwind CSS on GitHub

Contributing

If you're interested in contributing to Tailwind CSS, please read our contributing docs before submitting a pull request.


@tailwindcss/postcss plugin API

Changing where the plugin searches for source files

You can use the base option (defaults to the current working directory) to change the directory in which the plugin searches for source files:

import tailwindcss from '@tailwindcss/postcss'

export default {
  plugins: [
    tailwindcss({
      base: path.resolve(__dirname, './path'),
    }),
  ],
}

Enabling or disabling Lightning CSS

By default, this plugin detects whether or not the CSS is being built for production by checking the NODE_ENV environment variable. When building for production Lightning CSS will be enabled otherwise it is disabled.

If you want to always enable or disable Lightning CSS the optimize option may be used:

import tailwindcss from '@tailwindcss/postcss'

export default {
  plugins: [
    tailwindcss({
      // Enable or disable Lightning CSS
      optimize: false,
    }),
  ],
}

It's also possible to keep Lightning CSS enabled but disable minification:

import tailwindcss from '@tailwindcss/postcss'

export default {
  plugins: [
    tailwindcss({
      optimize: { minify: false },
    }),
  ],
}

Enabling or disabling url(…) rewriting

Our PostCSS plugin can rewrite url(…)s for you since it also handles @import (no postcss-import is needed). This feature is enabled by default.

In some situations the bundler or framework you're using may provide this feature itself. In this case you can set transformAssetUrls to false to disable this feature:

import tailwindcss from '@tailwindcss/postcss'

export default {
  plugins: [
    tailwindcss({
      // Disable `url(…)` rewriting
      transformAssetUrls: false,

      // Enable `url(…)` rewriting (the default)
      transformAssetUrls: true,
    }),
  ],
}