Skip to content

feat: ERD diagram support (erDiagram syntax, crow's foot notation) - #50

Merged
topspinj merged 12 commits into
mainfrom
feat/erd-diagrams
Jul 10, 2026
Merged

topspinj merged 12 commits into
mainfrom
feat/erd-diagrams

Conversation

@topspinj

@topspinj topspinj commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds erDiagram as a supported diagram type (previously listed as unsupported)
  • Entities render as table boxes with a dark header, typed attribute rows, and PK/FK/UK badges
  • Relationships use crow's foot notation (exactly-one, zero-or-one, one-or-many, zero-or-many) with solid lines for identifying relationships and dashed for non-identifying
  • Full Mermaid-compatible syntax: entity attribute blocks (type name PK), cardinality markers (||, |o, |{, o{), relationship labels, %% comments
  • Both DOM renderer (renderERDSVG) and headless string renderer (renderERDString) implemented — works with Python package and rehype plugin

New files

File Purpose
src/parser/erd.ts Line-by-line erDiagram parser
src/layout/erd.ts Dagre-based entity layout with attribute-aware sizing
src/renderer/erd.ts DOM SVG renderer — entity boxes + crow's foot marks
src/renderer/erd-string.ts Headless string renderer for Python / rehype
tests/parser/erd.test.ts 11 parser tests covering syntax, cardinalities, attributes

API changes

  • toLayout() return type gains an optional erdLayout?: ERDLayoutResult field (populated for ERD inputs; layout stays empty)
  • New exports: parseERD, computeERDLayout, renderERDSVG, renderERDString, and all ERD types (ERDAST, ERDEntity, ERDRelationship, ERDAttribute, ERDCardinality, ERDLayoutResult, ERDLayoutEntity, ERDLayoutRelationship)
  • DiagramAST updated to FlowchartAST | ERDAST | UnsupportedDiagramAST

Test plan

  • Run npm run test:run — 157 tests, all pass
  • Run npm run lint — zero type errors
  • Open playground.html and paste an erDiagram to verify visual rendering (entity boxes, attribute rows, crow's foot marks, relationship labels, zoom/pan)
  • Verify all four cardinality types render correctly: ||, |o, |{, o{
  • Verify identifying (solid) vs non-identifying (dashed) relationship lines
  • Test with multiple themes (default, tufte, digital)

🤖 Generated with Claude Code

topspinj and others added 12 commits July 8, 2026 01:23
Adds first-class entity-relationship diagram rendering via Mermaid-
compatible erDiagram syntax. Entities render as table boxes with typed
attribute rows and PK/FK/UK badges; relationships use crow's foot
notation (exactly-one, zero-or-one, one-or-many, zero-or-many) with
solid (identifying) or dashed (non-identifying) lines.

New modules:
- src/parser/erd.ts — line-by-line erDiagram parser
- src/layout/erd.ts — dagre-based entity layout with attribute-aware sizing
- src/renderer/erd.ts — DOM SVG renderer (entity boxes + crow's foot)
- src/renderer/erd-string.ts — headless string renderer for Python/rehype

Public API additions: parseERD, computeERDLayout, renderERDSVG,
renderERDString, ERDLayoutResult, ERDCardinality, and related types.
toLayout() now returns an optional erdLayout field for ERD inputs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move the zero-or-many circle from MARK_DIST1 (12) to MARK_DIST3 (36) so it
sits beyond the crow-foot base instead of threading through the center prong.

Switch attribute name column from percentage-based (w*0.44) to fixed offset
(56px) and update layout width estimation per-column, giving consistent
spacing between name and PK/FK/UK badges regardless of entity width.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces Comic Sans MS fallback with Bradley Hand / Segoe Print.
Increases nodePadding x:30→46 to absorb Comic Neue's wider per-char
width vs the 0.62 layout estimator, preventing label overflow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Name-column start was fixed at 56px regardless of type text width.
Now computed dynamically as max(NAME_COL_X, widest_type_estimate+14)
in both layout (so the box widens) and renderers (so name text shifts
right to match). Fixes overlap when types like varchar(255) are used.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes 8 duplicated constants (HEADER_HEIGHT, ATTR_ROW_HEIGHT, etc.)
and normalize() that were copy-pasted verbatim across erd.ts and
erd-string.ts. Also removes dead uid()/_nextId code from erd.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
REL_TYPE used + quantifier, allowing mixed/repeated delimiters like
--.. to parse silently with the wrong identifying flag. Changed to
exact match (-- or ..) only.

Multi-key priority comment claimed PK > FK > UK but k1 ?? k2 just
took the first listed key. Now resolved correctly via find().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eparately

dagre.graphlib.Graph() is not a multigraph by default, so multiple
relationships between the same entity pair collapsed to one edge and
rendered as overlapping identical lines. Now uses { multigraph: true }
with per-relationship index as edge name, and for-loop with push
instead of .map() to preserve the index for edge retrieval.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… placeholder

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@topspinj
topspinj marked this pull request as ready for review July 10, 2026 19:59
@topspinj
topspinj merged commit 3fb4c2d into main Jul 10, 2026
4 checks passed
@topspinj
topspinj deleted the feat/erd-diagrams branch July 10, 2026 19:59
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