pdf-triptych
hanzhangzzz/agent-skills-zh/pdf-triptych/SKILL.md
把一份标准、规范、白皮书或长技术 PDF 拆解成一页三联图 HTML:第一张讲骨架(这份文档的结构是什么),第二张讲细节(概念之间的准确关系),第三张举例子(换成具体场景后每样东西落在哪)。三张图共用同一根横轴和同一套颜色,既有递进也有共同标尺。用于把读不动的长文档变成一页能讲、能评审、能贴进汇报的图。当用户说 /pdf-triptych、把这份 PDF 画成图、标准拆解、三联图、一张图讲清这份标准、文档骨架图、把 PDF 做成可视化 时使用。不用于普通 PDF 转文字、摘要,也不用于纯数据图表。
Skill2 starsChanged 3 days ago
---
name: pdf-triptych
description: |
把一份标准、规范、白皮书或长技术 PDF 拆解成一页三联图 HTML:第一张讲骨架(这份文档的结构是什么),第二张讲细节(概念之间的准确关系),第三张举例子(换成具体场景后每样东西落在哪)。三张图共用同一根横轴和同一套颜色,既有递进也有共同标尺。用于把读不动的长文档变成一页能讲、能评审、能贴进汇报的图。当用户说 /pdf-triptych、把这份 PDF 画成图、标准拆解、三联图、一张图讲清这份标准、文档骨架图、把 PDF 做成可视化 时使用。不用于普通 PDF 转文字、摘要,也不用于纯数据图表。
---
# pdf-triptych
把一份长文档拆成三张有递进、有共同标尺的图。
## 这套流程解决什么
长标准文档读不动,不是因为字多,是因为**结构藏在字里**:哪些是主线、哪些是横切、哪些只是用法,原文往往不说。直接"把 PDF 转成图"会得到一堆罗列的方框;正确顺序是先把结构挖出来,再决定用什么形状承载,最后才写代码。
三张图的分工与联系:
| 图 | 讲什么 | 与上一张的关系 |
|---|---|---|
| 一 · 骨架 | 这份文档的层级结构:从抽象到具体怎么展开,哪些定义横跨若干层,有没有第三维度 | — |
| 二 · 细节 | 概念之间的准确关系,通常是把原文里的几张 figure 揉成一张 | 与图一**同轴叠放**:图二的每个框落在图一的哪一列,就属于哪一层 |
| 三 · 例子 | 换成一个具体场景,每样东西落在哪一列 | 与图一**同列**:沿竖虚线往上看就知道它对应结构的哪一层 |
共同标尺有两样,缺一不可:**贯穿全图的竖向虚线(列)** 和 **全文统一的三类颜色**。
**张数由文档结构决定,不是写死三张。** 判断标准:
- 原文的几张 figure **之间有主从关系**(一张是骨架,另几张是它某个节点的放大)→ 骨架与细节**分成两张**,细节那张标明谁是谁的放大。
- 原文的 figure **互不相交、谁也不属于谁** → 骨架与细节**合成一张**,把几张切面并排,并明说"它们不是一条线上的几段"。这时总共两张图。
- 例子层始终独立成图。
第二次执行(ISO/IEC 22989)走的是第二条:那份标准的三张图互不兼容,原文从未说过谁属于谁,合成一张并列展示是对的。
## 视觉语法的底线
这套图的视觉语法是固定的,不要每次重新发明。下面几条直接用:
| 项 | 内容 |
|---|---|
| 色板哲学 | 纸灰 `#F0EFEB` + 炭黑两极;**一律实心**:不透明材质、不发光、不渐变滤镜、无阴影。质感全靠明度对比和形状 |
| 卡片四件套 | 结论式标题 `h2` + 副标题(图例、单位、范围,用 ` · ` 分隔)+ 图 + 来源行(全大写、加字距) |
| 标题规则 | **写结论不写图型名**。"从一个概念展开到每一条可落地的指标" 好过 "扇出树" |
| 形状 | 卡片圆角 24px,无边框无阴影,靠留白分卡 |
| 字体 | Inter + 苹方;标题 700 / 数值 800 / 轴标签 600 |
| 动画 | 只用一次淡入,快进快停不弹跳;必须带 `prefers-reduced-motion` 降级 |
| 交互 | 这根线背后有没有真实记录?没有(纯示意的发丝线)→ **禁止加交互**,给没有内容的元素加 hover 是欺骗 |
| 演示数据 | 确定性伪随机,禁用 `Math.random()`——刷新必须长一样,否则截图和回归对比全失效 |
| 说不的底线 | 发光 / 玻璃拟态 / 3D → 拒绝;断轴 → 拒绝 |
有两条是**概念结构图特有的**,和常见的数据图表做法正好相反:
**一、不要单一强调色。** 数据图表通常有一个要讲的结论(哪个最大、哪个异常),拿一个强调色指向它是对的。但概念结构图要讲的是**整体结构**,没有哪个分支比别的更重要,单一强调色会制造虚假的重点。
> **失败模式**:首次执行时,我把唯一的橙色给了一个分支(它确实是原文里最特别的一支)。用户的反馈是:"整个页面唯一的颜色给了这一支,一般人会觉得这是所有体系里最重要的一点,但我们想表达的是整体逻辑。"
>
> 改法:**三类分类色**——颜色表达"这个东西属于哪一类",不表达"它有多重要"。具体见 `references/visual-grammar.md`。
**二、最小字号按中文定。** 常见的图表字号下限 6.5 / 5.5px 是给英文和数字定的。**中文笔画密,9px 才读得清**,8.4px 是绝对下限(检查脚本按这个报警)。装不下就换行或缩短文案,不要缩字号。
色值、字号、部件画法全部写在 `references/visual-grammar.md`,那个文件是自包含的,不依赖任何外部 skill。
## 阶段 0 · 提取
```bash
pdftotext -layout input.pdf out.txt # 正文
pdfinfo input.pdf | grep Pages # 页数
```
**图必须用 Read 工具直接看,不能只读 pdftotext 的输出。** 原文的 figure 在文本里只剩一行图题,框名、箭头方向、箭头上的文字、图例分组全都丢了。这个 skill 的图二基本就是在重画原文的 figure,看不到图就只能瞎编。
```
Read(file_path="input.pdf", pages="11-12") # 直接看图所在的页
```
## 阶段 1 · 结构探针(必须派 subagent,不可跳过)
派一个 opus subagent 通读全文。**不要自己只读目录和几节就动手**——这是本流程最容易翻车的地方:只读局部会把并列关系误认成父子关系,把"可以"读成"必须"。
提问模板见 `references/probe-template.md`,六个问题一个都不能少。重点是:
- 层与层之间用**原文的英文短句**连接,不是你的概括
- 每张 figure 的**每个框名、每条箭头的方向与文字、图例的分组**
- **易误读点**:全文有没有 shall、某条规则是不是带限定词、某个说法是不是只针对某一类对象
subagent 返回后,把它纠正你的地方单独记下来。这些是后面写图注的素材,也是最能体现"真读了"的证据。
**失败模式**:首次执行(ISO/IEC 25002)时,我只读了其中五六节就开画,把上位的两个分类当成了下位四个模型的父节点。subagent 通读后指出:原文是并列的分类句,全文没有任何 is-a 措辞。若不纠正,整张骨架图的第 2 层就是错的——**层级关系是这类图最核心的断言,也最容易在只读局部时读反。**
## 阶段 2 · 视觉逻辑推导(不碰代码)
把结构翻译成**表达需求**,每个需求配一条**独立的视觉通道**。通道撞车,图就乱。
典型的四个需求与可用通道:
| 表达需求 | 可用通道 | 不要用 |
|---|---|---|
| 抽象 → 具体,数量逐层变多 | 横向分叉扇出、同心环周长、分层板 | 金字塔(它表达漏斗与转化,不是展开) |
| 同层内部再分类 | 分支归属、扇区归属、上下分区 | 颜色(颜色要留给跨图的类别) |
| 某些定义横跨若干层,长短不一 | 与层共用同一根轴的**长短条**,条的起止位置即跨度 | 一视同仁的并列方框 |
| 第三维度(谁用、在哪些过程里用、适用范围) | 罩在整体之外的横括号或外圈 | 混进层级里 |
产出一段文字 + 一张通道分配表,先给用户看。**这一步不写任何代码。**
## 阶段 3 · 方案并置
做 3–4 个方案放在同一页,每个配一句话标题、一段副标题、一张图、一行"长处 / 短处"。不要替用户选。
常用的四种形:
- **扇出树 + 跨度条**:层级是横轴,越往右分得越细;贯穿性定义是下方同轴的长短条。信息密度最高,最适合当主图。
- **同心环 + 辐条**:圆心最抽象,外圈周长天然表达"越具体越多"。造型强,但径向文字难排。
- **原文 figure 合一**:把文档里的几张图揉成一张,标明谁是谁的放大。忠实度最高,但层次感弱。
- **分层剖面(可拖动)**:每层一块板,贯穿定义是穿板的立柱。最直观,但信息密度最低。
## 阶段 4 · 融合与对齐
用户通常会选两个:一个讲结构清楚,一个讲关系准确。
**融合不是提炼,是同轴叠放。** 两者完整保留,上下放,重排列宽让它们共用同一根横轴。
**失败模式**:本流程首次执行时,我说"扇出树的第 3 列就是原文的图 3",于是只保留了"哪个模型对应哪个实体",把图 3 的嵌套结构、四要素框、模型钉在哪个框上全丢了。用户一眼看出"丢了很多细节"。**任何以"其实已经包含了"开头的融合理由,都要先回去数一遍对方有几个框。**
对齐的做法:
1. 定一组分界线 `X[]`。**它是泳道的分界线,不是"列的位置"**——虚线本身没有实体,两条线之间的区域才是实体
2. 把最宽的那块内容(通常是原文 figure 的主体)测出需要多宽,反过来调整 `X[]` 的间距
3. 竖向虚线从图一顶部画到**最后一块按列读的内容**为止——不要无脑画到画布底部
4. 三张图用同一组 `X[]`
**一切内容在泳道内居中,禁止写 `X[i] + 偏移`。** 用 `cx(i, w)` 拿左上角,`lane(i).cx` 拿中心。泳道头、连接线端点、成组的小条,全都一样——连接线端点贴的是**矩形的边缘**,不是虚线。详见 `references/visual-grammar.md` 的「泳道」一节,检查脚本会逐个量左右间距。
### 横向区块一律走 place(),列归属必须显式声明
**共同标尺是这套图的核心契约:任何元素的横向跨度都在向读者宣称"我属于这些列"。** 跨度与真实归属不符就是撒谎,和柱状图断轴是同一类错误。
`references/skeleton.html` 提供了 `place(cols, y, w, h, o)`,`cols` 不给会直接抛错,元素在泳道内自动居中:
| `cols` | 含义 | 自动做什么 |
|---|---|---|
| `3` | 占第 3 泳道 | 泳道内居中 |
| `[2,5]` | 跨第 2–5 泳道 | 跨度内居中 |
| `5` + `{only:true}` | 整块只属于第 5 泳道,但要更宽才放得下 | 画归属线回第 5 泳道 + 一句说明 |
| `null` | 不按列读:并列切面、全局词表、容器框 | 不透明底色盖住虚线 |
检查脚本会从竖虚线本身推断列位置(只认长度超过画布 30% 的长虚线,短的是刻度或连接线),扫出所有横跨 ≥1.2 列却没有 `data-cols` 的矩形,列为"待确认"。它不影响退出码,但每一条都要逐个看过。
> **为什么这条要做成机器检查,而不是写在文档里就算了**:第二次执行时,同一份产物里一条四步链横跨七列却只属于其中一列(错),另一处三张并列切面却用底色盖住了虚线并明说"不是一条线上的三段"(对)。同一个问题一处解决一处没有——**靠文档里的规则拦不住**。回头看第一次执行的产物也有两处未声明(跨度条的起止是手工算的、一个容器框横跨全宽却不按列读),只是当时没人发现。
## 阶段 5 · 视觉打磨
### 5.1 先做一次纯视觉 review
先把 `SKILL_DIR` 设为当前已加载的本 skill 目录;以下命令都相对该目录定位脚本,不假设全局安装位置。
改文案之前,先当作没读过内容,只看形:
```bash
python3 "$SKILL_DIR/scripts/render_check.py" out.html --scale 2 --slice --height 4800
```
脚本会做五件事:**自动测量页面真实高度**(不用手猜 `--height`)、`node --check` 语法、抓 Chrome console 的运行时错误、在页面里自检(文字溢出画布 / 同行重叠 / 字号低于 8.4px)、按真实高度截图并分块。**分块截图必须用 Read 工具逐张看**——脚本只能抓到机械问题,"这一块读起来别扭"只有眼睛能发现。本流程首次执行时这一步抓到四个问题:列虚线太淡看不见、标签被分叉线压住、扇出起点因线叠线形成黑楔子、左下角一大块空地没用。
看的时候重点查三件脚本查不出来的事:
1. **有没有"不按列读"的区块被虚线穿过**——见 `visual-grammar.md` 同名小节,这是第二次执行时唯一的真实错误。
2. **一张图的视觉分区有没有超过 5 块**。超了不一定要拆,但要检查是不是靠留白和小标题分开了;挤在一起就该拆或该合并同类项。
3. **某张图是不是八成以上一个颜色**。例子层常见(全是"过程"类),可以接受,但要在副标题里说一句。
> **不要自己猜窗口高度。** 第二次 review 时我手动传了 `--height 5200`,截出来 70% 是空白,差点把它误判成产物的 viewBox 设错了——实测 viewBox 只空余 15px,完全正确。现在脚本默认自动测量,不要再手传,除非你明确要看某个高度下的表现。
### 5.2 颜色
- **不超过三类**,一类内容一个颜色,全文统一。类别按"这个东西属于什么"分,不按"它重不重要"分。
- **黑灰只给结构**:层的分界线、箭头、跨度条、外部维度。
- **不要单一强调色**。给某一支单独上色,读者会理解成"这是全文最重要的一点",而你想表达的是整体逻辑。
- **细线上的颜色要够亮**。低明度低饱和的色画成 1px 线,和黑色分不出来。色块能认出是绿,不代表线也能。
### 5.3 去掉决策过程
页面上不留只有作者知道的编号:
| 不要 | 改成 |
|---|---|
| 方案 A、风格 B | 直接写这张图讲什么 |
| 图 2 = 把这一段展开 | 这一段的完整展开 · §7.1 |
| 上层是全貌(方案 A) | 上层是全貌:概念怎样一层层展开 |
**条款号保留**(§7.2 这种),它能回查原文,是可信度的一部分。
### 5.4 每次改动后验证
```bash
python3 "$SKILL_DIR/scripts/render_check.py" out.html --height 4800
```
**语法检查过不代表能跑。** 本流程首次执行时出过一次变量先用后定义,`node --check` 通过,但整张图画不出来——因为 `const` 的暂时性死区是运行时才触发的。脚本因此同时抓 console 错误。
脚本自身经过对抗测试:人造一个带重叠、溢出、6px 小字的页面,三类问题都能抓到;真实产物全绿。
## 什么该固化成规则,什么不该
每次执行完都会有新发现,但不是所有发现都该写进 skill。判断标准只有一条:**它是这套图型的固有契约,还是这份文档的特殊情况?**
| 该固化 | 不该固化 |
|---|---|
| 列归属必须声明——共同标尺是图型契约,任何文档都适用 | "生命周期适合当横轴"——那是某一份标准的结论,别的文档未必有生命周期 |
| 图的张数由 figure 之间有无主从关系决定——这是通用判据 | "要画三张切面并排"——那是某份文档的 figure 恰好互不相交 |
| 列线要用长度过滤识别——任何图都可能有装饰性短虚线 | "117 条术语画成 barcode"——那是一次形式创意,换份文档可能完全不适用 |
| 派 subagent 通读、figure 必须看图——这是方法 | "全文 0 个 shall"——那是某一份标准的事实 |
判断不了的时候问自己:**换一份完全不同的 PDF,这条还成立吗?** 不成立就别写进来,写进 `references/` 当案例可以,但不要写成规则。
规则宁可少而硬,不要多而软。多一条软规则,执行者就多一分"看过了但没照做"的空间。
## 阶段 6 · 例子层
用同一组列换成一个具体场景。例子要**自下而上读**:最底下是"这个场景里有什么",往上是"怎么评价它",最上面是"拿来做什么"。
每一行是一条可追溯的链:挂在哪个实体上 → 从哪来 → 用哪个标准概念 → 量什么 → 实际多少。
## 已经有一份产物了怎么办
同一份 PDF 第二次跑、或者接手别人生成的图时,**旧产物是最大的上下文污染源**。三条硬规则:
**一、骨架只从 `references/skeleton.html` 复制,绝不从任何已有 HTML 复制代码。**
旧产物看起来"现成能用",但它可能是旧版 skill 生成的,带着已经修掉的坏模式。真实案例:坐标系统从"虚线基准"改成"泳道制"之后,所有旧产物里满是 `X[i]+2` 这种写法——照抄一次,刚修好的 bug 立刻复发。
**二、先诊断,再决定重做还是改。** 不要默认"在它基础上改":
```bash
python3 "$SKILL_DIR/scripts/render_check.py" 旧产物.html
```
- 报了 **[泳道居中]** → 它是旧坐标系统生成的,**重做**,不要在上面补丁
- 只报 [列归属] 待确认,或零报 → 可以在上面改,但改之前仍要把结构探针的结论过一遍
**三、结构探针不喂旧结论。** subagent 只拿到 PDF 和六问模板,不要把旧产物、旧的层级划分、旧的横轴选择告诉它。那些结论可能本来就是错的,先入为主会让它只去印证而不是去读。
文件命名固定下来,避免覆盖和堆积:
```
<日期>-<文档简称>-triptych.html 最终产物
<日期>-<文档简称>-options.html 阶段 3 的方案并置页(中间产物,可删)
```
重做时把旧产物改名或移走,不要让它和新产物同名同目录——否则下次接手的人分不清哪份是对的。
## 交付物
```
<日期>-<文档简称>-triptych.html 单文件,无构建,双击可开
<日期>-<文档简称>-options.html 阶段 3 的方案并置页,评审完可删
```
HTML 骨架见 `references/skeleton.html`,视觉语法细则见 `references/visual-grammar.md`。
## 检查清单
交付前逐条过:
- [ ] 派过 subagent 通读全文,不是只读了目录和几节
- [ ] 原文的每张 figure 都用 Read 直接看过
- [ ] subagent 指出的易误读点,图上有体现(比如"全文规则均为 should")
- [ ] 三张图共用同一组列,竖虚线贯穿
- [ ] 颜色不超过三类,全文统一,黑灰只给结构;**没有单一强调色**
- [ ] 卡片四件套齐全(结论式标题 / 副标题说清图例 / 图 / 来源行)
- [ ] 没有"方案 A""图 2"这类只有作者知道的编号
- [ ] 条款号保留,能回查
- [ ] 做过一次纯视觉 review(2 倍截图分块看),且截图高度是脚本自动测的
- [ ] 所有元素用 `cx(i,w)` / `lane(i).cx` 定位,全文没有 `X[i] + 偏移`;检查脚本的「泳道居中」零报
- [ ] 横向区块都走了 `place()`,`cols` 逐个想清楚;检查脚本报的"待确认"逐条看过
- [ ] 图例只画一次,第二张起写"颜色含义与上图相同"
- [ ] `node --check` 过,且 Chrome console 无 uncaught
- [ ] 最小字号 ≥ 9px(中文),无文字重叠、无超出画布
- [ ] 数据来源行写明了哪些内容不来自这份 PDF
- [ ] 没有从任何已有产物复制代码,骨架来自 `references/skeleton.html`
Discussion
Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.
Posts are public.Sign in to post
No one has posted yet. Be the first.

