Community程式設計與開發github.com

luk036/add-rust-svgbob

為 Rust 專案加入 svgbob ASCII 圖表(```svgbob)到文件註解中,使用 svgbobdoc crate。

add-rust-svgbob 是什麼?

此技能可將 ASCII 藝術圖表加入 Rust 程式碼的 `///` 文件註解,並透過 `svgbobdoc` crate 的 `transform!()` 巨集,在編譯時將 ````svgbob` 程式碼區塊內的 ASCII 圖表轉換為內嵌 SVG,以 `data:image/svg+xml` 資料 URI 的形式呈現。這麼做的好處是,圖表直接存在於原始碼中,任何閱讀 Rust 檔案的人都能直接看到 ASCII 圖,無需額外載入外部圖片檔案,且在本地 `cargo doc` 與 `docs.rs` 上都能正常運作。 當您需要為 Rust 函式庫中的結構、函式或模組加入結構性/架構性圖表(如流程圖、資料流、狀態機、樹狀結構等),並希望圖表在原始碼中清晰可見時,此技能特別有用。它透過 `cfg_attr` 與特徵門控 (feature-gating) 機制,確保只有在啟用 `doc-images` 特徵時才會編譯巨集,不會影響預設建置。支援 Unicode 方塊繪製字元、箭頭與標籤,可繪製簡潔的架構圖與流程圖。 使用前需確認專案滿足必要條件:Rust 版本 ≥ 1.54 或 nightly、在 `Cargo.toml` 中將 `svgbobdoc` 加入依賴(建議設為選用並啟用 `enable` 特徵)、定義 `doc-images` 特徵並設定 `[package.metadata.docs.rs]` 以確保 docs.rs 正確渲染 SVG。此技能會自動掃描 `src/` 目錄下的 Rust 檔案,辨識適合加入圖表的候選項目,並在找到 `svgbobdoc` 未設定時,協助完成基礎設施的加入。 不適合用於真實資料視覺化(如散佈圖、折線圖)、過於複雜的曲線圖或細節極多的圖表,且不支援 Rust 編譯器版本低於 1.54 的專案。若專案同時使用 `embed-doc-image`,可將兩者共用同一個 `doc-images` 特徵以簡化管理。

相容平台~Claude Code~Codex CLI~Cursor✓OpenCode
npx skills add https://github.com/luk036/agent-skills/tree/HEAD/skills/add-rust-svgbob

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

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

說明文件

技能:add-rust-svgbob

此技能中的檔案參考(@path)皆相對於此目錄。

我的職責

我負責將 ASCII 藝術圖表 加入 Rust 的 /// 文件註解中,使用 svgbobdoc crate 的 transform!() 巨集。```svgbob 程式碼區塊內的 ASCII 藝術圖表會在編譯時被轉換為 內嵌 SVG,並以 data:image/svg+xml 資料 URI 的形式嵌入——不需要額外檔案,無論在本機 cargo doc 或 docs.rs 上皆可運作。

圖表直接存在於原始碼中——任何閱讀 Rust 檔案的人都能直接看到 ASCII 藝術圖。

何時使用我

在以下情況使用此技能:

  • 您的 Rust 函式庫有 結構/架構概念,用圖表說明最為清楚
  • 您需要 快速流程圖、流程圖或資料流圖形,但不希望使用外部圖片檔案
  • 圖表簡單到可以用 ASCII 方框繪製字元來表示
  • 您希望圖表在 原始碼中可見(而非隱藏在外部 PNG 中)
  • 您維護的 crate 可以接受 svgbobdoc 的依賴權重

不適合用於:

  • 真實資料視覺化(散佈圖、折線圖)——請使用 embed-doc-image
  • 帶有曲線路徑或細節的複雜圖表——ASCII 藝術有其限制
  • 使用非常舊的 Rust 編譯器(< 1.54)的專案

必要條件

需求用途
Rust ≥ 1.54 或 nightly支援內部屬性 + 程序巨集
在依賴中加入 svgbobdoc程序巨集 crate
啟用 svgbobdoc 的 enable 特徵啟動 svgbob SVG 渲染器
doc-images 特徵旗標(或自訂)特徵門控以確保相容性
已設定 docs.rs 中繼資料確保 SVG 在 docs.rs 上正確渲染

我的運作方式

步驟 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) → 轉換後的座標
幾何轉換旋轉、投影、縮放
樹/圖結構二元樹、網路清單、相依性圖
架構模組層級、管線階段
狀態機狀態與轉換
比較之前 vs 之後、兩種替代方案
佈局平面圖、記憶體佈局、封裝

步驟 5:設計 ASCII 圖表

svgbob 渲染能力:

ASCII 元素svgbob 渲染
.─. / '─'圓角矩形邊框
│ / ─線條
/ / \對角線
► / ▼ / ▲ / ◄箭頭頭部(Unicode)
-> / <-箭頭連接器
=== / ~~~雙線/波浪線
( ) / [ ]曲線/方括號
○ / ●圓形標記
...虛線連接器

清晰圖表的設計提示:

  1. 保持簡潔——每個圖表最多 15-25 行
  2. 使用方框邊框——頂部用 .───.,底部用 '───'
  3. 標記箭頭——在 ──► 連接器旁加入文字
  4. 使用 Unicode 方框繪製字元對齊——─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼
  5. 測試圖表——使用 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 特徵——一個 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使用 ALL 特徵建置文件(謹慎使用)
[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 buildfeature = "doc-images" 為 false屬性被抑制——無巨集,無 svgbob 依賴
cargo build --features doc-imagesfeature = "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向右箭頭

建立方框

圓角矩形(圖表節點最常用):

.───────────.
│  內容     │
'───────────'
  • 左上角使用 .,右上角使用 '
  • 左下角使用 ',右下角使用 .
  • 用 ─ 填充頂部和底部邊框
  • 用 │ 填充側邊邊框

尖角矩形:

┌───────────┐
│  內容     │
└───────────┘

用箭頭連接方框

水平箭頭:

.───.         .───.
│ A │────────►│ B │
'───'         '───'

垂直箭頭:

.───.
│ A │
'───'
  │
  ▼
.───.
│ B │
'───'

從特定側邊的箭頭:

         .───.
         │ B │
         '───'
           ▲
           │
.───.      │
│ A │──────┘
'───'

為箭頭加入標籤

將文字放在箭頭線條旁。svgbob 會自動定位:

.───.     條件     .───.
│ A │══════════════════►│ B │
'───'                  '───'
.───.     false    .───.
│ A │──────────────►│ B │
'───'              '───'

方框中的多行文字

svgbob 會根據方框寬度自然地換行文字:

.──────────────────.
│ 這段文字會       │
│ 在方框邊界內     │
│ 自動換行         │
'──────────────────'

對角線

.───.     .───.
│ A │╲    │ C │
'───' ╲   '───'
       ╲
        ╲ .───.
         ╲│ B │
          ╲'───'

樹與層級結構

二元樹:

       .───.
       │ R │
       '───'
       ╱   ╲
   .───.     .───.
   │ L │     │ R │
   '───'     '───'
   ╱   ╲       ╲
 .───. .───.   .───.
 │LL │ │LR │   │RR │
 '───' '───'   '───'

縮排層級結構(無線條):

.───────────────.
│ 根節點        │
│ ├── 子節點 A  │
│ ├── 子節點 B  │
│ └── 子節點 C  │
'───────────────'

網格與矩陣

.──────┬──────┬──────.
│  a   │  b   │  c   │
├──────┼──────┼──────┤
│  d   │  e   │  f   │
├──────┼──────┼──────┤
│  g   │  h   │  i   │
'──────┴──────┴──────'

比較佈局

並排:

.─────────────.  .─────────────.
│ 之前       │  │ 之後       │
│  .───────.  │  │  .───────.  │
│  │ 舊版  │  │  │  │ 新版  │  │
│  '───────'  │  │  '───────'  │
'─────────────'  '─────────────'

之前 → 之後(順序性):

.───────────────.     .───────────────.
│  慢路徑       │────►│  快路徑       │
│  O(n²)        │     │  O(n log n)   │
'───────────────'     '───────────────'

資料庫/資料表結構

.──────────────────────.
│  資料表:users       │
├──────────────────────┤
│  id         INTEGER  │──► PK
│  name       TEXT     │
│  email      TEXT     │──► UNIQUE
│  created_at DATETIME │
'──────────────────────'

帶有決策的流程圖

.───────────.
│  開始     │
'─────┬─────'
      │
      ▼
.───────────.
│  處理     │
'─────┬─────'
      │
      ▼
.───────────.   是   .───────────.
│  檢查?  │─────────►│  選項 A  │
'─────┬─────'         '───────────'
      │
      │ 否
      ▼
.───────────.
│  選項 B  │
'───────────'

分層架構

.───────────────────────────.
│  應用層                  │
├───────────────────────────┤
│  商業邏輯層              │
├───────────────────────────┤
│  資料存取層              │
├───────────────────────────┤
│  資料庫                  │
'───────────────────────────'

時序/序列圖(簡化)

客戶端───┬──────────────────┐
         │   請求            │
         │─────────────────►│
         │                  │
         │◄─────────────────│
         │   回應            │
客戶端───┴──────────────────┘

進階技巧

使用區塊註解做內聯圖表

對於簡短的圖表,您可以使用 /*! 區塊註解將圖表內聯到程式碼中:

/*!
轉換流程:

```svgbob
.───.         .───.
│ A │────────►│ B │
'───'         '───'

*/ pub fn convert() { ... }


### 多個圖表在同一個文件註解中

可以使用多個 `transform!()` 巨集:

```rust
/// 步驟 1:
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───.
/// │ A │
/// '───'
/// ```
))]
/// 步驟 2:
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───.
/// │ B │
/// '───'
/// ```
))]
pub fn two_steps() { ... }

巢狀方框與分組

.───────────────────────────────.
│  系統                        │
│  .───────────. .───────────. │
│  │  模組 A   │ │  模組 B   │ │
│  '───────────' '───────────' │
│         │           │        │
│         └─────┬─────┘        │
│               │              │
│         .─────┴─────.        │
│         │  匯流排    │        │
│         '───────────'        │
'───────────────────────────────'

使用帶有標籤的邊框

.───. 輸入    .───.
│ A │════════►│ B │
'───'        '───'

常見問題

變更圖表而不改動原始碼

svgbobdoc 在編譯時處理圖表,因此無法在不修改原始碼或重新建置 crate 的情況下變更圖表。如果圖表需要頻繁更新,請考慮使用外部文件(例如 README.md)搭配 embed-doc-image。

效能影響

transform!() 巨集在編譯時執行,其開銷與 ASCII 圖表的大小和複雜度成正比。對於大多數圖表(< 50 行),開銷可以忽略不計。大型或大量的圖表可能會增加編譯時間。

與其他文件工具的相容性

  • rustdoc:完全支援——巨集直接輸出有效的 #[doc = ...] 屬性
  • docs.rs:只要 [package.metadata.docs.rs] 正確設定即可運作
  • 本地 cargo doc:如果正確啟用特徵,則可直接運作
  • IDE 整合:圖表在原始碼中顯示為 ASCII 藝術;SVG 在 rustdoc 預覽中可見

與 egui / 其他 GUI 的相容性

svgbobdoc 僅在文件建置期間執行,執行期間環境中不運作。它不會影響執行時期行為或二進位檔案大小。

對 no_std 的支援

是的。svgbobdoc 僅是一個程序巨集 crate,不需要 std。它可以在 #![no_std] crate 中安全使用。

對 WASM 的支援

是的。transform!() 在編譯期間執行,輸出的資料 URI 可以無問題地在 WASM 目標上使用。

故障排除

transform!() 巨集錯誤

問題: error: cannot find macro 'transform' in this scope

解決方案: 確保 svgbobdoc 已正確加入 Cargo.toml:

[dependencies]
svgbobdoc = { version = "0.3", features = ["enable"] }  # 需要 "enable" 特徵

並且在原始碼中正確導入:

use svgbobdoc::transform;  // 或使用完整路徑 svgbobdoc::transform!()

SVG 未在 docs.rs 上渲染

問題: 圖表在本機 cargo doc 中運作,但在 docs.rs 上未顯示。

解決方案: 驗證 [package.metadata.docs.rs] 已正確設定:

[package.metadata.docs.rs]
features = ["doc-images"]

重新發布 crate 以便 docs.rs 重建文件。

圖表在瀏覽器中看起來不對

問題: SVG 渲染具有斷裂的線條、遺失的字元或對齊不正確。

解決方案:

  1. 使用svgbob 編輯器測試 ASCII 圖表
  2. 確保使用正確的 Unicode 方框繪製字元(─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼)
  3. 在圖表中使用等寬字型(例如 Consolas、DejaVu Sans Mono)
  4. 檢查圖表中是否有不能正常顯示的寬字元(例如全形字元)

建置速度變慢

問題: 新增 svgbobdoc 後編譯時間顯著增加。

解決方案:

  1. 保持圖表簡潔(< 30 行)
  2. 使用 sccache 或 mold 來加速增量建置
  3. 如果圖表很多(> 50 個),考慮使用 embed-doc-image 將圖表拆分為外部檔案

參考資源

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相關技能