Skill: add-rust-svgbob
Las referencias a archivos (@ruta) en esta skill son relativas a este directorio.
Qué hago
Agrego diagramas de arte ASCII a los comentarios de documentación /// de Rust usando el macro transform!() de la crate svgbobdoc. El arte ASCII dentro de los bloques de código ```svgbob se convierte en SVG inline en tiempo de compilación y se incrusta como URIs de datos data:image/svg+xml — sin necesidad de archivos externos, funciona tanto en cargo doc local como en docs.rs.
El diagrama vive en el código fuente mismo — cualquiera que lea el archivo Rust ve el arte ASCII directamente.
Cuándo usarme
Úsala cuando:
- Tengas una biblioteca Rust con conceptos estructurales/arquitectónicos que se expliquen mejor con un diagrama
- Quieras diagramas de flujo rápidos, diagramas de proceso o visuales de flujo de datos sin archivos de imagen externos
- El diagrama sea lo suficientemente simple para representarlo con caracteres de dibujo de cajas ASCII
- Quieras diagramas que sean visibles en el código fuente (no ocultos en PNGs externos)
- Mantengas una crate donde el peso de dependencia de
svgbobdocsea aceptable
No es adecuado para:
- Visualizaciones de datos reales (dispersión, gráficos de líneas) — usa
embed-doc-imageen su lugar - Diagramas complejos con curvas o detalles finos — el arte ASCII tiene limitaciones
- Proyectos con compiladores Rust muy antiguos (< 1.54)
Prerrequisitos
| Requisito | Propósito |
|---|---|
| Rust ≥ 1.54 o nightly | Para soporte de atributos internos + proc macro |
svgbobdoc en dependencias | La crate de proc macro |
feature enable en svgbobdoc | Activa el renderizador SVG svgbob |
Flag de feature doc-images (o personalizada) | Feature-gating por compatibilidad |
| Metadatos de docs.rs configurados | Asegura que los SVG se rendericen en docs.rs |
Cómo funciono
Paso 1: Verificar el estado actual
Lee Cargo.toml para comprobar si svgbobdoc ya está configurado:
- ¿Está
svgbobdocen[dependencies]confeatures = ["enable"]? - ¿Es opcional (recomendado)?
- ¿Hay una feature
doc-imageso similar para habilitarlo? - ¿Incluye
[package.metadata.docs.rs]el campofeatures = ["doc-images"]?
Verifica los archivos fuente en busca de usos existentes de ```svgbob o llamadas a svgbobdoc::transform!().
Paso 2: Configurar la infraestructura (si falta)
Si svgbobdoc no está configurado, agrégalo:
Adiciones a Cargo.toml:
[dependencies]
svgbobdoc = { version = "0.3", optional = true, features = ["enable"] }
[features]
doc-images = ["dep:svgbobdoc"]
[package.metadata.docs.rs]
features = ["doc-images"]
Si también se usa embed-doc-image, combínalo bajo la misma feature:
[features]
doc-images = ["dep:embed-doc-image", "dep:svgbobdoc"]
Paso 3: Escanear el proyecto
Busca recursivamente en <proyecto>/src/ archivos *.rs. Identifica candidatos a diagrama — tipos y funciones donde un diagrama ASCII aclararía el concepto.
Paso 4: Identificar candidatos a diagrama
Una función/tipo/módulo es un "candidato a diagrama" cuando:
| Señal | Ejemplo |
|---|---|
| Flujo de datos | Entrada → Procesamiento → Salida |
| Pasos de proceso | Algoritmo con etapas claras |
| Mapeo de coordenadas | (x, y) → coordenadas transformadas |
| Transformación geométrica | Rotación, proyección, escalado |
| Estructura de árbol/grafo | Árbol binario, netlist, grafo de dependencias |
| Arquitectura | Jerarquía de módulos, etapas de pipeline |
| Máquina de estados | Estados y transiciones |
| Comparación | Antes vs Después, dos alternativas |
| Diseño | Plano, diseño de memoria, empaquetado |
Paso 5: Diseñar el diagrama ASCII
Capacidades de renderizado de svgbob:
| Elemento ASCII | Renderizado svgbob |
|---|---|
.─. / '─' | Bordes de rectángulo redondeados |
│ / ─ | Líneas |
/ / \ | Líneas diagonales |
► / ▼ / ▲ / ◄ | Cabezas de flecha (Unicode) |
-> / <- | Conectores de flecha |
=== / ~~~ | Líneas dobles/onduladas |
( ) / [ ] | Paréntesis curvos/angulares |
○ / ● | Marcadores de círculo |
... | Conectores punteados |
Consejos de diseño para diagramas claros:
- Mantenlo compacto — 15-25 filas máximo por diagrama
- Usa bordes de caja —
.───.para arriba,'───'para abajo - Etiqueta las flechas — Añade texto junto a los conectores
──► - Alinear con caracteres de dibujo de cajas Unicode —
─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ - Prueba el diagrama — Usa el editor svgbob para previsualizar
Ejemplo — un flujo de datos simple:
.───────────. .───────────. .───────────.
│ Entrada │────►│ Proceso │────►│ Salida │
'───────────' '───────────' '───────────'
Paso 6: Agregar el diagrama
Para documentación a nivel de struct:
/// Descripción existente.
///
/// El flujo de transformación:
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───────────. .───────────.
/// │ Paso 1 │────►│ Paso 2 │
/// '───────────' '───────────'
/// ```
))]
pub struct MiTipo { ... }
Para documentación a nivel de función:
/// Descripción.
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───────────. .───────────.
/// │ Entrada x│────►│ Salida f(x)│
/// '───────────' '───────────'
/// ```
))]
pub fn mi_funcion(x: f64) -> f64 { ... }
IMPORTANTE: Las líneas /// dentro de transform!() deben preservarse exactamente. El macro analiza /// como líneas de comentario de documentación y procesa los bloques ```svgbob dentro de ellas.
Paso 7: Compilar y verificar
# Compilar con diagramas
cargo doc --features doc-images --no-deps --open
Lista de verificación:
-
cargo build(sin features) pasa — sin fuga de dependencia de svgbobdoc -
cargo build --features doc-imagespasa — el macrotransform!()se ejecuta -
cargo doc --features doc-images --no-depsse completa con cero advertencias - El HTML generado contiene URIs
data:image/svg+xml;base64,... - Los SVG se renderizan correctamente en el navegador (flechas, cajas, texto adecuados)
# Verificar URIs de datos SVG en cada página de struct
grep -c "data:image/svg" target/doc/mi_crate/struct.MiTipo.html
Paso 8: Verificar ambos estados de feature
cargo build # Debe pasar (svgbobdoc no enlazado)
cargo build --features doc-images # Debe pasar (transform! se ejecuta)
cargo test --all-features # Todas las pruebas deben pasar
Referencia de configuración
Cargo.toml básico (solo svgbobdoc)
Configuración mínima para un proyecto que usa solo svgbobdoc:
[package]
name = "mi-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"]
Combinado con embed-doc-image
Cuando se usan tanto svgbobdoc (diagramas ASCII) como embed-doc-image (figuras 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"]
Ambos comparten la misma feature doc-images — un solo cargo doc --features doc-images habilita ambos.
Nombres de feature personalizados
Si tu proyecto ya tiene una feature doc-images para otros propósitos, usa un nombre diferente:
[features]
default = []
svg-docs = ["dep:svgbobdoc"] # Nombre personalizado
doc-images = ["dep:embed-doc-image"] # Nombre existente
Luego en el código fuente:
#[cfg_attr(feature = "svg-docs", doc = svgbobdoc::transform!(
/// ```svgbob
/// diagrama
/// ```
))]
pub struct MiTipo;
Resolución de features con sintaxis dep:
El prefijo dep: en las definiciones de features se estabilizó en Rust 1.60. Hace referencia explícita a una dependencia opcional:
# Sintaxis moderna (Rust ≥ 1.60) — recomendada:
doc-images = ["dep:svgbobdoc"]
# Sintaxis heredada — funciona pero es menos explícita:
doc-images = ["svgbobdoc"]
Se prefiere la forma dep: — evita ambigüedades entre nombres de dependencia y feature.
Opciones de metadatos de docs.rs
| Configuración | Propósito |
|---|---|
features = ["doc-images"] | Habilita svgbobdoc durante la compilación de documentación |
rustdoc-args = ["--html-in-header", "src/doc-header.html"] | Inyecta encabezados KaTeX/JS |
all-features = true | Compila la documentación con TODAS las features (usar con cuidado) |
[package.metadata.docs.rs]
features = ["doc-images"]
rustdoc-args = ["--html-in-header", "src/doc-header.html"]
Compilación condicional con cfg_attr
El patrón central:
#[cfg_attr(
feature = "doc-images", // condición
doc = svgbobdoc::transform!( // atributo a emitir
/// ```svgbob
/// diagrama
/// ```
)
)]
Cómo funciona en cada compilación:
| Comando de compilación | cfg_attr evalúa a | Resultado |
|---|---|---|
cargo build | feature = "doc-images" es falso | Atributo suprimido — sin macro, sin dependencia svgbob |
cargo build --features doc-images | feature = "doc-images" es verdadero | #[doc = svgbobdoc::transform!(...)] se emite — SVG generado |
cargo doc --features doc-images | Igual que arriba | URIs de datos SVG incrustados en HTML |
| docs.rs (metadatos establecen features) | Igual que arriba | SVG se renderiza en docs.rs |
Verificar la resolución de features
Verifica que la feature esté correctamente conectada:
# Verificar que svgbobdoc NO esté enlazado en la compilación por defecto
cargo build --verbose 2>&1 | grep svgbobdoc
# (no debería producir salida)
# Verificar que svgbobdoc SÍ esté enlazado con la feature
cargo build --features doc-images --verbose 2>&1 | grep svgbobdoc
# Salida: "Compiling svgbobdoc v0.3.0"
Guía de sintaxis de arte ASCII svgbob
Caracteres de dibujo de cajas
El renderizador svgbob reconoce estos caracteres Unicode de dibujo de cajas y los convierte en rutas SVG:
| Carácter | Punto de código | Renderizado como |
|---|---|---|
─ | U+2500 | Línea horizontal |
│ | U+2502 | Línea vertical |
┌ | U+250C | Esquina superior izquierda |
┐ | U+2510 | Esquina superior derecha |
└ | U+2514 | Esquina inferior izquierda |
┘ | U+2518 | Esquina inferior derecha |
├ | U+251C | Unión en T izquierda |
┤ | U+2524 | Unión en T derecha |
┬ | U+252C | Unión en T superior |
┴ | U+2534 | Unión en T inferior |
┼ | U+253C | Unión en cruz |
╱ | U+2571 | Diagonal hacia arriba-derecha |
╲ | U+2572 | Diagonal hacia arriba-izquierda |
◄ | U+25C4 | Cabeza de flecha izquierda |
► | U+25BA | Cabeza de flecha derecha |
▲ | U+25B2 | Cabeza de flecha arriba |
▼ | U+25BC | Cabeza de flecha abajo |
● | U+25CF | Círculo relleno |
○ | U+25CB | Círculo vacío |
═ | U+2550 | Doble horizontal |
║ | U+2551 | Doble vertical |
≈ | U+2248 | Línea ondulada |
→ | U+2192 | Flecha hacia la derecha |
Crear cajas
Rectángulo redondeado (más común para nodos de diagrama):
.───────────.
│ contenido │
'───────────'
- Usa
.para esquina superior izquierda,'para esquina superior derecha - Usa
'para esquina inferior izquierda,.para esquina inferior derecha - Rellena los bordes superior/inferior con
─ - Rellena los bordes laterales con
│
Rectángulo con bordes rectos:
┌───────────┐
│ contenido │
└───────────┘
Conectar cajas con flechas
Flecha horizontal:
.───. .───.
│ A │────────►│ B │
'───' '───'
Flecha vertical:
.───.
│ A │
'───'
│
▼
.───.
│ B │
'───'
Flecha desde un lado específico:
.───.
│ B │
'───'
▲
│
.───. │
│ A │──────┘
'───'
Agregar etiquetas a las flechas
Coloca texto junto a la línea de la flecha. svgbob lo posiciona automáticamente:
.───. condición .───.
│ A │══════════════════►│ B │
'───' '───'
.───. falso .───.
│ A │──────────────►│ B │
'───' '───'
Texto multilínea en cajas
svgbob ajusta el texto naturalmente según el ancho de la caja:
.──────────────────.
│ Este texto se │
│ ajustará dentro │
│ de los límites │
│ de la caja │
'──────────────────'
Líneas diagonales
.───. .───.
│ A │╲ │ C │
'───' ╲ '───'
╲
╲ .───.
╲│ B │
╲'───'
Árboles y jerarquías
Árbol binario:
.───.
│ R │
'───'
╱ ╲
.───. .───.
│ L │ │ R │
'───' '───'
╱ ╲ ╲
.───. .───. .───.
│LL │ │LR │ │RR │
'───' '───' '───'
Jerarquía indentada (sin líneas):
.───────────────.
│ Raíz │
│ ├── Hijo A │
│ ├── Hijo B │
│ └── Hijo C │
'───────────────'
Cuadrículas y matrices
.──────┬──────┬──────.
│ a │ b │ c │
├──────┼──────┼──────┤
│ d │ e │ f │
├──────┼──────┼──────┤
│ g │ h │ i │
'──────┴──────┴──────'
Diseños de comparación
Lado a lado:
.─────────────. .─────────────.
│ Antes │ │ Después │
│ .───────. │ │ .───────. │
│ │ Viejo │ │ │ │ Nuevo │ │
│ '───────' │ │ '───────' │
'─────────────' '─────────────'
Antes → Después (secuencial):
.───────────────. .───────────────.
│ Ruta lenta │────►│ Ruta rápida │
│ O(n²) │ │ O(n log n) │
'───────────────' '───────────────'
Esquemas de base de datos / Tablas
.──────────────────────.
│ Tabla: usuarios │
├──────────────────────┤
│ id INTEGER │──► PK
│ nombre TEXT │
│ correo TEXT │──► ÚNICO
│ creado_en DATETIME │
'──────────────────────'
Diagrama de flujo con decisión
.───────────.
│ Inicio │
'─────┬─────'
│
▼
.───────────.
│ Proceso │
'─────┬─────'
│
▼
.───────────. sí .───────────.
│ ¿Verificar? │─────────►│ Opción A │
'─────┬─────' '───────────'
│
│ no
▼
.───────────.
│ Opción B │
'───────────'
Arquitectura en capas
.───────────────────────────.
│ Capa de Aplicación │
├───────────────────────────┤
│ Capa de Lógica de Negocio│
├───────────────────────────┤
│ Capa de Acceso a Datos │
├───────────────────────────┤
│ Base de Datos │
'───────────────────────────'
Diagrama de temporización / secuencia (simple)
Cliente───┬──────────────────┐
│ Solicitud │
│─────────────────►│
│ │
│◄─────────────────│
│ Respuesta │
│ │
▼ ▼
.───. .───.
│Fin│ │Fin│
'───' '───'