> For AI agents: the complete documentation index is available at /zh/llms.txt, the full documentation bundle is available at /zh/llms-full.txt.

# 格式化 \{#formatting}

Rstack CLI 提供了基于 [Prettier](https://prettier.io/) 的格式化工具。相比直接使用 Prettier，`rs fmt` 的性能更好，主要得益于以下两点：

- **并行格式化**：通过 worker 池并行格式化文件。
- **Yuku 解析器**：默认使用高性能的 [Yuku](https://yuku.fyi/) 解析器处理 JavaScript、JSX 和 TypeScript 文件。
- **持久化缓存**：基于文件内容缓存结果，后续运行可以跳过未变化文件的格式化。

`rs fmt` 兼容 Prettier 的选项和插件，并提供更多内置能力，例如支持[排序 package.json 字段](#sort-package-json)。

## 基本用法 \{#basic-usage}

直接运行 `rs fmt`，即可格式化当前目录中的文件并保存修改：

```bash
rs fmt
```

使用 `--check` 检查文件是否已格式化，而不修改文件：

```bash
rs fmt --check
```

更多命令行选项请参考 [`rs fmt` CLI 文档](/zh/guide/cli/fmt.md)。

## 配置 \{#configuration}

在 `rstack.config.ts` 中使用 [`define.fmt()`](/zh/guide/configuration.md#define-fmt) 设置格式化规则。它支持所有的 [Prettier 选项](https://prettier.io/docs/options)：

```ts title="rstack.config.ts"
import { define } from 'rstack';

define.fmt({
  printWidth: 100,
  singleQuote: true,
});
```

除了 Prettier 选项和 `overrides`，Rstack CLI 还提供两个选项：

- [`ignorePatterns`](#ignore-files)：使用兼容 Gitignore 的模式排除文件。
- [`sortPackageJson`](#sort-package-json)：对 `package.json` 中的字段排序，默认值为 `false`。

:::warning Prettier 配置文件

`rs fmt` 不会自动加载 Prettier 配置文件、`.prettierignore` 或 `.editorconfig`。请在 `define.fmt()` 中设置格式化选项和额外的忽略规则。如需显式加载 ignore 文件，请使用 [`--ignore-path`](/zh/guide/cli/fmt.md#--ignore-path-path)。

:::

## 支持的语言 \{#supported-languages}

`rs fmt` 支持与 [Prettier](https://prettier.io/docs/) 相同的内置语言，通常会根据文件名自动推断语言：

- [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)、[JSX](https://react.github.io/jsx/)、[Flow](https://flow.org/) 和 [TypeScript](https://www.typescriptlang.org/)
- [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS)、[Less](https://lesscss.org/) 和 [SCSS](https://sass-lang.com/)
- [HTML](https://en.wikipedia.org/wiki/HTML)、[Angular](https://angular.dev/)、[Vue](https://vuejs.org/)、[Ember/Handlebars](https://emberjs.com/)、[Lightning Web Components（LWC）](https://developer.salesforce.com/developer-centers/lightning-web-components) 和 [MJML](https://mjml.io/)
- [JSON](https://json.org/) 和 [YAML](https://yaml.org/)
- [GraphQL](https://graphql.org/)
- [Markdown](https://commonmark.org/)，包括 [GFM](https://github.github.com/gfm/) 和 [MDX v1](https://mdxjs.com/)

你可以通过 [Prettier 插件](#prettier-plugins)支持其他语言。

## 格式化范围 \{#formatting-scope}

`rs fmt` 根据命令行中传入的路径确定格式化范围。以下输入可以组合使用：

- **文件**：只格式化指定文件。
- **目录**：递归扫描目录并格式化支持的文件。
- **glob 模式**：匹配多个路径，并通过以 `!` 开头的模式排除匹配结果。

不传入路径时，`rs fmt` 默认格式化当前目录。所有 glob 模式都基于当前工作目录解析。请为 glob 添加引号，避免它们被 shell 提前展开：

```bash
# 格式化一个目录和一个文件
rs fmt src package.json

# 格式化 JavaScript 和 TypeScript 文件，并排除生成文件
rs fmt "src/**/*.{js,ts}" "!src/generated/**"
```

扫描目录或 glob 时，`rs fmt` 会遵循 `.gitignore` 规则、跳过二进制文件，并且不会遍历版本控制目录或 `node_modules`。Prettier 无法推断解析器的文件也会被跳过。

`.gitignore` 只在扫描目录和 glob 时生效，不会排除命令行中显式传入的文件。如果需要始终排除某个文件，请使用 [`ignorePatterns`](#ignore-files)。

## 忽略文件 \{#ignore-files}

使用 `ignorePatterns` 排除不需要格式化的文件：

```ts title="rstack.config.ts"
import { define } from 'rstack';

define.fmt({
  ignorePatterns: ['dist/**', 'coverage/**', '**/generated/**'],
});
```

这些模式遵循 Gitignore 语法，并且基于 Rstack 配置文件所在的目录解析。由于规则会在确定格式化范围后生效，因此也会排除命令行中显式传入的文件。

### Lock 文件 \{#lock-files}

`rs fmt` 默认忽略常见的 lock 文件，包括 `package-lock.json`、`pnpm-lock.yaml` 和 `skills-lock.json`。

如果你需要格式化这些文件，可以使用否定模式主动包含它们：

```ts title="rstack.config.ts"
import { define } from 'rstack';

define.fmt({
  ignorePatterns: ['!pnpm-lock.yaml'],
});
```

### 忽略顺序 \{#ignore-order}

`rs fmt` 会通过以下三个步骤，决定需要格式化哪些路径：

1. **处理命令行参数和 `.gitignore`**：首先处理命令行中指定的文件、目录和 glob 模式。以 `!` 开头的 glob 模式用于排除路径。扫描目录或 glob 模式时会遵循 `.gitignore`，直接指定的文件则不会。在这一步被排除的路径无法被后续规则重新包含。
2. **应用默认忽略规则和 `ignorePatterns`**：默认忽略 [lock 文件](#lock-files)，随后应用 `ignorePatterns`。这些规则按顺序匹配，后面的规则优先。例如，`!pnpm-lock.yaml` 可以重新包含默认忽略的文件。
3. **应用 [`--ignore-path`](/zh/guide/cli/fmt.md#--ignore-path-path) 指定的文件**：每个 ignore 文件单独匹配，同一文件中后面的规则优先。不同 ignore 文件与 `ignorePatterns` 的排除结果会叠加：只要任一来源忽略某个路径，该路径就会保持排除，即使其他来源尝试重新包含它。

> 即使命令行直接指定了某个文件，默认忽略规则、`ignorePatterns` 和 `--ignore-path` 中的规则仍然有效。通过 [`--stdin-filepath`](/zh/guide/cli/fmt.md#--stdin-filepath-path) 指定的路径，以及通过 [`--lsp`](/zh/guide/cli/fmt.md#--lsp) 格式化的文档也是如此。

## 排序 package.json 字段 \{#sort-package-json}

启用 `sortPackageJson` 后，`rs fmt` 会使用 [`sort-package-json`](https://github.com/keithamus/sort-package-json) 对每个待格式化的 `package.json` 中的字段排序：

```ts title="rstack.config.ts"
import { define } from 'rstack';

define.fmt({
  sortPackageJson: true,
});
```

## 覆盖配置 \{#overrides}

通过 `overrides` 字段，可以为特定文件单独设置格式化选项。每一项都支持以下字段：

- `files`：需要应用格式化选项的文件或 glob 模式。
- `options`：应用于匹配文件的格式化选项。
- `excludeFiles`：可选，需要从匹配结果中排除的文件或 glob 模式。

```ts title="rstack.config.ts"
import { define } from 'rstack';

define.fmt({
  overrides: [
    {
      files: 'docs/**/*.md',
      excludeFiles: 'docs/generated/**',
      options: {
        proseWrap: 'always',
      },
    },
  ],
});
```

### 模式匹配 \{#pattern-matching}

`files` 和 `excludeFiles` 模式都基于 Rstack 配置文件所在目录解析。

在 `files` 中，不包含 `/` 的模式会匹配任意深度的文件名，包含 `/` 的模式则匹配相对路径。下面示例中的 `*.md` 会匹配任意目录中的 Markdown 文件，而 `scripts/**/*.js` 会匹配相对于 Rstack 配置文件所在目录的路径：

```ts
define.fmt({
  overrides: [
    { files: '*.md', options: { proseWrap: 'always' } },
    { files: 'scripts/**/*.js', options: { singleQuote: true } },
  ],
});
```

### 合并顺序 \{#merge-order}

如果同一文件匹配多条 override 规则，Rstack CLI 会按声明顺序合并配置，后面的值优先。下面的 `README.md` 会同时匹配两条规则，因此最终的 `printWidth` 为 `80`：

```ts
define.fmt({
  overrides: [
    { files: '*.md', options: { printWidth: 100 } },
    { files: 'README.md', options: { printWidth: 80 } },
  ],
});
```

## 缓存 \{#cache}

`rs fmt` 默认会在基于文件的 `--write`、`--check` 和 `--list-different` 调用中使用持久化缓存。格式化结果基于文件内容和最终格式化选项；任意一项发生变化时，文件都会重新格式化。不支持的 parser 查询结果通常基于文件路径和最终选项。对于没有扩展名的文件，还会基于文件内容，因为 Prettier 可能从 shebang 推断 parser。已安装的 Prettier 插件通过包名、版本和入口进行识别；本地插件、链接插件或缺少版本信息的插件会绕过缓存。

默认缓存目录位于 Rstack 配置根目录下的 `.rstack/cache/fmt`。从子目录运行命令时，仍会使用解析到的 `rstack.config.*` 文件旁的缓存。stdin 格式化不会使用该缓存。

使用 [`--cache-location <path>`](/zh/guide/cli/fmt.md#--cache-location-path) 可以将缓存保存到其他目录。相对路径基于当前工作目录解析。自定义目录会从文件发现中排除，但不会被 Git 自动忽略。

使用 [`--no-cache`](/zh/guide/cli/fmt.md#--no-cache) 可以在运行时跳过缓存读取、创建和更新：

```bash
rs fmt --no-cache
```

可以安全删除 `.rstack/cache` 来清理缓存结果。不要将整个 `.rstack` 目录视为可随意删除的内容，因为其中还可能包含用户维护的 Git hook 脚本。

## Prettier 插件 \{#prettier-plugins}

如果需要使用 Rstack CLI 未内置的格式化能力，可以安装相应的 [Prettier 插件](https://prettier.io/docs/plugins)，并添加到 `plugins` 中。插件支持通过包名、文件路径或 URL 引用，其中包名和相对路径基于 Rstack 配置文件所在的目录解析。

由于 `rs fmt` 会在 worker 中加载插件，因此不支持直接传入插件对象。请通过包名、路径或 URL 引用插件。

例如，安装并启用 [`prettier-plugin-tailwindcss`](https://github.com/tailwindlabs/prettier-plugin-tailwindcss)：


```sh [npm]
npm install -D prettier-plugin-tailwindcss
```

```sh [yarn]
yarn add -D prettier-plugin-tailwindcss
```

```sh [pnpm]
pnpm add -D prettier-plugin-tailwindcss
```

```sh [bun]
bun add -D prettier-plugin-tailwindcss
```

```sh [deno]
deno add -D npm:prettier-plugin-tailwindcss
```

```ts title="rstack.config.ts"
import { define } from 'rstack';

define.fmt({
  plugins: ['prettier-plugin-tailwindcss'],
});
```

如果只需要为特定文件启用插件，可以在 [`overrides`](#overrides) 的 `options` 中配置 `plugins`。
