CharGraph layout
Ownership and constraints for source-to-cell graph layout.
HEAD a63778eCharGraph layout
CharGraph routes diagrams by coordinate model, not Mermaid diagram name:
| Model | Diagrams | Layout owner |
|---|---|---|
| Directed relationships | Flow, State, Class, and ER | ELK Layered |
| Time sequence | Sequence | Participant columns and message rows |
| Cartesian data | Mermaid XY and Vega-Lite fences | CartesianChartSpec and D3 scales |
The directed-graph pipeline is:
Mermaid AST -> diagram adapter -> LayoutGraph + presentation sidecar
LayoutGraph -> ELK Layered -> integer cell projection -> GridLayout
GridLayout + presentation sidecar -> CharScene
Mermaid support is a reliable subset. Preprocessing removes comments and splits
top-level semicolon statements; a diagram renders only when every remaining
statement is consumed. Invalid syntax, unsupported directives, subgraph-edge
targets, and subgraph direction overrides preserve the complete source with a
diagnostic. The diagnostic remains metadata and never replaces the preserved
artifact body. Parsers must not return a partial AST. Sequence activation uses
the participant lifeline itself: + activates the receiver and - deactivates
the sender; standalone activate and deactivate commands share the same
source-ordered timeline as messages, notes, and block boundaries. Both forms
support nested intervals. Its sequence.activation style role
defaults to the render theme's warning token independently of participant borders.
LayoutGraph owns measured rectangular nodes, containment, labels, directed
edges, and rank constraints. It does not own Unicode glyphs, rounded corners,
line styles, or UML markers. The sidecar owns node drawing, stroke appearance,
and endpoint decoration, keyed by stable layout IDs. ELK owns layering,
ordering, crossings, ports, and orthogonal bends. Cell projection owns integer
coordinates, compact self-loops, route-aware labels, and topology validation.
An independent edge cannot share a node port, marker cell, or collinear route
cell; a perpendicular cell crossing remains valid. CharScene alone owns glyph
composition. Scene layers decide which contribution is visible, while explicit
connections and route bundles decide which contributions may share topology.
Container borders sit above edges but never join them; node borders remain
connective. Thick Mermaid edges use double-line topology while retaining ASCII
arrow markers; CharScene resolves mixed single/double junctions at borders and
crossings. A parallel Mermaid style-role canvas records visual meaning without
affecting geometry. Serialization groups adjacent equal style roles into
CharGraph fragments after layout and CJK-safe cell projection.
Flow assigns alignment priority from topology. On the SCC condensation graph, an edge with a multi-hop alternative is a shortcut; the longest remaining path is the visual backbone. ELK straightens that backbone while shortcuts use an outer corridor. When the remaining backbone is one chain containing every node, integer projection aligns its node centers on the cross axis before endpoint routing. Cycles and parallel edges remain ordinary relationships.
Flow edges opt into structured routing after cell projection. Only compatible, unlabelled fan-out or fan-in edges whose branch nodes occupy the same layer may share an explicit orthogonal bus. Labeled branches and cross-layer shortcuts remain independent. Labels competing at one endpoint reserve layout space; single-path labels remain route-placed. Mermaid edge labels reserve one blank cell on each horizontal side, so they do not visually merge with strokes, markers, or node borders. When continuous ELK attachments collapse onto one cell, Flow keeps the highest-priority aligned edge on the primary side and distributes other endpoint owners across free primary and perpendicular border cells. A bundle is one endpoint owner. Class and ER retain their diagram-specific port policies. A complete bipartite motif remains independent instead of being interpreted as overlapping fan buses. Larger cross-fans use independent ELK ports only when both sides compete and one side has at least three incident edges; ordinary decision fans keep their topology-aligned ports.
Marker cells are terminal and exclusive. After integer projection, invalid independent routes are repaired around nodes, marker corridors, and collinear routes before labels are placed and the scene is composed. Flow repair locks routes in topology-priority order, so lower-priority branches and shortcuts move around the backbone rather than deforming it. Readable Flow routes also prefer one visible line cell between an endpoint and its nearest bend. Strongly connected graphs skip DAG backbone priorities because they have no intrinsic forward path. Flow and State share terminal-corridor separation and stable route locking, and opt into readable routing: overlapping opposite endpoints share an axis when possible. Compact self-loops use two distinct node endpoints; multiple loops rotate across node sides so their routes and labels remain distinct. Route repair compares strict and relaxed orthogonal candidates by short legs, bends, length, area, then stable order instead of accepting the first feasible detour. Rounded glyphs therefore express real detours rather than search artifacts. Flow and State also opt into Brandes–Köpf balanced node placement; Class and ER retain ELK's automatic placement.
Flow presents every node as the same rounded card. Mermaid shape semantics are
retained by a first-line marker inside that card; multiline continuation text
aligns after the marker. node.border owns every structural node border, and
flow.node.marker owns the Flow shape signal. Every structural edge consumes
its source node's node.border, so line and arrow cannot diverge from that
border. Legacy flow.node.border, edge.line, and edge.arrow inputs are
ordered compatibility fallbacks, not output roles. Edge labels remain
independent. Topology does not assign colors. XY series retain independent
series.1–series.5 roles.
CartesianChartSpec is the renderer-facing chart contract. Linear axes retain
numeric coordinates; band axes retain ordered categories. D3 owns domain,
ticks, and scale projection; Unicode rendering owns integer-cell quantization
and mark glyphs. Vega-Lite unit specs and flat layers adapt inline data.values
into that contract. Unsupported URL data, transforms, facets, repeats, and
concatenation preserve the fenced source with a diagnostic.
The shared layered renderer owns layout invocation, validation, group-edge-node
composition order, route labels, cropping, and serialization. Diagram adapters
may contribute node and endpoint painters but do not repeat those steps. Flow,
State, Class, and ER use this contract. Class enables distributed ports and
keeps UML compartments, namespaces, cardinalities, and relationship markers in
its presentation sidecar. ER opts into one fixed-order ELK port per relationship
endpoint, expands an entity only when its border lacks port capacity, and reserves
the complete direction-aware crow's-foot marker corridor. ER labels are placed
against the projected route, and self-relationships use the compact grid route.
Its semantic relationships remain undirected while an optional Mermaid
direction controls layout orientation; declaration order supplies stable
orientation when no direction is declared.
State preserves parser-level diagram identity, uses depth-first cycle breaking
from its ranked pseudostates, and projects ELK attachment positions onto
adaptive node ports: one attachment stays centered while a shared side remains
distributed. Labels may be placed left or above the projected route; the final
grid is translated back to a nonnegative origin. Feedback cycles therefore stay
readable without inflating layer spacing. Initial and final pseudostates use the
independent state.start and state.end semantic roles; their adjacent edges
retain node.border.
Sequence keeps its participant-column coordinate model and consumes the same
scene-layer contract for lifelines, fragment borders, nodes, labels, and markers.
For a feasible layout, priorities are ordered rather than mixed into unstable weights: direction, crossings, bends, Manhattan edge length, area, then stable source order. Diagram-specific placement exceptions do not belong in the shared layout engine; add an adapter or use the correct coordinate model.
Flow, State, Class, and ER rendering is asynchronous because browser layout runs in a worker. Worker-less runtimes use the same ELK adapter inline. A layout or projection failure returns the existing Mermaid diagnostic fallback; the old placement algorithm is not a fallback path.