RepoPilotOpen in app →

ivanceras/svgbob

Convert your ascii diagram scribbles into happy little SVG

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

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 →
  • 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.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/ivanceras/svgbob)](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:

  1. 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.
  2. 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.
  3. 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 |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>ivanceras/svgbob</code></summary>
#!/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).

</details>

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 core svg_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

  1. Define the new character-to-shape mapping in the appropriate map file (ASCII, Unicode, or Circle). (crates/svgbob/src/map/ascii_map.rs)
  2. Update cell parsing logic if the pattern requires multi-cell spanning or special adjacency rules. (crates/svgbob/src/buffer/cell_buffer/cell.rs)
  3. 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)

  1. Create a new module under fragment with the shape struct and SVG conversion logic. (crates/svgbob/src/buffer/fragment_buffer/fragment/ellipse.rs)
  2. Implement the Fragment trait (render, bounding_box, merge logic). (crates/svgbob/src/buffer/fragment_buffer/fragment.rs)
  3. Update ASCII map or contact detection to recognize patterns that should produce this shape. (crates/svgbob/src/buffer/cell_buffer/contacts.rs)
  4. Add test case demonstrating the new shape in action. (crates/svgbob/tests/simple_shapes.rs)

Add a new styling option (color, font, stroke style)

  1. Add the new configuration field to the Settings struct. (crates/svgbob/src/settings.rs)
  2. Pass the setting value to PropertyBuffer and update property application logic. (crates/svgbob/src/buffer/property_buffer/property.rs)
  3. Expose the setting in the CLI or server if needed. (crates/svgbob_cli/src/main.rs)
  4. 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.rs to 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.
  • 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 span and 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 Fragment enum in crates/svgbob/src/buffer/fragment_buffer/fragment.rs to 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

📝Recent commits

Click to expand
  • 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 using cargo 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.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · ivanceras/svgbob — RepoPilot