Back to skills
extension
Category: Development & EngineeringNo API key required

ppt-editor

PPT 可视化编辑器

personAuthor: UnspokenSheephubModelScope

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.styleAstyleB 加一项,每项必须含 6 个 --* 变量 | | 加新版式 | layouts.js | Style AStyle B 区段加一项,必须填 category(cover/data/process/quote/feature) | | 改字段识别规则 | editor.js | FIELD_BLOCKLIST 黑名单 或 4 个 Pass 之一 | | 改风格检测 | editor.js | detectDeckStyle() 函数 | | 改主题切换 UI | index.html | 顶栏 segment 按钮 + editor.jssetDeckStyle | | 改导出清理逻辑 | editor.js | exportDeck() 末尾 | | 加键盘快捷键 | editor.js | 顶栏 keydown 监听器 | | 加图标 | index.html | <defs><symbol id="i-xxx" viewBox="0 0 24 24"> | | 加示例 deck | demos.js | PPTEditorDemos.styleAstyleB 加 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 步:

  1. 加载示例 A → 改一处字 → 200ms 内右侧同步
  2. 切到 Style B → 加载示例 B → 改字段 → 同步
  3. 切版式 → body 替换 + 字段保留(版式值迁移)
  4. 切主题(5 + 4 各试一次) → 色板变量生效
  5. 导出 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 文件清单

反模式(每条都来自实战)

  1. 跳过 Phase 1 直接改代码 —— 不知道现有结构就改,新引入的 bug 比修的多
  2. 改完不跑 5 步验证 —— 本项目无自动化测试,肉眼验证是唯一防线
  3. 改了代码不改 CHANGELOG —— 下次接手者无法理解历史
  4. 引入 npm 包 / 框架 —— 破坏"零依赖、双击即用"核心承诺
  5. 在 themes.js 之外写死颜色 hex —— 主题切换会失效
  6. 改 demos.js 的内嵌 HTML 但不更新 README 入口表 —— 用户找不到新示例
  7. __setLowPowerMode 相关代码 —— 2026-07-09 已删除静态预览功能,相关逻辑已下线
  8. 修改 guizang-ppt-skill 下的文件 —— 本项目只读引用它,不动它
  9. 加新主题只改 CSS 变量不更新 README 主题色板列表 —— 用户看不到新主题存在
  10. 修改 PASS D 复合字段的段数协议 —— writeCompositeField 按段数对位是用户输入约定,改了会让老 deck 改字崩
  11. 修改 FIELD_BLOCKLIST 不重读 demo-deck.html —— 黑名单改严会让 demo 字段消失
  12. 用 VL 看代码对不对 —— 几何/对齐判断 VL 强,代码逻辑判断应该 Read + Grep
  13. 覆盖 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