xstate-plantuml icon indicating copy to clipboard operation
xstate-plantuml copied to clipboard

Visualization of xstate statecharts using plantuml

Visualization for xstate using plantuml

Given an xstate definition of a statechart, this tool will output a plantuml source rendering of the statechart.

Installation:

(global install)

npm -g install

Usage:

xstate-plantuml <requireablepackage>

or (if not installed globally)

npm run main <requireablepackage>

The code will "require" the first argument, expecting it to be a full machine definition, and will print out a plantuml source code that corresponds to the statechart.

Example invocation:

xstate-plantuml ./on-off

will load the ./on-off.json file and print out the PlantUML diagram source code

For example, given the following statechart:

{
  "initial": "Off",
  "states": {
    "Off": {
      "on": {
        "FLICK": "On"
      },
      "initial": "A",
      "states": {
        "A": {
          "on": {
            "FLICK": "A",
            "UNBLOCK": "B"
          },
          "onEntry": {
            "type": "startUnblockTimer",
            "delay": 2000
          },
          "onExit": {
            "type": "cancelUnblockTimer"
          }
        },
        "B": {}
      }
    },
    "On": {
      "on": {
        "FLICK": "Off"
      },
      "initial": "C",
      "states": {
        "C": {
          "on": {
            "UNBLOCK": "D"
          },
          "onEntry": {
            "type": "startUnblockTimer",
            "delay": 500
          },
          "onExit": {
            "type": "cancelUnblockTimer"
          }
        },
        "D": {
          "onEntry": {
            "type": "turnOn"
          },
          "onExit": {
            "type": "turnOff"
          },
          "initial": "E",
          "states": {
            "E": {
              "on": {
                "UNBLOCK": "F"
              },
              "onEntry": {
                "type": "startUnblockTimer",
                "delay": 500
              },
              "onExit": {
                "type": "cancelUnblockTimer"
              },
              "initial": "G",
              "states": {
                "G": {
                  "on": {
                    "FLICK": "G"
                  }
                }
              }
            },
            "F": {}
          }
        }
      }
    }
  }
}
left to right direction
@startuml
 [*] --> Off
 state Off {
   [*] --> A
   Off --> On: FLICK
   state A {
     A --> A: FLICK
     A --> B: UNBLOCK
     A: onentry / startUnblockTimer
     A: onexit / cancelUnblockTimer
   }
   state B {
   }
 }
 state On {
   [*] --> C
   On --> Off: FLICK
   state C {
     C --> D: UNBLOCK
     C: onentry / startUnblockTimer
     C: onexit / cancelUnblockTimer
   }
   state D {
     [*] --> E
     D: onentry / turnOn
     D: onexit / turnOff
     state E {
       [*] --> G
       E --> F: UNBLOCK
       E: onentry / startUnblockTimer
       E: onexit / cancelUnblockTimer
       state G {
         G --> G: FLICK
       }
     }
     state F {
     }
   }
 }
@enduml

This results in the following diagram, after running it through PlantUML:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="342px" preserveAspectRatio="none" style="width:1496px;height:342px;" version="1.1" viewBox="0 0 1496 342" width="1496px" zoomAndPan="magnify"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="19" x="301" y="105.9951">Off<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="9" x="248" y="190.292">A<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="174" x="160" y="214.7324">onentry / startUnblockTimer<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="175" x="160" y="228.7012">onexit / cancelUnblockTimer<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="10" x="471" y="197.292">B<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="34" x="235.5" y="145.3638">FLICK<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="63" x="369" y="200.3638">UNBLOCK<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="20" x="1047" y="25.9951">On<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="10" x="790.5" y="167.792">C<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="174" x="703" y="192.2324">onentry / startUnblockTimer<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="175" x="703" y="206.2012">onexit / cancelUnblockTimer<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="11" x="1217" y="65.292">D<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="103" x="999" y="84.7324">onentry / turnOn<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="93" x="999" y="98.7012">onexit / turnOff<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="9" x="1157.5" y="137.5264">E<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="174" x="1067" y="156.9668">onentry / startUnblockTimer<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="175" x="1067" y="170.9355">onexit / cancelUnblockTimer<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="11" x="1149.5" y="254.7607">G<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="34" x="1138" y="209.8325">FLICK<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="8" x="1384" y="203.5264">F<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="63" x="1281" y="206.5981">UNBLOCK<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="63" x="912" y="177.8638">UNBLOCK<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="34" x="565" y="165.5669">FLICK<text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="34" x="565" y="190.5669">FLICK<!-- @startuml left to right direction

[] - -> Off state Off { [] - -> A Off - -> On: FLICK state A { A - -> A: FLICK A - -> B: UNBLOCK A: onentry / startUnblockTimer A: onexit / cancelUnblockTimer } state B { } } state On { [] - -> C On - -> Off: FLICK state C { C - -> D: UNBLOCK C: onentry / startUnblockTimer C: onexit / cancelUnblockTimer } state D { [] - -> E D: onentry / turnOn D: onexit / turnOff state E { [*] - -> G E - -> F: UNBLOCK E: onentry / startUnblockTimer E: onexit / cancelUnblockTimer state G { G - -> G: FLICK } } state F { } } } @enduml

PlantUML version 1.2018.00(Thu Jan 04 19:42:56 UTC 2018) (GPL source distribution) Java Runtime: Java(TM) SE Runtime Environment JVM: Java HotSpot(TM) 64-Bit Server VM Java Version: 1.7.0_25-b15 Operating System: Linux Default Encoding: UTF-8 Language: en Country: US -->

(Thanks to PlantText for the rendering services!)