Commit Graph

52 Commits

Author SHA1 Message Date
leaysgur f7acdc0bd9 fix(formatter): treat a JSDoc cast target as opaque in chain layouts (#26375)
Fixes #20181
2026-09-07 04:56:37 +00:00
leaysgur b3613b176a test(oxfmt): use svelte repo for jsdoc conformance fixture (#26371)
Add `svelte` repo for JSDoc conformance.
2026-09-07 04:56:36 +00:00
leaysgur 3b054de895 fix(formatter_graphql): align comment printing after open { (#26271)
Aligned the handling of line comments immediately following an opening `{`.

(For GraphQL only,) previously kept their own line, now matches other languages by inserting a line break and treating them as leading comments for the next element.

This brings it in line with Prettier's style. The only drawback is that the behavior of `-line` style comments. However, since most of these can be replaced with `-next-line` style comments, we are going to standardize on this consistent behavior for now.

prettier/prettier#1267 (won't fix)
2026-09-03 08:17:35 +00:00
leaysgur deab23cac2 test(oxfmt): consolidate redundant conformance edge-case fixtures (#26127)
Consolidate redundant fixtures.
2026-08-27 05:34:00 +00:00
leaysgur 181953b92d docs(oxfmt,formatter_core,formatter,formatter_yaml,formatter_css,formatter_graphql): extract DIVERGENCES.md out from AGENTS.md (#26121)
- Extract "known divergences" section from `AGENTS.md` to explicit `DIVERGENCES.md` with code example
- Update all anchors
- Add missing pinned fixtures
2026-08-27 05:33:58 +00:00
leaysgur faf11d9d6e fix(formatter_yaml): keep trailing whitespace in block scalars (#26072)
WS inside block scalar value is content, should be preserved.
2026-08-25 04:44:04 +00:00
Yuji Sugiura 223e7855fe docs(oxfmt/conformance): Update notes on conformance (#25757)
Filled current state.
2026-08-17 09:25:11 +09:00
leaysgur 6ef3984410 refactor(ci): self-provision prettier suite in oxc_formatter_tests (#25467)
Remove the Prettier related stuff from the conformance, which is purely aimed at JS/TS.

Instead, `oxc_formatter_tests` manage Prettier's test fixtures along with Oxfmt.
2026-08-12 00:40:59 +00:00
leaysgur 033ddf6d38 refactor(oxfmt,formatter): simplify js-in-html-in-js handling (#25464)
Prettier uses the `conditionalGroup` IR for JS and YAML.

When this appeared in JS(containing `conditionalGroup`)-in-HTML(`script` tags)-in-JS (`oxc_formatter`), we previously bypassed the `Doc` to IR conversion.

This PR adds support for this conversion and removes the string format fallback path.
2026-08-10 06:02:17 +00:00
leaysgur a9e76e9e1f fix(oxfmt): rework tsx-in-vue support (#25106)
Follow-up to #25063.

tsx-in-vue was supported in #25063 with a parse-retry (ts fails → retry as tsx), chosen to keep the common ts path single-parse.

However, this leaves a hole: a `lang="tsx"` block without JSX parses fine as plain ts, so the retry never fires and the lone generic comma is removed:

```vue
<script setup lang="tsx">
const identity = <T,>(x: T) => x; // → <T>(x: T) => x, breaks as TS17008
</script>
```

Since parse failure fundamentally cannot detect this, the only fix is to scan the `lang` declaration itself.

The JS host now scans the SFC once per file and passes `_oxfmtVueScriptLang: "tsx"` down to `textToDoc()`. This makes the retry obsolete, so it is removed.

This PR also settles the comma policy: keep it only where it is load-bearing.

- JSX grammar (`<T>` would be a JSX opener)
- and `.mts/.cts` (TS7060, #18928)

and remove it everywhere else, keyed on the grammar, regardless of context.

Deliberate divergence: Prettier keys on filepath and keeps the comma in ts-in-vue/svelte (while its own ts-in-md embed uses `dummy.ts` as `filepath` and removes it). Plain-TS sources now behave identically wherever they live.
2026-07-30 05:27:07 +00:00
leaysgur 1b57f783fb feat(oxfmt): support tsx-in-vue (#25063)
Part of #16608, closes #25046.

---

Even with a simple regexp, I don't want to impact the performance of the vast majority of ts-in-vue paths.

With this approach, only tsx-in-vue use cases will be affected, and even that will be kept to a minimum since it can be handled entirely on the Rust side. (JS <-> Rust roundtrip is also slow)
2026-07-29 07:27:43 +00:00
leaysgur f56009a676 fix(oxfmt): correct prose about comment width in fits measurement (#25054)
Audited every formatter crate against the trailing-comment width discipline.

- same-line trailing line comments ride `line_suffix` and are excluded from the fits measurement
- while trailing block comments print inline and count

Corrected the prose that misstated it.
2026-07-29 02:57:17 +00:00
leaysgur 22fdda4634 fix(oxfmt/conformance): fix typo (#25053)
Typo...
2026-07-29 02:57:17 +00:00
leaysgur 62a5ceaa4e test(oxfmt): add yaml conformance fixtures (#24892) 2026-07-28 07:43:14 +00:00
leaysgur 34c944f32f test(oxfmt/conformance): serialize fixture download of the same repo (#25015)
Fixes degit race issue: https://github.com/oxc-project/oxc/actions/runs/30334528300/job/90203690852?pr=24892
2026-07-28 07:31:08 +00:00
leaysgur e037709234 fix(formatter): stop preserving indent for embedded template exprs (#24972)
Fixes idempotency issue in html|css-in-js. (= align gql-in-js behavior)
2026-07-27 08:04:57 +00:00
leaysgur ae1a39b71c fix(formatter_css): align wrapped selector-arg indent (#24971)
Fixes #24843

---

Tracing back to the root cause, this is also related to what had diverged because of Prettier's inconsistent behavior.
Since I cannot determine for sure how it should be output in more complex cases (like that issue) at this point, decided to revert to being Prettier-compatible.
2026-07-27 06:47:19 +00:00
leaysgur dbf85def42 refactor(formatter_graphql): rework comment printing (#24970)
Also fixes #24927

- rework comment printing to follow the rules and align with other formatters
- bump `oxc-graphql-parser`
  - to track comments inside a node's span more accurately
2026-07-27 05:31:01 +00:00
leaysgur 33e32d8e51 fix(formatter_css): use line_suffix for EOL line comment (#24580)
The same motivation as #24579
2026-07-16 01:37:31 +00:00
leaysgur 0ccd8a14b7 feat(formatter_graphql): update oxc-graphql-parser 0.0.5 (#24106)
Part of #23923

Supports more syntax like:

- Fragment arguments
- Extends directives
2026-07-03 10:11:20 +00:00
leaysgur cd2452e170 fix(formatter_css): align SCSS output to Prettier 3.9.1 (#24097)
Part of #23923

Addressed these changes:

- https://github.com/prettier/prettier/blob/79f6cdfd9873a91be9b25c9c6a41d26dcd9a6656/changelog_unreleased/scss/18530.md
- https://github.com/prettier/prettier/blob/79f6cdfd9873a91be9b25c9c6a41d26dcd9a6656/changelog_unreleased/scss/18535.md
- https://github.com/prettier/prettier/blob/79f6cdfd9873a91be9b25c9c6a41d26dcd9a6656/changelog_unreleased/scss/19091.md

and also fixed minor formatting diffs regarding to trailing comment in map.

```scss
$m: (
  a: 1,
  b: 2, // THIS
);
```
2026-07-03 07:29:32 +00:00
leaysgur 7d663d3fd0 chore(oxfmt): update prettier to 3.9.1 (#23931)
Part of https://github.com/oxc-project/oxc/issues/23923
2026-07-03 07:12:06 +00:00
leaysgur cc8db2b11c refactor(formatter_graphql): fix up code and comments (#23488)
Finally fixed up Fable's work.
2026-06-29 03:15:27 +00:00
leaysgur af77116ac2 test(oxfmt): add css + less + scss conformance (#23435)
- Added a few repos for oxfmt conformance
  - CSS: mantine, docsaurous
  - LESS: NG-ZORRO
  - SCSS: Reuse vben, gitlab
2026-06-29 03:15:27 +00:00
leaysgur f5a49cd383 test(oxfmt): add gitlab as graphql conformance (#23421)
- Add `gitlabhq/gitlab` repo to oxfmt conformance
  - There are 700~ graphql files
- Once `gitlab` repo is migrated Oxfmt, we can add it to ecosystem-ci
2026-06-29 03:15:26 +00:00
leaysgur 48e2d7855b fix(formatter_css): improve major prettier diffs (#23327)
Fixed many formatting diffs by checking real world repo.
2026-06-29 03:15:26 +00:00
leaysgur accbc49def feat(oxfmt)!: format parser:css,less,scss files + css-in-js by oxc_formatter_css (#23321)
- Use `oxc_formatter_css` from Oxfmt to handle CSS/LESS/SCSS files
- css-in-js is also handled by `oxc_formatter_css`
  - But it will fallback to Prettier if formatting failed
  - No fallback for no-embedded path
- At the point of this PR, it will fallback to Prettier when tailwind is required to format

NOTE: Both fallback will be removed in later PR.

In that sense, as a result of this series of PRs, Oxfmt's CSS support will no longer be 100% compatible compared to Prettier.

Since the parsers used are also different, it will no longer be possible to support certain postcss-plugin-specific syntax, invalid syntax or legacy syntax.

> [!WARNING]
> TODO: Move fork under `oxc-project` org and replace refs
2026-06-29 03:15:24 +00:00
leaysgur a7fd35e7df refactor(oxfmt): handle gql-in-js by oxc_formatter_graphql (#23319)
- To use `oxc_formatter_graphql` in gql-in-js context, ground level refactoring was needed
- Extracted common logic for handling embeddings into `oxc_formatter_core`
- Updated other `xxx-in-js` callers to reflect these changes
- Added a `format_to_ir()` method to each formatter in addition to the existing `format()` method
2026-06-29 02:55:31 +00:00
leaysgur 439214b97c chore(oxfmt): update prettier-plugin-svelte@4.1.1 (#23696) 2026-06-22 01:11:28 +00:00
renovate[bot] cdc0ac4aef chore(deps): update npm packages (#23087)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Adoption](https://docs.renovatebot.com/merge-confidence/) |
[Passing](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|
|
[@arethetypeswrong/core](https://redirect.github.com/arethetypeswrong/arethetypeswrong.github.io)
([source](https://redirect.github.com/arethetypeswrong/arethetypeswrong.github.io/tree/HEAD/packages/core))
| [`0.18.2` →
`0.18.3`](https://renovatebot.com/diffs/npm/@arethetypeswrong%2fcore/0.18.2/0.18.3)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@arethetypeswrong%2fcore/0.18.3?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@arethetypeswrong%2fcore/0.18.3?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@arethetypeswrong%2fcore/0.18.2/0.18.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@arethetypeswrong%2fcore/0.18.2/0.18.3?slim=true)
|
| [@codspeed/vitest-plugin](https://codspeed.io)
([source](https://redirect.github.com/CodSpeedHQ/codspeed-node)) |
[`5.4.0` →
`5.5.0`](https://renovatebot.com/diffs/npm/@codspeed%2fvitest-plugin/5.4.0/5.5.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@codspeed%2fvitest-plugin/5.5.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@codspeed%2fvitest-plugin/5.5.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@codspeed%2fvitest-plugin/5.4.0/5.5.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@codspeed%2fvitest-plugin/5.4.0/5.5.0?slim=true)
|
|
[@typescript-eslint/parser](https://typescript-eslint.io/packages/parser)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser))
| [`8.60.0` →
`8.60.1`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.60.0/8.60.1)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/8.60.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fparser/8.60.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fparser/8.60.0/8.60.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/8.60.0/8.60.1?slim=true)
|
|
[@typescript-eslint/scope-manager](https://typescript-eslint.io/packages/scope-manager)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/scope-manager))
| [`8.60.0` →
`8.60.1`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fscope-manager/8.60.0/8.60.1)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fscope-manager/8.60.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fscope-manager/8.60.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fscope-manager/8.60.0/8.60.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fscope-manager/8.60.0/8.60.1?slim=true)
|
| [@typescript-eslint/visitor-keys](https://typescript-eslint.io)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/visitor-keys))
| [`8.60.0` →
`8.60.1`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fvisitor-keys/8.60.0/8.60.1)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fvisitor-keys/8.60.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fvisitor-keys/8.60.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fvisitor-keys/8.60.0/8.60.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fvisitor-keys/8.60.0/8.60.1?slim=true)
|
| [@vitest/browser](https://vitest.dev/guide/browser/)
([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/browser))
| [`4.1.7` →
`4.1.8`](https://renovatebot.com/diffs/npm/@vitest%2fbrowser/4.1.7/4.1.8)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@vitest%2fbrowser/4.1.8?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vitest%2fbrowser/4.1.8?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vitest%2fbrowser/4.1.7/4.1.8?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vitest%2fbrowser/4.1.7/4.1.8?slim=true)
|
|
[@vitest/browser-playwright](https://vitest.dev/config/browser/playwright)
([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright))
| [`4.1.7` →
`4.1.8`](https://renovatebot.com/diffs/npm/@vitest%2fbrowser-playwright/4.1.7/4.1.8)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@vitest%2fbrowser-playwright/4.1.8?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vitest%2fbrowser-playwright/4.1.8?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vitest%2fbrowser-playwright/4.1.7/4.1.8?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vitest%2fbrowser-playwright/4.1.7/4.1.8?slim=true)
|
| [degit](https://redirect.github.com/Rich-Harris/degit) | [`3.3.2` →
`3.4.1`](https://renovatebot.com/diffs/npm/degit/3.3.2/3.4.1) |
![age](https://developer.mend.io/api/mc/badges/age/npm/degit/3.4.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/degit/3.4.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/degit/3.3.2/3.4.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/degit/3.3.2/3.4.1?slim=true)
|
| [eslint](https://eslint.org)
([source](https://redirect.github.com/eslint/eslint)) | [`10.4.0` →
`10.4.1`](https://renovatebot.com/diffs/npm/eslint/10.4.0/10.4.1) |
![age](https://developer.mend.io/api/mc/badges/age/npm/eslint/10.4.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint/10.4.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint/10.4.0/10.4.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint/10.4.0/10.4.1?slim=true)
|
|
[prettier-plugin-svelte](https://redirect.github.com/sveltejs/prettier-plugin-svelte)
| [`4.0.1` →
`4.1.0`](https://renovatebot.com/diffs/npm/prettier-plugin-svelte/4.0.1/4.1.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/prettier-plugin-svelte/4.1.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier-plugin-svelte/4.1.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier-plugin-svelte/4.0.1/4.1.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier-plugin-svelte/4.0.1/4.1.0?slim=true)
|
| [svelte](https://svelte.dev)
([source](https://redirect.github.com/sveltejs/svelte/tree/HEAD/packages/svelte))
| [`5.55.10` →
`5.56.1`](https://renovatebot.com/diffs/npm/svelte/5.55.10/5.56.1) |
![age](https://developer.mend.io/api/mc/badges/age/npm/svelte/5.56.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/svelte/5.56.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/svelte/5.55.10/5.56.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/svelte/5.55.10/5.56.1?slim=true)
|
| [tsx](https://tsx.hirok.io)
([source](https://redirect.github.com/privatenumber/tsx)) | [`4.22.3` →
`4.22.4`](https://renovatebot.com/diffs/npm/tsx/4.22.3/4.22.4) |
![age](https://developer.mend.io/api/mc/badges/age/npm/tsx/4.22.4?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/tsx/4.22.4?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/tsx/4.22.3/4.22.4?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/tsx/4.22.3/4.22.4?slim=true)
|
| [type-fest](https://redirect.github.com/sindresorhus/type-fest) |
[`5.6.0` →
`5.7.0`](https://renovatebot.com/diffs/npm/type-fest/5.6.0/5.7.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/type-fest/5.7.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/type-fest/5.7.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/type-fest/5.6.0/5.7.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/type-fest/5.6.0/5.7.0?slim=true)
|
| [vitest](https://vitest.dev)
([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/vitest))
| [`4.1.7` →
`4.1.8`](https://renovatebot.com/diffs/npm/vitest/4.1.7/4.1.8) |
![age](https://developer.mend.io/api/mc/badges/age/npm/vitest/4.1.8?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vitest/4.1.8?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vitest/4.1.7/4.1.8?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest/4.1.7/4.1.8?slim=true)
|
|
[vscode-languageserver-protocol](https://redirect.github.com/Microsoft/vscode-languageserver-node)
([source](https://redirect.github.com/Microsoft/vscode-languageserver-node/tree/HEAD/protocol))
| [`3.17.5` →
`3.18.0`](https://renovatebot.com/diffs/npm/vscode-languageserver-protocol/3.17.5/3.18.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/vscode-languageserver-protocol/3.18.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vscode-languageserver-protocol/3.18.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vscode-languageserver-protocol/3.17.5/3.18.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vscode-languageserver-protocol/3.17.5/3.18.0?slim=true)
|

---

### Release Notes

<details>
<summary>arethetypeswrong/arethetypeswrong.github.io
(@&#8203;arethetypeswrong/core)</summary>

###
[`v0.18.3`](https://redirect.github.com/arethetypeswrong/arethetypeswrong.github.io/blob/HEAD/packages/core/CHANGELOG.md#0183)

##### Patch Changes

-
[`14e61d5`](https://redirect.github.com/arethetypeswrong/arethetypeswrong.github.io/commit/14e61d5):
Update [@&#8203;types/node](https://redirect.github.com/types/node), use
[@&#8203;typescript/native-preview](https://redirect.github.com/typescript/native-preview)
for local build/check
-
[`25031aa`](https://redirect.github.com/arethetypeswrong/arethetypeswrong.github.io/commit/25031aa):
- Fix "Cannot read properties of undefined (reading 'filename')" caused
by fflate 0.8.3
([#&#8203;258](https://redirect.github.com/arethetypeswrong/arethetypeswrong.github.io/issues/258))
  - Bump fflate to ^0.8.3

</details>

<details>
<summary>CodSpeedHQ/codspeed-node
(@&#8203;codspeed/vitest-plugin)</summary>

###
[`v5.5.0`](https://redirect.github.com/CodSpeedHQ/codspeed-node/releases/tag/v5.5.0)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/codspeed-node/compare/v5.4.0...v5.5.0)

### Highlights

We are introducing `@codspeed/playwright`, for walltime benchmarking and
profiling of end to end browser applications through playwright.

Here's an example usage, but head to the
[docs](https://codspeed.io/docs/benchmarks/nodejs/playwright) for more
information

```typescript
import { bench, type Page } from "@&#8203;codspeed/playwright-plugin";
import electronExecutable from "electron";
import path from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const appRoot = path.resolve(__dirname, "..");

async function waitUntilSettled(page: Page): Promise<void> {
  await page.waitForFunction(() => {
    const main = document.getElementById("main");
    return !!main && !main.classList.contains("loading");
  });
}

await bench(
  "inbox-search-archive-threads",
  async ({ page }) => {
    await page.fill("#search", "update");
    await waitUntilSettled(page);

    await page.click("#select-visible-btn");
    await page.click("#archive-btn");
    await waitUntilSettled(page);

    await page.click('#sidebar nav button[data-view="threads"]');
    await waitUntilSettled(page);
  },
  {
    target: {
      kind: "electron",
      appPath: path.join(appRoot, "out/main/index.js"),
      cwd: appRoot,
    },
    beforeRound: async ({ page }) => {
      page.setDefaultTimeout(180_000);
      await page.waitForSelector("#main");
      await waitUntilSettled(page);
    },
  },
);
```

Note: this plugin is only compatible with the walltime instrument.

#### What's Changed

- Add playwright profiling package by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[#&#8203;80](https://redirect.github.com/CodSpeedHQ/codspeed-node/pull/80)

**Full Changelog**:
<https://github.com/CodSpeedHQ/codspeed-node/compare/v5.4.0...v5.5.0>

</details>

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/parser)</summary>

###
[`v8.60.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8601-2026-06-01)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.60.0...v8.60.1)

This was a version bump only for parser to align it with other projects,
there were no code changes.

See [GitHub
Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.60.1)
for more information.

You can read about our [versioning
strategy](https://typescript-eslint.io/users/versioning) and
[releases](https://typescript-eslint.io/users/releases) on our website.

</details>

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/scope-manager)</summary>

###
[`v8.60.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/scope-manager/CHANGELOG.md#8601-2026-06-01)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.60.0...v8.60.1)

This was a version bump only for scope-manager to align it with other
projects, there were no code changes.

See [GitHub
Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.60.1)
for more information.

You can read about our [versioning
strategy](https://typescript-eslint.io/users/versioning) and
[releases](https://typescript-eslint.io/users/releases) on our website.

</details>

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/visitor-keys)</summary>

###
[`v8.60.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/visitor-keys/CHANGELOG.md#8601-2026-06-01)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.60.0...v8.60.1)

This was a version bump only for visitor-keys to align it with other
projects, there were no code changes.

See [GitHub
Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.60.1)
for more information.

You can read about our [versioning
strategy](https://typescript-eslint.io/users/versioning) and
[releases](https://typescript-eslint.io/users/releases) on our website.

</details>

<details>
<summary>vitest-dev/vitest (@&#8203;vitest/browser)</summary>

###
[`v4.1.8`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v4.1.8)

[Compare
Source](https://redirect.github.com/vitest-dev/vitest/compare/v4.1.7...v4.1.8)

#####    🐞 Bug Fixes

- **browser**:
- Disable client `cdp` API when `allowWrite/allowExec: false` \[backport
to v4]  -  by [@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa)
and **Codex** in
[#&#8203;10450](https://redirect.github.com/vitest-dev/vitest/issues/10450)
[<samp>(e4067)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/e4067b3b1)
- Remove orphaned Playwright route when same module is mocked via
multiple ids \[backport to v4]  -  by
[@&#8203;toxik](https://redirect.github.com/toxik) and
[@&#8203;Zelys-DFKH](https://redirect.github.com/Zelys-DFKH) in
[#&#8203;10474](https://redirect.github.com/vitest-dev/vitest/issues/10474)
[<samp>(675b4)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/675b4343f)

#####     [View changes on
GitHub](https://redirect.github.com/vitest-dev/vitest/compare/v4.1.7...v4.1.8)

</details>

<details>
<summary>Rich-Harris/degit (degit)</summary>

###
[`v3.4.1`](https://redirect.github.com/Rich-Harris/degit/compare/v3.4.0...v3.4.1)

[Compare
Source](https://redirect.github.com/Rich-Harris/degit/compare/v3.4.0...v3.4.1)

###
[`v3.4.0`](https://redirect.github.com/Rich-Harris/degit/compare/v3.3.2...v3.4.0)

[Compare
Source](https://redirect.github.com/Rich-Harris/degit/compare/v3.3.2...v3.4.0)

</details>

<details>
<summary>eslint/eslint (eslint)</summary>

###
[`v10.4.1`](https://redirect.github.com/eslint/eslint/releases/tag/v10.4.1)

[Compare
Source](https://redirect.github.com/eslint/eslint/compare/v10.4.0...v10.4.1)

#### Bug Fixes

-
[`e557467`](https://redirect.github.com/eslint/eslint/commit/e557467db7496220eebcbe2ac5ea6d38c12bb1ec)
fix: update `@eslint/plugin-kit` version to 0.7.2
([#&#8203;20930](https://redirect.github.com/eslint/eslint/issues/20930))
(Francesco Trotta)
-
[`d4ce898`](https://redirect.github.com/eslint/eslint/commit/d4ce898796ca22c3b96aa70d3014cb85f4bac1cd)
fix: propagate failures from delegated commands
([#&#8203;20917](https://redirect.github.com/eslint/eslint/issues/20917))
(Minh Vu)
-
[`f4f3507`](https://redirect.github.com/eslint/eslint/commit/f4f3507460bc016b5be979c05d2969793f570cbf)
fix: prefer-arrow-callback invalid autofix with newline after `async`
([#&#8203;20916](https://redirect.github.com/eslint/eslint/issues/20916))
(kuldeep kumar)
-
[`c5bc78b`](https://redirect.github.com/eslint/eslint/commit/c5bc78b37e08b9054a11f0cc2d81808bb24acb85)
fix: false positive for reference in `finally` block
([#&#8203;20655](https://redirect.github.com/eslint/eslint/issues/20655))
(Tanuj Kanti)
-
[`27538c0`](https://redirect.github.com/eslint/eslint/commit/27538c01f5df4e9306f6f4ba867b2dd6307fae59)
fix: add missing CodePath and CodePathSegment types
([#&#8203;20853](https://redirect.github.com/eslint/eslint/issues/20853))
(Pixel998)

#### Documentation

-
[`61b0add`](https://redirect.github.com/eslint/eslint/commit/61b0add61ffc52665562be7bb96f526690a78b30)
docs: remove deprecated rule from related rules of `max-params`
([#&#8203;20921](https://redirect.github.com/eslint/eslint/issues/20921))
(Tanuj Kanti)
-
[`305d5b9`](https://redirect.github.com/eslint/eslint/commit/305d5b91aeac24d36fde42f75625a8f183d4ce43)
docs: remove deprecated rules from related rules section
([#&#8203;20911](https://redirect.github.com/eslint/eslint/issues/20911))
(Tanuj Kanti)
-
[`49b0202`](https://redirect.github.com/eslint/eslint/commit/49b0202d01918b8061720d586dffd7c68047090c)
docs: fix `display: none` of ad
([#&#8203;20901](https://redirect.github.com/eslint/eslint/issues/20901))
(Tanuj Kanti)
-
[`9067f94`](https://redirect.github.com/eslint/eslint/commit/9067f9492ec998afc5b4f057a477ecf6ebd45e44)
docs: switch build to Node.js 24
([#&#8203;20893](https://redirect.github.com/eslint/eslint/issues/20893))
(Milos Djermanovic)
-
[`c91b041`](https://redirect.github.com/eslint/eslint/commit/c91b0417e3420c76807ce1fa2aea76e2de87ab86)
docs: Update README (GitHub Actions Bot)
-
[`e349265`](https://redirect.github.com/eslint/eslint/commit/e349265cb37f3ebc837e178e48a725bb782bd870)
docs: clarify semver strings in rule deprecation objects
([#&#8203;20885](https://redirect.github.com/eslint/eslint/issues/20885))
(Milos Djermanovic)

#### Chores

-
[`b0e466b`](https://redirect.github.com/eslint/eslint/commit/b0e466b6ab47bfc7de43d8de0c315d8ee83aa584)
test: add `data` property to invalid tests cases for rules
([#&#8203;20924](https://redirect.github.com/eslint/eslint/issues/20924))
(Tanuj Kanti)
-
[`f78838b`](https://redirect.github.com/eslint/eslint/commit/f78838bc4c86d487e1bcc7cede260c4467721c46)
test: add CodePath type coverage
([#&#8203;20904](https://redirect.github.com/eslint/eslint/issues/20904))
(Pixel998)
-
[`1daa4bd`](https://redirect.github.com/eslint/eslint/commit/1daa4bd734b79a62e317d0394394a6b38cff49f9)
chore: update `eslint-plugin-eslint-comments` test data to latest commit
([#&#8203;20922](https://redirect.github.com/eslint/eslint/issues/20922))
(Francesco Trotta)
-
[`002942c`](https://redirect.github.com/eslint/eslint/commit/002942ce988ea28b78e0a2f3b074081e638b552c)
ci: declare contents:read on update-readme workflow
([#&#8203;20919](https://redirect.github.com/eslint/eslint/issues/20919))
(Arpit Jain)
-
[`64bca24`](https://redirect.github.com/eslint/eslint/commit/64bca24e7bed35bc3c864fc625cb2d89eca87d5b)
chore: update ecosystem plugins
([#&#8203;20912](https://redirect.github.com/eslint/eslint/issues/20912))
(ESLint Bot)
-
[`6d7c832`](https://redirect.github.com/eslint/eslint/commit/6d7c832950d5e92499d88e504080661f888f8f56)
chore: ignore fflate updates in renovate
([#&#8203;20908](https://redirect.github.com/eslint/eslint/issues/20908))
(Pixel998)
-
[`b2c8638`](https://redirect.github.com/eslint/eslint/commit/b2c86382164d87c6203b78d52068cd6a2a6ffe30)
ci: bump pnpm/action-setup from 6.0.7 to 6.0.8
([#&#8203;20889](https://redirect.github.com/eslint/eslint/issues/20889))
(dependabot\[bot])
-
[`a9b8d7f`](https://redirect.github.com/eslint/eslint/commit/a9b8d7f74c50211701cfc49710fa541fd91b2aa5)
chore: increase maxBuffer for ecosystem tests
([#&#8203;20881](https://redirect.github.com/eslint/eslint/issues/20881))
(sethamus)
-
[`b702ead`](https://redirect.github.com/eslint/eslint/commit/b702ead5e1ed7cb9f28238a454797662efb37396)
chore: update ecosystem update PR settings
([#&#8203;20884](https://redirect.github.com/eslint/eslint/issues/20884))
(Pixel998)
-
[`507f60e`](https://redirect.github.com/eslint/eslint/commit/507f60e9a78c9a902bc8759f066ae17a1ea6cd81)
chore: update ecosystem plugins
([#&#8203;20882](https://redirect.github.com/eslint/eslint/issues/20882))
(ESLint Bot)
-
[`92f5c5b`](https://redirect.github.com/eslint/eslint/commit/92f5c5bb6bf3a5d167c8ee53a430833410295c6d)
test: add unit test for message-count
([#&#8203;20878](https://redirect.github.com/eslint/eslint/issues/20878))
(kuldeep kumar)
-
[`df32108`](https://redirect.github.com/eslint/eslint/commit/df321080af5758b1fa25e4b9a40e26135642dd6e)
chore: add
[@&#8203;eslint/markdown](https://redirect.github.com/eslint/markdown)
and typescript-eslint ecosystem tests
([#&#8203;20837](https://redirect.github.com/eslint/eslint/issues/20837))
(sethamus)
-
[`327f91d`](https://redirect.github.com/eslint/eslint/commit/327f91d36aa49f2a50ded931d841a16374fd875f)
chore: use includeIgnoreFile internally
([#&#8203;20876](https://redirect.github.com/eslint/eslint/issues/20876))
(Kirk Waiblinger)
-
[`f0dc4bd`](https://redirect.github.com/eslint/eslint/commit/f0dc4bd893fb3a9f44e4ddc3ad7063ffb0beacd3)
chore: pin fflate\@&#8203;0.8.2
([#&#8203;20877](https://redirect.github.com/eslint/eslint/issues/20877))
(Milos Djermanovic)
-
[`0f4bd25`](https://redirect.github.com/eslint/eslint/commit/0f4bd257a67a082b756de746d9e0c4842ab764ca)
ci: run Discord alert for ecosystem test failures
([#&#8203;20873](https://redirect.github.com/eslint/eslint/issues/20873))
(Copilot)

</details>

<details>
<summary>sveltejs/prettier-plugin-svelte
(prettier-plugin-svelte)</summary>

###
[`v4.1.0`](https://redirect.github.com/sveltejs/prettier-plugin-svelte/blob/HEAD/CHANGELOG.md#410)

[Compare
Source](https://redirect.github.com/sveltejs/prettier-plugin-svelte/compare/prettier-plugin-svelte@4.0.1...prettier-plugin-svelte@4.1.0)

##### Minor Changes

- feat: support Svelte 5 declaration tags
([#&#8203;533](https://redirect.github.com/sveltejs/prettier-plugin-svelte/pull/533))

</details>

<details>
<summary>sveltejs/svelte (svelte)</summary>

###
[`v5.56.1`](https://redirect.github.com/sveltejs/svelte/blob/HEAD/packages/svelte/CHANGELOG.md#5561)

[Compare
Source](https://redirect.github.com/sveltejs/svelte/compare/svelte@5.56.0...svelte@5.56.1)

##### Patch Changes

- fix: error at compile time on duplicate snippet/declaration tag
definitions
([#&#8203;18351](https://redirect.github.com/sveltejs/svelte/pull/18351))

- fix: parse declaration tag contents more robustly
([#&#8203;18353](https://redirect.github.com/sveltejs/svelte/pull/18353))

- fix: correctly transform references to earlier declarators in a
declaration tag (e.g. `{let a = $state(0), b = $derived(a * 2)}`)
([#&#8203;18348](https://redirect.github.com/sveltejs/svelte/pull/18348))

- fix: avoid spurious `state_referenced_locally` warnings for `$derived`
declarations in declaration tags
([#&#8203;18348](https://redirect.github.com/sveltejs/svelte/pull/18348))

- fix: tolerate whitespace before `let`/`const` in declaration tags
([#&#8203;18348](https://redirect.github.com/sveltejs/svelte/pull/18348))

- fix: prevent infinite loop when a tag's expression ends with a
trailing `/` at the end of the input
([#&#8203;18350](https://redirect.github.com/sveltejs/svelte/pull/18350))

- fix: more robust parsing of declaration tags with regards to `type`
([#&#8203;18330](https://redirect.github.com/sveltejs/svelte/pull/18330))

- fix: preserve newlines in spread input values when the `type`
attribute is applied after `value`
([#&#8203;18345](https://redirect.github.com/sveltejs/svelte/pull/18345))

- fix: update `SvelteURLSearchParams` when setting duplicate keys to the
same joined value
([#&#8203;18336](https://redirect.github.com/sveltejs/svelte/pull/18336))

- fix: check references for blockers on server, too
([#&#8203;18352](https://redirect.github.com/sveltejs/svelte/pull/18352))

###
[`v5.56.0`](https://redirect.github.com/sveltejs/svelte/blob/HEAD/packages/svelte/CHANGELOG.md#5560)

[Compare
Source](https://redirect.github.com/sveltejs/svelte/compare/svelte@5.55.10...svelte@5.56.0)

##### Minor Changes

- feat: allow declarations in the template
([#&#8203;18282](https://redirect.github.com/sveltejs/svelte/pull/18282))

##### Patch Changes

- perf: use `createElement` instead of `createElementNS` for HTML
elements
([#&#8203;18262](https://redirect.github.com/sveltejs/svelte/pull/18262))

- perf: store `current_sources` as a `Set` for O(1) membership checks
([#&#8203;18278](https://redirect.github.com/sveltejs/svelte/pull/18278))

- perf: deduplicate identical hoisted templates within a component
([#&#8203;18320](https://redirect.github.com/sveltejs/svelte/pull/18320))

- perf: hoist `rest_props` exclude list as a module-scope `Set`
([#&#8203;18252](https://redirect.github.com/sveltejs/svelte/pull/18252))

</details>

<details>
<summary>privatenumber/tsx (tsx)</summary>

###
[`v4.22.4`](https://redirect.github.com/privatenumber/tsx/releases/tag/v4.22.4)

[Compare
Source](https://redirect.github.com/privatenumber/tsx/compare/v4.22.3...v4.22.4)

##### Bug Fixes

- resolve CommonJS directory requires inside dependencies
([#&#8203;803](https://redirect.github.com/privatenumber/tsx/issues/803))
([1ce8463](https://redirect.github.com/privatenumber/tsx/commit/1ce846335b7c445a3328c7d27f06424949356d97))

***

This release is also available on:

- [npm package (@&#8203;latest
dist-tag)](https://www.npmjs.com/package/tsx/v/4.22.4)

</details>

<details>
<summary>sindresorhus/type-fest (type-fest)</summary>

###
[`v5.7.0`](https://redirect.github.com/sindresorhus/type-fest/releases/tag/v5.7.0)

[Compare
Source](https://redirect.github.com/sindresorhus/type-fest/compare/v5.6.0...v5.7.0)

##### New types

-
[`RemoveSuffix`](https://redirect.github.com/sindresorhus/type-fest/blob/main/source/remove-suffix.d.ts)
([#&#8203;1439](https://redirect.github.com/sindresorhus/type-fest/issues/1439))
[`d685b77`](https://redirect.github.com/sindresorhus/type-fest/commit/d685b77)
-
[`UnwrapRequired`](https://redirect.github.com/sindresorhus/type-fest/blob/main/source/unwrap-required.d.ts)
([#&#8203;1410](https://redirect.github.com/sindresorhus/type-fest/issues/1410))
[`3bfee8e`](https://redirect.github.com/sindresorhus/type-fest/commit/3bfee8e)

##### Improvements

- `ExtendsStrict`: Add `distributiveUnions`, `strictNever` & `strictAny`
options
([#&#8203;1408](https://redirect.github.com/sindresorhus/type-fest/issues/1408))
[`9ea810b`](https://redirect.github.com/sindresorhus/type-fest/commit/9ea810b)
- `TupleOf`: Improve implementation
([#&#8203;1441](https://redirect.github.com/sindresorhus/type-fest/issues/1441))
[`391e1bb`](https://redirect.github.com/sindresorhus/type-fest/commit/391e1bb)

##### Fixes

- `RemovePrefix`: Fix: Remove incorrect optimization and always fallback
to `string` for non-literal prefixes
([#&#8203;1438](https://redirect.github.com/sindresorhus/type-fest/issues/1438))
[`9f35398`](https://redirect.github.com/sindresorhus/type-fest/commit/9f35398)
- `DelimiterCase`: Fix behavior with non-single character delimiters
([#&#8203;1424](https://redirect.github.com/sindresorhus/type-fest/issues/1424))
[`9b36590`](https://redirect.github.com/sindresorhus/type-fest/commit/9b36590)
- `RemovePrefix`: Fix `any` prefix behavior in non-strict mode
([#&#8203;1423](https://redirect.github.com/sindresorhus/type-fest/issues/1423))
[`c49cb75`](https://redirect.github.com/sindresorhus/type-fest/commit/c49cb75)
- `DelimiterCase`: Fix behavior with union delimiters
([#&#8203;1422](https://redirect.github.com/sindresorhus/type-fest/issues/1422))
[`96172c0`](https://redirect.github.com/sindresorhus/type-fest/commit/96172c0)
- `ApplyDefaultOptions`: Fix behavior with generic instantiations &
`any` values
([#&#8203;1411](https://redirect.github.com/sindresorhus/type-fest/issues/1411))
[`c46020d`](https://redirect.github.com/sindresorhus/type-fest/commit/c46020d)
- `ApplyDefaultOptions`: Fix behavior with explicit `undefined`
([#&#8203;1407](https://redirect.github.com/sindresorhus/type-fest/issues/1407))
[`60bfd3f`](https://redirect.github.com/sindresorhus/type-fest/commit/60bfd3f)

***

</details>

---

### Configuration

📅 **Schedule**: (in timezone Asia/Shanghai)

- Branch creation
  - "before 10am on monday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/oxc-project/oxc).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDkuNCIsInVwZGF0ZWRJblZlciI6IjQzLjIwOS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
2026-06-07 17:44:09 +01:00
leaysgur a474264ac8 chore(oxfmt): Bump svelte and tailwind plugin version (#22705)
Upadte `prettier-plugin-svelte` along with `prettier-plugin-tailwindcss`.

- `prettier-plugin-svelte@4` has just released
  - This plugin requires Svelte 5 and uses new AST internally
- This breaks `prettier-plugin-tailwindcss`, which does not support new AST shape
- So we also update `prettier-plugin-tailwindcss` to support new AST

While `prettier-plugin-svelte@3` previously supported Svelte 4 and below, this new version has dropped that support. (= breaking change)

However, since Oxfmt has specified Svelte 5 as a peer dependency ever since adding Svelte support, it has never supported Svelte 4 or earlier.

In that sense, this is not a breaking change for Oxfmt.
2026-05-25 05:09:17 +00:00
leaysgur 4dd83ddaa0 fix(oxfmt): Send expandedStates variants as shared refs (#22366)
Fixes #22350

Currently, the js-in-vue process involves formatting the code on the Rust side using `oxc_formatter`, converting it into an IR, transforming that into a Prettier `Doc`, serializing it into JSON, and then sending it to the JS side, where it is finally passed to Prettier.

Some types of `Docs` include multiple variations that are selected based on the `printWidth`, and all of these variations were being included as part of the JSON payload.

As a result, deep nesting caused the payload size to grow exponentially, leading to hangs.

This PR resolves the issue by sending these variations separately as shared references.
2026-05-13 01:55:13 +00:00
leaysgur 838061bf83 test(oxfmt): Update conformance (#22299)
Update html-in-js fixtures.
2026-05-11 07:39:20 +00:00
leaysgur d29c5d60bb test(oxfmt): Arrange conformance fixtures dir (#22297)
Prepare for running conformance on CI as well.
2026-05-11 07:23:46 +00:00
leaysgur 47fb154918 test(oxfmt): Add tests and conformance (#21832) 2026-05-11 01:24:38 +00:00
leaysgur 22babdef67 fix(oxfmt): Fix unicode char escaping (#21162)
Fixes #21160
2026-04-08 08:39:35 +00:00
leaysgur d58883d248 test(oxfmt): Pin and update oxfmt/conformance (#21156) 2026-04-08 04:54:39 +00:00
leaysgur d9389c15d2 test(oxfmt): Update conformance, follow up #20954 (#20957) 2026-04-02 09:07:53 +00:00
Dunqing d10df39ae6 fix(formatter): resolve pending space in fits measurer before expanded-mode early exit (#20954)
Closes #20519
Alternative to #20858

## Summary

The `fits()` measurer in the printer defers `Space` elements via a `pending_space` boolean flag. When the measurer exits early through an expanded-mode line break (`Fits::Yes`), any unresolved `pending_space` is silently lost — causing the measured width to be off by one.

This caused the decorator in `@property(...) prop: Type` to incorrectly stay on the same line because the space after `:` was not counted in the width measurement.

### Root cause

In `FitsMeasurer::fits_element`, `Space` sets `pending_space = true` (deferred), while `HardSpace` immediately increments `line_width`. When `fits()` returns `Fits::Yes` via the expanded-mode line break path (line 1040), the pending space is never resolved.

For the decorator case:
1. After `@property(...)` + space + `tooltipPlacement` + `:` → `line_width = 80`
2. `Space` after `:` → `pending_space = true` (line_width stays 80)
3. Union type group inherits Expanded mode → `if_group_breaks(separator)` included
4. Separator's `SoftOrSpace` in Expanded mode → `return Fits::Yes` **without resolving pending_space**
5. The +1 char from the space is lost, making the decorator group incorrectly "fit"

### Fix

Resolve `pending_space` before returning `Fits::Yes` from the expanded-mode early exit path. This matches Ruff's approach where `Space` is counted eagerly via `fits_text(Text::Token(" "))`.

### Conformance

- JS: 746/753 (unchanged)
- TS: 591/601 (unchanged — `18148.ts` fixed, `comment.ts` regressed)

The `comment.ts` regression (`typescript/union/consistent-with-flow/comment.ts`) is a **pre-existing Prettier bug** — at `printWidth: 81`, Prettier itself produces the same double-indented output with a spurious blank line:

```ts
// printWidth: 81 → Prettier also double-indents:
type SuperLong...Blaa =
                         ← spurious blank line
    | Fooo1000           ← 4 spaces (double indent)
```

At exactly 80 chars, Prettier avoids this only because its own fits check has the same off-by-one (the space is not counted), causing the Fluid layout's inner group to accidentally "fit".

## Test plan

- [x] `cargo test -p oxc_formatter` — 262 passed
- [x] `cargo test -p oxc_formatter -- fixtures` — 213 passed (including new `issue-20519.ts`)
- [x] `cargo run -p oxc_prettier_conformance` — JS 746/753, TS 591/601
- [x] `cargo clippy -p oxc_formatter` — clean

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-02 08:32:15 +00:00
leaysgur 23050faba6 feat(oxfmt): Support markdown-in-js substitution (#20683)
Part of #15180, and the last piece...!
2026-03-24 13:13:56 +00:00
leaysgur 4087295040 feat(oxfmt): Support angular-in-js substitution (#20676)
Part of #15180, closes #18891

Angular-in-JS consists of 2 cases: `template` and `styles`.

- template: Similar to html-in-js, use the `parser: angular`
- styles: Same as css-in-js (already supported)
2026-03-24 13:13:56 +00:00
leaysgur 47c56b6a98 test(oxfmt): Refactor conformance tests (#20642)
Pure refactoring;

- Use explicit path for unsupported notes
- Download fixtures in parallel
- Test more variants
2026-03-23 08:06:57 +00:00
leaysgur c21c5a7e72 feat(oxfmt): Support html-in-js substitution (#20193)
Part of #15180

The basic flow is the same as css-in-js: replace `${expr}` with placeholder strings, let Prettier format the HTML, then substitute back with formatted `expr`s.

However, there are a few key differences:

### `options.htmlWhitespaceSensitivity`

This HTML-specific option also affects html-in-js (template wrapping strategy, hug detection), so it needed to be held in `oxc_formatter::FormatOptions`.

### `prettier.__internal.formatOptionsHiddenDefaults`

Prettier adds hidden fields to the `options` object during its internal print phase for embedded formatters.

However, `__debug.printToDoc()` runs `normalizeFormatOptions()` which strips unknown keys. Unlike internal `textToDoc()` (which uses `passThrough: true`), `printToDoc()` does not preserve them.

To work around this, we pre-register keys in `formatOptionsHiddenDefaults` so they survive normalization.

### NOTE: Not fully supported cases

#### js-in-html-in-js

Currently, the process of converting Docs to our IR does not support `conditionalGroup`.

Since Prettier only uses this for YAML and JS formatting.
YAML is never embedded, and we would like to use `oxc_formatter` for JS.

However, applying `oxc_formatter` to the **js**-in-html-in-js case was not straightforward. Therefore, I have implemented a fallback to a simpler formatting process for that case for now.

#### `label({ embed, hug })` equivalent

With current implementation, `is_huggable_html_embed_single_arg()` always hugs via early-return, ignoring line width.

Prettier uses `label({ embed, hug })` + `conditionalGroup` to try hugged first and fall back to expanded.

We have the equivalent `BestFitting` 3-variant flow in `write_grouped_arguments`, but `ExpandParent` from HTML template's `hardline` propagates through `will_break` / `propagate_expands` / fit check, forcing the expanded variant to always be chosen.

To fix, we need to add new IR for boundary (prevents `ExpandParent` propagation in `will_break` / `propagate_expands` / fit check), then add HTML embeds to `can_group_expression_argument` so they enter the existing `BestFitting` 3-variant flow.

However, I'm not sure this is worth to add. So just leave it for now.
2026-03-23 07:30:16 +00:00
leaysgur d35b25f93b fix(formatter,oxfmt): Remove redundant space after soft_line_break_or_space (#20562)
Fixes #20548

Remove redundant `Space` elements that immediately followed `soft_line_break_or_space()` in three places:

- Arrow function chain signatures
- `class ... extends` with member expressions
- `interface ... extends` with member expressions

This, in turn, fixes the js-in-vue issue.

---

The root cause is that `to_prettier_doc` cannot fully replicate the oxc_formatter printer's runtime behavior (e.g. deduplication of spaces).

While this commit fixes the three identified IR-level issues, there are other known divergences between the printer and `to_prettier_doc` (e.g. `Space` → `StartTag` → `Space` patterns around comments) that will be addressed separately...

TL;DR, converting between Prettier Doc and oxc_formatter IR doesn't seem to be straightforward after all. 🥲
2026-03-21 04:42:15 +00:00
leaysgur f8c452aa90 fix(formatter,oxfmt): Handle css-in-js comment inside template (#20452)
Fix the bug found in https://github.com/oxc-project/oxc/blob/605de80b541b8d85e5129ab620eae63ed07a6a1e/apps/oxfmt/conformance/snapshots/diffs/xxx-in-js-comment/comment-inside.js.md
2026-03-17 15:32:32 +00:00
leaysgur c5aeae4d93 feat(formatter,oxfmt): Support /* LANG */ comment for gql|html-in-js (#20224)
Part of #15180, supports ``/* HTML */ `...` `` and ``/* GraphQL */ `...` ``.
2026-03-17 15:32:32 +00:00
leaysgur c104c0e3dc test(oxfmt): Add css-in-js conformance fixture (#20448)
Add test fixture to close #19667
2026-03-17 04:57:12 +00:00
leaysgur 88ee826b90 fix(oxfmt): Handle literalline for script-in-vue (#20130)
Fixes #20084, closes #20085

Currently, in the context of `js-in-vue`, there are 2 types of code paths:

- Script block: `run_full()`
  - Converts a **string** formatted by `oxc_formatter` into Prettier's Doc format by splitting it into lines, joining with `hardline`
- Other cases: `run_fragment()`
  - Converts the **IR** formatted by `oxc_formatter` into Prettier's Doc format through an IR -> Doc implementation

The current issue can be described as a bug in the former.

As a result of simply splitting by lines, newlines within strings (newlines within `TemplateLiteral`s) are also treated as `hardline` (which are affected by parent indentation, it should be `literalline`), causing the nesting to deepen with each format.

To fix this, the former code path now also goes through an IR -> Doc conversion process.

Additionally, by doing this, the `printWidth` is also handled correctly.

In #20085, which involves re-converting a formatted string into an AST and then traversing it, was deemed undesirable.
2026-03-12 23:55:23 +00:00
leaysgur e483569a8a fix(oxfmt): Avoid double-escaping in css-in-js (#20211)
Fixes #20208
2026-03-11 04:48:26 +00:00
leaysgur ab446efc72 test(oxfmt): Update conformance to save each diff (#20170)
It's more efficient for both humans and AI to be able to see individual diffs.
2026-03-10 03:44:12 +00:00