Commit Graph

82 Commits

Author SHA1 Message Date
camc314 949d7a9302 chore(deps): update vitest to v5 (#26299)
## Summary

- update workspace test dependencies to Vitest 5.0.0
- pin Vitest and related tooling to Vite 8.2.2
- migrate removed sequential and benchmark APIs
- update the pnpm lockfile
2026-09-03 19:05:05 +00:00
Yuji Sugiura 1cad286676 perf(oxfmt): match editorconfig once per file (#26239) 2026-09-02 12:58:48 +09:00
Boshen 1193c9dbaf chore(oxfmt): dogfood operator position at line start (#25937)
dogfood
2026-08-20 14:36:47 +00:00
leaysgur a38f7b3d57 fix(oxlint,oxfmt): apply .gitignore only to walk targets, not explicitly named files (#25531)
Possibly fixes #25259, and partial revert of #25133.

---

- `.gitignore` applies only to discovery (walking directory targets, cwd, globs)
- An explicitly named file target is linted / formatted even when gitignored
  - = Restoring the pre-[#25133]() behavior for files, while fully keeping the [#25107]() fix for walk roots

| Target | Current | This PR |
| --- | --- | --- |
| Explicit file (`oxlint dist/a.js`) | skipped | linted |
| Explicit directory (`oxlint dist`) | skipped | skipped |
| cwd inside ignored tree | skipped | skipped |

The underlying principle:

> `.gitignore` is a message addressed to git, not to tools.
> Borrowing it to scope discovery is a useful heuristic, and a heuristic may narrow what the walk finds, but never refuse what the user names.
> Only tool's own ignore config can refuse. (which remain hard for the husky staged-file case).

This also re-aligns the CLI with stdin and LSP, which deliberately do not consult `.gitignore` (#19206).
👉🏻 This is the main motivation.

### Why not full revert

A directory target names where to search, not what to process.
The files under it are still discovered by the walk, so discovery rules apply.
Reverting that would bring back [#25107](), whose old behavior was not even a statable spec: whether running inside an ignored tree processed anything depended on the ignore pattern's form (bare `generated` did, `generated/**` didn't), an artifact of walker pruning, not a design.

### Regarding to `--no-ignore`

This flag remains orthogonal as a walk-level opt-out (`--no-ignore=vcs dist`) and for filling gap between existing tools.

However, with explicit files working again, I'm inclined to close those PRs and revisit if demand shows up.

For [#25259]()'s use case: name the files, e.g. `oxlint dist/foo.js` (or shell-expanded glob).
2026-08-14 03:35:34 +00:00
Boshen 00e1b762e0 refactor(diagnostics): vendor oxc-miette (#25499)
We no longer need to maintain the `oxc-miette` repo as most of the code is now removed, the remaining code is minimal and can be vendored.
2026-08-11 08:04:02 +00:00
renovate[bot] b91dc3a1f1 chore(deps): update napi (#25457)
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/) | Type |
Update |
|---|---|---|---|---|---|---|---|
| [@napi-rs/cli](https://napi.rs/)
([source](https://redirect.github.com/napi-rs/napi-rs)) | [`3.8.3` →
`3.8.5`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/3.8.3/3.8.5) |
![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/3.8.5?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/3.8.5?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/3.8.3/3.8.5?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/3.8.3/3.8.5?slim=true)
| pnpm.catalog.default | patch |
| [napi](https://redirect.github.com/napi-rs/napi-rs) | `3.12.0` →
`3.12.1` |
![age](https://developer.mend.io/api/mc/badges/age/crate/napi/3.12.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi/3.12.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi/3.12.0/3.12.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi/3.12.0/3.12.1?slim=true)
| workspace.dependencies | patch |
| [napi-build](https://redirect.github.com/napi-rs/napi-rs) | `2.4.0` →
`2.4.1` |
![age](https://developer.mend.io/api/mc/badges/age/crate/napi-build/2.4.1?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi-build/2.4.1?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi-build/2.4.0/2.4.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi-build/2.4.0/2.4.1?slim=true)
| workspace.dependencies | patch |
| [napi-derive](https://redirect.github.com/napi-rs/napi-rs) | `3.6.2` →
`3.6.3` |
![age](https://developer.mend.io/api/mc/badges/age/crate/napi-derive/3.6.3?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi-derive/3.6.3?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi-derive/3.6.2/3.6.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi-derive/3.6.2/3.6.3?slim=true)
| workspace.dependencies | patch |

---

### Release Notes

<details>
<summary>napi-rs/napi-rs (@&#8203;napi-rs/cli)</summary>

###
[`v3.8.5`](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.4...a5b5f277ab56e7e7e903b392b15c79da7a6520ce)

[Compare
Source](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.4...@napi-rs/cli@3.8.5)

###
[`v3.8.4`](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.3...@napi-rs/cli@3.8.4)

[Compare
Source](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.3...@napi-rs/cli@3.8.4)

</details>

---

### Configuration

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

- Branch creation
  - At any time (no schedule defined)
- 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:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Cameron <cclark@cloudflare.com>
2026-08-10 08:39:38 +00:00
leaysgur 20f68e74a3 fix(oxlint,oxfmt): respect .gitignore for walk targets and explicit paths (#25133)
Fixes #25107.

The `ignore` crate walker enforces gitignore's "everything under an ignored directory is ignored" rule only by pruning ignored directories during traversal.

And it never filters its walk roots.
So when a walk target (based on cwd or an explicit CLI target path) is already inside a gitignored tree, pruning never happens and a bare directory pattern like `generated` matches nothing file-level. (even though `git check-ignore` says they are ignored)

See also BurntSushi/ripgrep#2595

### Changes

- oxc_config: added `GitignoreChecker`
  - a pre-walk check that replays git's resolution order over the ancestor chain
  - Matchers and `.git`/`.jj` probes are cached per directory
- oxlint / oxfmt: filter all CLI targets through this check before walking

### Behavior changes

- Explicitly passed gitignored files are now skipped (previously always linted/formatted)
- `oxlint --no-ignore` no longer force-lints gitignored targets
  - The same behavior as `--no-ignore` does not disable during walk `.gitignore`

<details>
<summary>FYI: Current our ignore model overview</summary>

Two independent families, AND-ed (a path excluded by any layer is skipped):

| Layer                                        | Source                                                 | oxlint                                                                                         | oxfmt                                                |
| -------------------------------------------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| git-derived (always on, not user-disablable) | nested `.gitignore`, `.git/info/exclude` (during walk) | walker via shared `configure_walk_builder`                                                     | same (shared)                                        |
|                                              | walk roots / explicit CLI targets                      | `GitignoreChecker` (this PR)                                                                   | `GitignoreChecker` (this PR)                         |
| tool-owned                                   | ignore file                                            | `.eslintignore` / `--ignore-path`; disabled by `--no-ignore`                                   | `.prettierignore` / `--ignore-path`; no disable flag |
|                                              | CLI patterns                                           | `--ignore-pattern`; disabled by `--no-ignore`                                                  | `!pattern` path args                                 |
|                                              | config `ignorePatterns`                                | `LintIgnoreMatcher` (already containment-correct via `matched_path_or_any_parents`); always on | scope-local `is_path_ignored` (same); always on      |

NOTE: `ignorePatterns` never had this bug, only the walker-backed gitignore layer did; this PR brings it to the same level.
A `!` negation in `ignorePatterns` cannot re-include gitignored paths (unchanged; the layers are independent).

</details>
2026-08-02 13:11:06 +00:00
leaysgur 87e0970e7a test(oxfmt): fix windows ci (#25069)
It seems that picocolors, which Vite uses, always outputs color.
2026-07-29 09:13:56 +00:00
leaysgur be7f6da49a feat(oxfmt): colorize diff file list in check mode (#25061)
Fixes #25018
2026-07-29 06:00:25 +00:00
leaysgur 0c16cb5aba feat(oxfmt)!: Format parser:yaml files by oxc_formatter_yaml (#24890)
Format `.yaml`, `.yml` and others by `oxc_formatter_yaml`.

Also handle maybe-json-or-yaml files like `.prettierrc`.
2026-07-28 06:16:26 +00:00
leaysgur d7c222dc54 test(oxfmt): remove unicode-ascii replaces (#24895)
Now it is forced by env var.
2026-07-24 09:27:12 +00:00
leaysgur e81b2ff6c5 fix(oxlint,oxfmt): report error for invalid glob patterns (#24744)
Fixes #24612

- Update `fast-glob` to `1.1.0` which exposes `validate()` api
- Use it in `oxc_config`, apps will be validated through `deserialize`
- Oxfmt supports globs for CLI paths, also validated
2026-07-21 04:43:49 +00:00
camc314 92f154a07c feat(oxlint,oxfmt): auto-discover .mts config files (#24357)
## Summary

- auto-discover `oxfmt.config.mts` and `oxlint.config.mts`
- watch `.mts` configs in the language server and reject `.ts`/`.mts` conflicts
- add focused CLI and LSP coverage
2026-07-10 11:38:35 +00:00
leaysgur 415fe1e7bb fix(oxfmt): error on ignorePatterns that cannot match files outside the config directory (#24286)
Patterns in `ignorePatterns` use gitignore-style matching rooted at the config file's directory, so a `..` component can never match anything.

Reject such patterns at config load time instead of silently accepting them, and document the scoping.

Refs: #24276
2026-07-08 05:31:23 +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 ea5d09534d fix(oxfmt): update --migrate prettier (#23963)
A bit outdated, updated it to reflect the latest situation.

- Support `svelte` migration
- Better (but not yet complete) `overrides` detection
- Remove warning about `embeddedLanguageFormatting` (already supported)
- etc
2026-06-30 00:59:07 +00:00
leaysgur 6e29c56baf test(oxfmt): Fix windows snapshots for Vite+ diagnostics (#22635)
Fixes https://github.com/oxc-project/oxc/actions/runs/26157008185/job/76938896278
2026-05-21 01:42:28 +00:00
leaysgur 16b8058cd6 feat(oxfmt): Support vite-plus/resolveConfig for vite.config.ts (#22454)
Closes #21603, fixes #21418

To simplify the review process, I'll first add support to Oxfmt.

In the next PR, I'll move that implementation to `shared`.
2026-05-20 08:21:37 +00:00
leaysgur 47fb154918 test(oxfmt): Add tests and conformance (#21832) 2026-05-11 01:24:38 +00:00
leaysgur 5c6c390d47 feat(oxfmt)!: Respect more git ignore options, align with Oxlint (#22210)
Fixes #22034.

Oxfmt now respects the same Git ignore rules as Git itself:

- Reads `.gitignore` from parent directories (up to the repository boundary)
- Reads `.git/info/exclude`

like Oxlint does.
2026-05-07 07:42:28 +00:00
leaysgur 5f685f1961 test(oxfmt): Show generated .gitignore in the tree snapshot (#22208) 2026-05-07 06:20:06 +00:00
camc314 fdd4c92791 refactor(oxlint,oxfmt): share config discovery code (#21642) 2026-04-23 10:12:18 +00:00
Yuji Sugiura 0dce3c67dd fix(oxfmt): Handle invalid overrides config without panic (#21661)
Fixes #21651

Currently, we validate the config in advance (so, the root won't panic).
However, validating `overrides` beforehand is difficult.

- Since they are cumulative, the final result depends on specific file
paths
- The merged result can sometimes lead to invalid combinations (e.g.
`sortImports`)

Essentially, we have no choice but to return an error when an invalid
option is encountered for each target file, much like how we detect
syntax errors.

But I don't think abandoning pre-validation entirely is a good idea.
We have nested configs now, and cases where `overrides` cause errors
shouldn't happen very frequently.

---

👉🏻 Keep the current pre-validation (error early if possible (walk root,
stdin), validate `overrides` in separate files and report errors
individually (walk overrides, lsp).

As for changes from the current state, ensure that it does not panic at
the very least.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-23 10:57:37 +09:00
leaysgur 3bc54a96c5 feat(oxfmt): Respect nested config for --stdin-filepath (#21627)
Follow up on #21625

Now filepath in `--stdin-filepath` is not just a hint for parser detection.
2026-04-22 04:22:25 +00:00
leaysgur 144f27a042 feat(oxfmt): Respect ignore settings for --stdin-filepath (#21625)
Fixes #20545
2026-04-22 03:29:24 +00:00
leaysgur 5aa7fe1b12 feat(oxfmt): Add --disable-nested-config CLI flag (#21514)
Fixes #21420
2026-04-17 01:20:46 +00:00
leaysgur f87b33464d test(oxfmt): Refactor test fixtures usage (#21494)
- Normalized tests that were ambiguous as to whether they were fixtures or scenarios based
- Specified this rule in AGENTS.md
- Made the test name report in the CLI clearer
2026-04-16 09:40:58 +00:00
leaysgur 6f49fada82 fix(oxfmt): Respect nested config.ignorePatterns (#21489)
Previously, `ignorePatterns` could not skip directories in `filter_entry()` because doing so might hide nested configs beneath them.

This PR pre-scans config locations before the walk, so `filter_entry()` can safely skip `ignorePatterns` directories that have no nested config beneath them.

With all configs known upfront, the walk also resolves each file's scope dynamically from a pre-loaded scope map, replacing the sequential child-scope walks (`run_child_scope()` recursion) with a single parallel walk.

The pre-scan also preserves current streaming architecture (walk → channel → format workers), keeping format workers busy sooner than a batch-collect alternative would.
2026-04-16 08:10:30 +00:00
leaysgur 5900d23f76 test(oxfmt): Misc refactors (#21484)
- Simplify sort_imports test
- Add note comment to stdin_pipe test
- Update AGENTS.md
2026-04-15 22:50:00 +00:00
leaysgur c9b4db9ff7 test(oxfmt): Rework test/cli tests (#21463)
Switch to a fixture-based testing approach, similar to apps/oxlint.
2026-04-15 09:13:40 +00:00
leaysgur ce561a2d79 test(oxfmt): Place all format tests under the test/api dir (#21462) 2026-04-15 09:13:39 +00:00
leaysgur 16713d58cd feat(oxfmt/cli): Support per-directory config (#21103)
Fixes #19509

Initially, I thought about sharing the implementation with Oxlint, but finally I  decided not to do it due to constraints and structural differences.

- Strategy
  - Oxlint: Collects all file paths into memory upfront
    - for cross-module analysis?
    - then filters by `ignorePatterns` afterward
  - Oxfmt: Streams files to the formatter as they are discovered while walking
    - Scope-based walk resolves config at walk time, avoiding a separate post-walk filtering pass
- Config
  - Oxlint: There is a difference in what can be configured in the root config versus the rest
  - Oxfmt: No difference
2026-04-15 01:26:50 +00:00
leaysgur e3081e12a9 feat(oxfmt): Gate vite.config.ts recognition behind VP_VERSION env var (#21295)
Fixes #20416 for Oxfmt

- Gate `vite.config.ts` recognition behind `VP_VERSION` env var
  - With it, only vite.config.ts is recognized
  - Without it, excluded from config candidates (.oxfmtrc.json, oxfmt.config.ts are used)
- Refactor JS config loader into `loadJsConfig` / `loadVitePlusConfig` with shared `importJsConfig` helper
  - `loadVitePlusConfig` should be updated to use `resolveConfig` from `vite-plus` soon
- Split tests into `vite_config` (non VP mode) and `vite_plus` (VP mode)
2026-04-13 01:10:46 +00:00
leaysgur 94fe774190 fix(oxfmt): Handle paths with consecutive leading slashes (#21155)
Fixes #21086
2026-04-08 03:18:26 +00:00
leaysgur 0d678345aa feat(oxfmt): Show hint for all files are ignored case (#21154)
Fixes #21107

Messages that were previously omitted when `no_error_on_unmatched_pattern` is specified will now be displayed, resulting in more consistent behavior.
2026-04-08 02:16:24 +00:00
leaysgur 85075cee59 refactor(oxfmt): Rework glob expansion (#21083)
- Before: Resolved beforehand and treated as a simple list of paths
  - = 2-pass
- After: Walked through like a standard path, with processing handled by a custom matcher
  - = 1-pass
  - To support per-directory config, we need to locate the config files during the directory walk; glob is no exception

This is an internal change and generally has no impact on users.
(In niche cases, the content of the log output will change, but it will result in more consistent.)
2026-04-07 06:59:22 +00:00
leaysgur 50c389b64f fix(oxfmt): Support .editorconfig quote_type (#20989)
Fixes #20563

---

- [x] Merge https://github.com/oxc-project/editorconfig-parser/pull/42
- [x] Release https://github.com/oxc-project/editorconfig-parser/pull/43
- [x] Update crates version
- [x] Implement
- [x] Test
- [x] Update schema, snapshots
2026-04-07 02:03:35 +00:00
leaysgur 7ac69fa3f7 refactor(oxfmt): Arrange cli/js_config dir (#21078)
- Add `/js_config/` dir
- Use inline tests
- Always return `Error` instance
2026-04-06 02:27:59 +00:00
camc314 35cf6e87c0 feat(oxfmt): add node version hint for ts config import failures (#21046)
Refs:  #21032
2026-04-06 02:27:58 +00:00
leaysgur 4216380bc0 fix(oxfmt): Support .editorconfig tab_width fallback (#20988)
https://github.com/prettier/prettier/blob/90983f40dce5e20beea4e5618b5e0426a6a7f4f0/src/config/editorconfig/editorconfig-to-prettier.js#L25-L30
2026-04-03 02:28:39 +00:00
leaysgur 6ef440af18 feat(oxfmt): Support bool for object style options (#20853)
Fixes #20793
2026-03-30 02:05:35 +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 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 71628e6410 fix(formatter,oxfmt): Sort imports should not flush Empty line (#20443)
Fixes #20428

Since we're already handling the explicit `LineMode::Empty`, `LineMode::Hard` alone would have sufficed in this case.
2026-03-17 02:36:39 +00:00
leaysgur f9087426ce fix(oxfmt): Revert #20326 partially (#20413)
Current status:

- oxfmt: #20326 was merged
- oxlint: After discussion in #20327, it was decided NOT to merge

First, correct this inconsistency.

Since #20326 includes a change that displays errors from the JS side as-is, we will keep that part.
2026-03-16 01:23:49 +00:00
leaysgur 68fb0d0f6c fix(oxfmt): Skip vite.config.ts which fails to import (#20326)
If oxfmt.config.ts fails to load, it is the user's responsibility, so reporting it as an error is correct.
However, this does not apply to vite.config.ts, so we ignore it.

Also refactored to report error message from JS.
2026-03-13 14:24:37 +09:00
leaysgur 4ea67decf5 fix(oxlint,oxfmt): Skip vite.config.ts exports defineConfig(fn) (#20260)
`vite.config.ts` may return function from `defineConfig(({ mode }) => ({ ... }))`, but we can't evaluate.

Just skip it like no `.lint|fmt` config.
2026-03-12 04:56:57 +00:00
leaysgur fdaca97be4 refactor(oxfmt): extract vite fmt config in JS loader (#20257)
Closes #20243

The same as #20256, but for Oxfmt.
2026-03-12 04:14:27 +00:00
leaysgur 11a2b4530d fix(oxfmt): Skip vite.config.ts w/o .fmt field in auto-discovery (#20254)
Fixes #20237
2026-03-12 04:14:26 +00:00