{"id":13553358,"url":"https://github.com/sverweij/state-machine-cat","last_synced_at":"2026-05-10T21:19:11.849Z","repository":{"id":38381622,"uuid":"68237661","full_name":"sverweij/state-machine-cat","owner":"sverweij","description":"write beautiful state charts :scream_cat:","archived":false,"fork":false,"pushed_at":"2025-05-10T18:59:25.000Z","size":149895,"stargazers_count":827,"open_issues_count":6,"forks_count":45,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-05-10T19:12:22.365Z","etag":null,"topics":["scxml","state-diagram","state-machine","statechart","uml"],"latest_commit_sha":null,"homepage":"https://state-machine-cat.js.org","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sverweij.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-09-14T19:44:50.000Z","updated_at":"2025-05-10T18:59:20.000Z","dependencies_parsed_at":"2023-02-12T04:15:53.683Z","dependency_job_id":"c9136f9e-0a27-4202-a89d-363d64efb60d","html_url":"https://github.com/sverweij/state-machine-cat","commit_stats":{"total_commits":1184,"total_committers":5,"mean_commits":236.8,"dds":0.01604729729729726,"last_synced_commit":"3808be712d571d9d1b6ce2559f8804cbb20dfe1a"},"previous_names":[],"tags_count":292,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sverweij%2Fstate-machine-cat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sverweij%2Fstate-machine-cat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sverweij%2Fstate-machine-cat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sverweij%2Fstate-machine-cat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sverweij","download_url":"https://codeload.github.com/sverweij/state-machine-cat/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254129489,"owners_count":22019628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["scxml","state-diagram","state-machine","statechart","uml"],"created_at":"2024-08-01T12:02:22.780Z","updated_at":"2026-05-10T21:19:11.836Z","avatar_url":"https://github.com/sverweij.png","language":"TypeScript","funding_links":[],"categories":["JavaScript","hacktoberfest","TypeScript","State Machine","📊 Data \u0026 Analytics"],"sub_categories":["React Components"],"readme":"# State Machine cat\n\n_write beautiful state charts_\n\n[![ci](https://github.com/sverweij/state-machine-cat/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/sverweij/state-machine-cat/actions/workflows/ci.yml)\n[![npm stable version](https://img.shields.io/npm/v/state-machine-cat.svg?logo=npm)](https://npmjs.com/package/state-machine-cat)\n[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![state-machine-cat.js.org](https://img.shields.io/badge/js.org-state--machine--cat-ffb400.svg?style=flat-squared)](https://state-machine-cat.js.org)\n\n## What?\n\nMakes this\n\n\u003cimg width=\"853\" alt=\"docs/pics/sample.png\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/sample.png\"\u003e\n\nfrom this\n\n```smcat\ninitial,\ndoing: entry/ write unit test\n       do/ write code\n       exit/ ...,\n# smcat recognizes initial\n# and final states by name\n# and renders them appropriately\nfinal;\n\ninitial      =\u003e \"on backlog\" : item adds most value;\n\"on backlog\" =\u003e doing        : working on it;\ndoing        =\u003e testing      : built \u0026 unit tested;\ntesting      =\u003e \"on backlog\" : test not ok;\ntesting      =\u003e final        : test ok;\n```\n\n## Why\n\nTo enable me to make state charts ...\n\n- ... that look _good_\n- ... with the least effort possible\n- ... without having to interact with drag and drop tools. Entering text\n  is fine, doing my own layout is not.\n- ... without having to dive into GraphViz `dot` each time. GraphViz is cool,\n  but was not designed to write \u0026 maintain conceptual documents in\n  (_You'll know what I'm talking about if you ever tried to get it to draw nested nodes. Or edges between those._ )\n\n## Usage\n\n### On line\n\nA no-frills interpreter on line: [state-machine-cat.js.org](https://state-machine-cat.js.org).\n\n### Command line interface\n\n`npm install --global state-machine-cat` and run `smcat`\n\nThis is what `smcat --help` would get you:\n\n```\nUsage: smcat [options] [infile]\n\n Write beautiful state charts - https://github.com/sverweij/state-machine-cat\n\nOptions:\n  -V, --version               output the version number\n  -T --output-type \u003ctype\u003e     svg|eps|ps|ps2|dot|smcat|json|ast|scxml|oldsvg|scjson|pdf|png (default: \"svg\")\n  -I --input-type \u003ctype\u003e      smcat|json|scxml (default: \"smcat\")\n  -E --engine \u003ctype\u003e          dot|circo|fdp|neato|osage|twopi (default: \"dot\")\n  -d --direction \u003cdir\u003e        top-down|bottom-top|left-right|right-left (default: \"top-down\")\n  -o --output-to \u003cfile\u003e       File to write to. use - for stdout.\n  --desugar                   transform pseudo states into transitions (!experimental!)\n  -l --license                Display license and exit\n  -h, --help                  display help for command\n```\n\n... so to convert the above chart to `sample.svg`\n\n```sh\nsmcat docs/sample.smcat\n```\n\nOr, if you'd rather pull dot output through GraphViz dot yourself:\n\n```sh\nsmcat -T dot docs/sample.smcat -o - | dot -T svg -odoc/sample.svg\n```\n\nLeaving the options at the default settings usually deliver the best\nresults already, so if they bewilder you: don't worry.\n\nWhen you pass the `--desugar` (experimental) switch, state-machine-cat will,\nbefore rendering, transform some pseudo states into transitions - see\n[de-sugaring state machines](docs/desugar.md) for details.\n\nIn addition to what's documented in the `--help` you can use the following 'advanced'\noptions:\n\n```\n  --dot-graph-attrs \u003cstring\u003e  graph attributes to pass to the dot render engine\n  --dot-node-attrs \u003cstring\u003e   node attributes to pass to the dot render engine\n  --dot-edge-attrs \u003cstring\u003e   edge attributes to pass to the dot render engine\n```\n\nWith these you can override default attributes in the generated picture; e.g. to\nget a transparent background and draw edges as line segments instead of\nsplines, use this:\n\n```sh\nsmcat --dot-graph-attrs \"bgcolor=transparent splines=line\" docs/sample.smcat\n```\n\n### Syntax highlighting\n\n- For editors supporting tree sitter (like the now defunct atom): there's [tree-sitter-smcat](https://github.com/sverweij/tree-sitter-smcat)\n- For vim there's [ambagasdowa/vim-syntax-smcat](https://github.com/ambagasdowa/vim-syntax-smcat/)\n\n### State chart XML (SCXML)\n\n_state machine cat_ can write **and read** valid core constructs\n[scxml](https://www.w3.org/TR/scxml/) documents. If you're into that sort\nof thing you can read all about it in [State Machine Cat and SCXML](./docs/SCXML.md).\n\n### Programmatically\n\nAfter you `npm i` 'd `state-machine-cat`:\n\n```javascript\nimport { render } from \"state-machine-cat\";\n\ntry {\n  const lSVGInAString = await render(\n    `\n            initial =\u003e backlog;\n            backlog =\u003e doing;\n            doing =\u003e test;\n        `,\n    {\n      outputType: \"svg\",\n    },\n  );\n  console.log(lSVGInAString);\n} catch (pError) {\n  console.error(pError);\n}\n```\n\nRead more in [docs/api.md](docs/api.md)\n\nThere's also a script available to embed state machines into html with script\ntags like `\u003cscript type=\"text/x-smcat\"\u003e\u003c/script\u003e`. Documentation for that\n'in page' feature resides over at [state-machine-cat.js.org/inpage.html](https://state-machine-cat.js.org/inpage.html)\n\n## The language\n\n### Short tutorial\n\n#### simplest\n\n```smcat\non =\u003e off;\n```\n\n\u003cimg width=\"206\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/00simplest.png\"\u003e\n\n- _smcat_ automatically declares the states. You _can_ explicitly declare\n  them if you want them to have more than a name only - see _state\n  declarations_ below.\n\n#### labels\n\n```smcat\non =\u003e off: switch;\n```\n\n\u003cimg width=\"251\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/01labels.png\"\u003e\n\nUML prescribes to place _conditions_ after _events_, to place\n_conditions_ within squares and to place _actions_\nafter a `/`: `from =\u003e to: event [conditions]/ actions`, e.g. `on =\u003e off: switch flicked [not an emergency]/ light off;`.\n\nYou're free to do so, but _smcat_ doesn't check for it. It internally takes\nthe notation into account, though and if you choose to export to json, scxml\nor scjson you'll see them nicely split out.\n\n```smcat\non =\u003e off: switch flicked/\n           light off;\noff =\u003e on: switch flicked/\n           light on;\n```\n\n\u003cimg width=\"202\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/01labels_better.png\"\u003e\n\n\u003e You note that smcat rendered the states in this chart _top down_ instead of\n\u003e _left to right_. It did that because we told it so. You can do that too\n\u003e with `--direction` on the command line\n\n#### notes\n\n```smcat\n# this is a note\non =\u003e off;\n```\n\n\u003cimg width=\"233\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/02notes.png\"\u003e\n\n#### state declarations\n\nIf you need to define activities (e.g. `entry` or `exit` triggers) on\na state, you can explicitly declare the state and put the activites\nafter a colon:\n\n```smcat\n# yep, notes get rendered here as well\n# multiple notes translate into multiple\n# lines in notes in the diagram\ndoing:\n  entry/ make a feature branch\n  exit/ deploy code on production\n  ...;\n```\n\n\u003cimg width=\"478\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/04explicit_state_declarations.png\"\u003e\n\n_smcat_ recognizes the `entry/` and `exit/` keywords and treats\neverything after it on the same line to be the 'body' of the\ntrigger.\n\nHere too: you're free to use them, but you don't _have_ to.\n_smcat_ takes them into account in its internal representation\nand uses them in exports to json, scxml and scjson.\n\n#### state display names\n\nIf you want to use a display names that differ from how you\nname the states (e.g. if the display names are long),\nyou can do so by adding a label to them:\n\n```smcat\non [label=\"Lamp aan\"],\noff [label=\"Lamp uit\"];\n\noff =\u003e on: on pushed;\non =\u003e off: off pushed;\n```\n\n\u003cimg width=\"296\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/09labeled_states.png\"\u003e\n\n#### `initial` and `final`\n\nWhen `initial` or `final`, is part of a state's name _smcat_ treats\nit as the UML 'pseudo states' `initial` and `final` respectively:\n\n```smcat\ninitial =\u003e todo;\ntodo    =\u003e doing;\ndoing   =\u003e done;\ndone    =\u003e final;\n```\n\n\u003cimg width=\"375\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/03initial_and_final.png\"\u003e\n\n#### `history`\n\n_smcat_ recognizes states with `history` in their name as history states:\n\n```smcat\ninitial,\n\"power off\",\nrunning {\n  running.history;\n\n  washing -\u003e rinsing: 20 min;\n  rinsing -\u003e spinning: 20 min;\n  spinning -\u003e final: 20 min;\n},\nfinal;\n\ninitial =\u003e washing;\nrunning =\u003e \"power off\": power out;\n\"power off\" =\u003e running.history: restore power;\n```\n\n\u003cimg width=\"735\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/07history.png\"\u003e\n\nHistory states are _shallow_ by default. If you want a history state to\nbe _deep_ just put that somewhere in the name (e.g. `\"running deep history\"`\nor `running.history.deep`) - and smcat will render them as such.\n\n#### Choice - `^`\n\n_smcat_ treats states starting with `^` as UML pseudo state _choice_. Strictly\nspeaking 'choice' is a superfluous element of the UML state machine\nspecification, but it is there and sometimes it makes diagrams easier to read.\n\n```smcat\n^fraud?: transaction fraudulent?;\n\ninitial -\u003e reserved;\nreserved -\u003e quoted:\n    quote\n    requested;\nquoted -\u003e ^fraud?: payment;\n^fraud? -\u003e ticketed: [no];\n^fraud? -\u003e removed: [yes];\nticketed -\u003e final;\nremoved -\u003e final;\n```\n\n\u003cimg width=\"710\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/03achoice.png\"\u003e\n\n#### Forks, joins and junctions - `]`\n\nIn UML you can fork state transitions into multiple or join them into one\nwith the _fork_ (one to many) _join_ (many to one) and _junction_ (many to many)\npseudo states. _Fork_ and _join_ are represented by a black bar, _junction_\nby a filled circle.\nTo make a _join_, _fork_ or _junction_ pseudo state, start its\nname with a `]`.\nHere's an example of a _join_:\n\n```smcat\na =\u003e ]join;\nb =\u003e ]join;\n]join =\u003e c;\n```\n\n\u003cimg width=\"224\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/03bforkjoin.png\"\u003e\n\n\u003e State machine cat automatically derives which of the three types\n\u003e you meant by counting the number of incoming and the number of\n\u003e outgoing connections:\n\u003e\n\u003e - one incoming and multiple outgoing: it's a _fork_\n\u003e - multiple incoming and one outgoing: it's a _join_\n\u003e - all other cases: it's a _junction_\n\u003e\n\u003e If you want to defy UML semantics you can do that with\n\u003e [explicit type overrides](#overriding-the-type-of-a-state) .\n\n```smcat\na =\u003e ]junction;\nb =\u003e ]junction;\n]junction =\u003e c;\n]junction =\u003e d;\n```\n\n\u003cimg width=\"224\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/03cjunction.png\"\u003e\n\n#### Terminate\n\nUML has a special pseudo state to indicate your state machine didn't\nexit properly: _terminate_. If you want to use it, declare it\nexplicitly:\n\n```smcat\nAahnohd [type=terminate label=\"Terminated\"];\n\na =\u003e Aahnohd: [hit by meteorite];\n```\n\n\u003cimg width=\"321\" alt=\"rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/03dterminate.png\"\u003e\n\n\u003e For proper exits you'd typically use the _final_ state.\n\n#### Gotchas\n\n- when you need `;`, `,`, `{`, `[` or spaces as part of a state - place em in quotes\n  `\"a state\"`\n- Activities have the same restriction, except they allow spaces.\n- Labels have the same restriction as activities, except they allow for `,` too.\n- State declaration precedence is: deep wins from shallow; explicit wins from\n  implicit\n- It's possible to declare the same state multiple times on the same level, but\n  smcat will take the last declaration into account only. For example:\n\nThis\n\n```\n# first declaration of \"cool state\"\n\"cool state\",\n\"other state\",\n# second declaration of \"cool state\"\n\"cool state\": cool down;\n```\n\nresults in (/ is equivalent to):\n\n```\n# second declaration of \"cool state\"\n\"cool state\": cool down,\n\"other state\";\n```\n\n#### nested state machines\n\nIt's possible to have state machines _within_ states.\nthe states _stopped_, _playing_ and _pause_ can only occur when\nthe tape player is on:\n\n```\ninitial,\n\"tape player off\",\n\"tape player on\":\n  entry/ LED on\n  exit/ LED off\n{\n  stopped, playing, paused;\n\n  stopped =\u003e playing : play;\n  playing =\u003e stopped : stop;\n  playing =\u003e paused  : pause;\n  paused  =\u003e playing : pause;\n  paused  =\u003e stopped : stop;\n};\n\ninitial           =\u003e \"tape player off\";\n\"tape player off\" =\u003e stopped           : power;\n\"tape player on\"  =\u003e \"tape player off\" : power;\n\n```\n\nAs you can see in this sample you can use activities (like entry and exit\ntriggers) in the composite state declaration, just as you'd do for state that\ndoes not contain a state machine.\n\n\u003cimg width=\"653\" alt=\"tape player rendition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/05tape_player.png\"\u003e\n\n#### parallel states\n\nIf stuff is happening in parallel within a state you can express\nthat too. Just make sure the state has the word \"parallel\" in there:\n\n```smcat\ninitial,\nbla.parallel {\n    first{\n        first.thing -\u003e first.thang;\n    },\n    second{\n        second.thing -\u003e second.thang;\n        second.thang -\u003e second.thing;\n    };\n},\nfinal;\n\ninitial -\u003e ]split;\n]split  -\u003e first.thing;\n]split  -\u003e second.thing;\nfirst.thang  -\u003e ]merge;\nsecond.thang -\u003e ]merge;\n]merge  -\u003e final;\n```\n\n\u003cimg width=\"482\" alt=\"parallel\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/08parallel.png\"\u003e\n\n#### `internal` and `external` transitions\n\nIf you need to mark a transition in a nested state machine as either _internal_\nor _external_ - use the `type` attribute. The default type for a transition\nis `external` - just like it is in SCXML.\n\n```smcat\nplaying {\n  resting =\u003e walking;\n  walking =\u003e resting;\n\n};\n\nplaying =\u003e playing: ingest food;\nplaying =\u003e playing [type=internal]: ingest drink;\n```\n\n\u003cimg width=\"346\" alt=\"internal transition\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/13internal_transition.png\"\u003e\n\n#### marking states _active_\n\nYou can mark one or more states as active by adding `active` as an\nattribute for that state. E.g. to make the `do` state an active one\nin the demming circle, do this:\n\n```smcat\ndo [active];\n\ninitial -\u003e plan;\nplan    -\u003e do;\ndo      -\u003e study;\nstudy   -\u003e act;\nact     -\u003e plan;\n```\n\nwhich will result in\n\n\u003cimg width=\"424\" alt=\"active states\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/11active_state.png\"\u003e\n\n#### colors and line width\n\nAs of version 4.2.0 state-machine-cat has (experimental) support for colors on both\nstates and transitions and from version 8.1.0 for width on transitions.\n\nFor example, this ...\n\n```smcat\neat   [color=\"#008800\"],\nsleep [color=\"blue\" active],\nmeow  [color=\"red\"],\nplay  [color=\"purple\"];\n\nsleep -\u003e meow  [color=\"red\"]            : wake up;\nmeow  -\u003e meow  [color=\"red\"]            : no response from human;\nmeow  -\u003e eat   [color=\"#008800\"]        : human gives food;\nmeow  -\u003e play  [color=\"purple\"]         : human gives toy;\nplay  -\u003e sleep [color=\"blue\"]           : tired or bored;\neat   -\u003e sleep [color=\"blue\" width=3.5] : belly full;\n```\n\n... would yield this diagram:\n\n\u003cimg width=\"488\" alt=\"colored states and transitions\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/10colored_states_and_transitions.png\"\u003e\n\nWhat does 'experimental' mean?\n\n\u003e The color attribute is probably here to stay, as will the width\n\u003e\n\u003e However, I haven't found the balance between ease of use\n\u003e and expressiveness yet. Should the text in a state be rendered in the same color?\n\u003e should the background color automatically be rendered as well? In the same color,\n\u003e or in a shade smartly derived? Or should I include a bunch of color attributes\n\u003e (e.g. fillcolor, textcolor, textbgcolor) for ultimate control?\n\n#### classes\n\nAs of version 7.4.0 you can use the keyword `class` as an extended keyword on\nboth states and transitions. When you render `svg` or `dot` you'll see what you\nentered there in the output in the `class` attributes of their respective\nelements, along with the type of element (either 'state' or 'transition') and\noptionally the type of state or transition (e.g. for state: 'initial', 'regular',\n'final' etc.).\n\nFor example, this ...\n\n```smcat\na [class=\"dismissed\"],\nb [class=\"y\"];\n\na =\u003e b [class=\"a bunch of classes\"];\n```\n\n... will yield this 'dot' program ...\n\n```graphviz\ndigraph \"state transitions\" {\n  fontname=\"Helvetica\" fontsize=12 penwidth=2.0 splines=true ordering=out compound=true overlap=scale nodesep=0.3 ranksep=0.1\n  node [shape=plaintext style=filled fillcolor=\"#FFFFFF01\" fontname=Helvetica fontsize=12 penwidth=2.0]\n  edge [fontname=Helvetica fontsize=10]\n\n    \"a\" [margin=0 class=\"state regular dismissed\" label= \u003c\n      \u003ctable align=\"center\" cellborder=\"0\" border=\"2\" style=\"rounded\" width=\"48\"\u003e\n        \u003ctr\u003e\u003ctd width=\"48\" cellpadding=\"7\"\u003ea\u003c/td\u003e\u003c/tr\u003e\n      \u003c/table\u003e\n    \u003e]\n    \"b\" [margin=0 class=\"state regular y\" label= \u003c\n      \u003ctable align=\"center\" cellborder=\"0\" border=\"2\" style=\"rounded\" width=\"48\"\u003e\n        \u003ctr\u003e\u003ctd width=\"48\" cellpadding=\"7\"\u003eb\u003c/td\u003e\u003c/tr\u003e\n      \u003c/table\u003e\n    \u003e]\n\n    \"a\" -\u003e \"b\" [label=\" \" class=\"transition a bunch of classes\"]\n}\n```\n\nWhich will pass the class attributes on to the svg like so. E.g. the svg snippet\nfor the `a` state will look like this:\n\n```svg\n\u003c!-- ... --\u003e\n  \u003cg id=\"node1\" class=\"node state regular dismissed\"\u003e\n    \u003ctitle\u003ea\u003c/title\u003e\n    \u003cpolygon fill=\"#ffffff\" fill-opacity=\"0.003922\" stroke=\"transparent\" stroke-width=\"2\" points=\"56,-100 0,-100 0,-64 56,-64 56,-100\"\u003e\u003c/polygon\u003e\n    \u003ctext text-anchor=\"start\" x=\"24.6646\" y=\"-78.2\" font-family=\"Helvetica,sans-Serif\" font-size=\"12.00\" fill=\"#000000\"\u003ea\u003c/text\u003e\n    \u003cpath fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" d=\"M12.3333,-65C12.3333,-65 43.6667,-65 43.6667,-65 49.3333,-65 55,-70.6667 55,-76.3333 55,-76.3333 55,-87.6667 55,-87.6667 55,-93.3333 49.3333,-99 43.6667,-99 43.6667,-99 12.3333,-99 12.3333,-99 6.6667,-99 1,-93.3333 1,-87.6667 1,-87.6667 1,-76.3333 1,-76.3333 1,-70.6667 6.6667,-65 12.3333,-65\"\u003e\u003c/path\u003e\n  \u003c/g\u003e\n\u003c!-- ... --\u003e\n```\n\n#### Gotchas\n\n- You will have to provide the style sheet defining the classes yourself in the\n  context where you render the svg in order for them to actually show up\n- The characters you can use for class names is limited to alpha-numerics, dashes,\n  underscores - and spaces to separate them. This to make it harder to use\n  state-machine-cat to construct svg's that are either invalid or malicious. The\n  limited character set is in contrast to what css allows, which is\n  [everything under the sun and then some](https://mathiasbynens.be/notes/css-escapes) -\n  but it seems like a reasonable compromise.\n\n### overriding the type of a state\n\nAs you read above, _state machine cat_ derives the type of a state from its name.\nIn some cases that might not be what you want. In those cases, you can\noverride the type with the `type` attribute, like in this example for the\n`initialized` state.\n\n```smcat\ninitial,\nstarting,\ninitialized [color=\"red\" type=regular],\nrunning,\nfinal;\n\ninitial     =\u003e starting;\nstarting    =\u003e initialized;\ninitialized =\u003e running;\ninitialized =\u003e stopped;\nrunning     =\u003e stopped;\nstopped     =\u003e final;\n```\n\n\u003cimg width=\"520\" alt=\"colored states and transitions\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/12state_type_overrides.png\"\u003e\n\nThe values you can use for the `type` of a state:\n\n| type          | example                                                                              |\n| ------------- | ------------------------------------------------------------------------------------ |\n| `regular`     | \u003cimg width=\"90\" alt=\"regular state\" src=\"docs/pics/types/regular.dot.png\"\u003e           |\n| `initial`     | \u003cimg width=\"25\" alt=\"initial state\" src=\"docs/pics/types/initial.dot.png\"\u003e           |\n| `final`       | \u003cimg width=\"36\" alt=\"final state\" src=\"docs/pics/types/final.dot.png\"\u003e               |\n| `history`     | \u003cimg width=\"58\" alt=\"history state\" src=\"docs/pics/types/history.dot.png\"\u003e           |\n| `deephistory` | \u003cimg width=\"58\" alt=\"deep history state\" src=\"docs/pics/types/deep-history.dot.png\"\u003e |\n| `choice`      | \u003cimg width=\"112\" alt=\"choice state\" src=\"docs/pics/types/choice.dot.png\"\u003e            |\n| `fork`        | \u003cimg width=\"82\" alt=\"fork state\" src=\"docs/pics/types/fork.dot.png\"\u003e                 |\n| `join`        | \u003cimg width=\"82\" alt=\"join state\" src=\"docs/pics/types/join.dot.png\"\u003e                 |\n| `forkjoin`    | \u003cimg width=\"82\" alt=\"forkjoin state\" src=\"docs/pics/types/forkjoin.dot.png\"\u003e         |\n| `junction`    | \u003cimg width=\"25\" alt=\"junction state\" src=\"docs/pics/types/junction.dot.png\"\u003e         |\n| `parallel`    | \u003cimg width=\"333\" alt=\"parallel state\" src=\"docs/pics/types/parallel.dot.png\"\u003e        |\n| `terminate`   | \u003cimg width=\"104\" alt=\"terminate state\" src=\"docs/pics/types/terminate.dot.png\"\u003e      |\n\n#### grammar\n\nI made the parser with peggy - you can find it at\n[src/parse/smcat/smcat-parser.peggy](src/parse/smcat/smcat-parser.peggy), and\nrailroad diagrams generated from these on [state-machine-cat.js.org/grammar.html](https://state-machine-cat.js.org/grammar.html)\n\n## Status\n\n- Thoroughly tested and good enough for public use.\n- Despite this you might bump into the occasional issue - don't hesitate to\n  report it on [GitHub](https://github.com/sverweij/state-machine-cat/issues).\n- Runs on latest versions of firefox, safari and chrome and node versions \u003e=20.12.0\n  Although it might run on other environments, it's not tested there. I will\n  reject issues on these other environments, unless they're accompanied with\n  sufficient enticement to make it worth my while.\n\n\u003cimg width=\"640\" alt=\"colored states and transitions\" src=\"https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/state-machine-cat-social-sharing-picture.png\"\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsverweij%2Fstate-machine-cat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsverweij%2Fstate-machine-cat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsverweij%2Fstate-machine-cat/lists"}