diagram-design 图解导出实战:从自包含 HTML 到 SVG / PNG 的完整流程与源码级原理
2026/9/10 3:14:40 网站建设 项目流程

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 与自然语言

导出命令在仓库中以三个层次存在,但其底层执行逻辑完全一致

  1. commands/export-diagram.md——插件级的 Slash 命令定义(/diagram-design:export-diagram),带有allowed-tools声明(Read、Write、Edit、Bash、Glob),直接委托给references/export.md
  2. prompts/export-diagram.md——面向 Agent 的 Prompt 形式命令,其 frontmatter 中声明了argument-hint(参数提示)与description。它要求 Agent 通过 SKILL.md 的路径定位技能目录,references/export.md视为唯一权威(source of truth),不要自行重新实现导出逻辑
  3. 自然语言触发——当用户以"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.htmldiagram.svg+diagram.png输出到源文件旁
PNG 渲染倍率device_scale_factor=2默认 2 倍,保证清晰度

即不带任何标志时,命令会同时产出 SVG 与 PNG 两种格式,PNG 以 2 倍设备像素比渲染。

2.3 可选标志(Flags)

标志取值作用
--svg-only无值只输出 SVG,完全跳过 Playwright(不启动浏览器)
--png-only无值只输出 PNG
--scale=N1/2/3覆盖 PNG 的设备像素比(device scale factor),默认2
--output=<path>路径覆盖输出基础路径,命令会自动追加格式扩展名;两种格式同时产出时,该路径同时作用于两者

2.4 强制行为(Required behavior)

两条命令规范共同规定了 6 条必须遵守的行为约束,任何违反都意味着导出失败:

  1. 未提供源路径→ 询问用户要导出哪个.html文件,绝不猜测
  2. 源文件是assets/index.html(图库页面,一个文件包含多个 SVG)→ 拒绝导出,询问用户具体要哪个图解文件(对应export.md的 Edge cases 一节)。
  3. 源文件没有<svg>→ 拒绝并告知用户,什么都不写
  4. 请求 PNG 但未安装 Playwright→ 原样展示参考文档中的安装指引并停止,不自动安装("The user asked for one feature, not a system change.")。
  5. --scale超出 {1,2,3}→ 拒绝,合法值为 1、2、3。
  6. 同时给出--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、幻灯片、社交卡片或博客配图。

维度SVGPNG
本质矢量文本节点 + 字体浏览器实际渲染的像素
保留<svg>节点、矢量文本、<title>/<desc>与浏览器渲染完全一致的像素
丢失离线工具中字体可能被替换矢量可编辑性
适用Figma / Illustrator 二次编辑幻灯片、博客、社交卡片、打印
背景透明(无背景 rect 时)透明背景omit_background=True

此外,SVG 导出有一个重要的可访问性保证:SVG 保留源文件的<title><desc>。由于每个图解及其变体的 ID 都带前缀(如loop-titleloop-dark-title),多个导出的 SVG 可以安全地内联到同一页面,而不会出现一个图形的可访问名称被另一个图形解析的问题。

如果用户明确要求"包含卡片在内的整页截图",那是另一类请求——export.md规定回退到用户操作系统或浏览器的普通整页截图,导出命令本身不做这件事。

四、SVG 导出完整流程(--svg-only或默认路径)

SVG 导出不需要浏览器,其流程在 references/export.md 中有 5 个明确步骤:

  1. 读取源 HTML 文件。
  2. 提取第一个<svg ...>...</svg>——使用锚定在<svg</svg>上的多行正则。绝大多数生成的图解只有一个 SVG;若有多个,第一个即图解本体(图库文件除外,见 Edge cases)。
  3. 使其成为独立(standalone)SVG
    • 确保开标签带有xmlns="http://www.w3.org/2000/svg",缺失则补上;
    • 确保存在viewBox(技能模板总会自带一个;若缺失则警告用户而非擅自猜测);
    • 原样保留role="img"aria-labelledby以及作为首个子元素的<title>/<desc>
    • 注入 Google Fonts@import以保证浏览器中文字渲染正确。关键细节:必须将&分隔符转义为&amp;——独立.svg按严格 XML 解析,裸&会被视为实体引用起始符,导致整个文件解析失败。不能直接从 HTML 的<link href>复制原始 URL(那种带裸&的形式只在 HTML 中合法)。官方给出的注入样式如下:
      <defs> <style>@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&amp;family=Geist:wght@400;500;600&amp;family=Geist+Mono:wght@400;500;600&amp;display=swap');</style> </defs>

      如果 SVG 已有<defs>块,则<style>合并进去,而不是追加第二个<defs>

  4. 前置<?xml version="1.0" encoding="UTF-8"?>\n,保证文件是格式良好的 XML。
  5. 写入<basename>.svg到源文件旁(如example-architecture.htmlexample-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 已接好字体),同时满足"只导出图解"的规则。

三个关键约束:

  1. 透明背景——截图时使用omit_background=True,PNG 永远是透明背景,可放到任意颜色(幻灯片、文档)上而不会出现白色光晕。
  2. 动画源文件需静态化——对启用 motion 的 HTML,须追加?motion=static查询参数,等待document.fonts.ready,并在截图前断言 motion 根节点处于data-frame="static"状态;绝不可以在任意墙钟延迟后截图
  3. 字体就绪门控——截图前必须等待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 chromium

Then 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.htmlexample-architecture.png,写入源文件旁;若用户提供显式路径则优先遵循。

5.5 仓库中的同构实现:canonical 截图管线

值得指出的是,仓库的截图管线与export.md的 PNG 流程是同一套技术:scripts/render-canonical-screenshots.py 用 Playwright 以device_scale_factor=2viewport={"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'sviewBox×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、wiki22560×1440
幻灯片(投影)22560×1440
打印 / PDF 讲义33840×2160
内联缩略图、邮件11280×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 6008:51920×1200文章/README 正文宽度图解
doc-wide0 0 1280 72016:92560×1440全宽文档、wiki 页
slide-16x90 0 1280 72016:92560×1440幻灯片、投影
slide-4x30 0 1024 7684:32048×1536旧版模板
social-og0 0 1200 632~1.9:12400×1264链接预览卡片
social-square0 0 1080 10801:12160×2160信息流帖/轮播
print-a4-landscape0 0 1120 792~1.41:1@3 → 3360×2376A4 横向打印
print-letter-landscape0 0 1056 816~1.29:1@3 → 3168×2448US 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明确列出四类边界情况,命令层也对应实现了防御逻辑:

  1. 源是assets/index.html(图库,单文件多 SVG)→ 拒绝导出,询问用户具体想要哪个图解文件,不猜测。
  2. 找不到<svg>→ 源文件不是图解文件,告知用户,什么都不写。
  3. 用户在意周边 HTML(卡片/页头)→ 告知用户本技能只导出图解本体,建议改用浏览器整页截图(或单独 PDF 打印)。
  4. 运行时字体缺失→ 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询