首页
/ Claude Code artifact-diagramming 技能解析:Artifact 内联 SVG 制图的决策准则与实现机制

Claude Code artifact-diagramming 技能解析:Artifact 内联 SVG 制图的决策准则与实现机制

2026-09-04 15:57:32作者:伍希望

本文基于 system_prompts_leaks 仓库中泄露的 Claude Code artifact-diagramming 技能文档(SKILL.md),完整拆解 Claude Code 在生成 Artifact(可发布页面)时如何决定"该不该画一张图"、"画什么才算机制图",以及内联 SVG 在手写场景下的全部工程约束——viewBox 尺寸策略、currentColor 主题适配、箭头 marker 规范、无障碍标注与自包含要求。读完本文,你可以掌握一套可迁移到任意 HTML 输出场景的"机制图"画法,并理解这些约束与 Claude Code Artifact 运行时(CSP、主题系统)之间的底层对应关系。

这个技能在 Claude Code 技能体系中的位置

artifact-diagramming 是 Claude Code 内置技能集(Skills)中专门负责"图怎么画"的一条。技能的 front matter 声明如下:

name: artifact-diagramming
description: Diagramming know-how for Artifacts - when a picture earns its place,
  how to draw one that shows the real mechanism, and the inline-SVG mechanics
  that keep it legible in both themes.

从系统提示词的技能清单看,它与几个技能构成明确的分工。在 claude-code-fable-5.md 的 Skills 列表中:

  • artifact-design——"Design guidance and fundamentals for Artifacts",要求写任何 Artifact 前必须加载,负责整体视觉设计;
  • artifact-diagramming——专门管 Artifact 中示意图的画法;
  • datavizdataviz/SKILL.md)——管图表(chart/graph/dashboard)的选型、配色与校验。

也就是说,artifact-diagramming 只管"机制示意图"(数据流向、组件关系、状态迁移这类图),不接管图表(图表归 dataviz)也不接管页面整体设计(归 artifact-design)。

加载时机在 claude-code-fable-5.1.md 中有一段值得注意的例外说明:常规 Artifact 一律先加载 artifact-design;但 workshop 技能产出的文档有自己独立的两个"lane"(输出轨道),此时跳过 artifact-design,改为加载 artifact-diagramming 来负责模板页中的示意图。这条提示也解释了本文档中"lane"一词的来源——不同渲染轨道(HTML 页面 vs Markdown 页面)由不同的技能负责指定画图方式。

核心立场:像要长期维护这个决策的工程师那样画图

原文档开篇定调(SKILL.md 第 6 行):

Draw as the engineer who has to live with the decision, not as a decorator.

翻译过来就是:你是要长期为这个决策负责的工程师,不是装饰工。一张图"挣得它的位置"(earns its place)的条件是:它能让一个没有上下文的读者(cold reader)直接看到一段只能从文字里费力拼凑出来的机制——数据往哪里流、哪些组件在互相通信、两个方案之间差在哪里、一个请求经过哪些状态。

并给出一个硬性反证:如果一句话能更快说清楚,就写那句话。这条规则把"画图"从默认动作降格为例外动作,是整份技能的第一原则。

画什么:四条"机制图"准则

1. 画机制,不画名字(Depict the mechanism, not its name)

原文的核心论证是:一个标着 "cache" 的盒子,信息量还不如一段文字。真正有信息量的是——请求穿过缓存的路径、它夹在哪两个存储之间、以及当缓存被移除后消失的那根箭头。

准则要求:画出论证真正依赖的那些部分——正在被跨越的边界(boundary)、正在被新增的一跳(hop)、正在移动的数据——把无关部分全部去掉。这与"系统全景图"式画法相反:不画库存(inventory),只画决策的支点。

2. 比较方案时,画差异,不画两份清单(Comparing options? Draw the difference)

原文给出了"真比较"和"假比较"的判据:

  • 真比较:两套架构并排(side by side)、before/after、每个方案各自新增或删除的那一条边(edge)——读者应该能用手指指出"我要在什么之间做选择";
  • 假比较(被明确点名否决):每个方案各一个带标签的盒子、与系统之间没有任何连线——这不叫比较,这叫"把方案列表重述了一遍"。

这条规则在实操中可以直接当验收标准用:检查并排的两张图,看它们是否共享同一套系统骨架、差异是否体现在连线上,而不是两张孤立的盒子图。

3. 复杂度与赌注匹配(Match complexity to the stakes)

原文给了两个对称的锚点:

  • 一跳(one-hop)问题 → 三盒子的图就够;
  • 把写流量改道经过队列的迁移 → 必须画出队列、写者、读者和那根表顺序的箭头(ordering arrow)。

结论是"画到决策真正依赖的粒度为止":既不接受强行极简(forced minimalism),也不接受把整个系统列一遍(inventory of the whole system)。复杂度由"这个决策要赌什么"决定,而不是由作者的手感决定。

4. 给箭头打标签(Label the arrows)

原文的判断标准:

An unlabeled arrow is "related somehow".

无标签箭头只表达" somehow 有关系";而 writesinvalidatespolls every 30s 这种标签本身就是信息。

关于图例(legend),原文给了一条克制原则:只有当同一种编码方式(虚线、颜色、双线)在图中重复出现时,图例才值得存在;否则直接把含义写在标记本身(箭头/连线)上。这是对"每张图都配图例"惯例的反向约束。

内联 SVG 机制:手写 <svg> 的全部约束

适用前提:HTML 轨道才用内联 SVG

原文第 20 行划定了适用边界:

These mechanics apply where the page renders inline SVG natively (HTML pages); a markdown-rendered page draws its diagrams in whatever fence that lane's renderer supports, and the skill that owns the lane says which.

  • HTML 页面:直接手写内联 <svg>,本文后续所有机制都适用于这一轨道;
  • Markdown 渲染页面:图画在该轨道渲染器支持的代码围栏(fence)里,具体用哪个围栏由"拥有该轨道的技能"指定。结合 claude-code-fable-5.md 中 Artifact 运行时的说明可以印证这一点:Artifact 原生渲染 mermaid 图——Markdown 用 ```mermaid 围栏、HTML 用 <pre class="mermaid"> 块,不依赖任何外部库。

对 HTML 轨道的总要求是:手写内联 <svg>,只用原生形状(rectcirclelinepolylinepath)加 <text>——无库、无运行时、无外部图片。 这一条与 Artifact 的 CSP 约束是互相咬合的:claude-code-fable-5.md 中说明 Artifact 受严格 CSP 管控,外部请求(CDN 脚本、远程字体、远程图片、fetch/XHR)一律被拦截,所以图必须自包含;claude-code-haiku-4.5.md 也特别提醒不要把内容上传到第三方渲染工具(diagram renderers),因为上传即公开。这些运行时约束解释了为什么"无库、无运行时、无外部图片"不是风格偏好,而是硬性前提。

约束一:用 viewBox 定尺寸,交给 CSS 缩放

  • viewBox="0 0 W H",尺寸交给 CSS 缩放:max-width: 100%; height: auto
  • W 和 H 按内容选,不按预设选——不要套 800×600 这类默认画布;
  • 读向与内容对应:横向流(flow)左到右读;分层堆叠(stacked layers)上到下读。

这条的实操含义是:画布宽高比本身就是版式决策的一部分。一条"客户端 → 网关 → 队列 → 消费者"的管道图如果画成接近正方形的 viewBox,视觉读向会立刻失真。

约束二:用 currentColor 做主题适配

  • 描边(strokes)、文字、箭头头部一律用 currentColor,让它同时继承浅色与深色主题下的页面前景色;
  • 全图只保留一个字面颜色(literal hue)给唯一承载语义的元素——被倾向的那个方案、正在讨论的那一跳——并且必须确认这个颜色在深浅两种底色上都能看清。

这条机制与 artifact-design 技能的主题系统直接对应。artifact-design/SKILL.md 规定页面按"三种状态"设计主题:用户显式选择会在根元素打 data-theme="dark" / data-theme="light" 戳,而默认"跟随系统"状态下不打任何戳,此时只有 prefers-color-scheme 能区分深浅。currentColor 方案正是针对这个三态系统的最低成本适配:只要前景色 token 在两个主题下都正确,SVG 里所有走 currentColor 的元素自动跟着换;而那唯一一个字面色则要求作者自己为"两种底色都读得清"负责——这恰好是 artifact-design 中"给第二个主题和第一个同等的用心"这条设计准则在图上的投影。

约束三:箭头头部用 marker 或 polygon,永不用图片

两种合法做法:

  1. <defs> 里定义 <marker>,用 marker-end="url(#arrow)" 引用——注意 id 是**片段内(fragment-internal)**的,即指向本 SVG 内部的锚点;
  2. 在线条末端直接放一个小 <polygon>

底线是"never an image"——不引用任何图片资源,与"无外部图片"的总约束一致。一个符合本技能全部约束的最小片段大致长这样(依规则手工构造的示例,非仓库文件):

<figure>
  <svg viewBox="0 0 560 120" role="img"
       aria-label="请求经过网关后先查缓存,未命中再落到主库;去掉缓存后箭头直连主库"
       style="max-width: 100%; height: auto;">
    <defs>
      <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
              markerWidth="7" markerHeight="7" orient="auto-start-reverse">
        <path d="M 0 0 L 10 5 L 0 10 z" fill="currentColor"/>
      </marker>
    </defs>
    <rect x="10"  y="40" width="110" height="40" rx="4"
          fill="none" stroke="currentColor"/>
    <text x="65"  y="65" text-anchor="middle" font-size="12">Gateway</text>
    <rect x="225" y="40" width="110" height="40" rx="4"
          fill="none" stroke="#c05621"/>
    <text x="280" y="65" text-anchor="middle" font-size="12">Cache</text>
    <rect x="440" y="40" width="110" height="40" rx="4"
          fill="none" stroke="currentColor"/>
    <text x="495" y="65" text-anchor="middle" font-size="12">Primary</text>
    <line x1="120" y1="60" x2="220" y2="60" stroke="currentColor"
          stroke-width="1.5" marker-end="url(#arrow)"/>
    <line x1="335" y1="60" x2="435" y2="60" stroke="currentColor"
          stroke-width="1.5" marker-end="url(#arrow)"/>
    <text x="170" y="50" text-anchor="middle" font-size="11">reads</text>
    <text x="385" y="50" text-anchor="middle" font-size="11">falls through</text>
  </svg>
  <figcaption>缓存命中路径:Gateway 先查 Cache,未命中再写穿到主库;Cache 框用强调色标出当前讨论的对象。</figcaption>
</figure>

对照技能逐条核对:viewBox 按内容定宽(宽大于高,横向流);除 Cache 框外全部走 currentColor,唯一点缀色标出"讨论焦点";箭头头是 defs 内 marker、marker-end="url(#arrow)" 引用片段内 id;文字 11–12px 且短;标签(readsfalls through)直接写在箭头上而不是图例里;整段包在 <figure> 里,figcaption 陈述图的内容,role="img" + aria-label 带同一断言;无 <script>/<style>/<foreignObject>,无外部资源。

约束四:保持文字可读

  • 按绘制尺度算,字号大约 11–13px
  • text-anchor 做对齐(middle/start/end);
  • 短标签:一个词到三个词
  • 解释性的句子放图下方的 caption 里,不放进图内

这条把"图内信息"与"图外解释"的职责切开了:图内只承载命名与动作,叙事全部交给 <figcaption>

约束五:对齐到网格

Shared baselines and even gaps are most of what makes a hand diagram read as deliberate; eyeballed offsets read as noise.

共享基线 + 等距间隙,是一幅手写图"看起来是刻意的"的最大来源;凭眼睛估的偏移只会读起来像噪声。实操上意味着:盒子的 y 坐标、字号、线宽都从同一小组里取值(示例里所有盒子同 y=40、同高 40,线宽统一 1.5px),而不是每个元素各偏几像素。

约束六:一图一断言(One figure, one claim)

这是把前面所有约束收拢成"文档契约"的一条:

  • <svg> 必须包在 <figure> 里;
  • <figcaption> 陈述这张图展示了什么——不是"架构总览"这类空话,而是图的具体断言;
  • <svg>role="img"aria-label 携带同一个断言,服务于看不到图(读屏)的读者。

"一图一断言"同时是内容原则(一张图只证明一件事,对应"画什么"一节里只画决策支点)和无障碍原则(figcaption 与 aria-label 内容一致,视觉读者与非视觉读者拿到的是同一个事实)。

约束七:保持自包含(Stay self-contained)

  • SVG 内禁止 <script><style><foreignObject>
  • 渐变(gradients)、图案(patterns)、<use> 只能引用同一片段内的 idhref="#id")——不允许跨片段或跨文档引用;
  • 最后一条是风格自检:"长串装饰性的 path 数据是这张图该用真正的图形工具的信号——简化,别硬画"。

这条约束呼应了两个相邻技能。artifact-design 在"Build cleanly"一节明确:生成式或装饰性图形应走 Canvas 或 WebGL,而不是手写长 SVG path(artifact-design/SKILL.md);design 技能对图标的要求则是"永不使用 emoji 或 dingbat 字符,画内联 SVG(描边式、16/20/24px 网格、风格统一)以便缩放与改色"(design/SKILL.md)。三者合起来构成 Claude Code 的图形输出谱系:数据图走 dataviz 的图表规范,机制图走 artifact-diagramming 的手写内联 SVG,装饰图形交给 Canvas/WebGL,图标用网格化描边 SVG——artifact-diagramming 恰好覆盖中间"手写 SVG"那一格,它的自包含规则正是 Artifact CSP 环境对这一格的硬约束。

Markdown 轨道:围栏(fence)替代手写 SVG

技能的"Inline SVG mechanics"一节开头就声明:这些机制只适用于原生渲染内联 SVG 的页面(HTML 页面)。Markdown 渲染页面的示意图"画在该轨道渲染器支持的围栏里,由拥有该轨道的技能指定具体围栏"。

从仓库中 Artifact 运行时的描述可以还原出这条 lane 的实际形态:Artifact 原生渲染 mermaid——Markdown 页面用 ```mermaid 围栏,HTML 页面用 <pre class="mermaid"> 块,全程无外部库(见 claude-code-fable-5.md)。这意味着:

轨道 画图手段 主题/尺寸 适用判断
HTML 页面 手写内联 <svg>(原生形状 + <text> viewBox + CSS 缩放,currentColor 跟主题 需要精确控制布局、强调色、标签位置时
Markdown 页面 该 lane 渲染器支持的围栏(运行时原生支持 mermaid) 由渲染器托管 快速表达结构关系时

两条轨道共同的底线是"无外部图片、无外部资源",差异只在于 HTML 轨道把主题适配与无障碍标注的责任压给作者本人(currentColorrole="img"aria-label),而围栏轨道把这些交给渲染器。

实操自检清单

综合全文,产出一张符合该技能的 Artifact 示意图前,可以逐条过一遍:

  1. 该不该画:一句话能说清吗?能,就写句子。(技能第一条)
  2. 画的是机制不是名字:图里有没有"论证的支点"——被跨越的边界、新增/移除的那条边、移动的数据?无关组件是否都删了?
  3. 比较图是不是真比较:读者能否指出两方案共享的骨架与各自的差异连线?还是只是两个孤立盒子?
  4. 复杂度对不对:三盒子够不够?还是必须画出队列/写者/读者与顺序箭头?
  5. 箭头都有标签:每根无标签的箭头是否都值得存在?图例是否只在同一编码重复时才出现?
  6. viewBox 按内容定,宽幅对应横向流、纵向对应分层堆叠。
  7. currentColor 全覆盖 + 唯一强调色:强调色在深浅两种底色下都读得清吗?
  8. 箭头头是 marker 或 polygon,id 引用在本 SVG 片段内。
  9. 文字 11–13px、一词到三词,解释句挪进 caption。
  10. 基线共享、间隙均等,没有凭眼睛估的偏移。
  11. <figure> + <figcaption> + role="img" + aria-label,caption 与 aria-label 陈述同一断言。
  12. <script>/<style>/<foreignObject>,无外部资源;path 数据一长就回头简化。

参考与延伸阅读

需要说明的适用前提:artifact-diagramming 是 Claude Code 面向 Artifact 发布场景的技能文档,其"自包含、无运行时"等约束与 Artifact 的 CSP 运行时强绑定;在普通网页或文档站中使用这些内联 SVG 技巧时,"无外部资源"一条可以从硬性约束降级为最佳实践,而 viewBox 尺寸策略、currentColor 主题化、箭头标签、网格对齐与"一图一断言"这几条则不依赖任何特定运行时,可以直接复用。

登录后查看全文
热门项目推荐
相关项目推荐