PPT Editor Dev
一句话:定位文件改一处,手动跑 5 步验证,同步文档。本项目零依赖、零测试,改完靠人验。
这个 Skill 做什么
帮人(或 agent)安全地改动 PPT Editor 项目:
输入:用户的修改需求(加主题 / 加版式 / 改字段识别 / 修 bug)
↓
定位:找对应的 JS 文件和函数
↓
改:editor.js / themes.js / layouts.js / index.html 之一
↓
验:手动跑 5 步(加载示例 A/B → 改字段 → 切主题 → 切版式 → 导出)
↓
同步:README.md 文件清单 + CHANGELOG.md 变更记录
何时触发
匹配以下任意提示时激活:
- "改编辑器"、"编辑器 bug"、"PPT Editor 出问题了"
- "加个新主题色板"、"加一套版式"
- "改字段扫描规则"、"Pass X 不对"
- "加键盘快捷键"、"加个图标"
- "导出 HTML 坏了"、"截图失败"
- "主题切换没生效"、"字段没扫到"
不适用
- 生成 PPT 内容 → 用
guizang-ppt-skill生成 deck HTML,本编辑器只读它 - 改 guizang 模板文件 → 只读引用,绝不动
template.html/themes*.md - 新建一个独立的 PPT 编辑器 → 本 skill 改现有项目,不适合 from-scratch
- 改已经废弃的样式 / 旧 demo → 别动
demo-deck-generated.html里的 WebGL 代码
工作流(4 阶段)
Phase 1 · 定位改动点(必做,0 token)
# 1. 读总览
Read D:\web\ppt-editor\README.md # 7KB,2 分钟理解
Read D:\web\ppt-editor\SKILL.md # 本文件,核心契约
# 2. 按任务类型定位文件
grep -n "FIELD_SEMANTIC\|FIELD_BLOCKLIST" editor.js # 字段相关
grep -n "STYLE_A\|STYLE_B" themes.js # 主题相关
grep -n "category\|svg:\|template" layouts.js # 版式相关
grep -n "addEventListener\|keydown" editor.js # 快捷键相关
定位表(改什么 → 改哪里):
| 任务 | 文件 | 锚点 |
|---|---|---|
| 加新主题色板 | themes.js | THEMES.styleA 或 styleB 加一项,每项必须含 6 个 --* 变量 |
| 加新版式 | layouts.js | Style A 或 Style B 区段加一项,必须填 category(cover/data/process/quote/feature) |
| 改字段识别规则 | editor.js | FIELD_BLOCKLIST 黑名单 或 4 个 Pass 之一 |
| 改风格检测 | editor.js | detectDeckStyle() 函数 |
| 改主题切换 UI | index.html | 顶栏 segment 按钮 + editor.js 的 setDeckStyle |
| 改导出清理逻辑 | editor.js | exportDeck() 末尾 |
| 加键盘快捷键 | editor.js | 顶栏 keydown 监听器 |
| 加图标 | index.html | <defs> 内 <symbol id="i-xxx" viewBox="0 0 24 24"> |
| 加示例 deck | demos.js | PPTEditorDemos.styleA 或 styleB 加 HTML 字符串 |
Phase 2 · 改代码(核心契约必读)
字段扫描四遍策略(editor.js)
Pass A: [data-text] 显式标记
Pass B: 黑名单之外的所有叶子文本节点(FIELD_BLOCKLIST 排除 chrome/foot 等)
Pass C: <img> + background-image
Pass D: 含 inline 节点(br/span/em/b/i)的语义标题块
Pass D 的核心:addCompositeField / writeCompositeField / collectTextSegments。段数必须对位(多段忽略、缺段截断)。
主题切换不重写 CSS
documentElement.style.setProperty('--ink', theme.vars['--ink']);
只改 :root 变量,不写死 hex。模板硬编码 rgb() 是已知 bug 来源,模板侧用 rgba(var(--ink-rgb), .5)。
风格检测锚点
:root 含 --ink / --paper → Style A(自动切墨水经典)
:root 含 --accent / --grey-1 → Style B(自动切克莱因蓝)
手动切换走顶栏 Style A / Style B segment,只换色板列表,不动 deck 本身。
版式切换的 6 档兜底
insertIntoSlide(slide, html)
// 1. 替换 chrome 内部
// 2. 替换 foot 内部
// 3. 替换 main wrapper
// 4. 替换 kicker
// 5. 替换 grid/row/pipeline
// 6. appendChild 兜底
老模板(无 chrome/foot)也能正确插入。MAIN_WRAPPER_SELECTOR 是抽出的常量。
Phase 3 · 手动 5 步验证(必做)
本项目无自动化测试套件。改完必须手动跑完这 5 步:
- 加载示例 A → 改一处字 → 200ms 内右侧同步
- 切到 Style B → 加载示例 B → 改字段 → 同步
- 切版式 → body 替换 + 字段保留(版式值迁移)
- 切主题(5 + 4 各试一次) → 色板变量生效
- 导出 HTML → 双击打开独立可看
5 步全过才算改好。任一步异常 → 回 Phase 2。
Phase 4 · 同步文档(必做)
# 文件清单同步(如有新增/删除文件)
Edit D:\web\ppt-editor\README.md # 文件清单 section
# 变更记录
Edit D:\web\ppt-editor\CHANGELOG.md # 加一条 ## 2026-MM-DD · 简述
CHANGELOG 条目格式参考已有:
## 2026-07-09 · 删除「静态预览」功能
### 原因
- ...
### 改动
**代码层**
- `editor.js`:删除 ...
- `index.html`:删除 ...
**文档层**
- `README.md`:删除 ...
工具决策矩阵
| 工具 | 主要价值 | 该用 | 不该用 |
|---|---|---|---|
| Read | 代码 ground truth | 所有改动前先读对应文件 | — |
| Grep | 快速定位函数 / 类 / 锚点 | 不知道函数名时按关键词搜 | 已经知道改哪行时 |
| Glob | 找文件 | 列出 *.js / *.html 时 | 单文件已知路径 |
| Bash | 跑 node / chrome / python | node -c editor.js 语法检查;起 python -m http.server | — |
| Chrome headless | 浏览器渲染验证 | 双击 index.html 后看效果 | 自动化测试(本项目无) |
| AskUserQuestion | 消除歧义 | 风格选择 / 改 vs 不改 / 字段语义边界 | 实现细节(自行判断) |
| Memory | 跨会话保留 | 项目级元信息(如本项目零依赖) | 单次任务临时状态 |
项目结构(实存文件)
D:\web\ppt-editor\
├── index.html 编辑器主入口(1420 行 · 47KB)
├── editor.js 主逻辑(2050 行 · 79KB)
├── themes.js 9 套主题色板(Style A 5 + Style B 4)
├── layouts.js 10 套版式(Style A 6 + Style B 4)
├── demos.js 内嵌示例 deck HTML(file:// 协议兼容)
├── deck-stage.js <deck-stage> 自定义元素(621 行)
├── demo-deck.html Style A 杂志风 4 页示例
├── demo-deck-swiss.html Style B 瑞士风 3 页示例
├── demo-deck-generated.html 项目自展示 deck(1194 行)
├── assets/
│ └── motion.min.js Motion One 离线版(demo 用)
├── CHANGELOG.md 变更记录
├── README.md 给用户的项目说明
└── SKILL.md 本文件
输出规范
- 不创建额外子目录:项目根目录除
assets/外不要建cover/music/previews/tests/(其他会话临时产物,不属于本项目) - 不写 hex 色:模板/编辑器内颜色必须走 CSS 变量
- 不引入 npm 包:保持零依赖
- 不写
%TEMP%文件:如需临时文件放工作目录下 - 每次改动同步
CHANGELOG.md+ 必要时README.md文件清单
反模式(每条都来自实战)
- 跳过 Phase 1 直接改代码 —— 不知道现有结构就改,新引入的 bug 比修的多
- 改完不跑 5 步验证 —— 本项目无自动化测试,肉眼验证是唯一防线
- 改了代码不改 CHANGELOG —— 下次接手者无法理解历史
- 引入 npm 包 / 框架 —— 破坏"零依赖、双击即用"核心承诺
- 在 themes.js 之外写死颜色 hex —— 主题切换会失效
- 改 demos.js 的内嵌 HTML 但不更新 README 入口表 —— 用户找不到新示例
- 改
__setLowPowerMode相关代码 —— 2026-07-09 已删除静态预览功能,相关逻辑已下线 - 修改
guizang-ppt-skill下的文件 —— 本项目只读引用它,不动它 - 加新主题只改 CSS 变量不更新 README 主题色板列表 —— 用户看不到新主题存在
- 修改 PASS D 复合字段的段数协议 ——
writeCompositeField按段数对位是用户输入约定,改了会让老 deck 改字崩 - 修改 FIELD_BLOCKLIST 不重读 demo-deck.html —— 黑名单改严会让 demo 字段消失
- 用 VL 看代码对不对 —— 几何/对齐判断 VL 强,代码逻辑判断应该 Read + Grep
- 覆盖 demo-deck.html / demo-deck-swiss.html 前不问 —— demo 是用户验证入口,覆盖错了 demo 也坏
决策树
用户提需求
│
├─ 需求类型?
│ ├─ 加主题色板 → themes.js STYLE_A/STYLE_B 加项 → README 同步
│ ├─ 加版式 → layouts.js 加项 → README 同步
│ ├─ 改字段识别 → editor.js FIELD_BLOCKLIST / Pass X → 跑示例 A/B 验证
│ ├─ 改风格检测 → editor.js detectDeckStyle() → 跑示例 A/B 验证
│ ├─ 改快捷键/UI → editor.js + index.html → 手动触发键验证
│ └─ 修 bug → 读源码定位 → 改 → 5 步验证
│
├─ 5 步手动验证
│ ├─ 失败 → 回 Phase 2 改
│ └─ 全过 → 同步 CHANGELOG.md(必要时 README.md)
│
└─ 交付
关键代码速查(grep 锚点)
# 字段扫描
editor.js: FIELD_BLOCKLIST, FIELD_SEMANTIC_CLASSES,
scanFields(), addCompositeField(), writeCompositeField()
# 主题
themes.js: THEMES.styleA, THEMES.styleB
editor.js: applyTheme(), captureCurrentTheme(), patchStyleBlockForExport()
# 风格检测
editor.js: detectDeckStyle(), setDeckStyle()
# 版式
layouts.js: SVG(`...`), category: 'cover' | 'data' | 'process' | 'quote' | 'feature'
editor.js: insertIntoSlide(), applyLayoutToCurrentSlide(), MAIN_WRAPPER_SELECTOR
# 导出 / 截图
editor.js: exportDeck(), screenshotCurrentSlide() (html2canvas@1.4.1)
# 历史 / 自动保存
editor.js: saveHistory(), undo(), redo(), 800ms coalesce
localStorage debounce 3s
当前版本:v0.4 · V1.0+ 特性集 最后更新:2026-07-17
Scan to join WeChat group