Commit graph

6767 commits

Author SHA1 Message Date
Robin Malfait
6b0eb5193e
Ensure @source globs ending in **/* preserve dynamic path segments to avoid scanning too many files (#20217)
This PR fixes an issue where we were over-scanning because we lost
pattern information when a `@source` ended in `**/*` and contained other
dynamic parts in the glob pattern.

Noticed this while debugging and working on #20214. Let's say you have
the following:
```css
@source './blog/*/foo/bar/baz/**/*';
```

We make sure that folders or patterns ending in `**/*` are converted to
"auto sources", meaning that auto content detection should be used in
these folders.

However, when doing so, we would only take the `base` path of the glob.
And since we have "dynamic" parts (the `*`) in the pattern, that should
not be the case.

So the `@source` from above, would be turned into:
```rs
SourceEntry::Auto { base = "/Users/projects/project/blog" }
```

Notice that we lose all the information related to `/*/foo/bar/baz/`.
While this would technically still work, it also means that we are
scanning **too many files and folders** because we're only interested in
folders in the `blog` folder that also contain `foo/bar/baz`.

If the `*` wasn't there, then this would be correct, because then we
would've moved the `/blog/foo/bar/baz` part to the `base` ahead of time,
and the pattern would just be `/**/*`. That would result in:
```rs
SourceEntry::Auto { base = "/Users/projects/project/blog/foo/bar/baz" }
```

This PR fixes that, by _not_ converting it to an auto-source, and
instead convert it to a pattern:
```rs
SourceEntry::Pattern {
  base: "/Users/projects/project/blog",
  pattern: "/*/foo/bar/baz/**/*"
}
```

Notice that the static part `blog` is still moved to the base path. But
the rest stays in the `pattern` part as expected.

## Test plan

1. Added a failing test to make sure this doesn't happen anymore
2. Existing tests pass 
3. Tested this on the tailwindcss.com codebase using `@source
"../blog/tailwindcss*/**/*";`

```diff
 diff --git a/./tailwindcss-55526.log b/./tailwindcss-55527.log
index ce79c5da..03e97598 100644
--- a/./tailwindcss-55526.log
+++ b/./tailwindcss-55527.log
@@ -2,50 +2,9 @@ INFO tailwindcss_oxide::scanner: Provided sources:
 INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/app", pattern: "../blog/tailwindcss*/**/*", negated: false }
 INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin/.bun/bin", pattern: "bun", negated: true }
 INFO tailwindcss_oxide::scanner: Optimized sources:
-INFO tailwindcss_oxide::scanner: Source: Auto { base: "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog" }
+INFO tailwindcss_oxide::scanner: Source: Pattern { base: "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog", pattern: "/tailwindcss*/**/*" }
 INFO tailwindcss_oxide::scanner: Source: Ignored { base: "/Users/robin/.bun/bin", pattern: "/bun" }
 INFO discover_sources: tailwindcss_oxide::scanner: enter
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-05-23-headless-ui-v1-6-tailwind-ui-team-management/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-06-23-tailwind-templates-and-all-access/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-08-17-tailwind-framer-motion-template-and-tailwind-jobs/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-09-09-new-personal-website-heroicons-2-headless-ui-v17/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-12-15-protocol-api-documentation-template/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2023-04-24-new-changelog-template-and-the-biggest-tailwind-ui-update-ever/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2023-07-18-tailwind-connect-2023-recap/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2023-08-07-meet-studio-our-new-agency-template/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2024-05-24-catalyst-application-layouts/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2024-05-30-prettier-plugin-collapse-whitespace/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2024-06-21-headless-ui-v2-1/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2024-09-12-radiant-a-beautiful-new-marketing-site-template/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2025-05-14-compass-course-starter-kit/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/automatic-class-sorting-with-prettier/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/building-react-and-vue-support-for-tailwind-ui/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/building-the-tailwind-blog/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/designing-tailwind-ui-ecommerce/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/from-900-to-1-how-we-hired-robin-malfait/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-unstyled-accessible-ui-components/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v1-4/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v1-5/demo.tsx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v1-5/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v1/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v2/examples/HeadlessUIV2Examples.tsx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v2/examples/StateAttributesExample.tsx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v2/examples/anchor-positioning.tsx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v2/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/heroicons-micro/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/heroicons-v1/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/hiring-a-design-engineer-and-staff-engineer/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/introducing-catalyst/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/introducing-heroicons/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/introducing-linting-for-tailwindcss-intellisense/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/introducing-tailwind-play/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/just-in-time-the-next-generation-of-tailwind-css/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/multi-line-truncation-with-tailwindcss-line-clamp/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/simon-vrachliotis-joins-tailwind-labs/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/standalone-cli/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwind-plus/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwind-ui-ecommerce/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwind-ui-now-with-react-and-vue-support/index.mdx"
 INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-1-5/index.mdx"
 INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-1-6/index.mdx"
 INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-1-7/index.mdx"
@@ -68,10 +27,4 @@ INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/t
 INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-v4-beta/index.mdx"
 INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-v4/color-palette.tsx"
 INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-v4/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/utility-friendly-transitions-with-tailwindui-react/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/vanilla-js-support-for-tailwind-plus/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/welcoming-brad-cornes-to-the-tailwind-team/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/welcoming-david-luhr-to-tailwind-labs/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/welcoming-james-mcdonald-to-tailwind-labs/index.mdx"
-INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/whats-new-in-tailwindcss-on-youtube/index.mdx"
 INFO discover_sources: tailwindcss_oxide::scanner: exit
```

Notice now that a lot of files are skipped as expected since we-re not
accidentally over-scanning now.

[ci-all]
2026-06-11 11:59:58 +02:00
Robin Malfait
1bf4291e85
Fix @source with folders that are ignored (#20214)
This PR fixes an issue where a `@source` that's pointing to a folder
that is git ignored, is also ignored by the `@source` even if it's
explicitly added.

Internally, we convert `@source` directives from `PublicSourceEntry`s to
`SourceEntry`s where we have dedicated enum branches for `Auto`,
`Pattern`, `Ignored` and `External`.

The `Auto` one accepts a `base` path, and will be used for auto content
detection. However, these paths will make use of all the default auto
content detection rules, which includes git ignore rules.
We also have `External` where we link to something that's "external" to
the current repo. We can probably improve this name, but it's external
in the sense that it won't show up on GitHub for example, aka ignored.
We have some content dirs that we ignore by default, such as the
`node_modules` folder. When you do use `@source` with `node_modules` in
the path, then we will mark it as an `external` resource which does not
look at the `gitignore` related rules and allowing it to be included
this way.

The idea with this is that, even though the folder is ignored by
default, you can still include files from the folder by explicitly using
the `@source` directive.

The issue as seen in #19844 is using `vendor/` instead of
`node_modules/` which is _not_ ignored by default. While we can add
`vendor/` to this same ignored dirs list, it will result in a breaking
change because this folder is often used by the Laravel community to
store some resources in.

This PR fixes this problem by not only looking at the content dirs we
ignore by default, but also looking at the actual git ignore state of
this folder. If it turns out that this is ignored, then we promote the
`Auto` source to an `External` source.

Fixes: #19844
Closes: #20057


## Test plan

1. Added integration tests for this situation
2. Ran the fix on the reproduction from #19844. If we run the CLI with
the `DEBUG=*` environment variable, the log file produces these results:

```diff
diff --git a/./tailwindcss-29207.log b/./tailwindcss-30381.log
index bc3017c..921af0e 100644
--- a/./tailwindcss-29207.log
+++ b/./tailwindcss-30381.log
@@ -6,8 +6,9 @@ INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin
 INFO tailwindcss_oxide::scanner: Optimized sources:
 INFO tailwindcss_oxide::scanner: Source: Pattern { base: "/Users/robin/github.com/GrimLink/tailwind-gitignore-bug/app/design/frontend/theme", pattern: "/**/*.phtml" }
 INFO tailwindcss_oxide::scanner: Source: Pattern { base: "/Users/robin/github.com/GrimLink/tailwind-gitignore-bug/app/design/frontend/theme", pattern: "/**/*.xml" }
-INFO tailwindcss_oxide::scanner: Source: Auto { base: "/Users/robin/github.com/GrimLink/tailwind-gitignore-bug/vendor/acme/theme" }
+INFO tailwindcss_oxide::scanner: Source: External { base: "/Users/robin/github.com/GrimLink/tailwind-gitignore-bug/vendor/acme/theme" }
 INFO tailwindcss_oxide::scanner: Source: Ignored { base: "/Users/robin/.fnm/node-versions/v26.1.0/installation/bin", pattern: "/node" }
 INFO discover_sources: tailwindcss_oxide::scanner: enter
-INFO discover_sources: tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/GrimLink/tailwind-gitignore-bug/app/design/frontend/theme/index.phtml"
+INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/GrimLink/tailwind-gitignore-bug/app/design/frontend/theme/index.phtml"
+INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/GrimLink/tailwind-gitignore-bug/vendor/acme/theme/module/templates/component.phtml"
 INFO discover_sources: tailwindcss_oxide::scanner: exit
```

We're checking some `.gitignore` related files, so let's check on each
OS [ci-all]
2026-06-10 18:44:14 +02:00
depfu[bot]
1d5e15e9d8
Update all of react 19.2.6 → 19.2.7 (patch) (#20206)
<!--depfu-start-->
> 👉 **This PR is queued up to get rebased by Depfu**
<!--depfu-end-->





Here is everything you need to know about this upgrade. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ react (19.2.6 → 19.2.7) ·
[Repo](https://github.com/facebook/react) ·
[Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/facebook/react/releases/tag/v19.2.7">19.2.7</a></h4>

<blockquote><h2 dir="auto">React Server Components</h2>
<ul dir="auto">
<li>Fixed missing <code class="notranslate">FormData</code> entries in
Server Actions which regressed in 19.2.6<br>
(<a
href="https://bounce.depfu.com/github.com/facebook/react/pull/36566">#36566</a>
by <a
href="https://bounce.depfu.com/github.com/unstubbable">@unstubbable</a>)</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please let us
know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="eaf3e95ca9...6117d7cca4">See
the full diff on Github</a>. The new version differs by 5 commits:</p>
<ul>
<li><a
href="6117d7cca4"><code>Version
19.2.7 (#36591)</code></a></li>
<li><a
href="53a07de1a7"><code>[19.2.x]
Unified release process (#36550)</code></a></li>
<li><a
href="02c444c3f0"><code>[19.2.x][FlightReply]
Don&#39;t drop FormData entries in `decodeReplyFromBusboy`
(#36566)</code></a></li>
<li><a
href="750848e565"><code>[19.2.x][ci]
Create artifact attestations for builds on backport branches
(#36559)</code></a></li>
<li><a
href="e1cfa7b6de"><code>[19.2.x]
Enable CI (#36552)</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-06-09 10:44:01 +00:00
depfu[bot]
e7d64e7648
Update next 16.2.6 → 16.2.7 (patch) (#20207)
Here is everything you need to know about this upgrade. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ next (16.2.6 → 16.2.7) ·
[Repo](https://github.com/vercel/next.js)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/vercel/next.js/releases/tag/v16.2.7">16.2.7</a></h4>

<blockquote><div class="markdown-alert markdown-alert-note" dir="auto">
<p class="markdown-alert-title" dir="auto"><svg data-component="Octicon"
class="octicon octicon-info mr-2" viewbox="0 0 16 16" version="1.1"
width="16" height="16" aria-hidden="true"><path d="M0 8a8 8 0 1 1 16 0A8
8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5
7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0
1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1
1 0-2 1 1 0 0 1 0 2Z"></path></svg>Note</p>
<p dir="auto">This release is backporting bug fixes. It does
<strong>not</strong> include all pending features/changes on canary.</p>
</div>
<h3 dir="auto">Core Changes</h3>
<ul dir="auto">
<li>Backport documentation fixes for v16.2 (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/93804">#93804</a>)</li>
<li>[backport] Patch <code class="notranslate">playwright-core</code> to
resolve <code class="notranslate">_finishedPromise</code> on <code
class="notranslate">requestFailed</code> (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/93920">#93920</a>)</li>
<li>[backport] Fix dev mode hydration failure when page is served from
HTTP cache (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/93492">#93492</a>)</li>
<li>[backport] Fix catch-all <code
class="notranslate">router.query</code> corruption with <code
class="notranslate">basePath</code> + <code
class="notranslate">rewrites</code> (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/93917">#93917</a>)</li>
<li>[backport] Encode non-ASCII characters in cache tags at construction
(<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/93918">#93918</a>)</li>
<li>[backport] Fix server action forwarding loop with middleware
rewrites (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/93919">#93919</a>)</li>
<li>[backport] Turbopack: switch from base40 to base38 hash encoding (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/93932">#93932</a>)</li>
<li>[ci] Disable hanging node 24 typescript tests on 16.2 backport
branch (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/94164">#94164</a>)</li>
<li>[backport] Fix "type: module" in project dir when using standalone
or adapters (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/94050">#94050</a>)</li>
<li>[backport] Propagate adapter preferred regions (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/94200">#94200</a>)</li>
<li>[16.2.x] Don't drop <code class="notranslate">FormData</code>
entries (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/94240">#94240</a>)</li>
<li>[backport] feat(turbopack): add LocalPathOrProjectPath PostCSS
config resolution (<a
href="https://bounce.depfu.com/github.com/vercel/next.js/pull/94284">#94284</a>)</li>
</ul>
<h3 dir="auto">Credits</h3>
<p dir="auto">Huge thanks to <a
href="https://bounce.depfu.com/github.com/eps1lon">@eps1lon</a>, <a
href="https://bounce.depfu.com/github.com/icyJoseph">@icyJoseph</a>, <a
href="https://bounce.depfu.com/github.com/unstubbable">@unstubbable</a>,
<a href="https://bounce.depfu.com/github.com/mischnic">@mischnic</a>, <a
href="https://bounce.depfu.com/github.com/bgw">@bgw</a>, <a
href="https://bounce.depfu.com/github.com/timneutkens">@timneutkens</a>,
and <a
href="https://bounce.depfu.com/github.com/lukesandberg">@lukesandberg</a>
for helping!</p></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please let us
know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="ee6e79b179...9bd3c26a73">See
the full diff on Github</a>. The new version differs by 13 commits:</p>
<ul>
<li><a
href="9bd3c26a73"><code>v16.2.7</code></a></li>
<li><a
href="c63224f3d8"><code>[backport]
feat(turbopack): add LocalPathOrProjectPath PostCSS config resolution
(#94284)</code></a></li>
<li><a
href="63115c7987"><code>[16.2.x]
Don&#39;t drop `FormData` entries (#94240)</code></a></li>
<li><a
href="aef22fdc82"><code>[backport]
Propagate adapter preferred regions (#94200)</code></a></li>
<li><a
href="f126e72271"><code>[backport]
Fix &quot;type: module&quot; in project dir when using standalone or
adapters (#94050)</code></a></li>
<li><a
href="bda3e2aabe"><code>[ci]
Disable hanging node 24 typescript tests on 16.2 backport branch
(#94164)</code></a></li>
<li><a
href="7e16e07c02"><code>[backport]
Turbopack: switch from base40 to base38 hash encoding
(#93932)</code></a></li>
<li><a
href="6139f4b885"><code>[backport]
Fix server action forwarding loop with middleware rewrites
(#93919)</code></a></li>
<li><a
href="c021d10fe9"><code>[backport]
Encode non-ASCII characters in cache tags at construction
(#93918)</code></a></li>
<li><a
href="9184ddb1ae"><code>[backport]
Fix catch-all `router.query` corruption with `basePath` + `rewrites`
(#93917)</code></a></li>
<li><a
href="3279f01607"><code>[backport]
Fix dev mode hydration failure when page is served from HTTP cache
(#93492)</code></a></li>
<li><a
href="ffc4f29682"><code>[backport]
Patch `playwright-core` to resolve `_finishedPromise` on `requestFailed`
(#93920)</code></a></li>
<li><a
href="bc1791dd7e"><code>Backport
documentation fixes for v16.2 (#93804)</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-06-09 12:38:33 +02:00
Robin Malfait
d01e103cc4
Add missing inset keyword for inset-shadow-none (#20208)
This PR fixes an issue where the `inset-shadow-none` class did not use
the `inset` keyword. This PR fixes that by introducing the `inset`
keyword:

```diff
  .inset-shadow-none {
-   --tw-inset-shadow: 0 0 #0000;
+   --tw-inset-shadow: inset 0 0 #0000;
    box-shadow: var(--tw-inset-shadow), var
  }
```

While the end effect is the same (there will be no shadow), it also
means that we switch between the types of shadows. This results in the
fact that things like transitions don't behave the way they should.

A minimal reproduction looks like this:
https://play.tailwindcss.com/iOrnKWP49a (depending on when you visit
this link, it might be fixed)

## Test plan

1. Updated tests to reflect
2. Verified in the Vite playground that this is the case. In the video
you will notice that the transition is smooth in the fixed case, but
there is no transition in the current state:



https://github.com/user-attachments/assets/15d8c78e-6be5-4c6c-8df9-1044c14e8f39
2026-06-08 23:08:52 +02:00
Robin Malfait
68fcdf1f05
Do not crash when migrating empty classes (#20205)
This PR fixes a crash while using `npx @tailwindcss/upgrade` when
migrating classes with no body inside of an `@layer utilities`.

When running `npx @tailwindcss/upgrade`, one thing we do is migrate the
CSS from:
```css
@layer utilities {
  .foo {
    color: red;
  }
}
```
To:
```css
@utility foo {
  color: red;
}
```

We already have some logic that leaves non-classe (IDs, attribute
selectors, ...) alone. But if we are migrating a class that has no body,
then we will migrate that as well:
```css
@layer utilities {
  .empty {
  }
}
```
Is turned into:
```css
@utility empty {
}
```

But later in the migration process this will result in an error because
a `@utility` has to have at least _some_ nodes.

Ideally, you don't even have CSS that has empty rules since it doesn't
have any effect in the browser (except of making your CSS file bigger),
but it could be that you don't have control over this file, so a fix is
still valid.

This PR solves that by leaving those rules alone, and keep them in an
`@layer utilities`.

Fixes: #20204

## Test plan

1. Added a dedicated test for this usecase
2026-06-07 21:50:35 +02:00
Robin Malfait
3f58e52e36
Ensure @source globs with symlinks are preserved (#20203)
This PR fixes an issue when working with `@source` and `@source not`
that involves symlinks.

Internally our sources are mapped to a source entry where we have a
`base` path and a `pattern`. You can think about this where we insert a
`.gitignore` file in the `base` path for the given pattern.

However, we optimize these entries to move as many "static" parts into
the base path. For example:
```css
@source "./some/folder/here/*.html";
```

Is mapped to something like:
```ts
{ base: "/projects/my-project", pattern: "./some/folder/here/*.html" }
```
We then optimize it by turning it into:
```ts
{ base: "/projects/my-project/some/folder/here", pattern: "*.html" }
```

While doing this, we also use `dunce::canonicalize` to resolve the
actual paths on disk. This means that a symlink is resolved to their
real paths. This can cause issues because the "real" path is not what
you wrote in the `@source` directives.

So before, it could be that you have this:
```css
@source "./some/symlinked-folder/here/*.html";
```
Which was mapped to this on the Rust side:
```ts
{ base: "/projects/my-project", pattern: "./some/symlinked-folder/here/*.html" }
```
But was then optimized to:
```ts
{ base: "/projects/my-project/some/actual-folder/here", pattern: "*.html" }
```

...and we lost the `symlinked-folder` information. This causes issues as
seen in #17985.

With this PR, we keep the symlinked information in those globs since
that's what you wrote in those `@source` directives.

While setting up integration tests, I stumbled upon an issue because I
wanted to test that ignoring a symlinked folder, but including a single
particular file of that ignored folder resulted in that file being
ignored as well. Let's look at an example:

```css
@source     '../lib';
@source not '../lib/ignored';
@source     '../lib/ignored/except.html';
```

Earlier I mentioned that we create `.gitignore` files based on these
`@source` directives. In this case, when we're dealing with a folder, we
use `**/*` as the contents.

Looking at the example above, we should essentially have something like
this:
```gitignore
# lib/.gitignore
# @source '../lib'
!**/*

# lib/ignored/.gitignore
# @source '../lib/ignored'
**/*

# @source '../lib/ignored/except.html'
!except.html
```

Since it's a `.gitignore` file, we have to invert the globs. But the bug
I noticed is that in reality the result of those gitignores didn't look
like the above, it looked like:
```gitignore
# lib/.gitignore
# @source '../lib'
!**/*

# lib/ignored/.gitignore
# @source '../lib/ignored/except.html'
!except.html

# @source '../lib/ignored'
**/*
```

Notice how the `!except.html` and `**/*` are flipped. When dealing with
`.gitignore` files, the order is important.

This was caused because internally we kept a `BTreeMap` of `BTreeSet`s
where the map was the base path and a set of patterns. The patterns were
sorted because of the `BTreeSet`... which is not what we want.

Fixes: #17985
Closes: #20091

## Test plan

1. Added new tests in the scanner tests (on the Rust side)
2. Added integration tests with a symlink to another folder, outside of
the current folder
2. Added integration tests with a symlink to another folder, inside of
the current folder
2. Added integration tests to ensure that the order of `@source` files
with a folder + file is sorted correctly.
3. Since we're dealing with symlinks in these tests, let's test all OSes
[ci-all]
2026-06-07 20:44:22 +02:00
Jordan Pittman
ad6693906a
Allow @variant to be used inside addBase (#19480)
This seems like an unintentional omission

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-06-04 10:46:40 +00:00
Chris Hasiński
d42b34abbf
fix: handle invalid UTF-8 in Ruby and Vue preprocessors (#19588)
## Summary

This PR fixes a panic that occurs when the Ruby or Vue preprocessors
encounter files with invalid UTF-8 bytes.

**The issue:**
- `ruby.rs:37` and `vue.rs:18` used
`std::str::from_utf8(content).unwrap()`
- This panics when processing files containing invalid UTF-8 bytes

**Error message:**
```
thread panicked at crates/oxide/src/extractor/pre_processors/ruby.rs:37:59:
called `Result::unwrap()` on an `Err` value: Utf8Error { valid_up_to: 45, error_len: Some(1) }
```

**The fix:**
- Wrap UTF-8 conversion in `if let Ok(...)` to gracefully handle invalid
UTF-8
- Skip regex-based template extraction when UTF-8 conversion fails
- Allow byte-level processing to continue (in Ruby's case)

This can happen in Rails projects when:
- Binary files are inadvertently scanned
- Files contain non-UTF-8 encodings  
- Files are truncated at multi-byte character boundaries during parallel
processing

## Test plan

- [x] Added `test_invalid_utf8_does_not_panic` test for Ruby
preprocessor
- [x] Added `test_valid_utf8_with_multibyte_chars` test for Ruby
preprocessor
- [x] Added `test_invalid_utf8_does_not_panic` test for Vue preprocessor
- [x] All existing tests pass (`cargo test pre_processors` - 43 tests)

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-06-04 10:35:47 +00:00
Robin Malfait
0612ddc7dc
Add Twig pre-processor (#20198)
This PR fixes an issue where `addClass(opacity-50)` and
`removeClass(opacity-50)` in Twig templates isn't extracted properly.

This fixes that by adding a pre-processor for `.twig` files. This is a
simple initial implementation where we drop the `(` and `)` from the
`addClass` and `removeClass` functions. We don't do any special handling
around escaped characters or parenthesis inside of strings. We will add
them when there is a use case for it. Until then, we'll keep it simple.

If the real API would've been `addClass('opacity-50')` then it would've
worked out of the box.

A workaround you can use today is by using spaces `addClass( opacity-50
)` that works as well.

Fixes: #19458
Closes: #20110

## Test plan

1. Added new tests for `twig` extraction
2. Added tests with nested `(` and `)` e.g. `addClass(p-(--value))`
which should properly extarct `p-(--value)`
2026-06-04 11:44:13 +02:00
depfu[bot]
0b58dd69fd
Update @napi-rs/cli 3.6.2 → 3.7.0 (minor) (#20197)
Here is everything you need to know about this upgrade. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ @​napi-rs/cli (3.6.2 → 3.7.0) ·
[Repo](https://github.com/napi-rs/napi-rs)





Sorry, we couldn't find anything useful about this release.











---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-06-04 10:31:08 +02:00
Aarni Koskela
efae52c3af
Simplify CSS when using utilities that use a *-0 or *-1 value (#20196)
## Why?


While inspecting a Tailwind-powered site, I noticed selectors like

```css
.inset-0{inset:calc(var(--spacing) * 0)}
.inset-x-0{inset-inline:calc(var(--spacing) * 0)}
.top-0{top:calc(var(--spacing) * 0)}
```

which seem a bit silly, not to mention more complex for the end-user
device parsing the CSS.

## Summary

This PR adjusts helpers to not generate `calc(... * 0)` expressions.

https://github.com/tailwindlabs/tailwindcss/pull/19095 does a similar
thing on CSS AST, but that doesn't run during the build proper.

## Test plan

Ran `pnpm build && pnpm test && pnpm test:integration`. (Some unrelated
tests failed on my machine, hopefully less in CI.)

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-06-03 16:44:09 +00:00
Robin Malfait
0c5f8bfd88
Ignore the standalone CLI (#20139)
This PR fixes an issue where if you use the standalone CLI, and you move
the standalone CLI into the current project, then we would scan that
standalone CLI as-if it contains Tailwind CSS classes. Since the CLI
contains actual Tailwind CSS classes, and is in fact readable text, this
binary would've been used as a source.

There are a few ways of fixing this, we could hardcode all the known
names, but that would result in an issue if you rename the CLI. We could
check whether it's a binary format and look for magic numbers at the
top. We could also check for a shebang at the top of the file and skip
it that way.

While some of these solutions might still be useful for the future. For
now I fixed it by essentially always ignoring `process.execPath`. That
way we never ever scan the actual executable regardless of whether you
renamed it or not.

Fixes: #20134

## Test plan

- Added an integration tests
- Works on every OS [ci-all]
2026-06-02 12:49:53 +02:00
Robin Malfait
44818a6cf6
Ensure @tailwindcss/cli recovers from a deleted transitive dependency (#20137)
This PR fixes an issue where the `@tailwindcss/cli` can get into a
non-recoverable state when any of the transitive dependencies break.

Tailwind CSS has 2 kinds of dependencies:

1. All your templates
2. All dependencies that contribute to your configuration such as the
`input.css`, any plugins, any `tailwind.config.js` files and so on.

When a template changes, we just have to scan for new Tailwind CSS
classes and emit a new CSS file. But when the `input.css` file, or any
of its dependencies changes, then we want to perform a full rebuild.

The idea is that your `@theme` might have changed, or new plugins have
been added, or old plugins have been removed.

If you have an `input.css` file:
```css
@import "tailwindcss";
@config "./tailwind.config.js";
```

That relies on a custom config: `tailwind.config.js`:
```js
const theme = require('./my-custom-theme.js');
module.exports = {
  theme
}
```

If that file relies on yet another file: `./my-custom-theme.js`, then
changes there should also trigger a full rebuild.

Since we're dealing with JavaScript here, we want to clear the require
cache and rebuild the dependency tree such that another change to any of
these files triggers a full fresh build.

However, if any of those (transitive) dependencies are deleted, then we
will end up in an invalid state. Creating a new compiler will result in
a build error. The compiler won't be able to figure out the entire
dependency tree, and we're stuck.

Once the user fixes the potentially missing dependency, the watchers
will not be watching any of those files because we created a fresh
compiler.

With this PR, we fix that by keeping track of old paths and using those
while we are still in an invalid state. The moment everything is fixed,
a fresh dependency tree is created and everything starts working again
without you having to restart the `@tailwindcss/cli` command.

Fixes: #20113
Closes: #20114
Closes: #20133

## Test plan

- Added an integration test that removes the transitive dependency.
Re-adding that file later will recover the CLI state.
2026-06-01 19:15:40 +02:00
Robin Malfait
6b43b6400a
Canonicalization: limit arbitrary to bare values conversion (#20130)
This PR improves the canonicalization process by limiting the bare
values to a certain amount.

Before this PR, whenever we have an arbitrary value, e.g. `left-[6px]`,
then we prefer to use a bare value instead e.g. `left-1.5`. In most
cases, this makes sense.

However, there are places where this doesn't really make sense
(https://x.com/kettanaito/status/2059987396050268589)

- `left-[99999px]` → `left-24999.75 `

The hard part is to figure out _why_ this feels wrong. The `.75` could
feel wrong, but in the `left-[6px]` → `left-1.5`, the `.5` makes sense.
If we reduce that big number to `left-[99996px]` → `left-24999`, then
there is no floating point but it still feels wrong.

One possibility I can think of is to analyze the incoming value and see
if we find certain patterns. All repeating numbers, fun numbers like
`1337`, common numbers most programmers know such as `720px`, `1280px`,
etc.

But instead of that, I think it's more reasonable to limit the bare
value such that the `px` based value doesn't exceed a big number. We can
improve the logic if there are other cases that don't really make sense.

The biggest value we have in our default theme is `--breakpoint-2xl:
96rem`, which is equivalent to `1536px`.

So I think any bare value that results in a value `<= 1536px` should
probably be fine.

In this case, `left-[99999px]` would stay as `left-[99999px]`, but
`left-[6px]` is still converted to `left-1.5`.

Note: this is only happening for arbitrary values being converted to
bare values _if_ they use the `--spacing` variable internally.

Values such as `z-[99999999999]` will still be converted to
`z-99999999999`, since the intent is still clear.

## Test plan

1. Added new tests for these limitations
2. Other existing tests still pass
2026-05-29 21:31:47 +02:00
Robin Malfait
d4f24c5f16
Fix invalid canonicalization where 0<unit> was migrated to 0 (#20127)
This PR fixes a bug in the canonicalization process when we simplify /
fold declarations that contain `0<unit>` values.

The reason we even try to fold these in the first place is to simplify
values such as `m-[0rem]` to `m-0`. The more values we can
fold/canonicalize, the better we can suggest replacements _if_ they are
the same.

One thing we know in CSS is that if you have a `<length>` type, and that
value is `0<unit>`, then we can safely change that to just `0`.
```css
width: 0rem;
width: 0;    /* `0` is a <length> */
```
However, if this was part of a `calc(…)` (or another CSS math function),
then this could make the calc expression invalid:
- `calc(1rem + 0px)` → `calc(1rem + 0)` — this goes from _valid_ to
_invalid_
At runtime the `1rem` can be converted to a `px` based valued, then
`16px + 0px` makes sense. Adding `0` without unit does not.
- `calc(1rem * 0px)` → `calc(1rem * 0)` — this goes from _invalid_ to
_valid_
At runtime the `1rem` can be converted to a `px` based value, but `16px
* 0px` would result in `0px^2` which doesn't make sense either.

We will still normalize values such as `-0.0rem` to just `0rem`, but not
`0` if we know it's unsafe to do so.

If we end up with top-level `calc(…)` expressions that can be folded,
then we will try to do that:
- `calc(0px * -1)` → `0`
- `calc(calc(0px * -1) + 1rem)` → `calc(0px + 1rem)`
Notice that the inner `calc(…)` was folded to `0px` not `0` because that
would make the `calc(0 + 1rem)` invalid.
Additionally, we could potentially fold the `calc(0px + 1rem)` to just
`1rem`, but we have to make sure that we don't introduce valid values
from invalid values `calc(0s + 1rem)` would be invalid, but folding it
to `1rem` would make it valid which is not good.

Fixes:
https://github.com/tailwindlabs/tailwindcss-intellisense/issues/1579
2026-05-29 14:43:26 +02:00
Robin Malfait
829cdc930a
duration must be at least 500ms 2026-05-26 23:34:51 +02:00
Robin Malfait
2666194d5c
Improve internal instrumentation module (#20119)
This PR improves some of the internal instrumentation tooling we have.

While working on another branch, I updated the instrumentation tooling
to have a few different ways of measuring what's going on.

Until now, we had an `I.start(label)` and corresponding `I.end(label)`.
While this works, it also means that you have to make sure that you call
`I.end(label)` before every `return` to track things properly.

With this PR, I added a `I.span(label, () => /* some callback*/{})` API
that essentially does that in one go. It also handles promises and
resturns the value that was returned from the callback. This can be
useful in situations where you have a one-liner:
```ts
let css = I.span('toCss(…)', () => toCss(ast))
```

If your callback is longer, then you end up in a situation where you
have to indent your code, and if you want to stop measuring you have to
drop code in 2 places and re-indent:
```diff
- I.span('label', () => {
    …
- })
```

For this situation, I also added a `using _ = I.track(label)` API
instead. This can also be used in any block and automatically inserts
the `I.end(label)` on every exit point. This relies on the new `using`
keyword, but we already relied on that for the instrumentation module.

Last but not least, the constructor accepts a `shouldReport` which
defaults to the `env.DEBUG`. The reason for this change is so that it's
easier to report / not report during development instead of swapping out
an environment variable. Again, this is internal so there is no public
API change happening here.

## Test plan

All tests should still pass.
2026-05-26 23:20:39 +02:00
Robin Malfait
cdfae994ed
Remove unused test (#20117)
This PR cleans up some old stale test that has been skipped from the
beginning.

While this test wants to prove that migrating from Tailwind CSS v3 to
Tailwind CSS v4 can handle the `#{!important}` SCSS notation, it doesn't
prove that we can migrate an entire SCSS project. SCSS has much more
special syntax and we never supported that.

Let's get rid of this test that's doing nothing at the moment.
Especially since we don't want to migrate SCSS projects. Enabling this
might result in the false sense that we _do_ support SCSS migrations
which is not the case.

Closes: #20106
2026-05-26 19:45:00 +02:00
Robin Malfait
749c45ef26
Expose index and siblings on walk context (#20109)
This PR is a small improvement of the current `walk` implementation
where we will expose the `index` and the `siblings` on the current
context.

During a walk, we walk over objects that contain a `nodes: []` field.
The `ctx.parent` that already exists is a reference to the parent node,
but `ctx.siblings` is a reference to the `ctx.parent.nodes`.

The `ctx.index` is the index of the current node we are walking in the
`siblings` array. This way we can prevent the awkward
`ctx.parent?.nodes.indexOf(node)` which is a bit silly because we
already know the nodes we're walking and its index...

The `ctx.parent` can be `null`, but the `ctx.siblings` will never be
`null`, this can be seen in a situation like this:

```ts
let ast: AstNode = [nodeA, nodeB]

walk(ast, (node, ctx) => {
  if (node === nodeA) {
    ctx.parent === null; // Because there is no parent
    ctx.siblings === ast; // Because that's the current list we're looping over

    // Before this PR, we would have to do something like:
    let siblings = ctx.parent?.nodes ?? ast
  }
})
```

In the above example, the `ast` is a separately variable, but if this
was inlined, we would run into some issues:
```ts
walk([nodeA, nodeB], (node, ctx) => {
  if (node === nodeA) {
    ctx.parent === null; // Because there is no parent
    ctx.siblings === ast; // Because that's the current list we're looping over

    // At this point, there is no way to get to the `[nodeA, nodeB]` list
    // without moving it to a variable first.
  }
})
```

So, this PR doesn't change much, the additional information we track is
already known information that is now exposed to the caller of the
`walk` function.

In this PR we did update some usages and got rid of some awkward
`ctx.parent?.nodes ?? []` and `ctx.parent.nodes.indexOf(…)` usages.

## Test plan

- All tests still pass as expected
2026-05-24 22:32:05 +02:00
Jiahan Chen
982e920df8
Add Rspack optional peer dependency for @tailwindcss/webpack (#20027)
## Summary

This PR makes Rspack support explicit for `@tailwindcss/webpack` by
adding `@rspack/core` as an optional peer dependency alongside
`webpack`.

The loader already works through Rspack's webpack-compatible loader API,
as shown in this runnable example:
https://github.com/rstackjs/rstack-examples/tree/main/rspack/tailwindcss.
The README and package description are updated to document that usage.

## Test plan

No Rspack-specific tests were added. The loader implementation is
unchanged, and the existing webpack loader tests exercise the same
loader API path that Rspack uses, which should cover the relevant
behavior.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-05-23 11:14:48 +02:00
Robin Malfait
73983e1cf5
Fix 'Sourcemap is likely to be incorrect' warnings when using @tailwindcss/vite (#20103)
This PR fixes an issue where a bunch of warnings would be shown related
to sourcemaps.

This happens when we are dealing with CSS files that are _not_ Tailwind
CSS roots. In that case, in the `transform` step, we return the `src` of
that module as-is because we didn't modify anything. However, when
nothing changed, you have to return a `NullValue` such as `undefined`.

So this is a stupid little fix, but it should get rid of a bunch of
annoying warnings.

Fixes: #19930

## Test plan

- Added an integration test to mimic the problem
- Other tests still pass
- Tested it against the reproduction provided in #19930


Before:
<img width="1887" height="1763" alt="8oQNG5Lqr2B"
src="https://github.com/user-attachments/assets/2d8af456-4176-4f18-92a3-5327e395ac6b"
/>


After:
<img width="1885" height="1404" alt="8oQND5kWSb4"
src="https://github.com/user-attachments/assets/7dd98ea4-126b-45d4-9411-0afbacd2c797"
/>
2026-05-22 17:57:25 +02:00
Robin Malfait
e0a0c46c85
Cleanup lockfile / dependencies (#20102)
This PR reduces the installed dependencies by cleaning up the
`pnpm-lock.yaml` file.

This also pins `@parcel/watcher` such that the lockfile is generated
properly becauase of the patched dependencies.

This is a follow-up of #19499, but up to date with the latest state of
the repo.

## Test plan

- Lockfile is simpler. Most dependencies stayed the same, and were
published _months_ ago. There are a few cases where we have more recent
published dependencies. There are 7 dependencies that were published in
the last ~24 hours: `node-releases@2.0.46` (10 hours ago),
`electron-to-chromium@1.5.361` (12 hours ago), `semver@7.8.1` (20 hours
ago), `terser@5.48.0` (20 hours ago), `webpack-sources@3.5.0` (5 hours
ago), `vite@8.0.14` (yesterday). All of these but the `terser` version
used OIDC.
- Socket.dev didn't report any issues with the changed dependencies
- All tests still pass

---------

Co-authored-by: James Garbutt <43081j@users.noreply.github.com>
2026-05-22 16:57:46 +02:00
Jordan Brough
a480043a8a
Add --silent option to suppress output in @tailwindcss/cli (#20100)
Edited by: @RobinMalfait 

This PR adds a new `--silent` option to the `@tailwindcss/cli` to
suppress output (except for errors).

## Test plan

- Existing tests pass
- A new integration test for the `--silent` option was added

---

Original:

## Summary

Small change to add a `--quiet` option.

@adamwathan previously said this type of thing [sounded like a good
idea](https://github.com/tailwindlabs/tailwindcss/issues/8050#issuecomment-1100164351):

> [I] have made a note about the --silent option idea which I think
definitely has value 👍🏻

This is helpful to keep logs high signal in some scenarios. For example,
when I want AI to sift through my foreman logs, where "Done in X"
becomes the dominant log message over time when running tailwind
alongside other things.

## Test plan

I've added an integration test.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-05-22 13:03:32 +00:00
Robin Malfait
9f9b7c5c6d
Remove pnpm-lock.yaml from wasm32-wasi (#20101)
This PR removes the `pnpm-lock.yaml` file from one of the sub-packages.
This is unnecessary and causes confusion. Since this is a monorepo, we
can make use of the `pnpm-lock.yaml` file in the root of the project
instead.

Closes #20097
2026-05-22 14:33:17 +02:00
Robin Malfait
8dcdb66e8a
Bump dependencies (#20095)
This PR bumps some of our dependencies, common dependencies were moved
to pnpm's `catalog` feature.

Closes #20092
Closes #20085
Closes #20075
Closes #20066
Closes #20062


## Test plan

- All tests still pass
- Each dependency was published some time ago. Webpack has an even newer
version that was published <15min ago. Will update that one later.

[ci-all]
2026-05-21 17:58:55 +02:00
Robin Malfait
161569a541
Improve GitHub Actions (#20093)
This PR improves GitHub workflows by making sure that:

- Uesed actions are pinned
- We don't persist credentials
- Remove caches from release workflows
- Prevent template expansion when using `env.…` in `run` blocks
- Use the `gh release` instead of `softprops/action-gh-release`
2026-05-21 12:03:39 +02:00
Robin Malfait
d03edefd19
Fix parsing bug in SelectorParser (#20090)
While working on another feature, I noticed that a selector such as
`.foo::before` was parsed as:

```ts
[
  {
    kind: 'compound',
    nodes: [
      { kind: 'selector', value: '.foo' },
      { kind: 'selector', value: ':' },
      { kind: 'selector', value: '::before' },
    ],
  },
]
```

Instead of:
```ts
[
  {
    kind: 'compound',
    nodes: [
      { kind: 'selector', value: '.foo' },
      { kind: 'selector', value: '::before' },
    ],
  },
]
```

So far this hasn't been a real issue in practice, but it is in a
follow-up PR that I'm working on. To keep things separated, I wanted to
fix this behavior in a dedicated PR instead.

## Test plan

1. Added a test case for this situation
2. Other tests still pass
2026-05-20 15:54:07 +02:00
Robin Malfait
2c4726d3d5
Simplify selector combinators (#20089)
This PR is a follow-up of #20088 to further improve selectors, in
particular the `combinator`.

This PR explicitly types the `combinator` as:
```ts
type Combinator =
  | ' ' // Descendant combinator
  | '>' // Child combinator
  | '+' // Next-sibling combinator
  | '~' // Subsequent-sibling combinator
```

This allows us to explicitly test for this pattern in various places,
without us having to call `.trim()` first to know what the actual
combinator was.

In the selector parser itself, we already did a `.trim()` to know
whether we were dealing with a descendant combinator or not. With this
PR, we further ensure that there is no whitespace involved aroudn these
combinators.

This introduces a small problem because we need to be able to re-print a
selector's AST. So if we don't track whitespace, we have to re-introduce
it. But there are situations where we don't want it at all (during
canonicalization).

To solve this, we introduced a `minify = false` option in the
`SelectorParser.toCss`. If it's false (the default), then we introduce
whitespace, otherwise we remove all whitespace.

## Test plan

1. All existing tests pass
2. Manual cleanup/trimming of descendants is no longer necessary

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-05-20 15:30:55 +02:00
Robin Malfait
fc17df05f2
Add list, compound, and complex Selector nodes (#20088)
This PR introduces a few more nodes in the `SelectorParser`:

- A `list` node
- A `complex` node
- A `compound` node

These names are closer to the CSS Selector AST names
(https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Selectors/Selector_structure),
and are also used in other libraries.

The problem today is that there are situations where we parse a selector
like: `#a.b > .c, .d` as:
```ts
[
  { kind: 'selector', value: '#a' },
  { kind: 'selector', value: '.b' },
  { kind: 'combinator', value: ' > ' },
  { kind: 'selector', value: '.c' },
  { kind: 'separator', value: ', ' },
  { kind: 'selector', value: '.d' }
]
```

Which is a very simple structure, but this contains a flaw that is
annoying to deal with in practice: In order to determine that we are
dealing with multiple selectors, we have to loop through the nodes and
see if a separator occurs somewhere.

The other fun thing is that we already know the difference between
selectors, combinators and separators. So if we tweak this structure a
little bit during parsing, then we can answer the question from above in
a much simpler way:

With this PR, we will parse the selector as:
```ts
[
  {
    kind: 'list',
    nodes: [
      {
        kind: 'complex',
        nodes: [
          {
            kind: 'compound',
            nodes: [
              { kind: 'selector', value: '#a' },
              { kind: 'selector', value: '.b' }
            ]
          },
          { kind: 'combinator', value: '>' },
          { kind: 'selector', value: '.c' }
        ]
      },
      { kind: 'selector', value: '.d' }
    ]
  }
]
```

It definitely looks more complex, but now that we have a `list` node, we
already know that we are dealing with multiple selectors.

If you squint your eyes, in the inner part there is a `compound`
selector. This is essentially a node where each sub-node can be squished
together with no spaces whatsoever.

The `complex` selector is there just to group everything together. In
other tools, a complex selector is often represented as:
```ts
{
  kind: 'complex',
  combinator: '>',
  lhs: { … },
  rhs: { … },
}
```
While I want to have the concept of a `complex` node, I didn't go with
this syntax just because I want to keep the concept of `nodes` which
means that we don't need any special handling when using `walk` (which
loops over `.nodes` internally).

The reason this complex node exists is because otherwise you would end
up with this structure:
```ts
[
  {
    kind: 'list',
    nodes: [
      {
        kind: 'compound',
        nodes: [
          { kind: 'selector', value: '#a' },
          { kind: 'selector', value: '.b' }
        ]
      },
      { kind: 'combinator', value: '>' },
      { kind: 'selector', value: '.c' }
      { kind: 'selector', value: '.d' }
    ]
  }
]
```
But if you look at the `list` node now, it's not clear that we are
dealing with `2` selectors since there are 4 nodes. We could solve this
by re-introducing the separator node (`,`). The fact that the `list`
exists tells us that we're dealing with `n` selectors. But to know which
selectors we're dealing with, then we have to look for that `,` node
again, which introduces the original problem.

This is just an internal refactor to make future changes easier.

## Test plan

1. Everything still works as expected (all tests pass)
2. No public API breaking changes, this parser was never exposed
2026-05-20 15:04:05 +02:00
Robin Malfait
cea8c9721b
Improve parsing of shadow values (#20080)
This PR fixes an issue where a `calc(…)` value used in a shadow value
was incorrectly marked as the color of that shadow.

We have this feature where we can have colored shadows, this requires us
to replace the color in a value with a `var(--tw-shadow-color,
<original-value-here>)` such that we can swap out the color.
For this, we have to parse the value and figure out what the color part.

This PR uses the `ValueParser` to parse values, then figure out what the
color part is. The biggest reason for this is that we know what a
"function" is and what a normal "word" is, which allows us to do more
fine-grained checks on a per-type basis.
We tracked a few more functions that we _know_ produce color values, and
a few cases that we know produce length values so therefore can't be the
color.

Some examples:

- `calc(…)`, `min(…)`, `max(…)`, `clamp(…)`, `--spacing(…)` — these all
produce length-values.
- `color(…)`, `color-mix(…)`, `rgba?(…)`, `--alpha(…)` … — these all
produce color values.

Notice that we added `--spacing(…)` and `--alpha(…)` as well, these are
custom functions that Tailwind CSS provides, but we know what it will
eventually map to internally.

Last but not least, we also detect named colors and hex-based colors.

Fixes: #20065 
Closes: #20074

## Test plan

1. Added an integration test, before the fix the test would've looked
lik this:

  ```diff
    .drop-shadow-calc {
- --tw-drop-shadow-size: drop-shadow(0 0 calc(1 * var(--spacing))
var(--tw-drop-shadow-color, black));
+ --tw-drop-shadow-size: drop-shadow(0 0 var(--tw-drop-shadow-color,
calc(1 * var(--spacing))) black);
      --tw-drop-shadow: drop-shadow(var(--drop-shadow-calc));
filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, )
var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, )
var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
    }
  ```

2. Added more tests related to the shadow replacement logic itself where
we try to infer the color (or the length-values for x, y, blur, spread)
3. All other existing tests pass
2026-05-19 13:47:50 +02:00
Robin Malfait
36417cbd12
Properly negate custom variants with @container when used with not-* (#20059)
This PR fixes an issue where a custom variant declared with a
`@container` wasn't properly negated when using it in combination with
the `not-*` variant.

Given this CSS:
```css
@custom-variant has-a {
  @container style(--a) {
    @slot;
  }
}
```

If you then used `not-has-a:flex`, then the following CSS was produced:
```css
.not-has-a\:flex {
  @container style(--a) not {
    display: flex;
  }
}
```
But we expect the `not` to be in the correct location:
```css
.not-has-a\:flex {
  @container not style(--a) {
    display: flex;
  }
}
```

The issue was that we did some string related checks, and we assumed
that the `query` part of the `@container` (`style(--a)`) had to start
with a `(` character.

To fix this, we now parse the value to an AST, and verify the AST shape
before manipulating it. This now checks whether the `query` part is a
function (both `(…)` and `style(…)` are considered functions).

Also added some additional tests that were already handled, these cases
look like:

- `@container {query}`
- `@container not {query}`
- `@container {name} not {query}`
- `@container {name} {query}`


Fixes: #20058

## Test plan

1. Added a failing test for the use case of the linked issue.
2. Added a few more additional tests to explicitly track some use cases
we handled already but didn't track via tests.
3. All other tests still pass as expected.
2026-05-15 00:08:10 +02:00
Jordan Pittman
460a008120
v4: Allow @apply to be used with CSS mixins (#19427)
The CSS Custom Functions and Mixins spec [is using `@apply` with dashed
idents](https://drafts.csswg.org/css-mixins-1/#apply-rule) for native
mixin support. We shouldn't attempt to treat these as utilities and try
to compile them since they'll fail.

There one intentional limitation with regards to mixins and our use of
`@apply`: We do not allow users to mix utilities and mixins in the same
at-rule. In other words, all of the following `@apply` rules are
invalid:

```css
.foo {
  /* Invalid because the rules contain both mixins and utilities */
  @apply --my-mixin underline;
  @apply --my-mixin() underline;
  @apply underline --my-mixin;
  @apply underline --my-mixin();
}
```

Aside: Lightning CSS does not yet support this syntax so the results of
a production build won't produce the correct code but we'll at least
handle these correctly in Tailwind CSS itself.

Fixes #19422

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-05-14 14:22:26 +00:00
Robin Malfait
0db226a222
Add Vue integration test with 1000 components (#20055)
This PR adds an integration test with Vue where we use a 1000 components
and where each component references a CSS file via `@reference`. Each
component has a unique class that uses `@apply`.

There are some discussions in
https://github.com/tailwindlabs/tailwindcss/discussions/16429 that
mention that this causes OOM issues. Right now I can't reproduce that,
and even with a 1000 components, it produces CSS in a reasonable time:
```
vite v7.3.3 building client environment for production...
✓ 2011 modules transformed.
dist/index.html                   0.23 kB │ gzip:  0.18 kB
dist/assets/index-DNVNFkYQ.css  106.65 kB │ gzip: 10.79 kB
dist/assets/index-B8v7EbAN.js   223.84 kB │ gzip: 49.81 kB
✓ built in 3.17s
```

I also started a Vite server and triggered file changes to see if the
memory would grow forever, which it didn't. After a 1000 changes,
everything still behaves smoothly:
<img width="1694" height="1856" alt="image"
src="https://github.com/user-attachments/assets/b16800ae-4dce-4f0d-9d97-25f4cab21c1c"
/>

Making changes manually to a single component, result in proper HMR
request that update the browser:


https://github.com/user-attachments/assets/5c79ffc6-2329-4341-9d25-82b000093e31

This test is here to make sure that it keeps working in the future.

---

If I remove all `@reference` references, and usages of `@apply`, then
the build time is indeed faster:
```
vite v7.3.3 building client environment for production...
✓ 2011 modules transformed.
dist/index.html                   0.23 kB │ gzip:  0.18 kB
dist/assets/index-CcxXccJ1.css  106.61 kB │ gzip: 10.76 kB
dist/assets/index-M92YFF0G.js   223.84 kB │ gzip: 49.81 kB
✓ built in 1.97s
```

So we go from `1.97s` → `3.17s`, which is a `1.2s` increase when you use
`@reference` with `@apply` in 1000 files for a fresh build.

I also saw some comments about the CSS growing whenever `@reference` was
used, but as you can see in the snippets above they are at a stable
size.

## Test plan

1. All tests still pass

[ci-all] For testing on Windows / macOS

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-05-14 15:38:51 +02:00
Robin Malfait
559f92bbf8
Harden workflow security (#20054)
This PR improves the workflows a bit more by:

1. Making sure that we always use `pnpm install` with a frozen lockfile
2. Cleanup permissions
3. By not caching `~/.cargo/bin/`

## Test plan

1. Every test should still pass

[ci-all]
2026-05-14 13:00:37 +02:00
depfu[bot]
6ee13978e6
Update all of react 19.2.5 → 19.2.6 (patch) (#20050)
Here is everything you need to know about this upgrade. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ react (19.2.5 → 19.2.6) ·
[Repo](https://github.com/facebook/react) ·
[Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/facebook/react/releases/tag/v19.2.6">19.2.6</a></h4>

<blockquote><h2 dir="auto">React Server Components</h2>
<ul dir="auto">
<li>Type hardening and performance improvements<br>
(<a
href="https://bounce.depfu.com/github.com/facebook/react/pull/36425">#36425</a>
by <a href="https://bounce.depfu.com/github.com/eps1lon">@eps1lon</a>
and <a
href="https://bounce.depfu.com/github.com/unstubbable">@unstubbable</a>)</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please let us
know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="23f4f9f30d...eaf3e95ca9">See
the full diff on Github</a>. The new version differs by 2 commits:</p>
<ul>
<li><a
href="eaf3e95ca9"><code>Version
19.2.6</code></a></li>
<li><a
href="795203e75e"><code>[FlightReply]
Type hardening and performance improvements</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-05-14 12:41:48 +02:00
Serge Yudin
a2b89a7012
Fix canonicalize crash with plugin component values (#20052)
## Summary

Fixes #20051.

The collapse canonicalization pass speculatively checks compatible
functional utility roots. When one of those roots comes from a plugin
registered with `matchComponents`/`matchUtilities`, the speculative
candidate can call the plugin callback with an arbitrary value that is
not present in the configured `values` map. Plugins such as the Phoenix
Heroicons helper expect the mapped value shape and can throw while
canonicalize is only probing possible replacements.

This change skips speculative replacement utilities whose property
lookup throws, matching the best-effort behavior already used by utility
signature generation. The original candidates are preserved instead of
crashing canonicalization.

## Test plan

- `source ~/.nvm/nvm.sh && nvm use 22.14.0 && pnpm vitest run
packages/tailwindcss/src/canonicalize-candidates.test.ts -t "does not
crash when plugin matchComponents rejects speculative values during
collapse"`
- `source ~/.nvm/nvm.sh && nvm use 22.14.0 && pnpm vitest run
packages/tailwindcss/src/canonicalize-candidates.test.ts`
- `source ~/.nvm/nvm.sh && nvm use 22.14.0 && pnpm prettier --check
packages/tailwindcss/src/canonicalize-candidates.ts
packages/tailwindcss/src/canonicalize-candidates.test.ts`

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-05-14 09:59:19 +00:00
Robin Malfait
eefe64593a
Cleanup tests (#20053)
This PR does some cleanup work in the tests such that every test is
using the custom test helpers instead of creating the compiler itself
and using other test helpers such as `optimizeCss` or `pretty`.

For tests we have some helpers that introduce a small layer of
indirection. While you typically want to avoid indirection, this one
allows us to keep the tests the same whenever we make changes to the
internals.

It also allows us to run through the full core flow where we have to
setup a compiler, pass in the CSS, compile the candidates, optimize the
CSS and pretty print it for snapshot purposes.

Our tests often look like this when you are testing some candidates:
```ts
test('…', async () => {
  expect(await run(['flex', 'hover:flex'])).toMatchInlineSnapshot(`
    "
    .flex {
      display: flex;
    }

    @media (hover: hover) {
      .hover\\:flex:hover {
        display: flex;
      }
    }
    "
  `)
})
```

If you need to compile some CSS, we used the following:
```ts
test('…', async () => {
  expect(
    await compileCss(css`
      @tailwind utilities;
      .foo {
        @apply flex;
      }
    `),
  ).toMatchInlineSnapshot(`
    "
    .foo {
      display: flex;
    }
    "
  `)
})
```

With this PR, I normalized the tests by changing the signatures of those
tests slightly:
```ts
export async function run(
  // A list of candidates
  candidates: string[],

  // Optionally, custom CSS
  input = css`
    @tailwind utilities;
  `,

  // Optionally, custom compile options
  options: Parameters<typeof compile>[1] = {},
) {
  let { build } = await compile(input, options)
  return pretty(optimize(build(candidates)).code)
}

// Same as above, but without the candidates
export async function compileCss(css: string, options: Parameters<typeof compile>[1] = {}) {
  return run([], css, options)
}
```

They are very similar, but if we migrate _everything_ to `run`, then
there will be situations where you have to use:
```ts
test('…', async () => {
  expect(
    await run(
      [],
      css`
        @tailwind utilities;
        .foo {
          @apply flex;
        }
      `,
    ),
  ).toMatchInlineSnapshot(`
    "
    .foo {
      display: flex;
    }
    "
  `)
})
```

Which is a little bit confusing because what does `[]` even mean?

The next big change is that a lot of the tests were manually setting up
the compiler, passing in the CSS and compiler options, then building the
candidates, then manually optimizing the CSS and then manually pretty
printing the resulting CSS for snapshot purposes.

Other tests, didn't use all those steps and skipped the optimization
step for example. This means that not all tests were testing the
end-to-end core workflow.

This PR uses the tests helpers wherever we could. This now also means
that our tests look the same as much as possible.

The biggest goal of this was to get everything in a similar state.
Future PRs that add additional optimizations will now see those
optimizations reflected in the actual test output.

## Test plan

1. All tests still pass
- Some test _output_ has changed because the `optimizeCss` will now kick
in. But this reflects production better anyway.
2. No source code was changed
2026-05-14 11:43:34 +02:00
depfu[bot]
ece4824f0d
Update jiti 2.6.1 → 2.7.0 (minor) (#20044)
Here is everything you need to know about this update. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ jiti (2.6.1 → 2.7.0) · [Repo](https://github.com/unjs/jiti) ·
[Changelog](https://github.com/unjs/jiti/blob/main/CHANGELOG.md)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/unjs/jiti/releases/tag/v2.7.0">2.7.0</a></h4>

<blockquote><p dir="auto"><a
href="https://bounce.depfu.com/github.com/unjs/jiti/compare/v2.6.1...v2.7.0">compare
changes</a></p>
<h3 dir="auto">🚀 Enhancements</h3>
<ul dir="auto">
<li>Add explicit resource management (<code
class="notranslate">using</code>/<code class="notranslate">await
using</code>) support (<a
href="https://bounce.depfu.com/github.com/unjs/jiti/pull/422">#422</a>)</li>
<li>Support opt-in <code class="notranslate">tsconfigPaths</code> (<a
href="https://bounce.depfu.com/github.com/unjs/jiti/pull/427">#427</a>)</li>
<li>Support virtual modules (<a
href="https://bounce.depfu.com/github.com/unjs/jiti/pull/428">#428</a>)</li>
<li>Add <code class="notranslate">jiti/static</code> subpath (<a
href="https://bounce.depfu.com/github.com/unjs/jiti/pull/430">#430</a>)</li>
</ul>
<h3 dir="auto">🔥 Performance</h3>
<ul dir="auto">
<li>
<strong>interopDefault:</strong> Add caching to reduce proxy overhead by
~2x (<a
href="https://bounce.depfu.com/github.com/unjs/jiti/pull/421">#421</a>)</li>
</ul>
<h3 dir="auto">🩹 Fixes</h3>
<ul dir="auto">
<li>
<strong>require:</strong> Passthrough resolve options (<a
href="https://bounce.depfu.com/github.com/unjs/jiti/pull/412">#412</a>)</li>
<li>
<strong>require:</strong> Fallback to transpilation when <code
class="notranslate">tryNative</code> fails (<a
href="https://bounce.depfu.com/github.com/unjs/jiti/pull/413">#413</a>)</li>
<li>Fallback for <code class="notranslate">ENAMETOOLONG</code> when
evaluating esm (<a
href="https://bounce.depfu.com/github.com/unjs/jiti/pull/429">#429</a>)</li>
</ul>
<h3 dir="auto">📦 Build</h3>
<ul dir="auto">
<li>Upgrade rspack to v2 (<a
href="55194fb">55194fb</a>)</li>
<li>Experimental rolldown config (<a
href="8c0243f">8c0243f</a>)</li>
</ul>
<h3 dir="auto">✅ Tests</h3>
<ul dir="auto">
<li>Ignore jsx test for bun/cjs (<a
href="3a744ca">3a744ca</a>)</li>
</ul>
<h3 dir="auto">❤️ Contributors</h3>
<ul dir="auto">
<li>Pooya Parsa (<a
href="https://bounce.depfu.com/github.com/pi0">@pi0</a>)</li>
<li>Kricsleo (<a
href="https://bounce.depfu.com/github.com/kricsleo">@kricsleo</a>)</li>
<li>Espen Hovlandsdal (<a
href="https://bounce.depfu.com/github.com/rexxars">@rexxars</a>)</li>
<li>Rintaro Itokawa (<a
href="https://bounce.depfu.com/github.com/re-taro">@re-taro</a>)</li>
<li>Matteo Collina (<a
href="https://bounce.depfu.com/github.com/mcollina">@mcollina</a>)</li>
<li>Mario Zechner (<a
href="https://bounce.depfu.com/github.com/badlogic">@badlogic</a>)</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please let us
know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="aedcdee7fe...fd3bb289b7">See
the full diff on Github</a>. The new version differs by 29 commits:</p>
<ul>
<li><a
href="fd3bb289b7"><code>chore(release):
v2.7.0</code></a></li>
<li><a
href="27fe3f2a49"><code>chore:
update release script</code></a></li>
<li><a
href="4fcd2f23aa"><code>fix:
fallback for `ENAMETOOLONG` when evaluating esm (#429)</code></a></li>
<li><a
href="8c0243f14e"><code>build:
experimental rolldown config</code></a></li>
<li><a
href="55194fbb97"><code>build:
upgrade rspack</code></a></li>
<li><a
href="0abda72c11"><code>ci:
update node test matrix</code></a></li>
<li><a
href="8c7822ef2f"><code>chore:
update tsconfig</code></a></li>
<li><a
href="08fc868c92"><code>chore:
update deps</code></a></li>
<li><a
href="5d552e3beb"><code>feat:
add `jiti/static` export (#430)</code></a></li>
<li><a
href="ae790b0214"><code>feat:
support virtual modules option (#428)</code></a></li>
<li><a
href="a3e705dbdc"><code>fix(require):
fallback to transpilation when `tryNative` fails (#413)</code></a></li>
<li><a
href="4deba16283"><code>chore:
update agents.md</code></a></li>
<li><a
href="f85b0e523d"><code>lint</code></a></li>
<li><a
href="3ce242653f"><code>feat:
support opt-in `tsconfigPaths` (#427)</code></a></li>
<li><a
href="c49c54e42e"><code>chore:
init agents.md</code></a></li>
<li><a
href="b66bd233c2"><code>feat:
add explicit resource management (using/await using) support
(#422)</code></a></li>
<li><a
href="a467d31ffc"><code>perf(interopDefault):
add caching to reduce proxy overhead by ~2x (#421)</code></a></li>
<li><a
href="fe264b49f1"><code>fix(ci):
skip `--coverage` flag for node 18</code></a></li>
<li><a
href="058d91a338"><code>chore:
lint</code></a></li>
<li><a
href="650bc48a76"><code>chore:
add missing prettier dep</code></a></li>
<li><a
href="e28b5e9645"><code>chore(deps):
update autofix-ci/action digest to 7a166d7 (#424)</code></a></li>
<li><a
href="31096aa9e2"><code>chore(deps):
update actions/checkout action to v6 (#419)</code></a></li>
<li><a
href="498e8d73a4"><code>chore:
update deps</code></a></li>
<li><a
href="9ee314fd0f"><code>test:
update</code></a></li>
<li><a
href="3a744ca271"><code>test:
ignore jsx test for bun/cjs</code></a></li>
<li><a
href="e88ac44079"><code>chore:
update deps</code></a></li>
<li><a
href="4045c7a2a2"><code>chore:
fix lint issues</code></a></li>
<li><a
href="39e86de57c"><code>chore(deps):
update actions/setup-node action to v6 (#411)</code></a></li>
<li><a
href="ddb4683d37"><code>fix(require):
passthrough resolve options (#412)</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-05-13 12:02:13 +02:00
depfu[bot]
57521613ef
Update postcss 8.5.10 → 8.5.14 (patch) (#20040)
Here is everything you need to know about this upgrade. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ postcss (8.5.10 → 8.5.14) ·
[Repo](https://github.com/postcss/postcss) ·
[Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/postcss/postcss/releases/tag/8.5.14">8.5.14</a></h4>

<blockquote><ul dir="auto">
<li>Fixed custom syntax regression (by <a
href="https://bounce.depfu.com/github.com/43081j">@43081j</a>).</li>
</ul></blockquote>
<h4><a
href="https://github.com/postcss/postcss/releases/tag/8.5.13">8.5.13</a></h4>

<blockquote><ul dir="auto">
<li>Fixed <code class="notranslate">postcss-scss</code> commend
regression.</li>
</ul></blockquote>
<h4><a
href="https://github.com/postcss/postcss/releases/tag/8.5.12">8.5.12</a></h4>

<blockquote><ul dir="auto">
<li>Fixed reading any file via user-generated CSS.</li>
<li>Added <code class="notranslate">opts.unsafeMap</code> to disable
checks.</li>
</ul></blockquote>
<h4><a
href="https://github.com/postcss/postcss/releases/tag/8.5.11">8.5.11</a></h4>

<blockquote><ul dir="auto">
<li>Fixed nested brackets parsing performance (by <a
href="https://bounce.depfu.com/github.com/offset">@offset</a>).</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please let us
know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="33b9790263...3ec13948ae">See
the full diff on Github</a>. The new version differs by 21 commits:</p>
<ul>
<li><a
href="3ec13948ae"><code>Release
8.5.14 version</code></a></li>
<li><a
href="f2bb827b20"><code>Update
dependencies</code></a></li>
<li><a
href="d75953d608"><code>Merge
pull request #2084 from 43081j/raw-raws-rawing</code></a></li>
<li><a
href="68bd2139b5"><code>fix:
always call `raw` to retrieve raw values</code></a></li>
<li><a
href="af58cf1b7a"><code>Release
8.5.13 version</code></a></li>
<li><a
href="f227dbd0e9"><code>Temporary
ignore pnpm 11 config</code></a></li>
<li><a
href="d3abd40d72"><code>Update
dependencies</code></a></li>
<li><a
href="dd06c3e113"><code>Revert
stringifier changes because of the conflict with
postcss-scss</code></a></li>
<li><a
href="ae889c815f"><code>Try
to fix CI</code></a></li>
<li><a
href="e0093e49bc"><code>Move
to pnpm 11</code></a></li>
<li><a
href="9bc81c48f0"><code>Release
8.5.12 version</code></a></li>
<li><a
href="85c4d7dab8"><code>Another
try to fix coverage</code></a></li>
<li><a
href="94484cae6d"><code>Try
to fix coverage</code></a></li>
<li><a
href="c64b7488d2"><code>Load
only .map source maps</code></a></li>
<li><a
href="aaec7b78b3"><code>Avoid
throwing JSON parsing errors for non-JSON source maps</code></a></li>
<li><a
href="233fb264ea"><code>Mention
original author of the solution</code></a></li>
<li><a
href="2502f75030"><code>Release
8.5.11 version</code></a></li>
<li><a
href="5ca1901949"><code>Speed
up parsing many nested brackets</code></a></li>
<li><a
href="42b5337dd7"><code>Update
dependencies</code></a></li>
<li><a
href="7e36e153d0"><code>Cache
node.raws locally in Stringifier hot methods</code></a></li>
<li><a
href="8ec62b157b"><code>Bypass
MapGenerator for no-source-map stringify in LazyResult</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-05-12 15:21:44 +00:00
depfu[bot]
bcd581c568
🚨 [security] Update next 16.2.4 → 16.2.6 (patch) (#20039)
<hr>

🚨 <b>Your current dependencies have known security vulnerabilities</b> 🚨

This dependency update fixes known security vulnerabilities. Please see
the details below and assess their impact carefully. We recommend to
merge and deploy this as soon as possible!
<hr>



Here is everything you need to know about this upgrade. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ next (16.2.4 → 16.2.6) ·
[Repo](https://github.com/vercel/next.js)


<details>

<summary>Security Advisories 🚨</summary>
<h4><a
href="https://bounce.depfu.com/github.com/facebook/react/security/advisories/GHSA-rv78-f8rc-xrxh">🚨
Next.js Vulnerable to Denial of Service with Server Components</a></h4>
<blockquote><p dir="auto">A vulnerability affects certain React Server
Components packages for versions 19.x and frameworks that use the
affected packages, including Next.js 13.x, 14.x, 15.x, and 16.x using
the App Router. The issue is tracked upstream as <a
href="https://bounce.depfu.com/github.com/facebook/react/security/advisories/GHSA-rv78-f8rc-xrxh">CVE-2026-23870</a>.</p>
<p dir="auto">A specially crafted HTTP request can be sent to any App
Router Server Function endpoint that, when deserialized, may trigger
excessive CPU usage. This can result in denial of service in unpatched
environments.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-36qx-fr4f-26g5">🚨
Next.js has a Middleware / Proxy bypass in Pages Router applications
using i18n</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">Applications using the Pages Router with <code
class="notranslate">i18n</code> configured and middleware/proxy-based
authorization can allow unauthorized access to protected page data
through locale-less <code
class="notranslate">/_next/data/&lt;buildId&gt;/&lt;page&gt;.json</code>
requests. In affected configurations, middleware does not run for the
unprefixed data route, allowing an attacker to retrieve SSR JSON for
protected pages without passing the intended authorization checks.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">The matcher logic was updated to perform the same match as
it would on a non-i18n data route.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, enforce authorization
in the page's server-side data path instead of relying solely on
middleware.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">🚨
Next.js has a Middleware / Proxy bypass in App Router applications via
segment-prefetch routes</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">App Router applications that rely on middleware or
proxy-based checks for authorization can allow unauthorized access
through transport-specific route variants used for segment prefetching.
In affected configurations, specially crafted <code
class="notranslate">.rsc</code> and segment-prefetch URLs can resolve to
the same page without being matched by the intended middleware rule,
which can allow protected content to be reached without the expected
authorization check.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">We now include App Router transport variants when
generating middleware matchers, so middleware protections are applied
consistently to those requests as well as to the normal page URL.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, enforce authorization
in the underlying route or page logic instead of relying solely on
middleware.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-wfc6-r584-vfw7">🚨
Next.js vulnerable to cache poisoning in React Server Component
responses</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">Applications using React Server Components can be
vulnerable to cache poisoning when shared caches do not correctly
partition response variants. Under affected conditions, an attacker can
cause an RSC response to be served from the original URL and poison
shared cache entries so later visitors receive component payloads
instead of the expected HTML.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">We now validate and interpret <code
class="notranslate">RSC</code> request headers consistently across
request classification and rendering, and we enforce the intended
cache-busting behavior so RSC payloads are not unexpectedly served from
the original URL.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, ensure your CDN or
reverse proxy keys on the relevant RSC request headers and honors <code
class="notranslate">Vary</code>, or disable shared caching for affected
App Router and RSC responses.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-492v-c6pp-mqqv">🚨
Next.js has a Middleware / Proxy bypass through dynamic route parameter
injection</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">Applications that rely on middleware to protect dynamic
routes can be vulnerable to authorization bypass. In affected
deployments, specially crafted query parameters can alter the dynamic
route value seen by the page while leaving the visible path unchanged,
which can allow protected content to be rendered without passing the
expected middleware check.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">We now only honor internal route-parameter normalization
in trusted routing flows and ignore externally supplied parameter
encodings that should never have been accepted from ordinary
requests.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, enforce authorization
in route or page logic instead of relying solely on middleware path
matching.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-c4j6-fc7j-m34r">🚨
Next.js vulnerable to server-side request forgery in applications using
WebSocket upgrades</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">Self-hosted applications using the built-in Node.js server
can be vulnerable to server-side request forgery through crafted
WebSocket upgrade requests. An attacker can cause the server to proxy
requests to arbitrary internal or external destinations, which may
expose internal services or cloud metadata endpoints. Vercel-hosted
deployments are not affected.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">We now apply the same safety checks to WebSocket upgrade
handling that already existed for normal HTTP requests, so upgrade
requests are only proxied when routing has explicitly marked them as
safe external rewrites.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, do not expose the
origin server directly to untrusted networks. If WebSocket upgrades are
not required, block them at your reverse proxy or load balancer, and
restrict origin egress to internal networks and metadata services where
possible.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-h64f-5h5j-jqjh">🚨
Next.js has a Denial of Service in the Image Optimization API</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">When self-hosting Next.js with the default image loader,
the Image Optimization API fetches local images entirely into memory
without enforcing a maximum size limit. An attacker could cause
out-of-memory conditions by requesting large local assets from the <code
class="notranslate">/_next/image</code> endpoint that match the <code
class="notranslate">images.localPatterns</code> configuration (by
default, all patterns are allowed).</p>
<ul dir="auto">
<li>If you are using <code
class="notranslate">images.localPatterns</code>, only the patterns in
that array are impacted.</li>
<li>If you are using <code class="notranslate">images.unoptimized:
true</code>, you are NOT impacted.</li>
<li>If you are using <code class="notranslate">images.loader:
'custom'</code>, you are NOT impacted.</li>
<li>If you are using Vercel, you are NOT impacted.</li>
</ul>
<h3 dir="auto">Fix</h3>
<p dir="auto">We now apply response size limits consistently to internal
image fetches, not just external ones, and fail oversized responses
before they can exhaust process memory.</p>
<p dir="auto">This can be adjusted using the <code
class="notranslate">images.maximumResponseBody</code> configuration.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, avoid routing large
local assets through <code class="notranslate">/_next/image</code>,
disable image optimization for large or untrusted local files, or block
image optimization access to those assets at the edge.</p>
<p dir="auto">You can disable using the <code
class="notranslate">images.localPatterns: []</code> configuration. This
will still allow fetching remote images (which is not
impacted).</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-mg66-mrh9-m8jx">🚨
Next.js vulnerable to Denial of Service via connection exhaustion in
applications using Cache Components</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">Applications using Partial Prerendering through the Cache
Components feature can be vulnerable to connection exhaustion through
crafted POST requests to a server action. In affected configurations, a
malicious request can trigger a request-body handling deadlock that
leaves connections open for an extended period, consuming file
descriptors and server capacity until legitimate users are denied
service.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">We now treat the header used for resuming Partial
Prerendered requests as an internal-only header and strip it from
untrusted incoming requests. This header should never be accepted
directly from external clients.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, block requests that
would be handled by Next.js if they contain the <code
class="notranslate">Next-Resume</code> header at the
edge.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-gx5p-jg67-6x7h">🚨
Next.js has cross-site scripting in beforeInteractive scripts with
untrusted input</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">Applications that use <code
class="notranslate">beforeInteractive</code> scripts together with
untrusted content can be vulnerable to cross-site scripting. In affected
versions, serialized script content was not escaped safely before being
embedded into the document, which could allow attacker-controlled input
to break out of the intended script context and execute arbitrary
JavaScript in a visitor's browser.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">We now HTML-escape serialized <code
class="notranslate">beforeInteractive</code> script content before
embedding it into the page, preventing attacker-controlled content from
breaking out of the inline script boundary.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, do not pass untrusted
data into <code class="notranslate">beforeInteractive</code> scripts. If
that pattern is unavoidable, sanitize or escape the content before
embedding it.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-vfv6-92ff-j949">🚨
Next.js vulnerable to cache poisoning via collisions in React Server
Component cache-busting</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">React Server Component responses can be vulnerable to
cache poisoning in deployments that rely on shared caches with
insufficient response partitioning. In affected conditions, collisions
in the <code class="notranslate">_rsc</code> cache-busting value can
allow an attacker to poison cache entries so users receive the wrong
response variant for a given URL.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">We strengthened the <code class="notranslate">_rsc</code>
cache-busting mechanism to make practical collisions significantly
harder and to better separate response variants that should not share
cache entries.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, ensure intermediary
caches correctly honor <code class="notranslate">Vary</code> for
RSC-related request headers, or disable shared caching for affected RSC
responses until you can deploy a patched release.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-ffhc-5mcf-pf4q">🚨
Next.js vulnerable to cross-site scripting in App Router applications
using CSP nonces</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">App Router applications that rely on CSP nonces can be
vulnerable to stored cross-site scripting when deployed behind shared
caches. In affected versions, malformed nonce values derived from
request headers could be reflected into rendered HTML in an unsafe way,
allowing an attacker to poison cached responses and cause script
execution for later visitors.</p>
<h3 dir="auto">Fix</h3>
<p dir="auto">We now reject or ignore malformed nonce values before they
are embedded into HTML and apply stricter nonce sanitization so
request-derived nonce data cannot break out of the intended attribute
context.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">If you cannot upgrade immediately, strip inbound <code
class="notranslate">Content-Security-Policy</code> request headers from
untrusted traffic.</p></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-3g8h-86w9-wvmq">🚨
Next.js's Middleware / Proxy redirects can be cache-poisoned</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">Next.js uses the <code
class="notranslate">x-nextjs-data</code> request header for internal
data requests. On affected versions, an external client could send this
header on a normal request to a path handled by middleware that returns
a redirect.</p>
<p dir="auto">When that happened, the middleware/proxy could treat the
request as a data request and replace the standard <code
class="notranslate">Location</code> redirect header with the internal
<code class="notranslate">x-nextjs-redirect</code> header. Browsers do
not follow <code class="notranslate">x-nextjs-redirect</code>, so the
response became an unusable redirect for normal clients.</p>
<p dir="auto">If the application was deployed behind a CDN or reverse
proxy that caches 3xx responses without varying on this header, a single
attacker request could poison the cached redirect response for the
affected path. Subsequent visitors could then receive a cached redirect
response without a <code class="notranslate">Location</code> header,
causing a denial of service for that redirect path until the cache entry
expired or was purged.</p>
<h3 dir="auto">Affected scenarios</h3>
<p dir="auto">This affects applications that:</p>
<ul dir="auto">
<li>use middleware or proxy redirects</li>
<li>are deployed behind a caching CDN or reverse proxy</li>
<li>allow 3xx responses on those paths to be cached without
differentiating internal data requests from normal requests</li>
</ul>
<h3 dir="auto">Fix</h3>
<p dir="auto">The fix stops trusting <code
class="notranslate">x-nextjs-data</code> by itself for middleware
redirect handling. A request is now treated as an internal data request
only when it is validated as such by internal routing state, preserving
legitimate data-request redirect behavior while preventing external
header injection from changing normal redirect responses.</p>
<h3 dir="auto">Workarounds</h3>
<p dir="auto">Before upgrading, users can reduce risk by:</p>
<ul dir="auto">
<li>configuring the CDN or reverse proxy to vary its cache key on <code
class="notranslate">x-nextjs-data</code> for affected responses</li>
</ul></blockquote>
<h4><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">🚨
Next.js has a Middleware / Proxy bypass in App Router applications via
segment-prefetch routes - Incomplete Fix Follow-Up</a></h4>
<blockquote><h3 dir="auto">Impact</h3>
<p dir="auto">It was found that the fix addressing <a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">CVE-2026-44575</a>
did not apply to <code class="notranslate">middleware.ts</code> with
Turbopack. Refer to <a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">CVE-2026-44575</a>
for further details.</p>
<h3 dir="auto">References</h3>
<ul dir="auto">
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">CVE
CVE-2026-44575</a></li>
</ul></blockquote>
</details>

<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/vercel/next.js/releases/tag/v16.2.6">16.2.6</a></h4>

<blockquote><p dir="auto">This release contains security fixes for the
following advisories:</p>
<p dir="auto">High:</p>
<ul dir="auto">
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-8h8q-6873-q5fj">GHSA-8h8q-6873-q5fj:
Denial of Service with Server Components</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">GHSA-267c-6grr-h53f:
Middleware / Proxy bypass in App Router applications via
segment-prefetch routes</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-26hh-7cqf-hhc6">GHSA-26hh-7cqf-hhc6:
Middleware / Proxy bypass in App Router applications via
segment-prefetch routes - Incomplete Fix Follow-Up</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-mg66-mrh9-m8jx">GHSA-mg66-mrh9-m8jx:
Denial of Service via connection exhaustion in applications using Cache
Components</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-492v-c6pp-mqqv">GHSA-492v-c6pp-mqqv:
Middleware / Proxy bypass through dynamic route parameter
injection</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-c4j6-fc7j-m34r">GHSA-c4j6-fc7j-m34r:
Server-side request forgery in applications using WebSocket
upgrades</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-36qx-fr4f-26g5">GHSA-36qx-fr4f-26g5:
Middleware / Proxy bypass in Pages Router applications using
i18n</a></li>
</ul>
<p dir="auto">Moderate:</p>
<ul dir="auto">
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-ffhc-5mcf-pf4q">GHSA-ffhc-5mcf-pf4q:
Cross-site scripting in App Router applications using CSP
nonces</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-gx5p-jg67-6x7h">GHSA-gx5p-jg67-6x7h:
Cross-site scripting in beforeInteractive scripts with untrusted
input</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-h64f-5h5j-jqjh">GHSA-h64f-5h5j-jqjh:
Denial of Service in the Image Optimization API</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-wfc6-r584-vfw7">GHSA-wfc6-r584-vfw7:
Cache poisoning in React Server Component responses</a></li>
</ul>
<p dir="auto">Low:</p>
<ul dir="auto">
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-vfv6-92ff-j949">GHSA-vfv6-92ff-j949:
Cache poisoning via collisions in React Server Component
cache-busting</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-3g8h-86w9-wvmq">GHSA-3g8h-86w9-wvmq:
Middleware / Proxy redirects can be cache-poisoned</a></li>
</ul></blockquote>
<h4><a
href="https://github.com/vercel/next.js/releases/tag/v16.2.5">16.2.5</a></h4>

<blockquote><p dir="auto">This release contains security fixes for the
following advisories:</p>
<p dir="auto">High:</p>
<ul dir="auto">
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-8h8q-6873-q5fj">GHSA-8h8q-6873-q5fj:
Denial of Service with Server Components</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">GHSA-267c-6grr-h53f:
Middleware / Proxy bypass in App Router applications via
segment-prefetch routes</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-mg66-mrh9-m8jx">GHSA-mg66-mrh9-m8jx:
Denial of Service via connection exhaustion in applications using Cache
Components</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-492v-c6pp-mqqv">GHSA-492v-c6pp-mqqv:
Middleware / Proxy bypass through dynamic route parameter
injection</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-c4j6-fc7j-m34r">GHSA-c4j6-fc7j-m34r:
Server-side request forgery in applications using WebSocket
upgrades</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-36qx-fr4f-26g5">GHSA-36qx-fr4f-26g5:
Middleware / Proxy bypass in Pages Router applications using
i18n</a></li>
</ul>
<p dir="auto">Moderate:</p>
<ul dir="auto">
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-ffhc-5mcf-pf4q">GHSA-ffhc-5mcf-pf4q:
Cross-site scripting in App Router applications using CSP
nonces</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-gx5p-jg67-6x7h">GHSA-gx5p-jg67-6x7h:
Cross-site scripting in beforeInteractive scripts with untrusted
input</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-h64f-5h5j-jqjh">GHSA-h64f-5h5j-jqjh:
Denial of Service in the Image Optimization API</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-wfc6-r584-vfw7">GHSA-wfc6-r584-vfw7:
Cache poisoning in React Server Component responses</a></li>
</ul>
<p dir="auto">Low:</p>
<ul dir="auto">
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-vfv6-92ff-j949">GHSA-vfv6-92ff-j949:
Cache poisoning via collisions in React Server Component
cache-busting</a></li>
<li><a
href="https://bounce.depfu.com/github.com/vercel/next.js/security/advisories/GHSA-3g8h-86w9-wvmq">GHSA-3g8h-86w9-wvmq:
Middleware / Proxy redirects can be cache-poisoned</a></li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please let us
know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="2275bd8598...ee6e79b179">See
the full diff on Github</a>. The new version differs by 36 commits:</p>
<ul>
<li><a
href="ee6e79b179"><code>v16.2.6</code></a></li>
<li><a
href="afa053d9eb"><code>Turbopack:
Match proxy matchers with webpack implementation
(#93594)</code></a></li>
<li><a
href="97a154e5bb"><code>Turbopack:
Fix middleware matcher suffix (#93590)</code></a></li>
<li><a
href="83899bc891"><code>[backport]
Disable build caches for production/staging/force-preview deploys
(#93586)</code></a></li>
<li><a
href="7b222b9095"><code>[backport][test]
Pin package manager to patch versions (#93595)</code></a></li>
<li><a
href="a8dc24f1fe"><code>[backport]
Turbopack: more strict vergen setup (#93587)</code></a></li>
<li><a
href="766148f9cd"><code>v16.2.5</code></a></li>
<li><a
href="0dd94836a8"><code>fix:
add explicit checks for RSC header (#83) (#98)</code></a></li>
<li><a
href="d166096c39"><code>fix
proxy matching for segment prefetch URLs (#89) (#96)</code></a></li>
<li><a
href="9d50c0b719"><code>Strip
next-resume header from incoming requests (#92)</code></a></li>
<li><a
href="df7ab5ad72"><code>fix:
skip internal param normalization in unsupported
environments</code></a></li>
<li><a
href="ed41d1d454"><code>Move
htmlescape to shared/lib (#91)</code></a></li>
<li><a
href="b4c6705c70"><code>Ignore
malformed CSP nonce headers</code></a></li>
<li><a
href="5b194ee2d4"><code>router-server:
guard upgrade proxy against absolute-url SSRF (#77)</code></a></li>
<li><a
href="cb171d7494"><code>Fix
i18n middleware matching for default-locale data routes
(#82)</code></a></li>
<li><a
href="89e995431a"><code>[16.x]
Type hardening and performance improvements (#80)</code></a></li>
<li><a
href="66f6017f15"><code>Escape
properties for beforeInteractive scripts (#86)</code></a></li>
<li><a
href="3d98505a24"><code>[backport]
fix: preserve HTTP access fallbacks during prerender recovery
(#93470)</code></a></li>
<li><a
href="bb5ada6e38"><code>[backport]
[test] Deflake `instant-navs-devtools` (#93534)</code></a></li>
<li><a
href="f1c11203d5"><code>[backport]
Fix double-encoding of URL pathname parts in client param parsing
(#93506)</code></a></li>
<li><a
href="2d08397b3d"><code>[backport]
fix accidental test duplication (#93507)</code></a></li>
<li><a
href="75d19ecbb3"><code>[backport]
Include deployment id in `cacheHandlers` keys (#93471)</code></a></li>
<li><a
href="7ab1e2e93d"><code>CI:
Download and run self-contained datadog-ci instead of using pnpm dlx or
npx (#92546)</code></a></li>
<li><a
href="084f2bcf19"><code>[ci]:
trigger signed release commit via API (#93285)</code></a></li>
<li><a
href="a3bb370b00"><code>[ci]:
app-based release workflow (#93245)</code></a></li>
<li><a
href="6e23383c56"><code>[ci]:
add environment to publishRelease flow (#93093)</code></a></li>
<li><a
href="f40b8876e6"><code>[ci]:
remove publish token in favor of OIDC (#93065)</code></a></li>
<li><a
href="f6bda26ef9"><code>Fix
fallback route params case in app-page handler (#93109)</code></a></li>
<li><a
href="70defda2a8"><code>[ci]:
switch to GitHub runners (#93164)</code></a></li>
<li><a
href="af0e96ba23"><code>Fix
invalid HTML response for route-level RSC requests in deployment adapter
(#91541)</code></a></li>
<li><a
href="2cdb7ed34f"><code>[tests]:
fix cache-components.test.ts type error (#93113)</code></a></li>
<li><a
href="8cd3fdc111"><code>test:
scope css data-url typing to fixture (#91877)</code></a></li>
<li><a
href="6fd09bf8ab"><code>Patch
setHeader for direct route handlers (#93101)</code></a></li>
<li><a
href="688ed31e21"><code>Strengthen
_rsc cache-busting param (#92755)</code></a></li>
<li><a
href="62ef305096"><code>fix(next/image):
ensure `images.maximumResponseBody` applies to local images too
(#92920)</code></a></li>
<li><a
href="15341fdf49"><code>Ensure
x-nextjs-data header is only set during resolve (#92752)</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-05-12 17:12:36 +02:00
Robin Malfait
54d6b05b44
move localRequire to else branch 2026-05-12 11:19:48 +02:00
Antoine Lethimonnier
fc432e0fd5
fix(node): prefer Module#registerHooks over Module#register (#20028)
<!--

👋 Hey, thanks for your interest in contributing to Tailwind!

**Please ask first before starting work on any significant new
features.**

It's never a fun experience to have your pull request declined after
investing a lot of time and effort into a new feature. To avoid this
from happening, we request that contributors create a discussion to
first discuss any significant new features.

For more info, check out the contributing guide:


https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md

-->

## Summary

<!--

Provide a summary of the issue and the changes you're making. How does
your change solve the problem?

-->

Fix this warning when building apps with TailwindCSS with Node 26+:
```
(node:25346) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
    at node:internal/util:129:11
    at Module.register (node:internal/modules/esm/loader:969:3)
    at file:///Users/antoine/Developer/my-app/node_modules/.pnpm/@tailwindcss+node@4.3.0/node_modules/@tailwindcss/node/dist/index.mjs:18:214
    at ...
```

This PR:
- Correctly prefers using `Module#registerHooks` instead of
`Module#register` by checking its availability at runtime
- Adjusts the exports of the hooks’ file by creating a synchronous
version for the new API
- Remove now unused exports from the `package.json`, relying on the
[recommended usage in the
docs](https://nodejs.org/docs/latest/api/module.html#registration-of-asynchronous-customization-hooks)
for the `Module#register` calls

## Test plan

<!--

Explain how you tested your changes. Include the exact commands that you
used to verify the change works and include screenshots/screen
recordings of the update behavior in the browser if applicable.

-->

I'd be happy to ensure this works correctly on my end before merging
this, but it's not as trivial to test locally as a logic fix. Can you
guide me through what I need to do to test this?

I extensively based my change on the docs, following those guides:
- [Fixing imports for
`Module#register`](https://nodejs.org/docs/latest/api/module.html#registration-of-asynchronous-customization-hooks)
- [Using the new `Module#registerHooks`
function](https://nodejs.org/docs/latest/api/module.html#registration-of-synchronous-customization-hooks)

(and other more detailed sections of the same docs page)

---

Fixes #19893
Closes #19907

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-05-11 14:25:28 +00:00
depfu[bot]
ae96721fc5
Update @tybys/wasm-util 0.10.1 → 0.10.2 (minor) (#20031)
Here is everything you need to know about this update. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ @​tybys/wasm-util (0.10.1 → 0.10.2) ·
[Repo](https://github.com/toyobayashi/wasm-util)





Sorry, we couldn't find anything useful about this release.











---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-05-11 12:09:58 +02:00
Robin Malfait
f9216b2b8c
update changelog 2026-05-08 22:18:22 +02:00
Robin Malfait
588bd7371f
4.3.0 (#20023) 2026-05-08 22:03:59 +02:00
Robin Malfait
59936c6cbb
Add tab-* utilities (#20022)
This PR adds new `tab-*` utilities.

The `tab-*` utilities set the `tab-size` property. They support positive
integer bare values, and arbitrary values:

| Class | CSS |
| -- | -- |
| `tab-2` | `tab-size: 2;` |
| `tab-[12px]` | `tab-size: 12px;` |

This also adds `tab-size` to the property order near the other text
layout properties.

## Test plan

1. Added new `tab-*` utility tests
2. Updated the intellisense snapshot
3. Other existing tests still pass
2026-05-08 21:22:07 +02:00
Robin Malfait
90a2373620
add zoom-* utilities (#20020)
This PR adds new `zoom-*` utilities.

The `zoom-*` utilities accept bare values that are transformed into `%`
based values, and arbitrary values:

| Class | CSS |
| -- | -- |
| `zoom-50` | `zoom: 50%;` |
| `zoom-[1.1]` | `zoom: 1.1;` |
| `zoom-(--value)` | `zoom: var(--value);` |


This also adds the `zoom` property after the `transform` related
properties. Initially I added it right after `scale`, because logically
they are close together. But then `zoom-*` would sit between `scale` and
other tranfsorm related properties which is a bit weird. Instead, I
moved it after `transform`.

## Test plan

1. Added new zoom based tests
2. All other tests still pass
2026-05-08 21:15:59 +02:00
Robin Malfait
2e1ccf7f11
Add scrollbar-gutter-* utilities (#20018)
This PR adds new `scrollbar-gutter-*` utilities. The API looks like
this:

| Class | CSS |
| -- | -- |
| `scrollbar-gutter-auto` | `scrollbar-gutter: auto` |
| `scrollbar-gutter-stable` | `scrollbar-gutter: stable` |
| `scrollbar-gutter-both` | `scrollbar-gutter: stable both-edges` |
2026-05-08 21:13:06 +02:00
depfu[bot]
c00da894dd
Update listhen 1.9.1 → 1.10.0 (minor) (#20017)
Here is everything you need to know about this update. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ listhen (1.9.1 → 1.10.0) ·
[Repo](https://github.com/unjs/listhen) ·
[Changelog](https://github.com/unjs/listhen/blob/main/CHANGELOG.md)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/unjs/listhen/releases/tag/v1.10.0">1.10.0</a></h4>

<blockquote><p dir="auto"><a
href="https://bounce.depfu.com/github.com/unjs/listhen/compare/v1.9.1...v1.10.0">compare
changes</a></p>
<h3 dir="auto">🚀 Enhancements</h3>
<ul dir="auto">
<li>Support <code class="notranslate">extraURLs</code> and detect <a
href="https://portless.sh/">portless</a> from env by default (<a
href="https://bounce.depfu.com/github.com/unjs/listhen/pull/228">#228</a>)</li>
</ul>
<h3 dir="auto">🩹 Fixes</h3>
<ul dir="auto">
<li>Filter IPv4 link-local addresses from network interfaces (<a
href="https://bounce.depfu.com/github.com/unjs/listhen/pull/226">#226</a>)</li>
<li>Do not use fallback port in production (<a
href="https://bounce.depfu.com/github.com/unjs/listhen/pull/223">#223</a>)</li>
</ul>
<h3 dir="auto">❤️ Contributors</h3>
<ul dir="auto">
<li>Kricsleo (<a
href="https://bounce.depfu.com/github.com/kricsleo">@kricsleo</a>)</li>
<li>Tim Krajcar (<a
href="https://bounce.depfu.com/github.com/tkrajcar">@tkrajcar</a>)</li>
<li>Max (<a
href="https://bounce.depfu.com/github.com/onmax">@onmax</a>)</li>
<li>Pooya Parsa (<a
href="https://bounce.depfu.com/github.com/pi0">@pi0</a>)</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please let us
know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="60ba9f2ae2...33c98f262d">See
the full diff on Github</a>. The new version differs by 5 commits:</p>
<ul>
<li><a
href="33c98f262d"><code>fix:
do not use fallback port in production (#223)</code></a></li>
<li><a
href="49ef95e7a7"><code>fix:
filter IPv4 link-local addresses from network interfaces
(#226)</code></a></li>
<li><a
href="de2d49ae00"><code>chore(deps):
update all non-major dependencies (#221)</code></a></li>
<li><a
href="f341eb9f76"><code>feat:
support `extraURLs` and detect portless by env by default
(#228)</code></a></li>
<li><a
href="402c52df87"><code>chore:
update deps</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

[ci-all]

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2026-05-07 12:43:28 +00:00