diff --git a/website/docs/en/guide/cli/_meta.json b/website/docs/en/guide/cli/_meta.json index c4e4d09..0f31a84 100644 --- a/website/docs/en/guide/cli/_meta.json +++ b/website/docs/en/guide/cli/_meta.json @@ -1 +1 @@ -["dev", "build", "preview", "lib", "doc", "test", "lint", "setup", "staged"] +["dev", "build", "preview", "lib", "doc", "test", "lint", "fmt", "setup", "staged"] diff --git a/website/docs/en/guide/cli/fmt.mdx b/website/docs/en/guide/cli/fmt.mdx new file mode 100644 index 0000000..506037c --- /dev/null +++ b/website/docs/en/guide/cli/fmt.mdx @@ -0,0 +1,81 @@ +# fmt + +The `rs fmt` command is built on [Prettier](https://prettier.io/). It processes files in parallel by default and uses the high-performance [Yuku](https://yuku.fyi/) parser for JavaScript and TypeScript, providing better performance than using Prettier directly. + +## Usage + +```bash +rs fmt [options] [files/globs...] +``` + +Pass files, directories, or glob patterns to select what to format. When no inputs are provided, `rs fmt` formats the current directory. `rs format` is an alias for `rs fmt`. + +## Options + +| Option | Description | +| ---------------------------- | ----------------------------------------------------------------------------------- | +| `--write` | Write formatted files in place. This is the default mode. | +| `--check` | Check formatting without writing files. Exits with code 1 when files are different. | +| `--list-different` | Print only unformatted paths. Exits with code 1 when files are different. | +| `--parallel-workers ` | Set the maximum number of formatting workers. | +| `-h, --help` | Display usage and option information. | + +`--write`, `--check`, and `--list-different` are mutually exclusive. + +Examples: + +```bash +# Format the current directory in place +rs fmt + +# Format specific files and directories +rs fmt src package.json + +# Include and exclude files with quoted globs +rs fmt "src/**/*.{js,ts}" "!src/generated/**" + +# Check formatting in CI +rs fmt --check +``` + +## File discovery + +Directory and glob discovery follows `.gitignore` files, skips binary files, and does not traverse version-control directories or `node_modules`. Files for which Prettier cannot infer a parser are skipped. + +Use [`ignorePatterns`](../configuration#define-fmt) for additional project-specific exclusions. Both positive and negative input globs are resolved from the current working directory. + +## Configuration + +Configure formatting through [`define.fmt()`](../configuration#define-fmt) in the [Rstack configuration file](/guide/configuration#configuration-file): + +```ts title="rstack.config.ts" +import { define } from 'rstack'; + +define.fmt({ + printWidth: 100, + singleQuote: true, + sortPackageJson: true, + ignorePatterns: ['dist/**'], + overrides: [ + { + files: '*.md', + options: { + proseWrap: 'always', + }, + }, + ], +}); +``` + +`define.fmt()` accepts standard [Prettier options](https://prettier.io/docs/options) and the `overrides` field, plus these Rstack options: + +- `ignorePatterns`: Gitignore-compatible patterns relative to the directory containing `rstack.config.ts`. +- `sortPackageJson`: Sort `package.json` fields before formatting. The default value is `false`. + +:::warning Configuration sources + +`rs fmt` does not load Prettier configuration files, `.prettierignore`, or `.editorconfig`. Move those settings and ignore rules into `define.fmt()`. + +::: + +When using [Prettier plugins](https://prettier.io/docs/plugins), pass each plugin as a package name, file path, or URL. Imported plugin objects are not supported because formatting runs in workers. Package names and relative paths are resolved from the Rstack configuration directory. diff --git a/website/docs/en/guide/cli/staged.mdx b/website/docs/en/guide/cli/staged.mdx index e80cce4..0ff122f 100644 --- a/website/docs/en/guide/cli/staged.mdx +++ b/website/docs/en/guide/cli/staged.mdx @@ -96,6 +96,7 @@ Configure staged-file tasks through [`define.staged()`](../configuration#define- import { define } from 'rstack'; define.staged({ - '*.{js,jsx,ts,tsx}': 'rs lint', + '*.{js,jsx,ts,tsx}': ['rs lint', 'rs fmt'], + '*.{json,md,mdx,css,html}': 'rs fmt', }); ``` diff --git a/website/docs/en/guide/configuration.mdx b/website/docs/en/guide/configuration.mdx index 2dd823f..e405a8a 100644 --- a/website/docs/en/guide/configuration.mdx +++ b/website/docs/en/guide/configuration.mdx @@ -21,6 +21,10 @@ define.test({ define.lint({ // Rslint configuration }); + +define.fmt({ + // Formatting configuration +}); ``` The configuration file does not require a default export. Each `define.*()` API can be called at most once; defining the same configuration type more than once throws an error. @@ -67,6 +71,7 @@ Configuration options follow the formats of the underlying tools. When using API | [`define.doc()`](#define-doc) | [Rspress](https://rspress.rs/api/config/config-basic) | [`rs doc`](./cli/doc) | | [`define.test()`](#define-test) | [Rstest](https://rstest.rs/config/) | [`rs test`](./cli/test) | | [`define.lint()`](#define-lint) | [Rslint](https://rslint.rs/config/) | [`rs lint`](./cli/lint) | +| [`define.fmt()`](#define-fmt) | [Prettier](https://prettier.io/docs/options) | [`rs fmt`](./cli/fmt) | | [`define.staged()`](#define-staged) | [lint-staged](https://github.com/lint-staged/lint-staged#configuration) | [`rs staged`](./cli/staged) | ### `define.app()` \{#define-app} @@ -161,6 +166,35 @@ define.lint(async () => { }); ``` +### `define.fmt()` \{#define-fmt} + +Defines the formatting configuration used by [`rs fmt`](./cli/fmt). Pass the configuration directly, or return it from a synchronous or asynchronous function. + +`define.fmt()` accepts standard [Prettier options](https://prettier.io/docs/options) and the `overrides` field. It also supports `ignorePatterns` for Gitignore-compatible exclusions and `sortPackageJson` for sorting `package.json` fields before formatting. + +```ts title="rstack.config.ts" +import { define } from 'rstack'; + +define.fmt({ + printWidth: 100, + singleQuote: true, + sortPackageJson: true, + ignorePatterns: ['dist/**'], + overrides: [ + { + files: '*.md', + options: { + proseWrap: 'always', + }, + }, + ], +}); +``` + +Ignore patterns, override patterns, and relative plugin paths are resolved from the directory containing the Rstack configuration file. Specify Prettier plugins as package names, paths, or URLs rather than imported plugin objects. + +`rs fmt` does not load Prettier configuration files, `.prettierignore`, or `.editorconfig`; keep all formatting options and ignore rules in `define.fmt()`. + ### `define.staged()` \{#define-staged} Defines the [lint-staged configuration](https://github.com/lint-staged/lint-staged#configuration) used to run tasks on staged Git files. It accepts either an object that maps glob patterns to tasks or a task-generator function. Tasks can be commands, command arrays, or functions supported by lint-staged. @@ -169,7 +203,8 @@ Defines the [lint-staged configuration](https://github.com/lint-staged/lint-stag import { define } from 'rstack'; define.staged({ - '*.{js,jsx,ts,tsx}': 'rs lint', + '*.{js,jsx,ts,tsx}': ['rs lint', 'rs fmt'], + '*.{json,jsonc,md,mdx,css,html,yml,yaml}': 'rs fmt', }); ``` diff --git a/website/docs/en/guide/quick-start.mdx b/website/docs/en/guide/quick-start.mdx index 12d1810..7c90789 100644 --- a/website/docs/en/guide/quick-start.mdx +++ b/website/docs/en/guide/quick-start.mdx @@ -44,7 +44,8 @@ Add the commands your project needs to the `scripts` field in `package.json`. Fo "build": "rs build", "preview": "rs preview", "test": "rs test", - "lint": "rs lint" + "lint": "rs lint", + "format": "rs fmt" } } ``` @@ -60,6 +61,7 @@ The following commands are available: - [`rs doc`](./cli/doc): Develop, build, or preview a documentation site with Rspress. - [`rs test`](./cli/test): Run tests with Rstest. - [`rs lint`](./cli/lint): Lint source code with Rslint. +- [`rs fmt`](./cli/fmt): Format code. - [`rs setup`](./cli/setup): Install project-local Git hooks. - [`rs staged`](./cli/staged): Run tasks against files staged in Git with lint-staged. diff --git a/website/docs/zh/guide/cli/_meta.json b/website/docs/zh/guide/cli/_meta.json index c4e4d09..0f31a84 100644 --- a/website/docs/zh/guide/cli/_meta.json +++ b/website/docs/zh/guide/cli/_meta.json @@ -1 +1 @@ -["dev", "build", "preview", "lib", "doc", "test", "lint", "setup", "staged"] +["dev", "build", "preview", "lib", "doc", "test", "lint", "fmt", "setup", "staged"] diff --git a/website/docs/zh/guide/cli/fmt.mdx b/website/docs/zh/guide/cli/fmt.mdx new file mode 100644 index 0000000..8a6f4b2 --- /dev/null +++ b/website/docs/zh/guide/cli/fmt.mdx @@ -0,0 +1,81 @@ +# fmt + +`rs fmt` 命令底层基于 [Prettier](https://prettier.io/)。它默认并行处理文件,并使用高性能的 [Yuku](https://yuku.fyi/) 解析器处理 JavaScript 和 TypeScript,相比于直接使用 Prettier 具有更好的性能。 + +## 用法 \{#usage} + +```bash +rs fmt [options] [files/globs...] +``` + +可以传入文件、目录或 glob 模式来指定格式化范围。未传入目标时,`rs fmt` 会格式化当前目录。`rs format` 是 `rs fmt` 的别名。 + +## 选项 \{#options} + +| 选项 | 说明 | +| ---------------------------- | ----------------------------------------------------- | +| `--write` | 将格式化结果写回文件。这是默认模式。 | +| `--check` | 检查格式但不写入文件;存在格式差异时以状态码 1 退出。 | +| `--list-different` | 仅输出未格式化的路径;存在格式差异时以状态码 1 退出。 | +| `--parallel-workers ` | 设置格式化 worker 的最大数量。 | +| `-h, --help` | 显示命令用法和选项。 | + +`--write`、`--check` 和 `--list-different` 不能同时使用。 + +示例: + +```bash +# 就地格式化当前目录 +rs fmt + +# 格式化指定文件和目录 +rs fmt src package.json + +# 使用带引号的 glob 包含和排除文件 +rs fmt "src/**/*.{js,ts}" "!src/generated/**" + +# 在 CI 中检查格式 +rs fmt --check +``` + +## 文件发现 \{#file-discovery} + +扫描目录或 glob 时,`rs fmt` 会遵循 `.gitignore`、跳过二进制文件,并且不会遍历版本控制目录或 `node_modules`。Prettier 无法推断 parser 的文件也会被跳过。 + +如需添加项目专属的排除规则,请使用 [`ignorePatterns`](../configuration#define-fmt)。传入的正向和反向 glob 都基于当前工作目录解析。 + +## 配置 \{#configuration} + +在 [Rstack 配置文件](/guide/configuration#configuration-file)中通过 [`define.fmt()`](../configuration#define-fmt) 配置格式化: + +```ts title="rstack.config.ts" +import { define } from 'rstack'; + +define.fmt({ + printWidth: 100, + singleQuote: true, + sortPackageJson: true, + ignorePatterns: ['dist/**'], + overrides: [ + { + files: '*.md', + options: { + proseWrap: 'always', + }, + }, + ], +}); +``` + +`define.fmt()` 支持标准的 [Prettier 选项](https://prettier.io/docs/options)和 `overrides` 字段,并额外提供以下 Rstack 选项: + +- `ignorePatterns`:相对于 `rstack.config.ts` 所在目录的 Gitignore 兼容模式。 +- `sortPackageJson`:格式化前对 `package.json` 字段排序,默认值为 `false`。 + +:::warning 配置来源 + +`rs fmt` 不会加载 Prettier 配置文件、`.prettierignore` 或 `.editorconfig`。请将其中的配置和忽略规则迁移到 `define.fmt()`。 + +::: + +使用 [Prettier 插件](https://prettier.io/docs/plugins)时,需要将插件指定为包名、文件路径或 URL。由于格式化在 worker 中运行,因此不支持传入已导入的插件对象。包名和相对路径会基于 Rstack 配置文件所在目录解析。 diff --git a/website/docs/zh/guide/cli/staged.mdx b/website/docs/zh/guide/cli/staged.mdx index 6ead301..6191a67 100644 --- a/website/docs/zh/guide/cli/staged.mdx +++ b/website/docs/zh/guide/cli/staged.mdx @@ -96,6 +96,7 @@ rs staged --help import { define } from 'rstack'; define.staged({ - '*.{js,jsx,ts,tsx}': 'rs lint', + '*.{js,jsx,ts,tsx}': ['rs lint', 'rs fmt'], + '*.{json,md,mdx,css,html}': 'rs fmt', }); ``` diff --git a/website/docs/zh/guide/configuration.mdx b/website/docs/zh/guide/configuration.mdx index 59b6665..f8d4a75 100644 --- a/website/docs/zh/guide/configuration.mdx +++ b/website/docs/zh/guide/configuration.mdx @@ -21,6 +21,10 @@ define.test({ define.lint({ // Rslint 配置 }); + +define.fmt({ + // 格式化配置 +}); ``` 配置文件无需默认导出。每个 `define.*()` API 最多调用一次;重复定义同一类型的配置会抛出错误。 @@ -67,6 +71,7 @@ define.app(async () => { | [`define.doc()`](#define-doc) | [Rspress](https://rspress.rs/zh/api/config/config-basic) | [`rs doc`](./cli/doc) | | [`define.test()`](#define-test) | [Rstest](https://rstest.rs/zh/config/) | [`rs test`](./cli/test) | | [`define.lint()`](#define-lint) | [Rslint](https://rslint.rs/config/) | [`rs lint`](./cli/lint) | +| [`define.fmt()`](#define-fmt) | [Prettier](https://prettier.io/docs/options) | [`rs fmt`](./cli/fmt) | | [`define.staged()`](#define-staged) | [lint-staged](https://github.com/lint-staged/lint-staged#configuration) | [`rs staged`](./cli/staged) | ### `define.app()` \{#define-app} @@ -161,6 +166,35 @@ define.lint(async () => { }); ``` +### `define.fmt()` \{#define-fmt} + +定义 [`rs fmt`](./cli/fmt) 使用的格式化配置。可以直接传入配置,也可以通过同步或异步函数返回配置。 + +`define.fmt()` 支持标准的 [Prettier 选项](https://prettier.io/docs/options) 和 `overrides` 字段。此外,还可以通过 `ignorePatterns` 配置 Gitignore 兼容的排除规则,并通过 `sortPackageJson` 在格式化前对 `package.json` 字段排序。 + +```ts title="rstack.config.ts" +import { define } from 'rstack'; + +define.fmt({ + printWidth: 100, + singleQuote: true, + sortPackageJson: true, + ignorePatterns: ['dist/**'], + overrides: [ + { + files: '*.md', + options: { + proseWrap: 'always', + }, + }, + ], +}); +``` + +忽略模式、override 模式和插件相对路径都基于 Rstack 配置文件所在目录解析。Prettier 插件需要指定为包名、路径或 URL,不能传入已导入的插件对象。 + +`rs fmt` 不会加载 Prettier 配置文件、`.prettierignore` 或 `.editorconfig`;请将所有格式化选项和忽略规则集中在 `define.fmt()` 中。 + ### `define.staged()` \{#define-staged} 定义用于处理 Git 暂存文件的 [lint-staged 配置](https://github.com/lint-staged/lint-staged#configuration)。支持传入从 glob 匹配模式映射到任务的配置对象,也支持传入任务生成函数。任务可以是 lint-staged 支持的命令、命令数组或函数。 @@ -169,7 +203,8 @@ define.lint(async () => { import { define } from 'rstack'; define.staged({ - '*.{js,jsx,ts,tsx}': 'rs lint', + '*.{js,jsx,ts,tsx}': ['rs lint', 'rs fmt'], + '*.{json,jsonc,md,mdx,css,html,yml,yaml}': 'rs fmt', }); ``` diff --git a/website/docs/zh/guide/quick-start.mdx b/website/docs/zh/guide/quick-start.mdx index 8a8a0bc..79bb999 100644 --- a/website/docs/zh/guide/quick-start.mdx +++ b/website/docs/zh/guide/quick-start.mdx @@ -44,7 +44,8 @@ Rstack 支持使用 [Node.js](https://nodejs.org/)、[Deno](https://deno.com/) "build": "rs build", "preview": "rs preview", "test": "rs test", - "lint": "rs lint" + "lint": "rs lint", + "format": "rs fmt" } } ``` @@ -60,6 +61,7 @@ Rstack 提供以下命令: - [`rs doc`](./cli/doc):使用 Rspress 开发、构建或预览文档站点。 - [`rs test`](./cli/test):使用 Rstest 运行测试。 - [`rs lint`](./cli/lint):使用 Rslint 检查源代码。 +- [`rs fmt`](./cli/fmt):格式化代码。 - [`rs setup`](./cli/setup):安装项目本地 Git hooks。 - [`rs staged`](./cli/staged):使用 lint-staged 对 Git 暂存区中的文件运行任务。