diagram-design 图解导出实战:从自包含 HTML 到 SVG / PNG 的完整流程与源码级原理
【免费下载链接】diagram-design38 editorial diagram types for Claude Code, Codex, and Pi. Self-contained HTML + SVG. No shadows. No Mermaid slop.项目地址: https://gitcode.com/GitHub_Trending/di/diagram-design
本文以 prompts/export-diagram.md 为核心骨架,并以其权威细则 references/export.md 及仓库源码为佐证,系统讲解 diagram-design 的导出链路。
导读
本篇技术指南围绕 diagram-design 项目(一套面向 Claude Code、Codex、Pi 等 AI 编程助手的图解设计技能包)的导出(Export)链路展开,聚焦如何将生成的单文件、自包含 HTML 图解转换为可移植的.svg与.png,用于 Figma、Slides、博客、社交卡片等场景。读完本文,你将掌握:diagram-design 的导出命令语法与全部命令行参数、SVG 与 PNG 两条导出路径的完整操作步骤、导出尺寸的计算规则与预设、以及项目源码层面如何保证导出产物(可访问性、字体、静态帧)的质量。整篇文章以 prompts/export-diagram.md 和 commands/export-diagram.md 为命令入口,以 skills/diagram-design/references/export.md 为权威操作细则,并辅以 skills/diagram-design/SKILL.md 与相关脚本作为实现证据。
一、导出功能在 diagram-design 中的定位
1.1 从生成到交付:导出是链路末端的关键一环
diagram-design 的完整工作流是:选择图解类型 → 生成自包含 HTML → 通过 taste gate 自检 → 按需导出为 SVG / PNG。SKILL.md 的「输出」一节明确要求:每个图解都必须产出单个自包含的.html文件——内嵌 CSS(除 Google Fonts 外无外部资源)、内联 SVG(无外部图片)、默认静态、仅在显式需要动画时使用极少量内联 JavaScript。导出的两种格式(.svg、.png)均由该 HTML 文件派生而来,output-spec.md中明确写道:
Always generate the HTML first —
svgandpngare producedfromit viaexport.md. Never hand-author an SVG file directly; the HTML is the source of truth and the only artifact the taste gate (SKILL.md §9) is written against.
即先有 HTML、再导出 SVG/PNG,绝不手写 SVG。HTML 是唯一的事实来源(source of truth),也是 SKILL.md §9 品味闸门唯一检查的产物。这意味着导出环节的设计哲学是"一次生成、多格式复用"。
1.2 命令的三种入口:Slash 命令、Prompt 与自然语言
导出命令在仓库中以三个层次存在,但其底层执行逻辑完全一致:
- commands/export-diagram.md——插件级的 Slash 命令定义(
/diagram-design:export-diagram),带有allowed-tools声明(Read、Write、Edit、Bash、Glob),直接委托给references/export.md。 - prompts/export-diagram.md——面向 Agent 的 Prompt 形式命令,其 frontmatter 中声明了
argument-hint(参数提示)与description。它要求 Agent 通过 SKILL.md 的路径定位技能目录,将references/export.md视为唯一权威(source of truth),不要自行重新实现导出逻辑。 - 自然语言触发——当用户以"export this as PNG"、"save as SVG"、"rasterize it"、"convert to png and svg"等表达提出需求时,Agent 会加载
export.md并执行同一套流程。
值得注意的约束:导出是手动操作,绝不自动触发。export.md开篇即强调 "Manual only — never run unprompted."(仅手动——未经提示绝不运行)。这意味着html生成后,Agent 不会自动附带产出.svg/.png文件,必须由用户显式提出导出请求。
二、命令语法与参数详解
2.1 完整参数签名
根据 prompts/export-diagram.md 与 commands/export-diagram.md 的 frontmatter,命令的完整签名如下:
/diagram-design:export-diagram <html-file> [--svg-only|--png-only] [--scale=N] [--output=<path>]其中<html-file>是必选的位置参数($1),其余均为可选参数($ARGUMENTS传入完整参数串)。
2.2 默认行为(Defaults)
| 默认项 | 值 | 说明 |
|---|---|---|
| 输出格式 | .svg+.png两者 | 例如diagram.html→diagram.svg+diagram.png,输出到源文件旁 |
| PNG 渲染倍率 | device_scale_factor=2 | 默认 2 倍,保证清晰度 |
即不带任何标志时,命令会同时产出 SVG 与 PNG 两种格式,PNG 以 2 倍设备像素比渲染。
2.3 可选标志(Flags)
| 标志 | 取值 | 作用 |
|---|---|---|
--svg-only | 无值 | 只输出 SVG,完全跳过 Playwright(不启动浏览器) |
--png-only | 无值 | 只输出 PNG |
--scale=N | 1/2/3 | 覆盖 PNG 的设备像素比(device scale factor),默认2 |
--output=<path> | 路径 | 覆盖输出基础路径,命令会自动追加格式扩展名;两种格式同时产出时,该路径同时作用于两者 |
2.4 强制行为(Required behavior)
两条命令规范共同规定了 6 条必须遵守的行为约束,任何违反都意味着导出失败:
- 未提供源路径→ 询问用户要导出哪个
.html文件,绝不猜测。 - 源文件是
assets/index.html(图库页面,一个文件包含多个 SVG)→ 拒绝导出,询问用户具体要哪个图解文件(对应export.md的 Edge cases 一节)。 - 源文件没有
<svg>块→ 拒绝并告知用户,什么都不写。 - 请求 PNG 但未安装 Playwright→ 原样展示参考文档中的安装指引并停止,不自动安装("The user asked for one feature, not a system change.")。
--scale超出 {1,2,3}→ 拒绝,合法值为 1、2、3。- 同时给出
--svg-only和--png-only→ 拒绝,二者互斥(仅 prompts 版明确列出此项;commands 版则将其并入参数合法性检查)。
导出完成后,命令要求向用户汇报输出文件的路径与大小。
关于第 4 条,
export.md给出的安装指引原文如下(必须原样展示给用户,且不得代为执行):pip install playwright playwright install chromium然后让用户再次发起导出请求。这一约束体现了项目"最小化系统变更"的设计原则。
三、两种导出格式的语义差异
在进入操作步骤前,必须先理解 SVG 与 PNG 在项目语义上的根本区别。根据export.md的 Scope 一节:
Both formats arediagram-only— just the
<svg>node. Editorial wrappers (header, summary cards, footer in-fullvariants) are intentionally dropped.
两种格式都只导出图解本身(即<svg>节点),编辑性外壳(header、summary card、footer,主要存在于-full变体)会被有意剔除。导出的交付物就是图解本体,适用于 Figma、幻灯片、社交卡片或博客配图。
| 维度 | SVG | PNG |
|---|---|---|
| 本质 | 矢量文本节点 + 字体 | 浏览器实际渲染的像素 |
| 保留 | <svg>节点、矢量文本、<title>/<desc> | 与浏览器渲染完全一致的像素 |
| 丢失 | 离线工具中字体可能被替换 | 矢量可编辑性 |
| 适用 | Figma / Illustrator 二次编辑 | 幻灯片、博客、社交卡片、打印 |
| 背景 | 透明(无背景 rect 时) | 透明背景(omit_background=True) |
此外,SVG 导出有一个重要的可访问性保证:SVG 保留源文件的<title>和<desc>。由于每个图解及其变体的 ID 都带前缀(如loop-title、loop-dark-title),多个导出的 SVG 可以安全地内联到同一页面,而不会出现一个图形的可访问名称被另一个图形解析的问题。
如果用户明确要求"包含卡片在内的整页截图",那是另一类请求——export.md规定回退到用户操作系统或浏览器的普通整页截图,导出命令本身不做这件事。
四、SVG 导出完整流程(--svg-only或默认路径)
SVG 导出不需要浏览器,其流程在 references/export.md 中有 5 个明确步骤:
- 读取源 HTML 文件。
- 提取第一个
<svg ...>...</svg>块——使用锚定在<svg和</svg>上的多行正则。绝大多数生成的图解只有一个 SVG;若有多个,第一个即图解本体(图库文件除外,见 Edge cases)。 - 使其成为独立(standalone)SVG:
- 确保开标签带有
xmlns="http://www.w3.org/2000/svg",缺失则补上; - 确保存在
viewBox(技能模板总会自带一个;若缺失则警告用户而非擅自猜测); - 原样保留
role="img"、aria-labelledby以及作为首个子元素的<title>/<desc>; - 注入 Google Fonts
@import以保证浏览器中文字渲染正确。关键细节:必须将&分隔符转义为&——独立.svg按严格 XML 解析,裸&会被视为实体引用起始符,导致整个文件解析失败。不能直接从 HTML 的<link href>复制原始 URL(那种带裸&的形式只在 HTML 中合法)。官方给出的注入样式如下:<defs> <style>@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap');</style> </defs>如果 SVG 已有
<defs>块,则将<style>合并进去,而不是追加第二个<defs>。
- 确保开标签带有
- 前置
<?xml version="1.0" encoding="UTF-8"?>\n,保证文件是格式良好的 XML。 - 写入
<basename>.svg到源文件旁(如example-architecture.html→example-architecture.svg),若用户提供了显式输出路径则优先遵循。
4.1 必须向用户说明的注意事项(Caveat)
不支持在导入时抓取远程字体的工具(离线 Illustrator、部分 Figma 导入路径、旧版 SVG 查看器)会替换字体。SVG 在任何现代浏览器中渲染正确;若要像素级可移植性,建议改用 PNG 导出。
4.2 为什么字体注入如此关键:风格体系依赖
从源码角度看,diagram-design 的排版体系完全建立在 Google Fonts 之上。SKILL.md §5 的排版规范给出了 HTML 中的字体引用:
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">- Instrument Serif—— 标题(H1)用衬线;
- Geist(sans)—— 节点名称等人类可读标签;
- Geist Mono—— 端口、URL、字段类型等技术子标签与箭头标签。
而 skills/diagram-design/scripts/self_check.py 中对"单文件安全"的检查(is_approved_google_fonts_stylesheet)只放行https://fonts.googleapis.com/css2这一个远程样式表——这从质量闸门层面印证了字体是体系的一部分,也是导出时必须在 SVG 中保留/注入字体引用的根本原因。若源 HTML 缺少<head>中的fonts.googleapis.com<link>,export.md判定该文件并非来自当前模板,应修复源文件而不是在导出端绕开。
五、PNG 导出完整流程(需 Playwright)
5.1 渲染策略:渲染原 HTML,只截取 SVG 包围盒
与"提取 SVG 再渲染"的直觉相反,PNG 导出的官方流程是:
Renderthe original HTML(not the extracted SVG) and screenshot only the
<svg>element's bounding box.
即渲染原始 HTML(而非提取出的 SVG),仅对<svg>元素的包围盒截图。这样做的好处是字体加载可靠(源 HTML 已接好字体),同时满足"只导出图解"的规则。
三个关键约束:
- 透明背景——截图时使用
omit_background=True,PNG 永远是透明背景,可放到任意颜色(幻灯片、文档)上而不会出现白色光晕。 - 动画源文件需静态化——对启用 motion 的 HTML,须追加
?motion=static查询参数,等待document.fonts.ready,并在截图前断言 motion 根节点处于data-frame="static"状态;绝不可以在任意墙钟延迟后截图。 - 字体就绪门控——截图前必须等待
document.fonts.ready,否则字体尚未加载完成,截图会出现字体替换的偏差。
5.2 Playwright 可用性检测
开始任何操作前,先验证 Playwright 是否安装:
python -c "import playwright" 2>NUL || python -c "import playwright"若导入失败,将下述指引原样展示给用户并停止(不自动安装):
Playwright isn't installed. To enable PNG export, run:
pip install playwright playwright install chromiumThen ask me to export again.
5.3 官方栅格化脚本
export.md给出了可写入临时文件并以python <tmp.py> <src.html> <out.png>运行的完整参考脚本:
from playwright.sync_api import sync_playwright import sys, pathlib src, out = sys.argv[1], sys.argv[2] scale = int(sys.argv[3]) if len(sys.argv) > 3 else 2 with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page(device_scale_factor=scale) page.goto(f"file://{pathlib.Path(src).resolve()}") page.wait_for_load_state("networkidle") page.locator("svg").first.screenshot(path=out, omit_background=True) browser.close()要点解读:
device_scale_factor=scale控制输出分辨率,默认 2;file://协议 +resolve()保证本地文件正确加载;wait_for_load_state("networkidle")等待网络空闲(字体加载的兜底);page.locator("svg").first.screenshot(...)只截第一个 SVG 元素(即图解本体),omit_background=True产出透明背景。
5.4 输出命名
example-architecture.html→example-architecture.png,写入源文件旁;若用户提供显式路径则优先遵循。
5.5 仓库中的同构实现:canonical 截图管线
值得指出的是,仓库的截图管线与export.md的 PNG 流程是同一套技术:scripts/render-canonical-screenshots.py 用 Playwright 以device_scale_factor=2、viewport={"width": 1440, "height": 1000}打开每个 canonical 示例,等待page.evaluate("() => document.fonts.ready")后对page.locator("svg").first调用svg.screenshot(path=str(output), omit_background=True),为 39 个图解类型渲染官方截图并记录 SHA-256 摘要到 docs/screenshots/manifest.json。这与export.md中"渲染原 HTML + 截取首个 SVG + 透明背景 + 字体就绪门控"的约定一一对应,可以作为导出正确性的一种参照实现。相应的 scripts/verify-screenshot-freshness.py 会校验源文件与截图的摘要是否漂移。
六、尺寸决策:viewBox 与缩放系数
6.1 导出只选乘数,不决定尺寸
export.md的 "Sizing the export" 一节给出核心公式:
The PNG's pixel dimensions are the SVG's
viewBox×device_scale_factor. So the size decision was already made when the diagram was drawn — seeoutput-spec.md§2 for the presets. Export only picks the multiplier.
PNG 的像素尺寸 = SVG 的viewBox× 设备像素比。尺寸决策在绘图时就已定下(由 output-spec.md §2 的预设决定),导出环节只负责选择倍率。
6.2 目的地 × 倍率速查表
以一个 1280×720 的viewBox为例(来自export.md):
| 目的地 | Scale | 结果尺寸(1280×720 viewBox) |
|---|---|---|
| Docs、README、wiki | 2 | 2560×1440 |
| 幻灯片(投影) | 2 | 2560×1440 |
| 打印 / PDF 讲义 | 3 | 3840×2160 |
| 内联缩略图、邮件 | 1 | 1280×720 |
对应到命令层:--scale=2适合文档与幻灯片,--scale=3适合打印/PDF/Retina hero,--scale=1适合紧凑资源。
6.3 尺寸预设如何决定 viewBox:output-spec 对照
若需要精确匹配某个尺寸预设,可对照 output-spec.md §2 的预设表(以下为部分关键行):
| 预设 | viewBox | 宽高比 | PNG @2 | 用途 |
|---|---|---|---|---|
doc-inline(默认) | 0 0 960 600 | 8:5 | 1920×1200 | 文章/README 正文宽度图解 |
doc-wide | 0 0 1280 720 | 16:9 | 2560×1440 | 全宽文档、wiki 页 |
slide-16x9 | 0 0 1280 720 | 16:9 | 2560×1440 | 幻灯片、投影 |
slide-4x3 | 0 0 1024 768 | 4:3 | 2048×1536 | 旧版模板 |
social-og | 0 0 1200 632 | ~1.9:1 | 2400×1264 | 链接预览卡片 |
social-square | 0 0 1080 1080 | 1:1 | 2160×2160 | 信息流帖/轮播 |
print-a4-landscape | 0 0 1120 792 | ~1.41:1 | @3 → 3360×2376 | A4 横向打印 |
print-letter-landscape | 0 0 1056 816 | ~1.29:1 | @3 → 3168×2448 | US Letter 横向打印 |
fit | 由内容推导 | 任意 | @2 | 矢量交付,无固定画框 |
6.4 命中精确像素尺寸:计算而非猜测
当用户需要精确尺寸(如 OG 卡片恰为 1200×630、幻灯片图像 1920×1080)时,应计算缩放系数而不是猜——Playwright 接受小数倍率:
scale = target_width / viewBox_width例如 960 宽的viewBox要 1200px 目标宽度,则scale=1.25。但有两条铁律:
- 绝不为命中小目标把倍率降到 1 以下——那会让文字变模糊(soft-focus)。应改用一个更小的预设重新绘制。
- 绝不超过 4——超过 4 相当于把为更小画布设计的布局强行放大,应改用
slide-16x9或打印预设重绘。
此外,若目标宽高比与viewBox宽高比不匹配,应告知用户并提供重绘为匹配预设的方案。给已完成的图解加 padding 或裁剪来适配画框不属于导出操作——那会破坏 40px 安全边距(SKILL.md §6 / output-spec 的安全区约定)。
七、Edge cases:边界情况与防御式处理
export.md明确列出四类边界情况,命令层也对应实现了防御逻辑:
- 源是
assets/index.html(图库,单文件多 SVG)→ 拒绝导出,询问用户具体想要哪个图解文件,不猜测。 - 找不到
<svg>块→ 源文件不是图解文件,告知用户,什么都不写。 - 用户在意周边 HTML(卡片/页头)→ 告知用户本技能只导出图解本体,建议改用浏览器整页截图(或单独 PDF 打印)。
- 运行时字体缺失→ Playwright 会替换字体、截图效果异常。检查源 HTML 的
<head>是否含fonts.googleapis.com的<link>;缺失说明文件并非来自当前模板——修复源文件而不是在导出端绕开。
这些边界情况在命令层(prompts/export-diagram.md 第 3 条与 commands/export-diagram.md 第 2、3 条)被直接引用为强制行为,形成了"命令 → 参考文档"的双层防御。
八、导出命令永远不做的事(设计边界)
export.md最后以显式清单划定了命令的行为边界:
- 不修改源 HTML;
- 不添加导出按钮或
<script>标签——静态图解保持无脚本;已启用 motion 的源可保留其作用域控制器(来自 animation.md),但导出绝不注入另一个控制器; - 不在生成 HTML 时自动附带
.svg/.png——每次调用都是手动触发; - 不通过
foreignObject将 HTML 外壳(卡片、页头)嵌入 SVG——跨渲染器太脆弱。
这些"不做的事"共同维护了自包含 HTML 的静态性与可移植性,也解释了为什么导出的 SVG 必须走"字体 @import + XML 转义"而不是"把整个页面塞进 SVG"的路线。
九、动画图解的导出正确性:静态帧契约
对启用了 motion 的图解,导出并非简单截图,而是遵循一套严格的"最终静态帧契约"。依据 animation.md:
The final-state capture contract is synchronous:
?motion=static,<html contenteditable="false">【免费下载链接】diagram-design38 editorial diagram types for Claude Code, Codex, and Pi. Self-contained HTML + SVG. No shadows. No Mermaid slop.项目地址: https://gitcode.com/GitHub_Trending/di/diagram-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考