StatifierUI.Diagram (StatifierUI v0.1.0)

Copy Markdown View Source

Renders a compiled Statifier.Machine and an active configuration as Mermaid stateDiagram-v2 source, for display via Kino.Mermaid (or any other Mermaid consumer - this module is pure and depends on neither Kino nor LiveView).

render/2 is a pure function: machine and configuration in, diagram source out. That interface is the stable part. The Mermaid backend is the Livebook inspector's first rendering (statifier-ui ADR-0008 fixes the destination stack as client-side elkjs producing SVG, and explicitly leaves this first cut to the inspector epic); when the elkjs renderer arrives it replaces the body of this module, not its callers.

The accepted Mermaid compromise

Mermaid cannot draw a transition between internal states of two different composite states - the cross-hierarchy edges SCXML's LCCA semantics make routine, and the limitation that disqualified Mermaid as the destination renderer (ADR-0008). Rather than drop those transitions, render/2 lifts each one to the pair of composite siblings under the endpoints' least common ancestor and draws the edge there, with a [lifted: <source> -> <target>] marker appended to the label naming the real endpoints. The same lifting applies to a composite's [*] initial marker when its resolved initial state is a deep descendant rather than a direct child - the marker there is [deep: <target>].

What the source contains

  • Every state except the synthesized :scxml root is declared with a stable s<index> alias (the engine's document-order state index, the identity vocabulary of statifier ADR-0012), so tests and callers can address nodes without depending on how labels are escaped.
  • Compound states are composite blocks; parallel states are composite blocks whose children are separated by Mermaid's -- region divider.
  • <final> states carry a (final) label suffix; history states carry (H) (shallow) or (H*) (deep) - Mermaid has no native pseudo-state notation for either.
  • Transitions are labeled with their event descriptors; a guarded transition carries a [cond] marker (the Machine retains the compiled expression, not its source text).
  • Active states - every index in the configuration, ancestors included, per the full-configuration convention of statifier-ui ADR-0005 - are assigned the active Mermaid class. Out-of-range indexes and the root are ignored, so a stale or empty configuration degrades to an unhighlighted chart rather than an error.

Summary

Functions

Renders machine with configuration highlighted, as Mermaid stateDiagram-v2 source.

Functions

render(machine, configuration)

@spec render(Statifier.Machine.t(), Enumerable.t()) :: String.t()

Renders machine with configuration highlighted, as Mermaid stateDiagram-v2 source.

configuration is any enumerable of state indexes - typically the full active configuration (MapSet.t(non_neg_integer())) a trace message or Statifier.MachineState carries. Pass [] (or an empty set) for a chart that is not running.

Examples

iex> {:ok, machine} =
...>   Statifier.compile("""
...>       <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="on">
...>         <state id="on">
...>           <transition event="toggle" target="off"/>
...>         </state>
...>         <state id="off"/>
...>       </scxml>
...>   """)
iex> source = StatifierUI.Diagram.render(machine, [1])
iex> String.starts_with?(source, "stateDiagram-v2")
true
iex> source =~ "class s1 active"
true