Commit Graph

33 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 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 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 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 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 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 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 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
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 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 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 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