Skip to content

Latest commit

 

History

History
367 lines (289 loc) · 14.8 KB

File metadata and controls

367 lines (289 loc) · 14.8 KB

PdfToolbox — 项目规范文档 (SPEC)

受众:开源贡献者
最后更新:2026-06-02
版本:0.1.0


1. 项目目标

1.1 核心理念

PdfToolbox 是一个纯本地离线的 PDF 桌面工具箱,基于 Rust + Tauri 2.x 构建。

  • 本地优先:所有 PDF 处理在本机完成,无需联网,文件不会离开用户电脑
  • 即开即用:无需注册登录,无文件大小限制(受系统内存限制)
  • 免费开源:100% 开源,无广告,无收费功能
  • 极简体验:清爽的 UI 设计,聚焦核心功能,零学习成本

1.2 目标用户

  • 普通办公人员:需要快速合并、拆分、压缩 PDF
  • 文档处理用户:需要格式互转(Word/PPT/Excel ↔ PDF)
  • 隐私敏感用户:不愿意将文档上传到在线 PDF 工具
  • 开发者/贡献者:对 Rust + Tauri 桌面应用开发感兴趣的开源贡献者

1.3 项目状态

维度 状态
Rust 后端命令 ~48 个已实现
前端 UI 全部功能已有对应界面
测试覆盖率 基础功能有单元测试,覆盖率约 40%
CI/CD 未配置
国际化 仅中文
发布渠道 未发布

2. 开发命令

2.1 快捷命令

npm run dev              # 启动 Vite 前端开发服务器 (port 3000)
npm run tauri dev        # 启动 Tauri 完整开发模式(前端 + Rust 热重载)
npm run tauri build      # 生产构建,生成安装包 (.exe/.msi/.dmg)
npm run build            # 仅构建前端 (Vite)
npm run lint             # TypeScript 类型检查 (tsc --noEmit)
npm run clean            # 清理 dist 目录
npm run tauri -- [args]  # 透传参数给 Tauri CLI

2.2 Rust 测试

# 运行所有 Rust 单元测试(在 src-tauri 目录下)
cd src-tauri && cargo test

# 运行特定测试
cd src-tauri && cargo test test_merge_two_pdfs

# 运行测试并显示输出
cd src-tauri && cargo test -- --nocapture

# 检查编译
cd src-tauri && cargo check

2.3 代码检查

npm run lint            # TypeScript 类型检查
cd src-tauri && cargo clippy   # Rust 代码风格检查(需安装 clippy)
cd src-tauri && cargo fmt      # Rust 代码格式化

2.4 构建说明

  • Tauri 构建需要:Rust 工具链 (>=1.85)、Node.js (>=20)、WebView2 (Windows 内置)
  • 额外系统依赖
    • libheif — HEIC 转 JPG(可选,运行时检测)
    • LibreOffice — 文档格式互转(可选,运行时检测,推荐内置便携版)
    • poppler/cairo — PDF 渲染为图片(暂未实现,可选)

3. 项目结构

pdftoolbox/
├── src/                          # React 前端
│   ├── App.tsx                   # 主页:搜索 + 分类导航 + 工具卡片网格
│   ├── ToolDetailView.tsx        # 工具详情页:文件选择 + 设置 + 处理 + 结果预览
│   ├── PdfPreview.tsx            # PDF 预览(基于 pdf.js)
│   ├── types.ts                  # TypeScript 接口定义 (Tool/Category/ToolboxConfig)
│   ├── toolbox-config.json       # 配置驱动:工具定义清单(JSON 格式)
│   ├── main.tsx                  # React 入口
│   └── index.css                 # Tailwind CSS v4 样式
│
├── src-tauri/                    # Rust 后端
│   ├── src/
│   │   ├── main.rs               # Windows 入口(隐藏控制台窗口)
│   │   ├── lib.rs                # Tauri Builder + 命令注册 + 插件初始化
│   │   ├── commands.rs           # Tauri 命令层(输入校验 + 调用 pdf_ops)
│   │   └── pdf_ops.rs            # PDF 处理核心(merge/split/compress/rotate 等)
│   ├── Cargo.toml                # Rust 依赖管理
│   ├── tauri.conf.json           # Tauri 窗口/构建/安全配置
│   └── capabilities/             # Tauri v2 权限配置 (dialog/shell)
│
├── vite.config.ts                # Vite 构建配置
├── package.json                  # npm 依赖 + 脚本
├── tsconfig.json                 # TypeScript 配置
├── CLAUDE.md                     # AI 辅助说明文件
├── SPEC.md                       # 本文件 - 项目规范
└── README.md                     # 项目 README(待补充)

3.1 架构分层

┌─────────────────────────────────────────┐
│  前端 (React 19 + TypeScript + Tailwind) │
│  App.tsx → ToolDetailView.tsx           │
│         ↓ invoke('command', args)       │
├─────────────────────────────────────────┤
│  命令层 (commands.rs)                    │
│  输入校验 + 参数默认值 → 调用 pdf_ops    │
├─────────────────────────────────────────┤
│  核心处理层 (pdf_ops.rs)                 │
│  lopdf / image / pdf-extract / qrcode   │
├─────────────────────────────────────────┤
│  LibreOffice (可选)                     │
│  文档格式互转 (Word/PPT/Excel/EPUB/PDF) │
└─────────────────────────────────────────┘

3.2 数据流

用户点击"选择文件" → Tauri 原生对话框 → 文件路径传给前端
  → 用户设置参数 → 点击"处理"
    → invoke Tauri 命令 (camelCase 参数名)
      → Rust 后端处理 → 输出到 %TEMP%/pdftoolbox/ 临时目录
        → 返回路径给前端
          → 前端显示完成状态 → 用户"打开文件"/"打开所在文件夹"

3.3 配置驱动架构

工具定义在 src/toolbox-config.json,前端根据 tool.id 查找 CMD_MAPToolDetailView.tsx 中定义)映射到对应的 Tauri 命令。

// toolbox-config.json 中的一条工具定义
{ "id": "merge", "name": "PDF合并", "category": "BASICS", "icon": "Merge" }
// CMD_MAP 中的命令映射
merge: { cmd: 'merge_pdfs', multiple: true, getArgs: (files) => ({ files }) }

4. 代码风格

4.1 Rust 代码规范

  • 注释语言:所有 /// 文档注释使用中文
  • 属性位置/// 注释位于 #[tauri::command] 之前
  • 错误消息:使用中文
  • 命名风格:Rust 标准 snake_case
  • 错误处理:函数返回 Result<T, String>,用 map_err 转换错误为中文描述
/// 合并多个 PDF 文件为一个:加载所有 PDF,重映射对象 ID 避免冲突,合并页面树到同一文档
pub fn merge_pdfs(input_paths: &[String], output_path: &str) -> Result<(), String> {
    // ...
}

4.2 Rust 命令设计原则

  1. 命令拆分:避免一个命令包含多个 Option 参数区分不同模式,应拆分为独立命令
  2. 参数必填:参数尽量为必填(非 Option),减少反序列化歧义
  3. 参数命名:前端 invoke 传参使用 camelCase,Tauri v2 自动映射到 Rust snake_case
// ✅ 正确
fn split_pdf_pages(file: String, pages_per_group: u32)

// ❌ 避免
fn split_pdf(file: String, ranges: Option<String>, pages_per_group: Option<u32>)

4.3 TypeScript/React 规范

  • 类型定义:使用 TypeScript 接口(interface),不使用 type
  • 组件风格:函数组件 + React Hooks
  • 图标:使用 lucide-react,通过 ICON_MAP 按名称查找
  • 样式:Tailwind CSS v4 + utility classes
  • 动画:使用 motion (Framer Motion)

4.4 国际化

  • 所有 UI 文本目前为简体中文
  • 错误消息前端显示中文(来自 Rust 的 Err 字符串)
  • 暂未使用 i18n 框架,贡献者需保持中文一致性

5. 测试策略

5.1 Rust 单元测试

位置pdf_ops.rs 末尾的 #[cfg(test)] mod tests { ... }

已有测试覆盖

功能模块 测试用例 覆盖情况
Merge test_merge_two_pdfs
test_merge_empty_list (边界)
test_merge_single_pdf (边界)
test_merge_invalid_path (错误路径)
Split test_split_all_pages / test_split_ranges
test_split_by_pages / test_split_by_pages_zero
test_split_invalid_range (错误路径)
Compress test_compress_pdf / test_compress_levels
Rotate test_rotate_all_pages / test_rotate_cumulative
Delete test_delete_pages / test_delete_range
Extract test_extract_pages / test_extract_range
Reorder test_reorder_pages / test_reorder_empty
Watermark test_add_watermark
Page Numbers test_add_page_numbers
Info test_get_pdf_info / test_set_pdf_info
Crop/Resize test_crop_pdf / test_resize_pdf
Flatten test_flatten_pdf
Protect/Unlock test_protect_roundtrip / test_protect_empty_password
test_protect_wrong_password_fails (错误路径)
Replace Text test_replace_text_simple / test_replace_text_not_found
test_replace_text_empty_search / test_replace_text_multiple
Images to PDF test_images_to_pdf / test_images_to_pdf_empty
WebP to JPG test_webp_to_jpg
QR Code test_generate_qr / test_generate_qr_empty
Repair test_repair_valid_pdf / test_repair_nonexistent
test_repair_empty_file
Read File test_read_file_base64 / test_read_file_base64_invalid
HEIC test_heic_to_jpg_not_found
Extract Images test_extract_images
Fill Form test_fill_pdf_form_empty
PDF to Text test_pdf_to_text

5.2 测试辅助函数

  • create_test_pdf(page_count) — 创建用于测试的空白 PDF
  • create_text_pdf(text) — 创建含文本内容的 PDF
  • temp_path(ext) — 生成临时文件路径

5.3 测试要求

新增功能或修改既有功能时,必须

  1. 为核心处理函数(pdf_ops.rs)添加对应单元测试
  2. 至少包含:1 个正常路径、1 个边界条件、1 个错误路径
  3. 测试使用 create_test_pdf / create_text_pdf 等辅助函数
  4. 测试应独立、可重复、不依赖外部文件

5.4 前端测试

前端目前没有测试基础设施。贡献者可选择引入:

  • vitest + @testing-library/react 用于组件测试
  • 优先测试 ToolDetailView.tsx 中的 handleProcess 逻辑

6. 项目边界

6.1 ✅ 始终遵守

规则 说明
纯本地处理 所有文件操作在本地完成,不发送网络请求
Rust 核心 所有 PDF 处理逻辑在 Rust 端实现,前端仅做 UI 和调用
中文优先 UI 文本、注释、错误消息全部使用中文
配置文件驱动 新增工具时先注册到 toolbox-config.json
camelCase 传参 前端 invoke 使用 camelCase 参数名映射到 Rust snake_case
临时文件清理 输出文件放在 %TEMP%/pdftoolbox/,系统自动清理
中文注释 Rust /// 文档注释使用中文说明功能和参数
错误友好 Rust 端返回中文错误消息,前端直接显示
函数注释 所有 Rust 函数必须有中文注释描述用途、参数、返回值
测试覆盖 新增核心功能必须有对应的单元测试

6.2 ❓ 先询问再行动

场景 说明
新增外部依赖 添加 Rust crate 或 npm 包前先讨论必要性
引入系统依赖 需要用户安装额外系统库(如 poppler/tesseract)的功能需慎重讨论
改变架构 修改数据流、命令注册方式、配置格式等需先讨论
添加付费/云端功能 引入云存储、付费墙等违反本地优先理念的功能
影响性能的变更 大文件处理、内存占用优化等需讨论方案
跨平台问题 涉及 macOS/Linux 特有 API 或路径处理时需讨论
UI 大改 修改整体布局、色彩方案、交互模式时需讨论
数据库引入 项目目前无数据库依赖,引入需充分论证
CI/CD 配置 添加 GitHub Actions 自动构建等需讨论平台和策略
版本号升级 涉及 SemVer 主版本变更或破坏性变更前需讨论

6.3 ❌ 绝不做的

红线 说明
不上传文件到云端 任何功能都不应将用户文件发送到远程服务器
不收集用户数据 不埋点、不统计、不发送任何分析数据
不引入广告 应用内不展示任何商业广告
不要求注册/登录 用户无需创建账号即可使用全部功能
不开后门/远程代码执行 不做任何远程控制、自动更新下载、执行远程脚本
不引入 AGPL 等传染性许可证 依赖项需兼容当前许可证(MIT)
不修改用户文件 所有操作生成新文件,不覆盖原始文件(需另存为)

6.4 功能路线图

已实现 (48 个 Tauri 命令)

  • PDF 基础:合并、拆分(两种模式)、压缩(三级)、水印、页码、文字替换、叠加、优化、修复、扁平化、密文遮盖
  • 页面操作:旋转、删除、提取、重排、N-up、裁剪、缩放、裁半
  • 格式转换:图片→PDF、Markdown→PDF、HEIC→JPG、WebP→JPG
  • LibreOffice 互转:Word/PPT/Excel ↔ PDF、PDF→EPUB/HTML/PDF/A
  • 安全:加密、解密
  • 表单:填写 PDF 表单
  • 元数据:读取/设置 PDF 信息
  • 工具:生成二维码、生成密码、PDF 预览、比较差异、添加注释、添加书签、提取图片

待实现 (status: "pending" / "paused")

功能 状态 所需技术 优先级
PDF 编辑 (edit) pending 需要 PDF 内容流解析/重写
PDF 签署 (sign) pending 数字签名库
OCR 文本识别 (ocr) paused tesseract 系统库
创建可填写表单 (form-creator) paused 复杂表单字典构建
网页转 PDF (web-to-pdf) pending headless 浏览器
创建账单 (invoice-creator) paused PDF 排版引擎
用摄像头创建 PDF (cam-to-pdf) paused WebRTC 摄像头
PDF 求职申请书 (app-creator) paused 模板引擎

附录 A:技术栈版本

技术 版本
Rust edition 2021
Tauri 2.x
React 19.x
TypeScript 5.8.x
Vite 6.x
Tailwind CSS 4.x
lopdf 0.35
image 0.25
pdf-extract 0.7
pdfjs-dist 5.x
motion (Framer Motion) 12.x

附录 B:许可证

MIT License — 详情见项目 LICENSE 文件。