moonrockz/diagrams
Diagramming for MoonBit. The library will support formats such as Mermaid, PlantUML, Draw.io and Graphviz DOT.
Each diagram kind has one model that does not depend on a format. All formats of that kind read into it and write from it. The packages are:
| Package | Contents |
|---|---|
moonrockz/diagrams |
Diagnostic, Severity, Span and Position, which all modules use |
moonrockz/diagrams/sequence |
The immutable Sequence model, links, render properties and link resolution |
moonrockz/diagrams/bpmn |
Immutable process/collaboration views, graphical markers and ownership |
moonrockz/diagrams/swimlane |
Immutable responsibility lanes, groups, shapes, connections and validation |
moonrockz/diagrams/flowchart |
Immutable actions, control regions, graph connections, groups, explicit lanes, notes and validation |
moonrockz/diagrams/regex |
Immutable regex expressions: literals, classes, sets, anchors, groups, lookarounds, alternatives and symbolic repeats |
moonrockz/diagrams/ebnf |
Immutable grammars: ordered rules and notes, terminals, symbolic references, options, repetitions, counts and exclusions |
moonrockz/diagrams/data-tree |
Immutable ordered data: objects, arrays, exact-number scalars, member identities and view highlights |
moonrockz/diagrams/railroad-trace |
Railroad topology, immutable trace values, the RailroadTraceProvider trait and trace validation |
moonrockz/diagrams/animation |
Source-bound catalogs, oriented routes and explicit-time motion |
moonrockz/diagrams/render |
The Renderer trait, the Diagram enum and the Rendered result |
moonrockz/diagrams-mermaid reads Mermaid and moonrockz/diagrams-plantuml reads
PlantUML into these models, and
moonrockz/diagrams-svg renders them as SVG. Requirements come as OpenSpec
changes in openspec/changes/.
Sequence values
Sequence holds ordered participants and events, a title and accessibility
fields. Events are messages, notes, activation starts and ends, creation,
destruction, nested frames and autonumber changes. Frames have one or more
sections; each section has an optional label and ordered events. Constructors
copy caller-owned arrays, including arrays nested in sections and notes.
Participants have a declared kind, an optional box group, a link and render
properties. Messages have a line style, a head at each end, an optional number,
a link and render properties. Participant::with_properties and
Message::with_properties return new values. Participant::render_kind chooses
the render property kind and otherwise returns the declared kind.
A Link has a typed LinkScheme, Smithy or OpenRpc, and a target string.
Smithy targets use canonical IDs such as example.weather#Weather.
Implement LinkSource for a pure source adapter and call resolve(sequence, source). Its participant and message methods return optional render
properties for a link. Resolution visits nested frame sections, returns a new
sequence and preserves participant and event order, labels, links, groups,
numbering and metadata. An absent target produces a warning with code
sequence/unresolved-link and the target, and preserves any existing
properties. Source adapters cannot replace the diagram structure through this
contract. The Smithy and OpenRPC adapters belong to later changes.
BPMN compatibility
Diagram now includes Bpmn(view). Callers with exhaustive enum matches must
handle this case. The immutable visual values are in moonrockz/diagrams/bpmn;
source-bound motion plans and structural queries are in
moonrockz/diagrams/animation.
The independent BPMN document module does not depend on these packages. The
module guides describe document coverage, view selection and rendering policies.
Existing sequence models and static SVG bytes keep their current behavior.
Swimlane compatibility
Diagram::Swimlane(view) adds responsibility-based diagrams alongside sequence
and BPMN. Callers with exhaustive Diagram matches must add this case. The
swimlane model depends on neither Mermaid spelling nor BPMN documents.
Constructors copy ordered collections. Global direction is independent of each
lane/group's local direction, and never reverses a connection's source/target.
Nodes can be unowned; nested groups do not create extra lanes. Asset-dependent
shape identities remain values and fail SVG rendering explicitly.
The animation package adds typed swimlane occurrences and endpoint kinds.
Route.reversed and Motion::OrientedStep retain traversal orientation while
ordinary Motion::Step retains its forward-path meaning. Headless connections
require EdgeKind::Undirected in structural route selection. Lane membership
never adds a path. Existing sequence-specific Mermaid APIs remain unchanged.
Regex, EBNF and data-tree compatibility
Diagram now includes Regex(model), Ebnf(grammar) and DataTree(tree).
Callers with exhaustive Diagram matches must add these cases. The three models
are flat, immutable arenas: composite nodes name their children by identity, so
validate and Index::build find missing nodes, containment cycles and orphans
without recursion. Constructors copy caller arrays. Identities come from
ownership paths or explicit caller values, never from labels.
- Regex bounds are symbolic;
{1000000}is one node. Assertions are constraints, not alternatives. - EBNF references resolve by name. A missing or repeated name is a warning and stays a visible nonterminal; an explicit target identity that names no rule is an error. Recursive references never expand. An exclusion constrains its left term.
- Data trees keep member order, repeated names and exact number lexemes. Scalar text is never a reference.
The animation package adds OccurrenceKind::Railroad, DataConnector and
Visit, the VisitKind enum, Motion::Visit, NodeKind::RailroadPoint and
DataValue, EdgeKind::Railroad and Containment, and the visit field of
ScheduledStep and Active. Occurrence has four new optional fields. Callers
with exhaustive matches, or with record literals of these types, must add the new
cases and fields. Existing connection steps, orientation and BPMN, sequence and
swimlane behavior are unchanged.
///|
test "a constructed grammar keeps a recursive reference symbolic" {
let grammar = @ebnf.Grammar::new(
"lists",
[Rule(@ebnf.Rule::new("r", "list", body="s"))],
[
@ebnf.Node::new("s", Sequence(["x", "o"])),
@ebnf.Node::new("x", Terminal("x", Double)),
@ebnf.Node::new("o", Optional("again")),
@ebnf.Node::new("again", Reference("list", None)),
],
)
let index = @ebnf.Index::build(grammar).index.unwrap()
assert_eq(index.resolution("again"), Some(Resolved("r")))
assert_eq(grammar.nodes.length(), 4)
}
Flowchart compatibility
Diagram::Flowchart(view) uses the same format-independent model for Mermaid
flowcharts and both PlantUML activity dialects. Nodes keep shape identity
separate from typed control roles; plain Mermaid diamonds do not acquire
execution semantics. Notes distinguish node targets from connection targets.
Connection direction hints affect placement without reversing semantic endpoints.
Constructors and transformations copy mutable input collections.
Exhaustive consumers must add the flowchart renderer, catalog, node/visit and scene variants. Mermaid dispatch and PlantUML document/kind enums also have new variants. Existing named APIs and sequence, BPMN, swimlane, architecture, railroad and data-tree contracts remain available. Read the checked model guide and playback guide.