Community이미지github.com

xingcanlee/wisp-diagram

为博客、技术文档绘制 Wisp 风格的概念图、架构图、模型结构图、算法示意图(自注意力、Transformer、矩阵乘、KV cache、MoE、RAG、训练循环等)。当用户或 Agent 需要画图、生成 .excalidraw / .drawio 源文件、导出可移植 SVG/PNG,或提及 excalidraw、drawio、draw.io、Wisp 风格图表、语义色(Q/K/V)、图表调色板时使用。不适用于数据图表(折线图、柱状图等)。

wisp-diagram란 무엇인가요?

wisp-diagram 是一个专为技术博客与文档打造的专业绘图技能,支持 Excalidraw、draw.io 和 Mermaid 三种工具。其核心优势在于生成风格统一、支持主题切换(浅色/深色)且可移植的 SVG 图表:源文件使用 .excalidraw 或 .drawio 格式,构建后产生 .wisp.svg,内嵌 CSS 变量,在 Wisp 站点内跟随站点主题,在 GitHub 或其它博客中以 <img> 使用时根据系统偏好自动切换明暗。该技能通过 Python 脚本 wisp_diagram.py(依赖 uv 运行时自动管理)提供完整工作流:生成骨架、lint 检查、build 构建、导出 PNG/SVG。关键特性包括严格的颜色调色板(仅从 palette.json 取色,语义色如 Q-蓝、K-琥珀、V-绿)、8px 网格对齐、字号/线宽规范、以及预定义模板和素材库。支持 CI 增量构建、离线缓存,适合与 Hugo、Next.js 等静态站点或任何 Markdown 项目集成。

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/xingcanlee/astro-wisp/tree/HEAD/skills/wisp-diagram

Installed? Explore more 이미지 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

미리보기

스킬 README에서

自注意力:Q 与 K 打分后对 V 加权求和
Transformer Block 的残差结构
自注意力计算流程

문서

wisp-diagram:产出 Wisp 风格图表

目标:产出风格一致、可主题化、可移植的图表。源文件(.excalidraw / .drawio)+ 生成的 *.wisp.svg:同一个 SVG 在 Wisp 站点内联时跟随站点主题,在 GitHub README / 其他博客以 <img> 使用时跟随系统明暗。

本 skill 目录自包含,可整体复制到任何项目(~/.claude/skills/ 或 <项目>/.claude/skills/)。脚本是 Python,用 uv 运行:入口 scripts/wisp_diagram.py 头部用 PEP 723 声明了依赖(playwright、fonttools),uv run 会自动建好隔离环境,不需要 npm / pip install。

SKILL.md
palette.json          调色板(唯一的颜色来源)
reference/            style-guide.md  excalidraw-skeleton.md  drawio-cheatsheet.md  ml-patterns.md
assets/               wisp.excalidrawlib  wisp-drawio-library.xml  drawio-config.json  drawio-colors.txt
scripts/              wisp_diagram.py(统一入口)  wisp_diagram_lib/(实现)  tests/(pytest)

一次性准备

下文命令都在项目根目录运行,$W 代表 skill 的入口脚本(按 skill 实际位置调整路径):

W="uv run skills/wisp-diagram/scripts/wisp_diagram.py"   # 例如 .claude/skills/wisp-diagram/... 或 ~/.claude/skills/wisp-diagram/...
uv run --with playwright==1.64.1 playwright install chromium   # 导出用的无头浏览器(已装过可跳过)
$W probe                                                       # 查看 Chromium、Excalidraw、draw.io 导出方式(cli / docker / browser)是否可用

首次运行会下载并缓存(之后离线可用):

内容来源大小
Python 依赖 playwright 1.64.1、fonttoolsPyPI(uv 管理,放在 uv 自己的缓存)≈ 55 MB
Chromium(只在没装过时)playwright install chromium,放在 ~/.cache/ms-playwright/数百 MB
@excalidraw/excalidraw 0.18.1 及其依赖(≈110 个 ES 模块)jsDelivr,按锁定版本≈ 1.6 MB
svgo 4.1.0 浏览器构建(SVG 精简,在 Chromium 中运行)jsDelivr0.8 MB
字体:Excalifont、Inter 5.3.0、Noto Sans SC 5.3.1(按 unicode-range 分片,用到哪片下哪片)jsDelivr全部 ≈ 4.5 MB
draw.io viewer(只在 browser 导出方式下)viewer.diagrams.net≈ 4.7 MB

除 Python 依赖与 Chromium 外,缓存都在 ~/.cache/wisp-diagram/(可用 WISP_DIAGRAM_CACHE 改位置)。$W cache status 查看,$W cache clear 清空。

离线使用:先在联网环境运行一次 $W cache warm(下载上表全部前端资源,≈ 11 MB),之后设置 WISP_DIAGRAM_OFFLINE=1 即可完全离线;缓存缺文件时会报错并提示预热,不会静默联网。也可以用 WISP_EXCALIDRAW_BUNDLE=<本地 JS> 指定自己的 Excalidraw 构建(定义了 window.__wisp 的 IIFE,或导出 exportToSvg 等函数的 ES 模块),用 WISP_DRAWIO_VIEWER=<本地文件> 指定 draw.io viewer。

draw.io 导出按 cli → docker → browser 顺序自动回退。new、build、export 都需要 Chromium(Excalidraw 导出、svgo 精简都在无头浏览器里运行);lint、normalize、check 不需要。

1. 先选工具

场景选择源文件
流程图、时序图、状态图、类图等结构化图,节点关系为主Mermaid(最省事,直接写进正文的 ```mermaid 代码块;Wisp 站点构建期渲染)无独立文件
概念图、直觉示意、手绘风格、ML 算子数据流Excalidrawname.excalidraw(JSON)
精确对齐的模型结构图、分层架构图、需要直角折线和多页draw.ioname.drawio(未压缩 XML)
逐步演示、可交互不属于本 skill(React 组件)—

原则:能用 Mermaid 讲清楚就别画图;手绘风格不超过约 12 个节点;同一篇文章里风格统一。

2. 工作流(5 步)

以下以 diagrams/attention 为例,路径按实际位置替换。

① 判断类型(见上表)。选定后读对应 reference:Excalidraw → reference/excalidraw-skeleton.md;draw.io → reference/drawio-cheatsheet.md;常见模型图式直接从 reference/ml-patterns.md 复制修改。布局原则见 reference/style-guide.md。

② 生成源文件

  • Excalidraw:写骨架 JSON(位置、尺寸、label、语义色名、箭头起止 id),再转换。禁止手写完整的 Excalidraw 元素(seed、boundElements、version 等字段极易出错)。
    $W new diagrams/attention.skeleton.json -o diagrams/attention.excalidraw
    
    骨架文件转换后可以删除或留作生成脚本;之后以 .excalidraw 为准。
  • draw.io:直接写未压缩 mxGraph XML,样式字符串只用 reference/drawio-cheatsheet.md 的预设。拿到压缩过的 .drawio 时先 $W normalize diagrams/file.drawio 解压。
  • 手动在编辑器里画:导入 assets/wisp.excalidrawlib(Excalidraw 右侧 Library → Open)或 assets/wisp-drawio-library.xml(draw.io:File → Open Library from → Device),按 assets/drawio-colors.txt 配置调色板。

③ lint(先修复)再 build

$W lint diagrams/attention.excalidraw --fix      # 非调色板颜色吸附到最近令牌;无法自动修的会列出
$W lint diagrams/attention.excalidraw --strict   # 无任何 error/warn 才算通过
$W build diagrams/attention.excalidraw           # 生成 diagrams/attention.wisp.svg

build 常用参数:--embed-fonts(内嵌字体子集,发布到外部平台时用)、--fix、--title T --desc D(覆盖无障碍文本,仅单文件)、--drawio cli|docker|browser、--out-dir DIR、--strict。多页 draw.io 的第 2 页起输出为 name.page-2.wisp.svg。

④ 自检:导出 light 与 dark 预览,用 Read 工具查看

$W export diagrams/attention.wisp.svg --theme light -o /tmp/attention.light.png
$W export diagrams/attention.wisp.svg --theme dark  -o /tmp/attention.dark.png

检查:文字重叠、箭头穿过节点、标签压住箭头头部、暗色下看不清、中文被截断。发现问题改源文件,回到 ③ 重新 build。预览 PNG 放临时目录,不要提交。

⑤ 引用并写 alt:见下文「使用产物」。必须提供有意义的 alt 文本(描述图要表达的结论,而不是“图 1”)。

3. 调色板

颜色只能来自 palette.json。作画时只用浅色值(下表左值);build 会把它们映射成 var(--wd-*)(暗色值由 SVG 自动切换)。不要手选暗色值,不要用调色板之外的任何颜色(lint 报错,--fix 吸附到最近的令牌)。

huestroke(线条、文字)light / darkfill(填充)light / dark语义名
blue#1d4ed8 / #60a5fa#dbeafe / #1b2740q、active
amber#b45309 / #fbbf24#fef3c7 / #38290ck、highlight
green#15803d / #4ade80#dcfce7 / #122d1cv、done
rose#be123c / #fb7185#ffe4e6 / #3a1620grad、error
violet#7c3aed / #a78bfa#ede9fe / #272040weight
teal#0f766e / #2dd4bf#ccfbf1 / #0f2c29activation
orange#c2410c / #fb923c#ffedd5 / #3a2010bias
slate#475569 / #94a3b8#e2e8f0 / #222831mask、visited

基础色:正文 fg #1d1d1f(Excalidraw 默认黑 #000000/#1e1e1e 也会被视为 fg),次要 muted #5c6067,面 surface #f4f4f2,边框 border #e2e2dd,画布白 #ffffff(build 会去掉背景)。

语义色(所有文章、图表一致)

语义名含义hue
q查询 Queryblue
k键 Keyamber
v值 Valuegreen
weight权重、参数violet
activation激活、softmaxteal
grad梯度rose
bias偏置orange
mask掩码、输入slate
highlight高亮amber
visited已访问slate
active当前/进行中blue
done完成green
error错误、损失rose

骨架的 color 字段可直接写语义名("color": "q")或 hue 名;draw.io 中查表取 hue 对应的 fill/stroke。

4. 风格硬规则

项目规则
网格所有元素 x/y/宽/高取 8px 的倍数
字号只用 12(注释)/ 14(标签)/ 18(标题);lint 容差 ±1
线宽1.5(常规),2.5(强调,一张图一两处);细线 1 仅用于分隔
圆角矩形/容器圆角:Excalidraw round,draw.io rounded=1;arcSize=8
填充纯色填充,使用 hue 的 fill;禁止渐变
阴影禁止
字体Excalidraw 用 Excalifont(中文回落 Noto Sans SC,不用小赖体);draw.io 用 Inter
手绘roughness: 1;draw.io 不用 sketch=1
背景不画背景矩形,保持透明
源文件.excalidraw 为 JSON;.drawio 为未压缩 XML;嵌入图片会使文件膨胀(>2MB 警告)

5. 自检清单

  • lint --strict 通过:无非调色板颜色、无阴影/渐变、字号合规、元素在 8px 网格上
  • 语义色用对:Q 蓝、K 琥珀、V 绿、权重紫、激活青、梯度/损失玫红、偏置橙、掩码/输入灰
  • 一张图只讲一件事,节点 ≤ 12(手绘)
  • 连线不穿过节点、不交叉;短连线(间距 < 96px)上没有标签
  • 中文标签每行 ≤ 8–10 个汉字,没有被截断
  • 有标题(size: "title" 的文本 / draw.io 页面名)和一句注释
  • light 和 dark 的预览 PNG 都用 Read 看过
  • 已生成 .wisp.svg,且源文件修改后重新 build 过
  • alt 文本有意义

6. 使用产物

在 Wisp 站点中(可选)

站点的 pnpm diagram build|check|lint [--fix]、pnpm diagram new <skeleton.json> --build、pnpm diagram export <文件> --png --theme dark 是本 skill 的薄包装(转调 uv run skills/wisp-diagram/scripts/wisp_diagram.py,并带上 --root <仓库> --manifest scripts/diagram/manifest.json 做增量构建)。 源文件与文章放在一起(diagrams/ 目录),.wisp.svg 也要提交。在 MDX/Markdown 中用标准图片语法引用源文件(站点会内联同名 .wisp.svg,并附源文件下载链接):

![自注意力:Q 与 K 打分后对 V 加权求和](./diagrams/attention.excalidraw "图 1:自注意力计算流程")
![Transformer Block 的残差结构](./diagrams/transformer-block.drawio#page=encoder)

alt 写入 SVG 的 <title>,引号中的说明成为图注;#page=<页面名> 选择 draw.io 的页面。pnpm diagram check 只校验内容哈希,CI 里不需要浏览器(但需要 uv)。

其他项目也可以用同样的“项目模式”:$W build --root . --manifest diagrams.manifest.json 只重建有变化的源文件(扫描 <root>/src/content/**/diagrams/),$W check --root . --manifest diagrams.manifest.json 在 CI 中校验哈希。

在其他地方(GitHub README、其他博客、IDE 预览)

直接引用生成的 *.wisp.svg:它自带 <style>,作为 <img> 时通过 prefers-color-scheme 跟随系统明暗,没有 CSS 变量支持的渲染器会使用属性里的浅色 fallback。

![自注意力计算流程](diagrams/attention.wisp.svg)
  • 发布到外部平台前用 $W build <文件> --embed-fonts 内嵌字体子集(每张图通常几十 KB),避免字体回落。
  • 公众号、知乎等不支持 SVG 的平台:$W export <文件> --theme light --scale 2 -o out.png(--transparent 可得到透明背景;默认内嵌字体)。
  • 源文件一并保存在仓库中,便于以后修改;.excalidraw 可在 excalidraw.com 打开,.drawio 可在 app.diagrams.net 打开。

7. 常见错误

错误怎么避免
手写完整 Excalidraw 元素只写骨架,用 $W new 转换
在编辑器里用了调色板外的颜色(吸管、默认色)用素材库;lint --fix 吸附;仍报错就改源文件
手选暗色值作画只用浅色值,暗色靠 SVG 自动切换
骨架箭头穿过第三个节点箭头是中心连线上的直线;调整布局,或改用 draw.io 折线
短连线加标签,标签压住箭头头部节点间距 ≥ 96 再加标签,否则去掉标签
坐标不在 8px 网格上所有数值取 8 的倍数
.drawio 提交了压缩格式$W normalize 解压;File → Properties 取消 Compressed
draw.io 标签里的 & 没转义html=1 时写成 &amp;amp;,换行写 &lt;br&gt;
中文标签过长被截断每行 ≤ 8–10 个汉字,用 \n / <br> 换行,加宽节点
改了源文件忘记重新 build修改后重跑 $W build(站点里 pnpm diagram check 会发现哈希不一致)
没看暗色预览就交付步骤 ④ 的 dark 预览必须看
空洞的 alt(“图 1”“diagram”)alt 写图要说明的结论
用图表工具画数据图折线/柱状等数据图不属于本 skill

8. 排错

  • uv: command not found:安装 uv(curl -LsSf https://astral.sh/uv/install.sh | sh)。需要 Python ≥ 3.11,uv 会按需自动下载。
  • 无法启动 Chromium:uv run --with playwright==1.64.1 playwright install chromium(版本要与脚本锁定的 playwright 一致)。
  • 下载失败 / 离线模式下缓存缺少 N 个文件:联网运行一次 $W cache warm;缓存位置见 $W cache status。
  • draw.io 导出失败:$W probe 看哪种方式可用;可用 --drawio browser|cli|docker 强制指定。
  • 想看浏览器里的报错:设置 WISP_DIAGRAM_DEBUG=1。
  • lint 报 unrecognised colour:颜色不是十六进制(如 rgb() 之外的特殊值),手工改成调色板里的浅色值。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

관련 스킬