wisp-diagram:Wisp スタイルの図表を生成する
目標:スタイルが統一され、テーマに対応可能で、移植性の高い図表を生成すること。ソースファイル(.excalidraw / .drawio)+ 生成された *.wisp.svg:同じ SVG が Wisp サイト内ではサイトテーマに追従し、GitHub README / その他のブログで <img> として使用される場合はシステムのライト/ダークテーマに追従します。
このスキルディレクトリは自己完結しており、任意のプロジェクト(~/.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 はスキルのエントリスクリプトを表します(実際のパスに合わせて調整してください):
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、fonttools | PyPI(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 内で実行) | jsDelivr | 0.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 は Chromium を必要としません。
1. まずツールを選ぶ
| シナリオ | 選択 | ソースファイル |
|---|---|---|
| フローチャート、シーケンス図、状態図、クラス図などの構造化図、ノード関係が中心 | Mermaid(最も手軽、本文の ```mermaid コードブロックに直接記述;Wisp サイトではビルド時にレンダリング) | 独立したファイルなし |
| 概念図、直感的な図、手書き風、ML 演算子のデータフロー | Excalidraw | name.excalidraw(JSON) |
| 正確に整列されたモデル構造図、階層アーキテクチャ図、直角折れ線や複数ページが必要な場合 | draw.io | name.drawio(非圧縮 XML) |
| 段階的なデモ、インタラクティブ | このスキルの対象外(React コンポーネント) | — |
原則:Mermaid で説明できるなら図を描かない。手書き風は約 12 ノード以内。同じ記事内ではスタイルを統一する。
2. ワークフロー(5 ステップ)
以下では diagrams/attention を例とします。実際のパスに置き換えてください。
① タイプを判断(上の表を参照)。決定したら対応するリファレンスを読む:Excalidraw → reference/excalidraw-skeleton.md;draw.io → reference/drawio-cheatsheet.md;一般的なモデル図は reference/ml-patterns.md からコピーして修正する。レイアウトの原則は reference/style-guide.md を参照。
② ソースファイルを生成
- Excalidraw:スケルトン JSON を記述(位置、サイズ、ラベル、セマンティックカラー名、矢印の開始・終了 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 で最も近いトークンにスナップします)。
| hue | stroke(線、文字)light / dark | fill(塗りつぶし)light / dark | セマンティック名 |
|---|---|---|---|
blue | #1d4ed8 / #60a5fa | #dbeafe / #1b2740 | q、active |
amber | #b45309 / #fbbf24 | #fef3c7 / #38290c | k、highlight |
green | #15803d / #4ade80 | #dcfce7 / #122d1c | v、done |
rose | #be123c / #fb7185 | #ffe4e6 / #3a1620 | grad、error |
violet | #7c3aed / #a78bfa | #ede9fe / #272040 | weight |
teal | #0f766e / #2dd4bf | #ccfbf1 / #0f2c29 | activation |
orange | #c2410c / #fb923c | #ffedd5 / #3a2010 | bias |
slate | #475569 / #94a3b8 | #e2e8f0 / #222831 | mask、visited |
ベースカラー:本文 fg #1d1d1f(Excalidraw のデフォルト黒 #000000/#1e1e1e も fg として扱われます)、補助 muted #5c6067、面 surface #f4f4f2、境界線 border #e2e2dd、キャンバス白 #ffffff(build で背景を除去)。
セマンティックカラー(すべての記事、図表で統一)
| セマンティック名 | 意味 | hue |
|---|---|---|
q | クエリ Query | blue |
k | キー Key | amber |
v | バリュー Value | green |
weight | 重み、パラメータ | violet |
activation | 活性化、softmax | teal |
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~2 箇所)。細線 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 は、このスキルの薄いラッパーです(内部的に uv run skills/wisp-diagram/scripts/wisp_diagram.py を呼び出し、--root <リポジトリ> --manifest scripts/diagram/manifest.json を付けてインクリメンタルビルドを行います)。
ソースファイルは記事と同じ場所に置きます(diagrams/ ディレクトリ)。.wisp.svg もコミットします。MDX/Markdown では、標準の画像構文でソースファイルを参照します(サイトは同名の .wisp.svg をインライン化し、ソースファイルのダウンロードリンクを添付します):


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 変数に対応していないレンダラーでは、属性に設定されたライトテーマのフォールバック値が使用されます。

- 外部プラットフォームに公開する前に、
$W build <ファイル> --embed-fontsでフォントサブセットを埋め込みます(1 画像あたり通常数十 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 が自動的に切り替える |
| スケルトンの矢印が 3 つ目のノードを貫通する | 矢印は中心を結ぶ直線。レイアウトを調整するか、draw.io の折れ線に変更する |
| 短い線にラベルを付け、ラベルが矢印の先端にかかる | ノード間の間隔が 96px 以上の場合のみラベルを追加。それ以外はラベルを削除 |
| 座標が 8px グリッド上にない | すべての数値を 8 の倍数にする |
.drawio を圧縮形式でコミットする | $W normalize で解凍。File → Properties で Compressed を解除 |
draw.io のラベルで & をエスケープしていない | html=1 の場合は &amp; と書き、改行は <br> と書く |
| 中国語ラベルが長すぎて途切れる | 各行 8~10 文字以内にし、\n / <br> で改行、ノードの幅を広げる |
| ソースファイルを修正したのに build し忘れる | 修正後は再び $W build を実行(サイトでは pnpm diagram check でハッシュ不一致を検出) |
| ダークテーマのプレビューを確認せずに納品する | ステップ ④ の dark プレビューは必ず確認する |
| 内容のない alt(「図 1」「diagram」) | alt には図が説明する結論を書く |
| 図表ツールでデータプロットを描く | 折れ線/棒グラフなどのデータプロットはこのスキルの対象外 |
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エラー:色が 16 進数でない(例:rgb()以外の特殊な値)。手動でパレット内のライトテーマの値に変更してください。