ivanceras/svgbob
Convert your ascii diagram scribbles into happy little SVG
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 2w ago
- ✓4 active contributors
- ✓Apache-2.0 licensed
Show all 7 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Small team — 4 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 96% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/ivanceras/svgbob)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/ivanceras/svgbob on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: ivanceras/svgbob
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/ivanceras/svgbob shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 2w ago
- 4 active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Small team — 4 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 96% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live ivanceras/svgbob
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/ivanceras/svgbob.
What it runs against: a local clone of ivanceras/svgbob — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in ivanceras/svgbob | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 45 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of ivanceras/svgbob. If you don't
# have one yet, run these first:
#
# git clone https://github.com/ivanceras/svgbob.git
# cd svgbob
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of ivanceras/svgbob and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "ivanceras/svgbob(\\.git)?\\b" \\
&& ok "origin remote is ivanceras/svgbob" \\
|| miss "origin remote is not ivanceras/svgbob (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "crates/svgbob/src/lib.rs" \\
&& ok "crates/svgbob/src/lib.rs" \\
|| miss "missing critical file: crates/svgbob/src/lib.rs"
test -f "crates/svgbob/src/buffer.rs" \\
&& ok "crates/svgbob/src/buffer.rs" \\
|| miss "missing critical file: crates/svgbob/src/buffer.rs"
test -f "crates/svgbob/src/buffer/cell_buffer.rs" \\
&& ok "crates/svgbob/src/buffer/cell_buffer.rs" \\
|| miss "missing critical file: crates/svgbob/src/buffer/cell_buffer.rs"
test -f "crates/svgbob/src/buffer/fragment_buffer.rs" \\
&& ok "crates/svgbob/src/buffer/fragment_buffer.rs" \\
|| miss "missing critical file: crates/svgbob/src/buffer/fragment_buffer.rs"
test -f "crates/svgbob/src/map/ascii_map.rs" \\
&& ok "crates/svgbob/src/map/ascii_map.rs" \\
|| miss "missing critical file: crates/svgbob/src/map/ascii_map.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 45 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~15d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/ivanceras/svgbob"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Svgbob is a Rust library and CLI tool that converts ASCII art diagrams into scalable SVG graphics. It parses text-based drawings (boxes, lines, circles, arrows, text) and renders them as vector graphics, enabling developers to embed diagrams in documentation that render cleanly at any size. The core engine is in crates/svgbob/src and uses a cell-buffer architecture to analyze ASCII patterns and emit SVG fragments. Workspace monorepo with three crates: crates/svgbob (core parsing/rendering engine), crates/svgbob_cli (command-line wrapper), crates/svgbob_server (HTTP service). The engine uses a two-stage pipeline: cell_buffer (parses ASCII into a grid of cells, detects patterns like lines/boxes via contacts.rs, span.rs, cell_grid.rs) → fragment_buffer (emits SVG fragments for arcs, circles, paths via fragment.rs, direction.rs).
👥Who it's for
Documentation writers, technical authors, and developers using systems like mdBook, AsciiDoctor, Zola, or Typst who want to embed ASCII diagrams in markdown/AsciiDoc and have them render as professional SVG without learning a dedicated diagramming tool. Used by Google's Comprehensive Rust course and Kroki diagram service.
🌱Maturity & risk
Active and production-ready. The project is used by major documentation platforms (Google, AsciiDoctor, Discourse, Kroki). The workspace has CI/CD pipelines (crates/svgbob/.github/workflows/rust.yml, release.yml), Cargo.lock committed, and comprehensive examples. However, it appears to be single-maintainer (ivanceras) so long-term support depends on author availability.
Low-to-moderate risk. The core library has minimal external dependencies (Rust stdlib focused), but single-maintainer architecture means prolonged response to critical bugs. The monorepo structure (svgbob, svgbob_cli, svgbob_server) adds surface area. No explicit security audit visible. Architecture.md and spec.md suggest the format is relatively stable, mitigating breaking-change risk.
Active areas of work
Unable to determine from file metadata alone, but the presence of Changelog.md, TODO.md, Behavior.md, and recent example files (circles_generated.rs, merge.rs) suggests active maintenance. The crates/svgbob/spec.md documents feature parity. No specific recent commit timestamps provided, but GitHub Actions workflows are configured.
🚀Get running
git clone https://github.com/ivanceras/svgbob.git
cd svgbob
cargo build --release
cd crates/svgbob && cargo run --example simple
Or use the CLI directly: cargo run -p svgbob_cli -- input.txt -o output.svg
Daily commands:
cd crates/svgbob
cargo run --example simple # Runs src/examples/simple.rs
cargo run --example demo # Complex diagram
cargo build --release # Library build
Or call via CLI from root: cargo run -p svgbob_cli -- <input-file>
🗺️Map of the codebase
crates/svgbob/src/lib.rs— Main library entry point; exposes the coresvg_to_string()conversion API and orchestrates the parsing pipeline.crates/svgbob/src/buffer.rs— Buffer trait definition and composition layer; coordinates cell_buffer, fragment_buffer, and property_buffer stages.crates/svgbob/src/buffer/cell_buffer.rs— First-stage ASCII parsing that converts text input into a grid of cells with shape recognition.crates/svgbob/src/buffer/fragment_buffer.rs— Second-stage buffer that converts cells into vector fragments (lines, arcs, circles, polygons) for SVG generation.crates/svgbob/src/map/ascii_map.rs— Pattern matching rules for ASCII characters; defines how text symbols are interpreted as SVG primitives.crates/svgbob/src/settings.rs— Configuration and theming system; controls stroke width, font size, and styling applied during SVG rendering.crates/svgbob_cli/src/main.rs— CLI entrypoint; demonstrates the public API and handles file I/O for the command-line tool.
🛠️How to make changes
Add support for a new ASCII character pattern
- Define the new character-to-shape mapping in the appropriate map file (ASCII, Unicode, or Circle). (
crates/svgbob/src/map/ascii_map.rs) - Update cell parsing logic if the pattern requires multi-cell spanning or special adjacency rules. (
crates/svgbob/src/buffer/cell_buffer/cell.rs) - Add test case with .bob input file and validate SVG output. (
crates/svgbob/test_data/*.bob)
Add a new SVG primitive (e.g., Ellipse, Polyline)
- Create a new module under fragment with the shape struct and SVG conversion logic. (
crates/svgbob/src/buffer/fragment_buffer/fragment/ellipse.rs) - Implement the Fragment trait (render, bounding_box, merge logic). (
crates/svgbob/src/buffer/fragment_buffer/fragment.rs) - Update ASCII map or contact detection to recognize patterns that should produce this shape. (
crates/svgbob/src/buffer/cell_buffer/contacts.rs) - Add test case demonstrating the new shape in action. (
crates/svgbob/tests/simple_shapes.rs)
Add a new styling option (color, font, stroke style)
- Add the new configuration field to the Settings struct. (
crates/svgbob/src/settings.rs) - Pass the setting value to PropertyBuffer and update property application logic. (
crates/svgbob/src/buffer/property_buffer/property.rs) - Expose the setting in the CLI or server if needed. (
crates/svgbob_cli/src/main.rs) - Add or update test to verify styling is applied correctly. (
crates/svgbob/tests/styling.rs)
🔧Why these technologies
- Rust — Memory-safe, performant, enables CLI tool and server with zero-cost abstractions; suitable for text parsing at scale.
- Grid-cell abstraction (CellBuffer) — ASCII art is inherently 2D and grid-aligned; cells map naturally to character positions for adjacency and contact detection.
- Fragment-based rendering — Separates shape recognition from SVG generation; fragments can be merged, styled, and composed independently before output.
- Multi-buffer pipeline (String → Cell → Fragment → Property → SVG) — Clear separation of concerns: parsing, recognition, merging, and rendering happen in distinct stages, making the flow debuggable and extensible.
⚖️Trade-offs already made
-
Grid-cell grid over token stream or regex-based parsing
- Why: ASCII art has 2D spatial semantics; a grid naturally captures adjacency and span detection without ad-hoc pattern matching.
- Consequence: Requires more memory for large diagrams; compensated by fast spatial queries.
-
Eager merging of fragments vs. lazy rendering
- Why: Merge collinear segments during fragment generation to reduce SVG output size and simplify subsequent processing.
- Consequence: More CPU during parsing; smaller, more readable SVG strings.
-
Settings applied in PropertyBuffer rather than per-primitive
- Why: Centralized, consistent styling across all shapes; easier to theme the entire diagram.
- Consequence: Less granular per-fragment control; mitigation: styling layer in SVG can override if needed.
🚫Non-goals (don't propose these)
- Real-time collaborative editing (no server-side persistence or conflict resolution)
- Vector asset import/embedding (focuses on ASCII → SVG, not external image handling)
- Animation or interactivity (static SVG output only)
- Automatic layout or node positioning (user controls diagram structure via ASCII placement)
🪤Traps & gotchas
No hidden environment variables or service dependencies detected. Be aware: (1) The cell-buffer grid uses floating-point coordinates; rounding differences can cause misalignment in merged fragments (see fragment_buffer/ merge logic). (2) ASCII pattern matching is greedy and order-dependent; adding new patterns must account for overlap with existing ones (e.g., boxes vs. thick lines). (3) The SVG output depends on viewBox scaling; coordinate system is pixels, not characters (1 cell = ~8px by default, configurable). (4) No automatic testing infrastructure visible for visual output—examples are manual verification only.
🏗️Architecture
💡Concepts to learn
- Cell-grid analysis — Svgbob's core parsing strategy: ASCII is mapped to a grid of cells, and pattern recognition happens via cell neighbors and connectivity. Understanding this grid model is essential to extending shape detection.
- Flood fill / connectivity analysis — Used in
contacts.rsto determine which cells form connected components (e.g., a single line vs. multiple separate lines). Enables line tracing and shape detection. - SVG path data and arc syntax — Svgbob emits SVG arc and path elements; understanding cubic Bezier curves and arc flags is essential for implementing smooth curves from ASCII approximations.
- Two-stage rendering pipeline — The architecture separates parsing (cell_buffer) from emission (fragment_buffer). Understanding this separation enables adding new shape types without touching parsing logic.
- Rasterization / ASCII approximation — Svgbob approximates smooth curves and angles using discrete ASCII characters; understanding the limits of this representation (e.g., diagonal line width, circle smoothness) informs expected output quality.
- Monorepo workspace organization — The three-crate structure (core library, CLI, server) uses Cargo workspaces; understanding shared code vs. crate-specific logic is essential for contributing correctly.
- ViewBox coordinate scaling — SVG viewBox transformation determines pixel-to-cell mapping and zoom level. Misconfiguration causes misaligned diagrams; critical when adding coordinate-dependent features.
🔗Related repos
asciidoctor/asciidoctor— AsciiDoc ecosystem partner; integrates svgbob as a diagram processor for embedded ASCII art in technical documentation.google/comprehensive-rust— Major production user of svgbob; demonstrates real-world adoption for generating diagrams in educational markdown.boozook/mdbook-svgbob— mdBook plugin wrapping svgbob; enables one-command diagram rendering in Rust book documentation.yoav-lavi/melody— Similar regex-to-diagram concept in TypeScript; different target (regex visualization) but shares the ASCII→graphic philosophy.mermaid-js/mermaid— Competing diagram tool with broader feature set (flowcharts, sequence diagrams); svgbob focuses on ASCII art simplicity vs. Mermaid's DSL.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for fragment merging logic in src/merge.rs
The merge.rs file handles combining adjacent SVG fragments into optimized paths, which is a critical performance feature. The file structure suggests merge operations are important (it's at the root of src/), but there's no visible test_merge.rs or merge-specific tests in the codebase. Adding thorough unit tests would prevent regressions in this core optimization logic and help new contributors understand the merge algorithm.
- [ ] Create crates/svgbob/src/merge_tests.rs with test cases for adjacent line merging
- [ ] Add test cases for polygon/arc merging scenarios from the examples (circles.rs, circuits.rs)
- [ ] Add edge case tests: single fragments, non-adjacent fragments, overlapping fragments
- [ ] Document expected behavior in Behavior.md or add doc comments to merge functions
- [ ] Verify tests pass with
cargo test --lib merge
Add GitHub Actions workflow for generating and comparing SVG outputs across commits
The repo has multiple example files (demo.rs, circles.rs, circuits.rs) with corresponding shell scripts to generate SVGs. Currently, there's only rust.yml and release.yml in .github/workflows. A workflow that automatically generates SVGs on each commit and compares them visually (or via file diff) would catch unintended rendering changes, serve as regression tests, and help reviewers validate PRs visually.
- [ ] Create .github/workflows/svg-generation.yml workflow
- [ ] Run all example scripts in crates/svgbob (run_*.sh files) on PR commits
- [ ] Upload generated SVGs as workflow artifacts for manual inspection
- [ ] Optionally add a step to diff SVGs against main branch to detect visual regressions
- [ ] Document the workflow purpose in CONTRIBUTING.md or README.md
Add missing unit tests for cell_buffer span logic in src/buffer/cell_buffer/span/
The span module exists with a test_span.rs file but appears to be incomplete given the complexity of span detection (handling character widths, positions, etc.). The cell_buffer is foundational to converting ASCII art into cell coordinates. Adding comprehensive tests for span boundary detection, overlapping spans, and Unicode character handling would improve code quality and prevent regressions in the parsing pipeline.
- [ ] Review existing crates/svgbob/src/buffer/cell_buffer/span/test_span.rs and expand coverage
- [ ] Add tests for Unicode character span detection (referenced in src/map/unicode_map.rs)
- [ ] Add tests for edge cases: empty spans, single-character spans, multi-width characters
- [ ] Add tests for span merging/overlapping scenarios from actual ASCII diagrams
- [ ] Run
cargo test spanand ensure all tests pass
🌿Good first issues
- Add property tests for the cell connectivity logic in
crates/svgbob/src/buffer/cell_buffer/contacts.rs: create test cases that verify that all 8 neighbors of a cell are correctly classified as connected/disconnected for every ASCII character. - Implement unit tests for the
Fragmentenum incrates/svgbob/src/buffer/fragment_buffer/fragment.rsto verify SVG string generation (e.g., arc path syntax, circle radius calculation); currently examples are manual-only. - Document the coordinate transformation between cell grid and SVG viewBox in a new file
crates/svgbob/docs/coordinate_system.md; this is a source of confusion for contributors adding new shape types.
⭐Top contributors
Click to expand
Top contributors
- @ivanceras — 96 commits
- @deining — 2 commits
- @elviejo79 — 1 commits
- @judah-sotomayor — 1 commits
📝Recent commits
Click to expand
Recent commits
6d00ad9— Merge pull request #123 from elviejo79/patch-1 (ivanceras)bdfb652— Update example.bob with vertical unicode characters (elviejo79)04a9d85— prepare for 0.7.6 release (ivanceras)2f4f8f5— feat: add macron and overline on the unicode map module, copied from: https://github.com/ivanceras/svgbob/pull/116 (ivanceras)ab2579c— prepare for 0.7.5 release (ivanceras)ada88b8— expose major_flag (ivanceras)a7b712a— fix: scripts (ivanceras)c60be86— prepare for 0.7.4 release (ivanceras)36cf4f8— fix: rename packages to crates to maintain convention to other common projects (ivanceras)cef4f0a— fix: tests (ivanceras)
🔒Security observations
The svgbob project is a Rust-based ASCII-to-SVG converter with a relatively secure foundation due to Rust's memory safety guarantees. However, the primary security concern is potential XSS vulnerability from insufficiently sanitized user input when generating SVG output. The project shows good practices with workspace management and release optimizations, but lacks explicit security hardening for SVG generation. No hardcoded credentials or obvious injection points were detected in the visible file structure. The CLI and server components should implement strict input validation and output encoding. Regular dependency audits using cargo audit are recommended.
- Medium · Potential XSS vulnerability in SVG generation —
crates/svgbob/src/buffer/fragment_buffer/fragment/*.rs (text.rs, arc.rs, etc.). The svgbob project generates SVG output from user-provided ASCII art input. SVG files can contain executable code through event handlers and scripts. If user input is not properly sanitized before being embedded in SVG attributes or text elements, it could lead to XSS attacks when the SVG is rendered in a browser. Fix: Implement strict input validation and output encoding for all user-supplied content before embedding in SVG. Ensure that special characters in text elements are properly escaped. Consider using an SVG sanitization library. - Low · Publish script lacks security best practices —
.scripts/publish.sh. The .scripts/publish.sh script is present but cannot be fully reviewed. Shell scripts often contain security risks if they handle credentials, run with elevated privileges, or don't validate inputs properly. Fix: Review the publish script for: 1) Hardcoded credentials, 2) Insecure shell options (set -e, set -u), 3) Proper input validation, 4) Secure handling of sensitive data. Consider using authenticated CI/CD platforms instead of shell scripts for publishing. - Low · Missing explicit dependency version pinning in release builds —
Cargo.toml and workspace members. The Cargo.lock file is present, but the repository structure shows multiple crates in a workspace. If dependency management is not strictly enforced across all crates, transitive dependencies could introduce vulnerabilities. Fix: Ensure all workspace members are regularly audited usingcargo audit. Pin critical dependencies explicitly. Implement pre-commit hooks to prevent accidentally introducing vulnerable dependencies. - Low · Test data files could be vectors for injection —
crates/svgbob/test_data/. The test_data directory contains .bob files (ASCII art diagrams) used for testing. While these are test files, if any testing framework processes these files without proper validation, they could serve as injection vectors during development or CI/CD. Fix: Ensure test data files are reviewed for malicious content. Implement strict file type validation and size limits. Keep test data separate from production builds.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.