Files
testing-tool/.github/workflows/ci.yml
T
LingandRX efbed7cf53 feat: Tailwind CSS/shadcn/ui 迁移 & 右键菜单功能 (#42)
* feat: 添加 contextMenus 权限和消息类型定义

* feat: 实现右键菜单注册与点击分流逻辑

- 新增 utils/contextMenu.ts 封装菜单配置和解析函数
- 在 background.ts 监听 onInstalled 初始化菜单
- 实现 contextMenus.onClicked 点击事件处理
- 分流逻辑:优先发送到侧边栏,否则打开 options 页面
- 添加 contextMenu 单元测试(15个测试用例)
- 更新 vitest.setup.ts 添加 contextMenus mock

* feat: 实现 Content Script 原位轻量提示 UI

- 新增 uiPopover.ts 实现原位弹窗组件(深色主题、自动定位、自动隐藏)
- 新增 contextMenuHandler.ts 处理右键菜单消息
- 时间戳转换:在点击位置显示转换结果
- 文本统计:显示字符/单词/行数/字节统计
- 更新 messageHandler.ts 挂载右键菜单消息监听

* feat: 实现 React 页面层右键菜单数据联动

- 新增 useContextMenuData Hook 处理右键菜单数据传递
- 重构 Jwt/Base64Converter/TextStatistics/QrCode 页面接收右键数据
- RouterProvider 支持从 URL 参数解析右键菜单数据
- 添加 contextMenu/pendingData 存储键到 StorageSchema
- 添加 useContextMenuData 单元测试(12个测试用例)

* test: 添加 background 单元测试与边界情况处理

- 新增 entrypoints/__tests__/background.test.ts (12个测试用例)
- 超长文本截断限制 (>10000字符)
- Base64 内联图片拦截并返回错误提示
- 更新 parseContextMenuClick 返回 ParseResult 格式
- 更新测试匹配新的返回格式
- lint/typecheck/test 全部通过 (579个测试)

* fix: 修复右键菜单跳转到错误页面的问题

- 将 options 页面路径从 '/entrypoints/options/index.html' 修正为 '/options.html'
- WXT 构建后 entrypoints/options/index.html 会输出为根目录的 options.html

* fix: 修复右键菜单跳转目标为 popup 页面

- 将 fallback 页面从 options.html 改为 popup.html
- popup 页面使用 RouterProvider,可以正确处理 URL 参数并跳转到对应功能页面
- options 页面是独立设置页,不支持 URL 参数路由

* fix: 使用 openPopup() 替代 tabs.create() 打开弹窗

- background.ts: 使用 browser.action.openPopup() 打开 popup 弹窗
- 先保存数据到 storage,然后打开 popup
- RouterProvider.tsx: 初始化时检查 storage 中的 pendingData 并跳转到对应页面
- 移除之前错误的 tabs.create() 方式

* fix: 修复右键菜单数据未传递到目标页面的问题

- RouterProvider 不再提前清除 pendingData
- 让目标页面的 useContextMenuData 来消费和清除数据
- 这样确保 TextStatistics 等页面能正确接收选中的文本

* fix: 修复 popup 已打开时右键菜单不生效的问题

- 在 RouterProvider 中添加对 contextMenu/pendingData 的 storage 变化监听
- 当 pendingData 变化时,自动跳转到对应功能页面
- 解决了 openPopup() 只聚焦已有窗口而不触发重新挂载的问题

* feat: 支持右键菜单图片二维码识别

- 在 qrCodeParser.ts 中添加 parseQrCodeFromUrl 函数,支持从图片 URL 解析二维码
- 在 QrCodeToUrlSection 中使用 useContextMenuData 接收右键菜单传递的图片 URL
- 自动下载图片并解析二维码,显示解析结果

* refactor: 暂时移除图片二维码识别功能

- 删除 qrCode-image 右键菜单配置
- 删除 parseQrCodeFromUrl 函数
- 删除 QrCodeToUrlSection 中的 useContextMenuData 相关代码
- 更新相关测试用例

* feat: 支持右键菜单时间戳转换

- 在 useTimestampConverter 中添加 useContextMenuData hook
- 智能识别输入是时间戳还是日期时间字符串
- 自动切换到对应模式并执行转换
- 时间戳自动识别秒/毫秒单位

* fix: 修复右键菜单功能的多个逻辑漏洞

1. 修复时区硬编码问题 - 使用用户选择的时区而非固定 Asia/Shanghai
2. 修复 openPopup() 失败后数据残留 - 失败时清除 storage 中的待处理数据
3. 统一数据过期时间常量 - 导出 CONTEXT_MENU_DATA_EXPIRY_MS 并统一使用
4. 修复 featureKey 类型断言不安全 - 使用映射表处理非常规菜单 ID

* refactor(qrcode): 提取独立组件并添加单元测试

- 创建 pages/QrCode/types.ts 定义状态类型接口
- 提取 QrCodePreview 组件用于二维码预览和操作
- 提取 ImageUploader 组件封装图片上传、拖拽、粘贴逻辑
- 重构 UrlToQrCodeSection 状态提升到父组件
- 重构 QrCodeToUrlSection 通过回调传递解析结果
- 更新主页面 index.tsx 集中管理所有状态
- 为 QrCodePreview 和 ImageUploader 添加单元测试 (23 个用例)

* refactor(qrcode): 引入通用组件并重构双栏布局

- 引入 SwitchButtonGroup 用于模式切换
- 引入 TextInputArea 用于文本输入和结果展示
- 使用 MUI Grid 构建响应式双栏布局
- 实现 generate/parse 模式下的左右面板内容切换
- 修复 iconColor 颜色格式错误,使用 qrCodePageStyles.primaryColor

* refactor(qrcode): 国际化补充、质量保障与错误处理优化

- 补充 i18n 翻译键(generateMode, parseMode, pasteHint 等)
- 创建 useDebounce Hook 实现输入防抖 (200ms)
- 使用 useRef 解决 useEffect 无限循环问题
- 编写 pages/QrCode 单元测试 (7 个用例)
- 优化右键菜单错误处理,改进用户提示
- 运行 603 个测试全部通过

* refactor(qrcode): 组件化重构,采用 Context + Hook 模式

- 创建 QrCodeContext 和 QrCodeProvider 管理共享状态
- 提取 useQrCode Hook 封装所有状态和业务逻辑
- 创建 GeneratePanel 组件处理二维码生成模式
- 创建 ParsePanel 组件处理二维码解析模式
- 简化 index.tsx 为容器组件 (340行 → 47行)
- 删除未使用的旧组件文件 (QrCodeToUrlSection, UrlToQrCodeSection)
- 清理 types.ts 中未使用的类型定义
- 603 个测试全部通过

* fix(qrcode): 固定二维码预览图片尺寸,避免布局抖动

- 设置 QR_PREVIEW_IMAGE 固定尺寸 250x250
- 与 QRious 生成的二维码大小保持一致
- 解决输入内容变化时预览窗口大小跳动问题

* fix(qrcode): 修复切换 tab 后二维码图片失效问题

- 移除 ImageUploader 组件卸载时的预览 URL 释放逻辑
- 在 useQrCode hook 中统一管理预览 URL 生命周期
- 创建新预览 URL 前释放旧的,避免内存泄漏

* fix(qrcode): 固定图片上传区域高度,避免布局抖动

- 将 DROPZONE 的 minHeight: 200 改为 height: 250
- 与二维码预览图片高度保持一致
- 解决上传图片时 div 高度变化问题

* refactor(qrCode): 优化二维码解析功能

- 将'二维码转 URL'改为'二维码转文本'
- 将解析结果的文本预览框的 placeholder 置为空
- 去除手动解析二维码功能,只保留自动解析

* fix(pageHeader): 使用 MUI 主题色替代硬编码颜色,支持暗色模式

* feat(pageHeader): popup 模式下隐藏 PageHeader 组件

* fix(i18n): 统一使用 useLazyTranslation 避免翻译 key 闪烁

* perf: 配置 manualChunks 拆分 vendor chunk,优化打包体积

- 使用 Vite 插件 manualChunksForHtmlOnly 仅对 HTML 多入口构建生效
- 跳过 background/content-script 的 IIFE 构建(不支持 manualChunks)
- 拆分 vendor-react (193KB)、vendor-mui (326KB)、vendor-i18n (55KB)
- 按需加载 vendor-qr (78KB)、vendor-dnd (45KB)、vendor-markdown (41KB)
- PageErrorBoundary chunk 从 454KB 降至 36KB

* chore: upgrade wxt to v0.20.26 and @wxt-dev/module-react to v1.2.2

* chore: upgrade low-risk dependencies

- react: 19.2.3 → 19.2.6
- react-dom: 19.2.3 → 19.2.6
- dayjs: 1.11.19 → 1.11.20
- marked: 18.0.3 → 18.0.4
- prettier: 3.8.1 → 3.8.3
- terser: 5.46.0 → 5.47.1
- i18next: 26.0.8 → 26.2.0
- react-i18next: 17.0.6 → 17.0.8
- globals: 17.2.0 → 17.6.0
- eslint-plugin-react-hooks: 7.0.1 → 7.1.1
- @typescript-eslint/*: 8.54.0 → 8.59.4
- typescript-eslint: 8.54.0 → 8.59.4
- @testing-library/jest-dom: 6.6.0 → 6.9.1
- @testing-library/react: 16.0.0 → 16.3.2
- @testing-library/user-event: 14.5.2 → 14.6.1
- @testing-library/dom: added as peer dependency
- @types/react: 19.2.7 → 19.2.15
- @types/chrome: 0.1.36 → 0.1.42
- @types/webextension-polyfill: 0.12.4 → 0.12.5

* chore: upgrade medium-risk dependencies

- lint-staged: 16.2.7 → 17.0.5
- jsdom: 25.0.0 → 29.1.1
- @vitejs/plugin-react: 4.3.4 → 6.0.2
- vitest: 2.0.0 → 4.1.7
- @vitest/coverage-v8: upgraded to match vitest
- @webext-core/messaging: 2.3.0 → 3.0.1
- eslint: 9.39.2 → 10.4.0
- @eslint/js: added as new dependency
- @types/marked: removed (marked now provides its own types)

Fixes:
- Fix ref update during render in useQrCode.ts
- Fix ref update during render in useStorageCleaner.ts
- Add error cause in jwt.ts decode function
- Add type assertion for mock functions in htmlToMarkdown.test.ts

* chore(deps): 降级 eslint 版本并移除 @eslint/js

* docs: 精简 AGENTS.md,聚焦高信号信息

* test: 修复测试中的 act() 警告和 clipboard mock 问题

- TextInputArea: 使用 userEvent 替代 fireEvent,用 vi.spyOn 替代 Object.assign mock clipboard
- ImageMode/FileMode: 添加 waitForStorageReady() 等待 useStorageState 异步初始化

* perf: 优化首屏加载,快照有效时跳过骨架屏

- isLoaded 初始值根据 localStorage 快照是否存在决定
- 后续访问直接渲染真实 DOM,无需等待 chrome.storage 异步加载
- loadInitialData 仍在后台静默执行确保数据同步

* 引入 Tailwind CSS 和 shadcn/ui

* 替换 Timestamp 页面图标为 lucide-react 的 Clock 图标

* 用 Tailwind CSS 重写 Timestamp 页面的 MUI 基础排版组件

* 用 Tailwind CSS 重构 ResultView 和 LiveClock 组件

* 用 Tailwind CSS 重写 Dashboard/index.tsx 和 ToolCard.tsx

* 用 Tailwind CSS 重写 TextStatistics 页面

* 用 Tailwind CSS 重写 Base64Converter 页面

* 用 Tailwind CSS 重写 QrCode 页面及相关组件

* 用 Tailwind CSS 重写 Jwt 页面

* 用 Tailwind CSS 重写 StorageCleaner 页面,创建 shadcn/ui Dialog 组件

* 用 Tailwind CSS 重写 JsonTools 页面

* 用 Tailwind CSS 重构所有共享组件

* 修复 TypeScript 类型错误:将 MUI sx 语法改成标准 CSS 属性

* 重写基础骨架组件:用纯 Tailwind CSS 替换 MUI Box 组件

* 重写所有页面和组件:用纯 Tailwind CSS 替换 MUI 组件和图标

* 移除 MUI 依赖,简化配置文件,重写 ThemeModeProvider

* 移除 wxt.config.ts 中残留的 MUI chunk 配置

* 为 Dialog 组件添加暗黑模式背景色支持

* fix: 修复暗黑模式样式兼容性

- 在 tailwind.config.js 中启用 darkMode: 'class' 并扩展语义化颜色变量
- 将全项目硬编码颜色(bg-white、text-gray-*、border-gray-* 等)替换为语义化类名
- 修复 popup/index.html 硬编码浅色背景色
- 同步更新相关单元测试中的类名断言

* fix: 修复输入框和按钮在暗色模式下的样式问题

- 为 :root 和 .dark 添加 color-scheme,使浏览器表单控件默认样式适配暗色模式
- 将 bg-primary 搭配 text-white 的按钮改为 text-primary-foreground
- 替换残留的 hover:bg-blue-700、text-blue-500、bg-gray-200 等硬编码颜色
- 同步更新 TextInputArea 单元测试

* fix: 增强 SwitchButtonGroup 和立即转换按钮的视觉层级

- SwitchButtonGroup 选中按钮阴影从 shadow-sm 升级到 shadow-md
- 同步更新单元测试中断言
- Timestamp 立即转换按钮添加 shadow-md 增强边界感

* style: 隐藏所有窗口的滚动条

- 在全局 CSS 中为 html 添加 scrollbar-width: none(Firefox)
- 添加 ::-webkit-scrollbar { display: none }(Chrome/Safari/Opera)

* feat: add sonner dependency for toast notifications

* refactor: remove DomainHeader component and its usage

* refactor: 使用 className 替换 sx/buttonSx 并优化 SwitchButtonGroup 选中动画

* refactor: 简化 TextInputArea,移除 showMessage 和 MUI 样式,改用 shadcn 样式和 sonner toast

* refactor: 简化 TextInputArea,移除 showMessage 和 MUI 样式,改用 shadcn 样式和 sonner toast

* refactor: 重构 QrCodePreview 组件,继承 HTMLDiv 属性并统一 shadcn 样式

- 组件改为继承 `React.HTMLAttributes<HTMLDivElement>`,支持外部传入 className 和事件
- 使用 `cn()` 函数合并外部类名
- 空白状态改用 `border border-dashed` 和更浅的 `bg-muted/40` 背景
- 正常状态改为纯白背景柔边圆角容器包裹二维码,确保暗黑模式下黑白对比度
- 下载/复制按钮完全对齐 shadcn 的 Outline 与 Default 样式规范
- 更新测试用例中的 alt 文本为 "QR Code Preview"

* refactor: 将 PageHeader 组件样式从 MUI sx 迁移至 Tailwind 类名,并更新测试

* refactor: 更新PageErrorBoundary的文案和样式以对齐shadcn主题

- 错误提示从“该页面加载失败”改为“该功能运行异常”
- 重试按钮文字从“重试”改为“重新尝试”
- 使用border-destructive, bg-destructive等语义化类名替换硬编码颜色
- 更新对应测试断言

* refactor: 重构 CopyButton 与 RouterContainer 组件,移除 GlobalSnackbar 并统一使用 sonner toast 和 cn 工具函数

* refactor: 移除 MUI sx 样式和未使用的 GlobalSnackbar 引用

* feat: add @radix-ui/react-select dependency

* feat: add Input and Select shadcn UI components

* refactor: 重构 Timestamp 页面使用响应式 Hook 统一状态并全面迁移至 shadcn 样式

* refactor: 将 TextStatistics 页面和 TextInputArea 组件全面迁移至 shadcn 样式并优化布局

* feat: add Badge, Checkbox, Label, and Switch shadcn UI components

* refactor: 全面迁移 StorageCleaner 页面至 shadcn 样式并移除 GlobalSnackbar 依赖

* refactor: 全面重构 JsonTools 页面,采用声明式响应架构并统一 shadcn 样式

* refactor: 全面重构 Jwt 页面,采用防抖输入并统一 shadcn 样式

* refactor: 重构 Dashboard 页面和 ToolCard 组件,全面迁移至 shadcn 样式并优化布局

* refactor: 重构 HtmlToMarkdown 和 MarkdownToHtml 页面,统一 shadcn 样式并优化打印与暗色模式

* refactor: 抽离 useBase64Converter hook 并新增 Base64ConverterSection 组件,统一 Base64 转换页面的 shadcn 样式

* refactor: 重构 QrCode 页面为声明式响应架构并统一 shadcn 样式

* refactor: 优化 Dashboard 布局及 ToolCard 描述文本截断处理

* refactor: 优化 MarkdownToHtml 预览样式,剥离 CSS 变量回退值并增强 iframe 暗色模式自适应

* refactor: 优化 Popover 安全性和交互体验,修复 Context Menu 数据持久化问题并添加 i18n 支持

* refactor: strengthen i18n type safety and fix async Promise handling in language detection

* refactor: extend vitest setup with full chrome/browser mocks and i18n utility mock

* refactor: migrate storage listeners to wxt/browser and refactor provider state management

* refactor: restructure CI/CD pipelines with cached dependencies, separate setup job, and multi-browser builds

* refactor: remove tsc check from lint-staged and reorder lint commands

* refactor: migrate eslint config to tseslint.config with projectService and upgrade React rules

* refactor: use __MSG_ placeholders for i18n and remove postcss config

* refactor: replace __MSG_ placeholders with static strings for extension name and description

* refactor: add React version detection and disable prop-types in eslint; refactor lazy translation tests with proper mock isolation and Chrome/browser stubs

* refactor: use regex matchers in StorageCleanerConfirm tests and add chrome/browser mocks

* refactor: use regex matchers for i18n text and add uniform mocks in test files

* ci: add wxt prepare step to generate .wxt types for typecheck and tests

---------

Co-authored-by: Ubuntu <ubuntu@localhost.localdomain>
2026-05-23 00:02:43 +08:00

162 lines
4.5 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# 💡 1. 提速核心:前置基建节点(Infrastructure Initialization
# 专门负责锁死环境、同步下载并缓存 node_modules,下游节点直接满血复用!
setup:
name: Prepare Dependencies
runs-on: ubuntu-latest
outputs:
cache-key: ${{ steps.cache-info.outputs.key }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
# 建立基于 package-lock.json 唯一哈希的缓存大闸
- name: Cache Node Modules
id: cache-nodemodules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-v22-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-v22-
- name: Install dependencies
if: steps.cache-nodemodules.outputs.cache-hit != 'true'
run: npm ci
- name: Output Cache Key
id: cache-info
run: echo "key=${{ runner.os }}-node-v22-${{ hashFiles('**/package-lock.json') }}" >> $GITHUB_OUTPUT
# 💡 2. 静态语法质检节点(依赖前置节点完成)
lint:
name: Lint
runs-on: ubuntu-latest
needs: setup
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Restore Node Modules Instantantly
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-v22-${{ hashFiles('**/package-lock.json') }}
- name: Run ESLint
run: npm run lint
# 💡 3. 强类型守卫节点(2秒瞬时恢复,开箱即查)
typecheck:
name: TypeScript Check
runs-on: ubuntu-latest
needs: setup
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Restore Node Modules Instantantly
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-v22-${{ hashFiles('**/package-lock.json') }}
- name: Generate WXT types
run: npx wxt prepare
- name: Run TypeScript type check
run: npm run typecheck
# 💡 4. 单元测试节点(无缝运行你刚刚修复完的 setupTests.ts 套件)
test:
name: Unit Tests
runs-on: ubuntu-latest
needs: setup
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Restore Node Modules Instantantly
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-v22-${{ hashFiles('**/package-lock.json') }}
- name: Generate WXT types
run: npx wxt prepare
- name: Run tests
run: npm run test
# 💡 5. 多端分布式最终编译节点(Production Matrix Compliance
build:
name: Build (${{ matrix.browser }})
runs-on: ubuntu-latest
# 只有当 Linter、类型大闸、Vitest 单元测试全数满分通过,才放行最终打包编译
needs: [ lint, typecheck, test ]
strategy:
matrix:
# 💡 完美对齐 WXT 跨端架构:将 firefox 同步纳入生产编译大矩阵,
# 如果 firefox 编译因任何多端不兼容挂掉,CI 会立刻拉起警报,防护力拉满!
browser: [ chrome, firefox ]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Restore Node Modules Instantantly
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-v22-${{ hashFiles('**/package-lock.json') }}
# 💡 动态代理编译指令:完美匹配 WXT / 各类多端打包器的标准构建命令
- name: Generate WXT types
run: npx wxt prepare
- name: Build Extension (${{ matrix.browser }})
run: |
if npm run | grep -q "build:${{ matrix.browser }}"; then
npm run build:${{ matrix.browser }}
else
npm run build -- --browser ${{ matrix.browser }}
fi