Community编程与开发github.com

luk036/add-rust-svgbob

为Rust项目的文档注释中添加svgbob ASCII图表(```svgbob),使用svgbobdoc crate实现。

add-rust-svgbob 是什么?

该技能旨在帮助Rust开发者通过`svgbobdoc` crate在文档注释(`///`)中嵌入ASCII艺术图表,并在编译时自动转换为内联SVG,最终以`data:image/svg+xml`数据URI的形式嵌入生成的HTML文档中。它特别适用于需要在`cargo doc`或docs.rs上展示架构图、流程图或数据结构图,但又不想依赖外部图片文件的场景。技能支持多种平台(如cargo doc和docs.rs),并提供了完整的Cargo.toml配置指导,包括可选依赖、特性门控(feature gating)和docs.rs元数据设置。通过本技能,开发者可以在Rust源代码中直接维护清晰的图表,同时确保这些图表在默认构建中不会引入额外的依赖开销。

兼容平台~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)均相对于此目录。

我做什么

我使用 svgbobdoc crate 的 transform!() 宏,向 Rust 的 /// 文档注释添加 ASCII 艺术图表。```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) → 转换后的坐标
几何变换旋转、投影、缩放
树/图结构二叉树、网表、依赖图
架构模块层次结构、流水线阶段
状态机状态和转换
比较前后对比、两种替代方案
布局平面图、内存布局、打包

步骤 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使用所有特性构建文档(谨慎使用)
[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  │
'───────────'

分层架构

.───────────────────────────.
│  应用层                  │
├───────────────────────────┤
│  业务逻辑层              │
├───────────────────────────┤
│  数据访问层              │
├───────────────────────────┤
│  数据库                  │
'───────────────────────────'

时序/序列图(简单)

客户端───┬──────────────────┐
         │   请求           │
         │─────────────────►│

Individual skills in this repo

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

相关技能