v2.0.0 · Windows · MIT

从零写起的
PDF 阅读与批注工具

打开快、标注真的存进文件、页面能改。没有安装程序,不需要联网,也不上传你的文档。

连续滚动与页面虚拟化、完整重写 PDF 的页面编辑、11 种标记与图形批注、6 种标准图章、批注回复、注释展平与总括、跨文件夹搜索。界面代码与 PDF 写入器都是自己写的。

免安装,解压即用 Windows 10 及以上 2026-10-18 发布

PDF Looker Pro — Test Fixture · 24 pages
PDF Looker Pro 界面:左侧为缩略图与批注列表,页面中有打字机批注、高亮、图章与距离测量
真实的界面截图:打字机批注、文字高亮、标准图章、距离测量,以及右侧按页编排的批注列表
731项浏览器断言
28个测试套件
11种标记与图形批注
<1 MB应用自身代码与素材
能力

四块功能,每一块都做到能用

不是功能清单的堆砌:每一块都有对应的实现深度和回归测试,也都在打包后的应用里验证过。

阅读

像一个阅读器那样快

  • 连续、单页、对开、连续对开四种视图
  • 页面虚拟化:只渲染视口附近的页面,两百页和两页一样快
  • 实际大小、适合宽度、适合页面、适合可见区域、缩放到指定比例
  • 放大镜跟随指针,图案直接取自渲染好的页面
  • 打印:页范围、缩放、方向;视图历史用 Alt+← / →
文档编辑

真的改这一份文件

  • 整份重写:重建页树、逐对象搬运、重算交叉引用
  • 旋转、删除、插入、插入空白页、提取、裁剪、页面重排
  • 合并另一份 PDF:引用重新编号,页面按位置插入
  • 新建空白文档;从一张图片生成一份文档
  • 批注跟着页面走,页面挪了位置批注也挪
批注

写进 PDF,别的阅读器也看得见

  • 高亮、下划线、删除线、替换文本、手绘、便签、矩形、椭圆、箭头、打字机、对应文本
  • 6 种标准图章,写成 /Stamp,其他阅读器认得出名字
  • 回复写成 /IRT 批注,是一条真的讨论串
  • 每条批注带作者(/T);展平进页面,或把带批注的页面汇总成一份新文档
  • 高亮表单字段,一眼看出哪里要填(本阅读器不代填)
查找

找得到,也找得全

  • 结果按页分组,每条带命中词前后的原文
  • 点一条就跳过去并高亮,不用按四十次回车
  • 跨文件夹搜索:递归查找整棵目录里的 PDF,按文件→页两级排列
  • 保存搜索:起个名字,下次一键重跑
实现

PDF 写入器是自己写的

阅读交给 pdf.js(Apache-2.0),外壳是 Electron。但「把批注写进文件」和「改页面」这两件事,没有现成组件能用,是从字节开始实现的。

增量更新,不动原文

追加新对象、重写加了批注的那几页、末尾再补一段带 /Prev 的交叉引用。原始字节一个不改,所以别家阅读器看不出异常,文件被截断也不会坏。

% appended by this application
63 0 obj
<< /Type /Annot /Subtype /FreeText
   /Rect [90 652 330 722] /P 5 0 R
   /Contents <feff8fd94e005bb9758476846539>
   /PLP << /V 1 /K /textbox >> >>
endobj
startxref
21328   % previous section is chained through /Prev

改页面就是重写一份

删页、换序、合并不能靠追加完成,所以另有一条整份重写路径:把页树拍平、继承来的 MediaBox 和 Resources 物化到每一页、所有对象搬过去重新编号,再算出一份新的交叉引用。旧对象成了孤儿,合法且无害。

// merging is the only cross-graph copy in the codebase
for (const num of extraDoc.objectNumbers()) {
  map.set(num, next++);          // old → new
}
// every reference inside the incoming document is renumbered,
// or it would point at whatever the host keeps at that number
验证

怎么证明它是对的

功能写完不算完:构建要过,浏览器里要真的点一遍,打包后的应用里还要再点一遍。这套流程抓出过不少只有真跑一遍才会现形的问题。

✓npm test — 28 个套件、731 项断言,0 失败
✓npm run test:desktop — 打包后的应用里 26 + 21 + 8 项断言
✓npm run build — 类型检查与构建,CI 里每次都跑
✓保存 → 重开 → 点选 → 连存两次 → 删一条 → 存 → 重开,这条链有专门的回归测试:它对应的正是「批注存进去以后删不掉」那类缺陷。
已知限制

没做的,和做不到的

写在这里,是因为把边界说清楚比把功能说满更有用。

  • 只有 Windows 便携版,没有安装程序,也没有代码签名 —— 首次运行会被 SmartScreen 拦一下。
  • 加密的 PDF 不能写,可以打开看,但保存批注会被拒绝。
  • 反复保存会让文件变大:增量更新不重写全文,被替换的对象留成孤儿。
  • 展平不能编码非 Latin-1 文字,因为嵌入的是 Helvetica。中文批注展平后可能变成问号。
  • 表单字段只能高亮、不能填写;没有 OCR、没有数字签名。
  • 108 MB 的下载体积几乎全是 Electron 运行时;应用自身代码和素材不到 1 MB。瘦身仍在路线图上。

下载,然后打开你自己的 PDF

解压即用,不需要注册,不上传任何文件。源码是 MIT,欢迎拿去改。