Skip to content

feat(mermaid): add terminal diagram renderer - #1351

Open
kitlangton wants to merge 34 commits into
anomalyco:mainfrom
kitlangton:feat/mermaid-package
Open

feat(mermaid): add terminal diagram renderer#1351
kitlangton wants to merge 34 commits into
anomalyco:mainfrom
kitlangton:feat/mermaid-package

Conversation

@kitlangton

@kitlangton kitlangton commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

What

Add @opentui/mermaid, a publishable OpenTUI package for rendering Mermaid-flavored flowchart, sequence, state, and timeline diagrams as terminal text and styled Markdown blocks.

The implementation comes from @kitlangton/merman and the production OpenCode integration.

How

  • Adds parsers, layout/routing, drawing, diagnostics, and plain renderers for all four diagram families.
  • Adds createMermaidMarkdownRenderer and createMermaidCodeBlockRenderer for OpenTUI Markdown integration.
  • Preserves the last valid diagram while a fence is streaming, without reusing a neighboring fence's positional cache after insertion.
  • Reuses custom renderables and prepared output in place while preserving margins, scroll state, dynamic colors, and non-streaming fallback behavior.
  • Speeds canvas output with tracked row extents, height-only measurement, and a Unicode-safe ASCII fast path.
  • Hardens flowchart obstacle, feedback, fan-in, mixed-subgraph, and label routing from a curated visual-QA corpus.
  • Adds a deterministic spatial-claims algebra for collision-safe semantic bodies, routes, and labels, with composition-law tests.
  • Normalizes Mermaid text consistently, including quoted labels, line breaks, Unicode, and named or numeric HTML entities.
  • Prevents sequence group overlap/excessive growth, respects multiline participant aliases, frames notes, renders activation intervals, and keeps filled arrowheads terminal-width safe.
  • Preserves nested state composite labels and explicit choice vertices, and routes parallel/composite transitions around occupied state bounds.
  • Provides semantic color roles and horizontal scrolling for wide diagrams.
  • Publishes a deliberately small root API while keeping layout/routing internals private.
  • Wires build, test, preview, snapshot, latest-release, and pre-publish workflows.
  • Includes package documentation, component docs, and entrypoint docs.
flowchart LR
  Source[Mermaid source] --> Detect
  Detect --> Parse
  Parse --> Layout
  Layout --> Draw[Styled grid]
  Draw --> Text[OpenTUI StyledText]
  Text --> Markdown[MarkdownRenderable]
Loading

Performance

A calibrated benchmark covers one medium fixture from each family and emits machine-readable METRIC lines.

macOS arm64, Bun 1.3.14, seven measured 400 ms rounds:

Stage Before After
Complete pipeline 1.411 ms 1.050 ms
AST to grid 1.247 ms 0.875 ms

The true-prefix Markdown streaming benchmark runs five revisions: reset, valid growth, invalid partial fallback, completion, and closing fence.

Streaming phase Before After Change
Complete cycle 1.213 ms 0.573 ms -52.7%
Valid growth 257 µs 168 µs -34.5%
Invalid fallback 112 µs 26 µs -76.5%
Closing fence 332 µs 58 µs -82.5%

Baseline diagnostics:

Stage Median per diagram RME
Detect 1.197 µs 1.08%
Parse 14.791 µs 1.92%
Grid to StyledText 87.072 µs 1.04%

Drawing dominates the current workload; parsing is roughly 1% of complete render time. This gives future Zig work a concrete target at the canvas/drawing boundary rather than the syntax layer.

Scope

This PR upstreams and optimizes the TypeScript implementation while establishing its performance contract. It does not add native Mermaid code; the measured TypeScript path is already sub-millisecond for the complete representative streaming cycle.

OpenCode-specific plugin registration and theme-token mapping remain in OpenCode; they can become a thin adapter over this package after release.

Testing

  • bun test in packages/mermaid: 313 pass
  • focused core Markdown suite: 158 pass
  • bunx tsc --noEmit -p tsconfig.json
  • bun run build in packages/mermaid
  • bun run test:dist --skip-build: clean built-artifact consumer import, typecheck, and all four family renders
  • npm pack --dry-run from packages/mermaid/dist: 20 files, 148.5 kB packed
  • Root bun run fmt:check
  • Root bun run lint
  • Root aggregate non-native package tests pass after building the expected SSH artifact
  • Calibrated pipeline and true-prefix streaming benchmarks, including a paired untouched-baseline worktree run
  • 33 curated raster diagrams plus deterministic stress matrices: 75 flowcharts / 495 routes, 48 sequences, and 48 state diagrams
  • Three-agent simplify review plus final strict review

The local full native build is blocked by Zig 0.15.2 versus current main's required Zig 0.16.0. The new Mermaid CI job uses the repository-pinned Zig 0.16.0 on Linux and Windows and performs build, source tests, and built-artifact consumer tests.

Demo

Direct @opentui/mermaid integration inside an OpenTUI MarkdownRenderable, with clean q teardown:

opentui-mermaid-pr.mp4

Timeline update

The package now also renders Mermaid timeline, timeline TD, and timeline LR fences as a terminal-native vertical spine. It supports titles, sections, standalone periods, inline and continued events, entities, <br> lines, comments, and accessibility metadata. The vertical form is intentional for narrow Markdown viewports; parsed Mermaid direction remains available through the public model.

Input:

timeline
  title From private fork to upstream profile in one day
  section Morning
    11:30 : Profile PR parked as draft
    12:05 : MCP transport fixes
          : Environment-spawner stdio transport
  section Midday
    13:16 : MCP stdio merged
    13:20 : Interrupt report lands
  section Afternoon
    14:07 : Workerd profile merged
    14:36 : Deployed and live self-test
Loading

Actual terminal output from renderTimelineDiagram:

From private fork to upstream profile in one day

  Morning ───┐
             │
    11:30 ───●  Profile PR parked as draft
             │
    12:05 ───●  MCP transport fixes
             │  Environment-spawner stdio transport
             │
   Midday ───┤
             │
    13:16 ───●  MCP stdio merged
             │
    13:20 ───●  Interrupt report lands
             │
Afternoon ───┤
             │
    14:07 ───●  Workerd profile merged
             │
    14:36 ───●  Deployed and live self-test
             │

Additional validation after the timeline update:

  • focused timeline and diagnostics tests: 29 pass
  • focused core Markdown suite: 158 pass
  • package typecheck and build
  • clean packed consumer importing and rendering all four families
  • root format and lint checks
  • synchronized OpenCode mirror #42130: 311 Merman tests and typecheck

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