sverweij / state-machine-cat Goto Github PK
View Code? Open in Web Editor NEWwrite beautiful state charts :scream_cat:
Home Page: https://state-machine-cat.js.org
License: MIT License
write beautiful state charts :scream_cat:
Home Page: https://state-machine-cat.js.org
License: MIT License
Hello,
currently I am using your project to visualize a state machine in a web-page using this code based on the inpage.html example:
<script type="text/x-smcat" src="state_diagram.smcat" data-dot-graph-attrs="splines=ortho"></script>
The file state_diagram.smcat is auto generated every second by an external application. The SVG image needs to be regenerated. What is the best way using your library?
Thanks
Marco
The smcat
cli ignores the --input-type
parameter - it just infers the input file format from the extension. This means the input type is not overridable. Notably annoying when processing input from stdin (cf #56).
The cli takes the --input-type parameter
into account
It doesn't
echo '{"states":[{"name":"a", "type":"regular"}]}' | smcat --input-type json --output-type scxml -
Should import library and generate SVG from example
After adding minimal code to import the library and call the render function, starting the react app using the default "npm start" script causes the compiler to throw and out of memory error
<--- Last few GCs --->
[5660:00000197D18FBE40] 71158 ms: Mark-sweep 2016.1 (2051.7) -> 2015.9 (2052.2) MB, 3223.0 / 0.1 ms (average mu = 0.074, current mu = 0.001) allocation failure scavenge might not succeed
[5660:00000197D18FBE40] 75705 ms: Mark-sweep 2016.6 (2052.2) -> 2016.3 (2052.2) MB, 4543.2 / 0.1 ms (average mu = 0.031, current mu = 0.001) allocation failure scavenge might not succeed
<--- JS stacktrace --->
==== JS stack trace =========================================
0: ExitFrame [pc: 00007FF63FC3224D]
Security context: 0x03b7d0d00919 <JSObject>
1: print [000002D0EDC04DE1] [C:\Users\spenc\workspace\state-machine-test\node_modules\@babel\generator\lib\printer.js:~244] [pc=000002027C84DEDE](this=0x030cbe740289 <Printer map = 0000039DF858BA89>,0x016d51cd5b59 <Node map = 00000191C79F6BE9>,0x016d51cd2fe9 <Node map = 0000039DF85AF0C9>)
2: AssignmentExpression [000002058C0E2549] [C:\Users\spenc\w...
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
Writing Node.js report to file: report.20200221.095452.5660.0.001.json
Node.js report completed
1: 00007FF63F07F0DF napi_wrap+121039
2: 00007FF63F0251D6 public: bool __cdecl v8::base::CPU::has_sse(void)const __ptr64+34470
3: 00007FF63F025E96 public: bool __cdecl v8::base::CPU::has_sse(void)const __ptr64+37734
4: 00007FF63F8189AE private: void __cdecl v8::Isolate::ReportExternalAllocationLimitReached(void) __ptr64+94
5: 00007FF63F800951 public: class v8::SharedArrayBuffer::Contents __cdecl v8::SharedArrayBuffer::Externalize(void) __ptr64+833
6: 00007FF63F6CEC8C public: static void __cdecl v8::internal::Heap::EphemeronKeyWriteBarrierFromCode(unsigned __int64,unsigned __int64,class v8::internal::Isolate * __ptr64)+1436
7: 00007FF63F6D812F public: void __cdecl v8::internal::Heap::ProtectUnprotectedMemoryChunks(void) __ptr64+1279
8: 00007FF63F6D6614 public: static bool __cdecl v8::internal::Heap::PageFlagsAreConsistent(class v8::internal::HeapObject)+3204
9: 00007FF63F6CC263 public: bool __cdecl v8::internal::Heap::CollectGarbage(enum v8::internal::AllocationSpace,enum v8::internal::GarbageCollectionReason,enum v8::GCCallbackFlags) __ptr64+1235
10: 00007FF63F6CAB04 public: void __cdecl v8::internal::Heap::AddRetainedMap(class v8::internal::Handle<class v8::internal::Map>) __ptr64+2356
11: 00007FF63F6EA315 public: class v8::internal::Handle<class v8::internal::HeapObject> __cdecl v8::internal::Factory::NewFillerObject(int,bool,enum v8::internal::AllocationType) __ptr64+53
12: 00007FF63F458FAD public: class v8::internal::interpreter::JumpTableTargetOffsets::iterator & __ptr64 __cdecl v8::internal::interpreter::JumpTableTargetOffsets::iterator::operator=(class v8::internal::interpreter::JumpTableTargetOffsets::iterator && __ptr64) __ptr64+3981
13: 00007FF63FC3224D public: virtual bool __cdecl v8::internal::SetupIsolateDelegate::SetupHeap(class v8::internal::Heap * __ptr64) __ptr64+575565
14: 000002027C84DEDE
npm ERR! code ELIFECYCLE
npm ERR! errno 134
npm ERR! [email protected] start: `react-scripts start`
npm ERR! Exit status 134
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\spenc\AppData\Roaming\npm-cache\_logs\2020-02-21T09_54_53_392Z-debug.log
Process finished with exit code 134
Created a react app using:
npx create-react-app state-machine-test --typescript
npm i state-machine-cat --save
App.tsx
component import {render as smcat} from 'state-machine-cat';
npm start
Alternatively, clone the following:
npm start
Looks like a really cool library so it'd be a shame not to use it!
This model gives different outputs when I'm using it via the NPM module vs when I try it on the official website - see screenshots
let lSVGInAString = smcat.render(data, {
inputType: "smcat-json", //unknown value actually leads to pass through. data is pre-parsed JSON
outputType: "svg",
direction: "left-right"
});
document.getElementById("svg-stama").innerHTML = lSVGInAString;
I'm unsure if I'm doing something wrong or the code is truly different...
Can I still enter the XMI output file format ?
Hi,
never done it before, but hopefully I'm not the only one trying do use it in a typescript environment.
Do you have a short and clean example of how to include your lib in an Angular project?
Thanks in advance
When rendering a SCXML with an outgoing transition from a parallel state it is rendered like from a compound state.
The transition gets lost and is not rendered.
In this scxml
<?xml version="1.0" encoding="UTF-8"?>
<scxml version="1.0" initial="Start">
<state id="Start">
<transition event="_FORK" target="ParallelState"/>
</state>
<!-- change PrallelState from "parallel" to "state",
then it renders as expected -->
<parallel id="ParallelState">
<transition target="Done"/>
<state id="Region1">
<initial>
<transition target="State1"/>
</initial>
<state id="State1">
<transition event="_DONE1" target="Final_1"/>
</state>
<final id="Final_1"/>
</state>
<state id="Region2">
<initial>
<transition target="State2"/>
</initial>
<state id="State2">
<transition event="_DONE2" target="Final_2"/>
</state>
<final id="Final_2"/>
</state>
</parallel>
<state id="Done">
<transition event="_END" target="Final_3"/>
</state>
<final id="Final_3"/>
</scxml>
Change PrallelState from "parallel" to "state", then it renders as expected.
It could be just the import of the SCXML, because here
stama-visualiser
there is an outgoing transition from a parallel state in the example diagram.
Thanks for having a look, b.t.w. awsome tool!
The size of the state rectangles are sometimes unnecessarily large, often when sub-states are present.
Possibly related to #124.
The size of the state rectangle should be no larger than required to contain the sub-states.
Sometimes the state rectangles are much larger than necessary.
Using the same example as #124, as the root cause seems to be related:
root.initial,
s1,
s2 [type=parallel] {
s3 {
s3.initial,
a_very_long_name_just_to_emphasize_the_issue;
};
},
c1 [type=choice],
j1 [type=junction],
final;
root.initial -> s1;
s1 -> c1 : "ev1";
s2 -> s1 : "tm(3)";
s3.initial -> a_very_long_name_just_to_emphasize_the_issue;
c1 -> j1 : "[is_ready()]";
c1 -> s1 : "[else]";
j1 -> s2 : "";
s2 -> final : "strangely_placed_text";
This is a minor issue, since the diagram is still readable but can still be difficult to read.
https://state-machine-cat.js.org/
Version: 7.0.3
Is this possible? It seems that any node name that has initial or final as a substring will become special nodes.
from a quick glance, it's unclear if state-machine-cat is a superset of mermaid-js. It would be nice, if so, if it could parse mermaidjs state diagrams as a language.
it would just be neat, especially since i'm used to mermaid's syntax
it would be a new input type
supported input are smcat, json and scxml
well, just using mermaid, of course.
I am trying to convert a simple smcat file to SVG:
➜ cat test.smcat
initial,
"media player off",
"media player on" {
stopped, playing, paused;
stopped => playing : play;
playing => stopped : stop;
playing => paused : pause;
paused => playing : play;
paused => stopped : stop;
};
initial => "media player off";
"media player off" => stopped : power;
"media player on" => "media player off" : power;
I expect smcat -o test.svg < test.smcat
to create that SVG file.
➜ smcat -o test.svg < test.smcat
(node:11096) V8: /usr/local/lib/node_modules/state-machine-cat/node_modules/viz.js/viz.js:33 Invalid asm.js: Function definition doesn't match use
Seems this is related to this upstream bug in viz.js
that was never fixed. Now this project is archived, and it seems there is no obvious solution to the issue. I think it cannot be used as a dependency anymore.
The same error is referenced in this issue as well. One solution is proposed: to use dagre instead.
Thanks for this great project and sorry for the strange title. When nested states reference themself the rendered outpout looks weird and it's hard to see what is happening in the statechart:
I would expect that a transition from a nested state to itself looks the same as a non nested-state to itself.
The transition of a nested state to itself is drawn inside of the nested state which is easy to miss when looking at the diagram.
Not sure
This is the diagram I am drawing:
initial,
"media player off",
"media player on" {
stopped, playing, paused;
stopped => playing : play;
playing => stopped : stop;
playing => paused : pause;
paused => playing : pause;
paused => stopped : stop;
};
initial => "media player off";
"media player off" => stopped : power;
"media player on" => "media player off" : power;
"media player off" => "media player off";
"media player on" => "media player on";
I'm trying to build a visualizer for an ember-addon https://github.com/LevelbossMike/ember-statecharts that I am working on and would like to use state-machine-cat as the project that creates the visual output.
I'm using the web-editor.
Thanks again for this great project! I'm using your diagramming tool nearly every day and it makes my dev-life much easier 🍻
First of all I think this is the best javascript library for drawing state machines I could find - and i found a lot of libraries. This is the only one that handles compound states very well.
I seem to have found a small bug: The display of state declarations inside compound states are quirky:
The line separating the state name and its declarations should expand to the whole width of the compound state node.
The separating line is too short.
Example state machine:
initial,
"media player off":
entry / init()
do / idle()
exit / poweron(),
"media player on" :
entry / init()
do / idle()
exit / poweroff() {
mpo.initial, stopped, playing, paused;
mpo.initial => stopped;
stopped => playing : play;
playing => stopped : stop;
playing => paused : pause;
paused => playing : pause;
paused => stopped : stop;
};
initial => "media player off";
"media player off" => "media player on" : power;
"media player on" => "media player off" : power;
I'm trying to let the program draw state machines with nested compound states and declarations
Web browser Google Chrome 80.0.3987.149 64-bit
pointed to the online editor (https://state-machine-cat.js.org/)
how to specify object position? like x,y coordinate.
It is possible to add the address from bottom to top
See title - set up GitHub actions for this repository (see GitHubs actions landing page and their documentation for background information)
GitHub actions are potentially a nice addition to the continuous integration options out there, and with their extension mechanism might have useful additions to the ci cycle.
If I define activities for a second state, the interpreter gives a syntex error.
# initial
initial,
# final
final,
# choice
^choice,
# fork or join
]forkjoin,
# junction
junction [type=junction],
# history
history,
# deep history
deep.history,
# a and be are
# parallel states
parallel {
a{x;},b{y;};
},
# nested state
alive {
sleep -- eat;
eat -- work;
work -- sleep;
},
# regular state
state,
# terminate
Terminate [type=terminate],
# regular state
# with activities
active:
entry/say hello
exit/say bye;
state:
entry/say hello
exit/say bye;
# transition with
# events, conditions and actions
"some state" -- "some other state": event [conditions]/ actions;
When creating parallel machines, every state must have a unique name.
For example:
parallel {
bold{
first.on -> first.off;
first.off -> first.on;
},
underline{
second.on -> second.off;
second.off -> second.on;
};
};
I'd like to be able to have the states just be named on
and off
.
I wonder if when using the json
representation of the state machine we could have the idea of states having something like a displayName
that when provided is used for rendering the state name.
This would allow me to use the current name
field as a unique id, with displayName
giving a nice compact output.
I'm working on a library to convert xstate
state chart descriptions in svg diagrams using state-machine-cat
.
With xstate
you can re-use the same state name across each part of a parallel or nested state machine. I'd like to be able to preserve these state names in the diagram output from state-machine-cat
.
Currently the license is GPL. This is fine for the majority of cases where the average user will generate the SCXML files and use them statically. If you want to use the library programmatically then its next to impossible to use under the current licensing. It's possible to use it server side in SaaS products without any hassle but using it in the frontend causes a world of pain. Trying to get a derivative with strong separation to stop the license affecting the entire codebase is next to impossible on the frontend. This stops most companies I work with from allowing its use, which is a shame because it's a great library.
If its possible to dual license it with the BSD or preferably MIT license then that would solve the issue.
I work with enterprise software (ERP, Banking, reporting, etc). Most have an outright ban on using GPL'd libraries in case it could open them up to litigation.
First of all, thank you for your amazing package! I upgraded webpack and did some work around and it worked!
I came across some issues here. I'm not sure they are bugs or the way I used this lib is wrong.
When I changed the style of different nodes, the graph layout could be totally different.
Below is the syntax that define the graph.
ACTIVE_STATES{IDLE,EXECUTE,HELD;},INIT_STATES{STOPPED;},ABORTED;
IDLE=>EXECUTE:Start;
EXECUTE=>IDLE:Execute_SC;
EXECUTE=>HELD:Hold;
HELD=>EXECUTE:Unhold;
ACTIVE_STATES=>STOPPED:Stop;
ACTIVE_STATES=>ABORTED:Abort;
STOPPED=>IDLE:Stopped_Reset;
INIT_STATES=>ABORTED:Abort;
ABORTED=>STOPPED:Clear;
I think the layout should stays the same.
Want to highlight EXECUTE by
EXECUTE [color = "red"]
, got weird error.
Try to highlight a level 1 node like ABORTED by
ABORTED [color = "red"]
, but nothing changed.
I'm not sure the way I change the style of a node is the only way or not. May you have better solutions.
The graph layout changes may be annoying since I prefer more stable visualization of state machines.
I'd like to highlight any nodes(which has no substates no matter what level it is).
Be able to render aliases (i.e. labels) for nested states. As smcat requires all state names to be unique, and our system uses reusable sub-states, I need to be able to specify full paths to those sub states.
Example:
outer {
inner.one [label="one"] {
inner.one.innerest [label="innerest"];
},
inner.two [label="two"] {
inner.two.innerest [label="innerest"];
};
};
This renders wonderfully using smcat, however I can't seem to get the magic right to do the same in scxml.
Using smcat to render the above smcat to scxml gives me:
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0">
<state id="outer">
<state id="inner.one">
<state id="inner.one.innerest">
</state>
</state>
<state id="inner.two">
<state id="inner.two.innerest">
</state>
</state>
</state>
</scxml>
which strips off the labels. This is a problem, but not my use case.
What I need is the ability to specify the labels in some way and have it render as SVG.
(having smcat render the smcat -> scxml would be nice too)
Like maybe:
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0">
<state id="outer" label="outer">
<state id="inner.one" label="one">
<state id="inner.one.innerest" label="innerest">
</state>
</state>
<state id="inner.two" label="two">
<state id="inner.two.innerest" label="innerest">
</state>
</state>
</state>
</scxml>
render the smcat/scxml given above
Right now, I'm fine. I can just use smcat format to generate SVGs. However, I did have to add a generator for smcat format from our internal code. No biggie, I prefer smcat. However, in the future we might need to generate scxml (say to integrate with an editor) and we'd not be able to use that scxml to render in smcat.
validated in current atom plugin and https://state-machine-cat.js.org/
I don't if this feature is already available or not.
I'd like to use state-machine-cat to show several graphs in a single page. .
I can image I need to set up different containers with different id. How about the svg generated in smcat.render()? Shall I assign an id for each generated svg? I think in this package there should be a portal for us to do so.
I tried to do so and thought the render graph action should run correctly. Like each syntax generated corresponding svg and each svg displys in corresponding div.innerHtml.
The smcat.render() threw an error.
Hope you can think about this. Thanks.
There is a wrong conversion to the SCXML format for junction, choice, fork, and join. View the document:
A choice declaration causes a syntax error.
No syntax error.
Get syntax error.
// the following line produces error
// "SyntaxError: Expected comment, end of input, line end, or
// whitespace but "^" found."
^authenticated?: is user authenticated?
//
// State actions definitions
//
Authentication:
"check if google token exists
if yes, authenticate user
if no, sign up";
//
// State Machine
//
initial => Launch;
Launch -> Authentication;
Authentication -> ^authenticated?;
^authenticated? -> Home: no;
^authenticated? -> SignUp: yes;
Home -> final;
SignUp -> final;
This causes the SVG to not show a description for choice "authenticated"
Using the online interpreter.
In the following state machine:
initial,
outer,
parallel {
s1 {
s11 -> s12;
},
s2 {
s21 -> s22;
},
history;
};
initial -> parallel;
parallel -> outer;
outer -> history;
The history state is expected to show up as a child of the parallel state...
Instead, the history state is rendered incorrectly and shows up next to the parallel state:
If the history state is not mentioned in any transition, it is not rendered at all.
Whenever a parallel state has a history child, the problem occurs.
For my purposes, history states should be allowed to be children of parallel states.
Ubuntu 19.10.
state-machine-cat 6.0.1 from NPM.
Node 10.15.2 (from Ubuntu repository)
Exact same problem with the online version: https://state-machine-cat.js.org/
Hi, currently writing a LaTeX package to add smcat
support, it appears Inkscape
(and inkview.exe
) cannot interpret correctly the produced svg
output, ie. from your own example :
initial,
doing: entry/ write unit test
do/ write code
exit/ ...,
# smcat recognizes initial
# and final states by name
# and renders them appropriately
final;
initial => "on backlog" : item adds most value;
"on backlog" => doing : working on it;
doing => testing : built & unit tested;
testing => "on backlog" : test not ok;
testing => final : test ok;
The svg
output "features" something like <polygon fill="transparent" stroke="transparent" ...
where "transparent"
is not recognized.
Check this out :
https://tools.ietf.org/html/draft-brownlee-svg-rfc-13 <- https://tools.ietf.org/id/svg
Did you meant stroke-opacity
instead of stroke
?
Please check the result not just in web browsers, but also with more conformant and less forgiving tools.
Btw you're not the only one to produce "strange" svg
files, https://github.com/mermaid-js/mermaid is also pretty "lazy" regarding svg
conformance and Inkscape
compatibility...
Anyway, good job overall...
Occasionally the text for a transition is not placed anywhere near the arrow it applies to.
Possibly related to #125.
The transition text should be placed next to the arrow.
The transition text seems to be pulled off to one side.
Sorry for the rather verbose example, but this issue seems to only occur in certain circumstances, this is one that I found (see the transition text "strangely_placed_text"):
root.initial,
s1,
s2 [type=parallel] {
s3 {
s3.initial,
a_very_long_name_just_to_emphasize_the_issue;
};
},
c1 [type=choice],
j1 [type=junction],
final;
root.initial -> s1;
s1 -> c1 : "ev1";
s2 -> s1 : "tm(3)";
s3.initial -> a_very_long_name_just_to_emphasize_the_issue;
c1 -> j1 : "[is_ready()]";
c1 -> s1 : "[else]";
j1 -> s2 : "";
s2 -> final : "strangely_placed_text";
When the transition text appears randomly in the diagram it is very unclear what it applies to, leading to confusion.
https://state-machine-cat.js.org/
Version: 7.0.3
Suggestion to produce xstate js output, would be really useful and provide wider audience for use with most popular js library for state charts/ state machines.
Ideally, would be available as an option in the exporter list in the ui side menu.
Example format, this includes its guard and action (onEntry, onExit) features, but even a more limited/simplistic output of the events and actions would be beneficial:
var stateMachine = new xstate.Machine({
initial: "not_green",
states: {
not_green: {
on: {
change: {
green: {
cond: (text) => text.length > 0
}
}
}
},
green: {
onEntry: "startHttpRequest",
onExit: "cancelHttpRequest",
on: {
results: "not_green",
change: {
not_green: {
cond: (text) => text.length == 0
}
}
}
}
}
});
Website:
https://xstate.js.org/docs/
Notice they have there on visualiser, but your tool and syntax/lang is much easier to use for mocking up.
I'm trying to push SMCAT to render SVGs of our in-house high TPS nested state engine.
I love the idea of SMCAT and it's exactly what I need (simple way to visualize with no attempts at behavior)
When I render any self transition, it probably should be a segment of an elipse... a simple arc, and multiple self transitions should probably appear concentrically around each other.
Also, room needed for these transitions should make space on the graph (internally or expanding the bounds)
And finally, there should be a way to render internal transitions, especially internal self transitions. These are generally represented as traversing internally in a state, (inside the boundaries as opposed to outside), specifically, the internal self transitions should render as described above: concentric simple arcs, just inside the host state boundary instead of outside.
2 problems:
To be clear, I'm suggesting that it's an error to render a self transition (internal or external) as a complex path.
I tried multiple renderers in your online formatter (I typically use the atom plugin for prototyping... kudos again, BTW) dot was the only legible one, and the others were completely unreadable.
I can render SMCAT and SCXML formats, but I can't use SCXML, as the newer name aliasing you added (kudos again... I need this to simplify nested state names) doesn't work for SCXML inputs, and SCXML renderer doesn't help anyway as the internal transitions don't render.
Here's an example SMCAT that shows the tangled behavior of self transitions when rendered to SVG: (note: the interenal/external transitions are tangled left and above their host state B)
NestedStateTests [label="NestedStateTests"] :
/entry Root Entry
/exit Root Exit
{
NestedStateTests.A [label="A"] :
{
NestedStateTests.A.A1 [label="A1"] :
/entry A1 Entry
/exit A1 Exit
{
NestedStateTests.A.A1 => NestedStateTests.A.A2 : I1
/A1->A2 Action;
},
NestedStateTests.A.A2 [label="A2"] :
/entry A2 Entry
/exit A2 Exit
{
NestedStateTests.A.A2 => NestedStateTests.B.B2 : I1
/A2->B2 Action;
},
NestedStateTests.A.A3 [label="A3"] : ;
NestedStateTests.A => NestedStateTests.B.B2 : I2
/A->B2 Action;
NestedStateTests.A => NestedStateTests.B : E1
/A->B Action;
NestedStateTests.A => NestedStateTests.C : E2
/A->C Action;
},
NestedStateTests.B [label="B"] :
/entry B Entry
/exit B Exit
{
NestedStateTests.B.B2 [label="B2"] :
/entry B2 Entry
/exit B2 Exit,
NestedStateTests.B.B1 [label="B1"] :
/entry B1 Entry
/exit B1 Exit;
NestedStateTests.B => NestedStateTests.A : E1;
NestedStateTests.B => NestedStateTests.B : E3
/B->B (external) Action;
NestedStateTests.B => NestedStateTests.B : <<internal>> E4
/B->B (internal) Action;
},
NestedStateTests.C [label="C"] :
/entry C Entry
/exit C Exit
{
NestedStateTests.C.C1 [label="C1"] :
/entry C1 Entry
/exit C1 Exit
{
NestedStateTests.C.C1 => NestedStateTests.C.C2 : --AUTO--
/C1 -> C2 Action;
},
NestedStateTests.C.C2 [label="C2"] :
/entry C2 Entry
/exit C2 Exit;
};
};
Hello,
currently I am using your project to for converting SMCAT to SCXML format. I try to convert
`^fraud?: transaction fraudulent?;
initial -> reserved;
reserved -> quoted:
quote
requested;
quoted -> ^fraud?: payment;
^fraud? -> ticketed: [no];
^fraud? -> removed: [yes];
ticketed -> final;
removed -> final;`
into SCXML.
In version 6.0.3 I've got current SCXML:
But in version 6.0.4 I've got next result:
As you see tag disappeared. Is it correct behavior?
Thanks
It's necessary to escape double quotes when they are contained in actions (or state names). However the escaping is currently being rendered rather than un-escaped.
The escaped double quotes are changed to double quotes.
The escaped double quotes are displayed as escaped double quotes.
The escaping should be stripped.
a -> b : "/call_function_with_string(\"a string\");";
It's possible the action is calling a function with a string argument.
https://state-machine-cat.js.org/
Version: 7.0.2
I want to import your API to visualize the state machine. But once I add:
const smcat = require("state-machine-cat");
My code will be built successfully while cant generate a working bundled js file.
I tried
import * as smcat from 'state-machine-cat'
still the same situation.
I use webpack to build it, into AMD libraryTarget.
Also, I use npm.
The most important issue I'm dealing with using smcat (which is awesome, BTW) is that the diagrams would be greatly improved with some manual tweaking.
It's the primary blocker for using smcat to display state in our production monitoring system
It would be nice if I could add bias when defining states and transitions.
Maybe something like this:
X [label="X" color="black", position="below Y"]
A [label="A" color="black", position="center"]
meaning: try to place state X below Y in it's superstate, or on the diagram generally. Try to bias placing state A in the middle of the graph (or the middle of it's superstate)
and
X => Y [from="right", to="top"] : Done;
meaning: try to have the arrow go from the right side of state X to the top side of state Y
Some possible bias behavior examples:
no control (that I'm aware of)
X [label="X" color="black"] :
{
X.Y [label="Y" color="gray"] :
{
X.Y.V [label="V" color="gray"] :
{
X.Y.V => X.Y.Z : 1. Done;
},
X.Y.Z [label="Z" color="gray"] : ,
X.Y.T [label="T" color="gray"] :
{
X.Y.T => X.Y.V : 3. bb;
X.Y.T => X.Y.V : 4. bb;
X.Y.T => X.U : 2. jj;
X.Y.T => X.W : 1. Done;
};
X.Y => X.Y.T : 2. aa;
X.Y => X.Y.T : 1. cc;
X.Y => X.Y.T : 9. dd;
X.Y => X.Y.T : 3. ee;
X.Y => X.Y.T : 6. ff;
X.Y => X.Y.T : 4. gg;
X.Y => X.Y.T : 8. hh;
X.Y => X.Y.T : 7. ii;
X.Y => X.Y.T : 5. ll;
},
X.W [label="W" active color="red"] :
{
X.W => X.Y.T : 2. aa;
X.W => X.Y.V : 8. dd;
X.W => X.U : 4. jj;
X.W => X.Y.V : 1. kk;
X.W => X.Y.V : 5. ff;
X.W => X.Y.T : 3. gg;
X.W => X.Y.V : 7. hh;
X.W => X.Y.V : 6. ii;
},
X.U [label="U" color="gray"] : ;
X.initial => X.W;
};
Svg output sometimes produces distorted lines.
direction: 'left-right'
svg source
idle
state borderdirection: 'top-down
svg source
Try to smc.render
from following input:
initial => idle;
idle => pending: REQUEST;
pending => fulfilled: SUCCESS;
pending => rejected: FAILURE;
fulfilled => pending: REQUEST;
rejected => pending: REQUEST;
nodejs 9.4.0, smc 2.2.1
I am trying to visualise a fairly sizable statechart (maybe 50 states, with 7 levels deep nesting), but get an error when going beyond level 5.
Expect the SVG to be produced.
abort("Cannot enlarge memory arrays. Either
(1) compile with -s TOTAL_MEMORY=X with X higher than the current value 16777216,
(2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations,
(3) set Module.TOTAL_MEMORY to a higher value before the program runs, or
(4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ").
Build with -s ASSERTIONS=1 for more info.
Increase allocated memory, or provide more detailed error logging why it runs out? Perhaps a small tweak to the statechart will prevent the engine from choking?
I'm just trying to find a good visualizer for our statechart, most importantly one that is stable (in its layout).
The ids generated in {output: 'scxml'}
mode can be invalid. Spaces are not supported in ID tokens. According to the xml specs:
ID tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens (-), underscores (_), colons (:), and periods (.).
The generator should take quoted states and camelCase, kebab-case or snake_case them (or any other casing strategy that would meet the requirements). It should also check for invalid chars.
It generates the ids without any processing or checking for invalid chars. Below is an example of the parse error caused by the incorrect output when the tape example in the README is taken as input.
One would be to restrict the input for the names to valid scxml names. This would be to the detriment of the diagrams though. Another options would be to process all names. I dont think the scheme matters too much. For simplicity it may be best to stick to javascript notation (camelCase).
Below is a simple demo app that can be run to generate a scion state machine from the scxml exported. I test these on runkit (with the blow code prepopulated) to reproduce (https://runkit.com/embed/16wxk3gr6h6w)
const R = require('ramda');
const smcat = require('state-machine-cat');
const scxml = require('scxml');
const scxmlToMachine = (xml) => new Promise((resolve, reject) => {
scxml.documentStringToModel(null, xml, (err, model) => {
if (err) return reject(err);
return resolve(model);
});
}).then((model) => new Promise((resolve, reject) => {
model.prepare((err, preparedModel) => {
if (err) return reject(err);
return resolve(preparedModel);
})
})).then(R.constructN(1, scxml.scion.Statechart));
const dslDefinition = `
# yep, notes get rendered here as well
# multiple notes translate into multiple
# lines in notes in the diagram
initial,
"tape player off",
"tape player on" {
stopped => playing : play;
playing => stopped : stop;
playing => paused : pause;
paused => playing : pause;
paused => stopped : stop;
};
initial => "tape player off";
"tape player off" => stopped : power;
"tape player on" => "tape player off" : power;
`;
// generate state machine diagram
const svgDiagram = smcat.render(dslDefinition, {outputType: 'svg'});
console.log(svgDiagram);
// generate scxml and a scion state machine to test validity
const scxmlDocument = smcat.render(dslDefinition, {outputType: 'scxml'});
console.log(scxmlDocument)
scxmlToMachine(scxmlDocument).then(console.log.bind(console))
.catch(console.warn.bind(console))
PS Thanks for the great project. 👍
State box width might be sign-width independent.
State box with 2-bytes unicode signs (i.e. cyrillic) has 2x width, than text is.
Change text length calculation function.
Create "Hello world" state, "Привет мир" state, "你好,世界" state.
Atom plugin, debian 9.
... which is called here: https://github.com/sverweij/state-machine-cat/blob/master/src/parse/peg/smcat-parser.pegjs#L87
Transition lines should originate on the edge of the "from state" (i.e. the outer state)
A couple of small, unrelated things (related to the example below) to notice. Not sure if these are fixable, but I thought it would be helpful to let you know:
transitions from Y to substates originate in empty space inside Y
(bonus: and they cross too often)
IMHO, it would be neat if:
Here is a model displaying the issue:
X [label="X" color="black"] :
{
X.Y [label="Y" color="gray"] :
{
X.Y.V [label="V" color="gray"] :
{
X.Y.V => X.Y.Z : 1. Done;
},
X.Y.Z [label="Z" color="gray"] : ,
X.Y.T [label="T" color="gray"] :
{
X.Y.T => X.Y.V : 3. bb;
X.Y.T => X.Y.V : 4. bb;
X.Y.T => X.U : 2. jj;
X.Y.T => X.W : 1. Done;
};
X.Y => X.Y.T : 2. aa;
X.Y => X.Y.T : 1. cc;
X.Y => X.Y.T : 9. dd;
X.Y => X.Y.T : 3. ee;
X.Y => X.Y.T : 6. ff;
X.Y => X.Y.T : 4. gg;
X.Y => X.Y.T : 8. hh;
X.Y => X.Y.T : 7. ii;
X.Y => X.Y.T : 5. ll;
},
X.W [label="W" active color="red"] :
{
X.W => X.Y.T : 2. aa;
X.W => X.Y.V : 8. dd;
X.W => X.U : 4. jj;
X.W => X.Y.V : 1. kk;
X.W => X.Y.V : 5. ff;
X.W => X.Y.T : 3. gg;
X.W => X.Y.V : 7. hh;
X.W => X.Y.V : 6. ii;
},
X.U [label="U" color="gray"] : ;
X.initial => X.W;
};
I'm pushing to use smcat in a production monitoring system. We have some fairly intense diagrams (the sample above is an obfuscated example) and the main selling point will be that the graphs are much clearer than the representation we currently use.
I absolutely love smcat. I very much appreciate that you made it available and that you've been so responsive to my requests so far.
Love your work!!
Version used: state-machine-cat-preview 4.6.10 in atom 1.45.0 x86 on mac
also in https://state-machine-cat.js.org/ v6.0.5
Thank you for this awesome project ❤️ — this is more of a feature request / support issue. I don't have much experience with GraphViz, so please excuse me if I'm missing something obvious.
For charts that could potentially be large, it would be helpful to be able to specify the ratio or output dimensions so that graphs are properly laid out.
When I produce an SVG with the following smcat code:
initial,
undefined,
fooState {
foo -> bar: barEvent;
foo -> baz: bazEvent;
bork -> foo: fooEvent;
bork -> bar: barEvent;
foo -> bork: borkEvent;
foo -> bar: barEvent;
foo -> baz: bazEvent;
bar -> foo: fooEvent;
bar -> baz2: bazEvent;
baz -> bork: borkEvent;
baz -> foo: fooEvent;
baz -> bar: barEvent;
baz2 -> bork: borkEvent;
baz2 -> foo: fooEvent;
baz2 -> bar: barEvent;
},
initFooState {
initbar -> initFoo: bazEvent;
initFoo -> foo: fooEvent;
initbar -> foo: fooEvent;
};
initial -> undefined;
undefined -> foo: fooEvent;
undefined -> initFoo: bazEvent;
undefined -> initFoo: unstartedEvent;
undefined -> initbar: barEvent;
initFoo -> bork: borkEvent;
… using left-to-right layout, I get quite a wide image:
Using the default, the labels and arrows are overlapping quite often:
Hence, I chose the LTR variant.
Could the layout options for rendering the output be somehow specified, e.g. using a -r
option?
I imagine a parameter that would set the ratio
such as described here: https://www.graphviz.org/doc/info/attrs.html#d:ratio
I have an smc file (at end of issue) which renders correctly using https://state-machine-cat.js.org
When I try to visualise this file from the cli I'm getting an error:
smcat select_registration.gv
(node:1596406) V8: /usr/lib/node_modules/state-machine-cat/node_modules/viz.js/viz.js:33 Invalid asm.js: Function definition doesn't match use
smcat -V
7.0.13
I'm using the version installed via npm and I'm running on ubuntu 20.10.
During the install I saw one warning:
sudo npm install --global state-machine-cat
npm WARN deprecated [email protected]: no longer supported
/usr/bin/smcat -> /usr/lib/node_modules/state-machine-cat/bin/smcat
/usr/bin/sm_cat -> /usr/lib/node_modules/state-machine-cat/bin/smcat
/usr/bin/state-machine-cat -> /usr/lib/node_modules/state-machine-cat/bin/smcat
/usr/bin/sm-cat -> /usr/lib/node_modules/state-machine-cat/bin/smcat
> [email protected] postinstall /usr/lib/node_modules/state-machine-cat/node_modules/fast-xml-parser
> node tasks/postinstall.js || exit 0
Love fast-xml-parser? Check https://amitkumargupta.work for more projects and contribution.
+ [email protected]
added 36 packages from 56 contributors in 2.169s
AppLaunched {
AppLaunched => RegistrationRequired : OnForceRegistration;
AppLaunched => RegistrationRequired : OnMissingApiKey;
AppLaunched => Registered : OnHasApiKey;
},
Registered {
Registered => RegistrationRequired : OnForceRegistration;
},
RegistrationRequired {
RegistrationTypeAcquired {
NewOrganisation,
RecoverAccount,
AcceptInvitation;
NewOrganisation.initial => NewOrganisation;
};
RegistrationTypeAcquired.initial => RegistrationTypeAcquired;
RegistrationRequired => AcceptInvitation : OnRegistrationType;
RegistrationRequired => NewOrganisation : OnRegistrationType;
RegistrationRequired => RecoverAccount : OnRegistrationType;
};
initial => AppLaunched : AppLaunched;
This source ...
a { aa;},
final;
# this transition will be missing in the scjson/ scxml output
aa => final;
... transforms into this scxml:
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0">
<state id="a">
<state id="aa">
<transition target="final"/>
</state>
</state>
<final id="final">
</final>
</scxml>
... it transforms into this. Notice the missing transition from aa to final
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0">
<state id="a">
<state id="aa">
</state>
</state>
<final id="final">
</final>
</scxml>
First of all, I just wanted to say state-machine-cat is the bomb and is definitely the best tool I've found for making these diagrams.
Currently, this following singly nested code works:
"while (1)" {
"while (fgets(c,n,stdin) > 0)" {
read_input;
a => b : c;
};
LIVE_STREAM => dog : stop;
};
but when I try to add an extra level of nesting, I get a syntax error:
"while (1)" {
"while (fgets(c,n,stdin) > 0)" {
read_input;
"while (flagTextRemaining)" {
d => e : f;
};
a => b : c;
};
LIVE_STREAM => dog : stop;
};
begin => read_input;
It might not even be a bug, I'm just not sure what I'm supposed to do to get multiply nested states to be visualized.
Thank you!
'External' transitions exit a state and re-enter, and should be rendered as an arrow leaving the outermost state and re-entering. This works when the target state is the same as the source, but when the target is a sub-state or super-state, the arrow is not shown as leaving the outermost state and one of the ends of the arrow is floating.
a {
b;
},
c {
d;
};
a -> b;
d -> c;
The default transition type is external
, so there's no need to specify it (but doing so also doesn't work).
Support for internal/external transitions is present, so you'd expect this to work.
https://state-machine-cat.js.org/
Version: 7.0.3
First up, thank you so much for State Machine Cat. It is awesome 🎉
I was able to add auto generated state machine visualisations to our code base in just a few hours thanks to your great work!
When using the script:
APP,
PLAYER {
RESTART_STREAM {
PAUSED => PLAYING: play;
PLAYING => PAUSED : pause;
};
LIVE_STREAM => PLAYING : switch to restart;
RESTART_STREAM => LIVE_STREAM: stream finished;
RESTART_STREAM => CONFIRM_SWITCH_TO_LIVE: start to live;
CONFIRM_SWITCH_TO_LIVE => PLAYING: cancel switch to live;
CONFIRM_SWITCH_TO_LIVE => LIVE_STREAM: confirm switch to live;
};
APP => LIVE_STREAM: start playback;
PLAYER => APP: on close;
I would expect it to generate a visualisation.
The following error occurs:
Error: lost LIVE_STREAM PLAYING edge
When testing using https://state-machine-cat.js.org/ with the default settings.
Copy the script above into https://state-machine-cat.js.org/
We have started using state machines to model our more complex async UI state management. We use unit tests and State Machine Cat to auto generate up to date visualisations for our state machines.
I've been investigating adding support for nested states to our code and wanted to see what our state machine would look like with them. While converting the script to use nested states I spotted the error above.
Using https://state-machine-cat.js.org/ on Chrome on macOS. I also get the same bug when running State Machine Cat from node.
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="initial" version="1.0">
<state id="initial">
<transition cond="product is offered" event="customer_enters" target="offered"/>
<transition cond="product is not offered" event="customer_enters" target="final"/>
</state>
<state id="offered">
<onentry>send offered event</onentry>
<transition event="customer_selects_the_product" target="selected"/>
<transition target="final"/>
</state>
<state id="selected">
<onentry>send 'added' event</onentry>
<transition event="customer_removes_the_product" target="removed"/>
<transition target="final"/>
</state>
<state id="removed">
<onentry>send 'deleted' event</onentry>
<transition target="final"/>
</state>
<final id="final">
</final>
</scxml>
As per spec
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="offered" version="1.0">
<state id="offered">
<onentry>send offered event</onentry>
<transition event="customer_selects_the_product" target="selected"/>
<transition target="final"/>
</state>
<state id="selected">
<onentry>send 'added' event</onentry>
<transition event="customer_removes_the_product" target="removed"/>
<transition target="final"/>
</state>
<state id="removed">
<onentry>send 'deleted' event</onentry>
<transition target="final"/>
</state>
<final id="final">
</final>
</scxml>
try to render this source as SCXML
initial,
offered:
onentry/send offered event,
selected:
onentry/send 'added' event,
removed:
onentry/send 'deleted' event;
initial -> offered:
customer enters [product is offered];
offered -> selected:
customer selects the product;
selected -> removed:
customer removes the product;
offered -> final;
selected -> final;
removed -> final;
initial -> final: customer enters [product is not offered];
I'm trying to create a tool to create svg visualisations of xstate state machines.
To do this I'm attempting to convert xstate machine descriptions to State Machine Cat json, which I can then feed into State Machine Cat to generate an svg.
Alongside entry and exit triggers, xstate supports the idea of activities. At the moment State Machine Cat json has a hard coded list of acceptable trigger types, which only include entry
and exit
.
https://github.com/sverweij/state-machine-cat/blob/develop/src/parse/smcat-ast.schema.json#L29
Would it be possible to add activity
(or some equivalent) to that list?
I can whip up a minimal example of the problem if that is useful!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.