@topmindspace/tms-skills 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.
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/README.md +102 -0
- package/bin/tms-skills.js +160 -0
- package/package.json +48 -0
- package/top-ppt-html/README.md +254 -0
- package/top-ppt-html/SKILL.md +111 -0
- package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.html +3926 -0
- package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.model.json +168 -0
- package/top-ppt-html/assets/examples/2026-09-09-architecture-spectrum.html +3926 -0
- package/top-ppt-html/assets/examples/2026-09-09-architecture-spectrum.model.json +168 -0
- package/top-ppt-html/assets/examples/2026-09-09-presentation-apple-mono.html +4325 -0
- package/top-ppt-html/assets/examples/2026-09-09-presentation-apple-mono.model.json +321 -0
- package/top-ppt-html/assets/examples/2026-09-09-presentation-brand-red.html +4325 -0
- package/top-ppt-html/assets/examples/2026-09-09-presentation-brand-red.model.json +321 -0
- package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.html +4325 -0
- package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.model.json +321 -0
- package/top-ppt-html/assets/examples/2026-09-09-research-deep-teal.html +5527 -0
- package/top-ppt-html/assets/examples/2026-09-09-research-deep-teal.model.json +914 -0
- package/top-ppt-html/assets/examples/2026-09-09-research-indigo-violet.html +5527 -0
- package/top-ppt-html/assets/examples/2026-09-09-research-indigo-violet.model.json +914 -0
- package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.html +5527 -0
- package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.model.json +914 -0
- package/top-ppt-html/assets/examples/2026-09-09-research-warm-sand.html +5527 -0
- package/top-ppt-html/assets/examples/2026-09-09-research-warm-sand.model.json +914 -0
- package/top-ppt-html/assets/pptx-export.js +1944 -0
- package/top-ppt-html/assets/style-gallery.html +589 -0
- package/top-ppt-html/assets/templates/architecture.html +3728 -0
- package/top-ppt-html/assets/templates/engine.css +840 -0
- package/top-ppt-html/assets/templates/presentation.html +3738 -0
- package/top-ppt-html/assets/templates/research.html +4017 -0
- package/top-ppt-html/assets/templates/ui.js +520 -0
- package/top-ppt-html/assets/theme-overview-architecture.png +0 -0
- package/top-ppt-html/assets/theme-overview-presentation.png +0 -0
- package/top-ppt-html/assets/theme-overview-research.png +0 -0
- package/top-ppt-html/assets/theme-overview.png +0 -0
- package/top-ppt-html/evals/prompts.csv +15 -0
- package/top-ppt-html/evals/rubric.schema.json +25 -0
- package/top-ppt-html/evals/run_evals.py +220 -0
- package/top-ppt-html/evals/trace.example.json +16 -0
- package/top-ppt-html/package.json +35 -0
- package/top-ppt-html/references/charts-basic.md +624 -0
- package/top-ppt-html/references/charts-discipline.md +108 -0
- package/top-ppt-html/references/charts-extended.md +482 -0
- package/top-ppt-html/references/charts.md +28 -0
- package/top-ppt-html/references/components-atoms.md +624 -0
- package/top-ppt-html/references/components.md +30 -0
- package/top-ppt-html/references/content-rules.md +490 -0
- package/top-ppt-html/references/design-system-engine.md +235 -0
- package/top-ppt-html/references/design-system.md +478 -0
- package/top-ppt-html/references/failure-modes.md +214 -0
- package/top-ppt-html/references/high-fidelity.md +127 -0
- package/top-ppt-html/references/icons.md +397 -0
- package/top-ppt-html/references/industry-benchmark.md +105 -0
- package/top-ppt-html/references/infographics-stats.md +308 -0
- package/top-ppt-html/references/infographics-structure.md +226 -0
- package/top-ppt-html/references/infographics.md +43 -0
- package/top-ppt-html/references/layout-grammar.md +315 -0
- package/top-ppt-html/references/layouts-architecture.md +108 -0
- package/top-ppt-html/references/layouts-combo.md +600 -0
- package/top-ppt-html/references/layouts-research.md +160 -0
- package/top-ppt-html/references/modes.md +254 -0
- package/top-ppt-html/references/outline-design.md +275 -0
- package/top-ppt-html/references/playbook.md +266 -0
- package/top-ppt-html/references/pptx-export.md +209 -0
- package/top-ppt-html/references/reform-plan.md +252 -0
- package/top-ppt-html/references/styles.md +370 -0
- package/top-ppt-html/references/tech-design.md +138 -0
- package/top-ppt-html/scripts/audit_css.py +109 -0
- package/top-ppt-html/scripts/audit_docs.py +176 -0
- package/top-ppt-html/scripts/audit_skill.py +220 -0
- package/top-ppt-html/scripts/audit_styles.py +351 -0
- package/top-ppt-html/scripts/build_examples.py +2276 -0
- package/top-ppt-html/scripts/build_pptx.js +2380 -0
- package/top-ppt-html/scripts/capture_theme_overview.js +78 -0
- package/top-ppt-html/scripts/checks_html.py +127 -0
- package/top-ppt-html/scripts/cross_verify.py +294 -0
- package/top-ppt-html/scripts/env_probe.py +158 -0
- package/top-ppt-html/scripts/extract_model.py +210 -0
- package/top-ppt-html/scripts/extract_snippet.py +374 -0
- package/top-ppt-html/scripts/gen_channel_a.js +214 -0
- package/top-ppt-html/scripts/layout-constants.json +3377 -0
- package/top-ppt-html/scripts/layout_slots.json +830 -0
- package/top-ppt-html/scripts/lib_layout_regions.js +412 -0
- package/top-ppt-html/scripts/measure_height.py +178 -0
- package/top-ppt-html/scripts/model-schema.json +547 -0
- package/top-ppt-html/scripts/negative_tests.py +307 -0
- package/top-ppt-html/scripts/package_skill.py +291 -0
- package/top-ppt-html/scripts/prepare_images.py +341 -0
- package/top-ppt-html/scripts/probe_image_export.py +188 -0
- package/top-ppt-html/scripts/quality_gate.py +301 -0
- package/top-ppt-html/scripts/regression.py +308 -0
- package/top-ppt-html/scripts/render_compare.py +275 -0
- package/top-ppt-html/scripts/render_from_model.py +698 -0
- package/top-ppt-html/scripts/scaffold_report.py +1054 -0
- package/top-ppt-html/scripts/section-file-map.json +105 -0
- package/top-ppt-html/scripts/sync_runtime.py +662 -0
- package/top-ppt-html/scripts/validate_pptx.py +1510 -0
- package/top-ppt-html/scripts/validate_report.py +1456 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# 风格系统(9 套预设 · 覆盖 8 个色族 + 1 个彩色数据板)
|
|
2
|
+
|
|
3
|
+
> **何时读**:改配色、换/新增风格、调亮暗 token、配编码色板、对齐风格语汇(字体/圆角/字阶/密度)时。**何时不读**:只想挑风格(Gate 0 参考图 + `--task style-theme` 速览即可)。
|
|
4
|
+
> **取节**:`python scripts/extract_snippet.py --task style-theme`(快速选型 + 新增步骤);单套风格细节 `--file styles.md --section <1-11>`(数字节号)。
|
|
5
|
+
|
|
6
|
+
## 工作原理
|
|
7
|
+
|
|
8
|
+
报告结构与样式分离。`design-system.md` 提供**风格无关的 CSS 引擎**(版式、栅格、组件、排版类、SVG 语义类全部复用);每套风格**覆盖两层 token**:
|
|
9
|
+
|
|
10
|
+
1. **结构色层**(必须):强调色、表面色族、文字色、边框——决定「是什么颜色」;
|
|
11
|
+
2. **风格语汇层**(必须与定位一致):`--font-body` / `--font-display` / `--radius` / `--fs-*` 微调 / `--letter-*` / `--lh-*` / `--gap` / `--shadow-*` / `--link`——决定「是什么气质」(字体、圆角、字阶、留白、阴影)。
|
|
12
|
+
|
|
13
|
+
**语汇清单单源** = `scripts/layout-constants.json` `styleIdentity`;`engine.css` 覆盖块逐项落地;`audit_styles.py` 校验缺一即 FAIL。**只改色不改语汇 = 只有皮肤没有性格**。
|
|
14
|
+
|
|
15
|
+
切换方式:`<html data-mode="X" data-style="business-blue" data-theme="light">`。
|
|
16
|
+
|
|
17
|
+
- **模式(三选一,生成时锁定)与风格正交**:结构 / 类名 / 组件由模式模板决定(`assets/templates/`),风格覆盖上述两层 token。
|
|
18
|
+
- 生成后 header 风格下拉可实时切换 9 套(纯视觉皮肤不动内容);交付前切回选定值(`data-style` 与 `REPORT_MODEL.style` 一致,校验器检查)。
|
|
19
|
+
- 除 `spectrum` 外,每套风格**只有一个强调色**,层次仍靠表面明度差 + 1px 边框;`spectrum` 的彩色仅限数据系列(见第 9 节边界)。
|
|
20
|
+
- 每套都同时给出 light 与 dark 两套**色**值;语汇层(字体/圆角/字阶)两主题共用。
|
|
21
|
+
- 风格 × 模式矩阵预览见 `assets/style-gallery.html`(三模式 Tab 为一级维度、9 风格卡片为二级,每张卡按当前模式渲染迷你版式特征)。
|
|
22
|
+
- **PPTX 导出侧的色 token 与本文件同源**:单一事实源在 `scripts/layout-constants.json` `styles`(light 变量),两导出通道自动消费(`sync_runtime.py` 注入/校验);改风格值改 JSON,不要只改本文档。**PPTX 字体族一律 Microsoft YaHei**(投影可读性),不跟 HTML 换衬线/系统栈。
|
|
23
|
+
|
|
24
|
+
## 快速选型(含三模式推荐风格)
|
|
25
|
+
|
|
26
|
+
| 风格 | data-style | 一句话定位 | 适用场景 |
|
|
27
|
+
|------|-----------|-----------|---------|
|
|
28
|
+
| 商务蓝(默认) | `business-blue` | 专业克制、信息密度高,最通用 | 技术/数据/通用商务;**架构模式推荐** |
|
|
29
|
+
| 优雅黑白 | `apple-mono` | 极简、大留白、大字,高级产品感 | 产品发布、品牌、高管演示 |
|
|
30
|
+
| 麦肯锡咨询 | `mckinsey` | 结构化、正式、咨询范 | 战略/咨询/立项;**研究模式首选** |
|
|
31
|
+
| 品牌红 | `brand-red` | 以品牌主色红为强调,正式有辨识度 | 企业品牌材料、正式汇报 |
|
|
32
|
+
| 暖沙金 | `warm-sand` | 温暖高级、编辑感 | 年报、品牌叙事、文化;**研究模式推荐** |
|
|
33
|
+
| 墨绿 | `deep-teal` | 沉稳可信赖 | 金融、风控、ESG;**研究模式推荐** |
|
|
34
|
+
| 石墨深灰 | `graphite-dark` | 深色优先的沉浸石墨风(近黑面板 + 亮蓝青;浅色石墨纸灰为辅助) | 发布会、大屏展示;**架构模式首选** |
|
|
35
|
+
| 靛紫 | `indigo-violet` | 创新前沿 | AI、科技、研发 |
|
|
36
|
+
| 光谱彩色 | `spectrum` | 中性结构 + 5 色数据色板,图表出彩不花哨 | 数据密集汇报、运营复盘、大屏看板;**架构模式推荐** |
|
|
37
|
+
|
|
38
|
+
> **三模式推荐组合速记**:演示 → 商务蓝(默认)/优雅黑白;研究 → 麦肯锡/墨绿/暖沙金;架构 → 石墨深灰/商务蓝/彩色。研究模式偏好衬线标题 + 细线框架的咨询质感,架构模式偏好深色沉浸或彩色数据面,演示模式全部可用、默认商务蓝。
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 1. 商务蓝 `business-blue`(默认)
|
|
43
|
+
|
|
44
|
+
**定位**:专业、克制、信息密度高。中性灰阶 + Google Blue。
|
|
45
|
+
**适用**:绝大多数商务/技术/数据汇报。
|
|
46
|
+
|
|
47
|
+
**语汇**:Google Material · 圆角 16 · 同字族 · 密度 normal · `--link` = accent-text。
|
|
48
|
+
|
|
49
|
+
```css
|
|
50
|
+
html[data-style="business-blue"] {
|
|
51
|
+
--font-body: "Google Sans","Roboto",-apple-system,BlinkMacSystemFont,"Segoe UI",
|
|
52
|
+
"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans SC",sans-serif;
|
|
53
|
+
--font-display: var(--font-body);
|
|
54
|
+
--radius: 16px; --fw-display:700; --fw-title:600;
|
|
55
|
+
--letter-display:-.03em; --letter-eyebrow:.11em; --lh-body:1.68; --lh-lead:1.62; --link:#1b66c9;
|
|
56
|
+
--bg:#ffffff; --surface:#ffffff; --surface-1:#f8f9fa; --surface-2:#f1f3f4; --surface-3:#e8eaed;
|
|
57
|
+
--surface-inv:#202124; --text:#202124; --text-2:#5f6368; --text-3:#80868b; --text-inv:#ffffff;
|
|
58
|
+
--border:#dadce0; --border-soft:#e8eaed;
|
|
59
|
+
--accent:#1a73e8; --accent-soft:#e8f0fe; --accent-soft-2:#d2e3fc; --accent-text:#1b66c9; --accent-on:#ffffff;
|
|
60
|
+
}
|
|
61
|
+
html[data-style="business-blue"][data-theme="dark"] {
|
|
62
|
+
--bg:#0d0f13; --surface:#14171c; --surface-1:#191d23; --surface-2:#20252c; --surface-3:#2a3038;
|
|
63
|
+
--surface-inv:#e8eaed; --text:#e8eaed; --text-2:#adb4bd; --text-3:#868d96; --text-inv:#14171c;
|
|
64
|
+
--border:#2f353d; --border-soft:#23282f;
|
|
65
|
+
--accent:#8ab4f8; --accent-soft:#16243a; --accent-soft-2:#1d3557; --accent-text:#8ab4f8; --accent-on:#0d1b2e;
|
|
66
|
+
--link:#8ab4f8;
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 2. 优雅黑白 `apple-mono`
|
|
73
|
+
|
|
74
|
+
**定位**:苹果式极简。大留白、超大字号、几乎无彩色,靠留白与排版取胜。
|
|
75
|
+
**适用**:产品发布、品牌、面向高管/外部的演示。
|
|
76
|
+
**特点**:强调色为近黑/近白(按钮实底黑),CTA 可极少量用系统蓝 `#0071e3`(`--link`);分块少、字大、行宽松。
|
|
77
|
+
**语汇**:Apple 极简 · 圆角 20 · **typeBoost**(display/h1 放大)· `--fw-title:500` 更轻 · 行高 1.75 · 栅格 gap 放大 · 阴影几乎归零。
|
|
78
|
+
|
|
79
|
+
```css
|
|
80
|
+
html[data-style="apple-mono"] {
|
|
81
|
+
--font-body: -apple-system,BlinkMacSystemFont,"SF Pro Text","Helvetica Neue",
|
|
82
|
+
"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
|
|
83
|
+
--font-display: -apple-system,BlinkMacSystemFont,"SF Pro Display","Helvetica Neue","PingFang SC",sans-serif;
|
|
84
|
+
--radius: 20px; --fw-display:600; --fw-title:500;
|
|
85
|
+
--fs-display: clamp(3rem,5.4vw,4.75rem); /* typeBoost */
|
|
86
|
+
--fs-h1: clamp(2.125rem,3.6vw,3.25rem);
|
|
87
|
+
--letter-display:-.04em; --letter-eyebrow:.12em; --lh-body:1.75; --lh-lead:1.7;
|
|
88
|
+
--gap:clamp(22px,2.2vw,36px); --link:#0071e3;
|
|
89
|
+
--bg:#ffffff; --surface:#ffffff; --surface-1:#f5f5f7; --surface-2:#f5f5f7; --surface-3:#e8e8ed;
|
|
90
|
+
--surface-inv:#1d1d1f; --text:#1d1d1f; --text-2:#6e6e73; --text-3:#86868b; --text-inv:#f5f5f7;
|
|
91
|
+
--border:#d2d2d7; --border-soft:#e8e8ed;
|
|
92
|
+
--accent:#1d1d1f; --accent-soft:#f5f5f7; --accent-soft-2:#e8e8ed; --accent-text:#1d1d1f; --accent-on:#ffffff;
|
|
93
|
+
--shadow-1:none; --shadow-2:0 4px 24px rgba(0,0,0,.06);
|
|
94
|
+
}
|
|
95
|
+
html[data-style="apple-mono"][data-theme="dark"] {
|
|
96
|
+
--bg:#000000; --surface:#000000; --surface-1:#161617; --surface-2:#1d1d1f; --surface-3:#2a2a2d;
|
|
97
|
+
--surface-inv:#f5f5f7; --text:#f5f5f7; --text-2:#a1a1a6; --text-3:#86868b; --text-inv:#1d1d1f;
|
|
98
|
+
--border:#38383d; --border-soft:#2a2a2d;
|
|
99
|
+
--accent:#f5f5f7; --accent-soft:#1d1d1f; --accent-soft-2:#2a2a2d; --accent-text:#f5f5f7; --accent-on:#000000;
|
|
100
|
+
--link:#2997ff;
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 3. 麦肯锡咨询 `mckinsey`
|
|
107
|
+
|
|
108
|
+
**定位**:结构化、正式、咨询范。衬线标题 + 无衬线正文 + 细线框架 + 小圆角 + 高密表格。
|
|
109
|
+
**适用**:战略、咨询、立项、可研、对标。
|
|
110
|
+
**特点**:强调色为藏青;标题用衬线(Georgia/宋体),eyebrow 小字大写拉开字距;靠 1px hairline 与网格分块,几乎不用阴影。
|
|
111
|
+
**语汇**:咨询范 · **serifDisplay** · 圆角 6(近直角)· 密度 dense · `--letter-eyebrow:.14em` · 行高收紧 1.55 · gap 收紧。
|
|
112
|
+
|
|
113
|
+
```css
|
|
114
|
+
html[data-style="mckinsey"] {
|
|
115
|
+
--font-body: "Inter","IBM Plex Sans",-apple-system,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
|
|
116
|
+
--font-display: "Georgia","Times New Roman","Songti SC","STSong","SimSun",serif;
|
|
117
|
+
--radius: 6px; --fw-display:600; --fw-title:600;
|
|
118
|
+
--letter-display:-.015em; --letter-eyebrow:.14em; --lh-body:1.55; --lh-lead:1.5;
|
|
119
|
+
--gap:clamp(14px,1.3vw,22px);
|
|
120
|
+
--bg:#ffffff; --surface:#ffffff; --surface-1:#f2f4f7; --surface-2:#f2f4f7; --surface-3:#e4e7ec;
|
|
121
|
+
--surface-inv:#101828; --text:#101828; --text-2:#475467; --text-3:#667085; --text-inv:#ffffff;
|
|
122
|
+
--border:#d0d5dd; --border-soft:#e4e7ec;
|
|
123
|
+
--accent:#003a70; --accent-soft:#eef4fb; --accent-soft-2:#d9e8f6; --accent-text:#003a70; --accent-on:#ffffff;
|
|
124
|
+
--shadow-1:none; --shadow-2:0 1px 2px rgba(16,24,40,.06);
|
|
125
|
+
}
|
|
126
|
+
html[data-style="mckinsey"][data-theme="dark"] {
|
|
127
|
+
--bg:#0c1116; --surface:#0c1116; --surface-1:#12181f; --surface-2:#182030; --surface-3:#21293a;
|
|
128
|
+
--surface-inv:#e4e7ec; --text:#e4e7ec; --text-2:#aab3c2; --text-3:#8a94a6; --text-inv:#101828;
|
|
129
|
+
--border:#2a3342; --border-soft:#1f2733;
|
|
130
|
+
--accent:#7fb2e5; --accent-soft:#12233a; --accent-soft-2:#1b3358; --accent-text:#7fb2e5; --accent-on:#0c1a2e;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
> 标题用 `.t-h1/.t-h2` 时衬线字体生效(`--font-display`);eyebrow 走 `--letter-eyebrow:.14em` + `text-transform:uppercase` 强化咨询感。
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 4. 品牌红 `brand-red`
|
|
139
|
+
|
|
140
|
+
**定位**:以品牌主色红为强调,正式且有辨识度。可将下方红色替换为任意企业品牌色。
|
|
141
|
+
**适用**:企业品牌材料、正式汇报、对外宣讲。
|
|
142
|
+
**语汇**:正式品牌 · HarmonyOS Sans 栈 · 圆角 14 · 同字族粗字重 · 密度 normal。
|
|
143
|
+
|
|
144
|
+
```css
|
|
145
|
+
html[data-style="brand-red"] {
|
|
146
|
+
--font-body: "HarmonyOS Sans","PingFang SC","Microsoft YaHei","Noto Sans SC",-apple-system,"Segoe UI",sans-serif;
|
|
147
|
+
--font-display: var(--font-body);
|
|
148
|
+
--radius: 14px; --fw-display:700; --fw-title:600;
|
|
149
|
+
--letter-display:-.025em; --letter-eyebrow:.12em; --lh-body:1.66; --lh-lead:1.6;
|
|
150
|
+
--bg:#ffffff; --surface:#ffffff; --surface-1:#faf7f7; --surface-2:#f5f0f0; --surface-3:#ece5e5;
|
|
151
|
+
--surface-inv:#1f1a1b; --text:#1f1a1b; --text-2:#5d5456; --text-3:#8a8083; --text-inv:#ffffff;
|
|
152
|
+
--border:#e2d9da; --border-soft:#ece5e5;
|
|
153
|
+
--accent:#d0021b; --accent-soft:#fbecec; --accent-soft-2:#f6d5d7; --accent-text:#b00217; --accent-on:#ffffff;
|
|
154
|
+
}
|
|
155
|
+
html[data-style="brand-red"][data-theme="dark"] {
|
|
156
|
+
--bg:#130d0e; --surface:#130d0e; --surface-1:#1a1213; --surface-2:#231718; --surface-3:#2e1e20;
|
|
157
|
+
--surface-inv:#f3ecec; --text:#f3ecec; --text-2:#c4b6b7; --text-3:#9a8d8e; --text-inv:#1f1a1b;
|
|
158
|
+
--border:#37272a; --border-soft:#2a1e20;
|
|
159
|
+
--accent:#ff5a66; --accent-soft:#331518; --accent-soft-2:#471c21; --accent-text:#ff7a83; --accent-on:#2a0d10;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 5. 暖沙金 `warm-sand`
|
|
166
|
+
|
|
167
|
+
**定位**:温暖高级、编辑感/年报感。米白暖底 + 古铜金强调,衬线标题。
|
|
168
|
+
**适用**:年度报告、品牌叙事、文化建设、价值观。
|
|
169
|
+
**语汇**:编辑/年报 · **serifDisplay** · 圆角 12 · 宽松行高 1.72 · gap 略放 · 阴影极轻。
|
|
170
|
+
|
|
171
|
+
```css
|
|
172
|
+
html[data-style="warm-sand"] {
|
|
173
|
+
--font-body: "Inter","Source Han Sans","PingFang SC","Microsoft YaHei",-apple-system,sans-serif;
|
|
174
|
+
--font-display: "Georgia","Playfair Display","Songti SC","STSong","SimSun",serif;
|
|
175
|
+
--radius: 12px; --fw-display:600; --fw-title:600;
|
|
176
|
+
--letter-display:-.01em; --letter-eyebrow:.13em; --lh-body:1.72; --lh-lead:1.65;
|
|
177
|
+
--gap:clamp(18px,1.8vw,30px);
|
|
178
|
+
--bg:#fbf9f6; --surface:#ffffff; --surface-1:#f6f2ec; --surface-2:#efe9df; --surface-3:#e6ded2;
|
|
179
|
+
--surface-inv:#2a2521; --text:#2a2521; --text-2:#6b5f52; --text-3:#93836f; --text-inv:#f6f2ec;
|
|
180
|
+
--border:#e0d7c9; --border-soft:#eae3d6;
|
|
181
|
+
--accent:#96681f; --accent-soft:#f3ecdd; --accent-soft-2:#eaddc4; --accent-text:#8f6117; --accent-on:#ffffff;
|
|
182
|
+
--shadow-1:none; --shadow-2:0 1px 3px rgba(42,37,33,.08);
|
|
183
|
+
}
|
|
184
|
+
html[data-style="warm-sand"][data-theme="dark"] {
|
|
185
|
+
--bg:#15120e; --surface:#15120e; --surface-1:#1d1913; --surface-2:#26201a; --surface-3:#312920;
|
|
186
|
+
--surface-inv:#ece5db; --text:#ece5db; --text-2:#c4b8a8; --text-3:#9b8d7a; --text-inv:#2a2521;
|
|
187
|
+
--border:#3a3128; --border-soft:#2c261e;
|
|
188
|
+
--accent:#d9b36a; --accent-soft:#2e2417; --accent-soft-2:#3e3019; --accent-text:#e0c184; --accent-on:#2a1f10;
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 6. 墨绿 `deep-teal`
|
|
195
|
+
|
|
196
|
+
**定位**:沉稳、可信赖。冷灰底 + 深青强调。
|
|
197
|
+
**适用**:金融、风控、ESG、可持续、审计。
|
|
198
|
+
**语汇**:金融可信 · Inter/Source Han 栈 · 圆角 12 · 同字族 · 密度 normal。
|
|
199
|
+
|
|
200
|
+
```css
|
|
201
|
+
html[data-style="deep-teal"] {
|
|
202
|
+
--font-body: "Inter","Source Han Sans","PingFang SC","Microsoft YaHei",-apple-system,sans-serif;
|
|
203
|
+
--font-display: var(--font-body);
|
|
204
|
+
--radius: 12px; --fw-display:700; --fw-title:600;
|
|
205
|
+
--letter-display:-.028em; --letter-eyebrow:.11em; --lh-body:1.66; --lh-lead:1.6;
|
|
206
|
+
--bg:#ffffff; --surface:#ffffff; --surface-1:#f2f6f5; --surface-2:#e8f0ef; --surface-3:#dce7e5;
|
|
207
|
+
--surface-inv:#14201e; --text:#14201e; --text-2:#4a5a57; --text-3:#73837f; --text-inv:#ffffff;
|
|
208
|
+
--border:#cfdedc; --border-soft:#e0eae9;
|
|
209
|
+
--accent:#0f6b5c; --accent-soft:#e4f1ee; --accent-soft-2:#cfe5e0; --accent-text:#0d5a4e; --accent-on:#ffffff;
|
|
210
|
+
}
|
|
211
|
+
html[data-style="deep-teal"][data-theme="dark"] {
|
|
212
|
+
--bg:#0d1312; --surface:#0d1312; --surface-1:#131b1a; --surface-2:#1a2523; --surface-3:#22302d;
|
|
213
|
+
--surface-inv:#e2ecea; --text:#e2ecea; --text-2:#b3c2bf; --text-3:#86948f; --text-inv:#14201e;
|
|
214
|
+
--border:#293834; --border-soft:#1e2a27;
|
|
215
|
+
--accent:#4fc3b0; --accent-soft:#12312c; --accent-soft-2:#1a423b; --accent-text:#66cfbd; --accent-on:#0c2420;
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 7. 石墨深灰 `graphite-dark`(深色优先)
|
|
222
|
+
|
|
223
|
+
**定位**:深色优先的沉浸石墨风。近黑石墨面板 + 亮蓝青强调,**默认即深色**;浅色变体为「石墨纸灰 + 同系蓝青」,供打印/外发辅助。
|
|
224
|
+
**适用**:产品发布会、指挥中心大屏、深色优先场景。
|
|
225
|
+
**深色优先的落地**:架构模式模板(默认风格即 graphite-dark)出厂 `data-theme="dark"`;其他模式选用本风格时,交付前建议切到 dark(或向用户明示浅色为辅助变体)。浅色变体的灰阶为**中性石墨灰**(不带蓝味),与商务蓝的白底纯蓝拉开辨识度;强调色为深蓝青(与 dark 侧亮蓝青 #4da3ff 同系)。
|
|
226
|
+
|
|
227
|
+
**语汇**:沉浸石墨 · Inter/SF 栈 · 圆角 14 · 密度 dense · 深色阴影更沉 · gap 紧。
|
|
228
|
+
|
|
229
|
+
```css
|
|
230
|
+
html[data-style="graphite-dark"] {
|
|
231
|
+
--font-body: "Inter","SF Pro Text","PingFang SC","Microsoft YaHei",-apple-system,sans-serif;
|
|
232
|
+
--font-display: "Inter","SF Pro Display","PingFang SC",sans-serif;
|
|
233
|
+
--radius: 14px; --fw-display:700; --fw-title:600;
|
|
234
|
+
--letter-display:-.03em; --letter-eyebrow:.1em; --lh-body:1.62; --lh-lead:1.55;
|
|
235
|
+
--gap:clamp(14px,1.4vw,24px);
|
|
236
|
+
--bg:#f4f5f7; --surface:#ffffff; --surface-1:#eceef1; --surface-2:#e3e6ea; --surface-3:#d8dbdf;
|
|
237
|
+
--surface-inv:#14171b; --text:#1a1d21; --text-2:#4b5158; --text-3:#767c84; --text-inv:#eef2f6;
|
|
238
|
+
--border:#ced1d6; --border-soft:#e3e6ea;
|
|
239
|
+
--accent:#0369a1; --accent-soft:#e2eff7; --accent-soft-2:#c8e1f2; --accent-text:#075985; --accent-on:#ffffff;
|
|
240
|
+
}
|
|
241
|
+
html[data-style="graphite-dark"][data-theme="dark"] {
|
|
242
|
+
--bg:#0b0e12; --surface:#12161b; --surface-1:#171d24; --surface-2:#1f2732; --surface-3:#28323f;
|
|
243
|
+
--surface-inv:#eef2f6; --text:#eef2f6; --text-2:#b9c2cd; --text-3:#85909d; --text-inv:#12161b;
|
|
244
|
+
--border:#2b3540; --border-soft:#212932;
|
|
245
|
+
--accent:#4da3ff; --accent-soft:#132841; --accent-soft-2:#1a3a5e; --accent-text:#6fb2ff; --accent-on:#07182b;
|
|
246
|
+
--shadow-1:0 1px 2px rgba(0,0,0,.5); --shadow-2:0 4px 12px rgba(0,0,0,.45);
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
> **深浅两套变体的分工**:dark 是本风格的主面孔(沉浸/大屏/发布会);light 是辅助(打印/外发/明亮环境)。风格画廊(`style-gallery.html`)中本风格卡片以 dark 为主预览、light 为辅助条,直接传达这一分工。
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 8. 靛紫 `indigo-violet`
|
|
255
|
+
|
|
256
|
+
**定位**:创新、前沿。冷白底 + 靛紫强调。
|
|
257
|
+
**适用**:AI、科技、研发、创新、前沿技术。
|
|
258
|
+
**语汇**:科技前沿 · Inter/SF 栈 · 圆角 16 · 轻快字距 · 密度 normal。
|
|
259
|
+
|
|
260
|
+
```css
|
|
261
|
+
html[data-style="indigo-violet"] {
|
|
262
|
+
--font-body: "Inter","SF Pro Text","PingFang SC","Microsoft YaHei",-apple-system,sans-serif;
|
|
263
|
+
--font-display: var(--font-body);
|
|
264
|
+
--radius: 16px; --fw-display:700; --fw-title:600;
|
|
265
|
+
--letter-display:-.032em; --letter-eyebrow:.12em; --lh-body:1.68; --lh-lead:1.62;
|
|
266
|
+
--bg:#ffffff; --surface:#ffffff; --surface-1:#f4f4fb; --surface-2:#ececf7; --surface-3:#e0e0f0;
|
|
267
|
+
--surface-inv:#1b1a2e; --text:#1b1a2e; --text-2:#52506b; --text-3:#7a779a; --text-inv:#ffffff;
|
|
268
|
+
--border:#d7d7e8; --border-soft:#e6e6f2;
|
|
269
|
+
--accent:#5b5bd6; --accent-soft:#ececf9; --accent-soft-2:#dcdcf3; --accent-text:#4848c0; --accent-on:#ffffff;
|
|
270
|
+
}
|
|
271
|
+
html[data-style="indigo-violet"][data-theme="dark"] {
|
|
272
|
+
--bg:#100f1c; --surface:#100f1c; --surface-1:#171629; --surface-2:#1f1e36; --surface-3:#292845;
|
|
273
|
+
--surface-inv:#e6e5f5; --text:#e6e5f5; --text-2:#b6b4d4; --text-3:#8b89b0; --text-inv:#1b1a2e;
|
|
274
|
+
--border:#322f52; --border-soft:#262441;
|
|
275
|
+
--accent:#a5a4f0; --accent-soft:#232146; --accent-soft-2:#2e2c58; --accent-text:#b6b5f5; --accent-on:#171631;
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## 9. 光谱彩色 `spectrum`(彩色定位 · 数据色板以彩色为主)
|
|
282
|
+
|
|
283
|
+
**定位**:中性结构 + 彩色的 5 色数据色板。图表、图例、小段标签"出彩",页面骨架依然安静。
|
|
284
|
+
**适用**:数据密集汇报、运营复盘、大屏看板、多系列对比。
|
|
285
|
+
|
|
286
|
+
**彩色边界(9 套风格同一条纪律)**:
|
|
287
|
+
- 彩色**只**出现在:图表数据系列(`.f-c1~c5` / `.s-c1~c5`)、图例 chip、小段标签、仪表盘/环形分段。
|
|
288
|
+
- **不用**彩色的地方:标题、正文、边框、按钮、大面积底色、卡片背景——这些全部保持中性 + 单一 `--accent`。
|
|
289
|
+
- 同屏彩色数据系列 ≤ 5;超过就合并为"其他"。
|
|
290
|
+
- **9 套风格各有自己的 `c1–c5`**(单源 `styleDataColors`,见第 11 节与 `design-system.md` §9b)——本风格只是把彩色作为**定位**(`c1` = 强调色),并不是"唯一能出彩的风格"。
|
|
291
|
+
|
|
292
|
+
**语汇**:数据看板 · Inter/SF 栈 · 圆角 14 · 密度 dense · 紧凑 gap · 行高略紧。
|
|
293
|
+
|
|
294
|
+
```css
|
|
295
|
+
html[data-style="spectrum"] {
|
|
296
|
+
--font-body: "Inter","SF Pro Text","PingFang SC","Microsoft YaHei",-apple-system,sans-serif;
|
|
297
|
+
--font-display: var(--font-body);
|
|
298
|
+
--radius: 14px; --fw-display:700; --fw-title:600;
|
|
299
|
+
--letter-display:-.03em; --letter-eyebrow:.1em; --lh-body:1.6; --lh-lead:1.55;
|
|
300
|
+
--gap:clamp(12px,1.2vw,20px);
|
|
301
|
+
--bg:#fbfcfe; --surface:#ffffff; --surface-1:#f4f6fa; --surface-2:#eceff5; --surface-3:#dfe4ec;
|
|
302
|
+
--surface-inv:#171a21; --text:#171a21; --text-2:#4d5566; --text-3:#7b8494; --text-inv:#ffffff;
|
|
303
|
+
--border:#d6dce6; --border-soft:#e6eaf1;
|
|
304
|
+
--accent:#4563ef; --accent-soft:#eceeff; --accent-soft-2:#d8defb; --accent-text:#3d5bef; --accent-on:#ffffff;
|
|
305
|
+
}
|
|
306
|
+
html[data-style="spectrum"][data-theme="dark"] {
|
|
307
|
+
--bg:#0e1116; --surface:#131720; --surface-1:#171c26; --surface-2:#1d2330; --surface-3:#252c3b;
|
|
308
|
+
--surface-inv:#e8ebf2; --text:#e8ebf2; --text-2:#a7afbf; --text-3:#7e8798; --text-inv:#171a21;
|
|
309
|
+
--border:#2b3342; --border-soft:#212839;
|
|
310
|
+
--accent:#8ba0f8; --accent-soft:#1b2242; --accent-soft-2:#26305c; --accent-text:#93a7f9; --accent-on:#141a38;
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
> **编码色板(`--c1..--c5`)不在本节重复列出**:9 套风格各自的 5 色由单源 `styleDataColors` / `styleDataColorsDark` 注入 `engine.css` 覆盖块(第 11 节),避免两处维护。
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 10. 为什么是 9 套(风格集的准入门槛)
|
|
319
|
+
|
|
320
|
+
> **风格集刻意保持 9 套**:覆盖 8 个色族(蓝 / 藏青 / 蓝青深色 / 黑白 / 红 / 金棕 / 墨绿 / 紫)+ 1 个彩色数据板,任意组合已足够。
|
|
321
|
+
> **每多一套风格的真实成本**:单源 5 张表(`styles` / `stylesDark` / `styleAccents` / `styleDataColors` / `styleDataColorsDark`)× 亮暗 + `engine.css` 4 个块 + `ui.js` 色板 + 画廊卡片 + 参考图重生成 + 审计与回归全跑一遍。**选项冗余不是免费的。**
|
|
322
|
+
|
|
323
|
+
**新增一套风格的门槛(三条全满足才加)**:
|
|
324
|
+
|
|
325
|
+
1. **新色族**——引入现有 8 族之外的色相族,而不是同族换明度 / 换名;
|
|
326
|
+
2. **新语汇**——带来新的字体搭配(衬线 / 等宽)或新的圆角、阴影语汇;
|
|
327
|
+
3. **场景缺口**——现有 9 套无法覆盖的真实场景,且能给出反例。
|
|
328
|
+
|
|
329
|
+
> **反面教材**:同色族换名的风格(曾扩到 18 套后删回 9 套)——选项冗余有真实成本。新增门槛见 §10。
|
|
330
|
+
> 这 9 套与前 9 套**同色族换名**(蓝 / 红 / 绿青 / 金棕 / 无彩各多一份),既未引入新色族,也未引入新语汇 → 属于"看上去有用、实际低价值"的选项冗余。
|
|
331
|
+
> 需要"政企庄重 / 东方雅致 / 环保自然"等气质时,用现有 9 套的**组合**近似:`brand-red`(宋体标题)→ 政企庄重;`mckinsey` / `warm-sand`(衬线标题)→ 东方雅致 / 编辑感;`deep-teal` → ESG / 可持续。
|
|
332
|
+
|
|
333
|
+
**配色纪律不变**:除 `spectrum` 外每套**只有一个强调色**,层次靠表面明度差 + 1px 边框;`styleAccents` 收录各套 light/dark 强调色(含派生 hover/active 色),供 `validate_report.py` 做「单一强调色」检查。
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 11. 编码色板(每套风格各 5 色 · 数据专用)
|
|
338
|
+
|
|
339
|
+
> **9 套 ≠ 9 种皮肤而已**:每套风格都带自己的**编码色板 `c1–c5`**,用于多系列图表(多段环形 / 分组柱 / 多折线 / 散点分组 / 桑基流带 / 马赛克段)。这样"数据密集报告"在任何风格下都能出彩色系列,而**结构色仍保持单一强调色**。
|
|
340
|
+
|
|
341
|
+
| 项 | 说明 |
|
|
342
|
+
|----|------|
|
|
343
|
+
| 单源 | `scripts/layout-constants.json` 的 `styleDataColors`(light)/ `styleDataColorsDark`(dark),各 9 套 × 5 色 |
|
|
344
|
+
| HTML 消费 | `engine.css` 的 `html[data-style="X"]{--c1..--c5}` 覆盖块 → 语义类 `.f-c1~c5` / `.s-c1~c5`(由 `sync_runtime.py` 注入模板) |
|
|
345
|
+
| PPTX 消费 | `build_pptx.js` / `pptx-export.js` 的 `dataColors(style, theme)`(按 `model.theme` 选 light/dark 表) |
|
|
346
|
+
| 生成规则 | `c1` = 该风格强调色;`c2`/`c3` = 近似色(±32°/±38°);`c4`/`c5` = 降饱和补色(168°/205°,饱和度 ×0.6) |
|
|
347
|
+
| 硬约束 | 每色对所在主题 `bg` 对比度 ≥ 3.0;同套内两两色相差 ≥25° 或明度差 ≥0.12(`audit_styles.py` 逐值校验) |
|
|
348
|
+
| 色值格式 | **一律裸 hex(6 位、不带 `#`)**,与 `styles` / `stylesDark` / `styleAccents` 同口径;`#` 前缀会原样流入 PPTX 的 `<a:srgbClr val>` 造成非法色值,`engine.css` 覆盖块与画廊才补 `#`(`audit_styles.py` 校验 + `validate_pptx.py` 的 `INVALID_HEX_COLOR` 硬拦) |
|
|
349
|
+
| 使用边界 | 彩色**只**出现在数据本体(数据系列 / 图例色点 / 小段标签);同屏 ≤5 系列。**状态类表达(好/坏、达标/未达标、涨/跌)不得用红绿**,仍走强调色明度阶梯 |
|
|
350
|
+
|
|
351
|
+
改色值只改 JSON → 跑 `python scripts/sync_runtime.py`(注入 engine.css 消费端已在 JSON 单源内)→ `python scripts/audit_styles.py`。
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## 新增一套风格的步骤
|
|
356
|
+
|
|
357
|
+
> **先过第 10 节的门槛**(新色族 + 新语汇 + 场景缺口,三条全满足)——否则不加。
|
|
358
|
+
|
|
359
|
+
1. 在「快速选型」表加一行(中/英文名 + data-style + 定位 + 适用 + 族)。
|
|
360
|
+
2. 选一个**中性色族**(冷灰/暖灰/纯黑白)+ 一个**强调色**,写 light + dark 两个覆盖块。
|
|
361
|
+
3. 定**风格语汇**(缺一即「只有皮肤没有性格」):字体栈 `--font-body` / `--font-display`、圆角 `--radius`、字阶微调(`--fs-*`)、字距/行高(`--letter-*` / `--lh-*`)、密度(`--gap`)、阴影、必要时 `--link`。
|
|
362
|
+
4. **六处同步**(缺一即漂移):
|
|
363
|
+
- `scripts/layout-constants.json` → `styles`(light 10 字段)+ `stylesDark`(dark 10 字段)+ `styleAccents`(强调色族)+ **`styleIdentity`(语汇清单)** + **`styleDataColors` / `styleDataColorsDark`(编码色板 c1–c5,见第 11 节)**
|
|
364
|
+
- `assets/templates/engine.css` → `html[data-style="X"]{…}` + `html[data-style="X"][data-theme="dark"]{…}` + **编码色板两个覆盖块(`--c1..--c5`)**——语汇 token 必须落在 light 块
|
|
365
|
+
- `assets/templates/ui.js` → `var STYLES` 数组加一项(`['id','中文名','#亮色accent']`)
|
|
366
|
+
- 本文件速查表 + 各节 CSS(语汇与 engine 逐字一致)+ 第 11 节编码色板表
|
|
367
|
+
- `assets/style-gallery.html` 画廊 `STYLE_META` 描述行(`pfontBody`/`pfontDisplay`/`prad`/`pscale`/`peye`/`plh`/`pgap`/`pw`/`pletter`;配色由注入的 `PRESETS` 自动派生)
|
|
368
|
+
- `references/design-system.md` 字体决策矩阵(若引入新字体语汇)
|
|
369
|
+
5. 跑 `python scripts/sync_runtime.py`(注入到三模板与画廊)→ `python scripts/audit_styles.py`(**9 套** × light/dark × 8 组 WCAG + 双源色 token + 编码色板 + ui.js 色板 + **风格语汇 styleIdentity**,全过才通过)→ `python scripts/build_examples.py` → `python scripts/regression.py`。
|
|
370
|
+
6. 可选:`node scripts/capture_theme_overview.js`(需 playwright)重生成 `assets/theme-overview*.png` 参考图。
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# TopPPT HTML 总体技术方案
|
|
2
|
+
|
|
3
|
+
> 本文是**总体技术方案**(架构 / 双单源 / 双通道 / 门禁 / 深度模式 / 工作流 / 演进)。
|
|
4
|
+
> 生成报告前不必读本文;**改动架构、导出机制、常量或校验体系前必读**。
|
|
5
|
+
|
|
6
|
+
## 一、一句话架构
|
|
7
|
+
|
|
8
|
+
**一套内容模型,两种交付形态,双单源,双通道,按需深度模式。**
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
用户意图 ──六项问询──> 模式 × 风格 × 亮暗主题 × 篇幅 × 交付格式
|
|
12
|
+
│
|
|
13
|
+
▼
|
|
14
|
+
内容架构(outline-design.md)
|
|
15
|
+
│
|
|
16
|
+
▼
|
|
17
|
+
scaffold_report.py 出骨架(data-skel / layoutPreset)
|
|
18
|
+
→ 只填 window.REPORT_MODEL(纯文本,[n] 引用)
|
|
19
|
+
→ render_from_model.py --inplace 回填 HTML(模型单写路径)
|
|
20
|
+
│
|
|
21
|
+
┌─────────────────┴──────────────────┐
|
|
22
|
+
HTML(阅读/演示) PPTX(精导)
|
|
23
|
+
validate_report --strict extract_model → build_pptx
|
|
24
|
+
LAYOUT_* / qualityGates → validate_pptx --strict
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 二、双单源(唯一事实源)
|
|
28
|
+
|
|
29
|
+
| 单源 | 内容 | 消费方 |
|
|
30
|
+
|------|------|--------|
|
|
31
|
+
| `scripts/layout-constants.json` | 页面几何 `page` / **12 列网格 `grid`** / **语义字阶 `typography` C0–T14** / 三模式比例尺 `typeScale`+`modeTypeScale` / 页型几何 `pageTypes`+`pageTypeGeometry` / **9 风格 token `styles`+`stylesDark`+`styleAccents`** / **编码色板 `styleDataColors`+`styleDataColorsDark`(9 套 × 亮暗 × c1–c5)** / **图表登记四元组 `charts.registry`** / 图表最小尺寸 `charts.minSize` / **图表多样性预算 `charts.variety`** / **容器内边距 `containers`** / **锚点容差 `anchorTolerance`** / **图片准入门 `imageAdmission`** / **图片规格 `imageSpec`**(版式 `layouts` / 比例 `ratioDefault`+`ratioCssClass` / 建议尺寸 / 占位标签 / 体积上限) / **深度模式 `deepMode`** / 校验预算 `checkBudgets` / 强调带 `emphasis` / 待核实 `annotations` / 去AI味词 `aiFlavor` / **内容级质量 `contentQuality`**(版式节奏 / so-what 实质 / research 标题判断) | `build_pptx.js`(require)、`pptx-export.js`(注入常量块)、三模板、`style-gallery.html`、`validate_report.py`、`validate_pptx.py`、`audit_styles.py`、`audit_skill.py`、`prepare_images.py`、`evals/run_evals.py` |
|
|
32
|
+
| `scripts/model-schema.json` | 29 种页型的字段与必填约束 / **图表类型白名单 `chartTypes`(30 类:16 原生 + 14 形状)** / **数据表策略 `chartDataTable`** / 通用可选字段 `commonSectionFields` | `extract_model.py`(本地校验)、`pptx-export.js`(浏览器端 `validateModel`) |
|
|
33
|
+
| `scripts/layout_slots.json` | **页型布局 IR(29 页型全量)**:语义槽位(head/primary/secondary/annotation + required)——双通道按同一槽位语义落位 | `sync_runtime.py`(完整性校验);`lib_layout_regions.js`(槽位→英寸矩形);`extract_snippet.py --page-type` |
|
|
34
|
+
| 交付一键 | `quality_gate.py` | `validate_report --strict` + 可选 `validate_pptx` + `evals --score` + **rubric 启发式五维**(content/layout/chart/infographic/tone) |
|
|
35
|
+
|
|
36
|
+
**纪律**:改常量只改 JSON,改 schema 只改 schema JSON,然后跑 `python scripts/sync_runtime.py`(注入 + 完整性校验 + 哈希摘要)。**禁止手改** `pptx-export.js` / 三模板 / `style-gallery.html` 的标记块。
|
|
37
|
+
|
|
38
|
+
**`sync_runtime.py` 的完整性校验**(任一不过即 PASS→WARN):
|
|
39
|
+
1. 双端引用(`build_pptx.js` require 常量;`extract_model.py` 读 schema)
|
|
40
|
+
2. **页型四件套**:每个 schema 页型都有 `pageTypeGeometry` 几何映射
|
|
41
|
+
3. **图表登记四元组**:`charts.types` ↔ `charts.registry` 双向一致;`pptx` 通道合法;非原生图表 `dataTable` 不得为 off(登记表自身声明 off 的装饰微图豁免);`schema.chartTypes` 是 registry 子集
|
|
42
|
+
4. **图表类型可达性不变量**:`registry.types == chartTypes ∪ 信息图专属页型`——每个登记类型都必须能由模型表达(作 `chart.type` 或作 `sections[].type`),否则双引擎实现沦为死代码(该不变量正是为拦住「登记 36 类但模型只能表达 16 类」这类漂移而加);信息图页型清单亦单源于 `charts.scaffold.infoTypes`
|
|
43
|
+
5. **页型实现可达性(冒烟)**:schema 每个页型都应出现在 `build_pptx.js` 与 `pptx-export.js` 源码中(子串级,拦「schema 加了页型、引擎没实现」)
|
|
44
|
+
6. **骨架尺寸单源不变量**:`charts.scaffold`(scaffold_report.py 骨架尺寸唯一事实源)键 ⊆ registry,且默认值 ≥ `charts.minSize` 同口径阈值——拦「脚本硬编码第二源漂移」
|
|
45
|
+
7. **语义字阶**:每个 level 的 `role` 在 `modeTypeScale` 中存在
|
|
46
|
+
8. **页型布局 IR**:`layout_slots.json` 每个页型在 schema 中存在,且含 head + primary 槽位
|
|
47
|
+
|
|
48
|
+
> **图表计数的两种口径**(同一事实的两种切法,勿混用):`registry` 视角 **36 = 16 原生 + 20 形状**(SKILL.md 铁律 9 用此口径);`chartTypes` 视角 **30 = 16 原生 + 14 形状**(可作 `chart.type` 的形状类,`pptx-export.md` 页型表用此口径)——差额 6 类是信息图专属页型(sankey/treemap/boxplot/network/marimekko/streamgraph),它们只作 `sections[].type`,不作 `chart.type`。
|
|
49
|
+
|
|
50
|
+
## 三、双通道(A 预览 / B 交付)
|
|
51
|
+
|
|
52
|
+
| | A 通道(`assets/pptx-export.js`) | B 通道(`scripts/build_pptx.js`) |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| 角色 | 页面「预览 PPTX」WYSIWYG + 回归双裁判 | **唯一交付通道** |
|
|
55
|
+
| 输出 | 手写 OOXML 形状/文本框/表格(零依赖,约 120KB) | pptxgenjs → 原生形状 + **原生数据图表**(chart part + 内嵌 Excel) |
|
|
56
|
+
| 图表 | 全部类型做**形状近似**(类别标签与数值都落为文本) | 原生通道走 `addChart`;形状通道走高保真形状还原 + 数据表;**已登记类型禁止静默回落**(`SHAPE_RENDERER_MISSING` / 原生调用失败即非 0) |
|
|
57
|
+
| 一致性 | 与 B 通道**逐页文本集合一致**(`cross_verify.py` 用 python-pptx 第三方裁判核对) | 同左 |
|
|
58
|
+
|
|
59
|
+
**为什么手写序列化而不内嵌 pptxgenjs**:pptxgenjs 浏览器版约 700KB,内嵌进每份单文件报告不可接受;手写运行时约 120KB 且与 B 通道消费同一份常量单源。**复用的是引擎与规范,自研的只是轻量序列化轮毂**。
|
|
60
|
+
|
|
61
|
+
**`cross_verify.py` 归一化三件事**(新增图表类型时必须同步扩展,否则误报):
|
|
62
|
+
1. B 端 chart part 的 `plots[0].categories` 并入文本集
|
|
63
|
+
2. `NUMERIC_TOKEN` 纯数值 token(含枚举单位)两端对称过滤
|
|
64
|
+
3. `sorted(set(...))` 集合语义去重
|
|
65
|
+
|
|
66
|
+
## 四、门禁体系(分层)
|
|
67
|
+
|
|
68
|
+
| 层 | 工具 | 通过标准 |
|
|
69
|
+
|----|------|---------|
|
|
70
|
+
| HTML | `validate_report.py` | 全 PASS(模式预算 + 页高溢出估算 + 模型一致性 + 图表数据表策略 + **图表多样性(类型数下限 / 不连续同型)** + **组合版式比例(research)** + **内容级质量(版式节奏连用 / so-what 实质 / research 标题含判断)** + 页型↔版式对应 + 锚点闭环 + 图表登记与最小尺寸 + Exhibit 连续性 + 强调带/待核实/**素材图片与配图占位**(零外链·alt·版式与比例锁定类对应·占位可见标签·内联体积)+ 预览配套断言) |
|
|
71
|
+
| PPTX(交付基线) | `validate_pptx.py --strict --model=` | 0 errors / 0 warnings:模型往返保真 + 按类型原生图表断言 + 数据表落位 + 容器级溢出 + 表格语义字号与密度 + 越界/文本溢出/字号下限/未声明图片 + **图片版式·裁切·多图数量·相对路径文件存在性** |
|
|
72
|
+
| PPTX(深度模式) | 加 `--deep` | 再把**连续文本流**与**空间锚点**纳入 strict |
|
|
73
|
+
| 双裁判 | `cross_verify.py`(python-pptx) | A/B 产物均可严格解析 + 逐页文本一致 + 溢出启发式 |
|
|
74
|
+
| 素材图片 | `probe_image_export.py` | 真实位图 build→strict 0/0 且 `pictures == 声明数`(示例矩阵刻意零图片,真实素材路径/版式/门禁靠它覆盖) |
|
|
75
|
+
| 风格与单源 | `audit_styles.py` | 9 风格 × light/dark × 8 组 WCAG 配对 + engine.css ↔ JSON 双源逐字段一致 + **编码色板 9×2×5(双源 + 对 bg 对比 ≥3.0 + 同套两两可区分)** + ui.js 色板一致 + 单源完整性 |
|
|
76
|
+
| 技能工程 | `audit_skill.py` | 体积预算(SKILL.md ≤13KB / L1 playbook / 单份 reference / 模板)+ description 软硬上限 + **三档披露(L0/L1/L2)** + **Gate 0 位于六项问询之前** + 交互轮次与必读文件预算声明 + 引用完整性 + **内容重复(SKILL.md↔references 归一化滑窗 ≥20 字含 CJK)** |
|
|
77
|
+
| 文档一致性 | `audit_docs.py` | § 引用可解析(含大写后缀)+ 文件前缀规范 + §46 覆盖 36 图表/29 页型 + 图表代码节齐备 + 元数据与必需文件 + **任务路由可解析(TASK_ROUTES 每条实际抽取)** |
|
|
78
|
+
| CSS 覆盖率 | `audit_css.py` | engine.css 选择器类 ↔ 消费方语料(剔除注入镜像);**报告制**(列出疑似死类,不设门禁) |
|
|
79
|
+
| 单源注入 | `sync_runtime.py` | 注入成功 + 完整性校验(①–⑪:双端引用 / 页型四件套 / 图表登记四元组 / 可达性 / 实现冒烟 / **骨架尺寸单源 7d** / 语义字阶 / 布局 IR / **版本一致性**)PASS + 哈希摘要一致 |
|
|
80
|
+
| 反向验证 | `negative_tests.py` | 14 例故障注入(编号/引用/备注/数值/标题/字号/登记/多样性/外链/tbd 图例/主题与模式矛盾/锚点)→ 校验器必须报错 |
|
|
81
|
+
| Eval(四类目标) | `evals/run_evals.py` | 结果(零外链 / strict 0/0 / 模型一致)+ 风格(图表多样性 / 组合版式 / 结构图形)+ 过程(Gate 0)+ 效率(轮次 ≤3 / 工具调用 ≤25 / 读取 ≤40KB);定性部分用 `evals/rubric.schema.json` |
|
|
82
|
+
| 全链路 | `regression.py` | 以上全部 + 9 示例端到端 + **任务路由全量遍历**(与 audit_docs ⑥ 共用 `verify_routes`) |
|
|
83
|
+
|
|
84
|
+
## 五、按需深度模式
|
|
85
|
+
|
|
86
|
+
**触发**:用户明示「高保真 / 1:1 / 精确还原 / 正式交付…」(`deepMode.triggers`)或页面含复杂信息图(`deepMode.complexCharts`)。
|
|
87
|
+
|
|
88
|
+
**多做的三件事**:
|
|
89
|
+
1. `validate_pptx.py --strict --deep` → 连续文本流 + 空间锚点(页头标题对齐版心左边界,容差 `anchorTolerance.keyPx`)纳入 strict
|
|
90
|
+
2. `--emit-manifest=<path>` → 机器可验证的 manifest(锚点注册 / 容器清单 / 数据表清单 / 图表通道清单 / 图片资产登记 / 门禁计数)
|
|
91
|
+
3. `render_compare.py` → 渲染对照材料(PPTX→PDF→位图 + HTML/PPTX 并排对照页 + 自动偏差登记),**缺依赖自动跳过**
|
|
92
|
+
|
|
93
|
+
**明确不引入**:SHA-256 冻结签名、逐页人工验收确认、ImageGen 逐页蓝图、PowerPoint COM 硬门禁(详见 `high-fidelity.md` §八)。
|
|
94
|
+
|
|
95
|
+
## 六、工作流
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
听意图 → Gate 0 先给参考图(theme-overview*.png)
|
|
99
|
+
→ 六项问询一次收集(形式参数:模式/篇幅/风格/主题/交付格式/参考图)
|
|
100
|
+
→ 按路径分流:轻量路径(1 张规划卡)/ 完整路径(内容架构七步法 + 按需大纲确认)
|
|
101
|
+
→ scaffold_report.py 起骨架(锁模式/风格/主题 + 预生成 REPORT_MODEL,不读模板全文)
|
|
102
|
+
→ 照规划卡填内容(每页 = 主件 + 从件 + 注释层)→ 自校验自修复 → 交付
|
|
103
|
+
→ [深度模式] --deep --emit-manifest + render_compare
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**效率预算(硬)**:交互轮次 ≤3;必读 = `SKILL.md`(L0)+ `references/playbook.md`(L1)共 2 份;L2 深度文件按需读、读完即停。
|
|
107
|
+
**断点可恢复**:`REPORT_MODEL` 即恢复锚点——上下文中断后重跑 `extract_model.py` → `build_pptx.js` 即恢复,无需重新生成内容。
|
|
108
|
+
|
|
109
|
+
## 七、发布态与兼容
|
|
110
|
+
|
|
111
|
+
- **发布版**:**v0.1**(布局语法 + 模型单写 + 硬门禁 + 风格语汇层)。**版本唯一事实源 = `layout-constants.json` `version`**;`model-schema.json` / `layoutSlots` 同步该值、技能 `package.json` 为 `0.1.x`;`sync_runtime.py` 校验一致。变更流水见仓库根 `CHANGELOG.md`。
|
|
112
|
+
- **兼容回落**:排版比例尺只有 `modeTypeScale` 一套;未知模式回落 `presentation` 档。环境变量 `TOP_PPT_NODE_EXE` / `TOP_PPT_NODE_PATH`(旧名已移除)。
|
|
113
|
+
- **文档分工**:本文件管架构与机制;日常规范见 `references/*`,业界对标依据见 `industry-benchmark.md`。
|
|
114
|
+
|
|
115
|
+
## 八、目录职责
|
|
116
|
+
|
|
117
|
+
| 路径 | 职责 |
|
|
118
|
+
|------|------|
|
|
119
|
+
| `SKILL.md` | **L0** 路由与门禁:触发边界、**Gate 0 参考图先行**、三模式速选、六项问询、两条路径、**12 条铁律**、阶段路由(L0/L1/L2)、效率预算 |
|
|
120
|
+
| `references/playbook.md` | **L1 唯一常读入口(决策层)**:三模式契约、两条路径、页型选型、**组合版式矩阵**、**图表选型决策树**、内容规则 Top-12、信息图页型族、配色与主题、校验命令 |
|
|
121
|
+
| `references/modes.md` | 三模式密度契约与锁定版式(L2:定模式细节时读) |
|
|
122
|
+
| `references/outline-design.md` | 内容架构七步法 + 跨页叙事节奏 + 细节保全 |
|
|
123
|
+
| `references/design-system.md` | MD3 对齐、设计原理(CRAP/7:2:1/字体矩阵)、页高模型、12 列网格、语义字阶、SVG 语义类(生成时主读) |
|
|
124
|
+
| `references/design-system-engine.md` | 顶栏/卡片/列表/表格/页脚/动效等 CSS 类实现目录(维护者;生成时勿读) |
|
|
125
|
+
| `references/styles.md` | 9 套风格定义与选型 |
|
|
126
|
+
| `references/content-rules.md` | 页内写作规则、密度三档、表格语义字号、容器内边距、连续文本流 |
|
|
127
|
+
| `references/components.md` | 结构组件与锁定版式(`components.md` §1–§15c、§32–§50)+ 版式选型表 + **组合版式矩阵(§46c)** |
|
|
128
|
+
| `references/charts.md` | 图表全库(`charts.md` §16–§31、§29b、§35、§52–§70)+ **误用反例与多样性纪律(§66)** |
|
|
129
|
+
| `references/infographics.md` | 信息图铁律与边界(逻辑入口);代码在 `infographics-stats.md` / `infographics-structure.md` |
|
|
130
|
+
| `references/icons.md` | 内联 SVG 图标库与使用准则 |
|
|
131
|
+
| `references/pptx-export.md` | PPTX 导出通道、模型字段、双单源、29 页型、图表双通道 |
|
|
132
|
+
| `references/high-fidelity.md` | 按需深度模式规范(触发、容差、manifest、渲染对照) |
|
|
133
|
+
| `references/failure-modes.md` | 十四类失败模式 + 修复顺序铁律 + 错误解释纠正表 |
|
|
134
|
+
| `references/industry-benchmark.md` | 业界对标与采纳/不采纳决策依据 |
|
|
135
|
+
| `scripts/*` | 校验器、**骨架生成器 `scaffold_report.py`**、注入器、回归、**三项审计(styles / docs / skill)**、打包(全部标准库;PPTX 精导需 Node + pptxgenjs) |
|
|
136
|
+
| `evals/*` | Eval 框架:`prompts.csv`(14 条,含负对照)+ `rubric.schema.json`(风格目标评分契约)+ `run_evals.py`(结果/过程/风格/效率四类目标) |
|
|
137
|
+
| `assets/templates/*` | 三模式模板 + 公共引擎/UI(标记块由 `sync_runtime.py` 注入) |
|
|
138
|
+
| `assets/examples/*` | 示例矩阵(含信息图页型与原生图表技巧) |
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""TopPPT HTML · CSS 类覆盖率审计(engine.css ↔ 消费方语料 · 零依赖 · 报告制)
|
|
4
|
+
|
|
5
|
+
用法:
|
|
6
|
+
python scripts/audit_css.py # 输出未引用类清单与占比(仅报告,不影响退出码)
|
|
7
|
+
python scripts/audit_css.py --json # 机器可读
|
|
8
|
+
|
|
9
|
+
为什么需要它:
|
|
10
|
+
engine.css(≈53KB)是三模板与全部交付报告的样式单源。新增版式/组件后旧类
|
|
11
|
+
可能不再被任何模板、示例或运行时引用——这类「视觉债」此前无任何工具度量。
|
|
12
|
+
本脚本做**报告制**审计(不设门禁):列出疑似未引用类,供维护者决策
|
|
13
|
+
「删除 / 保留(如为未来预留)/ 标注豁免」。
|
|
14
|
+
|
|
15
|
+
口径(刻意宽松,宁可漏报不可误报):
|
|
16
|
+
· 类「已使用」= 类名以子串形式出现在任一消费方文本中(模板/示例/运行时 JS/画廊/
|
|
17
|
+
build_examples 内容包)——JS 动态拼接的类名片段也能命中
|
|
18
|
+
· engine.css 侧只统计**选择器位置的类**(块内属性值如 `.5em` 不算;类名以字母开头)
|
|
19
|
+
· 明确豁免:engine.css 自身注释中提到的类、以 `--` 开头的 CSS 变量名(非类)
|
|
20
|
+
|
|
21
|
+
何时跑:删除/新增 engine.css 规则、清理模板示例之后(与 audit_styles 互补——
|
|
22
|
+
后者管 token 双源一致性,本工具管选择器死活)。
|
|
23
|
+
"""
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import json
|
|
27
|
+
import re
|
|
28
|
+
import sys
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
33
|
+
except Exception:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
37
|
+
ENGINE = ROOT / 'assets' / 'templates' / 'engine.css'
|
|
38
|
+
|
|
39
|
+
# 消费方语料(模板含 engine.css 注入副本,组装时剔除 __TOPPPT_ENGINE__ 镜像块防自命中)
|
|
40
|
+
# references/*.md 计入消费方:其中的代码配方是交付报告类名的合法来源(智能体照文档写报告)
|
|
41
|
+
CONSUMERS = (
|
|
42
|
+
list((ROOT / 'assets' / 'templates').glob('*.html'))
|
|
43
|
+
+ list((ROOT / 'assets' / 'examples').glob('*.html'))
|
|
44
|
+
+ [ROOT / 'assets' / 'pptx-export.js', ROOT / 'assets' / 'style-gallery.html',
|
|
45
|
+
ROOT / 'assets' / 'templates' / 'ui.js']
|
|
46
|
+
+ [ROOT / 'scripts' / 'build_examples.py', ROOT / 'scripts' / 'build_pptx.js',
|
|
47
|
+
ROOT / 'scripts' / 'scaffold_report.py']
|
|
48
|
+
+ sorted((ROOT / 'references').glob('*.md'))
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
SELECTOR_CLASS = re.compile(r'\.([a-zA-Z][-\w]*)')
|
|
52
|
+
# 模板/示例内嵌的 engine.css 注入镜像块——语料必须剔除,否则所有类名自命中、审计恒空
|
|
53
|
+
_ENGINE_MIRROR = re.compile(r'/\* __TOPPPT_ENGINE_START__ \*/[\s\S]*?/\* __TOPPPT_ENGINE_END__ \*/')
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def strip_engine_mirror(text: str) -> str:
|
|
57
|
+
return _ENGINE_MIRROR.sub('', text)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def strip_blocks(css: str) -> str:
|
|
61
|
+
"""去掉 {...} 声明块,只留选择器区(注释一并去掉;块替换为空格防相邻选择器拼接)。"""
|
|
62
|
+
css = re.sub(r'/\*[\s\S]*?\*/', '', css)
|
|
63
|
+
# 循环剥嵌套块(@media 外层块的声明块在首轮被替换后,外层变空壳再剥一次)
|
|
64
|
+
for _ in range(3):
|
|
65
|
+
new = re.sub(r'\{[^{}]*\}', ' ', css)
|
|
66
|
+
if new == css:
|
|
67
|
+
break
|
|
68
|
+
css = new
|
|
69
|
+
return css
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main() -> int:
|
|
73
|
+
if not ENGINE.exists():
|
|
74
|
+
print('错误: 缺 assets/templates/engine.css')
|
|
75
|
+
return 2
|
|
76
|
+
|
|
77
|
+
selector_zone = strip_blocks(ENGINE.read_text(encoding='utf-8'))
|
|
78
|
+
classes: list[str] = sorted(set(SELECTOR_CLASS.findall(selector_zone)))
|
|
79
|
+
|
|
80
|
+
corpus = '\n'.join(
|
|
81
|
+
strip_engine_mirror(p.read_text(encoding='utf-8'))
|
|
82
|
+
for p in CONSUMERS if p and p.exists())
|
|
83
|
+
|
|
84
|
+
unused = [c for c in classes if c not in corpus]
|
|
85
|
+
used = len(classes) - len(unused)
|
|
86
|
+
|
|
87
|
+
if '--json' in sys.argv[1:]:
|
|
88
|
+
print(json.dumps({'total': len(classes), 'used': used,
|
|
89
|
+
'unused': unused,
|
|
90
|
+
'coverage': round(used / len(classes), 4) if classes else 1.0},
|
|
91
|
+
ensure_ascii=False, indent=2))
|
|
92
|
+
return 0
|
|
93
|
+
|
|
94
|
+
print('CSS 类覆盖率审计 · engine.css(报告制 · 不设门禁)')
|
|
95
|
+
print('-' * 56)
|
|
96
|
+
print(f' 选择器类总数:{len(classes)} · 被消费方引用:{used}'
|
|
97
|
+
f'(覆盖率 {used / max(1, len(classes)):.0%})')
|
|
98
|
+
if unused:
|
|
99
|
+
print(f' 疑似未引用({len(unused)} 个,请逐个判断 删除/保留/豁免):')
|
|
100
|
+
for c in unused:
|
|
101
|
+
print(f' · .{c}')
|
|
102
|
+
print(' 注意:JS 变量拼接类名的极端形态可能漏判,删除前先全局搜一遍。')
|
|
103
|
+
else:
|
|
104
|
+
print(' 未发现未引用类。')
|
|
105
|
+
return 0
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if __name__ == '__main__':
|
|
109
|
+
sys.exit(main())
|