From 3f73adc01524b507c3e8c48e60ff9626c5f9586e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= Date: Sun, 7 Jun 2026 09:30:42 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E5=92=8C=E9=85=8D=E7=BD=AE=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=9C=AA?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E6=9D=83=E9=99=90=E5=92=8C=E8=BF=87?= =?UTF-8?q?=E6=97=B6=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/CI.md | 17 ++++++++++++ .github/I18N.md | 42 ++++++++++++++++++++++++++++ AGENTS.md | 74 ++++--------------------------------------------- wxt.config.ts | 2 -- 4 files changed, 65 insertions(+), 70 deletions(-) create mode 100644 .github/CI.md create mode 100644 .github/I18N.md diff --git a/.github/CI.md b/.github/CI.md new file mode 100644 index 0000000..6ab7abd --- /dev/null +++ b/.github/CI.md @@ -0,0 +1,17 @@ +# CI/CD 配置 + +## CI 步骤 + +严格顺序,任一步骤失败则停止并标记 CI 失败: + +1. `setup`(安装依赖、`wxt prepare`) +2. 并行运行 `lint`、`typecheck`、`test`(三者全部通过才继续) +3. `build`(仅当步骤 2 全部成功时执行) + +## Pre-commit Hook + +`.husky/pre-commit` 调用 `lint-staged`,任一步骤返回非零则终止提交: + +1. 代码文件 (`*.{ts,tsx,js,jsx,mjs}`):运行 `eslint --fix --max-warnings=0 --no-warn-ignored`;若失败则终止并报告错误 +2. 同一代码文件:运行 `prettier --write` +3. 其他文件 (`*.{json,css,scss,md}`):运行 `prettier --write` diff --git a/.github/I18N.md b/.github/I18N.md new file mode 100644 index 0000000..80e4ee8 --- /dev/null +++ b/.github/I18N.md @@ -0,0 +1,42 @@ +# i18n 开发指南 + +## 概述 + +项目使用 Chrome 扩展标准的 `chrome.i18n` API 进行本地化,通过 `src/utils/chromeI18n.ts` 提供类型安全的 React Hook 包装。 + +## 配置 + +- **翻译文件**: `public/_locales/{zh_CN,en}/messages.json`(Chrome 扩展标准格式) +- **默认语言**: `zh_CN`(在 `wxt.config.ts` 的 `manifest.default_locale` 中配置) + +## 使用方式 + +```typescript +import { useI18n } from '@/utils/chromeI18n'; +``` + +## 翻译键格式 + +- **直接 key**: `t('dashboard_title')` → 查找 `dashboard_title` +- **命名空间格式(兼容旧用法)**: `t('common:buttons.search')` → 查找 `common_buttons_search` +- **带命名空间参数**: `useI18n(['common', 'features'])`,会自动尝试 `common_key`、`features_key` + +## 占位符支持 + +```typescript +t('router_notFoundDescription', { entryPointType: 'popup' }); +``` + +## Hook 返回值 + +```typescript +{ t, i18n: { language, changeLanguage }, isLoaded } +``` + +## 回退策略 + +当翻译 key 未命中时,返回 key 本身(开发模式下在控制台记录 warning) + +## 限制 + +`chrome.i18n` 无法动态切换语言,语言跟随浏览器设置,切换后需刷新页面 diff --git a/AGENTS.md b/AGENTS.md index 14c0a43..97606b7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,27 +18,9 @@ npm run test:watch # vitest 监视模式 npm run test:coverage # 带覆盖率的测试 ``` -运行单个测试: `npx vitest run path/to/file.test.ts` - ## 验证流程 -CI 步骤(严格顺序,任一步骤失败则停止并标记 CI 失败): - -1. `setup`(安装依赖、`wxt prepare`) -2. 并行运行 `lint`、`typecheck`、`test`(三者全部通过才继续) -3. `build`(仅当步骤 2 全部成功时执行) - -Pre-commit hook(`.husky/pre-commit` 调用 `lint-staged`,任一步骤返回非零则终止提交): - -1. 代码文件 (`*.{ts,tsx,js,jsx,mjs}`):运行 `eslint --fix --max-warnings=0 --no-warn-ignored`;若失败则终止并报告错误 -2. 同一代码文件:运行 `prettier --write` -3. 其他文件 (`*.{json,css,scss,md}`):运行 `prettier --write` - -## WXT 生成文件 - -- `.wxt/` 目录由 `postinstall` 自动执行 `wxt prepare` 生成,包含 TypeScript 类型声明和扩展的 tsconfig。 -- 生产构建输出到 `.output/` 目录。 -- `tsconfig.json` 继承自 `./.wxt/tsconfig.json`。 +详见 [CI 配置](./.github/CI.md) ## 项目结构 @@ -77,37 +59,6 @@ src/pages/FeatureName/ - 当 `index.tsx` 超过 150 行时,必须拆分为 UI + Hook 模式 - 复杂页面可增加 `contexts/`、`hooks/`、`components/` 子目录 -### 测试数据生成器模块 - -``` -src/pages/TestDataGenerator/ -├── index.tsx # 主页面(字段配置 + 标签页切换) -├── hooks/useGenerator.ts # Web Worker 管理 Hook(创建、复用、通信、销毁) -└── components/ - ├── FieldList.tsx # 字段列表(虚拟滚动 + @dnd-kit 拖拽排序 + 规则保存) - ├── FieldItem.tsx # 字段卡片展示 - ├── FieldEditor.tsx # 字段编辑器(名称校验、生成器选择、参数配置) - ├── GeneratorSelector.tsx # 生成器选择器(分类 + 搜索) - ├── GeneratorConfig.tsx # 生成器参数表单(动态渲染 string/number/boolean/select/array) - ├── GenerateOptions.tsx # 生成选项(数量、格式) - ├── GenerateButton.tsx # 生成按钮 + 进度条 - ├── DataPreview.tsx # 示例数据预览(JSON 语法高亮) - ├── ResultPanel.tsx # 生成结果状态面板 - ├── ExportPanel.tsx # 导出面板(复制/下载 JSON/CSV) - └── RuleManager.tsx # 规则管理(CRUD、搜索、导入/导出) - -src/utils/ -├── ruleStorage.ts # 规则持久化存储(localStorage) -├── dataExporter.ts # 数据导出工具(JSON/CSV 转换、下载、剪贴板) -└── generators/ # 内置生成器定义(个人信息、企业、技术、基础类型) - -src/workers/ -└── generator.worker.ts # 数据生成 Web Worker - -src/types/ -└── testDataGenerator.ts # 类型定义(FieldConfig, DataRule, GeneratorDefinition 等) -``` - ## 关键架构决策 **路由**: 不使用 React Router。通过 `src/config/features.tsx` 的 `FEATURES` 数组管理,`RouterProvider` 根据 `PageType` @@ -116,7 +67,6 @@ src/types/ **存储**: 所有 Chrome Storage 键必须在 `src/types/storage.d.ts` 的 `StorageSchema` 中定义,键名使用 kebab-case 格式(如 `app/currentRoute`)。 使用 `src/utils/chromeStorage.ts` 及其 Hook。Router 同时使用 `chrome.storage.local` 和 `localStorage` 做快照以消除首屏闪烁。 -修改 StorageSchema 时,必须在 `src/utils/chromeStorage.ts` 添加版本迁移函数,并在测试中覆盖迁移场景。 **通信**: 使用 `@webext-core/messaging`,协议定义在 `src/utils/messages.ts`。 @@ -132,7 +82,7 @@ src/types/ - 全局变量: `vitest/globals` (describe, it, expect 等无需导入) - Setup 文件: `vitest.setup.ts` 自动 mock: - `chrome.*` / `browser.*` API (storage, tabs, runtime, cookies 等) - - `@/utils/chromeI18n` (从 `public/_locales/zh/messages.json` 加载真实翻译) + - `@/utils/chromeI18n` (从 `public/_locales/zh_CN/messages.json` 加载真实翻译) - `window.matchMedia` - 测试文件命名: `__tests__/*.test.{ts,tsx}` 或 `*.test.{ts,tsx}` - Mock 模式: 使用 `vi.mock()` 进行模块级 mock,避免在测试文件中重复 mock 代码 @@ -140,19 +90,7 @@ src/types/ ## i18n (chrome.i18n) -项目使用 Chrome 扩展标准的 `chrome.i18n` API 进行本地化,通过 `src/utils/chromeI18n.ts` 提供类型安全的 React Hook 包装。 - -- **翻译文件**: `public/_locales/{zh,en}/messages.json`(Chrome 扩展标准格式) -- **默认语言**: `zh`(在 `wxt.config.ts` 的 `manifest.default_locale` 中配置) -- **使用方式**: `import { useI18n } from '@/utils/chromeI18n'` -- **翻译键格式**: - - 直接 key: `t('dashboard_title')` → 查找 `dashboard_title` - - 命名空间格式(兼容旧用法): `t('common:buttons.search')` → 查找 `common_buttons_search` - - 带命名空间参数: `useI18n(['common', 'features'])`,会自动尝试 `common_key`、`features_key` -- **占位符支持**: `t('router_notFoundDescription', { entryPointType: 'popup' })` -- **Hook 返回值**: `{ t, i18n: { language, changeLanguage }, isLoaded }` -- **回退策略**: 当翻译 key 未命中时,返回 key 本身(开发模式下在控制台记录 warning) -- **限制**: `chrome.i18n` 无法动态切换语言,语言跟随浏览器设置,切换后需刷新页面 +详见 [i18n 开发指南](./.github/I18N.md) ## 新功能开发清单 @@ -160,10 +98,10 @@ src/types/ 2. 在 `src/config/features.tsx` 的 `FEATURES` 数组添加配置(指定 key、翻译键、图标、三种渲染模式的组件) 3. 在 `src/pages/` 创建页面组件 (懒加载): - `index.tsx` — UI 组件,使用 `useI18n` 获取翻译 - - `useFeatureName.ts` — 业务逻辑 Hook + - `use{FeatureName}.ts` — 业务逻辑 Hook - `constants.ts` — 常量(可选) 4. 在 `public/_locales/zh/messages.json`(及 `en/messages.json`)添加翻译 -5. 如需新权限,更新 `wxt.config.ts` 的 `manifest.permissions` +5. 如需新权限,更新 `wxt.config.ts` 的 `manifest.permissions`;如有不使用的权限,需移除 6. 添加对应的单元测试 ## 代码规范 @@ -176,6 +114,7 @@ src/types/ - 格式: Prettier (`.prettierrc`: 100 字符宽, 单引号, 尾逗号 all, LF 换行) - ESLint 使用 `typescript-eslint` 的 `projectService: true`(无需手动维护 project 路径) - **Git Commit**: 必须使用中文描述,遵循 Conventional Commits 规范(如 `fix(组件名): 描述`、`feat(功能名): 描述`) +- **测试维护**: 新增/编辑已有功能/组件时,需要针对相关的测试进行更新 ## 关键外部库(非显而易见的) @@ -184,4 +123,3 @@ src/types/ - `qrious` + `qr-scanner` — 二维码生成与解析 - `dayjs` — 日期处理(时间戳转换) - `sonner` — Toast 通知(替代传统 snackbar) -- Web Worker — 批量数据生成(`src/workers/generator.worker.ts`),避免阻塞 UI 线程 diff --git a/wxt.config.ts b/wxt.config.ts index 9bbbf6b..50bf923 100644 --- a/wxt.config.ts +++ b/wxt.config.ts @@ -48,9 +48,7 @@ export default defineConfig({ default_locale: 'zh_CN', permissions: [ 'storage', - 'unlimitedStorage', 'clipboardWrite', - 'activeTab', 'scripting', 'tabs', 'cookies',