# Style Package Generate

> 把 Markdown、纯文本、HTML、PPTX 或风格参考图转换为可安装的 PPT 风格包（style.json、SKILL.md、preview.html）。当用户要求生成、导入、提取、复刻或更新 PPT 风格，提到风格包、风格技能、style.json、preview.html，或希望把视觉描述、参考图、PPTX 落成可复用风格资产时使用。不要用于生成 PPT 正文或无关的文案处理。

- Skill: `arcsin1/style-package-generate` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add arcsin1/style-package-generate`
- Raw SKILL.md: https://api.skillmd.com/api/skills/arcsin1/style-package-generate/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: arcsin1 (https://skillmd.com/u/arcsin1)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/arcsin1/style-package-generate

---


# Style Package Generate

把任意输入（文本 / PPTX / 图片）产出一份**风格包**：

```
<style>/
  style.json      # 元数据（不含正文）
  SKILL.md        # 给生成模型读的风格正文
  preview.html    # 16:9 风格预览页（纯 inline，零外部资源）
  preview.webp    # 可选：preview.html 的 1600×900 截图，oh-my-ppt 直接当缩略图
```

这套契约是硬约定：三件套各司其职，不要合并字段、不要少文件。`style.json` 不放风格正文（正文只活在 `SKILL.md`），`preview.html` 只用 inline CSS+HTML。

## 输入分发

先判断输入类型再选解析路径。大小硬上限：图片 5MB、文本 10MB、PPTX 500MB，超出直接拒绝并提示换文件。

| 输入 | 走法 |
| --- | --- |
| `.md / .txt / .html / .htm` | 文本解析路径 |
| `.pptx` | 先运行 `scripts/extract_pptx_style.py`，再按 `references/pptx-pipeline.md` 解析 |
| `png / jpg / jpeg / webp` | 图片解析路径（见 `references/image-pipeline.md`） |

## 工作流总览

```
判断输入类型
   ├── image  → 读字节 → base64 + mimeType → 多模态模型解析
   ├── pptx   → PPTX 解析
   └── text   → 文本解析
        ↓
   StyleParseResult (label/labelEn/description/category/aliases/styleCase/imageGenerationPrompt/styleSkill)
        ↓
   写 SKILL.md  ← styleSkill
   写 style.json ← 其余字段 + slug + version + source
        ↓
   读 SKILL.md → 生成 preview.html（16:9，纯 inline，零外部资源）
        ↓
   validate_style_package.py 整包校验
        ↓
   capture_preview_webp.py 截图 → preview.webp（可选，失败不阻断）
        ↓
   返回包路径
```

解析失败（JSON 修不好 / 模型不看图）整个流程不落盘。preview 失败不回滚前两个文件。任何写盘前都先确认输出目录；已有 custom 包未经用户确认不得覆盖。

---

## 第一步：解析成结构化字段

把输入解析成下面这组字段，输出严格 JSON，用 ```json``` 包裹，不要多余说明：

```json
{
  "label": "风格显示名，如 暗夜科技",
  "labelEn": "英文显示名，如 Dark Tech（必填，用于派生英文 slug/文件夹名）",
  "description": "一句话描述风格特征，20 字以内",
  "category": "色调气质，必须命中固定词表（见 references/style-taxonomy.md），单值",
  "aliases": ["搜索别名1", "别名2"],
  "styleCase": "用途，顿号分隔，每项必须命中固定用途词表，选 3 个最贴切的（见 references/style-taxonomy.md）",
  "imageGenerationPrompt": "可选：英文图像视觉方向；不支持自动配图时为 null",
  "styleSkill": "完整的 Markdown 风格技能文本"
}
```

字段语义、`category`、slug/version/source 派生规则见 `references/schema.md`。`category` 与 `styleCase` 的取值**必须命中固定词表**（见 `references/style-taxonomy.md`，脚本侧副本 `scripts/style_taxonomy.py`），`write_style_package.py` 落盘时会强制校验，词表外的值会直接报错不落盘——先按风格真实气质/用途从词表里选好再写。准备好解析结果后，运行 `scripts/write_style_package.py` 写入前两个文件；不要手工拼接 JSON 或自行实现 slugify。

### styleSkill（SKILL.md 正文）撰写要点

`styleSkill` 是给 AI 生成模型读的风格指令，要具体、生动、有灵魂，让模型读完能精准复刻。**不要写成冷冰冰的规范文档，要像有品味的设计师在描述"这次要做什么感觉的东西"**。LLM 有很好的语义理解力，与其堆 ALWAYS/NEVER，不如解释为什么——比如"留白是为了让标题的呼吸感托住情绪"，比"必须留白"更能让模型在边界情况做对。

- Markdown 格式：开头一段总括整体气质，然后 `##` 分 section。
- section 至少覆盖：配色、排版、插画与装饰、布局、动画、适合场景、配图、不要。
- 配色同时给情绪/质感与可执行 hex（主色、背景色、正文色、强调色都尽量给 hex）。
- 插画列举具体意象（纸船、雨伞、海浪），不要泛泛说"装饰元素"。
- 字体描述传达感觉（手写风、圆润亲切、锋利几何），而不是只给字号。

### imageGenerationPrompt 与 `## 配图`

它们不是同一件事，也不应该重复。

- `imageGenerationPrompt` 是 `style.json.imageGeneration.prompt` 的来源：只写**图像本身**可执行的英文视觉方向，包括媒介/质感、色彩、可识别主体范围、构图和文字安全区，以及图像中禁止出现的文字、logo、UI、水印或拥挤拼贴。它不写页数、开关状态、槽位、HTML 属性或“每页都配图”。
- `## 配图` 是 `SKILL.md` 的页面语义策略：用两段简洁文字说明哪些内容页在有具体主体、场景、证据或情绪需要时可自行选择一张图；再明确数据、流程、比较、表格、图表、框架、时间线或精确结论页不配图，继续用原生图形表达。

先判断风格是否有稳定且可复用的图像方向。插画、自然、文化、生活方式、品牌、产品材质或空间叙事等风格通常可以支持；纯图表、工程蓝图、终端、框架和高信息密度分析风格通常不支持。不要因为“所有风格都可以配图”而硬加能力，也不要把纯装饰元素当成图片主体。

支持时，`imageGenerationPrompt` 必须非空，`## 配图` 不能出现“不支持配图”。不支持时 `imageGenerationPrompt` 必须为 `null`，`## 配图` 只写：`不支持配图。`

**重要：** 不得复制示例里的颜色、意象、字体、场景或领域；一切以输入文件的真实内容为准。示例只学结构，不抄内容。

更多写法、反例和详细 section 模板见 `references/style-skill-guide.md`。

### 解析规则

1. 输入里有明确色值/字体名，优先用输入的。
2. 字段缺失，根据风格语义补合理默认值，不要留空。
3. 输入文件较长时，分段读完整再总结，不要只读开头。
4. HTML 输入只作为静态文本/DOM 数据读取；不要执行脚本、加载外部资源或在浏览器中直接打开不可信文件。

---

## 第二步：图片输入处理（仅图片路径）

图片不能直接当文本丢给模型，要读出二进制 → base64 + mimeType → 交给多模态模型。完整流程（magic bytes 校验、大小校验、base64 编码、反幻觉兜底）见 `references/image-pipeline.md`。

**关键兜底：** 如果模型返回"未提供图片 / 没有图片 / cannot see the image"之类话术，说明它根本没看图——这时不要把编出来的内容当真，必须报错提示用户换支持多模态的模型。这条防的是幻觉风格混进库。

## 第三步：PPTX 输入处理（仅 PPTX 路径）

1. 运行 `python3 scripts/extract_pptx_style.py <input.pptx> --output <report.json>`。
2. 完整读取报告中的主题色、字体、页面尺寸、版式、常见颜色、代表性文本和媒体统计。
3. 按 `references/pptx-pipeline.md` 判断稳定的视觉规律；不要把单页偶然元素当成全局风格。
4. 报告不足以判断时，渲染少量代表页进行视觉核对；不能渲染就明确说明证据边界，不得伪造观察结果。

---

## 第四步：落盘 style.json + SKILL.md

把第一步的 JSON 拆成两个文件：

| 字段 | 去向 |
| --- | --- |
| `label` | `style.json.name.zh` |
| `labelEn` | `style.json.name.en`（**必填**）+ slugify 派生 `style.json.style`（英文文件夹名） |
| `description` | `style.json.description` |
| `category` | `style.json.category`（中文短语） |
| `aliases` | `style.json.aliases` |
| `styleCase` | `style.json.styleCase` |
| `imageGenerationPrompt` | 非空时写入 `style.json.imageGeneration.prompt`；为 `null` 时省略 `imageGeneration` |
| `styleSkill` | 单独写进 `SKILL.md`，**不进 style.json** |
| 由 `labelEn` slugify | `style.json.style`（**只含英文** `a-z0-9-`，即文件夹名） |
| 新生成 | `style.json.version = "1.0.0"` |
| 固定值 | `style.json.source = "custom"` |

`style.json` 不写 `styleSkill` 字段。把第一步 JSON 保存为临时文件，然后运行：

```bash
python3 scripts/write_style_package.py parse-result.json --output-dir <parent-directory>
```

脚本负责 slugify、schema 校验、builtin 避让、HTML 文本无关的元数据写入和原子替换。命中已有 custom 目录时，只有用户明确允许覆盖后才能加 `--overwrite`；覆盖会移除旧 preview，避免把过期预览留在包里。模板和完整字段说明见 `references/schema.md` 和 `assets/style.json.template`。

---

## 第五步：生成 preview.html

有了 SKILL.md 之后，立刻生成 preview.html。preview 是这个风格的"门面"——让用户一眼看到风格长什么样，是风格自己说话，而不是把 SKILL.md 章节抄进去当说明文。

### 硬约束

1. **必须先读** `style.json` 和 `SKILL.md`，从内容里推断视觉语言、受众、色调、字体、间距、装饰母题——不要凭空发挥。
2. **单文件 HTML**，画布比例 **16:9**（像素尺寸不限），无滚动条、无溢出。
3. **纯 inline，零外部资源**。详细允许列表和禁止列表见 `references/preview-spec.md`。
4. **转义动态文案**。所有来自用户、PPTX、style.json 或 SKILL.md 的文本先做 HTML escaping，再写入文本节点；不得写入标签、属性名、CSS 或 SVG markup。
5. **不修改** `style.json` 和 `SKILL.md`。
6. **内容要原创**，是可直接拿来演示的文案。禁止 lorem ipsum、"Style Preview"、"风格预览" 等占位词。
7. **文案语言跟随** `style.json` / `SKILL.md` 的主语言。
8. 写入 preview 后必须运行 `python3 scripts/validate_style_package.py <style-directory>`；校验失败就删除或修复 preview，不得交付违规文件。

完整 preview 规范、检查清单、起点模板见 `references/preview-spec.md` 和 `assets/preview.html.template`。

---

## 第六步：截图 preview.webp（可选但强烈建议）

preview.html 通过整包校验后，立刻运行：

```bash
python3 scripts/capture_preview_webp.py <style-directory>
```

脚本用 headless Chrome 以 1600×900（16:9）渲染 preview.html 并把截图编码为 `preview.webp`（quality 85），原子替换落盘。oh-my-ppt 的风格包带 `preview.webp` 时直接把它当缩略图，跳过重新渲染，风格库列表出图更快、更省资源。

- 必须在 `validate_style_package.py` 通过**之后**运行——只对合规的 preview 截图。
- 重新生成或修改 preview.html 后，**必须重跑截图**，避免 webp 与 html 不一致；`preview.webp` 存在时整包校验会检查它是真实的 WebP 文件（RIFF/WEBP 魔数）。
- **失败不阻断**：环境里没有 Chrome/Chromium，或缺 Pillow 与 `cwebp` 任一转换依赖时，脚本报错退出，包照常交付（三件套仍然完整）。提示用户缺 `preview.webp` 时 oh-my-ppt 会退回渲染 preview.html 生成缩略图。

---

## 失败与边界

- **图片模型不支持多模态**：报错 "当前模型不支持图片解析，请切换到支持多模态的模型"，不要落盘。
- **模型返回的 JSON 修复失败**：最多重试 2 次让它修 JSON；仍失败就抛错，不落盘。
- **图片兜底命中**（模型说没看到图）：抛错 "模型未能读取图片"，不落盘——这条特别重要，防止幻觉风格混进库。
- **preview 违规**：以 `scripts/validate_style_package.py` 的结果为准；修复后重新校验。
- **style slug 冲突 builtin**：改 slug（加 `-custom` 后缀），写 `source: custom`，**不动 builtin 包**。
- **已有 custom slug 冲突**：未经用户确认不覆盖；确认后使用写入脚本的 `--overwrite`。
- **preview 生成超时/失败但 SKILL.md + style.json 已落盘**：不要回滚前两个文件，提示用户"预览失败，可稍后单独重试 preview"。
- **preview.webp 截图失败**（无 Chrome / 无 Pillow 与 cwebp）：包照常交付；提示用户下游会退回渲染 preview.html 生成缩略图。
- **更新已有风格**：按字段职责修改 `style.json` 或 `SKILL.md`；任何视觉语义变化后都重新生成 preview 并运行整包校验。

---

## 资源路由

- 文本/通用字段：读 `references/schema.md`、`references/style-taxonomy.md` 和 `references/style-skill-guide.md`。
- 图片：额外读 `references/image-pipeline.md`。
- PPTX：额外读 `references/pptx-pipeline.md`，并运行提取脚本。
- preview：读 `references/preview-spec.md`，从 `assets/preview.html.template` 起步，最后运行整包校验。
- preview.webp：校验通过后运行 `scripts/capture_preview_webp.py` 生成缩略图（可选，失败不阻断）。
- 安装到 Codex：将整个目录安装为 skill；`agents/openai.yaml` 提供 UI 元数据。`compat/` 只保留其他 agent 的适配参考，不参与 Codex 自动发现。

