Skip to content

Migrate lint pipeline from ESLint/Prettier to Oxlint/oxfmt - #905

Open
YusukeHirao wants to merge 25 commits into
v6from
feat/oxlint-migration
Open

Migrate lint pipeline from ESLint/Prettier to Oxlint/oxfmt#905
YusukeHirao wants to merge 25 commits into
v6from
feat/oxlint-migration

Conversation

@YusukeHirao

@YusukeHirao YusukeHirao commented Aug 14, 2026

Copy link
Copy Markdown
Member

Summary

  • Migrate the root lint pipeline (lint/lint:ci/lint:fix) to Oxlint + oxfmt, keeping Prettier for Pug/Astro only
  • Add @d-zero/oxlint-config and @d-zero/oxlint-plugin (ports no-click-event; Vue @click/v-on:click is intentionally not detected by the Oxlint port, see MIGRATION-v6.md)
  • Add an Astro preset to @d-zero/prettier-config
  • Switch @d-zero/lint-staged-config's default extension mapping from eslint/prettier to oxlint/oxfmt
  • Remove typescript-eslint and all @typescript-eslint/* dependencies entirely, and drop the TypeScript 6/7 compatibility shim in favor of TypeScript 7 directly
    • @d-zero/eslint-config now only lints what Oxlint doesn't cover (regexp, jsdoc, import-x/no-extraneous-dependencies, no-restricted-syntax, etc.) and excludes .ts/.tsx files entirely
    • Consolidate standard/node/nodeNoTS/frontendNoTS/oxlintCompanion presets into just base and frontend
    • @d-zero/eslint-plugin's createRule now uses ESLint's own Rule types instead of @typescript-eslint/utils
    • Fix a pre-existing bug where no-click-event never detected Vue @click/v-on:click (the <template> AST requires defineTemplateBodyVisitor, which the rule never used)
  • Normalize package.json field order across all packages (mechanical, no behavior change)
  • Document the migration in MIGRATION-v6.md

Breaking change (alpha)

@d-zero/eslint-config's configs.standard/node/nodeNoTS/frontendNoTS are removed in favor of base/frontend. This is a breaking change for any consumer still on those preset names; acceptable at this 0.x/alpha stage per product-manager guidance, but downstream repos upgrading past this version will need to switch to base/frontend and, if they use @d-zero/lint-staged-config, add oxlint/oxfmt as dependencies.

Test plan

  • yarn build (all packages build)
  • yarn lint (tsc/oxlint/eslint/oxfmt/prettier/textlint/cspell/secretlint all pass)
  • yarn test (178 tests passing across 10 files, including new Oxlint plugin unit tests, Vue template-body detection tests, and CLI integration tests)

Comment thread packages/@d-zero/oxlint-plugin/package.json
Comment thread packages/@d-zero/oxlint-plugin/package.json Outdated
Comment thread packages/@d-zero/oxlint-config/index.js
Switch TypeScript from the TS6/TS7 shim to TypeScript 7 directly, since
typescript-eslint no longer needs a programmatic compiler API.
…y visitor

Vue's <template> block parses into a separate templateBody AST that
vue-eslint-parser exposes only through defineTemplateBodyVisitor; a plain
visitor never saw it, so the Vue selectors never matched. The name.name="on"
selector also compared a VIdentifier node against a string, which never
matched either.
@YusukeHirao
YusukeHirao force-pushed the feat/oxlint-migration branch from 7633a93 to a004a9a Compare August 19, 2026 01:42
@YusukeHirao

Copy link
Copy Markdown
Member Author

ESLintのルールを残す方向で大幅に変更しました。

目的

  1. TypeScript 7対応のためにtypescript-eslintを廃止
  2. Oxlint/oxfmtによる速度改善

方針

  • Oxlintに移行できるものはすべて移行(no-array-constructor等はOxlint側に新規移植)
  • Oxlintに実装がない領域(regexp・jsdoc主要チェック・import-x/no-extraneous-dependencies等)は継続してESLintを採用
  • TS関連でどうしても落としたのは以下の3点
    • no-floating-promises: Oxlint側にルール自体はあるが、型認識実行には別パッケージoxlint-tsgolint--type-awareフラグが必要で、有効化すると無関係な型認識系ルールが14個一括で有効になり影響範囲が読めない。導入は別PRで検討
    • no-restricted-syntaxのTS構文チェック(private/public修飾子禁止・protected命名規則): AIエージェントによるコーディングで致命的な問題にはならないと判断し不採用
    • no-explicit-anyfixToUnknownno-namespaceallowDeclarationsオプション: 同様にAIエージェントによるコーディングで致命的な問題にはならないと判断し不採用

Comment thread packages/@d-zero/eslint-config/base.js Outdated
Oxlint's unicorn/no-null now covers this file; align with the rest of the
codebase and drop the unused abbreviation in modPath.
…er null

Oxlint's unicorn/no-anonymous-default-export and unicorn/no-null now cover
this file.
…ver null

Oxlint's unicorn/no-anonymous-default-export and unicorn/no-null now cover
this file.
Oxlint's unicorn/no-null now covers this file. CSSTree's own null return
from matchProperty is left untouched since it's that library's API.
Oxlint's unicorn/consistent-function-scoping and unicorn/prefer-string-raw
now cover this file.
These 9 rules have an Oxlint implementation but default to off outside
their own category (style/suspicious/restriction/pedantic), so
categories.correctness alone didn't turn them on. base.js was disabling
them for ESLint on the assumption Oxlint covered them, so neither linter
was actually checking for them.
Replace the hand-maintained per-rule off lists in base.js (200+ entries,
copied from each plugin's recommended preset) with
eslint-plugin-oxlint's buildFromOxlintConfig(), fed directly from
@d-zero/oxlint-config's config object. A manual list drifts silently
whenever either config changes; generating it keeps the two in sync.

eslint-plugin-oxlint maps oxlint's `import` scope to the `import/` prefix,
not eslint-plugin-import-x's `import-x/`, so those overlapping rules stay
disabled by hand in the importX block. `unicorn/no-null` is force-enabled
back off for `**/stylelint-config/**` in oxlint.config.mts, since `null`
there is Stylelint's own rule-disabling value, not a stray literal.
@YusukeHirao
YusukeHirao requested review from arktds and yusasa16 August 24, 2026 08:46
These rules were off before the Oxlint migration; the overlap
auto-generation accidentally re-enabled them in the wrong direction.
11 unicorn rules that were off before the Oxlint migration reverted to
their enabled defaults when the manual disable list was replaced by
eslint-plugin-oxlint auto-generation. Restore them as an explicit block
since they are repo style choices, not oxlint-overlap suppressions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants