# Prettier 代码格式化

## Purpose

定义前端代码格式化规则、工具集成、编辑器配置，确保多人协作时代码风格一致。

## Requirements

### Requirement: Prettier 核心配置

前端 SHALL 在 `.prettierrc` 文件中配置以下格式化规则：

- `semi`: `false` — 语句末尾 SHALL NOT 使用分号
- `singleQuote`: `true` — 字符串 SHALL 使用单引号
- `jsxSingleQuote`: `true` — JSX 属性 SHALL 使用单引号
- `tabWidth`: `2` — 缩进 SHALL 使用 2 个空格
- `useTabs`: `false` — 缩进 SHALL NOT 使用制表符
- `trailingComma`: `"es5"` — 多行结构末尾 SHALL 使用 ES5 兼容的尾随逗号
- `printWidth`: `120` — 每行最大字符数 SHALL 为 120
- `bracketSpacing`: `true` — 对象字面量花括号内 SHALL 有空格
- `arrowParens`: `"always"` — 箭头函数参数 SHALL 始终使用括号
- `endOfLine`: `"lf"` — 换行符 SHALL 使用 Unix 风格 (LF)
- `proseWrap`: `"preserve"` — Markdown 文本换行 SHALL 保持原样
- `htmlWhitespaceSensitivity`: `"css"` — HTML 空白处理 SHALL 根据 CSS display 属性
- `embeddedLanguageFormatting`: `"auto"` — 嵌入语言（如 Markdown 中的代码块）SHALL 自动格式化
- `singleAttributePerLine`: `false` — JSX 多属性 SHALL NOT 强制每行一个

#### Scenario: 格式化 JavaScript 代码

- **WHEN** 运行 `prettier --write` 格式化 JavaScript 文件
- **THEN** 代码 SHALL 使用单引号、无分号、2 空格缩进
- **THEN** 行宽超过 120 字符时 SHALL 自动换行

#### Scenario: 格式化 TypeScript 代码

- **WHEN** 运行 `prettier --write` 格式化 TypeScript 文件
- **THEN** 代码 SHALL 使用单引号、无分号、2 空格缩进
- **THEN** type import SHALL 保持内联风格 `import { type Foo }`

#### Scenario: 格式化 JSX 代码

- **WHEN** 运行 `prettier --write` 格式化 JSX 文件
- **THEN** JSX 属性 SHALL 使用单引号
- **THEN** 多属性 SHALL 根据行宽自动换行

#### Scenario: 格式化 SCSS 代码

- **WHEN** 运行 `prettier --write` 格式化 SCSS 文件
- **THEN** 代码 SHALL 使用 2 空格缩进
- **THEN** CSS 规则 SHALL 保持一致的格式

#### Scenario: 格式化 JSON 文件

- **WHEN** 运行 `prettier --write` 格式化 JSON 文件
- **THEN** JSON SHALL 使用 2 空格缩进
- **THEN** JSON SHALL 保持尾随换行

#### Scenario: 格式化 Markdown 文件

- **WHEN** 运行 `prettier --write` 格式化 Markdown 文件
- **THEN** 文本换行 SHALL 保持原样
- **THEN** 代码块 SHALL 自动格式化

### Requirement: Prettier 忽略文件配置

前端 SHALL 在 `.prettierignore` 文件中配置以下忽略规则：

- `node_modules` — 依赖目录 SHALL NOT 格式化
- `dist` — 构建输出 SHALL NOT 格式化
- `dist-ssr` — SSR 构建输出 SHALL NOT 格式化
- `bun.lock` — Bun 锁文件 SHALL NOT 格式化
- `package-lock.json` — npm 锁文件 SHALL NOT 格式化
- `yarn.lock` — Yarn 锁文件 SHALL NOT 格式化
- `pnpm-lock.yaml` — pnpm 锁文件 SHALL NOT 格式化
- `.env.*` — 环境变量文件 SHALL NOT 格式化
- `*.local` — 本地配置文件 SHALL NOT 格式化
- `coverage` — 测试覆盖率报告 SHALL NOT 格式化
- `**/*.snap` — Jest snapshot 文件 SHALL NOT 格式化
- `**/__snapshots__/**` — Jest snapshot 目录 SHALL NOT 格式化
- `*.svg` — SVG 文件 SHALL NOT 格式化
- `*.min.js` — 压缩的 JS 文件 SHALL NOT 格式化
- `*.min.css` — 压缩的 CSS 文件 SHALL NOT 格式化
- `openspec/changes/archive/` — 已归档的变更 SHALL NOT 格式化

#### Scenario: 不格式化依赖目录

- **WHEN** 运行 `prettier --write .`
- **THEN** `node_modules` 目录 SHALL NOT 被格式化

#### Scenario: 不格式化锁文件

- **WHEN** 运行 `prettier --write .`
- **THEN** `bun.lock` 文件 SHALL NOT 被格式化

#### Scenario: 不格式化测试快照

- **WHEN** 运行 `prettier --write .`
- **THEN** `**/*.snap` 文件 SHALL NOT 被格式化
- **THEN** `**/__snapshots__/**` 目录 SHALL NOT 被格式化

#### Scenario: 不格式化 SVG 文件

- **WHEN** 运行 `prettier --write .`
- **THEN** `*.svg` 文件 SHALL NOT 被格式化

### Requirement: EditorConfig 配置

前端 SHALL 在 `.editorconfig` 文件中配置以下编辑器设置：

- `root = true` — 声明为根配置文件
- `[*]` `charset = utf-8` — 所有文件 SHALL 使用 UTF-8 编码
- `[*]` `indent_style = space` — 所有文件 SHALL 使用空格缩进
- `[*]` `indent_size = 2` — 所有文件 SHALL 使用 2 空格缩进
- `[*]` `end_of_line = lf` — 所有文件 SHALL 使用 Unix 换行符
- `[*]` `insert_final_newline = true` — 所有文件 SHALL 在末尾插入空行
- `[*]` `trim_trailing_whitespace = true` — 所有文件 SHALL 删除行尾空白
- `[*.md]` `trim_trailing_whitespace = false` — Markdown 文件 SHALL NOT 删除行尾空白（Markdown 语法需要）

#### Scenario: 编辑器使用统一缩进

- **WHEN** 开发者在编辑器中打开项目
- **THEN** 编辑器 SHALL 自动使用 2 空格缩进
- **THEN** 编辑器 SHALL NOT 使用制表符缩进

#### Scenario: 编辑器使用统一换行符

- **WHEN** 开发者在编辑器中创建新文件
- **THEN** 编辑器 SHALL 使用 Unix 换行符 (LF)
- **THEN** 编辑器 SHALL NOT 使用 Windows 换行符 (CRLF)

#### Scenario: 编辑器使用统一编码

- **WHEN** 开发者在编辑器中保存文件
- **THEN** 文件 SHALL 使用 UTF-8 编码保存

### Requirement: VS Code 扩展推荐

前端 SHALL 在 `.vscode/extensions.json` 文件中推荐以下扩展：

- `esbenp.prettier-vscode` — Prettier 格式化扩展
- `dbaeumer.vscode-eslint` — ESLint 检查扩展

#### Scenario: VS Code 提示安装扩展

- **WHEN** 开发者使用 VS Code 打开项目
- **THEN** VS Code SHALL 提示安装推荐的扩展
- **THEN** 推荐列表 SHALL 包含 Prettier 和 ESLint 扩展

### Requirement: VS Code 格式化设置

前端 SHALL 在 `.vscode/settings.json` 文件中配置以下设置：

- `editor.formatOnSave = true` — 保存时 SHALL 自动格式化
- `editor.defaultFormatter = "esbenp.prettier-vscode"` — 默认格式化器 SHALL 为 Prettier
- `editor.codeActionsOnSave.source.fixAll.eslint = "explicit"` — 保存时 SHALL 自动修复 ESLint 问题

#### Scenario: 保存时自动格式化

- **WHEN** 开发者在 VS Code 中保存文件
- **THEN** 文件 SHALL 自动使用 Prettier 格式化
- **THEN** ESLint 可修复的问题 SHALL 自动修复

#### Scenario: 使用 Prettier 作为默认格式化器

- **WHEN** 开发者在 VS Code 中使用格式化命令
- **THEN** SHALL 使用 Prettier 进行格式化
- **THEN** SHALL NOT 使用其他格式化器

### Requirement: Prettier 与 ESLint 集成

前端 SHALL 在 `eslint.config.js` 中导入 `eslint-config-prettier` 配置，关闭与 Prettier 冲突的 ESLint 规则。

#### Scenario: ESLint 配置集成 Prettier

- **WHEN** 配置 `eslint.config.js`
- **THEN** SHALL 导入 `eslint-config-prettier`
- **THEN** `eslint-config-prettier` SHALL 放在配置数组的最后
- **THEN** 与 Prettier 冲突的 ESLint 规则 SHALL 被关闭

#### Scenario: ESLint 与 Prettier 不冲突

- **WHEN** 运行 `eslint .` 和 `prettier --check .`
- **THEN** ESLint 检查和 Prettier 格式化 SHALL NOT 产生冲突
- **THEN** 同一文件 SHALL NOT 同时报告 ESLint 错误和 Prettier 格式问题

### Requirement: 格式化脚本配置

前端 SHALL 在 `package.json` 中配置以下脚本：

- `format = "prettier --write ."` — 格式化所有文件
- `format:check = "prettier --check ."` — 检查文件格式
- `check = "bun run lint && bun run format:check"` — 检查 lint 和格式
- `fix = "bun run lint:fix && bun run format"` — 修复 lint 问题并格式化

#### Scenario: 运行格式化命令

- **WHEN** 执行 `bun run format`
- **THEN** SHALL 运行 `prettier --write .`
- **THEN** 所有文件 SHALL 被格式化

#### Scenario: 运行格式检查命令

- **WHEN** 执行 `bun run format:check`
- **THEN** SHALL 运行 `prettier --check .`
- **THEN** 未格式化的文件 SHALL 报告错误

#### Scenario: 运行统一检查命令

- **WHEN** 执行 `bun run check`
- **THEN** SHALL 运行 `bun run lint && bun run format:check`
- **THEN** lint 错误和格式问题 SHALL 都被检查

#### Scenario: 运行统一修复命令

- **WHEN** 执行 `bun run fix`
- **THEN** SHALL 运行 `bun run lint:fix && bun run format`
- **THEN** lint 问题 SHALL 被修复
- **THEN** 文件 SHALL 被格式化

### Requirement: Prettier 依赖安装

前端 SHALL 安装以下依赖：

- `prettier` — Prettier 核心库
- `eslint-config-prettier` — 关闭与 Prettier 冲突的 ESLint 规则

#### Scenario: 安装 Prettier 依赖

- **WHEN** 执行 `bun install`
- **THEN** `prettier` SHALL 被安装
- **THEN** `eslint-config-prettier` SHALL 被安装
- **THEN** 依赖版本 SHALL 在 `package.json` 中声明
