スキル: add-rust-svgbob
このスキル内のファイル参照(@path)は、このディレクトリからの相対パスです。
私が行うこと
私は、svgbobdocクレートのtransform!()マクロを使用して、Rustの///ドキュメンテーションコメントにASCIIアート図を追加します。```svgbobコードフェンス内のASCIIアートは、コンパイル時にインラインSVGに変換され、data:image/svg+xmlデータURIとして埋め込まれます。外部ファイルは不要で、ローカルのcargo docとdocs.rsの両方で動作します。
図はソースコード自体に存在します — Rustファイルを読む誰もがASCIIアートを直接見ることができます。
使用するタイミング
以下の場合に使用します:
- 構造的/アーキテクチャ的な概念を図で説明するのが最適なRustライブラリがある場合
- 外部画像ファイルを必要とせずにクイックフローチャート、プロセス図、データフローのビジュアルが必要な場合
- 図がASCIIボックス描画文字で表現できるほど単純な場合
- ソースコード内で表示可能な図(外部PNGに隠れていない)が必要な場合
svgbobdocの依存関係の重さを受け入れられるクレートをメンテナンスしている場合
不適切な場合:
- 実際のデータ可視化(散布図、折れ線グラフ)— 代わりに
embed-doc-imageを使用 - 曲線パスや細かいディテールを含む複雑な図 — ASCIIアートには限界があります
- 非常に古いRustコンパイラ(< 1.54)のプロジェクト
前提条件
| 要件 | 目的 |
|---|---|
| Rust ≥ 1.54 または nightly | 内部属性とプロシージャルマクロのサポートのため |
svgbobdoc を依存関係に含める | プロシージャルマクロクレート |
svgbobdoc の enable フィーチャー | svgbob SVGレンダラーを有効化 |
doc-images フィーチャーフラグ(またはカスタム) | 互換性のためのフィーチャーゲーティング |
| docs.rs メタデータの設定 | docs.rs上でSVGが表示されることを保証 |
動作の仕組み
ステップ1: 現在の状態を確認
Cargo.tomlを読み取り、svgbobdocがすでに設定されているか確認します:
svgbobdocが[dependencies]にfeatures = ["enable"]とともに存在するか?- それはオプション(推奨)になっているか?
- それを有効にするための
doc-imagesまたは類似のフィーチャーがあるか? [package.metadata.docs.rs]にfeatures = ["doc-images"]が含まれているか?
ソースファイルで既存の ```svgbob の使用または svgbobdoc::transform!() の呼び出しを確認します。
ステップ2: インフラストラクチャのセットアップ(不足している場合)
svgbobdoc が設定されていない場合、追加します:
Cargo.toml への追加:
[dependencies]
svgbobdoc = { version = "0.3", optional = true, features = ["enable"] }
[features]
doc-images = ["dep:svgbobdoc"]
[package.metadata.docs.rs]
features = ["doc-images"]
embed-doc-image も使用する場合は、同じフィーチャーの下にまとめます:
[features]
doc-images = ["dep:embed-doc-image", "dep:svgbobdoc"]
ステップ3: プロジェクトをスキャン
<project>/src/ を再帰的に見て *.rs ファイルを探します。図の候補 — ASCII図が概念を明確にする型と関数を特定します。
ステップ4: 図の候補を特定
関数/型/モジュールが「図の候補」となるのは、以下の場合です:
| シグナル | 例 |
|---|---|
| データフロー | 入力 → 処理 → 出力 |
| プロセスステップ | 明確な段階を持つアルゴリズム |
| 座標マッピング | (x, y) → 変換された座標 |
| 幾何学的変換 | 回転、投影、スケーリング |
| 木/グラフ構造 | 二分木、ネットリスト、依存関係グラフ |
| アーキテクチャ | モジュール階層、パイプライン段階 |
| ステートマシン | 状態と遷移 |
| 比較 | 変更前と変更後、2つの代替案 |
| レイアウト | フロアプラン、メモリレイアウト、パッキング |
ステップ5: ASCII図のデザイン
svgbob レンダリング機能:
| ASCII要素 | svgbob レンダリング |
|---|---|
.─. / '─' | 角丸長方形の境界線 |
│ / ─ | 線 |
/ / \ | 斜め線 |
► / ▼ / ▲ / ◄ | 矢印ヘッド(Unicode) |
-> / <- | 矢印コネクタ |
=== / ~~~ | 二重線/波線 |
( ) / [ ] | 曲線/角括弧 |
○ / ● | 円マーカー |
... | 破線コネクタ |
明確な図のためのデザインヒント:
- コンパクトに保つ — 図ごとに最大15〜25行
- ボックス境界線を使用 — 上は
.───.、下は'───' - 矢印にラベルを付ける —
──►コネクタの横にテキストを追加 - Unicodeの罫線文字で整列 —
─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ - 図をテストする — svgbob エディタでプレビュー
例 — 簡単なデータフロー:
.───────────. .───────────. .───────────.
│ 入力 │────►│ 処理 │────►│ 出力 │
'───────────' '───────────' '───────────'
ステップ6: 図の追加
構造体レベルのドキュメントの場合:
/// 既存の説明。
///
/// 変換フロー:
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───────────. .───────────.
/// │ ステップ1 │────►│ ステップ2 │
/// '───────────' '───────────'
/// ```
))]
pub struct MyType { ... }
関数レベルのドキュメントの場合:
/// 説明。
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───────────. .───────────.
/// │ 入力 x │────►│ 出力 f(x) │
/// '───────────' '───────────'
/// ```
))]
pub fn my_function(x: f64) -> f64 { ... }
重要: transform!() 内の /// 行は正確に保持する必要があります。マクロは /// をドキュメンテーションコメント行として解析し、その中の ```svgbob ブロックを処理します。
ステップ7: ビルドと確認
# 図を含めてビルド
cargo doc --features doc-images --no-deps --open
確認チェックリスト:
-
cargo build(フィーチャーなし)がパスする — svgbobdoc依存関係の漏洩なし -
cargo build --features doc-imagesがパスする —transform!()マクロが実行される -
cargo doc --features doc-images --no-depsが警告ゼロで完了する - 生成されたHTMLに
data:image/svg+xml;base64,...URIが含まれている - SVGがブラウザで正しく表示される(適切な矢印、ボックス、テキスト)
# 各構造体ページのSVGデータURIを確認
grep -c "data:image/svg" target/doc/my_crate/struct.MyType.html
ステップ8: 両方のフィーチャーステートを確認
cargo build # パスする必要あり(svgbobdocはリンクされない)
cargo build --features doc-images # パスする必要あり(transform!が実行される)
cargo test --all-features # すべてのテストがパスする必要あり
設定リファレンス
基本的な Cargo.toml(svgbobdoc のみ)
svgbobdoc のみを使用するプロジェクトの最小設定:
[package]
name = "my-crate"
version = "0.1.0"
edition = "2024"
[dependencies]
svgbobdoc = { version = "0.3", optional = true, features = ["enable"] }
[features]
doc-images = ["dep:svgbobdoc"]
[package.metadata.docs.rs]
features = ["doc-images"]
embed-doc-image との組み合わせ
svgbobdoc(ASCII図)と embed-doc-image(PNG/SVG図)の両方を使用する場合:
[dependencies]
embed-doc-image = { version = "0.1", optional = true }
svgbobdoc = { version = "0.3", optional = true, features = ["enable"] }
[features]
doc-images = ["dep:embed-doc-image", "dep:svgbobdoc"]
[package.metadata.docs.rs]
features = ["doc-images"]
両方が同じ doc-images フィーチャーを共有します — 1回の cargo doc --features doc-images で両方が有効になります。
カスタムフィーチャー名
プロジェクトにすでに別の目的で doc-images フィーチャーがある場合は、異なる名前を使用します:
[features]
default = []
svg-docs = ["dep:svgbobdoc"] # カスタム名
doc-images = ["dep:embed-doc-image"] # 既存の名前
ソースコード内:
#[cfg_attr(feature = "svg-docs", doc = svgbobdoc::transform!(
/// ```svgbob
/// diagram
/// ```
))]
pub struct MyType;
dep: 構文によるフィーチャー解決
フィーチャー定義内の dep: プレフィックスは Rust 1.60 で安定化されました。オプションの依存関係を明示的に参照します:
# 最新の構文(Rust ≥ 1.60)— 推奨:
doc-images = ["dep:svgbobdoc"]
# レガシー構文 — 機能するが明示性に劣る:
doc-images = ["svgbobdoc"]
dep: 形式が推奨されます — 依存関係とフィーチャー名の間の曖昧さを防ぎます。
docs.rs メタデータオプション
| 設定 | 目的 |
|---|---|
features = ["doc-images"] | ドキュメントビルド中に svgbobdoc を有効化 |
rustdoc-args = ["--html-in-header", "src/doc-header.html"] | KaTeX/JS ヘッダーを注入 |
all-features = true | すべてのフィーチャーでドキュメントをビルド(注意して使用) |
[package.metadata.docs.rs]
features = ["doc-images"]
rustdoc-args = ["--html-in-header", "src/doc-header.html"]
cfg_attr を使用した条件付きコンパイル
コアパターン:
#[cfg_attr(
feature = "doc-images", // 条件
doc = svgbobdoc::transform!( // 生成する属性
/// ```svgbob
/// diagram
/// ```
)
)]
各ビルドでの動作:
| ビルドコマンド | cfg_attr の評価結果 | 結果 |
|---|---|---|
cargo build | feature = "doc-images" はfalse | 属性抑制 — マクロなし、svgbob依存関係なし |
cargo build --features doc-images | feature = "doc-images" はtrue | #[doc = svgbobdoc::transform!(...)] が生成 — SVG生成 |
cargo doc --features doc-images | 上記と同じ | SVGデータURIがHTMLに埋め込まれる |
| docs.rs(メタデータでフィーチャー設定) | 上記と同じ | SVGがdocs.rs上でレンダリングされる |
フィーチャー解決の確認
フィーチャーが正しく配線されていることを確認:
# デフォルトビルドでsvgbobdocがリンクされていないことを確認
cargo build --verbose 2>&1 | grep svgbobdoc
# (出力がないはず)
# フィーチャーを使用するとsvgbobdocがリンクされることを確認
cargo build --features doc-images --verbose 2>&1 | grep svgbobdoc
# 出力: "Compiling svgbobdoc v0.3.0"
svgbob ASCIIアート構文ガイド
罫線文字
svgbob レンダラーは、以下のUnicode罫線文字を認識し、SVGパスに変換します:
| 文字 | コードポイント | レンダリング結果 |
|---|---|---|
─ | U+2500 | 水平線 |
│ | U+2502 | 垂直線 |
┌ | U+250C | 左上隅 |
┐ | U+2510 | 右上隅 |
└ | U+2514 | 左下隅 |
┘ | U+2518 | 右下隅 |
├ | U+251C | 左T字路 |
┤ | U+2524 | 右T字路 |
┬ | U+252C | 上T字路 |
┴ | U+2534 | 下T字路 |
┼ | U+253C | 交差点 |
╱ | U+2571 | 右上がり斜線 |
╲ | U+2572 | 左上がり斜線 |
◄ | U+25C4 | 左矢印ヘッド |
► | U+25BA | 右矢印ヘッド |
▲ | U+25B2 | 上矢印ヘッド |
▼ | U+25BC | 下矢印ヘッド |
● | U+25CF | 塗りつぶし円 |
○ | U+25CB | 空円 |
═ | U+2550 | 二重水平線 |
║ | U+2551 | 二重垂直線 |
≈ | U+2248 | 波線 |
→ | U+2192 | 右向き矢印 |
ボックスの作成
角丸長方形(図のノードに最も一般的):
.───────────.
│ content │
'───────────'
- 左上隅には
.、右上隅には'を使用 - 左下隅には
'、右下隅には.を使用 - 上下の境界線は
─で埋める - 側面の境界線は
│で埋める
シャープな長方形:
┌───────────┐
│ content │
└───────────┘
矢印でボックスを接続
水平矢印:
.───. .───.
│ A │────────►│ B │
'───' '───'
垂直矢印:
.───.
│ A │
'───'
│
▼
.───.
│ B │
'───'
特定の側からの矢印:
.───.
│ B │
'───'
▲
│
.───. │
│ A │──────┘
'───'
矢印へのラベル追加
矢印線の横にテキストを配置します。svgbob が自動的に配置します:
.───. condition .───.
│ A │══════════════════►│ B │
'───' '───'
.───. false .───.
│ A │──────────────►│ B │
'───' '───'
ボックス内の複数行テキスト
svgbob はボックスの幅に基づいてテキストを自然に折り返します:
.──────────────────.
│ このテキストは │
│ ボックス境界 │
│ 内で折り返されます │
'──────────────────'
斜線
.───. .───.
│ A │╲ │ C │
'───' ╲ '───'
╲
╲ .───.
╲│ B │
╲'───'
木構造と階層
二分木:
.───.
│ R │
'───'
╱ ╲
.───. .───.
│ L │ │ R │
'───' '───'
╱ ╲ ╲
.───. .───. .───.
│LL │ │LR │ │RR │
'───' '───' '───'
インデント階層(線なし):
.───────────────.
│ Root │
│ ├── Child A │
│ ├── Child B │
│ └── Child C │
'───────────────'
グリッドと行列
.──────┬──────┬──────.
│ a │ b │ c │
├──────┼──────┼──────┤
│ d │ e │ f │
├──────┼──────┼──────┤
│ g │ h │ i │
'──────┴──────┴──────'
比較レイアウト
並べて表示:
.─────────────. .─────────────.
│ Before │ │ After │
│ .───────. │ │ .───────. │
│ │ Old │ │ │ │ New │ │
│ '───────' │ │ '───────' │
'─────────────' '─────────────'
Before → After(順次):
.───────────────. .───────────────.
│ 低速パス │────►│ 高速パス │
│ O(n²) │ │ O(n log n) │
'───────────────' '───────────────'
データベース / テーブルスキーマ
.──────────────────────.
│ テーブル: users │
├──────────────────────┤
│ id INTEGER │──► PK
│ name TEXT │
│ email TEXT │──► UNIQUE
│ created_at DATETIME │
'──────────────────────'
判断を含むフローチャート
.───────────.
│ Start │
'─────┬─────'
│
▼
.───────────.
│ 処理 │
'─────┬─────'
│
▼
.───────────. yes .───────────.
│ チェック? │─────────►│ オプションA │
'─────┬─────' '───────────'
│
│ no
▼
.───────────.
│ オプションB │
'───────────'
階層化アーキテクチャ
.───────────────────────────.
│ アプリケーション層 │
├───────────────────────────┤
│ ビジネスロジック層 │
├───────────────────────────┤
│ データアクセス層 │
├───────────────────────────┤
│ データベース │
'───────────────────────────'
タイミング / シーケンス図(簡易)
Client───┬──────────────────┐
│ リクエスト │
│─────────────────►│
│ │Ser
│ │