dsh-courseware 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -0
  3. package/cordis.patch.yml +9 -0
  4. package/engine/pptxgen/__init__.py +8 -0
  5. package/engine/pptxgen/__main__.py +4 -0
  6. package/engine/pptxgen/builtin_template.py +218 -0
  7. package/engine/pptxgen/cli.py +575 -0
  8. package/engine/pptxgen/examples.py +290 -0
  9. package/engine/pptxgen/imagegen.py +564 -0
  10. package/engine/pptxgen/layoutmap.py +211 -0
  11. package/engine/pptxgen/patterns.py +106 -0
  12. package/engine/pptxgen/preview.py +126 -0
  13. package/engine/pptxgen/profile.py +456 -0
  14. package/engine/pptxgen/render.py +1673 -0
  15. package/engine/pptxgen/review.py +184 -0
  16. package/engine/pptxgen/schemacheck.py +122 -0
  17. package/engine/pptxgen/schemas/XAdES.xsd +466 -0
  18. package/engine/pptxgen/schemas/XAdESv141.xsd +15 -0
  19. package/engine/pptxgen/schemas/chartEx.xsd +838 -0
  20. package/engine/pptxgen/schemas/dml-chart.xsd +1499 -0
  21. package/engine/pptxgen/schemas/dml-chartDrawing.xsd +146 -0
  22. package/engine/pptxgen/schemas/dml-diagram.xsd +1085 -0
  23. package/engine/pptxgen/schemas/dml-drawing.xsd +63 -0
  24. package/engine/pptxgen/schemas/dml-lockedCanvas.xsd +11 -0
  25. package/engine/pptxgen/schemas/dml-main.xsd +3081 -0
  26. package/engine/pptxgen/schemas/dml-picture.xsd +23 -0
  27. package/engine/pptxgen/schemas/dml-spreadsheetDrawing.xsd +185 -0
  28. package/engine/pptxgen/schemas/dml-wordprocessingDrawing.xsd +287 -0
  29. package/engine/pptxgen/schemas/drawing-chart2012.xsd +129 -0
  30. package/engine/pptxgen/schemas/markup-compatibility.xsd +95 -0
  31. package/engine/pptxgen/schemas/opc-digSig.xsd +49 -0
  32. package/engine/pptxgen/schemas/opc-relationships.xsd +33 -0
  33. package/engine/pptxgen/schemas/pml.xsd +1676 -0
  34. package/engine/pptxgen/schemas/shared-additionalCharacteristics.xsd +28 -0
  35. package/engine/pptxgen/schemas/shared-bibliography.xsd +144 -0
  36. package/engine/pptxgen/schemas/shared-commonSimpleTypes.xsd +172 -0
  37. package/engine/pptxgen/schemas/shared-customXmlDataProperties.xsd +25 -0
  38. package/engine/pptxgen/schemas/shared-customXmlSchemaProperties.xsd +18 -0
  39. package/engine/pptxgen/schemas/shared-documentPropertiesCustom.xsd +59 -0
  40. package/engine/pptxgen/schemas/shared-documentPropertiesExtended.xsd +56 -0
  41. package/engine/pptxgen/schemas/shared-documentPropertiesVariantTypes.xsd +195 -0
  42. package/engine/pptxgen/schemas/shared-math.xsd +582 -0
  43. package/engine/pptxgen/schemas/shared-relationshipReference.xsd +25 -0
  44. package/engine/pptxgen/schemas/signatureInfo.xsd +103 -0
  45. package/engine/pptxgen/schemas/sml.xsd +4439 -0
  46. package/engine/pptxgen/schemas/visio.xsd +829 -0
  47. package/engine/pptxgen/schemas/vml-main.xsd +570 -0
  48. package/engine/pptxgen/schemas/vml-officeDrawing.xsd +509 -0
  49. package/engine/pptxgen/schemas/vml-presentationDrawing.xsd +12 -0
  50. package/engine/pptxgen/schemas/vml-spreadsheetDrawing.xsd +108 -0
  51. package/engine/pptxgen/schemas/vml-wordprocessingDrawing.xsd +96 -0
  52. package/engine/pptxgen/schemas/vmlDrawing.xsd +36 -0
  53. package/engine/pptxgen/schemas/wml.xsd +3643 -0
  54. package/engine/pptxgen/schemas/word12.xsd +66 -0
  55. package/engine/pptxgen/schemas/xlThreadedComments.xsd +59 -0
  56. package/engine/pptxgen/schemas/xlThreadedComments2.xsd +22 -0
  57. package/engine/pptxgen/schemas/xmldsig-core-schema.xsd +318 -0
  58. package/engine/pptxgen/shapes.py +417 -0
  59. package/engine/pptxgen/spec.py +529 -0
  60. package/engine/pptxgen/template.py +834 -0
  61. package/engine/pptxgen/util.py +218 -0
  62. package/engine/pptxgen/xmlutil.py +298 -0
  63. package/engine/pptxgen.sh +7 -0
  64. package/engine/requirements.txt +9 -0
  65. package/lib/index.js +186 -0
  66. package/package.json +34 -0
  67. package/skills/courseware/SKILL.md +130 -0
  68. package/skills/courseware/references/content-polish.md +121 -0
  69. package/skills/courseware/references/deck-spec.md +155 -0
  70. package/skills/courseware/references/design-review.md +121 -0
  71. package/skills/courseware/references/image-backends.md +94 -0
  72. package/skills/courseware/references/quality-gates.md +71 -0
  73. package/skills/courseware/references/roadmap.md +55 -0
  74. package/skills/courseware/references/template-fidelity.md +100 -0
  75. package/skills/courseware/workflows/generate.md +172 -0
  76. package/skills/courseware/workflows/quick.md +41 -0
  77. package/skills/courseware/workflows/revise.md +40 -0
  78. package/skills/courseware/workflows/routing.md +49 -0
  79. package/skills/courseware/workflows/stages/generate-images.md +74 -0
  80. package/skills/courseware/workflows/template-intake.md +112 -0
@@ -0,0 +1,121 @@
1
+ # 设计审查(Design Review)—— 把"好看"变成可检查的规则
2
+
3
+ 规则借鉴自腾讯 PPTX 技能的设计宪法(`story-principle.md` / `design-principle.md` /
4
+ `designs/design-principle.academic.md`),按**中小学课件**的场景下调阈值。
5
+
6
+ 原技能靠"提示词里的 checklist"约束模型;我们把它**落成命令**,每次交付前机器检查:
7
+
8
+ ```bash
9
+ "$ENGINE_HOME/pptxgen.sh" review "decks/xxx.yaml" --pptx "out/xxx.pptx"
10
+ ```
11
+
12
+ - 不带 `--pptx`:只查大纲层(版式多样性、信息密度、润色落实)
13
+ - 带 `--pptx`:追加成品层检查(视觉锚点:字号梯度与配图面积)
14
+ - 有「错误」→ 退出码 1;只有「建议」→ 退出码 0
15
+
16
+ ---
17
+
18
+ ## 一、借鉴过来的五条宪法(已适配课件场景)
19
+
20
+ ### 1. 版式多样性(原:"相邻页面必须用不同版式")
21
+
22
+ - **相邻两页不得同为 `bullets` 或 `cards`**(steps / flow / compare / levels / timeline 之间允许相邻,因为形态差别明显)
23
+ - 单一骨架占比 > 55% → 全篇偏单调
24
+ - `cards` 占比 > 45% → 卡片刷屏,要求穿插其它骨架
25
+
26
+ > 这条直接对应"每页排版都一样"这类问题——现在会在交付前被拦下来。
27
+
28
+ ### 2. 信息密度下限(原:内容页 ≥180 字、卡片组每卡 ≥100 字)
29
+
30
+ 中小学课件下调为:
31
+
32
+ | 页型 | 正文字数下限 |
33
+ |---|---|
34
+ | 知识点/例题 | 60 |
35
+ | 目标页 | 60 |
36
+ | 练习/小结 | 40 |
37
+ | 作业 | 30 |
38
+ | 封面/结束页 | 8 |
39
+
40
+ 低于下限 → 「建议:内容偏薄」。**空 ≠ 极简**,稀薄的页面必须补内容或合并。
41
+
42
+ ### 3. 视觉锚点(原:"每页至少一个超大字号/超大图/超大色块")
43
+
44
+ 每页至少要有一个明显压过正文的元素,判定(满足其一即可):
45
+
46
+ - 最大字号 ≥ **页面正文字号**(该页出现次数最多的字号)× 1.35
47
+ - 配图面积 ≥ 幻灯片面积 12%
48
+ - 整页只有一个字号时,该字号 ≥ 32pt
49
+
50
+ 都不满足 → 「建议:缺少视觉锚点」。**禁止所有元素趋近中间大小。**
51
+
52
+ > 基准取"正文(最常见)字号"而不是"次大字号":封面只有标题+副标题时,
53
+ > 拿次大字号比会把 44pt 标题误判成没有锚点。
54
+
55
+ ### 3.5 统一字号阶梯(引擎行为,2026-09 起)
56
+
57
+ 模板样张常是"一页没几条字"的大字号(本模板正文 28pt)。一旦页面里有卡片、
58
+ 步骤、配图,同字号会撑爆版面,逼引擎逐页自动缩字 —— 结果是**页与页字号忽大忽小**。
59
+
60
+ 因此正文族字号统一从"模板学到的正文"等比推导,**全篇同一套阶梯**:
61
+
62
+ | 档位 | 相对正文 | 本模板(正文 20.2pt) |
63
+ |---|---|---|
64
+ | 页面标题(标题条) | 模板学到 | 28pt |
65
+ | 块标题 / 卡片标题 | ×1.08 | 21.8pt |
66
+ | 正文要点(bullets) | ×1.00 | 20.2pt |
67
+ | 卡片条目 / 步骤说明 | ×0.88 | 17.7pt |
68
+ | 导语 | ×0.75 | 15.1pt |
69
+ | 图注 / 页码 | ×0.55 | 11.1pt |
70
+ | 核心问题/结论 | ×1.35 | 27.3pt |
71
+
72
+ 换模板时整族一起走(以该模板学到的正文为基准),并有上下限兜底
73
+ (正文 13–22pt、图注 9–13pt 等),避免小字号模板被压到看不清。
74
+
75
+ ### 4. 超长列表必须分块(原:"流程/步骤禁用 N 卡片横排""内容类型→最佳版式")
76
+
77
+ 一级要点 ≥ 5 条还挂在 `bullets` 上 → 「建议分块」。
78
+ 内容形态与骨架的对应关系(`pptxgen/patterns.py` 的 `CONTENT_MATCH`):
79
+
80
+ | 内容形态 | 骨架 |
81
+ |---|---|
82
+ | 流程 / 环节 | `flow` |
83
+ | 有序步骤 | `steps` |
84
+ | 并列要点 | `cards` |
85
+ | 分级 / 强弱梯度 | `levels` |
86
+ | 两者对照 | `compare` |
87
+ | 先后 / 因果 | `timeline` |
88
+ | 核心问题 / 结论 | `callout` |
89
+ | 一般叙述 | `bullets` |
90
+
91
+ ### 5. 润色落实(原:`anti_pattern` 逐页显式声明)
92
+
93
+ - 内容页整页没有 `**关键词**` 高亮 → 「建议」
94
+ - 有配图但没有 `image_caption` → 「建议」
95
+
96
+ ---
97
+
98
+ ## 二、没有照搬的部分(以及为什么)
99
+
100
+ | 原技能的做法 | 我们的取舍 |
101
+ |---|---|
102
+ | `hero / supporting / transition` 页面角色 + 20–30% 配额 + 节奏曲线 | **未强制**:中小学课件节奏由教学环节决定(导入→概念→练习→小结),硬套 20–30% hero 会打乱教学结构;视觉起伏改由"视觉锚点 + 版式多样性"来保证 |
103
+ | 非对称版式 ≥ 40%、`N卡片横排` 全篇 ≤ 2 页 | **未强制**:我们的骨架全部在模板学到的内容区内排版,对称/非对称由模板决定,不该由内容层翻转 |
104
+ | 强调色面积 ≤ 10%、主色 ≤ 60% 等面积配额 | **未强制**:颜色全部来自模板(引擎不引入野色),面积比例改由"视觉锚点 + 配图占比"间接约束 |
105
+ | 目录 ↔ 章节扉页一一对应 | **未采用**:课件一般不做"目录 N 章 → N 个扉页"的强契约 |
106
+ | 数据必须落点(数字后补判断) | **已写入** `content-polish.md`(教学场景改为"讲清一个道理/结论") |
107
+
108
+ ---
109
+
110
+ ## 三、与原技能的分工差异
111
+
112
+ | 能力 | 腾讯技能 | 我们 |
113
+ |---|---|---|
114
+ | 页面 DSL | SlideDSL(`.slide` 文件 + `slidep` 渲染器) | YAML 课件规格 + `pptxgen` 引擎 |
115
+ | 设计约束 | 提示词内的 checklist(靠模型自觉) | **命令行机器检查**(`review`) |
116
+ | 版式来源 | 自由版面 + 组件库 | **从用户模板学到的骨架**(保真优先) |
117
+ | 配图 | ImageGen + SVG 自由版面 | AI 生图(无 SVG 层) |
118
+ | 结构产物 | STORY.md + DESIGN.md + slides/ | 单个 `decks/xxx.yaml` |
119
+
120
+ **结论**:他们的"设计宪法"值得抄,他们的"自由版面"我们抄不了也不该抄——
121
+ 我们的卖点是**严格贴合用户模板**。所以只把可检查的约束吸收进来。
@@ -0,0 +1,94 @@
1
+ # 参考:图像后端
2
+
3
+ ## 配置优先级
4
+
5
+ 环境变量 > 课件 `options.images` > 配置文件(`./.pptxgen.yaml` 或 `~/.pptxgen/config.yaml`)
6
+
7
+ 生成配置文件:
8
+
9
+ ```bash
10
+ "$ENGINE_HOME/pptxgen.sh" images --init-config .pptxgen.yaml
11
+ ```
12
+
13
+ ```yaml
14
+ images:
15
+ backend: openai-compatible
16
+ base_url: https://your-relay.example.com/v1
17
+ model: your-image-model
18
+ api_key: sk-xxxx
19
+ size: "1024x1024"
20
+ cache_dir: ../out/images
21
+ style: >
22
+ 儿童科普插画风格,扁平化矢量插画,明亮清爽的配色,构图简洁,主体突出,
23
+ 背景干净,画面中不要出现任何文字、字母或数字
24
+ ```
25
+
26
+ `.pptxgen.yaml` 已在 `.gitignore` 里,不会外泄。
27
+
28
+ ## 内置后端
29
+
30
+ | backend | 说明 | key 环境变量 | 默认模型 |
31
+ |---|---|---|---|
32
+ | `openai-compatible` | **任意 OpenAI 协议中转**(填 base_url + model) | `PPTXGEN_IMAGE_API_KEY` | 自填 |
33
+ | `openai` | OpenAI | `OPENAI_API_KEY` | `gpt-image-1` |
34
+ | `qwen` | 阿里通义 / 百炼 | `DASHSCOPE_API_KEY` / `QWEN_API_KEY` | `qwen-image-2.0-pro` |
35
+ | `volcengine` | 火山引擎豆包 Seedream | `ARK_API_KEY` | `doubao-seedream-4-5-251128` |
36
+ | `zhipu` | 智谱 GLM | `ZHIPU_API_KEY` | `glm-image` |
37
+ | `siliconflow` | 硅基流动 | `SILICONFLOW_API_KEY` | `Qwen/Qwen-Image` |
38
+ | `modelscope` | 魔搭 | `MODELSCOPE_API_KEY` | `Qwen/Qwen-Image` |
39
+ | `gemini` | Google Gemini | `GEMINI_API_KEY` | `gemini-3.1-flash-image` |
40
+ | `openrouter` | OpenRouter | `OPENROUTER_API_KEY` | `google/gemini-3.1-flash-image` |
41
+ | `minimax` | MiniMax | `MINIMAX_API_KEY` | `image-01` |
42
+ | `mock` | **本地占位图,不联网不花钱** | — | `placeholder` |
43
+
44
+ 切换后端:
45
+
46
+ ```bash
47
+ "$ENGINE_HOME/pptxgen.sh" images "decks/xxx.yaml" --backend volcengine
48
+ # 或
49
+ export PPTXGEN_IMAGE_BACKEND=volcengine
50
+ ```
51
+
52
+ ## 尺寸
53
+
54
+ | 版位 | 建议尺寸 | 理由 |
55
+ |---|---|---|
56
+ | `image_side: right`(默认) | `1024x1024` | 图片栏约 4.1×5.4in,正方形图按比例缩放后约 4.1×4.1,留少量留白 |
57
+ | `image_side: top` / `bottom` | `1536x1024` 或更宽 | 上下布局是宽幅栏位 |
58
+ | 全屏背景图 | 与画布同比例(16:9 → `1536x864`) | 避免裁切 |
59
+
60
+ 图片按比例缩放居中,**不裁切**。尺寸不对只会浪费空间,不会变形。
61
+
62
+ ## 成本控制
63
+
64
+ | 手段 | 作用 |
65
+ |---|---|
66
+ | `--dry-run` | 列出清单,不发请求 |
67
+ | `--limit N` | 只生成前 N 张 |
68
+ | prompt 哈希缓存 | 同 prompt 重跑不计费 |
69
+ | `--force` | 仅在你确实要重做时才用 |
70
+
71
+ **推荐流程**:`--dry-run` 看清单 → `--limit 2` 验风格 → 全量。
72
+
73
+ ## 全局风格 style
74
+
75
+ `style` 会拼在每个 `image_prompt` 后面。课件统一画风靠它,**不要每页重复写风格词**。
76
+
77
+ 中小学课件的默认风格已内置为儿童科普插画风。要改整体画风就改这一处:
78
+
79
+ ```yaml
80
+ style: 水彩绘本风格,柔和色调,纸张质感,画面中不要出现任何文字
81
+ ```
82
+
83
+ ## 与 ppt-master 的差异
84
+
85
+ | | ppt-master | courseware |
86
+ |---|---|---|
87
+ | 后端数 | 14 | 11(覆盖常用) |
88
+ | 抽象方式 | 注册表 + importlib + 鸭子类型 | 数据表 `BACKENDS` + 统一 `_request` 分发 |
89
+ | 接口契约 | 无 Protocol/ABC,靠约定 | 每种 `kind` 一个明确方法,缺 key 显式报错 |
90
+ | 缓存 | **无** | 按 prompt 哈希缓存 |
91
+ | 图片搜索 | ✅ 4 个源 + 许可合规 | ❌ 暂未实现 |
92
+ | 许可合规 | ✅ 未知许可直接拒收 | ❌ 暂未实现 |
93
+
94
+ **图片搜索与许可合规是我们缺的**,见 SKILL.md 的已知短板记录。
@@ -0,0 +1,71 @@
1
+ # 参考:质量闭闸
2
+
3
+ 交付前必须跑完,并把**原始输出**给用户。这是可证伪的证据,不是自我评估。
4
+
5
+ ```bash
6
+ "$ENGINE_HOME/pptxgen.sh" check "out/xxx.pptx" --render
7
+ ```
8
+
9
+ ## 检查项
10
+
11
+ | 类别 | 说明 | 判定 |
12
+ |---|---|---|
13
+ | 空白页 | 整页无文字无图片 | 必失败 |
14
+ | 文字溢出 | 估算高度超过文本框 | 必失败 |
15
+ | 文字越界 | 文本框超出画布 | 必失败 |
16
+ | **文字重叠** | 真实渲染后两个文本块重叠面积 > 25% | 必失败 |
17
+
18
+ `--render` 会调用 LibreOffice 真实渲染成 PDF,再比对各文本块的实际包围盒。
19
+ **只有它报 0 问题才算闭闸。**
20
+
21
+ ## 修复闭环:读全量 → 一次合并修 → 单次复跑
22
+
23
+ 不要「改一条、跑一次」。`check` 一次会报出所有问题,**一次读完**,
24
+ 把修改合并成一批,然后**只复跑一次**。
25
+
26
+ 反复单条试错会浪费大量时间,而且容易按下葫芦浮起瓢。
27
+
28
+ ## 常见问题的修法
29
+
30
+ | 报告 | 根因 | 修法(按优先级) |
31
+ |---|---|---|
32
+ | 文本可能溢出 | 该页内容太多 | ① 拆成两页 ② 精简要点文字 ③ 调低 `fit_shrink_floor` |
33
+ | 文字互相重叠 | 副标题/正文版位冲突 | 报告为引擎缺陷,修 `pptxgen/render.py` 并补回归测试 |
34
+ | 文字跑出页面 | 占位符超出画布 | 通常是模板问题,`inspect` 确认后报告用户 |
35
+ | 文本框超出边界 | 版式几何异常 | 同上 |
36
+ | 空白页 | 页型没渲染出内容 | 检查该页 `type` 与字段是否匹配 |
37
+
38
+ ## 版面质量的经验判据
39
+
40
+ `check` 查不出"不好看",但有几条可量化的参考:
41
+
42
+ | 指标 | 健康区间 | 怎么测 |
43
+ |---|---|---|
44
+ | 内容区墨迹占比 | 40%–70% | 见下方脚本 |
45
+ | 正文实际字号 | ≥ 18pt | 从渲染 PDF 提 span 字号 |
46
+ | 标题条行数 | = 1 行 | 渲染后看标题区文字行数 |
47
+ | 一页要点条数 | 3–6 条 | 人工看 |
48
+
49
+ 墨迹占比快速测量:
50
+
51
+ ```python
52
+ from PIL import Image
53
+ im = Image.open("out/preview/xxx_05.png").convert("RGB")
54
+ W, H = im.size
55
+ crop = im.crop((int(W*0.15), int(H*0.22), int(W*0.85), int(H*0.88)))
56
+ px = crop.load(); cw, ch = crop.size
57
+ ink = sum(1 for y in range(0, ch, 2) for x in range(0, cw, 2)
58
+ if not all(v > 242 for v in px[x, y]))
59
+ print(f"墨迹 {ink / ((cw//2)*(ch//2)) * 100:.1f}%")
60
+ ```
61
+
62
+ **参考值**:模板自带页面通常 60%+,纯文字页约 25%,**加配图后约 43%**。
63
+ 低于 15% 说明页面太空,考虑加配图或减少页数。
64
+
65
+ ## 无障碍与对比度(ppt-master 缺的能力)
66
+
67
+ 工具会从模板的背景图估算平均亮度并自动选深/浅文字色。人工复核:
68
+
69
+ - 深色背景页的文字应为浅色(`inspect` 里母版背景 `亮度 < 0.45` 即深色)
70
+ - 正文与背景对比度建议 ≥ 4.5:1(WCAG AA)
71
+ - 模块标签压在装饰色块上时,要确认对比度足够
@@ -0,0 +1,55 @@
1
+ # 能力对照与路线图
2
+
3
+ 诚实记录:我们比 ppt-master 强在哪、弱在哪、还没吸收什么。
4
+
5
+ ## 我们更强的地方
6
+
7
+ | 能力 | courseware | ppt-master | 证据 |
8
+ |---|---|---|---|
9
+ | **正文真实字体字号** | ✅ 从样张文字 run 加权投票 | ❌ 只读主题拉丁字体 | 对同一模板:我们学到 `微软雅黑 28pt`;它 manifest 里 `微软雅黑` 出现 **0 次** |
10
+ | 代码规模 | ~5,000 行 | 156,622 行 | — |
11
+ | 测试 | 23 项端到端回归 | **0 个**(240 个 .py 中 pytest import = 0) | — |
12
+ | 安装体积 | 几 MB | 1.9 GB | 其中模板 253MB、git 779MB |
13
+ | 单文件最大 | ~1000 行 | 7791 行(`checker.py`) | `builder.py` 里 `create_pptx_with_native_svg` **1475 行 / 48 参数** |
14
+ | 配图缓存 | ✅ prompt 哈希 | ❌ 无 | — |
15
+ | 文字重叠检测 | ✅ 真实渲染后比对包围盒 | ❌ 无 | 它只检查"模块 vs 画布"溢出 |
16
+ | 4:3 支持 | ✅ 含占位符越界纠正 | 未明确 | — |
17
+ | 规则单一来源 | ✅ 每条规则一处 | ❌ 同一规则散落 3–5 处 | EMF 规则在 generate 5 处、quick 3 处 |
18
+
19
+ ## 我们更弱的地方(尚未吸收)
20
+
21
+ | 能力 | 差距 | 影响 | 优先级 |
22
+ |---|---|---|---|
23
+ | **SVG → 原生 DrawingML** | 它有 47,210 行自研转换器,能把手写 SVG 变成原生可编辑对象 | 我们的版面由固定模板驱动,**设计自由度受限**;无法做任意自由布局 | 高(但成本极高) |
24
+ | **图片搜索 + 许可合规** | 它 4 个图源(pexels/pixabay/openverse/wikimedia),未知许可直接拒收 | 我们只有 AI 生成,无版权安全的现成图来源 | 中 |
25
+ | **原生图表/表格/公式** | 它能把图表变成带内嵌 xlsx 的 `chartSpace`,表格变 `<a:tbl>`,LaTeX 变 OMML | 我们的表格/图表只能作为图片或纯文字 | 中 |
26
+ | **动画 / 转场 / 旁白 / MP4** | 它有 `pptx_animations`(3965 行)、`narration_sync`(2252 行) | 我们只做静态页 | 低(中小学课件用得少) |
27
+ | **模板蒸馏成 brand/style/layout** | 它能把参考稿反推成可复用品牌库 | 我们只能"用某一个模板",不能跨模板复用风格 | 中 |
28
+ | **对比度/无障碍检查** | —— | **它也没有**,双方都缺 | 中 |
29
+
30
+ ## 明确不做的
31
+
32
+ | 能力 | 为什么不做 |
33
+ |---|---|
34
+ | SmartArt | ppt-master 也 deliberate 不做(无法可靠生成) |
35
+ | 从零自由设计(无模板) | 这是 ppt-master 的主场,不是我们的定位。我们做"忠实复刻用户模板" |
36
+ | 桌面 GUI / Flask 编辑器 | 命令行 + 预览图足够;引入 Web 服务得不偿失 |
37
+ | 253MB 内置模板库 | 与"轻量"定位冲突;用户的模板就是模板 |
38
+
39
+ ## 下一步候选(按性价比排序)
40
+
41
+ 1. **图片搜索 + 许可合规**(中成本,直接补上"没有素材"的短板)
42
+ 2. **模板蒸馏**:把用户多个模板的共性抽成 style profile 复用
43
+ 3. **对比度检查**:在 `check` 里加 WCAG 对比度检测(双方都缺,做了就是差异点)
44
+ 4. **原生表格**:练习页/实验记录表用真表格而非文本对齐
45
+ 5. **SVG 自由版面**:仅在用户明确需要"设计感"时才考虑,成本极高
46
+
47
+ ## 设计取舍记录
48
+
49
+ | 决策 | 理由 |
50
+ |---|---|
51
+ | 不做 SVG 中间层 | 我们的目标是模板保真,不是设计自由。SVG 层会带来 10 倍代码量 |
52
+ | 不做 7 步带闸门的长流程 | 中小学课件场景简单,两次确认(大纲 + 交付)足够 |
53
+ | Quick 只砍交互不砍检查 | ppt-master 的 Quick 会丢质量门禁,长对话里容易失控 |
54
+ | 用 YAML 规格而非对话驱动 | 规格可版本化、可 diff、可复用;对话驱动不可追溯 |
55
+ | 每条规则只写一处 | ppt-master 的规则副本漂移是真实维护灾难 |
@@ -0,0 +1,100 @@
1
+ # 参考:模板保真原理
2
+
3
+ 这份文档解释「为什么模板会被套错」,以及工具是怎么避免的。
4
+ 用户抱怨"背景/字体不对"时,先读这里。
5
+
6
+ ## 1. 多母版是最大的坑
7
+
8
+ 一个 pptx 里可以有**多个母版**(多套设计)。典型情况:
9
+
10
+ ```
11
+ master1 12 个版式 背景 = 浅绿图片 ← python-pptx 只暴露这个
12
+ master2 2 个版式 背景 = 白 + 左侧绿带 ← 模板 23/25 页实际在用
13
+ ```
14
+
15
+ `python-pptx` 的 `Presentation.slide_layouts` **只返回第一个母版的版式**。
16
+ 直接用它就会套错整套配色、背景和字体 —— 而且 XML 层面看不出问题,
17
+ 只有把渲染结果像素对比才会暴露。
18
+
19
+ **工具的处理**:
20
+
21
+ 1. 遍历 `p:sldMasterIdLst`,把所有母版的版式汇成一张全局表
22
+ 2. 统计示例页实际挂在哪个母版,定为**主母版**(配色/字体取自主母版)
23
+ 3. 按**角色**从样张学版式:
24
+ - 封面 → 首页用的版式
25
+ - 内容 → 出现频率最高的版式
26
+ - 结束页 → 末页用的版式
27
+ 因为封面/结束页经常和内容页**不是同一套母版**
28
+ 4. 单独记住封面/结束页的**幻灯片级 `<p:bg>` 覆盖**(它们常常不跟随母版)
29
+
30
+ 验证方式:`inspect` 输出里的「母版」和「样式档案」两段。
31
+
32
+ ## 2. 背景的三种来源
33
+
34
+ | 来源 | 位置 | 处理 |
35
+ |---|---|---|
36
+ | 母版 `<p:bg>` | `slideMaster.xml` | 自动继承,不用管 |
37
+ | 版式自带图形 | `slideLayout.xml` 里的非占位符形状 | 用对该版式就自动继承 |
38
+ | 幻灯片级 `<p:bg>` | `slideN.xml` 自己的 `<p:bg>` | **只在个别页出现时不会被全局继承**,需要按角色单独复制 |
39
+
40
+ 第 2 种最容易被忽略:真正的"页面设计"经常不在母版里,而在版式的装饰形状里
41
+ (例如左侧竖贯色条、标签底色、角标图片)。
42
+
43
+ ## 3. 字体为什么会读错
44
+
45
+ `theme1.xml` 里声明的 `majorFont/minorFont` 经常**和模板实际用的字体不一致**:
46
+
47
+ ```
48
+ 主题声明: majorLatin = 等线 Light, minorLatin = 等线
49
+ 实际正文: 微软雅黑 28pt ← 作者手工设的
50
+ ```
51
+
52
+ 而且主题里往往**根本没有 `<a:ea>`(中文字体)声明**,中文会回落到系统默认。
53
+
54
+ **工具的处理**:`profile.py` 统计样张里**非占位符、非模块标签、非标题条**的文字 run,
55
+ 按字符数加权投票,得出真实的正文 `(字体, 字号)`。
56
+
57
+ 验证方式:`inspect` 输出的「正文排版 : 微软雅黑 28.0pt」。
58
+
59
+ ## 4. 页面骨架(模块标签 + 标题条)
60
+
61
+ 很多模板不靠版式定义观感,而是把同一套设计**重复画在每一页**上:
62
+
63
+ ```
64
+ [模块标签] ← 左上角小文本框,如"科学解释"(23/25 页重复)
65
+ ┌──────────────┐
66
+ │ 天气现象-雨… │ ← 白色圆角标题条,绿描边(10/25 页重复)
67
+ └──────────────┘
68
+ ```
69
+
70
+ 工具会统计重复出现的形状,学出:位置、字体、字号、填充色、描边色、圆角半径。
71
+ 渲染时按学到的参数重画,并用 `module` 字段填标签、`title` 填标题条。
72
+
73
+ **标题条宽度按文字长度自适应**。注意中文字体下英文空格和数字比估算更宽,
74
+ 所以留了 18% 余量;超长标题会缩字号而不是折行(折行会溢出标题条)。
75
+
76
+ ## 5. 装饰层(反复出现的素材)
77
+
78
+ 同一张图片出现在 ≥2 页 → 判定为装饰素材,复制到每一张新页面。
79
+ 页脚色条、角标、logo、边框都属于这类。
80
+
81
+ `inspect` 输出的「全局装饰层」列出它们。识别不出来时:
82
+ - 模板只有 1-2 页示例 → 整页背景图会被识别
83
+ - 每页装饰都不同 → 不会被识别(这是对的,它不是模板的一部分)
84
+
85
+ ## 6. 4:3 与 16:9
86
+
87
+ 工具读模板的**实际画布尺寸**,字号按比例缩放。
88
+ 4:3 模板下若版式占位符超出画布,会自动拉回并给出警告。
89
+
90
+ ---
91
+
92
+ ## 常见误判排查表
93
+
94
+ | 用户说 | 先查 | 命令 |
95
+ |---|---|---|
96
+ | 背景不对 | 母版数、主母版、封面/内容是否跨母版 | `inspect` |
97
+ | 字体不对 | 样式档案的「正文排版」 | `inspect` |
98
+ | 版式不对 | 页型→版式映射 | `inspect --map` |
99
+ | 页面上有别人的内容 | 模板示例页没清干净 | `build`(默认会清空) |
100
+ | 装饰少了 | 全局装饰层是否识别到 | `inspect --json` |
@@ -0,0 +1,172 @@
1
+ # Generate —— 用模板 + 大纲生成课件
2
+
3
+ **权威文件**:本文件是该路线的唯一执行权威。与其他文档冲突时以本文件为准。
4
+
5
+ ## 前置检查
6
+
7
+ 进入本路线前必须确认:
8
+
9
+ | 条件 | 检查方式 | 缺失时 |
10
+ |---|---|---|
11
+ | 有模板 pptx | `ls templates/*.pptx` | 报告缺失并停止;不要用内置模板冒充用户模板 |
12
+ | 已跑过 `inspect` | 本轮对话里有无 inspect 输出 | 先跑 `"$ENGINE_HOME/pptxgen.sh" inspect <模板>` |
13
+ | 有大纲内容 | 用户提供或已有文档 | 向用户索取,不要自行编造课程内容 |
14
+
15
+ ---
16
+
17
+ ## 步骤 1 —— 读模板(诊断,不产出)
18
+
19
+ ```bash
20
+ "$ENGINE_HOME/pptxgen.sh" inspect "templates/xxx.pptx"
21
+ ```
22
+
23
+ 读三块并理解:
24
+
25
+ - **母版**:几个?主母版是哪个?封面/内容/结束页各在哪套母版上?
26
+ 多母版模板下这一步错了会整套配色都不对。
27
+ - **样式档案**:模块标签位置、标题条位置与配色、内容区、**正文真实字体与字号**。
28
+ - **页型→版式映射**:确认每个页型落到哪个版式。
29
+
30
+ 细节原理见 [`references/template-fidelity.md`](../references/template-fidelity.md)。
31
+
32
+ **若模板没有可用版式**(例如所有示例页都是空白),走
33
+ [`template-intake.md`](template-intake.md) 的处理分支。
34
+
35
+ ## 步骤 2 —— 读大纲,切分页面
36
+
37
+ 大纲可以是教案 docx、markdown、或用户直接贴的文本。docx 读取方式:
38
+
39
+ ```bash
40
+ "$ENGINE_HOME/pptxgen.sh" init-deck --title "占位" -o /tmp/x.yaml # 看字段格式
41
+ ```
42
+
43
+ 解析 docx 用工作区的 Python:
44
+
45
+ ```python
46
+ import zipfile
47
+ from lxml import etree
48
+ W = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
49
+ root = etree.fromstring(zipfile.ZipFile(path).read("word/document.xml"))
50
+ # 遍历 body 的 w:p / w:tbl
51
+ ```
52
+
53
+ **切分原则**(中小学一节课 40 分钟,页数是硬约束):
54
+
55
+ | 时段 | 页数参考 |
56
+ |---|---|
57
+ | 导入/主题引入 | 2–3 页 |
58
+ | 概念讲解 | 每 1 个知识点 1 页,不超过 6 页 |
59
+ | 互动讨论/科学问题 | 1–2 页 |
60
+ | 练习/检测 | 1–2 页 |
61
+ | 小结 + 作业 | 1–2 页 |
62
+ | 结束页 | 1 页 |
63
+
64
+ 教案里带 `P2-3`、`P4` 这类页码标注时,**照它的节奏切**,不要重新编排。
65
+
66
+ ## 步骤 3 —— 写课件规格(YAML)
67
+
68
+ 写到 `decks/<课件名>.yaml`。字段全表见 [`references/deck-spec.md`](../references/deck-spec.md)。
69
+ 页型清单见 [`references/slide-types.md`](../references/slide-types.md)。
70
+ **内容必须按 [`references/content-polish.md`](../references/content-polish.md) 润色**——
71
+ 照抄教案文字视为不及格:标题要二次创作、每页有导语、长列表分块、
72
+ 术语用 `**关键词**` 内嵌着色、结论用色块、配图写图注。
73
+
74
+ 要点:
75
+
76
+ - `module` 字段填**教案里的模块名**(主题引入 / 互动讨论 / 科学概念 / 科学解释 /
77
+ 科学问题 / 科学问答 / 实验设计 / 展示),它会显示在左上角模块标签上。
78
+ - `title` 写进标题条,**不要写太长**(超过约 24 个汉字会被压字号)。
79
+ - `subtitle` 当**导语**用(标题下的一句话)。
80
+ - `pattern` 选正文骨架(steps / flow / compare / cards / timeline / callout /
81
+ image_left),同一份课件不要连续三页用同一种。
82
+ - 每页 `note:` 写讲稿 —— 会进 PPT 备注栏,老师上课直接看。
83
+ - 需要配图的页写 `image_prompt` + `image_side`,并尽量写 `image_caption`(图注)。
84
+
85
+ ### ⛔ 闸门 1 —— 大纲确认
86
+
87
+ **停下来,把页面清单给用户确认**:
88
+
89
+ ```
90
+ P1 封面 小小气象预报员
91
+ P2 主题引入 天气预报里有什么?
92
+ ...
93
+ 共 18 页
94
+ ```
95
+
96
+ 明确问:**页数够不够?模块名对不对?有没有要加的页?**
97
+
98
+ "沉默不等于同意" —— 必须等到明确答复再进入步骤 4。
99
+
100
+ ## 步骤 4 —— 配图(可跳过)
101
+
102
+ 只有课件里写了 `image_prompt` 才需要。
103
+
104
+ ```bash
105
+ "$ENGINE_HOME/pptxgen.sh" images "decks/xxx.yaml" --dry-run # 先看会生成几张
106
+ "$ENGINE_HOME/pptxgen.sh" images "decks/xxx.yaml" --limit 2 # 先试 2 张
107
+ ```
108
+
109
+ 细节见 [`stages/generate-images.md`](stages/generate-images.md)。
110
+
111
+ 用户没配图像模型 key 时:用 `--backend mock` 出本地占位图把版面跑通,
112
+ **明确告诉用户这是占位图**,并给出配 key 的方法。不要假装已经配好图。
113
+
114
+ ## 步骤 5 —— 生成 pptx
115
+
116
+ ```bash
117
+ "$ENGINE_HOME/pptxgen.sh" build "decks/xxx.yaml" -o "out/xxx.pptx"
118
+ ```
119
+
120
+ 读生成报告里的「注意」列表。每一条都要处理或解释:
121
+
122
+ | 警告 | 处理 |
123
+ |---|---|
124
+ | 自动缩小字号 | 内容太多 → 拆页;或确认缩后仍可读 |
125
+ | 找不到图片 | 路径错或没生成 → 修路径或跑 `images` |
126
+ | 配图还没生成 | 跑 `pptxgen images` |
127
+ | 占位符超出画布 | 模板问题 → 报告用户 |
128
+
129
+ ## 步骤 6 —— 质量闭闸(必做)
130
+
131
+ ```bash
132
+ "$ENGINE_HOME/pptxgen.sh" check "out/xxx.pptx" --render
133
+ "$ENGINE_HOME/pptxgen.sh" review "decks/xxx.yaml" --pptx "out/xxx.pptx"
134
+ "$ENGINE_HOME/pptxgen.sh" preview "out/xxx.pptx" -o out/preview
135
+ ```
136
+
137
+ `check --render` 检查:空白页、文字溢出、越界、**真实渲染下的文字重叠**,
138
+ 外加 **OOXML Schema 严格校验**(PowerPoint 同源规则,抓"点了修复才能打开"的结构错误)。
139
+
140
+ `review` 是**设计审查**:版式多样性(相邻页不得同型)、信息密度下限、
141
+ 视觉锚点、润色落实(关键词高亮 / 图注 / 长列表分块)。
142
+ 规则与阈值见 [`references/design-review.md`](../references/design-review.md);
143
+ 报「错误」必须改,报「建议」逐条解释或修掉。
144
+
145
+ **`check` 报 0 问题、`review` 无「错误」才算通过。** 有问题时:一次性读完所有报错 →
146
+ 合并成一次修改 → 只复跑一次。不要"改一条跑一次"。
147
+
148
+ 判定标准与常见修法见 [`references/quality-gates.md`](../references/quality-gates.md)。
149
+
150
+ ### ⛔ 闸门 2 —— 交付确认
151
+
152
+ 把这三样给用户:
153
+
154
+ 1. 课件路径 `out/xxx.pptx`
155
+ 2. `check --render` 与 `review` 的完整输出
156
+ 3. 总览图路径 `out/preview/_总览.png`
157
+
158
+ 并主动说明**已知的不足**(例如"这一版没有配图"/"第 9 页字号缩到了 20pt")。
159
+
160
+ ---
161
+
162
+ ## 失败恢复
163
+
164
+ | 症状 | 归属层 | 处理 |
165
+ |---|---|---|
166
+ | 单页排版难看/溢出 | 页面 | 改该页内容量或 `image_side`,重跑 build |
167
+ | 多页同类问题 | 引擎/规格 | 改 `options`(如 `fit_shrink_floor`),改一次全跑 |
168
+ | 背景/字体不对 | 模板诊断 | 回到步骤 1 重读 inspect,检查母版与样式档案 |
169
+ | 版式选错 | 映射 | 在 YAML 里用 `layout: "版式名"` 或 `layout_map` 覆盖 |
170
+ | 引擎报错 | 引擎 | 修 `pptxgen/` 源码,并补一条回归测试 |
171
+
172
+ **禁止**:用"换一页内容"绕过引擎缺陷;用删除内容绕过溢出;静默跳过失败步骤。
@@ -0,0 +1,41 @@
1
+ # Quick —— 跳过两次确认
2
+
3
+ 与 [Generate](generate.md) **完全相同**,只省略两个 `⛔ 闸门`:
4
+
5
+ | 步骤 | Generate | Quick |
6
+ |---|---|---|
7
+ | 1 读模板 `inspect` | 必做 | **必做** |
8
+ | 2 读大纲切页 | 必做 | 必做(自行决定页数与切分) |
9
+ | 3 写规格 YAML | 必做 | 必做 |
10
+ | ⛔ 大纲确认 | 等用户 | **跳过** |
11
+ | 4 配图 | 可选 | 可选(有 `image_prompt` 就必须处理) |
12
+ | 5 生成 pptx | 必做 | 必做 |
13
+ | 6 质量闭闸 | 必做 | **必做** |
14
+ | ⛔ 交付确认 | 等用户 | **跳过**,直接报告 |
15
+
16
+ ## 自行决定的边界
17
+
18
+ 用户明确说过的**照做**;没说的**自己定,不要回头问**:
19
+
20
+ | 未指定项 | 自行决定 |
21
+ |---|---|
22
+ | 页数 | 按教案节奏,40 分钟课约 16–20 页 |
23
+ | 模块名 | 用教案里的原词 |
24
+ | 是否配图 | 有 `image_prompt` 且能生成就配;不能就明确说明 |
25
+ | 字体/配色 | 一律用模板学到的,不要自创 |
26
+
27
+ ## 仍然禁止
28
+
29
+ - 跳过 `inspect`(会套错母版)
30
+ - 跳过 `check --render`(会交付有重叠的课件)
31
+ - 编造课程内容填补大纲空白
32
+ - 用本地占位图冒充真实配图而不说明
33
+
34
+ ## 收尾
35
+
36
+ Quick 结束时仍然要给用户:
37
+
38
+ 1. 课件路径
39
+ 2. `check --render` 的完整输出
40
+ 3. 总览图路径
41
+ 4. **你做过的所有自主决定**(页数、切分、配图与否)—— 这样用户能一眼看出哪里需要调整