state-machine-cat 10.1.2 → 10.1.3
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/bin/smcat.mjs +5 -0
- package/dist/commonjs/bundle.js +64 -64
- package/package.json +20 -25
- package/src/cli/actions.mjs +9 -0
- package/src/cli/file-name-to-stream.mjs +5 -6
- package/src/cli/make-description.mjs +9 -0
- package/src/cli/normalize.mjs +79 -41
- package/src/cli/validations.mjs +27 -1
- package/src/index-node.mjs +15 -47
- package/src/index.mjs +9 -9
- package/src/options.mjs +19 -13
- package/src/parse/index.mjs +13 -0
- package/src/parse/parser-helpers.mjs +70 -6
- package/src/parse/scxml/index.mjs +40 -1
- package/src/parse/scxml/normalize-machine.mjs +1 -1
- package/src/render/dot/attributebuilder.mjs +7 -0
- package/src/render/dot/counter.mjs +13 -0
- package/src/render/dot/index.mjs +66 -28
- package/src/render/dot/render-dot-from-ast.js +37 -15
- package/src/render/dot/state-transformers.mjs +4 -2
- package/src/render/dot/utl.mjs +20 -0
- package/src/render/index-node.mjs +9 -3
- package/src/render/index.mjs +3 -3
- package/src/render/scjson/index.mjs +6 -0
- package/src/render/scjson/make-valid-xml-name.mjs +7 -1
- package/src/render/scxml/index.mjs +3 -1
- package/src/render/smcat/index.js +48 -14
- package/src/render/vector/dot-to-vector-native.mjs +1 -1
- package/src/render/vector/vector-native-dot-with-fallback.mjs +3 -2
- package/src/render/vector/vector-with-viz-js.mjs +3 -2
- package/src/state-machine-model.mjs +46 -4
- package/src/transform/desugar.mjs +67 -18
- package/src/transform/utl.mjs +8 -0
- package/src/version.mjs +1 -1
- package/types/state-machine-cat.d.ts +41 -14
package/src/render/dot/utl.mjs
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} pString
|
|
5
|
+
* @returns {string}
|
|
6
|
+
*/
|
|
1
7
|
function escapeString(pString) {
|
|
2
8
|
return pString
|
|
3
9
|
.replace(/\\/g, "\\\\")
|
|
@@ -6,6 +12,10 @@ function escapeString(pString) {
|
|
|
6
12
|
.concat("\\l");
|
|
7
13
|
}
|
|
8
14
|
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} pString
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
9
19
|
function escapeLabelString(pString) {
|
|
10
20
|
return pString
|
|
11
21
|
.replace(/\\/g, "\\\\")
|
|
@@ -14,12 +24,22 @@ function escapeLabelString(pString) {
|
|
|
14
24
|
.concat(" \\l");
|
|
15
25
|
}
|
|
16
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} pDirection
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
17
31
|
function isVertical(pDirection) {
|
|
18
32
|
const lDirection = pDirection || "top-down";
|
|
19
33
|
|
|
20
34
|
return lDirection === "top-down" || lDirection === "bottom-top";
|
|
21
35
|
}
|
|
22
36
|
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @param {import("../../state-machine-model.mjs").default} pStateMachineModel
|
|
40
|
+
* @param {import("../../../types/state-machine-cat").ITransition} pTransition
|
|
41
|
+
* @returns {boolean}
|
|
42
|
+
*/
|
|
23
43
|
function isCompositeSelf(pStateMachineModel, pTransition) {
|
|
24
44
|
return (
|
|
25
45
|
pTransition.from === pTransition.to &&
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/* eslint-disable security/detect-object-injection */
|
|
2
3
|
import has from "lodash/has.js";
|
|
3
4
|
import smcat from "./smcat/index.js";
|
|
@@ -7,8 +8,13 @@ import oldVector from "./vector/vector-with-viz-js.mjs";
|
|
|
7
8
|
import scjson from "./scjson/index.mjs";
|
|
8
9
|
import scxml from "./scxml/index.mjs";
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {import("../../types/state-machine-cat.js").OutputType} pOutputType
|
|
14
|
+
* @returns {import("../../types/state-machine-cat.js").RenderFunctionType}
|
|
15
|
+
*/
|
|
10
16
|
export default function getRenderFunction(pOutputType) {
|
|
11
|
-
const
|
|
17
|
+
const lOutputType2RenderFunction = {
|
|
12
18
|
smcat,
|
|
13
19
|
dot,
|
|
14
20
|
svg: vector,
|
|
@@ -24,7 +30,7 @@ export default function getRenderFunction(pOutputType) {
|
|
|
24
30
|
scxml,
|
|
25
31
|
};
|
|
26
32
|
|
|
27
|
-
return has(
|
|
28
|
-
?
|
|
33
|
+
return has(lOutputType2RenderFunction, pOutputType)
|
|
34
|
+
? lOutputType2RenderFunction[pOutputType]
|
|
29
35
|
: (pX) => pX;
|
|
30
36
|
}
|
package/src/render/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import scjson from "./scjson/index.mjs";
|
|
|
7
7
|
import scxml from "./scxml/index.mjs";
|
|
8
8
|
|
|
9
9
|
export default function getRenderFunction(pOutputType) {
|
|
10
|
-
const
|
|
10
|
+
const lOutputType2RenderFunction = {
|
|
11
11
|
smcat,
|
|
12
12
|
dot,
|
|
13
13
|
svg,
|
|
@@ -16,7 +16,7 @@ export default function getRenderFunction(pOutputType) {
|
|
|
16
16
|
scxml,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
return has(
|
|
20
|
-
?
|
|
19
|
+
return has(lOutputType2RenderFunction, pOutputType)
|
|
20
|
+
? lOutputType2RenderFunction[pOutputType]
|
|
21
21
|
: (pX) => pX;
|
|
22
22
|
}
|
|
@@ -137,6 +137,12 @@ function findInitialStateName(pStateMachine, pInitialPseudoStateName) {
|
|
|
137
137
|
return lReturnValue;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
/**
|
|
141
|
+
* @param {import("../../../types/state-machine-cat").IStateMachine} pStateMachine
|
|
142
|
+
* @param {import("../../../types/state-machine-cat").IRenderOptions?} _pOptions
|
|
143
|
+
* @param {import("../../../types/state-machine-cat").ITransition[]?} pTransitions
|
|
144
|
+
* @returns {any}
|
|
145
|
+
*/
|
|
140
146
|
export default function render(pStateMachine, _pOptions, pTransitions) {
|
|
141
147
|
const lInitialPseudoStateName = findInitialPseudoStateName(pStateMachine);
|
|
142
148
|
const lInitialStateName = findInitialStateName(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/*
|
|
2
3
|
* In the XML spec we read: https://www.w3.org/TR/xml/#NT-Name:
|
|
3
4
|
*
|
|
@@ -18,6 +19,11 @@ const NAME_CHAR_FORBIDDEN_RE =
|
|
|
18
19
|
const START_NAME_CHAR_FORBIDDEN_EXTRA_RE =
|
|
19
20
|
/[-|.|0-9|\u00B7|\u0300-\u036F|\u203F-\u2040]/g;
|
|
20
21
|
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param {string} pCandidateNameTail
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
21
27
|
function makeValidNameChars(pCandidateNameTail) {
|
|
22
28
|
return pCandidateNameTail.replace(NAME_CHAR_FORBIDDEN_RE, "_");
|
|
23
29
|
}
|
|
@@ -25,7 +31,7 @@ function makeValidNameChars(pCandidateNameTail) {
|
|
|
25
31
|
/**
|
|
26
32
|
* if it's an invalid NameStartChar but a valid NameChar smack a '_' in front of it
|
|
27
33
|
* if it's an invalid NameChar as well - run it through the makeValidNameChars replacer
|
|
28
|
-
* @param {
|
|
34
|
+
* @param {string} pCandidateChar - start char
|
|
29
35
|
* @returns {string} valid start string
|
|
30
36
|
*/
|
|
31
37
|
function makeValidNameStartChar(pCandidateChar) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import ast2scjson from "../scjson/index.mjs";
|
|
2
3
|
import renderFomSCJSON from "./render-from-scjson.js";
|
|
3
4
|
|
|
5
|
+
/** @type {import("../../../types/state-machine-cat.js").StringRenderFunctionType} */
|
|
4
6
|
export default function renderSCXML(pStateMachine) {
|
|
5
|
-
return renderFomSCJSON(ast2scjson(pStateMachine));
|
|
7
|
+
return renderFomSCJSON(ast2scjson(pStateMachine, null));
|
|
6
8
|
}
|
|
@@ -1,13 +1,25 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @type {any} - the type definitions for Handlebars don't match what we're actually using - hence this override*/
|
|
1
3
|
const Handlebars = require("handlebars/dist/handlebars.runtime.js");
|
|
2
4
|
const cloneDeep = require("lodash/cloneDeep.js");
|
|
3
5
|
|
|
4
6
|
// eslint-disable-next-line import/no-unassigned-import
|
|
5
7
|
require("./smcat.template.js");
|
|
6
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {{hasExtendedAttributes?: boolean} & import("../../../types/state-machine-cat.js").IState} IExtendedState
|
|
11
|
+
* @typedef {{actions: string;} & Omit<IExtendedState, "actions">} IFlattenedActionsState
|
|
12
|
+
*/
|
|
13
|
+
|
|
7
14
|
const NAME_QUOTABLE = /;|,|{| |\[/;
|
|
8
15
|
const ACTIONS_QUOTABLE = /;|,|{/;
|
|
9
16
|
const LABEL_QUOTABLE = /;|{/;
|
|
10
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @param {RegExp} pRegExp
|
|
20
|
+
* @param {string} pString
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
11
23
|
function quoteIfNecessary(pRegExp, pString) {
|
|
12
24
|
return pRegExp.test(pString) ? `"${pString}"` : pString;
|
|
13
25
|
}
|
|
@@ -17,20 +29,31 @@ Handlebars.registerPartial(
|
|
|
17
29
|
Handlebars.templates["smcat.template.hbs"]
|
|
18
30
|
);
|
|
19
31
|
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} pString
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
20
36
|
function formatActionType(pString) {
|
|
21
37
|
return pString === "activity" ? "" : `${pString}/ `;
|
|
22
38
|
}
|
|
23
39
|
|
|
40
|
+
/**
|
|
41
|
+
* @param {IExtendedState} pState
|
|
42
|
+
* @returns {IFlattenedActionsState}
|
|
43
|
+
*/
|
|
24
44
|
function flattenActions(pState) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return lReturnValue;
|
|
45
|
+
return {
|
|
46
|
+
...pState,
|
|
47
|
+
actions: (pState.actions || [])
|
|
48
|
+
.map((pAction) => `${formatActionType(pAction.type)}${pAction.body}`)
|
|
49
|
+
.join("\n "),
|
|
50
|
+
};
|
|
32
51
|
}
|
|
33
52
|
|
|
53
|
+
/**
|
|
54
|
+
* @param {IExtendedState} pState
|
|
55
|
+
* @returns {IExtendedState}
|
|
56
|
+
*/
|
|
34
57
|
/* eslint complexity:0 */
|
|
35
58
|
function flagExtendedStateAttributes(pState) {
|
|
36
59
|
if (
|
|
@@ -40,19 +63,27 @@ function flagExtendedStateAttributes(pState) {
|
|
|
40
63
|
Object.prototype.hasOwnProperty.call(pState, "active") ||
|
|
41
64
|
Object.prototype.hasOwnProperty.call(pState, "class")
|
|
42
65
|
) {
|
|
66
|
+
// note & fixme: mutating a parameter here
|
|
43
67
|
pState.hasExtendedAttributes = true;
|
|
44
68
|
}
|
|
45
69
|
return pState;
|
|
46
70
|
}
|
|
47
71
|
|
|
48
|
-
|
|
72
|
+
/**
|
|
73
|
+
* @param {import("../../../types/state-machine-cat.js").IState[]} pStates
|
|
74
|
+
* @returns {IFlattenedActionsState[]}
|
|
75
|
+
*/
|
|
76
|
+
function transformStates(pStates) {
|
|
49
77
|
pStates
|
|
50
78
|
.map(flagExtendedStateAttributes)
|
|
51
79
|
.filter((pState) => pState.statemachine)
|
|
52
80
|
.forEach((pState) => {
|
|
81
|
+
// @ts-expect-error because of the filter above the statemachine is
|
|
82
|
+
// sure to exist, although TS currently doesn't detect this.
|
|
83
|
+
// also fixme: mutating a parameter here
|
|
53
84
|
pState.statemachine.states = transformStates(
|
|
54
|
-
|
|
55
|
-
|
|
85
|
+
// @ts-expect-error - see above
|
|
86
|
+
pState.statemachine.states
|
|
56
87
|
);
|
|
57
88
|
});
|
|
58
89
|
|
|
@@ -86,10 +117,13 @@ Handlebars.registerHelper("quotifyActions", (pItem) =>
|
|
|
86
117
|
quoteIfNecessary(ACTIONS_QUOTABLE, pItem)
|
|
87
118
|
);
|
|
88
119
|
|
|
89
|
-
|
|
120
|
+
/** @type {import("../../../types/state-machine-cat.js").StringRenderFunctionType} */
|
|
121
|
+
module.exports = function renderSmcat(pStateMachine) {
|
|
90
122
|
return Handlebars.templates["smcat.template.hbs"]({
|
|
91
|
-
...
|
|
92
|
-
states: transformStates(cloneDeep(
|
|
93
|
-
transitions: transformTransitions(
|
|
123
|
+
...pStateMachine,
|
|
124
|
+
states: transformStates(cloneDeep(pStateMachine.states)),
|
|
125
|
+
transitions: transformTransitions(
|
|
126
|
+
cloneDeep(pStateMachine.transitions || [])
|
|
127
|
+
),
|
|
94
128
|
});
|
|
95
129
|
};
|
|
@@ -11,7 +11,7 @@ const DEFAULT_OPTIONS = {
|
|
|
11
11
|
* the result
|
|
12
12
|
*
|
|
13
13
|
* @param {string} pDot The dot program as a string
|
|
14
|
-
* @param {
|
|
14
|
+
* @param {{exec: string, format: import("../../../types/state-machine-cat").OutputType}} pOptions
|
|
15
15
|
* exec: the path to the executable to run. Default: 'dot'
|
|
16
16
|
* @return {string} the dot program converted into an svg
|
|
17
17
|
* @throws {Error} when something ontowards has happened (executable not found, erroneous dot program)
|
|
@@ -10,8 +10,9 @@ const DEFAULT_INDENT = 2;
|
|
|
10
10
|
const DOGMATIC_CONSOLE_WIDTH = 78;
|
|
11
11
|
const VIZ_JS_UNSUPPORTED_OUTPUT_FORMATS = ["pdf", "png"];
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
/** @type {import("../../../types/state-machine-cat.js").StringRenderFunctionType} */
|
|
14
|
+
export default (pStateMachine, pOptions) => {
|
|
15
|
+
const lDotProgram = ast2dot(pStateMachine, pOptions);
|
|
15
16
|
const lDotOptions = {
|
|
16
17
|
engine: options.getOptionValue(pOptions, "engine"),
|
|
17
18
|
format: options.getOptionValue(pOptions, "outputType"),
|
|
@@ -8,8 +8,9 @@ const OUTPUT_TYPE2FORMAT = {
|
|
|
8
8
|
oldeps: "eps",
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
/** @type {import("../../../types/state-machine-cat.js").StringRenderFunctionType} */
|
|
12
|
+
export default (pStateMachine, pOptions) =>
|
|
13
|
+
viz(ast2dot(pStateMachine, pOptions), {
|
|
13
14
|
engine: options.getOptionValue(pOptions, "engine"),
|
|
14
15
|
format:
|
|
15
16
|
OUTPUT_TYPE2FORMAT[options.getOptionValue(pOptions, "outputType")] ||
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* @param {import("../types/state-machine-cat").IState[]} pStates
|
|
4
|
+
* @param {boolean} pHasParent
|
|
5
|
+
* @returns {any} // IFlattenedState - a state, but flattened (statemachine is a boolean, the new attr hasParent as well)
|
|
6
|
+
*/
|
|
1
7
|
function flattenStates(pStates, pHasParent = false) {
|
|
2
8
|
let lReturnValue = [];
|
|
3
9
|
|
|
@@ -6,6 +12,8 @@ function flattenStates(pStates, pHasParent = false) {
|
|
|
6
12
|
.forEach((pState) => {
|
|
7
13
|
if (Object.prototype.hasOwnProperty.call(pState.statemachine, "states")) {
|
|
8
14
|
lReturnValue = lReturnValue.concat(
|
|
15
|
+
// @ts-expect-error TS doesn't detect that after the call in the filter
|
|
16
|
+
// the .statemachine is guaranteed to exist
|
|
9
17
|
flattenStates(pState.statemachine.states, true)
|
|
10
18
|
);
|
|
11
19
|
}
|
|
@@ -21,10 +29,17 @@ function flattenStates(pStates, pHasParent = false) {
|
|
|
21
29
|
);
|
|
22
30
|
}
|
|
23
31
|
|
|
32
|
+
/**
|
|
33
|
+
* @param {import("../types/state-machine-cat").IStateMachine} pStateMachine
|
|
34
|
+
* @returns {import("../types/state-machine-cat").ITransition[]}
|
|
35
|
+
*/
|
|
24
36
|
function flattenTransitions(pStateMachine) {
|
|
37
|
+
/** @type {import("../types/state-machine-cat").ITransition[]} */
|
|
25
38
|
let lTransitions = [];
|
|
26
39
|
|
|
27
40
|
if (Object.prototype.hasOwnProperty.call(pStateMachine, "transitions")) {
|
|
41
|
+
// @ts-expect-error TS doesn't detect that after the call in the if the
|
|
42
|
+
// .transitions is guaranteed to exist
|
|
28
43
|
lTransitions = pStateMachine.transitions;
|
|
29
44
|
}
|
|
30
45
|
if (Object.prototype.hasOwnProperty.call(pStateMachine, "states")) {
|
|
@@ -32,6 +47,8 @@ function flattenTransitions(pStateMachine) {
|
|
|
32
47
|
.filter((pState) => Boolean(pState.statemachine))
|
|
33
48
|
.forEach((pState) => {
|
|
34
49
|
lTransitions = lTransitions.concat(
|
|
50
|
+
// @ts-expect-error TS doesn't detect that after the call in the filter
|
|
51
|
+
// the .statemachine is guaranteed to exist
|
|
35
52
|
flattenTransitions(pState.statemachine)
|
|
36
53
|
);
|
|
37
54
|
});
|
|
@@ -40,25 +57,42 @@ function flattenTransitions(pStateMachine) {
|
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
export default class StateMachineModel {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
/**
|
|
61
|
+
* @param {import("../types/state-machine-cat").IStateMachine} pStateMachine
|
|
62
|
+
*/
|
|
63
|
+
constructor(pStateMachine) {
|
|
64
|
+
this._flattenedStates = flattenStates(pStateMachine.states || []);
|
|
65
|
+
this._flattenedTransitions = flattenTransitions(pStateMachine);
|
|
46
66
|
}
|
|
47
|
-
|
|
67
|
+
/**
|
|
68
|
+
* @returns {import("../types/state-machine-cat").ITransition[]}
|
|
69
|
+
*/
|
|
48
70
|
get flattenedTransitions() {
|
|
49
71
|
return this._flattenedTransitions;
|
|
50
72
|
}
|
|
51
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @param {string} pName
|
|
76
|
+
* @returns {any} // IFlattenedState
|
|
77
|
+
*/
|
|
52
78
|
findStateByName(pName) {
|
|
53
79
|
return this._flattenedStates.find((pState) => pState.name === pName);
|
|
54
80
|
}
|
|
55
81
|
|
|
82
|
+
/**
|
|
83
|
+
* @param {import("../types/state-machine-cat").StateType[]} pTypes
|
|
84
|
+
* @returns {any} // IFlattenedState
|
|
85
|
+
*/
|
|
56
86
|
findStatesByTypes(pTypes) {
|
|
57
87
|
return this._flattenedStates.filter((pState) =>
|
|
58
88
|
pTypes.includes(pState.type)
|
|
59
89
|
);
|
|
60
90
|
}
|
|
61
91
|
|
|
92
|
+
/**
|
|
93
|
+
* @param {string} pStateName
|
|
94
|
+
* @returns {import("../types/state-machine-cat").ITransition[]}
|
|
95
|
+
*/
|
|
62
96
|
findExternalSelfTransitions(pStateName) {
|
|
63
97
|
return this._flattenedTransitions.filter(
|
|
64
98
|
(pTransition) =>
|
|
@@ -68,12 +102,20 @@ export default class StateMachineModel {
|
|
|
68
102
|
);
|
|
69
103
|
}
|
|
70
104
|
|
|
105
|
+
/**
|
|
106
|
+
* @param {string} pFromStateName
|
|
107
|
+
* @returns {import("../types/state-machine-cat").ITransition[]}
|
|
108
|
+
*/
|
|
71
109
|
findTransitionsByFrom(pFromStateName) {
|
|
72
110
|
return this._flattenedTransitions.filter(
|
|
73
111
|
(pTransition) => pTransition.from === pFromStateName
|
|
74
112
|
);
|
|
75
113
|
}
|
|
76
114
|
|
|
115
|
+
/**
|
|
116
|
+
* @param {string} pToStateName
|
|
117
|
+
* @returns {import("../types/state-machine-cat").ITransition[]}
|
|
118
|
+
*/
|
|
77
119
|
findTransitionsByTo(pToStateName) {
|
|
78
120
|
return this._flattenedTransitions.filter(
|
|
79
121
|
(pTransition) => pTransition.to === pToStateName
|
|
@@ -1,14 +1,31 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/* eslint-disable security/detect-object-injection */
|
|
2
3
|
import cloneDeep from "lodash/cloneDeep.js";
|
|
3
4
|
import reject from "lodash/reject.js";
|
|
4
5
|
import StateMachineModel from "../state-machine-model.mjs";
|
|
5
6
|
import utl from "./utl.mjs";
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {{[stateName: string]: import("../../types/state-machine-cat.js").ITransition[]}} ITransitionMap
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {string|undefined} pIncomingThing
|
|
14
|
+
* @param {string} pOutgoingThing
|
|
15
|
+
* @param {string} pJoinChar
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
7
18
|
function fuseTransitionAttribute(pIncomingThing, pOutgoingThing, pJoinChar) {
|
|
8
19
|
return pIncomingThing
|
|
9
20
|
? `${pIncomingThing}${pJoinChar}${pOutgoingThing}`
|
|
10
21
|
: pOutgoingThing;
|
|
11
22
|
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {import("../../types/state-machine-cat.js").ITransition} pIncomingTransition
|
|
26
|
+
* @param {import("../../types/state-machine-cat.js").ITransition} pOutgoingTransition
|
|
27
|
+
* @returns {import("../../types/state-machine-cat.js").ITransition}
|
|
28
|
+
*/
|
|
12
29
|
function fuseIncomingToOutgoing(pIncomingTransition, pOutgoingTransition) {
|
|
13
30
|
// in:
|
|
14
31
|
// a => ]: event [condition]/ action;
|
|
@@ -19,6 +36,7 @@ function fuseIncomingToOutgoing(pIncomingTransition, pOutgoingTransition) {
|
|
|
19
36
|
//
|
|
20
37
|
// events and conditions are illegal on transitions outgoing
|
|
21
38
|
// from forks, so we ignore them
|
|
39
|
+
/** @type {import("../../types/state-machine-cat.js").ITransition} */
|
|
22
40
|
const lReturnValue = {
|
|
23
41
|
...pIncomingTransition,
|
|
24
42
|
...pOutgoingTransition,
|
|
@@ -44,27 +62,50 @@ function fuseIncomingToOutgoing(pIncomingTransition, pOutgoingTransition) {
|
|
|
44
62
|
return lReturnValue;
|
|
45
63
|
}
|
|
46
64
|
|
|
65
|
+
/**
|
|
66
|
+
* @param {import("../../types/state-machine-cat.js").ITransition[]} pTransitions
|
|
67
|
+
* @param {string[]} pPseudoStateNames
|
|
68
|
+
* @param {ITransitionMap} pOutgoingTransitionMap
|
|
69
|
+
* @returns {import("../../types/state-machine-cat.js").ITransition[]}
|
|
70
|
+
*/
|
|
47
71
|
function fuseTransitions(
|
|
48
72
|
pTransitions,
|
|
49
73
|
pPseudoStateNames,
|
|
50
74
|
pOutgoingTransitionMap
|
|
51
75
|
) {
|
|
52
|
-
return pTransitions.reduce(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
76
|
+
return pTransitions.reduce(
|
|
77
|
+
/**
|
|
78
|
+
* @param {import("../../types/state-machine-cat.js").ITransition[]} pAll
|
|
79
|
+
* @param {import("../../types/state-machine-cat.js").ITransition} pTransition
|
|
80
|
+
* @returns {import("../../types/state-machine-cat.js").ITransition[]}
|
|
81
|
+
*/
|
|
82
|
+
(pAll, pTransition) => {
|
|
83
|
+
pPseudoStateNames.forEach((pStateName, pIndex) => {
|
|
84
|
+
if (
|
|
85
|
+
pStateName === pTransition.to &&
|
|
86
|
+
pOutgoingTransitionMap[pStateName]
|
|
87
|
+
) {
|
|
88
|
+
pAll = pAll.concat(
|
|
89
|
+
pOutgoingTransitionMap[pStateName].map((pOutgoingTransition) =>
|
|
90
|
+
fuseIncomingToOutgoing(pTransition, pOutgoingTransition)
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
} else {
|
|
94
|
+
pAll = pIndex === 0 ? pAll.concat(pTransition) : pAll;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
return pAll;
|
|
98
|
+
},
|
|
99
|
+
[]
|
|
100
|
+
);
|
|
66
101
|
}
|
|
67
102
|
|
|
103
|
+
/**
|
|
104
|
+
* @param {import("../../types/state-machine-cat.js").IStateMachine} pMachine
|
|
105
|
+
* @param {string[]} pPseudoStateNames
|
|
106
|
+
* @param {ITransitionMap} pOutgoingTransitionMap
|
|
107
|
+
* @returns {import("../../types/state-machine-cat.js").IStateMachine}
|
|
108
|
+
*/
|
|
68
109
|
function deSugarPseudoStates(
|
|
69
110
|
pMachine,
|
|
70
111
|
pPseudoStateNames,
|
|
@@ -96,6 +137,11 @@ function deSugarPseudoStates(
|
|
|
96
137
|
return lMachine;
|
|
97
138
|
}
|
|
98
139
|
|
|
140
|
+
/**
|
|
141
|
+
* @param {import("../../types/state-machine-cat.js").IStateMachine} pMachine
|
|
142
|
+
* @param {string[]} pStateNames
|
|
143
|
+
* @returns {import("../../types/state-machine-cat.js").IStateMachine}
|
|
144
|
+
*/
|
|
99
145
|
function removeStatesCascading(pMachine, pStateNames) {
|
|
100
146
|
const lMachine = cloneDeep(pMachine);
|
|
101
147
|
|
|
@@ -142,19 +188,22 @@ function removeStatesCascading(pMachine, pStateNames) {
|
|
|
142
188
|
* b => d;
|
|
143
189
|
* ```
|
|
144
190
|
*
|
|
145
|
-
* @param {IStateMachine} pMachine The state machine still containing forks
|
|
146
|
-
* @param {StateType[]} pDesugarableStates array of de-sugarable states
|
|
147
|
-
* @returns {IStateMachine}
|
|
191
|
+
* @param {import("../../types/state-machine-cat.js").IStateMachine} pMachine The state machine still containing forks
|
|
192
|
+
* @param {import("../../types/state-machine-cat.js").StateType[]} pDesugarableStates array of de-sugarable states
|
|
193
|
+
* @returns {import("../../types/state-machine-cat.js").IStateMachine} the transformed state machine
|
|
148
194
|
*/
|
|
149
195
|
export default (
|
|
150
196
|
pMachine,
|
|
151
197
|
pDesugarableStates = ["fork", "junction", "choice"]
|
|
152
198
|
) => {
|
|
153
199
|
const lModel = new StateMachineModel(pMachine);
|
|
200
|
+
|
|
201
|
+
/** @type {string[]} */
|
|
154
202
|
const lPseudoStateNames = lModel
|
|
155
203
|
.findStatesByTypes(pDesugarableStates)
|
|
156
|
-
.map((
|
|
204
|
+
.map(({ name }) => name);
|
|
157
205
|
|
|
206
|
+
/** @type {ITransitionMap} */
|
|
158
207
|
const lOutgoingTransitionMap = lPseudoStateNames.reduce(
|
|
159
208
|
(pAll, pStateName) => {
|
|
160
209
|
pAll[pStateName] = lModel.findTransitionsByFrom(pStateName);
|
package/src/transform/utl.mjs
CHANGED
package/src/version.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// generated by tools/get-version.mjs - edits will be overwritten
|
|
2
|
-
export const version = "10.1.
|
|
2
|
+
export const version = "10.1.3";
|
|
@@ -183,13 +183,22 @@ export function getAllowedValues(): IAllowedValues;
|
|
|
183
183
|
export type InputType = "smcat" | "json" | "scxml";
|
|
184
184
|
|
|
185
185
|
export type OutputType =
|
|
186
|
-
| "
|
|
186
|
+
| "ast"
|
|
187
187
|
| "dot"
|
|
188
|
+
| "eps"
|
|
188
189
|
| "json"
|
|
189
|
-
| "
|
|
190
|
-
| "
|
|
190
|
+
| "oldeps"
|
|
191
|
+
| "oldps"
|
|
192
|
+
| "oldps2"
|
|
193
|
+
| "oldsvg"
|
|
194
|
+
| "pdf"
|
|
195
|
+
| "png"
|
|
196
|
+
| "ps"
|
|
197
|
+
| "ps2"
|
|
191
198
|
| "scjson"
|
|
192
|
-
| "scxml"
|
|
199
|
+
| "scxml"
|
|
200
|
+
| "smcat"
|
|
201
|
+
| "svg";
|
|
193
202
|
|
|
194
203
|
export type EngineType = "dot" | "circo" | "fdp" | "neato" | "osage" | "twopi";
|
|
195
204
|
|
|
@@ -204,7 +213,7 @@ export type dotAttributesType = {
|
|
|
204
213
|
value: string;
|
|
205
214
|
}[];
|
|
206
215
|
|
|
207
|
-
export interface
|
|
216
|
+
export interface IBaseRenderOptions {
|
|
208
217
|
/**
|
|
209
218
|
* How to interpret the input (defaults to 'smcat')
|
|
210
219
|
*/
|
|
@@ -222,6 +231,17 @@ export interface IRenderOptions {
|
|
|
222
231
|
* (defaults to 'top-down')
|
|
223
232
|
*/
|
|
224
233
|
direction?: DirectionType;
|
|
234
|
+
/**
|
|
235
|
+
* If true state machine cat will replace 'sugar' pseudo states
|
|
236
|
+
* (choice, forks and junctions) with their equivalent meaning
|
|
237
|
+
* (defaults to false).
|
|
238
|
+
*
|
|
239
|
+
* For details: https://github.com/sverweij/state-machine-cat/blob/master/docs/desugar.md
|
|
240
|
+
*/
|
|
241
|
+
desugar?: boolean;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface IRenderOptions extends IBaseRenderOptions {
|
|
225
245
|
/**
|
|
226
246
|
* For the 'dot' renderer: Graph attributes to the engine
|
|
227
247
|
*/
|
|
@@ -234,18 +254,25 @@ export interface IRenderOptions {
|
|
|
234
254
|
* For the 'dot' renderer: Edge attributes to the engine
|
|
235
255
|
*/
|
|
236
256
|
dotEdgeAttrs?: dotAttributesType;
|
|
237
|
-
/**
|
|
238
|
-
* If true state machine cat will replace 'sugar' pseudo states
|
|
239
|
-
* (choice, forks and junctions) with their equivalent meaning
|
|
240
|
-
* (defaults to false).
|
|
241
|
-
*
|
|
242
|
-
* For details: https://github.com/sverweij/state-machine-cat/blob/master/docs/desugar.md
|
|
243
|
-
*/
|
|
244
|
-
desugar?: boolean;
|
|
245
257
|
}
|
|
246
258
|
|
|
259
|
+
export type StringRenderFunctionType = (
|
|
260
|
+
pScript: IStateMachine,
|
|
261
|
+
pOptions: IRenderOptions
|
|
262
|
+
) => string;
|
|
263
|
+
|
|
264
|
+
export type WhateverRenderFunctionType = (
|
|
265
|
+
pScript: IStateMachine,
|
|
266
|
+
pOptions: IRenderOptions
|
|
267
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
268
|
+
) => any;
|
|
269
|
+
|
|
270
|
+
export type RenderFunctionType =
|
|
271
|
+
| StringRenderFunctionType
|
|
272
|
+
| WhateverRenderFunctionType;
|
|
273
|
+
|
|
247
274
|
/**
|
|
248
|
-
* Translates the input script to an
|
|
275
|
+
* Translates the input script to an output script.
|
|
249
276
|
*
|
|
250
277
|
* @param pScript The script to translate
|
|
251
278
|
* @param pOptions options influencing parsing & rendering.
|