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 是什麼?

本技能旨在產生風格一致、可主題化且可移植的圖表,特別適用於技術部落格、文件與演算法示意圖。支援 Excalidraw 與 draw.io 兩種工具,並遵循嚴格的 Wisp 風格規範,包含專用調色板(僅允許使用淺色值),以及語義色系(如 Q 對應藍色、K 對應琥珀色、V 對應綠色)。主要工作流程分為五個步驟:判斷圖表類型、產生原始檔(骨架轉換)、lint 修復與構建、匯出預覽圖、引用並撰寫 alt 文字。圖表最終輸出為 `.wisp.svg` 格式,該 SVG 內建 CSS 變數,可在 Wisp 站點中跟隨主題,或在外部平台(如 GitHub README)中跟隨系統明暗模式,無需額外適配。技能本身為自包含的 Python 腳本,使用 `uv` 執行,無需手動安裝 npm 或 pip 依賴;初次執行時會自動下載所需資源(如 Chromium、Excalidraw 前端函式庫等),並支援離線使用。

相容平台✓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 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

預覽

來自技能 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.

相關技能