Skill: add-rust-svgbob
Dateiverweise (@pfad) in diesem Skill beziehen sich auf dieses Verzeichnis.
Was ich tue
Ich füge ASCII-Art-Diagramme zu Rust ///-Dokumentationskommentaren hinzu, unter Verwendung des transform!()-Makros der svgbobdoc-Crate. Die ASCII-Art in ```svgbob-Codeblöcken wird zur Kompilierzeit in inline SVG umgewandelt und als data:image/svg+xml-Daten-URIs eingebettet – keine externen Dateien nötig, funktioniert sowohl mit lokalem cargo doc als auch auf docs.rs.
Das Diagramm lebt im Quellcode selbst – jeder, der die Rust-Datei liest, sieht die ASCII-Art direkt.
Wann ich verwendet werde
Verwende mich, wenn:
- Du eine Rust-Bibliothek mit strukturellen/architektonischen Konzepten hast, die am besten mit einem Diagramm erklärt werden
- Du schnelle Flussdiagramme, Prozessdiagramme oder Datenflussvisualisierungen ohne externe Bilddateien möchtest
- Das Diagramm einfach genug ist, um es mit ASCII-Boxzeichen darzustellen
- Du Diagramme möchtest, die im Quellcode sichtbar sind (nicht in externen PNGs versteckt)
- Du eine Crate wartest, bei der das Abhängigkeitsgewicht von
svgbobdocakzeptabel ist
Nicht geeignet für:
- Echte Datenvisualisierungen (Punktdiagramme, Liniendiagramme) – verwende stattdessen
embed-doc-image - Komplexe Diagramme mit gekrümmten Pfaden oder feinen Details – ASCII-Art hat Grenzen
- Projekte mit sehr alten Rust-Compilern (< 1.54)
Voraussetzungen
| Anforderung | Zweck |
|---|---|
| Rust ≥ 1.54 oder nightly | Für inneres Attribut + Proc-Macro-Unterstützung |
svgbobdoc in Abhängigkeiten | Die Proc-Macro-Crate |
enable-Feature bei svgbobdoc | Aktiviert den svgbob-SVG-Renderer |
doc-images-Feature-Flag (oder benutzerdefiniert) | Feature-Gating für Kompatibilität |
| docs.rs-Metadaten konfiguriert | Stellt sicher, dass SVGs auf docs.rs gerendert werden |
Wie ich arbeite
Schritt 1: Aktuellen Zustand prüfen
Lese Cargo.toml, um zu prüfen, ob svgbobdoc bereits konfiguriert ist:
- Ist
svgbobdocin[dependencies]mitfeatures = ["enable"]? - Ist es optional (empfohlen)?
- Gibt es ein
doc-imagesoder ähnliches Feature, um es zu aktivieren? - Enthält
[package.metadata.docs.rs]features = ["doc-images"]?
Überprüfe Quelldateien auf vorhandene ```svgbob-Verwendung oder svgbobdoc::transform!()-Aufrufe.
Schritt 2: Infrastruktur einrichten (falls fehlend)
Wenn svgbobdoc nicht konfiguriert ist, füge es hinzu:
Cargo.toml-Ergänzungen:
[dependencies]
svgbobdoc = { version = "0.3", optional = true, features = ["enable"] }
[features]
doc-images = ["dep:svgbobdoc"]
[package.metadata.docs.rs]
features = ["doc-images"]
Wenn embed-doc-image ebenfalls verwendet wird, kombiniere unter dem gleichen Feature:
[features]
doc-images = ["dep:embed-doc-image", "dep:svgbobdoc"]
Schritt 3: Das Projekt scannen
Durchsuche <project>/src/ rekursiv nach *.rs-Dateien. Identifiziere Diagrammkandidaten – Typen und Funktionen, bei denen ein ASCII-Diagramm das Konzept verdeutlichen würde.
Schritt 4: Diagrammkandidaten identifizieren
Eine Funktion/ein Typ/ein Modul ist ein „Diagrammkandidat“, wenn:
| Signal | Beispiel |
|---|---|
| Datenfluss | Eingabe → Verarbeitung → Ausgabe |
| Prozessschritte | Algorithmus mit klaren Phasen |
| Koordinatenabbildung | (x, y) → transformierte Koordinaten |
| Geometrische Transformation | Rotation, Projektion, Skalierung |
| Baum-/Graphstruktur | Binärbaum, Netzliste, Abhängigkeitsgraph |
| Architektur | Modulhierarchie, Pipeline-Stufen |
| Zustandsmaschine | Zustände und Übergänge |
| Vergleich | Vorher vs. Nachher, zwei Alternativen |
| Layout | Grundriss, Speicherlayout, Packung |
Schritt 5: Das ASCII-Diagramm entwerfen
svgbob-Renderfähigkeiten:
| ASCII-Element | svgbob-Rendering |
|---|---|
.─. / '─' | Abgerundete Rechteckrahmen |
│ / ─ | Linien |
/ / \ | Diagonale Linien |
► / ▼ / ▲ / ◄ | Pfeilspitzen (Unicode) |
-> / <- | Pfeilverbinder |
=== / ~~~ | Doppelte/gewellte Linien |
( ) / [ ] | Gebogene/eckige Klammern |
○ / ● | Kreismarker |
... | Gestrichelte Verbinder |
Gestaltungstipps für klare Diagramme:
- Halte es kompakt – maximal 15-25 Zeilen pro Diagramm
- Verwende Boxrahmen –
.───.für oben,'───'für unten - Beschrifte Pfeile – Füge Text neben
──►-Verbindern hinzu - Richte mit Unicode-Boxzeichen aus –
─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ - Teste das Diagramm – Verwende den svgbob-Editor zur Vorschau
Beispiel – ein einfacher Datenfluss:
.───────────. .───────────. .───────────.
│ Eingabe │────►│ Verarbeit│────►│ Ausgabe │
'───────────' '───────────' '───────────'
Schritt 6: Das Diagramm hinzufügen
Für Struct-Level-Dokumentation:
/// Vorhandene Beschreibung.
///
/// Der Transformationsfluss:
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───────────. .───────────.
/// │ Schritt 1│────►│ Schritt 2│
/// '───────────' '───────────'
/// ```
))]
pub struct MyType { ... }
Für Funktions-Level-Dokumentation:
/// Beschreibung.
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───────────. .───────────.
/// │ Eingabe x│────►│ Ausgabe f(x)│
/// '───────────' '───────────'
/// ```
))]
pub fn my_function(x: f64) -> f64 { ... }
WICHTIG: Die ///-Zeilen innerhalb von transform!() müssen exakt erhalten bleiben. Das Makro parst /// als Dokumentationskommentarzeilen und verarbeitet ```svgbob-Blöcke darin.
Schritt 7: Bauen und verifizieren
# Mit Diagrammen bauen
cargo doc --features doc-images --no-deps --open
Verifizierungs-Checkliste:
-
cargo build(ohne Features) besteht – kein svgbobdoc-Abhängigkeitsleck -
cargo build --features doc-imagesbesteht –transform!()-Makro läuft -
cargo doc --features doc-images --no-depswird ohne Warnungen abgeschlossen - Generiertes HTML enthält
data:image/svg+xml;base64,...-URIs - SVGs werden im Browser korrekt gerendert (korrekte Pfeile, Boxen, Text)
# SVG-Daten-URIs auf jeder Struct-Seite überprüfen
grep -c "data:image/svg" target/doc/my_crate/struct.MyType.html
Schritt 8: Beide Feature-Zustände prüfen
cargo build # Muss bestehen (svgbobdoc nicht verlinkt)
cargo build --features doc-images # Muss bestehen (transform! läuft)
cargo test --all-features # Alle Tests müssen bestehen
Konfigurationsreferenz
Basis-Cargo.toml (nur svgbobdoc)
Minimale Einrichtung für ein Projekt, das nur svgbobdoc verwendet:
[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"]
Kombiniert mit embed-doc-image
Bei Verwendung von sowohl svgbobdoc (ASCII-Diagramme) als auch embed-doc-image (PNG/SVG-Abbildungen):
[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"]
Beide teilen sich dasselbe doc-images-Feature – ein cargo doc --features doc-images aktiviert beide.
Benutzerdefinierte Feature-Namen
Falls dein Projekt bereits ein doc-images-Feature für andere Zwecke hat, verwende einen anderen Namen:
[features]
default = []
svg-docs = ["dep:svgbobdoc"] # Benutzerdefinierter Name
doc-images = ["dep:embed-doc-image"] # Vorhandener Name
Dann im Quellcode:
#[cfg_attr(feature = "svg-docs", doc = svgbobdoc::transform!(
/// ```svgbob
/// diagramm
/// ```
))]
pub struct MyType;
Feature-Auflösung mit dep:-Syntax
Das dep:-Präfix in Feature-Definitionen wurde in Rust 1.60 stabilisiert. Es referenziert explizit eine optionale Abhängigkeit:
# Moderne Syntax (Rust ≥ 1.60) – empfohlen:
doc-images = ["dep:svgbobdoc"]
# Legacy-Syntax – funktioniert, aber weniger explizit:
doc-images = ["svgbobdoc"]
Die dep:-Form wird bevorzugt – sie verhindert Mehrdeutigkeiten zwischen Abhängigkeits- und Feature-Namen.
docs.rs-Metadaten-Optionen
| Einstellung | Zweck |
|---|---|
features = ["doc-images"] | Aktiviert svgbobdoc während des Dokumentationsbuilds |
rustdoc-args = ["--html-in-header", "src/doc-header.html"] | Injiziert KaTeX/JS-Header |
all-features = true | Baut Dokumentation mit ALLEN Features (vorsichtig verwenden) |
[package.metadata.docs.rs]
features = ["doc-images"]
rustdoc-args = ["--html-in-header", "src/doc-header.html"]
Bedingte Kompilierung mit cfg_attr
Das Kernmuster:
#[cfg_attr(
feature = "doc-images", // Bedingung
doc = svgbobdoc::transform!( // auszugebendes Attribut
/// ```svgbob
/// diagramm
/// ```
)
)]
Wie es bei jedem Build funktioniert:
| Build-Befehl | cfg_attr wertet aus zu | Ergebnis |
|---|---|---|
cargo build | feature = "doc-images" ist false | Attribut unterdrückt – kein Makro, keine svgbob-Abhängigkeit |
cargo build --features doc-images | feature = "doc-images" ist true | #[doc = svgbobdoc::transform!(...)] wird ausgegeben – SVG generiert |
cargo doc --features doc-images | Gleich wie oben | SVG-Daten-URIs in HTML eingebettet |
| docs.rs (Metadaten setzen Features) | Gleich wie oben | SVG wird auf docs.rs gerendert |
Feature-Auflösung prüfen
Überprüfe, ob das Feature korrekt verdrahtet ist:
# Prüfen, dass svgbobdoc NICHT im Standard-Build verlinkt ist
cargo build --verbose 2>&1 | grep svgbobdoc
# (sollte keine Ausgabe produzieren)
# Prüfen, dass svgbobdoc MIT Feature verlinkt ist
cargo build --features doc-images --verbose 2>&1 | grep svgbobdoc
# Ausgabe: "Compiling svgbobdoc v0.3.0"
svgbob ASCII-Art-Syntax-Referenz
Boxzeichen
Der svgbob-Renderer erkennt diese Unicode-Boxzeichen und wandelt sie in SVG-Pfade um:
| Zeichen | Codepunkt | Rendert als |
|---|---|---|
─ | U+2500 | Horizontale Linie |
│ | U+2502 | Vertikale Linie |
┌ | U+250C | Oben-links Ecke |
┐ | U+2510 | Oben-rechts Ecke |
└ | U+2514 | Unten-links Ecke |
┘ | U+2518 | Unten-rechts Ecke |
├ | U+251C | Links T-Kreuzung |
┤ | U+2524 | Rechts T-Kreuzung |
┬ | U+252C | Oben T-Kreuzung |
┴ | U+2534 | Unten T-Kreuzung |
┼ | U+253C | Kreuzung |
╱ | U+2571 | Diagonale nach oben-rechts |
╲ | U+2572 | Diagonale nach oben-links |
◄ | U+25C4 | Pfeilspitze links |
► | U+25BA | Pfeilspitze rechts |
▲ | U+25B2 | Pfeilspitze oben |
▼ | U+25BC | Pfeilspitze unten |
● | U+25CF | Gefüllter Kreis |
○ | U+25CB | Leerer Kreis |
═ | U+2550 | Doppelte horizontale Linie |
║ | U+2551 | Doppelte vertikale Linie |
≈ | U+2248 | Gewellte Linie |
→ | U+2192 | Pfeil nach rechts |
Boxen erstellen
Abgerundetes Rechteck (am häufigsten für Diagrammknoten):
.───────────.
│ Inhalt │
'───────────'
- Verwende
.für oben-links,'für oben-rechts Ecken - Verwende
'für unten-links,.für unten-rechts Ecken - Fülle die oberen/unteren Ränder mit
─ - Fülle die Seitenränder mit
│
Scharfes Rechteck:
┌───────────┐
│ Inhalt │
└───────────┘
Boxen mit Pfeilen verbinden
Horizontaler Pfeil:
.───. .───.
│ A │────────►│ B │
'───' '───'
Vertikaler Pfeil:
.───.
│ A │
'───'
│
▼
.───.
│ B │
'───'
Pfeil von einer bestimmten Seite:
.───.
│ B │
'───'
▲
│
.───. │
│ A │──────┘
'───'
Beschriftungen zu Pfeilen hinzufügen
Platziere Text neben der Pfeillinie. svgbob positioniert ihn automatisch:
.───. Bedingung .───.
│ A │══════════════════►│ B │
'───' '───'
.───. falsch .───.
│ A │──────────────►│ B │
'───' '───'
Mehrzeiliger Text in Boxen
svgbob bricht Text basierend auf der Boxbreite natürlich um:
.──────────────────.
│ Dieser Text wird │
│ innerhalb der │
│ Box-Grenzen │
│ umgebrochen │
'──────────────────'
Diagonale Linien
.───. .───.
│ A │╲ │ C │
'───' ╲ '───'
╲
╲ .───.
╲│ B │
╲'───'
Bäume und Hierarchien
Binärbaum:
.───.
│ R │
'───'
╱ ╲
.───. .───.
│ L │ │ R │
'───' '───'
╱ ╲ ╲
.───. .───. .───.
│LL │ │LR │ │RR │
'───' '───' '───'
Eingerückte Hierarchie (ohne Linien):
.───────────────.
│ Wurzel │
│ ├── Kind A │
│ ├── Kind B │
│ └── Kind C │
'───────────────'
Gitter und Matrizen
.──────┬──────┬──────.
│ a │ b │ c │
├──────┼──────┼──────┤
│ d │ e │ f │
├──────┼──────┼──────┤
│ g │ h │ i │
'──────┴──────┴──────'
Vergleichslayouts
Nebeneinander:
.─────────────. .─────────────.
│ Vorher │ │ Nachher │
│ .───────. │ │ .───────. │
│ │ Alt │ │ │ │ Neu │ │
│ '───────' │ │ '───────' │
'─────────────' '─────────────'
Vorher → Nachher (sequentiell):
.───────────────. .───────────────.
│ Langsamer Pfad│────►│ Schneller Pfad│
│ O(n²) │ │ O(n log n) │
'───────────────' '───────────────'
Datenbank-/Tabellenschemata
.──────────────────────.
│ Tabelle: benutzer │
├──────────────────────┤
│ id INTEGER │──► PK
│ name TEXT │
│ email TEXT │──► UNIQUE
│ created_at DATETIME │
'──────────────────────'
Flussdiagramm mit Entscheidung
.───────────.
│ Start │
'─────┬─────'
│
▼
.───────────.
│ Prozess │
'─────┬─────'
│
▼
.───────────. ja .───────────.
│ Prüfung?│─────────►│ Option A │
'─────┬─────' '───────────'
│
│ nein
▼
.───────────.
│ Option B │
'───────────'
Geschichtete Architektur
.───────────────────────────.
│ Anwendungsschicht │
├───────────────────────────┤
│ Geschäftslogikschicht │
├───────────────────────────┤
│ Datenzugriffsschicht │
├───────────────────────────┤
│ Datenbank │
'───────────────────────────'
Zeit-/Sequenzdiagramm (einfach)
Client───┬──────────────────┐
│ Anfrage │
│─────────────────►│
│ │
│ Antwort │
│◄─────────────────│
│ │
│ Update │
│─────────────────►│
'────────┴──────────────────'