Commit 091424b2 by lijiabin

从prettier迁移到oxfmt

parent 9861a95d
---
name: migrate-oxfmt
description: Guide for migrating a project from Prettier or Biome to Oxfmt. Use when asked to migrate, convert, or switch a JavaScript/TypeScript project's formatter from Prettier or Biome to Oxfmt.
---
This skill guides you through migrating a JavaScript/TypeScript project from Prettier or Biome to [Oxfmt](https://oxc.rs/docs/guide/usage/formatter).
## Overview
Oxfmt is a high-performance, Prettier-compatible code formatter. Most Prettier options are supported directly.
An automated migration tool is built into oxfmt, supporting both Prettier and Biome as migration sources.
## Step 1: Run Automated Migration
### From Prettier
```bash
npx oxfmt@latest --migrate prettier
```
This will:
- Find and read your Prettier config (any format Prettier supports)
- Create `.oxfmtrc.json` with migrated options
- Migrate `.prettierignore` patterns to `ignorePatterns`
- Migrate `prettier-plugin-tailwindcss` options to `sortTailwindcss`
- Detect `prettier-plugin-packagejson` and enable `sortPackageJson`
### From Biome
```bash
npx oxfmt@latest --migrate biome
```
This will:
- Find and read `biome.json` or `biome.jsonc`
- Create `.oxfmtrc.json` with migrated options
- Migrate negated patterns from `files.includes` to `ignorePatterns`
- Map Biome's two-level config (`formatter.*` and `javascript.formatter.*`) to oxfmt options
Biome option mapping:
| Biome | oxfmt |
| ----------------------------------------------------------- | --------------------------------- |
| `formatter.indentStyle` (`"tab"`/`"space"`) | `useTabs` (`true`/`false`) |
| `formatter.indentWidth` | `tabWidth` |
| `formatter.lineWidth` | `printWidth` |
| `javascript.formatter.quoteStyle` | `singleQuote` |
| `javascript.formatter.jsxQuoteStyle` | `jsxSingleQuote` |
| `javascript.formatter.quoteProperties` (`"asNeeded"`) | `quoteProps` (`"as-needed"`) |
| `javascript.formatter.trailingCommas` | `trailingComma` |
| `javascript.formatter.semicolons` (`"always"`/`"asNeeded"`) | `semi` (`true`/`false`) |
| `javascript.formatter.arrowParentheses` (`"asNeeded"`) | `arrowParens` (`"avoid"`) |
| `formatter.bracketSameLine` | `bracketSameLine` |
| `formatter.bracketSpacing` | `bracketSpacing` |
| `formatter.attributePosition` (`"multiline"`) | `singleAttributePerLine` (`true`) |
Notes (both sources):
- Fails if `.oxfmtrc.json` already exists. Delete it first if you want to re-run.
- If no source config is found, creates a blank `.oxfmtrc.json` instead.
- `overrides` cannot be auto-migrated for either source and must be converted manually.
## Step 2: Review Generated Config
After migration, review the generated `.oxfmtrc.json` for these key differences:
### printWidth
Prettier and Biome default is 80, oxfmt default is 100. The migration tool sets `printWidth: 80` if not specified in your source config. Decide whether to keep 80 or adopt 100.
### Unsupported Options (Prettier only)
These Prettier options are skipped during migration:
| Option | Status |
| ------------------------------ | ------------------------------------------------ |
| `endOfLine: "auto"` | Not supported. Use `"lf"` or `"crlf"` explicitly |
| `experimentalTernaries` | Not supported in JS/TS files yet |
| `experimentalOperatorPosition` | Not supported in JS/TS files yet |
### sortPackageJson (Prettier only)
Enabled by default in oxfmt, but the migration tool disables it unless `prettier-plugin-packagejson` was detected. Review whether you want this enabled.
Note: Oxfmt's sorting algorithm differs from `prettier-plugin-packagejson`.
### embeddedLanguageFormatting (Prettier only)
Embedded language formatting (e.g., CSS-in-JS) generally works, but some formatting may differ from Prettier.
### overrides
The `overrides` field cannot be auto-migrated from either Prettier or Biome. Convert manually:
```json
{
"overrides": [
{
"files": ["*.md"],
"options": { "tabWidth": 4 }
}
]
}
```
### Nested Config
Oxfmt does not support nested configuration files (e.g., a separate `.oxfmtrc.json` in a subdirectory). If your project used per-directory Prettier or Biome configs, consolidate them using `overrides` with file glob patterns, or run oxfmt separately per directory with different working directories.
### Prettier-Compatible Options
These options transfer directly with the same behavior:
`tabWidth`, `useTabs`, `semi`, `singleQuote`, `jsxSingleQuote`, `quoteProps`, `trailingComma`, `arrowParens`, `bracketSpacing`, `bracketSameLine`, `endOfLine`, `proseWrap`, `htmlWhitespaceSensitivity`, `singleAttributePerLine`, `vueIndentScriptAndStyle`
## Step 3: Configure Oxfmt Extensions
Oxfmt offers features not available in Prettier:
### sortImports
Sort import statements, inspired by `eslint-plugin-perfectionist/sort-imports` (disabled by default):
```json
{
"sortImports": {
"partitionByNewline": true,
"newlinesBetween": false
}
}
```
### sortTailwindcss
Replaces `prettier-plugin-tailwindcss`. Auto-migrated with renamed options:
| Prettier (top-level) | oxfmt (`sortTailwindcss.*`) |
| ---------------------------- | --------------------------- |
| `tailwindConfig` | `config` |
| `tailwindStylesheet` | `stylesheet` |
| `tailwindFunctions` | `functions` |
| `tailwindAttributes` | `attributes` |
| `tailwindPreserveWhitespace` | `preserveWhitespace` |
| `tailwindPreserveDuplicates` | `preserveDuplicates` |
### Other Extensions
| Option | Default | Description |
| -------------------- | ------- | ---------------------------------------------------------------------------- |
| `insertFinalNewline` | `true` | Whether to add a final newline at end of file |
| `sortPackageJson` | `true` | Sort `package.json` keys. Set `{ "sortScripts": true }` to also sort scripts |
## Step 4: Update CI and Scripts
Replace formatter commands with oxfmt:
```bash
# Before (Prettier)
npx prettier --write .
npx prettier --check .
# Before (Biome)
npx biome format --write .
npx biome check .
# After
npx oxfmt@latest
npx oxfmt@latest --check
```
### Common CLI Options
| Prettier / Biome | oxfmt |
| ----------------------------------------------- | -------------------------------------------- |
| `prettier --write .` / `biome format --write .` | `oxfmt` (default: cwd, `--write` mode) |
| `prettier --check .` / `biome check .` | `oxfmt --check` |
| `prettier --list-different .` | `oxfmt --list-different` |
| `prettier --config path` | `oxfmt --config path` |
| `prettier --ignore-path .prettierignore` | `oxfmt --ignore-path .prettierignore` |
| `cat file \| prettier --stdin-filepath=file.ts` | `cat file \| oxfmt --stdin-filepath=file.ts` |
### File Type Coverage
- JS/TS: Formatted natively by oxfmt
- TOML: Formatted natively (via taplo)
- CSS, HTML, YAML, Markdown, GraphQL, etc.: Delegated to Prettier internally (when using `npx oxfmt`)
## Tips
- EditorConfig: Oxfmt reads `.editorconfig` automatically for `useTabs`, `tabWidth`, `endOfLine`, `insertFinalNewline`, and `printWidth`. Options in `.oxfmtrc.json` take precedence.
- CI: Use `npx oxfmt@latest --check` to enforce formatting in CI.
- LSP: Run `oxfmt --lsp` for editor integration via Language Server Protocol.
- Schema support: Add `"$schema": "./node_modules/oxfmt/configuration_schema.json"` to `.oxfmtrc.json` for editor autocompletion.
- Init: Run `npx oxfmt@latest --init` to create a default `.oxfmtrc.json` without migration.
## References
- [CLI Reference](https://oxc.rs/docs/guide/usage/formatter/cli.html)
- [Config File Reference](https://oxc.rs/docs/guide/usage/formatter/config-file-reference.html)
- [Unsupported Features](https://oxc.rs/docs/guide/usage/formatter/unsupported-features.html)
---
name: migrate-oxfmt
description: Guide for migrating a project from Prettier or Biome to Oxfmt. Use when asked to migrate, convert, or switch a JavaScript/TypeScript project's formatter from Prettier or Biome to Oxfmt.
---
This skill guides you through migrating a JavaScript/TypeScript project from Prettier or Biome to [Oxfmt](https://oxc.rs/docs/guide/usage/formatter).
## Overview
Oxfmt is a high-performance, Prettier-compatible code formatter. Most Prettier options are supported directly.
An automated migration tool is built into oxfmt, supporting both Prettier and Biome as migration sources.
## Step 1: Run Automated Migration
### From Prettier
```bash
npx oxfmt@latest --migrate prettier
```
This will:
- Find and read your Prettier config (any format Prettier supports)
- Create `.oxfmtrc.json` with migrated options
- Migrate `.prettierignore` patterns to `ignorePatterns`
- Migrate `prettier-plugin-tailwindcss` options to `sortTailwindcss`
- Detect `prettier-plugin-packagejson` and enable `sortPackageJson`
### From Biome
```bash
npx oxfmt@latest --migrate biome
```
This will:
- Find and read `biome.json` or `biome.jsonc`
- Create `.oxfmtrc.json` with migrated options
- Migrate negated patterns from `files.includes` to `ignorePatterns`
- Map Biome's two-level config (`formatter.*` and `javascript.formatter.*`) to oxfmt options
Biome option mapping:
| Biome | oxfmt |
| ----------------------------------------------------------- | --------------------------------- |
| `formatter.indentStyle` (`"tab"`/`"space"`) | `useTabs` (`true`/`false`) |
| `formatter.indentWidth` | `tabWidth` |
| `formatter.lineWidth` | `printWidth` |
| `javascript.formatter.quoteStyle` | `singleQuote` |
| `javascript.formatter.jsxQuoteStyle` | `jsxSingleQuote` |
| `javascript.formatter.quoteProperties` (`"asNeeded"`) | `quoteProps` (`"as-needed"`) |
| `javascript.formatter.trailingCommas` | `trailingComma` |
| `javascript.formatter.semicolons` (`"always"`/`"asNeeded"`) | `semi` (`true`/`false`) |
| `javascript.formatter.arrowParentheses` (`"asNeeded"`) | `arrowParens` (`"avoid"`) |
| `formatter.bracketSameLine` | `bracketSameLine` |
| `formatter.bracketSpacing` | `bracketSpacing` |
| `formatter.attributePosition` (`"multiline"`) | `singleAttributePerLine` (`true`) |
Notes (both sources):
- Fails if `.oxfmtrc.json` already exists. Delete it first if you want to re-run.
- If no source config is found, creates a blank `.oxfmtrc.json` instead.
- `overrides` cannot be auto-migrated for either source and must be converted manually.
## Step 2: Review Generated Config
After migration, review the generated `.oxfmtrc.json` for these key differences:
### printWidth
Prettier and Biome default is 80, oxfmt default is 100. The migration tool sets `printWidth: 80` if not specified in your source config. Decide whether to keep 80 or adopt 100.
### Unsupported Options (Prettier only)
These Prettier options are skipped during migration:
| Option | Status |
| ------------------------------ | ------------------------------------------------ |
| `endOfLine: "auto"` | Not supported. Use `"lf"` or `"crlf"` explicitly |
| `experimentalTernaries` | Not supported in JS/TS files yet |
| `experimentalOperatorPosition` | Not supported in JS/TS files yet |
### sortPackageJson (Prettier only)
Enabled by default in oxfmt, but the migration tool disables it unless `prettier-plugin-packagejson` was detected. Review whether you want this enabled.
Note: Oxfmt's sorting algorithm differs from `prettier-plugin-packagejson`.
### embeddedLanguageFormatting (Prettier only)
Embedded language formatting (e.g., CSS-in-JS) generally works, but some formatting may differ from Prettier.
### overrides
The `overrides` field cannot be auto-migrated from either Prettier or Biome. Convert manually:
```json
{
"overrides": [
{
"files": ["*.md"],
"options": { "tabWidth": 4 }
}
]
}
```
### Nested Config
Oxfmt does not support nested configuration files (e.g., a separate `.oxfmtrc.json` in a subdirectory). If your project used per-directory Prettier or Biome configs, consolidate them using `overrides` with file glob patterns, or run oxfmt separately per directory with different working directories.
### Prettier-Compatible Options
These options transfer directly with the same behavior:
`tabWidth`, `useTabs`, `semi`, `singleQuote`, `jsxSingleQuote`, `quoteProps`, `trailingComma`, `arrowParens`, `bracketSpacing`, `bracketSameLine`, `endOfLine`, `proseWrap`, `htmlWhitespaceSensitivity`, `singleAttributePerLine`, `vueIndentScriptAndStyle`
## Step 3: Configure Oxfmt Extensions
Oxfmt offers features not available in Prettier:
### sortImports
Sort import statements, inspired by `eslint-plugin-perfectionist/sort-imports` (disabled by default):
```json
{
"sortImports": {
"partitionByNewline": true,
"newlinesBetween": false
}
}
```
### sortTailwindcss
Replaces `prettier-plugin-tailwindcss`. Auto-migrated with renamed options:
| Prettier (top-level) | oxfmt (`sortTailwindcss.*`) |
| ---------------------------- | --------------------------- |
| `tailwindConfig` | `config` |
| `tailwindStylesheet` | `stylesheet` |
| `tailwindFunctions` | `functions` |
| `tailwindAttributes` | `attributes` |
| `tailwindPreserveWhitespace` | `preserveWhitespace` |
| `tailwindPreserveDuplicates` | `preserveDuplicates` |
### Other Extensions
| Option | Default | Description |
| -------------------- | ------- | ---------------------------------------------------------------------------- |
| `insertFinalNewline` | `true` | Whether to add a final newline at end of file |
| `sortPackageJson` | `true` | Sort `package.json` keys. Set `{ "sortScripts": true }` to also sort scripts |
## Step 4: Update CI and Scripts
Replace formatter commands with oxfmt:
```bash
# Before (Prettier)
npx prettier --write .
npx prettier --check .
# Before (Biome)
npx biome format --write .
npx biome check .
# After
npx oxfmt@latest
npx oxfmt@latest --check
```
### Common CLI Options
| Prettier / Biome | oxfmt |
| ----------------------------------------------- | -------------------------------------------- |
| `prettier --write .` / `biome format --write .` | `oxfmt` (default: cwd, `--write` mode) |
| `prettier --check .` / `biome check .` | `oxfmt --check` |
| `prettier --list-different .` | `oxfmt --list-different` |
| `prettier --config path` | `oxfmt --config path` |
| `prettier --ignore-path .prettierignore` | `oxfmt --ignore-path .prettierignore` |
| `cat file \| prettier --stdin-filepath=file.ts` | `cat file \| oxfmt --stdin-filepath=file.ts` |
### File Type Coverage
- JS/TS: Formatted natively by oxfmt
- TOML: Formatted natively (via taplo)
- CSS, HTML, YAML, Markdown, GraphQL, etc.: Delegated to Prettier internally (when using `npx oxfmt`)
## Tips
- EditorConfig: Oxfmt reads `.editorconfig` automatically for `useTabs`, `tabWidth`, `endOfLine`, `insertFinalNewline`, and `printWidth`. Options in `.oxfmtrc.json` take precedence.
- CI: Use `npx oxfmt@latest --check` to enforce formatting in CI.
- LSP: Run `oxfmt --lsp` for editor integration via Language Server Protocol.
- Schema support: Add `"$schema": "./node_modules/oxfmt/configuration_schema.json"` to `.oxfmtrc.json` for editor autocompletion.
- Init: Run `npx oxfmt@latest --init` to create a default `.oxfmtrc.json` without migration.
## References
- [CLI Reference](https://oxc.rs/docs/guide/usage/formatter/cli.html)
- [Config File Reference](https://oxc.rs/docs/guide/usage/formatter/config-file-reference.html)
- [Unsupported Features](https://oxc.rs/docs/guide/usage/formatter/unsupported-features.html)
{
"$schema": "https://json.schemastore.org/prettierrc",
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"semi": false,
"singleQuote": true,
"printWidth": 100
"printWidth": 100,
"sortPackageJson": false,
"ignorePatterns": []
}
......@@ -3,6 +3,6 @@
"Vue.volar",
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"esbenp.prettier-vscode"
"oxc.oxc-vscode"
]
}
<!DOCTYPE html>
<!doctype html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/webicon.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/webicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>企业文化平台</title>
</head>
</head>
<body>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</body>
</html>
......@@ -12,7 +12,8 @@
"preview": "vite preview",
"type-check": "vue-tsc --build",
"lint": "eslint . --fix --cache",
"format": "prettier --write src/",
"format": "oxfmt",
"format:check": "oxfmt --check",
"build-only": "vite build",
"build:dev": "nvm use 20 && vite build --mode development",
"build:test": "nvm use 20 && vite build --mode test",
......@@ -54,7 +55,7 @@
"eslint-plugin-vue": "~10.5.0",
"jiti": "^2.6.1",
"npm-run-all2": "^8.0.4",
"prettier": "3.6.2",
"oxfmt": "^0.44.0",
"rollup-plugin-visualizer": "^6.0.5",
"sass-embedded": "^1.93.2",
"typescript": "~5.9.0",
......
......@@ -99,9 +99,9 @@ importers:
npm-run-all2:
specifier: ^8.0.4
version: 8.0.4
prettier:
specifier: 3.6.2
version: 3.6.2
oxfmt:
specifier: ^0.44.0
version: 0.44.0
rollup-plugin-visualizer:
specifier: ^6.0.5
version: 6.0.5(rolldown@1.0.0-rc.15)(rollup@4.52.5)
......@@ -644,6 +644,120 @@ packages:
'@oxc-project/types@0.124.0':
resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==}
'@oxfmt/binding-android-arm-eabi@0.44.0':
resolution: {integrity: sha512-5UvghMd9SA/yvKTWCAxMAPXS1d2i054UeOf4iFjZjfayTwCINcC3oaSXjtbZfCaEpxgJod7XiOjTtby5yEv/BQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
'@oxfmt/binding-android-arm64@0.44.0':
resolution: {integrity: sha512-IVudM1BWfvrYO++Khtzr8q9n5Rxu7msUvoFMqzGJVdX7HfUXUDHwaH2zHZNB58svx2J56pmCUzophyaPFkcG/A==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
'@oxfmt/binding-darwin-arm64@0.44.0':
resolution: {integrity: sha512-eWCLAIKAHfx88EqEP1Ga2yz7qVcqDU5lemn4xck+07bH182hDdprOHjbogyk0In1Djys3T0/pO2JepFnRJ41Mg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
'@oxfmt/binding-darwin-x64@0.44.0':
resolution: {integrity: sha512-eHTBznHLM49++dwz07MblQ2cOXyIgeedmE3Wgy4ptUESj38/qYZyRi1MPwC9olQJWssMeY6WI3UZ7YmU5ggvyQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
'@oxfmt/binding-freebsd-x64@0.44.0':
resolution: {integrity: sha512-jLMmbj0u0Ft43QpkUVr/0v1ZfQCGWAvU+WznEHcN3wZC/q6ox7XeSJtk9P36CCpiDSUf3sGnzbIuG1KdEMEDJQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
'@oxfmt/binding-linux-arm-gnueabihf@0.44.0':
resolution: {integrity: sha512-n+A/u/ByK1qV8FVGOwyaSpw5NPNl0qlZfgTBqHeGIqr8Qzq1tyWZ4lAaxPoe5mZqE3w88vn3+jZtMxriHPE7tg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@oxfmt/binding-linux-arm-musleabihf@0.44.0':
resolution: {integrity: sha512-5eax+FkxyCqAi3Rw0mrZFr7+KTt/XweFsbALR+B5ljWBLBl8nHe4ADrUnb1gLEfQCJLl+Ca5FIVD4xEt95AwIw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@oxfmt/binding-linux-arm64-gnu@0.44.0':
resolution: {integrity: sha512-58l8JaHxSGOmOMOG2CIrNsnkRJAj0YcHQCmvNACniOa/vd1iRHhlPajczegzS5jwMENlqgreyiTR9iNlke8qCw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
'@oxfmt/binding-linux-arm64-musl@0.44.0':
resolution: {integrity: sha512-AlObQIXyVRZ96LbtVljtFq0JqH5B92NU+BQeDFrXWBUWlCKAM0wF5GLfIhCLT5kQ3Sl+U0YjRJ7Alqj5hGQaCg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
'@oxfmt/binding-linux-ppc64-gnu@0.44.0':
resolution: {integrity: sha512-YcFE8/q/BbrCiIiM5piwbkA6GwJc5QqhMQp2yDrqQ2fuVkZ7CInb1aIijZ/k8EXc72qXMSwKpVlBv1w/MsGO/A==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
'@oxfmt/binding-linux-riscv64-gnu@0.44.0':
resolution: {integrity: sha512-eOdzs6RqkRzuqNHUX5C8ISN5xfGh4xDww8OEd9YAmc3OWN8oAe5bmlIqQ+rrHLpv58/0BuU48bxkhnIGjA/ATQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
'@oxfmt/binding-linux-riscv64-musl@0.44.0':
resolution: {integrity: sha512-YBgNTxntD/QvlFUfgvh8bEdwOhXiquX8gaofZJAwYa/Xp1S1DQrFVZEeck7GFktr24DztsSp8N8WtWCBwxs0Hw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
'@oxfmt/binding-linux-s390x-gnu@0.44.0':
resolution: {integrity: sha512-GLIh1R6WHWshl/i4QQDNgj0WtT25aRO4HNUWEoitxiywyRdhTFmFEYT2rXlcl9U6/26vhmOqG5cRlMLG3ocaIA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
'@oxfmt/binding-linux-x64-gnu@0.44.0':
resolution: {integrity: sha512-gZOpgTlOsLcLfAF9qgpTr7FIIFSKnQN3hDf/0JvQ4CIwMY7h+eilNjxq/CorqvYcEOu+LRt1W4ZS7KccEHLOdA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
'@oxfmt/binding-linux-x64-musl@0.44.0':
resolution: {integrity: sha512-1CyS9JTB+pCUFYFI6pkQGGZaT/AY5gnhHVrQQLhFba6idP9AzVYm1xbdWfywoldTYvjxQJV6x4SuduCIfP3W+A==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
'@oxfmt/binding-openharmony-arm64@0.44.0':
resolution: {integrity: sha512-bmEv70Ak6jLr1xotCbF5TxIKjsmQaiX+jFRtnGtfA03tJPf6VG3cKh96S21boAt3JZc+Vjx8PYcDuLj39vM2Pw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
'@oxfmt/binding-win32-arm64-msvc@0.44.0':
resolution: {integrity: sha512-yWzB+oCpSnP/dmw85eFLAT5o35Ve5pkGS2uF/UCISpIwDqf1xa7OpmtomiqY/Vzg8VyvMbuf6vroF2khF/+1Vg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
'@oxfmt/binding-win32-ia32-msvc@0.44.0':
resolution: {integrity: sha512-TcWpo18xEIE3AmIG2kpr3kz5IEhQgnx0lazl2+8L+3eTopOAUevQcmlr4nhguImNWz0OMeOZrYZOhJNCf16nlQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ia32]
os: [win32]
'@oxfmt/binding-win32-x64-msvc@0.44.0':
resolution: {integrity: sha512-oj8aLkPJZppIM4CMQNsyir9ybM1Xw/CfGPTSsTnzpVGyljgfbdP0EVUlURiGM0BDrmw5psQ6ArmGCcUY/yABaQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
'@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'}
......@@ -3076,6 +3190,11 @@ packages:
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
engines: {node: '>= 0.4'}
oxfmt@0.44.0:
resolution: {integrity: sha512-lnncqvHewyRvaqdrnntVIrZV2tEddz8lbvPsQzG/zlkfvgZkwy0HP1p/2u1aCDToeg1jb9zBpbJdfkV73Itw+w==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
......@@ -3748,6 +3867,10 @@ packages:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'}
tinypool@2.1.0:
resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==}
engines: {node: ^20.0.0 || >=22.0.0}
to-object-path@0.3.0:
resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==}
engines: {node: '>=0.10.0'}
......@@ -4794,6 +4917,63 @@ snapshots:
'@oxc-project/types@0.124.0': {}
'@oxfmt/binding-android-arm-eabi@0.44.0':
optional: true
'@oxfmt/binding-android-arm64@0.44.0':
optional: true
'@oxfmt/binding-darwin-arm64@0.44.0':
optional: true
'@oxfmt/binding-darwin-x64@0.44.0':
optional: true
'@oxfmt/binding-freebsd-x64@0.44.0':
optional: true
'@oxfmt/binding-linux-arm-gnueabihf@0.44.0':
optional: true
'@oxfmt/binding-linux-arm-musleabihf@0.44.0':
optional: true
'@oxfmt/binding-linux-arm64-gnu@0.44.0':
optional: true
'@oxfmt/binding-linux-arm64-musl@0.44.0':
optional: true
'@oxfmt/binding-linux-ppc64-gnu@0.44.0':
optional: true
'@oxfmt/binding-linux-riscv64-gnu@0.44.0':
optional: true
'@oxfmt/binding-linux-riscv64-musl@0.44.0':
optional: true
'@oxfmt/binding-linux-s390x-gnu@0.44.0':
optional: true
'@oxfmt/binding-linux-x64-gnu@0.44.0':
optional: true
'@oxfmt/binding-linux-x64-musl@0.44.0':
optional: true
'@oxfmt/binding-openharmony-arm64@0.44.0':
optional: true
'@oxfmt/binding-win32-arm64-msvc@0.44.0':
optional: true
'@oxfmt/binding-win32-ia32-msvc@0.44.0':
optional: true
'@oxfmt/binding-win32-x64-msvc@0.44.0':
optional: true
'@parcel/watcher-android-arm64@2.5.1':
optional: true
......@@ -7363,6 +7543,30 @@ snapshots:
object-keys: 1.1.1
safe-push-apply: 1.0.0
oxfmt@0.44.0:
dependencies:
tinypool: 2.1.0
optionalDependencies:
'@oxfmt/binding-android-arm-eabi': 0.44.0
'@oxfmt/binding-android-arm64': 0.44.0
'@oxfmt/binding-darwin-arm64': 0.44.0
'@oxfmt/binding-darwin-x64': 0.44.0
'@oxfmt/binding-freebsd-x64': 0.44.0
'@oxfmt/binding-linux-arm-gnueabihf': 0.44.0
'@oxfmt/binding-linux-arm-musleabihf': 0.44.0
'@oxfmt/binding-linux-arm64-gnu': 0.44.0
'@oxfmt/binding-linux-arm64-musl': 0.44.0
'@oxfmt/binding-linux-ppc64-gnu': 0.44.0
'@oxfmt/binding-linux-riscv64-gnu': 0.44.0
'@oxfmt/binding-linux-riscv64-musl': 0.44.0
'@oxfmt/binding-linux-s390x-gnu': 0.44.0
'@oxfmt/binding-linux-x64-gnu': 0.44.0
'@oxfmt/binding-linux-x64-musl': 0.44.0
'@oxfmt/binding-openharmony-arm64': 0.44.0
'@oxfmt/binding-win32-arm64-msvc': 0.44.0
'@oxfmt/binding-win32-ia32-msvc': 0.44.0
'@oxfmt/binding-win32-x64-msvc': 0.44.0
p-limit@3.1.0:
dependencies:
yocto-queue: 0.1.0
......@@ -8112,6 +8316,8 @@ snapshots:
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
tinypool@2.1.0: {}
to-object-path@0.3.0:
dependencies:
kind-of: 3.2.2
......
{
"version": 1,
"skills": {
"migrate-oxfmt": {
"source": "oxc-project/oxc",
"sourceType": "github",
"computedHash": "b3ae0d11b61d07471cf466ba0386490a9f7ed5c1186d4956a58ac55a4b6be6ad"
}
}
}
---
name: migrate-oxfmt
description: Guide for migrating a project from Prettier or Biome to Oxfmt. Use when asked to migrate, convert, or switch a JavaScript/TypeScript project's formatter from Prettier or Biome to Oxfmt.
---
This skill guides you through migrating a JavaScript/TypeScript project from Prettier or Biome to [Oxfmt](https://oxc.rs/docs/guide/usage/formatter).
## Overview
Oxfmt is a high-performance, Prettier-compatible code formatter. Most Prettier options are supported directly.
An automated migration tool is built into oxfmt, supporting both Prettier and Biome as migration sources.
## Step 1: Run Automated Migration
### From Prettier
```bash
npx oxfmt@latest --migrate prettier
```
This will:
- Find and read your Prettier config (any format Prettier supports)
- Create `.oxfmtrc.json` with migrated options
- Migrate `.prettierignore` patterns to `ignorePatterns`
- Migrate `prettier-plugin-tailwindcss` options to `sortTailwindcss`
- Detect `prettier-plugin-packagejson` and enable `sortPackageJson`
### From Biome
```bash
npx oxfmt@latest --migrate biome
```
This will:
- Find and read `biome.json` or `biome.jsonc`
- Create `.oxfmtrc.json` with migrated options
- Migrate negated patterns from `files.includes` to `ignorePatterns`
- Map Biome's two-level config (`formatter.*` and `javascript.formatter.*`) to oxfmt options
Biome option mapping:
| Biome | oxfmt |
| ----------------------------------------------------------- | --------------------------------- |
| `formatter.indentStyle` (`"tab"`/`"space"`) | `useTabs` (`true`/`false`) |
| `formatter.indentWidth` | `tabWidth` |
| `formatter.lineWidth` | `printWidth` |
| `javascript.formatter.quoteStyle` | `singleQuote` |
| `javascript.formatter.jsxQuoteStyle` | `jsxSingleQuote` |
| `javascript.formatter.quoteProperties` (`"asNeeded"`) | `quoteProps` (`"as-needed"`) |
| `javascript.formatter.trailingCommas` | `trailingComma` |
| `javascript.formatter.semicolons` (`"always"`/`"asNeeded"`) | `semi` (`true`/`false`) |
| `javascript.formatter.arrowParentheses` (`"asNeeded"`) | `arrowParens` (`"avoid"`) |
| `formatter.bracketSameLine` | `bracketSameLine` |
| `formatter.bracketSpacing` | `bracketSpacing` |
| `formatter.attributePosition` (`"multiline"`) | `singleAttributePerLine` (`true`) |
Notes (both sources):
- Fails if `.oxfmtrc.json` already exists. Delete it first if you want to re-run.
- If no source config is found, creates a blank `.oxfmtrc.json` instead.
- `overrides` cannot be auto-migrated for either source and must be converted manually.
## Step 2: Review Generated Config
After migration, review the generated `.oxfmtrc.json` for these key differences:
### printWidth
Prettier and Biome default is 80, oxfmt default is 100. The migration tool sets `printWidth: 80` if not specified in your source config. Decide whether to keep 80 or adopt 100.
### Unsupported Options (Prettier only)
These Prettier options are skipped during migration:
| Option | Status |
| ------------------------------ | ------------------------------------------------ |
| `endOfLine: "auto"` | Not supported. Use `"lf"` or `"crlf"` explicitly |
| `experimentalTernaries` | Not supported in JS/TS files yet |
| `experimentalOperatorPosition` | Not supported in JS/TS files yet |
### sortPackageJson (Prettier only)
Enabled by default in oxfmt, but the migration tool disables it unless `prettier-plugin-packagejson` was detected. Review whether you want this enabled.
Note: Oxfmt's sorting algorithm differs from `prettier-plugin-packagejson`.
### embeddedLanguageFormatting (Prettier only)
Embedded language formatting (e.g., CSS-in-JS) generally works, but some formatting may differ from Prettier.
### overrides
The `overrides` field cannot be auto-migrated from either Prettier or Biome. Convert manually:
```json
{
"overrides": [
{
"files": ["*.md"],
"options": { "tabWidth": 4 }
}
]
}
```
### Nested Config
Oxfmt does not support nested configuration files (e.g., a separate `.oxfmtrc.json` in a subdirectory). If your project used per-directory Prettier or Biome configs, consolidate them using `overrides` with file glob patterns, or run oxfmt separately per directory with different working directories.
### Prettier-Compatible Options
These options transfer directly with the same behavior:
`tabWidth`, `useTabs`, `semi`, `singleQuote`, `jsxSingleQuote`, `quoteProps`, `trailingComma`, `arrowParens`, `bracketSpacing`, `bracketSameLine`, `endOfLine`, `proseWrap`, `htmlWhitespaceSensitivity`, `singleAttributePerLine`, `vueIndentScriptAndStyle`
## Step 3: Configure Oxfmt Extensions
Oxfmt offers features not available in Prettier:
### sortImports
Sort import statements, inspired by `eslint-plugin-perfectionist/sort-imports` (disabled by default):
```json
{
"sortImports": {
"partitionByNewline": true,
"newlinesBetween": false
}
}
```
### sortTailwindcss
Replaces `prettier-plugin-tailwindcss`. Auto-migrated with renamed options:
| Prettier (top-level) | oxfmt (`sortTailwindcss.*`) |
| ---------------------------- | --------------------------- |
| `tailwindConfig` | `config` |
| `tailwindStylesheet` | `stylesheet` |
| `tailwindFunctions` | `functions` |
| `tailwindAttributes` | `attributes` |
| `tailwindPreserveWhitespace` | `preserveWhitespace` |
| `tailwindPreserveDuplicates` | `preserveDuplicates` |
### Other Extensions
| Option | Default | Description |
| -------------------- | ------- | ---------------------------------------------------------------------------- |
| `insertFinalNewline` | `true` | Whether to add a final newline at end of file |
| `sortPackageJson` | `true` | Sort `package.json` keys. Set `{ "sortScripts": true }` to also sort scripts |
## Step 4: Update CI and Scripts
Replace formatter commands with oxfmt:
```bash
# Before (Prettier)
npx prettier --write .
npx prettier --check .
# Before (Biome)
npx biome format --write .
npx biome check .
# After
npx oxfmt@latest
npx oxfmt@latest --check
```
### Common CLI Options
| Prettier / Biome | oxfmt |
| ----------------------------------------------- | -------------------------------------------- |
| `prettier --write .` / `biome format --write .` | `oxfmt` (default: cwd, `--write` mode) |
| `prettier --check .` / `biome check .` | `oxfmt --check` |
| `prettier --list-different .` | `oxfmt --list-different` |
| `prettier --config path` | `oxfmt --config path` |
| `prettier --ignore-path .prettierignore` | `oxfmt --ignore-path .prettierignore` |
| `cat file \| prettier --stdin-filepath=file.ts` | `cat file \| oxfmt --stdin-filepath=file.ts` |
### File Type Coverage
- JS/TS: Formatted natively by oxfmt
- TOML: Formatted natively (via taplo)
- CSS, HTML, YAML, Markdown, GraphQL, etc.: Delegated to Prettier internally (when using `npx oxfmt`)
## Tips
- EditorConfig: Oxfmt reads `.editorconfig` automatically for `useTabs`, `tabWidth`, `endOfLine`, `insertFinalNewline`, and `printWidth`. Options in `.oxfmtrc.json` take precedence.
- CI: Use `npx oxfmt@latest --check` to enforce formatting in CI.
- LSP: Run `oxfmt --lsp` for editor integration via Language Server Protocol.
- Schema support: Add `"$schema": "./node_modules/oxfmt/configuration_schema.json"` to `.oxfmtrc.json` for editor autocompletion.
- Init: Run `npx oxfmt@latest --init` to create a default `.oxfmtrc.json` without migration.
## References
- [CLI Reference](https://oxc.rs/docs/guide/usage/formatter/cli.html)
- [Config File Reference](https://oxc.rs/docs/guide/usage/formatter/config-file-reference.html)
- [Unsupported Features](https://oxc.rs/docs/guide/usage/formatter/unsupported-features.html)
......@@ -23,10 +23,15 @@ export default function ExchangeContent(
<div class="py-4">
{/* 商品信息卡片 */}
<div class="flex gap-4 p-4 bg-gray-50 rounded-xl mb-5">
<div class="w-24 h-24 bg-white rounded-xl overflow-hidden shadow-sm shrink-0
flex items-center justify-center p-2">
<img src={item.imageUrl} alt={item.name}
class="max-w-full max-h-full object-contain rounded-lg" />
<div
class="w-24 h-24 bg-white rounded-xl overflow-hidden shadow-sm shrink-0
flex items-center justify-center p-2"
>
<img
src={item.imageUrl}
alt={item.name}
class="max-w-full max-h-full object-contain rounded-lg"
/>
</div>
<div class="flex flex-col justify-center min-w-0 gap-1.5">
<div class="text-base font-semibold text-gray-800 line-clamp-2">{item.name}</div>
......@@ -82,7 +87,9 @@ export default function ExchangeContent(
<span class="text-sm text-gray-500">
合计扣除
{modelValue.num > 1 && (
<span class="text-gray-400 text-xs ml-1">({item.price} × {modelValue.num})</span>
<span class="text-gray-400 text-xs ml-1">
({item.price} × {modelValue.num})
</span>
)}
</span>
<div class="flex items-baseline gap-0.5">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment