Instantly* transform your MermaidJS into a Finite State Machine / Statechart into actual code you can run in XState! Save time over hand-coding both seperately.
*OK a bit of a strech here; not 'instant', you do have to run this script, taking a few ms of your time. & the output is missing functions, might have some bugs, but gets you 70% of the way there!
2024-05-25.22.29.41.mp4
Click to show text example.
Similar to Markdown, MermaidJS is a simple text format for basic diagrams.
Start & end points are flagged with [*]
, %%
preceed comments, and colins :
flag an event (named transition).
Below is a simple example from MermaidJS docs, used as a source.
stateDiagram-v2
id mermaidJS state diagram
%% inspiration: https://mermaid.js.org/syntax/stateDiagram.html
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still : STOP %% named transition / event
Moving --> Crash
Crash --> [*]
Mermex takes the MermaidJS text file, then translates it into an "Object State Machine", an intermediate notation that is not meant to consumed directly (though still human readable).
If there are no specified named transitions (events) in the Mermaid source, then programmically one is assigned with [source]--[target]
nominclature.
{
"final": [
"Still",
"Crash",
],
"id": "mermaidJS state diagram",
"initial": "Still",
"isConcurrent": false,
"states": {
"Still": {
"Still--FINIS": "FINIS",
"Still--Moving": "Moving",
},
"Moving": {
"STOP": "Still",
"Moving--Crash": "Crash",
},
"Crash": {
"Crash--FINIS": "FINIS",
},
"FINIS": "final",
},
}
Finally, the OSM has been transformed into executable code for XState.
Note: to create a "final" state for states that have more than one event, a state named "FINIS" is created to be assigned type: "final"
import { createMachine } from "xstate";
export const machinemermaidJSstatediagram = createMachine({
id: "mermaidJS state diagram",
initial: "Still",
states: {
Still: { on: {
"Still--FINIS": {
target: "FINIS"
},
"Still--Moving": {
target: "Moving"
} } },
Moving: { on: {
STOP: {
target: "Still"
},
"Moving--Crash": {
target: "Crash"
} } },
Crash: { on: {
"Crash--FINIS": {
target: "FINIS"
} } },
FINIS: {
type: "final"
}
} });
Clone/download this repo, then try out the examples MermaidJS in test/mmd
. You can use either NodeJS or Bun to run mermex-cli.js
❯ bun run mermex-cli.js
Please input path & file for mermax to process:
? test/mmd/mermaid.mmd
Please enter output path (empty/malformed = input path):
? test/xstate
creating folder: test/xstate
test/xstate/mermaid.machine.js 💾 written to file
NOTE: the CLI is a helper & example on how to use the files in the /src
folder. If you want to use them in your own project, copy the contents of /src
into your own project, then
import { mermaidToObject } from "YOURPATH/src/origins/mermaid.js"
import { xstateObjToxstateJS } from "YOURPATH/src/targets/xstate.js"
...
const xstateProgram = xstateObjToxstateJS( mermaidToObject(mermaidText) )
MermaidJS state diagram as source
Supported:
- Composite states (also called "children")
- named transitions (also called "events"; without names the default is
SOURCE--DESTINATION
) - comments, both inline & End Of Line
- Concurrency ("parallel states")
- Start ("initial") and End ("type: final", may need
FINIS
state)
NOT Supported:
<<choice>>
, workaround: use, if: guardName
(note comma)<<fork>>
(useif
conditions)<<join>>
(simply target the same state)
- anything GUI; note, direction, classDefs
Supported:
- FSM, much of Statecharts
- Events and transitions
- Initial & Final (FINIS) states
- Parent/Children states
- Parallel states, including onDone transition
NOT Supported (yet)
- Context
- functions for actions
"State Machine Rosetta Stone", multiple source & desination formats
- 0 (no) Dependencies for mermex, only for CLI file I/O, & testing
bun test
to test against snapshots,bun test --update-snapshots
if you change behavour