diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index ad75f01..0000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,141 +0,0 @@ -# Copilot 指令 - -基于 WXT 框架的浏览器扩展项目(React 19 + TypeScript),为开发者和测试人员提供效率工具:时间戳转换、存储清理、JWT 解析、JSON 工具、二维码、Base64、Markdown 等。 - -## 核心命令 - -```bash -npm run dev # Chrome 开发模式(支持 HMR) -npm run dev:firefox # Firefox 开发模式 -npm run build # Chrome 生产构建 -npm run build:firefox # Firefox 生产构建 -npm run zip # 打包 Chrome 扩展(.output/*.zip) -npm run zip:firefox # 打包 Firefox 扩展 -npm run lint # ESLint 检查(--max-warnings=0) -npm run typecheck # TypeScript 类型检查(tsc --noEmit) -npm run test # 运行全部单元测试(vitest run) -npm run test:watch # Vitest 监视模式 -npm run test:coverage # 带覆盖率的测试 -``` - -运行单个测试文件:`npx vitest run path/to/file.test.ts` - -修改 `package.json` 后需运行 `npm install`(会自动触发 `postinstall` → `wxt prepare` 重新生成 `.wxt/` 类型声明)。 - -## CI 流水线(GitHub Actions) - -严格顺序门控,任一步骤失败则终止: - -1. **setup** — 安装依赖,缓存 `node_modules` -2. **lint**、**typecheck**、**test** — 三者并行运行,全部通过才继续 -3. **build** — Chrome + Firefox 矩阵构建(仅当步骤 2 全部通过时执行) - -Pre-commit 钩子(`.husky/pre-commit` → `lint-staged`): - -1. 代码文件(`*.{ts,tsx,js,jsx,mjs}`):运行 `eslint --fix --max-warnings=0` -2. 同一代码文件:运行 `prettier --write` -3. 其他文件(`*.{json,css,scss,md}`):运行 `prettier --write` - -## 项目架构 - -### 路由(不使用 React Router) - -路由完全通过 `config/features.tsx` 中的 `FEATURES` 数组管理。每个功能定义一个 `key`(类型为 `types/storage.d.ts` 中的 `PageType`)和三个懒加载组件,分别对应 `popup`、`sidepanel`、`tab` 三种渲染模式。`providers/RouterProvider.tsx` 中的 `RouterProvider` 根据存储状态渲染当前页面。 - -存在三套独立的路由作用域:`app/popupRoute`、`app/sidepanelRoute`、`app/tabRoute`,各自维护独立的可见页面列表和页面排序。 - -### 存储 - -所有 Chrome Storage 键必须在 `types/storage.d.ts` 的 `StorageSchema` 中声明,键名使用 kebab-case 格式(如 `app/currentRoute`)。使用 `utils/chromeStorage.ts` 中的类型安全封装(`storageUtil.get/set/remove`)。 - -Router 同时使用 `chrome.storage.local` 持久化和 `localStorage` 快照来消除首屏闪烁。 - -### 扩展通信 - -使用 `@webext-core/messaging`。通信协议在 `utils/messages.ts` 中通过 `ProtocolMap` 定义。使用该模块导出的 `sendMessage` / `onMessage`,不要直接使用原生 `chrome.runtime.sendMessage`。 - -### 页面组件模式 - -功能页面遵循 **UI + Hook 分离** 模式,详见 [CODING_STANDARDS.md § 11](./CODING_STANDARDS.md#11-页面开发规范): - -``` -pages/FeatureName/ -├── index.tsx # UI 组件(纯展示,使用 shadcn/ui 组件) -├── useFeatureName.ts # 业务逻辑 Hook(状态管理 + 转换逻辑) -└── constants.ts # 常量定义(可选) -``` - -- 页面组件调用 `useI18n('featureName')` 获取翻译函数 -- Hook 负责所有状态管理,通过返回值暴露给页面 -- 子组件可进一步拆分(如 `LiveClock.tsx`、`ResultView.tsx`) - -### 新功能开发清单 - -1. 在 `types/storage.d.ts` 的 `PageType` 联合类型中添加新成员 -2. 在 `config/features.tsx` 的 `FEATURES` 数组中添加配置(key、翻译键、图标、三种渲染模式组件) -3. 在 `pages/` 目录创建页面组件(懒加载): - - `index.tsx` — 使用 `useLazyTranslation` 的 UI 组件 - - `useFeatureName.ts` — 业务逻辑 Hook - - `constants.ts` — 常量(可选) -4. 在 `i18n/locales/{zh,en}/features.json` 添加翻译(复杂功能可新建独立 JSON 文件) -5. 如需新权限,更新 `wxt.config.ts` 的 `manifest.permissions` -6. 添加对应的单元测试 - -## 关键规范 - -> 完整的代码编写规范详见 [CODING_STANDARDS.md](./CODING_STANDARDS.md)。 - -### 浏览器 API - -始终使用 `wxt/browser` 导出的 `browser` 对象,而非原生 `chrome` API,以确保跨浏览器兼容性。 - -### 路径别名 - -`@/` 映射到项目根目录(已在 tsconfig 和 vitest.config 中配置)。跨目录导入使用 `@/` 绝对别名,同目录导入使用 `./` 相对路径。 - -### UI 组件 - -- 使用 `components/ui/` 下的 shadcn/ui 组件(button、dialog、select、input 等) -- 图标:`lucide-react` -- 样式:Tailwind CSS + `@/lib/utils` 中的 `cn()` 工具函数(clsx + tailwind-merge) -- 主题:使用 shadcn/ui 语义化 token(`bg-background`、`text-foreground`、`border-border` 等),禁止硬编码颜色 - -### 代码分割 - -`wxt.config.ts` 通过 `manualChunksForHtmlOnly()` 自动分组 vendor 依赖(vendor-react、vendor-i18n、vendor-qr、vendor-dnd),无需手动配置。 - -### 代码风格 - -- 禁止使用 `any`(测试文件除外) -- 未使用的变量/参数:使用 `_` 前缀(如 `_unused`) -- Prettier:100 字符宽、单引号、尾逗号 all、LF 换行 -- ESLint 使用 `typescript-eslint` 的 `projectService: true` -- 导出模式:页面组件 default export,工具函数/Hook 命名导出,UI 组件 forwardRef + 命名导出 - -### 测试 - -- 环境:jsdom -- 全局变量:`vitest/globals`(describe、it、expect 等无需导入) -- Setup 文件:`vitest.setup.ts` 自动 mock 以下内容: - - `chrome.*` / `browser.*` API(storage、tabs、runtime、cookies 等) - - `react-i18next`(返回 key 作为翻译) - - `@/utils/useLazyTranslation`(返回 `ns:key` 格式) - - `window.matchMedia` -- 测试文件命名:`__tests__/*.test.{ts,tsx}` 或 `*.test.{ts,tsx}` -- 使用 `vi.mock()` 进行模块级 mock;避免重复 mock `vitest.setup.ts` 中已有的内容 -- 测试工具:`@testing-library/react` + `@testing-library/user-event` - -### 国际化(i18n) - -- 命名空间:`common`(默认)、`features` -- 翻译键格式:`namespace:key`(如 `features:timestamp.title`) -- 语言:`zh`(默认)、`en` -- 翻译文件:`i18n/locales/{zh,en}/{common,features}.json` + 各功能独立 JSON 文件 -- 使用 `useLazyTranslation` Hook 加载功能专属翻译 -- 回退策略:缺失的翻译键回退到 `zh`,若仍缺失则返回占位格式 `namespace:key` - -### WXT 生成文件 - -- `.wxt/` 目录由 `postinstall`(`wxt prepare`)自动生成,包含 TypeScript 类型声明和扩展 tsconfig -- 生产构建输出到 `.output/` 目录 -- `tsconfig.json` 继承自 `./.wxt/tsconfig.json` diff --git a/AGENTS.md b/AGENTS.md index d868cbe..75ab9b2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,23 @@ # AGENTS.md -WXT 浏览器扩展项目 (React 19 + TypeScript)。提供时间戳转换、存储清理、JWT 解析、JSON 工具、二维码、Base64、Markdown、测试数据生成器等测试效率工具。 +WXT 浏览器扩展项目 (React 19 + TypeScript)。为开发者和测试人员提供浏览器内效率工具集。 + +## 功能列表 + +功能定义见 `src/config/features.tsx`,`PageType` 见 `src/types/storage.d.ts`。 + +| key | 页面目录 | 说明 | +| -------------------- | -------------------------- | ------------------------------------------- | +| `dashboard` | `pages/Dashboard` | 仪表盘首页,工具导航与最近使用 | +| `timestamp` | `pages/Timestamp` | Unix 时间戳转换与格式化 | +| `storageCleaner` | `pages/StorageCleaner` | 清理 Cookies、本地存储、IndexedDB、Cache 等 | +| `qrCode` | `pages/QrCode` | 二维码生成与解析 | +| `textStatistics` | `pages/TextStatistics` | 文本字符、单词、行数、字节统计 | +| `jwt` | `pages/Jwt` | JWT 解码与查看 | +| `jsonTools` | `pages/JsonTools` | JSON 差异比较、格式化、YAML/TOML 转换与压缩 | +| `base64Converter` | `pages/Base64Converter` | 文本、文件、图像 Base64 编解码 | +| `rightClickRestorer` | `pages/RightClickRestorer` | 恢复被网站禁用的右键菜单 | +| `testDataGenerator` | `pages/TestDataGenerator` | 自定义规则批量生成测试数据 | ## 核心命令 @@ -16,30 +33,64 @@ npm run typecheck # tsc --noEmit npm run test # vitest run (单次执行) npm run test:watch # vitest 监视模式 npm run test:coverage # 带覆盖率的测试 +npx vitest run path/to/file.test.ts # 运行单个测试文件 +npx wxt prepare # 重新生成 .wxt/ 类型声明(npm install 时 postinstall 会自动执行) ``` +修改 `package.json` 或首次克隆仓库后需执行 `npm install`,会自动触发 `postinstall` → `wxt prepare`。 + ## 验证流程 -详见 [CI 配置](./.github/CI.md) +详见 [CI 配置](./.github/CI.md)。本地与 CI 的检查层次如下。 + +### Pre-commit(`.husky/pre-commit`) + +1. 后台运行 `tsc --noEmit`(不阻塞提交,结果输出到 stderr) +2. 前台运行 `lint-staged`: + - 代码文件 (`*.{ts,tsx,js,jsx,mjs}`):`eslint --fix --max-warnings=0`,再 `prettier --write` + - 其他文件 (`*.{json,css,scss,md}`):`prettier --write` + +### Pre-push(`.husky/pre-push`) + +1. 全项目 `tsc --noEmit`(阻塞推送) +2. 对本次推送相对 upstream(或 `origin/main`)变更的 `*.{ts,tsx,js,jsx,mjs}` 文件运行 `eslint --max-warnings=0` + +### CI(GitHub Actions) + +1. `setup` — 安装依赖 +2. 并行 `lint`、`typecheck`(含 `wxt prepare`)、`test` +3. `build` — Chrome + Firefox 矩阵构建(仅当步骤 2 全部通过) ## 项目结构 ``` -src/ # 源代码根目录 - config/features.tsx # 功能定义(路由 + 元数据的单一事实来源) - entrypoints/ # 扩展入口点 (popup/, sidepanel/, background.ts, content.ts) - pages/ # 功能页面组件 (懒加载) - components/ # 可复用 UI 组件 - components/ui/ # shadcn/ui 基础组件 (button, dialog, select 等) - providers/ # React Context (Router, Theme 等) - hooks/ # 自定义 React Hooks - utils/ # 工具函数与服务抽象 - types/ # TypeScript 类型声明 - lib/ # 通用工具函数(cn、utils) - workers/ # Web Worker(数据生成等耗时任务) -public/ # 静态资源(图标、_locales 等) +src/ # 源代码根目录 + config/features.tsx # 功能定义(路由 + 元数据的单一事实来源) + entrypoints/ # 扩展入口点 (popup/, sidepanel/, background.ts, content.ts) + layout/ # 应用壳层布局(TopBar 导航、搜索、主题切换) + pages/ # 功能页面组件 (懒加载) + components/ # 可复用 UI 组件 + components/ui/ # shadcn/ui 基础组件 (button, dialog, select 等) + providers/ # React Context (Router, Theme 等) + hooks/ # 自定义 React Hooks + utils/ # 工具函数与服务抽象 + types/ # TypeScript 类型声明 + lib/ # 通用工具函数(cn、utils)及数据生成器定义 + workers/ # Web Worker(数据生成等耗时任务) +spec/ # 功能规格、修复方案与验收标准(见 spec/README.md) +public/ # 静态资源(图标、_locales 等) +.wxt/ # wxt prepare 自动生成,含类型声明与扩展 tsconfig(勿手动编辑) +.output/ # 生产构建输出目录 ``` +### layout/ + +应用壳层,与 popup / sidepanel / tab 入口绑定。当前含 `TopBar/`(搜索、主题切换、返回导航、「在标签页打开」),遵循与 `pages/` 相同的 UI + Hook 模式。详见 [layout/README.md](./src/layout/README.md)。 + +### spec/ + +功能规格与验收标准文档,重大改动前优先查阅。索引见 [spec/README.md](./spec/README.md)。 + ### 页面组件模式 典型功能页面遵循 **UI + Hook 分离** 模式。详见 [CODING_STANDARDS.md § 11](./.github/CODING_STANDARDS.md#11-页面开发规范)。 @@ -62,7 +113,7 @@ src/pages/FeatureName/ ## 关键架构决策 **路由**: 不使用 React Router。通过 `src/config/features.tsx` 的 `FEATURES` 数组管理,`RouterProvider` 根据 `PageType` -渲染对应组件。支持三种渲染模式:popup(弹窗)、sidepanel(侧边栏)和 browser-tab(浏览器新标签页,通过 `open_in_tab` 打开)。 +渲染对应组件。支持三种渲染模式:popup(弹窗)、sidepanel(侧边栏)和 tab(浏览器新标签页,TopBar「在标签页打开」调用 `openExtensionPage('popup.html', { mode: 'tab' })`,由 `getEntryPointType()` 根据 URL 参数 `mode=tab` 识别)。 每种模式有独立的路由和可见页面配置(`app/popupRoute`、`app/sidepanelRoute`、`app/tabRoute` 等)。 **存储**: 所有 Chrome Storage 键必须在 `src/types/storage.d.ts` 的 `StorageSchema` 中定义,键名使用 kebab-case 格式(如 `app/currentRoute`)。 @@ -70,12 +121,10 @@ src/pages/FeatureName/ **通信**: 使用 `@webext-core/messaging`,协议定义在 `src/utils/messages.ts`。 -**路径别名**: `@/` 映射到项目根目录 (已在 tsconfig 和 vitest.config 中配置)。 +**路径别名**: `@/` 映射到 `src/` 目录(已在 `.wxt/tsconfig.json` 和 `vitest.config.ts` 中配置)。项目根目录使用 `@@/`。 **浏览器兼容**: 优先使用 `wxt/browser` 导出的 `browser` 对象,而非原生 `chrome` API。 -**代码分割**: `wxt.config.ts` 通过 `manualChunksForHtmlOnly()` 自动分组依赖(vendor-react、vendor-qr、vendor-dnd 等),无需手动配置。 - ## 测试环境 - 环境: jsdom @@ -87,17 +136,6 @@ src/pages/FeatureName/ - Mock 模式: 使用 `vi.mock()` 进行模块级 mock,避免在测试文件中重复 mock 代码 - 测试工具: `@testing-library/react` + `@testing-library/user-event` 进行组件测试 -## 新功能开发清单 - -1. 在 `src/types/storage.d.ts` 添加 `PageType` 联合类型 -2. 在 `src/config/features.tsx` 的 `FEATURES` 数组添加配置(指定 key、翻译键、图标、三种渲染模式的组件) -3. 在 `src/pages/` 创建页面组件 (懒加载): - - `index.tsx` — UI 组件 - - `use{FeatureName}.ts` — 业务逻辑 Hook - - `constants.ts` — 常量(可选) -4. 如需新权限,更新 `wxt.config.ts` 的 `manifest.permissions`;如有不使用的权限,需移除 -5. 添加对应的单元测试 - ## 代码规范 - 禁止使用 `any` (测试文件除外) @@ -105,10 +143,9 @@ src/pages/FeatureName/ - 样式: 使用 Tailwind CSS + shadcn/ui (通过 `className` 和 `cn()` 工具) - UI 组件: 优先使用 `src/components/ui/` 下的 shadcn/ui 组件 (button, dialog, select 等) - 图标: 使用 `lucide-react` 图标库 -- 格式: Prettier (`.prettierrc`: 100 字符宽, 单引号, 尾逗号 all, LF 换行) -- ESLint 使用 `typescript-eslint` 的 `projectService: true`(无需手动维护 project 路径) -- **Git Commit**: 必须使用中文描述,遵循 Conventional Commits 规范(如 `fix(组件名): 描述`、`feat(功能名): 描述`) -- **测试维护**: 新增/编辑已有功能/组件时,需要针对相关的测试进行更新 +- 格式: Prettier [配置](./.prettierrc) +- ESLint 使用 `typescript-eslint` 的 `projectService: true` +- Git Commit: 使用中文描述,遵循 [Conventional Commits 规范](https://www.conventionalcommits.org/zh-hans/v1.0.0/) ## 关键外部库(非显而易见的) @@ -116,4 +153,4 @@ src/pages/FeatureName/ - `@dnd-kit` — 拖拽排序(用于页面顺序管理和字段列表排序) - `qrious` + `qr-scanner` — 二维码生成与解析 - `dayjs` — 日期处理(时间戳转换) -- `sonner` — Toast 通知(替代传统 snackbar) +- `sonner` — Toast 通知 diff --git a/CLAUDE.md b/CLAUDE.md index 39c76db..43c994c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1 +1 @@ -@AGENT.md +@AGENTS.md diff --git a/src/entrypoints/README.md b/src/entrypoints/README.md deleted file mode 100644 index 9349724..0000000 --- a/src/entrypoints/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# entrypoints/ - -WXT 框架要求的扩展生命周期入口点,对应 Chrome Extension 的各个上下文。 - -## 入口文件 - -| 文件 | 用途 | -| ------------------------------- | --------------------------------------------------------------------------------------------- | -| `background.ts` | Service Worker 入口:注册右键菜单、监听菜单点击、处理消息通信、管理侧边栏状态、注入主环境脚本 | -| `content.ts` | Content Script 入口:注入所有页面(``),在 `document_end` 时初始化消息处理器 | -| `rightClickRestorer.content.ts` | 专用 Content Script:处理右键菜单恢复功能,注入浮动状态徽章 | - -## 子目录 - -### popup/ - -Popup 弹窗页面(点击扩展图标弹出)。 - -| 文件 | 用途 | -| ------------ | ------------------------------------------------------------------------------------- | -| `index.html` | HTML 入口 | -| `main.tsx` | React 挂载点 | -| `App.tsx` | 根组件,组装 `RouterProvider` + `layout/TopBar` + `ErrorBoundary` + `RouterContainer` | - -### sidepanel/ - -侧边栏页面,结构与 popup 类似,额外通知 background 侧边栏开启/关闭状态。 - -### options/ - -设置页面,支持: - -- 拖拽排序功能顺序(`@dnd-kit`) -- 功能可见性管理(显示/隐藏) -- Popup/Sidepanel/Tab 三种模式独立配置 - -### content/ - -Content Script 内部分模块: - -| 文件 | 用途 | -| ----------------------- | ------------------------------------------------------------------- | -| `messageHandler.ts` | 消息处理器初始化入口 | -| `contextMenuHandler.ts` | 右键菜单点击事件处理,执行时间戳转换/文本统计并通过 UI Popover 展示 | -| `uiPopover.ts` | 在页面中注入浮层 Popover UI,展示右键菜单操作结果 | - -## 架构说明 - -- `background.ts` 是扩展的核心协调者,处理跨上下文通信 -- `content.ts` 注入到所有页面,负责接收和处理来自 background 的消息 -- `popup/`、`sidepanel/`、`options/` 共享同一套页面组件(来自 `pages/`),通过 `RouterProvider` 的不同配置实现独立路由 diff --git a/src/pages/README.md b/src/pages/README.md deleted file mode 100644 index 1125899..0000000 --- a/src/pages/README.md +++ /dev/null @@ -1,139 +0,0 @@ -# pages/ - -功能页面组件目录,每个子目录对应一个工具页面。 - -## 目录结构约定 - -典型页面遵循 **UI + Hook 分离** 模式: - -``` -pages/FeatureName/ -├── index.tsx # 页面 UI(纯展示,使用 shadcn/ui 组件) -├── useFeatureName.ts # 业务逻辑 Hook(状态管理 + 转换逻辑) -├── constants.ts # 常量定义(可选) -├── SubComponent.tsx # 子组件(可选) -└── __tests__/ # 测试文件 - └── index.test.tsx -``` - -## 页面列表 - -### Dashboard/ - -仪表盘首页,以卡片网格展示所有可见工具,支持点击导航。 - -| 文件 | 用途 | -| ----------- | -------------------------- | -| `index.tsx` | 页面组件,渲染工具卡片网格 | - -### Timestamp/ - -时间戳转换工具,支持秒/毫秒级互转、多时区选择、实时时钟。 - -| 文件 | 用途 | -| -------------------------- | ----------------------------------------------------------------- | -| `index.tsx` | 页面 UI | -| `useTimestampConverter.ts` | 业务逻辑 Hook,包含转换模式、输入、单位、时区状态和响应式计算管线 | -| `LiveClock.tsx` | 实时时钟子组件,`React.memo` 优化 | -| `ResultView.tsx` | 转换结果展示子组件 | -| `constants.ts` | 时区列表等常量 | - -### StorageCleaner/ - -浏览器存储清理工具,支持 Cookie/LocalStorage/SessionStorage/IndexedDB/Cache/SW 清理。 - -| 文件 | 用途 | -| --------------------------- | -------------- | -| `index.tsx` | 页面 UI | -| `useStorageCleaner.ts` | 业务逻辑 Hook | -| `StorageOptionsGrid.tsx` | 清理选项网格 | -| `StorageCleanerConfirm.tsx` | 清理确认对话框 | -| `AutoRefreshToggle.tsx` | 自动刷新开关 | -| `ErrorDisplay.tsx` | 错误展示组件 | -| `CleaningResult.tsx` | 清理结果展示 | -| `OptionItem.tsx` | 单个选项组件 | - -### QrCode/ - -二维码工具,支持生成(URL→QR)和解析(QR→URL)。 - -| 文件/目录 | 用途 | -| ------------- | ---------------- | -| `index.tsx` | 页面 UI | -| `types.ts` | 类型定义 | -| `contexts/` | Context Provider | -| `hooks/` | 业务逻辑 Hooks | -| `components/` | 子组件 | - -### TextStatistics/ - -文本统计工具,实时计算字符数、单词数、行数、字节大小。 - -| 文件 | 用途 | -| ----------- | --------------------------------------------- | -| `index.tsx` | 页面组件,集成 `TextInputArea` 和统计结果展示 | - -### Jwt/ - -JWT 解析工具,解码 Header/Payload/Signature。 - -| 文件/目录 | 用途 | -| ------------- | ---------------- | -| `index.tsx` | 页面 UI | -| `types.ts` | 类型定义 | -| `contexts/` | Context Provider | -| `hooks/` | 业务逻辑 Hooks | -| `components/` | 子组件 | - -### JsonTools/ - -JSON 工具集:差异比较、格式化、YAML/TOML/Minify 转换。 - -| 文件 | 用途 | -| ------------------------ | ---------------------------- | -| `index.tsx` | 页面入口,子模式切换 | -| `types.ts` | 类型定义 | -| `diffEngine.ts` | 差异比较引擎 | -| `JsonDiffInput.tsx` | JSON 输入组件 | -| `DiffResult.tsx` | 差异结果展示 | -| `DiffNavigator.tsx` | 差异导航器 | -| `JsonFormatSection.tsx` | 格式化区域 | -| `JsonConvertSection.tsx` | 转换区域(YAML/TOML/Minify) | -| `JsonTree.tsx` | JSON 树形展示 | - -### Base64Converter/ - -Base64 编解码工具,支持文本/文件/图片三种模式。 - -| 文件 | 用途 | -| ---------------------------- | --------------------- | -| `index.tsx` | 页面入口,子模式切换 | -| `useBase64Converter.ts` | 业务逻辑 Hook | -| `TextMode.tsx` | 文本模式 | -| `Base64ConverterSection.tsx` | 文件/图片通用转换区域 | - -### MarkdownToHtml/ - -Markdown 转 HTML 工具,支持分栏/预览/源码三种视图模式。 - -### HtmlToMarkdown/ - -HTML 转 Markdown 工具,支持分栏/预览/Markdown 三种视图模式。 - -### RightClickRestorer/ - -右键菜单恢复工具,解除网站对右键的限制。 - -| 文件 | 用途 | -| -------------------------- | ------------- | -| `index.tsx` | 页面 UI | -| `useRightClickRestorer.ts` | 业务逻辑 Hook | - -## 新增页面 - -1. 在 `types/storage.d.ts` 添加 `PageType` 联合类型成员 -2. 在 `config/features.tsx` 的 `FEATURES` 数组添加配置 -3. 在 `pages/` 创建页面目录(遵循上述结构) -4. 在 `i18n/locales/{zh,en}/features.json` 添加翻译 -5. 如需新权限,更新 `wxt.config.ts` -6. 添加对应的单元测试