技能: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) |
-> / <- | 箭头连接器 |
=== / ~~~ | 双线/波浪线 |
( ) / [ ] | 弯曲/尖括号 |
○ / ● | 圆形标记 |
... | 虚线连接器 |
清晰图表的设计技巧:
- 保持紧凑——每个图表最多 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 特性——一次 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 | 向右箭头 |
创建框
圆角矩形(图表节点最常用):
.───────────.
│ 内容 │
'───────────'
- 左上角用
.,右上角用' - 左下角用
',右下角用. - 顶部/底部边框用
─填充 - 侧边边框用
│填充
尖锐矩形:
┌───────────┐
│ 内容 │
└───────────┘
用箭头连接框
水平箭头:
.───. .───.
│ 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 │
'───────────'
分层架构
.───────────────────────────.
│ 应用层 │
├───────────────────────────┤
│ 业务逻辑层 │
├───────────────────────────┤
│ 数据访问层 │
├───────────────────────────┤
│ 数据库 │
'───────────────────────────'
时序/序列图(简单)
客户端───┬──────────────────┐
│ 请求 │
│─────────────────►│