Commit Graph

10 Commits

Author SHA1 Message Date
leaysgur 1a83a8ddb2 fix(oxfmt): mirror printer line suppression and restore dedent-to-root (#25573)
Fixes #25568, #25569
2026-08-13 03:50:19 +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 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 6e8e8185c0 feat(oxfmt): Experimental .svelte support (#21700)
Part of #19715

Note that:

> Users are required to perform 2 steps below
> 1️⃣ Install svelte/compiler@^5.0.0 and/or @astrojs/compiler@^2.9.1 manually
> 2️⃣ Enable option in config
2026-05-11 01:24:37 +00:00
leaysgur 7faba51ae4 refactor(oxfmt): Use FormatConfig as SoT (#21981)
In Oxfmt, there is only one config file, but there were multiple conversion paths to the specific options used by subsequent formatters.

For example, it would generate `FormatOptions` for `oxc_formatter`, while assembling the necessary `JSON` for `prettier`.

There was a lack of consistency here, as some paths referenced the parsed `FormatConfig` while others referenced the raw JSON of `Oxfmtrc`. This inconsistency led to issues like the one mentioned in #21919.

In this PR, I have established `FormatConfig` as the single SoT, ensuring that all options are derived from it.
2026-05-01 01:52:26 +00:00
leaysgur 035933c443 feat(formatter,oxfmt): Support js-in-vue (partially) (#19514)
### Overview

Part of #16608

This PR applies `oxc_formatter` to the js-in-vue section.

However, it is not complete and is only applied to the following parts within js-in-vue:

- `script` block
  - and `generic="..."`
- `v-for` LHS
- `v-slot`

In the `script` block, `external_callback` is used like a regular JS file, but it isn't for others.

TL;DR: Now you can use sort-imports for Vue files.

### Review points

The points I'd like to ask your review are the following:

- Addition of `format_node()` to `oxc_formatter`
  - Made it possible to process any type that implements `Format`, not just `Program`
- The implementation of `js-in-vue` fragment was separated as much as possible to avoid impacting existing code
- `oxc_formatter` IR to prettier `Doc`

### TODOs

- [x] Planning
- [x] Implementation
- [x] Check benchmark
- [x] Check coverage
- [x] Understand & refactor
  - [x] oxfmt: JS side
  - [x] oxfmt: Rust side
  - [x] oxfmt: to_doc.rs
  - [x] oxc_formatter: fragment_format
- [x] Check benchmark again
- [x] Check coverage again
- [x] Check ecosystem-ci
- [x] Tests 👉🏻 #19563
2026-02-24 10:17:35 +00:00
leaysgur c4a3cb5fad refactor(oxfmt): Move textToDoc() implementatin to Rust (#19307)
Part of #16608

Prettier's `textToDoc()` context has special handling based on hidden flags.

Initially, for Markdown, I implemented with heuristic string manipulation.

However,

- Similar processing is needed for HTML and Vue
- There are cases that cannot be handled by string manipulation alone
  - Considering adding options to the `oxc_formatter` side

For these reasons, a refactoring was performed as preparation.
2026-02-12 09:05:56 +00:00
leaysgur 5ea5bda86c fix(oxfmt): Handle isSingleJsxExpressionStatementInMarkdown() check for js-in-md (#19042) 2026-02-09 08:59:37 +00:00
leaysgur 5b53e83b79 refactor(oxfmt): Split oxfmt-plugin files (#19031)
Extract main `textToDoc()` implementation.
2026-02-06 07:53:00 +00:00