Skip to content

SVG figure pipeline: JSON-driven diagram renderer - #23

Open
ben wants to merge 15 commits into
mainfrom
ben/svg-pipeline
Open

SVG figure pipeline: JSON-driven diagram renderer#23
ben wants to merge 15 commits into
mainfrom
ben/svg-pipeline

Conversation

@ben

@ben ben commented Aug 21, 2026

Copy link
Copy Markdown
Member

Summary

Introduces a new figure-rendering pipeline for the book: diagrams are defined declaratively as JSON (nodes, edges, layout grid) and rendered to SVG, replacing the prior hand-drawn figure workflow. The pipeline covers all 113 of the book's figures and integrates with the Rake build so SVGs are generated for every book output target (HTML, EPUB, PDF, etc.).

Key pieces:

  • A JSON schema and renderer that turns a node/edge graph description into SVG, with a shared visual palette (commit/blob/ref node kinds, arrow styles including muted and double-headed, git-object content boxes)
  • A Rake namespace for building figures as part of the normal book build
  • An SVG-to-JSON extractor used to bootstrap draft JSON from the existing hand-drawn figures, so all 113 figures start from real layouts rather than from scratch
  • Edges (relationships between nodes) authored across the full figure set — the DAG diagrams in ch02/ch03, rebase/merge diagrams, branching and workflow diagrams, and more — turning the extracted draft JSON into complete, renderable definitions
  • Renderer fixes discovered while authoring figures: arrowhead rendering, git-object content boxes, and additional arrow styles

Remaining work

  • figure formats not yet represented by the renderer, might need a separate method for these
    • clean and smudge
    • distributed and local
    • lifecycle
    • lr-branches-2
    • managed-team-flow
    • remote-branches-*
    • replace*
    • rerere*
    • reset-*
    • small-team-flow
  • commit-and-tree is still rough
  • commits-and-parents is still rough
  • data-model-* need work
  • deltas needs arrows
  • interesting-rebase-* and rebase-2 need muted nodes
  • large-merges-* needs better arrow routing maybe?
  • perils-of-rebasing-*
  • snapshots needs different styles for not-new files (muted? dashed outlines?)
  • undomerge-reset needs muted nodes

Test plan

  • bundle exec rake book:build_html builds cleanly
  • Manually spot-check regenerated SVGs in the HTML/PDF output for visual regressions

ben and others added 15 commits August 4, 2026 09:43
Defines the symbol vocabulary (colors, node kinds, box geometry) extracted
from images/symbols.svg, and a JSON Schema for editor autocomplete and
pre-render validation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bin/render-figures.rb reads figures/*.json and emits images/*.svg.
Pure Ruby stdlib, no new dependencies. Output is deterministic
(byte-identical across runs) so figures:check can detect stale images.

Uses JetBrains Mono as the primary font (with Source Code Pro as
fallback), matching the PDF theme. Geometry constants (127px horizontal
pitch, 62px vertical pitch, 89×33 commit pills) are measured from the
existing Sketch-exported SVGs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rake tasks: figures:validate, figures:build, figures:render[name],
figures:raster, figures:check, figures:review.

Includes the first hand-authored JSON source for basic-branching-1
and its rendered SVG/PNG output.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Figures added: basic-branching-1, basic-branching-2, basic-merging-2,
two-branches, areas. Covers all shape classes: DAG commits, ref nodes,
other-kind nodes, diagonal merge edges, banner arrows, and rule dividers.

Renderer fixes:
- Grid y-pitch corrected to 62px (measured from original SVGs)
- Text baseline at y+21 to match original
- Vertical arrow direction logic handles all four ref/commit orderings
- SVG output includes width/height at 2x for correct browser rendering
- IMAGES_DIR/FIGURES_DIR env overrides for figures:check subprocess
- Review page uses absolute file:// paths

Visual comparison confirms near pixel-perfect parity with the
Sketch-exported originals (font differs by design: JetBrains Mono).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bin/svg-to-figure.rb parses images/*.svg and bootstraps figures/*.json
draft specs. It flattens nested SVG transforms, classifies rects by size
and fill color, infers grid pitch from node center clusters, and snaps
nodes to col/row coordinates.

Results on all 112 non-symbols SVGs:
  50 figures clean (< 3px residual)
  62 figures flagged (> 3px — need manual review)

Edges are not auto-detected; all figures get an empty edges array to fill.
Report written to tmp/extractor-report.json (not committed).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Auto-generated by bin/svg-to-figure.rb from images/*.svg.
All figures have node positions; edges are empty and must be added manually.
50 figures have < 3px grid residual; 62 are flagged for position review.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds edges to: basic-branching-3..6, basic-merging-1, basic-rebase-1..4,
head-to-{testing,master}, checkout-master, commits-and-parents,
commit-and-tree, rebasing-1..2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ches, merging-workflows

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… remote-branches, local, rerere, undomerge, replace figures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ches, large-merges, perils-of-rebasing, reset series, centralized_workflow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…manager, benevolent-dictator; regenerate Phase 4 SVGs

Fix data-model-1 and data-model-2 node extraction (missing tree nodes, wrong positions).
Add structural edges to data-model-3/4, clean, smudge, integration-manager, benevolent-dictator.
Regenerate SVGs for lifecycle, snapshots, deltas, centralized, distributed, managed-team-flow,
small-team-flow, symbols (no edge changes; SVGs updated from Sketch originals to renderer output).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Arrow paths for vertical/diagonal/horizontal-forward edges were building
the shaft correctly but then drawing the arrowhead at the wrong end
(back near the start point instead of at the tip), and the diagonal
arrow's shaft had zero width. Rewrote all of these to draw the
arrowhead at the tip, matching the original hand-drawn SVG idiom.

Also add commit-full/tree-full/blob-full node kinds for figures that
show actual git object contents (hash label, key/value rows, body
text) rather than the small symbol pills used elsewhere, and rewrite
commit-and-tree.json to use them with the real transcribed content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- edges support style: muted (thinner, lower-opacity) for secondary
  relationships, used for the pull fan-out in benevolent-dictator.json
- edges support arrow: both for double-headed arrows, used in
  centralized_workflow.json

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant