state-machine-cat 13.0.2 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -125,10 +125,10 @@ of thing you can read all about it in [State Machine Cat and SCXML](./docs/SCXML
125
125
  After you `npm i` 'd `state-machine-cat`:
126
126
 
127
127
  ```javascript
128
- import smcat from "state-machine-cat";
128
+ import { render } from "state-machine-cat";
129
129
 
130
130
  try {
131
- const lSVGInAString = smcat.render(
131
+ const lSVGInAString = await render(
132
132
  `
133
133
  initial => backlog;
134
134
  backlog => doing;
@@ -638,7 +638,7 @@ The values you can use for the `type` of a state:
638
638
  #### grammar
639
639
 
640
640
  I made the parser with peggy - you can find it at
641
- [src/parse/peg/smcat-parser.peggy](src/parse/smcat/peg/smcat-parser.peggy), and
641
+ [src/parse/smcat-parser.peggy](src/parse/smcat/smcat-parser.peggy), and
642
642
  railroad diagrams generated from these on [state-machine-cat.js.org/grammar.html](https://state-machine-cat.js.org/grammar.html)
643
643
 
644
644
  ## Status
@@ -1,4 +1,4 @@
1
- import smcat from "../index-node.mjs";
1
+ import { render } from "../index-node.mjs";
2
2
  import { getOutStream, getInStream } from "./file-name-to-stream.mjs";
3
3
  const LICENSE = `
4
4
  state machine cat - write beautiful state charts
@@ -44,8 +44,8 @@ export function displayLicense(pOutStream) {
44
44
  pOutStream.write(LICENSE, "utf8");
45
45
  }
46
46
  export function transform(pOptions) {
47
- return getStream(getInStream(pOptions.inputFrom)).then((pInput) => {
48
- const lOutput = smcat.render(pInput, {
47
+ return getStream(getInStream(pOptions.inputFrom)).then(async (pInput) => {
48
+ const lOutput = await render(pInput, {
49
49
  inputType: pOptions.inputType,
50
50
  outputType: pOptions.outputType,
51
51
  engine: pOptions.engine,
package/dist/cli/cli.mjs CHANGED
@@ -2,7 +2,18 @@ import { parseArgs } from "node:util";
2
2
  import { version } from "../version.mjs";
3
3
  import { formatError, displayLicense, transform } from "./actions.mjs";
4
4
  import normalize from "./normalize.mjs";
5
- import validations from "./validations.mjs";
5
+ import {
6
+ validOutputType,
7
+ validInputType,
8
+ validEngine,
9
+ validDirection,
10
+ validDotAttrs,
11
+ validateArguments,
12
+ defaultOutputType,
13
+ defaultInputType,
14
+ defaultEngine,
15
+ defaultDirection,
16
+ } from "./validations.mjs";
6
17
  const HELP_TEXT = `Usage: smcat [options] [infile]
7
18
 
8
19
  Write beautiful state charts - https://github.com/sverweij/state-machine-cat
@@ -51,22 +62,22 @@ function parseArguments(pArguments) {
51
62
  "output-type": {
52
63
  type: "string",
53
64
  short: "T",
54
- default: validations.defaultOutputType,
65
+ default: defaultOutputType,
55
66
  },
56
67
  "input-type": {
57
68
  type: "string",
58
69
  short: "I",
59
- default: validations.defaultInputType,
70
+ default: defaultInputType,
60
71
  },
61
72
  engine: {
62
73
  type: "string",
63
74
  short: "E",
64
- default: validations.defaultEngine,
75
+ default: defaultEngine,
65
76
  },
66
77
  direction: {
67
78
  type: "string",
68
79
  short: "d",
69
- default: validations.defaultDirection,
80
+ default: defaultDirection,
70
81
  },
71
82
  "output-to": {
72
83
  type: "string",
@@ -108,22 +119,16 @@ function parseArguments(pArguments) {
108
119
  allowPositionals: true,
109
120
  tokens: false,
110
121
  });
111
- values["output-type"] = validations.validOutputType(values["output-type"]);
112
- values["input-type"] = validations.validInputType(values["input-type"]);
113
- values.engine = validations.validEngine(values.engine);
114
- values.direction = validations.validDirection(values.direction);
122
+ values["output-type"] = validOutputType(values["output-type"]);
123
+ values["input-type"] = validInputType(values["input-type"]);
124
+ values.engine = validEngine(values.engine);
125
+ values.direction = validDirection(values.direction);
115
126
  if (values["dot-graph-attrs"])
116
- values["dot-graph-attrs"] = validations.validDotAttrs(
117
- values["dot-graph-attrs"],
118
- );
127
+ values["dot-graph-attrs"] = validDotAttrs(values["dot-graph-attrs"]);
119
128
  if (values["dot-node-attrs"])
120
- values["dot-node-attrs"] = validations.validDotAttrs(
121
- values["dot-node-attrs"],
122
- );
129
+ values["dot-node-attrs"] = validDotAttrs(values["dot-node-attrs"]);
123
130
  if (values["dot-edge-attrs"])
124
- values["dot-edge-attrs"] = validations.validDotAttrs(
125
- values["dot-edge-attrs"],
126
- );
131
+ values["dot-edge-attrs"] = validDotAttrs(values["dot-edge-attrs"]);
127
132
  return { values: camelizeObject(values), positionals };
128
133
  }
129
134
  export default async function cli(pArguments = process.argv, pOptions) {
@@ -146,9 +151,7 @@ export default async function cli(pArguments = process.argv, pOptions) {
146
151
  displayLicense(lOptions.outStream);
147
152
  return;
148
153
  }
149
- await transform(
150
- validations.validateArguments(normalize(positionals[0], values)),
151
- );
154
+ await transform(validateArguments(normalize(positionals[0], values)));
152
155
  } catch (pError) {
153
156
  presentError(pError, lOptions.errorStream);
154
157
  }
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import options from "../options.mjs";
2
+ import { getAllowedValues } from "../options.mjs";
3
3
  import { parse as parseAttributes } from "./attributes-parser.mjs";
4
4
  const INPUT_EXTENSIONS = {
5
5
  ".smcat": "smcat",
@@ -58,7 +58,7 @@ function determineInputType(pInputFrom, pInputType) {
58
58
  return classifyExtension(
59
59
  pInputFrom,
60
60
  INPUT_EXTENSIONS,
61
- options.getAllowedValues().inputType.default,
61
+ getAllowedValues().inputType.default,
62
62
  );
63
63
  }
64
64
  function determineOutputType(pOutputTo, pOutputType) {
@@ -69,15 +69,15 @@ function determineOutputType(pOutputTo, pOutputType) {
69
69
  return classifyExtension(
70
70
  pOutputTo,
71
71
  OUTPUT_EXTENSIONS,
72
- options.getAllowedValues().outputType.default,
72
+ getAllowedValues().outputType.default,
73
73
  );
74
74
  }
75
- return options.getAllowedValues().outputType.default;
75
+ return getAllowedValues().outputType.default;
76
76
  }
77
77
  function determineParameter(pOptions, pParameter) {
78
78
  return Object.hasOwn(pOptions, pParameter)
79
79
  ? pOptions[pParameter]
80
- : options.getAllowedValues()[pParameter].default;
80
+ : getAllowedValues()[pParameter].default;
81
81
  }
82
82
  function determineDotAttributes(pOptions, pDotAttributes) {
83
83
  return pOptions?.[pDotAttributes] &&
@@ -1,7 +1,7 @@
1
- import fs from "node:fs";
2
- import smcat from "../index-node.mjs";
1
+ import { accessSync, constants } from "node:fs";
2
+ import { getAllowedValues } from "../index-node.mjs";
3
3
  import { parse as parseAttributes } from "./attributes-parser.mjs";
4
- const allowedValues = smcat.getAllowedValues();
4
+ const allowedValues = getAllowedValues();
5
5
  function getName(pValue) {
6
6
  return pValue.name;
7
7
  }
@@ -15,7 +15,7 @@ function isStdout(pFilename) {
15
15
  function fileExists(pFilename) {
16
16
  try {
17
17
  if (!isStdout(pFilename)) {
18
- fs.accessSync(pFilename, fs.constants.R_OK);
18
+ accessSync(pFilename, constants.R_OK);
19
19
  }
20
20
  return true;
21
21
  } catch (pError) {
@@ -28,63 +28,61 @@ function validOption(pOption, pValidValues, pError) {
28
28
  }
29
29
  throw new Error(pError);
30
30
  }
31
- export default {
32
- validOutputType: (pType) =>
33
- validOption(
34
- pType,
35
- VALID_OUTPUT_TYPES,
36
- `\n error: '${pType}' is not a valid output type. smcat can emit:` +
37
- `\n ${VALID_OUTPUT_TYPES.join(", ")}\n\n`,
38
- ),
39
- validInputType: (pType) =>
40
- validOption(
41
- pType,
42
- VALID_INPUT_TYPES,
43
- `\n error: '${pType}' is not a valid input type.` +
44
- `\n smcat can read ${VALID_INPUT_TYPES.join(", ")}\n\n`,
45
- ),
46
- validEngine: (pEngine) =>
47
- validOption(
48
- pEngine,
49
- VALID_ENGINES,
50
- `\n error: '${pEngine}' is not a valid input type.` +
51
- `\n you can choose from ${VALID_ENGINES.join(", ")}\n\n`,
52
- ),
53
- validDirection: (pDirection) =>
54
- validOption(
55
- pDirection,
56
- VALID_DIRECTIONS,
57
- `\n error: '${pDirection}' is not a valid direction.` +
58
- `\n you can choose from ${VALID_DIRECTIONS.join(", ")}\n\n`,
59
- ),
60
- validDotAttrs: (pDotAttributes) => {
61
- try {
62
- parseAttributes(pDotAttributes);
63
- return pDotAttributes;
64
- } catch (pError) {
65
- throw new Error(`Invalid dot attributes: ${pError.message}`);
66
- }
67
- },
68
- validateArguments(pOptions) {
69
- if (!pOptions.inputFrom) {
70
- throw new Error(`\n error: Please specify an input file.\n\n`);
71
- }
72
- if (!pOptions.outputTo) {
73
- throw new Error(`\n error: Please specify an output file.\n\n`);
74
- }
75
- if (!fileExists(pOptions.inputFrom)) {
76
- throw new Error(
77
- `\n error: Failed to open input file '${pOptions.inputFrom}'\n\n`,
78
- );
79
- }
80
- return pOptions;
81
- },
82
- validOutputTypeRE: VALID_OUTPUT_TYPES.join("|"),
83
- defaultOutputType: allowedValues.outputType.default,
84
- validInputTypeRE: VALID_INPUT_TYPES.join("|"),
85
- defaultInputType: allowedValues.inputType.default,
86
- validEngineRE: VALID_ENGINES.join("|"),
87
- defaultEngine: allowedValues.engine.default,
88
- validDirectionRE: VALID_DIRECTIONS.join("|"),
89
- defaultDirection: allowedValues.direction.default,
31
+ export const validOutputType = (pType) =>
32
+ validOption(
33
+ pType,
34
+ VALID_OUTPUT_TYPES,
35
+ `\n error: '${pType}' is not a valid output type. smcat can emit:` +
36
+ `\n ${VALID_OUTPUT_TYPES.join(", ")}\n\n`,
37
+ );
38
+ export const validInputType = (pType) =>
39
+ validOption(
40
+ pType,
41
+ VALID_INPUT_TYPES,
42
+ `\n error: '${pType}' is not a valid input type.` +
43
+ `\n smcat can read ${VALID_INPUT_TYPES.join(", ")}\n\n`,
44
+ );
45
+ export const validEngine = (pEngine) =>
46
+ validOption(
47
+ pEngine,
48
+ VALID_ENGINES,
49
+ `\n error: '${pEngine}' is not a valid input type.` +
50
+ `\n you can choose from ${VALID_ENGINES.join(", ")}\n\n`,
51
+ );
52
+ export const validDirection = (pDirection) =>
53
+ validOption(
54
+ pDirection,
55
+ VALID_DIRECTIONS,
56
+ `\n error: '${pDirection}' is not a valid direction.` +
57
+ `\n you can choose from ${VALID_DIRECTIONS.join(", ")}\n\n`,
58
+ );
59
+ export const validDotAttrs = (pDotAttributes) => {
60
+ try {
61
+ parseAttributes(pDotAttributes);
62
+ return pDotAttributes;
63
+ } catch (pError) {
64
+ throw new Error(`Invalid dot attributes: ${pError.message}`);
65
+ }
66
+ };
67
+ export const validateArguments = (pOptions) => {
68
+ if (!pOptions.inputFrom) {
69
+ throw new Error(`\n error: Please specify an input file.\n\n`);
70
+ }
71
+ if (!pOptions.outputTo) {
72
+ throw new Error(`\n error: Please specify an output file.\n\n`);
73
+ }
74
+ if (!fileExists(pOptions.inputFrom)) {
75
+ throw new Error(
76
+ `\n error: Failed to open input file '${pOptions.inputFrom}'\n\n`,
77
+ );
78
+ }
79
+ return pOptions;
90
80
  };
81
+ export const validOutputTypeRE = VALID_OUTPUT_TYPES.join("|");
82
+ export const defaultOutputType = allowedValues.outputType.default;
83
+ export const validInputTypeRE = VALID_INPUT_TYPES.join("|");
84
+ export const defaultInputType = allowedValues.inputType.default;
85
+ export const validEngineRE = VALID_ENGINES.join("|");
86
+ export const defaultEngine = allowedValues.engine.default;
87
+ export const validDirectionRE = VALID_DIRECTIONS.join("|");
88
+ export const defaultDirection = allowedValues.direction.default;
@@ -1,19 +1,23 @@
1
- import options from "./options.mjs";
2
- import parse from "./parse/index.mjs";
1
+ import {
2
+ getAllowedValues as _getAllowedValues,
3
+ getOptionValue,
4
+ } from "./options.mjs";
5
+ import { getAST } from "./parse/index.mjs";
3
6
  import desugar from "./transform/desugar.mjs";
4
7
  import getRenderFunction from "./render/index-node.mjs";
5
- import { version } from "./version.mjs";
6
- export default {
7
- render(pScript, pOptions) {
8
- const lStateMachine = parse.getAST(pScript, pOptions);
9
- const lDesugar = options.getOptionValue(pOptions, "desugar");
10
- return getRenderFunction(options.getOptionValue(pOptions, "outputType"))(
11
- lDesugar ? desugar(lStateMachine) : lStateMachine,
12
- pOptions,
13
- );
14
- },
15
- version,
16
- getAllowedValues() {
17
- return options.getAllowedValues();
18
- },
19
- };
8
+ import { version as _version } from "./version.mjs";
9
+ export async function render(pScript, pOptions) {
10
+ const lStateMachine = await getAST(pScript, pOptions);
11
+ const lDesugar = getOptionValue(pOptions, "desugar");
12
+ const lRenderFunction = await getRenderFunction(
13
+ getOptionValue(pOptions, "outputType"),
14
+ );
15
+ return lRenderFunction(
16
+ lDesugar ? desugar(lStateMachine) : lStateMachine,
17
+ pOptions,
18
+ );
19
+ }
20
+ export const version = _version;
21
+ export function getAllowedValues() {
22
+ return _getAllowedValues();
23
+ }
package/dist/index.mjs CHANGED
@@ -1,23 +1,31 @@
1
- import options from "./options.mjs";
2
- import parse from "./parse/index.mjs";
3
- import desugar from "./transform/desugar.mjs";
1
+ import {
2
+ getAllowedValues as _getAllowedValues,
3
+ getOptionValue,
4
+ } from "./options.mjs";
5
+ import { getAST } from "./parse/index.mjs";
4
6
  import getRenderFunction from "./render/index.mjs";
5
7
  import { version as _version } from "./version.mjs";
6
- export function render(pScript, pOptions) {
8
+ let gDesugarModule = null;
9
+ async function desugar(pStateMachine) {
10
+ if (!gDesugarModule) {
11
+ gDesugarModule = await import("./transform/desugar.mjs");
12
+ }
13
+ const lDesugarFunction = gDesugarModule.default;
14
+ return lDesugarFunction(pStateMachine);
15
+ }
16
+ export async function render(pScript, pOptions) {
7
17
  const lOptions = pOptions ?? {};
8
- const lStateMachine = parse.getAST(pScript, lOptions);
9
- const lDesugar = options.getOptionValue(lOptions, "desugar");
10
- return getRenderFunction(options.getOptionValue(lOptions, "outputType"))(
11
- lDesugar ? desugar(lStateMachine) : lStateMachine,
18
+ const lStateMachine = await getAST(pScript, lOptions);
19
+ const lDesugar = getOptionValue(lOptions, "desugar");
20
+ const lRenderFunction = await getRenderFunction(
21
+ getOptionValue(lOptions, "outputType"),
22
+ );
23
+ return lRenderFunction(
24
+ lDesugar ? await desugar(lStateMachine) : lStateMachine,
12
25
  lOptions,
13
26
  );
14
27
  }
15
28
  export const version = _version;
16
29
  export function getAllowedValues() {
17
- return options.getAllowedValues();
30
+ return _getAllowedValues();
18
31
  }
19
- export default {
20
- render,
21
- version,
22
- getAllowedValues,
23
- };
package/dist/options.mjs CHANGED
@@ -55,7 +55,3 @@ export function getOptionValue(pOptions, pOptionName) {
55
55
  export function getAllowedValues() {
56
56
  return ALLOWED_VALUES;
57
57
  }
58
- export default {
59
- getAllowedValues,
60
- getOptionValue,
61
- };
@@ -1,27 +1,26 @@
1
1
  import Ajv from "ajv";
2
- import options from "../options.mjs";
2
+ import { getOptionValue } from "../options.mjs";
3
3
  import { parse as parseSmCat } from "./smcat/parse.mjs";
4
- import { parse as parseSCXML } from "./scxml/index.mjs";
5
4
  import $schema from "./smcat-ast.schema.mjs";
6
5
  const ajv = new Ajv();
7
- function validateAgainstSchema(pSchema, pObject) {
8
- if (!ajv.validate(pSchema, pObject)) {
6
+ const validate = ajv.compile($schema);
7
+ const parseSCXML = async (pScript) => {
8
+ const { parse } = await import("./scxml/index.mjs");
9
+ return parse(pScript);
10
+ };
11
+ export async function getAST(pScript, pOptions) {
12
+ let lReturnValue = pScript;
13
+ if (getOptionValue(pOptions, "inputType") === "smcat") {
14
+ lReturnValue = parseSmCat(pScript);
15
+ } else if (getOptionValue(pOptions, "inputType") === "scxml") {
16
+ lReturnValue = await parseSCXML(pScript);
17
+ } else if (typeof pScript === "string") {
18
+ lReturnValue = JSON.parse(pScript);
19
+ }
20
+ if (!validate(lReturnValue)) {
9
21
  throw new Error(
10
22
  `The provided JSON is not a valid state-machine-cat AST: ${ajv.errorsText()}.\n`,
11
23
  );
12
24
  }
25
+ return lReturnValue;
13
26
  }
14
- export default {
15
- getAST(pScript, pOptions) {
16
- let lReturnValue = pScript;
17
- if (options.getOptionValue(pOptions, "inputType") === "smcat") {
18
- lReturnValue = parseSmCat(pScript);
19
- } else if (options.getOptionValue(pOptions, "inputType") === "scxml") {
20
- lReturnValue = parseSCXML(pScript);
21
- } else if (typeof pScript === "string") {
22
- lReturnValue = JSON.parse(pScript);
23
- }
24
- validateAgainstSchema($schema, lReturnValue);
25
- return lReturnValue;
26
- },
27
- };
@@ -38,11 +38,11 @@ const RE2STATE_TYPE = [
38
38
  function matches(pName) {
39
39
  return (pEntry) => pEntry.re.test(pName);
40
40
  }
41
- function getStateType(pName) {
41
+ export function getStateType(pName) {
42
42
  return (RE2STATE_TYPE.find(matches(pName)) || { stateType: "regular" })
43
43
  .stateType;
44
44
  }
45
- function initState(pName) {
45
+ export function initState(pName) {
46
46
  return {
47
47
  name: pName,
48
48
  type: getStateType(pName),
@@ -59,27 +59,27 @@ function getAlreadyDeclaredStates(pStateMachine) {
59
59
  lStates.map(({ name }) => name),
60
60
  );
61
61
  }
62
- function extractUndeclaredStates(pStateMachine, pKnownStateNames) {
62
+ export function extractUndeclaredStates(pStateMachine, pKnownStateNames) {
63
63
  pKnownStateNames =
64
64
  pKnownStateNames ?? getAlreadyDeclaredStates(pStateMachine);
65
65
  pStateMachine.states = pStateMachine?.states ?? [];
66
66
  const lTransitions = pStateMachine?.transitions ?? [];
67
- pStateMachine.states.filter(isComposite).forEach((pState) => {
68
- pState.statemachine.states = extractUndeclaredStates(
69
- pState.statemachine,
67
+ for (const lState of pStateMachine.states.filter(isComposite)) {
68
+ lState.statemachine.states = extractUndeclaredStates(
69
+ lState.statemachine,
70
70
  pKnownStateNames,
71
71
  );
72
- });
73
- lTransitions.forEach((pTransition) => {
74
- if (!stateExists(pKnownStateNames, pTransition.from)) {
75
- pKnownStateNames.push(pTransition.from);
76
- pStateMachine.states.push(initState(pTransition.from));
72
+ }
73
+ for (const lTransition of lTransitions) {
74
+ if (!stateExists(pKnownStateNames, lTransition.from)) {
75
+ pKnownStateNames.push(lTransition.from);
76
+ pStateMachine.states.push(initState(lTransition.from));
77
77
  }
78
- if (!stateExists(pKnownStateNames, pTransition.to)) {
79
- pKnownStateNames.push(pTransition.to);
80
- pStateMachine.states.push(initState(pTransition.to));
78
+ if (!stateExists(pKnownStateNames, lTransition.to)) {
79
+ pKnownStateNames.push(lTransition.to);
80
+ pStateMachine.states.push(initState(lTransition.to));
81
81
  }
82
- });
82
+ }
83
83
  return pStateMachine.states;
84
84
  }
85
85
  function classifyForkJoin(pInComingCount, pOutGoingCount) {
@@ -92,7 +92,7 @@ function classifyForkJoin(pInComingCount, pOutGoingCount) {
92
92
  }
93
93
  return lReturnValue;
94
94
  }
95
- function classifyForkJoins(
95
+ export function classifyForkJoins(
96
96
  pStateMachine,
97
97
  pFlattenedStateMachineModel = new StateMachineModel(pStateMachine),
98
98
  ) {
@@ -116,10 +116,10 @@ function classifyForkJoins(
116
116
  });
117
117
  return pStateMachine;
118
118
  }
119
- function stateEqual(pStateOne, pStateTwo) {
119
+ export function stateEqual(pStateOne, pStateTwo) {
120
120
  return pStateOne.name === pStateTwo.name;
121
121
  }
122
- function uniq(pArray, pEqualFunction) {
122
+ export function uniq(pArray, pEqualFunction) {
123
123
  return pArray.reduce((pBag, pMarble) => {
124
124
  const lMarbleIndex = pBag.findIndex((pBagItem) =>
125
125
  pEqualFunction(pBagItem, pMarble),
@@ -131,7 +131,7 @@ function uniq(pArray, pEqualFunction) {
131
131
  return pBag.concat(pMarble);
132
132
  }, []);
133
133
  }
134
- function parseTransitionExpression(pString) {
134
+ export function parseTransitionExpression(pString) {
135
135
  const lTransitionExpressionRe = /([^[/]+)?(\[[^\]]+\])?[^/]*(\/.+)?/;
136
136
  const lReturnValue = {};
137
137
  const lMatchResult = lTransitionExpressionRe.exec(pString);
@@ -151,12 +151,12 @@ function parseTransitionExpression(pString) {
151
151
  }
152
152
  return lReturnValue;
153
153
  }
154
- function setIf(pObject, pProperty, pValue, pCondition = Boolean) {
154
+ export function setIf(pObject, pProperty, pValue, pCondition = Boolean) {
155
155
  if (pCondition(pValue)) {
156
156
  pObject[pProperty] = pValue;
157
157
  }
158
158
  }
159
- function setIfNotEmpty(pObject, pProperty, pValue) {
159
+ export function setIfNotEmpty(pObject, pProperty, pValue) {
160
160
  setIf(pObject, pProperty, pValue, (pX) => pX && pX.length > 0);
161
161
  }
162
162
  function extractAction(pActivityCandidate) {
@@ -174,21 +174,9 @@ function extractAction(pActivityCandidate) {
174
174
  body: pActivityCandidate,
175
175
  };
176
176
  }
177
- function extractActions(pString) {
177
+ export function extractActions(pString) {
178
178
  return pString
179
179
  .split(/\n\s*/g)
180
180
  .map((pActivityCandidate) => pActivityCandidate.trim())
181
181
  .map(extractAction);
182
182
  }
183
- export default {
184
- initState,
185
- extractUndeclaredStates,
186
- classifyForkJoins,
187
- getStateType,
188
- stateEqual,
189
- uniq,
190
- parseTransitionExpression,
191
- extractActions,
192
- setIf,
193
- setIfNotEmpty,
194
- };
@@ -2,11 +2,10 @@ import { XMLParser } from "fast-xml-parser";
2
2
  import he from "he";
3
3
  import traverse from "neotraverse";
4
4
  import { Counter } from "../../counter.mjs";
5
- import parserHelpers from "../parser-helpers.mjs";
6
- import utl from "../../transform/utl.mjs";
5
+ import { getStateType } from "../parser-helpers.mjs";
6
+ import { formatLabel } from "../../transform/utl.mjs";
7
7
  import { castArray } from "./utl.mjs";
8
8
  import { normalizeMachine } from "./normalize-machine.mjs";
9
- const formatLabel = utl.formatLabel;
10
9
  function extractActions(pState, pActionType) {
11
10
  return castArray(pState[pActionType]).map((pAction) => ({
12
11
  type: pActionType === "onexit" ? "exit" : "entry",
@@ -46,7 +45,7 @@ function mapState(pType) {
46
45
  name: pState.id,
47
46
  type: deriveStateType(pType, pState),
48
47
  };
49
- if (parserHelpers.getStateType(pState.id) !== lReturnValue.type) {
48
+ if (getStateType(pState.id) !== lReturnValue.type) {
50
49
  lReturnValue.typeExplicitlySet = true;
51
50
  }
52
51
  if (pState.onentry || pState.onexit || pState.invoke) {
@@ -1,4 +1,14 @@
1
- import parserHelpers from "../parser-helpers.mjs";
1
+ import {
2
+ classifyForkJoins,
3
+ extractActions,
4
+ extractUndeclaredStates,
5
+ initState,
6
+ parseTransitionExpression,
7
+ setIf,
8
+ setIfNotEmpty,
9
+ stateEqual,
10
+ uniq,
11
+ } from "../parser-helpers.mjs";
2
12
  class peg$SyntaxError extends SyntaxError {
3
13
  constructor(message, expected, found, location) {
4
14
  super(message);
@@ -313,13 +323,13 @@ function peg$parse(input, options) {
313
323
  const peg$e75 = peg$classExpectation(["\r", "\n"], true, false, false);
314
324
  const peg$e76 = peg$otherExpectation("comment");
315
325
  function peg$f0(statemachine) {
316
- statemachine.states = parserHelpers.extractUndeclaredStates(statemachine);
317
- return parserHelpers.classifyForkJoins(statemachine);
326
+ statemachine.states = extractUndeclaredStates(statemachine);
327
+ return classifyForkJoins(statemachine);
318
328
  }
319
329
  function peg$f1(states, transitions) {
320
330
  let lStateMachine = {};
321
- parserHelpers.setIf(lStateMachine, "states", states);
322
- parserHelpers.setIfNotEmpty(lStateMachine, "transitions", transitions);
331
+ setIf(lStateMachine, "states", states);
332
+ setIfNotEmpty(lStateMachine, "transitions", transitions);
323
333
  return lStateMachine;
324
334
  }
325
335
  function peg$f2(state) {
@@ -329,10 +339,7 @@ function peg$parse(input, options) {
329
339
  return state;
330
340
  }
331
341
  function peg$f4(states) {
332
- return parserHelpers.uniq(
333
- states[0].concat(states[1]),
334
- parserHelpers.stateEqual,
335
- );
342
+ return uniq(states[0].concat(states[1]), stateEqual);
336
343
  }
337
344
  function peg$f5(notes, id, attrs) {
338
345
  return attrs;
@@ -344,29 +351,21 @@ function peg$parse(input, options) {
344
351
  return sm;
345
352
  }
346
353
  function peg$f8(notes, id, extended_state_attributes, actions, statemachine) {
347
- let lState = parserHelpers.initState(id);
348
- (extended_state_attributes || []).forEach((pExtendedAttribute) =>
349
- parserHelpers.setIf(
350
- lState,
351
- pExtendedAttribute.name,
352
- pExtendedAttribute.value,
353
- ),
354
- );
355
- parserHelpers.setIf(
354
+ let lState = initState(id);
355
+ for (const lExtendedAttribute of extended_state_attributes || []) {
356
+ setIf(lState, lExtendedAttribute.name, lExtendedAttribute.value);
357
+ }
358
+ setIf(
356
359
  lState,
357
360
  "typeExplicitlySet",
358
361
  (extended_state_attributes || []).some(
359
362
  (pExtendedAttribute) => pExtendedAttribute.typeExplicitlySet,
360
363
  ),
361
364
  );
362
- parserHelpers.setIf(lState, "statemachine", statemachine);
363
- parserHelpers.setIfNotEmpty(lState, "note", notes);
365
+ setIf(lState, "statemachine", statemachine);
366
+ setIfNotEmpty(lState, "note", notes);
364
367
  if (actions) {
365
- parserHelpers.setIfNotEmpty(
366
- lState,
367
- "actions",
368
- parserHelpers.extractActions(actions),
369
- );
368
+ setIfNotEmpty(lState, "actions", extractActions(actions));
370
369
  }
371
370
  return lState;
372
371
  }
@@ -403,19 +402,12 @@ function peg$parse(input, options) {
403
402
  function peg$f19(notes, trans, extended_attributes, label) {
404
403
  if (label) {
405
404
  trans.label = label;
406
- trans = Object.assign(
407
- trans,
408
- parserHelpers.parseTransitionExpression(label),
409
- );
405
+ trans = Object.assign(trans, parseTransitionExpression(label));
410
406
  }
411
- (extended_attributes || []).forEach((pExtendedAttribute) =>
412
- parserHelpers.setIf(
413
- trans,
414
- pExtendedAttribute.name,
415
- pExtendedAttribute.value,
416
- ),
417
- );
418
- parserHelpers.setIfNotEmpty(trans, "note", notes);
407
+ for (const lExtendedAttribute of extended_attributes || []) {
408
+ setIf(trans, lExtendedAttribute.name, lExtendedAttribute.value);
409
+ }
410
+ setIfNotEmpty(trans, "note", notes);
419
411
  trans.id = options.counter.next();
420
412
  return trans;
421
413
  }
@@ -37,11 +37,20 @@ function toNameValueString(pAttribute) {
37
37
  return `${pAttribute.name}=${pAttribute.value}`;
38
38
  }
39
39
  export function buildGraphAttributes(pEngine, pDirection, pDotGraphAttributes) {
40
- return GENERIC_GRAPH_ATTRIBUTES.concat(GRAPH_ATTRIBUTES[pEngine] || [])
41
- .concat(DIRECTION_ATTRIBUTES[pDirection] || [])
42
- .concat(pDotGraphAttributes || [])
43
- .map(toNameValueString)
44
- .join(" ");
40
+ const lParts = [];
41
+ for (const lAttribute of GENERIC_GRAPH_ATTRIBUTES) {
42
+ lParts.push(lAttribute);
43
+ }
44
+ for (const lAttribute of GRAPH_ATTRIBUTES[pEngine] || []) {
45
+ lParts.push(lAttribute);
46
+ }
47
+ for (const lAttribute of DIRECTION_ATTRIBUTES[pDirection] || []) {
48
+ lParts.push(lAttribute);
49
+ }
50
+ for (const lAttribute of pDotGraphAttributes || []) {
51
+ lParts.push(lAttribute);
52
+ }
53
+ return lParts.map(toNameValueString).join(" ");
45
54
  }
46
55
  export function buildNodeAttributes(pDotNodeAttributes) {
47
56
  return NODE_ATTRIBUTES.concat(pDotNodeAttributes || [])
@@ -53,8 +62,3 @@ export function buildEdgeAttributes(pDotEdgeAttributes) {
53
62
  .map(toNameValueString)
54
63
  .join(" ");
55
64
  }
56
- export default {
57
- buildGraphAttributes,
58
- buildNodeAttributes,
59
- buildEdgeAttributes,
60
- };
@@ -180,9 +180,9 @@ function state(pState, pIndent, pOptions, pModel, pRenderedTransitions) {
180
180
  pState.name,
181
181
  pRenderedTransitions,
182
182
  );
183
- lCandidateTransitions.forEach((pTransition) => {
184
- pRenderedTransitions.add(pTransition.id);
185
- });
183
+ for (const lTransition of lCandidateTransitions) {
184
+ pRenderedTransitions.add(lTransition.id);
185
+ }
186
186
  const lTransitions = transitions(
187
187
  lCandidateTransitions,
188
188
  pIndent,
@@ -1,26 +1,23 @@
1
- import smcatRendererAsImported from "./smcat.mjs";
2
- import renderDot from "./dot/index.mjs";
3
- import vector from "./vector/vector-native-dot-with-fallback.mjs";
4
- import oldVector from "./vector/vector-with-wasm.mjs";
5
- import scjson from "./scjson/index.mjs";
6
- import scxml from "./scxml/index.mjs";
7
- const smcat = smcatRendererAsImported;
8
- export default function getRenderFunction(pOutputType) {
9
- const lOutputType2RenderFunctionMap = new Map([
10
- ["smcat", smcat],
11
- ["dot", renderDot],
12
- ["svg", vector],
13
- ["dot", renderDot],
14
- ["eps", vector],
15
- ["ps", vector],
16
- ["ps2", vector],
17
- ["oldsvg", oldVector],
18
- ["oldps2", oldVector],
19
- ["oldeps", oldVector],
20
- ["pdf", vector],
21
- ["png", vector],
22
- ["scjson", scjson],
23
- ["scxml", scxml],
24
- ]);
25
- return lOutputType2RenderFunctionMap.get(pOutputType) ?? ((pX) => pX);
1
+ const OUTPUT_TYPE2RENDER_MODULE = new Map([
2
+ ["smcat", "./smcat.mjs"],
3
+ ["dot", "./dot/index.mjs"],
4
+ ["svg", "./vector/vector-native-dot-with-fallback.mjs"],
5
+ ["eps", "./vector/vector-native-dot-with-fallback.mjs"],
6
+ ["ps", "./vector/vector-native-dot-with-fallback.mjs"],
7
+ ["ps2", "./vector/vector-native-dot-with-fallback.mjs"],
8
+ ["oldsvg", "./vector/vector-with-wasm.mjs"],
9
+ ["oldps2", "./vector/vector-with-wasm.mjs"],
10
+ ["oldeps", "./vector/vector-with-wasm.mjs"],
11
+ ["pdf", "./vector/vector-native-dot-with-fallback.mjs"],
12
+ ["png", "./vector/vector-native-dot-with-fallback.mjs"],
13
+ ["scjson", "./scjson/index.mjs"],
14
+ ["scxml", "./scxml/index.mjs"],
15
+ ]);
16
+ export default async function getRenderFunction(pOutputType) {
17
+ const lModulePath = OUTPUT_TYPE2RENDER_MODULE.get(pOutputType);
18
+ if (lModulePath) {
19
+ const lImportedModule = await import(lModulePath);
20
+ return lImportedModule.default;
21
+ }
22
+ return (pX) => pX;
26
23
  }
@@ -1,17 +1,42 @@
1
- import smcatRendererAsImported from "./smcat.mjs";
2
- import renderDot from "./dot/index.mjs";
3
- import svg from "./vector/vector-with-wasm.mjs";
4
- import scjson from "./scjson/index.mjs";
5
- import scxml from "./scxml/index.mjs";
6
- const smcat = smcatRendererAsImported;
7
- export default function getRenderFunction(pOutputType) {
8
- const lOutputType2RenderFunctionMap = new Map([
9
- ["smcat", smcat],
10
- ["dot", renderDot],
11
- ["svg", svg],
12
- ["oldsvg", svg],
13
- ["scjson", scjson],
14
- ["scxml", scxml],
15
- ]);
16
- return lOutputType2RenderFunctionMap.get(pOutputType) ?? ((pX) => pX);
1
+ let gSmCatModule = null;
2
+ let gDotModule = null;
3
+ let gSVGModule = null;
4
+ let gSCJSONModule = null;
5
+ let gSCXMLModule = null;
6
+ export default async function getRenderFunction(pOutputType) {
7
+ switch (pOutputType) {
8
+ case "smcat": {
9
+ if (!gSmCatModule) {
10
+ gSmCatModule = await import("./smcat.mjs");
11
+ }
12
+ return gSmCatModule.default;
13
+ }
14
+ case "dot": {
15
+ if (!gDotModule) {
16
+ gDotModule = await import("./dot/index.mjs");
17
+ }
18
+ return gDotModule.default;
19
+ }
20
+ case "svg":
21
+ case "oldsvg": {
22
+ if (!gSVGModule) {
23
+ gSVGModule = await import("./vector/vector-with-wasm.mjs");
24
+ }
25
+ return gSVGModule.default;
26
+ }
27
+ case "scjson": {
28
+ if (!gSCJSONModule) {
29
+ gSCJSONModule = await import("./scjson/index.mjs");
30
+ }
31
+ return gSCJSONModule.default;
32
+ }
33
+ case "scxml": {
34
+ if (!gSCXMLModule) {
35
+ gSCXMLModule = await import("./scxml/index.mjs");
36
+ }
37
+ return gSCXMLModule.default;
38
+ }
39
+ default:
40
+ return (pX) => pX;
41
+ }
17
42
  }
@@ -3,7 +3,7 @@ const DEFAULT_OPTIONS = {
3
3
  exec: "dot",
4
4
  format: "svg",
5
5
  };
6
- function convert(pDot, pOptions) {
6
+ export function convert(pDot, pOptions) {
7
7
  const lOptions = {
8
8
  ...DEFAULT_OPTIONS,
9
9
  ...pOptions,
@@ -23,7 +23,7 @@ function convert(pDot, pOptions) {
23
23
  throw new Error(`Unexpected error occurred. Exit code ${status}`);
24
24
  }
25
25
  }
26
- function isAvailable(pOptions) {
26
+ export function isAvailable(pOptions) {
27
27
  const lOptions = {
28
28
  ...DEFAULT_OPTIONS,
29
29
  ...pOptions,
@@ -33,7 +33,3 @@ function isAvailable(pOptions) {
33
33
  status === 0 && stderr.toString("utf8").startsWith("dot - graphviz version")
34
34
  );
35
35
  }
36
- export default {
37
- convert,
38
- isAvailable,
39
- };
@@ -1,17 +1,17 @@
1
1
  import { Graphviz } from "@hpcc-js/wasm-graphviz";
2
- import options from "../../options.mjs";
2
+ import { getOptionValue } from "../../options.mjs";
3
3
  import ast2dot from "../dot/index.mjs";
4
- import dotToVectorNative from "./dot-to-vector-native.mjs";
4
+ import { isAvailable, convert } from "./dot-to-vector-native.mjs";
5
5
  const VIZ_JS_UNSUPPORTED_OUTPUT_FORMATS = ["pdf", "png"];
6
6
  const gGraphViz = await Graphviz.load();
7
7
  const renderVector = (pStateMachine, pOptions) => {
8
8
  const lDotProgram = ast2dot(pStateMachine, pOptions);
9
9
  const lDotOptions = {
10
- engine: options.getOptionValue(pOptions, "engine"),
11
- format: options.getOptionValue(pOptions, "outputType"),
10
+ engine: getOptionValue(pOptions, "engine"),
11
+ format: getOptionValue(pOptions, "outputType"),
12
12
  };
13
- if (dotToVectorNative.isAvailable(pOptions)) {
14
- return dotToVectorNative.convert(lDotProgram, lDotOptions);
13
+ if (isAvailable(pOptions)) {
14
+ return convert(lDotProgram, lDotOptions);
15
15
  } else {
16
16
  if (VIZ_JS_UNSUPPORTED_OUTPUT_FORMATS.includes(lDotOptions.format)) {
17
17
  throw new Error(
@@ -1,5 +1,5 @@
1
1
  import { Graphviz } from "@hpcc-js/wasm-graphviz";
2
- import options from "../../options.mjs";
2
+ import { getOptionValue } from "../../options.mjs";
3
3
  import ast2dot from "../dot/index.mjs";
4
4
  const OUTPUT_TYPE2FORMAT = {
5
5
  oldsvg: "svg",
@@ -8,12 +8,10 @@ const OUTPUT_TYPE2FORMAT = {
8
8
  };
9
9
  const gGraphViz = await Graphviz.load();
10
10
  function getFormat(pOptions) {
11
- return (
12
- OUTPUT_TYPE2FORMAT[options.getOptionValue(pOptions, "outputType")] || "svg"
13
- );
11
+ return OUTPUT_TYPE2FORMAT[getOptionValue(pOptions, "outputType")] || "svg";
14
12
  }
15
13
  function getEngine(pOptions) {
16
- return options.getOptionValue(pOptions, "engine");
14
+ return getOptionValue(pOptions, "engine");
17
15
  }
18
16
  const renderVectorWithWasm = (pStateMachine, pOptions) =>
19
17
  gGraphViz.layout(
@@ -1,19 +1,17 @@
1
1
  function flattenStatesToMap(pStates, pMap, pParent = "") {
2
- pStates
3
- .filter((pState) => Boolean(pState.statemachine))
4
- .forEach((pState) => {
5
- if (Object.hasOwn(pState.statemachine, "states")) {
6
- flattenStatesToMap(pState.statemachine.states, pMap, pState.name);
7
- }
8
- });
9
- pStates.forEach((pState) =>
10
- pMap.set(pState.name, {
11
- name: pState.name,
12
- type: pState.type,
13
- statemachine: Boolean(pState.statemachine),
2
+ for (const lState of pStates) {
3
+ if (lState?.statemachine?.states) {
4
+ flattenStatesToMap(lState.statemachine.states, pMap, lState.name);
5
+ }
6
+ }
7
+ for (const lState of pStates) {
8
+ pMap.set(lState.name, {
9
+ name: lState.name,
10
+ type: lState.type,
11
+ statemachine: Boolean(lState.statemachine),
14
12
  parent: pParent,
15
- }),
16
- );
13
+ });
14
+ }
17
15
  }
18
16
  function flattenTransitions(pStateMachine) {
19
17
  let lTransitions = [];
@@ -21,13 +19,13 @@ function flattenTransitions(pStateMachine) {
21
19
  lTransitions = structuredClone(pStateMachine.transitions);
22
20
  }
23
21
  if (Object.hasOwn(pStateMachine, "states")) {
24
- pStateMachine.states
25
- .filter((pState) => Boolean(pState.statemachine))
26
- .forEach((pState) => {
22
+ for (const lState of pStateMachine.states) {
23
+ if (lState.statemachine) {
27
24
  lTransitions = lTransitions.concat(
28
- flattenTransitions(pState.statemachine),
25
+ flattenTransitions(lState.statemachine),
29
26
  );
30
- });
27
+ }
28
+ }
31
29
  }
32
30
  return lTransitions;
33
31
  }
@@ -1,6 +1,6 @@
1
1
  import StateMachineModel from "../state-machine-model.mjs";
2
2
  import { Counter } from "../counter.mjs";
3
- import utl from "./utl.mjs";
3
+ import { formatLabel } from "./utl.mjs";
4
4
  function fuseTransitionAttribute(pIncomingThing, pOutgoingThing, pJoinChar) {
5
5
  return pIncomingThing
6
6
  ? `${pIncomingThing}${pJoinChar}${pOutgoingThing}`
@@ -26,7 +26,7 @@ function fuseIncomingToOutgoing(
26
26
  );
27
27
  }
28
28
  if (lReturnValue.event || lReturnValue.cond || lReturnValue.action) {
29
- lReturnValue.label = utl.formatLabel(
29
+ lReturnValue.label = formatLabel(
30
30
  lReturnValue.event,
31
31
  lReturnValue.cond,
32
32
  lReturnValue.action,
@@ -40,20 +40,24 @@ function fuseTransitions(
40
40
  pOutgoingTransitionMap,
41
41
  pCounter,
42
42
  ) {
43
- return pTransitions.reduce((pAll, pTransition) => {
44
- pPseudoStateNames.forEach((pStateName, pIndex) => {
45
- if (pStateName === pTransition.to && pOutgoingTransitionMap[pStateName]) {
46
- pAll = pAll.concat(
47
- pOutgoingTransitionMap[pStateName].map((pOutgoingTransition) =>
48
- fuseIncomingToOutgoing(pTransition, pOutgoingTransition, pCounter),
49
- ),
50
- );
51
- } else {
52
- pAll = pIndex === 0 ? pAll.concat(pTransition) : pAll;
43
+ const lResult = [];
44
+ for (const lTransition of pTransitions) {
45
+ let lAdded = false;
46
+ for (const lStateName of pPseudoStateNames) {
47
+ if (lStateName === lTransition.to && pOutgoingTransitionMap[lStateName]) {
48
+ for (const lOutgoing of pOutgoingTransitionMap[lStateName]) {
49
+ lResult.push(
50
+ fuseIncomingToOutgoing(lTransition, lOutgoing, pCounter),
51
+ );
52
+ }
53
+ lAdded = true;
53
54
  }
54
- });
55
- return pAll;
56
- }, []);
55
+ }
56
+ if (!lAdded) {
57
+ lResult.push(lTransition);
58
+ }
59
+ }
60
+ return lResult;
57
61
  }
58
62
  function deSugarPseudoStates(
59
63
  pMachine,
@@ -1,4 +1,4 @@
1
- function formatLabel(pEvent, pCond, pActions) {
1
+ export function formatLabel(pEvent, pCond, pActions) {
2
2
  let lReturnValue = "";
3
3
  if (pEvent) {
4
4
  lReturnValue += pEvent;
@@ -11,6 +11,3 @@ function formatLabel(pEvent, pCond, pActions) {
11
11
  }
12
12
  return lReturnValue.trim();
13
13
  }
14
- export default {
15
- formatLabel,
16
- };
package/dist/version.mjs CHANGED
@@ -1 +1 @@
1
- export const version = "13.0.2";
1
+ export const version = "14.0.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "state-machine-cat",
3
- "version": "13.0.2",
3
+ "version": "14.0.0",
4
4
  "description": "write beautiful state charts",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -286,7 +286,7 @@ export type RenderFunctionType =
286
286
  * @param pScript The script to translate
287
287
  * @param pOptions options influencing parsing & rendering.
288
288
  * See below for the complete list.
289
- * @return the string with the rendered content if
289
+ * @return a promise to the string with the rendered content if
290
290
  * no error was found
291
291
  * @throws {Error} If an error occurred and no callback
292
292
  * function was passed: the error
@@ -297,4 +297,4 @@ export type RenderFunctionType =
297
297
  export function render(
298
298
  pScript: IStateMachine | string,
299
299
  pOptions: IRenderOptions,
300
- ): string;
300
+ ): Promise<string>;