For those curious about the internals, here’s how a Mermaid diagram type comes together.
The Stack
Input (DSL) → Langium Grammar → Parser → AST → Database → Renderer → SVG
Each layer has a specific job. Let’s walk through them.
Grammar (wardley.langium)
The grammar defines what’s valid syntax. Langium makes this declarative:
WardleyComponent:
"component" id=ID label=STRING coords=Coordinates EOL
;
Coordinates:
"[" x=NUMBER "," y=NUMBER "]"
;
No imperative code. Just structure.
Parser + Database
The parser turns text into an AST. The database (wardleyDb.ts) stores the parsed data in a queryable format:
addComponent(id, label, x, y)addEdge(source, target)getComponents()
Clean separation. The renderer never touches the parser directly.
Renderer
The renderer (wardleyRenderer.ts) takes database state and produces SVG. Key responsibilities:
- Draw evolution stage backgrounds
- Position components on the map
- Draw dependency arrows
- Handle labels and collision avoidance
What I Learned
- Follow existing patterns: Mermaid’s Pie/Packet diagrams were my template
- Langium is the future: Cleaner than Jison, better tooling
- Tests matter: Integration tests caught several edge cases
- Docs are part of the PR: Nobody uses undocumented features
Future: Regions and More
The current implementation covers basics. Next on the list:
- Regions: Visual groupings for market segments
- Pipelines: Horizontal groupings at same visibility level
- Annotations: Notes and callouts
- Cynefin diagrams: Different strategic framework, similar architecture
Open source means this can grow with community input. The foundation is there.