state-machine-cat 12.0.18 → 12.0.20
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 +1 -1
- package/dist/cli/cli.mjs +2 -17
- package/dist/counter.mjs +9 -0
- package/dist/parse/index.mjs +1 -1
- package/dist/parse/parser-helpers.mjs +0 -9
- package/dist/parse/scxml/index.mjs +11 -8
- package/dist/parse/smcat/parse.mjs +5 -0
- package/dist/parse/smcat/smcat-parser.mjs +1 -2
- package/dist/parse/smcat-ast.schema.mjs +1 -1
- package/dist/render/dot/index.mjs +43 -16
- package/dist/render/dot/utl.mjs +3 -2
- package/dist/state-machine-model.mjs +22 -12
- package/dist/transform/desugar.mjs +14 -2
- package/dist/version.mjs +1 -1
- package/package.json +2 -3
- package/types/state-machine-cat.d.mts +4 -4
package/README.md
CHANGED
|
@@ -518,7 +518,7 @@ eat -> sleep [color="blue" width=3.5] : belly full;
|
|
|
518
518
|
|
|
519
519
|
... would yield this diagram:
|
|
520
520
|
|
|
521
|
-
<img width="
|
|
521
|
+
<img width="488" alt="colored states and transitions" src="https://raw.githubusercontent.com/sverweij/state-machine-cat/main/docs/pics/10colored_states_and_transitions.png">
|
|
522
522
|
|
|
523
523
|
What does 'experimental' mean?
|
|
524
524
|
|
package/dist/cli/cli.mjs
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
1
|
import { parseArgs } from "node:util";
|
|
3
|
-
import
|
|
2
|
+
import { version } from "../version.mjs";
|
|
4
3
|
import { formatError, displayLicense, transform } from "./actions.mjs";
|
|
5
4
|
import normalize from "./normalize.mjs";
|
|
6
5
|
import validations from "./validations.mjs";
|
|
7
|
-
const $package = JSON.parse(
|
|
8
|
-
readFileSync(new URL("../../package.json", import.meta.url), "utf8"),
|
|
9
|
-
);
|
|
10
6
|
const HELP_TEXT = `Usage: smcat [options] [infile]
|
|
11
7
|
|
|
12
8
|
Write beautiful state charts - https://github.com/sverweij/state-machine-cat
|
|
@@ -130,31 +126,20 @@ function parseArguments(pArguments) {
|
|
|
130
126
|
);
|
|
131
127
|
return { values: camelizeObject(values), positionals };
|
|
132
128
|
}
|
|
133
|
-
function assertNodeVersion(pCurrentNodeVersion, pSupportedEngines) {
|
|
134
|
-
if (!satisfies(pCurrentNodeVersion, pSupportedEngines)) {
|
|
135
|
-
throw new Error(
|
|
136
|
-
`\nERROR: your node version (${pCurrentNodeVersion}) is not recent enough.\n` +
|
|
137
|
-
` state-machine-cat is supported on node ${pSupportedEngines}\n\n`,
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
129
|
export default async function cli(pArguments = process.argv, pOptions) {
|
|
142
130
|
const lOptions = {
|
|
143
|
-
currentNodeVersion: process.versions.node,
|
|
144
|
-
supportedEngines: $package.engines.node,
|
|
145
131
|
outStream: process.stdout,
|
|
146
132
|
errorStream: process.stderr,
|
|
147
133
|
...pOptions,
|
|
148
134
|
};
|
|
149
135
|
try {
|
|
150
|
-
assertNodeVersion(lOptions.currentNodeVersion, lOptions.supportedEngines);
|
|
151
136
|
const { values, positionals } = parseArguments(pArguments.slice(2));
|
|
152
137
|
if (values.help) {
|
|
153
138
|
lOptions.outStream.write(HELP_TEXT, "utf8");
|
|
154
139
|
return;
|
|
155
140
|
}
|
|
156
141
|
if (values.version) {
|
|
157
|
-
lOptions.outStream.write(`${
|
|
142
|
+
lOptions.outStream.write(`${version}\n`, "utf8");
|
|
158
143
|
return;
|
|
159
144
|
}
|
|
160
145
|
if (values.license) {
|
package/dist/counter.mjs
ADDED
package/dist/parse/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
2
|
import options from "../options.mjs";
|
|
3
|
-
import { parse as parseSmCat } from "./smcat/
|
|
3
|
+
import { parse as parseSmCat } from "./smcat/parse.mjs";
|
|
4
4
|
import { parse as parseSCXML } from "./scxml/index.mjs";
|
|
5
5
|
import $schema from "./smcat-ast.schema.mjs";
|
|
6
6
|
const ajv = new Ajv();
|
|
@@ -2,7 +2,6 @@ import StateMachineModel from "../state-machine-model.mjs";
|
|
|
2
2
|
const TRIGGER_RE_AS_A_STRING =
|
|
3
3
|
"^(entry|activity|exit)\\s*/\\s*([^\\n$]*)(\\n|$)";
|
|
4
4
|
const TRIGGER_RE = new RegExp(TRIGGER_RE_AS_A_STRING);
|
|
5
|
-
let gTransitionIdHwm = 0;
|
|
6
5
|
function stateExists(pKnownStateNames, pName) {
|
|
7
6
|
return pKnownStateNames.includes(pName);
|
|
8
7
|
}
|
|
@@ -181,12 +180,6 @@ function extractActions(pString) {
|
|
|
181
180
|
.map((pActivityCandidate) => pActivityCandidate.trim())
|
|
182
181
|
.map(extractAction);
|
|
183
182
|
}
|
|
184
|
-
function nextTransitionId() {
|
|
185
|
-
return ++gTransitionIdHwm;
|
|
186
|
-
}
|
|
187
|
-
function resetTransitionId() {
|
|
188
|
-
gTransitionIdHwm = 0;
|
|
189
|
-
}
|
|
190
183
|
export default {
|
|
191
184
|
initState,
|
|
192
185
|
extractUndeclaredStates,
|
|
@@ -198,6 +191,4 @@ export default {
|
|
|
198
191
|
extractActions,
|
|
199
192
|
setIf,
|
|
200
193
|
setIfNotEmpty,
|
|
201
|
-
nextTransitionId,
|
|
202
|
-
resetTransitionId,
|
|
203
194
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import fastxml from "fast-xml-parser";
|
|
2
2
|
import he from "he";
|
|
3
|
-
import traverse from "
|
|
4
|
-
import
|
|
3
|
+
import traverse from "neotraverse";
|
|
4
|
+
import { Counter } from "../../counter.mjs";
|
|
5
5
|
import parserHelpers from "../parser-helpers.mjs";
|
|
6
|
+
import utl from "../../transform/utl.mjs";
|
|
6
7
|
import { castArray } from "./utl.mjs";
|
|
7
8
|
import { normalizeMachine } from "./normalize-machine.mjs";
|
|
8
9
|
const formatLabel = utl.formatLabel;
|
|
@@ -97,12 +98,13 @@ function extractTransitionAttributes(pTransition) {
|
|
|
97
98
|
}
|
|
98
99
|
return lReturnValue;
|
|
99
100
|
}
|
|
100
|
-
function reduceTransition(pState) {
|
|
101
|
+
function reduceTransition(pState, pCounter) {
|
|
101
102
|
return (pAllTransitions, pTransition) => {
|
|
102
103
|
const lTargets = (pTransition?.target ?? pState.id).split(/\s+/);
|
|
103
104
|
const lTransitionAttributes = extractTransitionAttributes(pTransition);
|
|
104
105
|
return pAllTransitions.concat(
|
|
105
106
|
lTargets.map((pTarget) => ({
|
|
107
|
+
id: pCounter.next(),
|
|
106
108
|
from: pState.id,
|
|
107
109
|
to: pTarget,
|
|
108
110
|
...lTransitionAttributes,
|
|
@@ -110,13 +112,13 @@ function reduceTransition(pState) {
|
|
|
110
112
|
);
|
|
111
113
|
};
|
|
112
114
|
}
|
|
113
|
-
function extractTransitions(pStates) {
|
|
115
|
+
function extractTransitions(pStates, pCounter) {
|
|
114
116
|
return pStates
|
|
115
117
|
.filter((pState) => Object.hasOwn(pState, "transition"))
|
|
116
118
|
.reduce((pAllTransitions, pThisState) => {
|
|
117
119
|
const lTransitionAsArray = castArray(pThisState.transition);
|
|
118
120
|
return pAllTransitions.concat(
|
|
119
|
-
lTransitionAsArray.reduce(reduceTransition(pThisState), []),
|
|
121
|
+
lTransitionAsArray.reduce(reduceTransition(pThisState, pCounter), []),
|
|
120
122
|
);
|
|
121
123
|
}, []);
|
|
122
124
|
}
|
|
@@ -130,9 +132,10 @@ function mapMachine(pSCXMLStateMachine) {
|
|
|
130
132
|
.concat(lNormalizedMachine.history.map(mapState("history")))
|
|
131
133
|
.concat(lNormalizedMachine.final.map(mapState("final"))),
|
|
132
134
|
};
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
.concat(extractTransitions(lNormalizedMachine.
|
|
135
|
+
const lCounter = new Counter();
|
|
136
|
+
const lTransitions = extractTransitions(lNormalizedMachine.initial, lCounter)
|
|
137
|
+
.concat(extractTransitions(lNormalizedMachine.state, lCounter))
|
|
138
|
+
.concat(extractTransitions(lNormalizedMachine.parallel, lCounter));
|
|
136
139
|
if (lTransitions.length > 0) {
|
|
137
140
|
lReturnValue.transitions = lTransitions;
|
|
138
141
|
}
|
|
@@ -321,7 +321,6 @@ function peg$parse(input, options) {
|
|
|
321
321
|
var peg$e78 = peg$classExpectation(["\r", "\n"], true, false);
|
|
322
322
|
var peg$e79 = peg$otherExpectation("comment");
|
|
323
323
|
var peg$f0 = function (statemachine) {
|
|
324
|
-
parserHelpers.resetTransitionId();
|
|
325
324
|
statemachine.states = parserHelpers.extractUndeclaredStates(statemachine);
|
|
326
325
|
return parserHelpers.classifyForkJoins(statemachine);
|
|
327
326
|
};
|
|
@@ -431,7 +430,7 @@ function peg$parse(input, options) {
|
|
|
431
430
|
),
|
|
432
431
|
);
|
|
433
432
|
parserHelpers.setIfNotEmpty(trans, "note", notes);
|
|
434
|
-
trans.id =
|
|
433
|
+
trans.id = options.counter.next();
|
|
435
434
|
return trans;
|
|
436
435
|
};
|
|
437
436
|
var peg$f20 = function (from_, to) {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
normalizeState,
|
|
17
17
|
stateNote,
|
|
18
18
|
} from "./utl.mjs";
|
|
19
|
+
let gRenderedTransitions = new Set();
|
|
19
20
|
function initial(pState, pIndent) {
|
|
20
21
|
const lActiveAttribute = pState.active ? " penwidth=3.0" : "";
|
|
21
22
|
return `${pIndent} "${pState.name}" [shape=circle style=filled class="${pState.class}" color="${pState.color}" fillcolor="${pState.color}" fixedsize=true height=0.15 label=""${lActiveAttribute}]${pState.noteText}`;
|
|
@@ -164,13 +165,28 @@ const STATE_TYPE2FUNCTION = new Map([
|
|
|
164
165
|
]);
|
|
165
166
|
function state(pState, pIndent, pOptions, pModel) {
|
|
166
167
|
const lState = normalizeState(pState, pOptions, pIndent);
|
|
168
|
+
const lCandidateTransitions = pModel.findTransitionsToSiblings(
|
|
169
|
+
pState.name,
|
|
170
|
+
gRenderedTransitions,
|
|
171
|
+
);
|
|
172
|
+
lCandidateTransitions.forEach((pTransition) => {
|
|
173
|
+
gRenderedTransitions.add(pTransition.id);
|
|
174
|
+
});
|
|
175
|
+
const lTransitions = transitions(
|
|
176
|
+
lCandidateTransitions,
|
|
177
|
+
pIndent,
|
|
178
|
+
pOptions,
|
|
179
|
+
pModel,
|
|
180
|
+
);
|
|
167
181
|
return (
|
|
168
182
|
(STATE_TYPE2FUNCTION.get(pState.type) ?? regular)(
|
|
169
183
|
lState,
|
|
170
184
|
pIndent,
|
|
171
185
|
pOptions,
|
|
172
186
|
pModel,
|
|
173
|
-
) +
|
|
187
|
+
) +
|
|
188
|
+
lTransitions +
|
|
189
|
+
"\n"
|
|
174
190
|
);
|
|
175
191
|
}
|
|
176
192
|
function states(pStates, pIndent, pOptions, pModel) {
|
|
@@ -197,25 +213,32 @@ function transition(pTransition, pIndent, pOptions, pModel) {
|
|
|
197
213
|
? ` lhead="cluster_${pTransition.to}"`
|
|
198
214
|
: "";
|
|
199
215
|
const lTransitionName = `tr_${pTransition.from}_${pTransition.to}_${pTransition.id}`;
|
|
200
|
-
if (pTransition.note) {
|
|
201
|
-
const lNoteName = `note_${lTransitionName}`;
|
|
202
|
-
const lNoteNodeName = `i_${lNoteName}`;
|
|
203
|
-
const lNoteNode = `\n${pIndent} "${lNoteNodeName}" [shape=point style=invis margin=0 width=0 height=0 fixedsize=true]`;
|
|
204
|
-
const lTransitionFrom = `\n${pIndent} "${pTransition.from}" -> "${lNoteNodeName}" [arrowhead=none${lTail}${lColorAttribute}]`;
|
|
205
|
-
const lTransitionTo = `\n${pIndent} "${lNoteNodeName}" -> "${pTransition.to}" [label="${lLabel}"${lHead}${lColorAttribute}${lFontColorAttribute}]`;
|
|
206
|
-
const lLineToNote = `\n${pIndent} "${lNoteNodeName}" -> "${lNoteName}" [style=dashed arrowtail=none arrowhead=none weight=0]`;
|
|
207
|
-
const lNote = `\n${pIndent} "${lNoteName}" [label="${noteToLabel(pTransition.note)}" shape=note fontsize=10 color=black fontcolor=black fillcolor="#ffffcc" penwidth=1.0]`;
|
|
208
|
-
return lNoteNode + lTransitionFrom + lTransitionTo + lLineToNote + lNote;
|
|
209
|
-
}
|
|
210
216
|
if (isCompositeSelf(pModel, pTransition)) {
|
|
211
217
|
const { lTailPorts, lHeadPorts } = getTransitionPorts(
|
|
212
218
|
pOptions,
|
|
213
219
|
pModel,
|
|
214
220
|
pTransition,
|
|
215
221
|
);
|
|
216
|
-
|
|
222
|
+
let lNoteAndLine = "";
|
|
223
|
+
if (pTransition.note) {
|
|
224
|
+
const lNoteName = `note_${lTransitionName}`;
|
|
225
|
+
const lLineToNote = `\n${pIndent} "${lNoteName}" -> "self_tr_${pTransition.from}_${pTransition.to}_${pTransition.id}" [style=dashed arrowtail=none arrowhead=none weight=0]`;
|
|
226
|
+
const lNote = `\n${pIndent} "${lNoteName}" [label="${noteToLabel(pTransition.note)}" shape=note fontsize=10 color=black fontcolor=black fillcolor="#ffffcc" penwidth=1.0]`;
|
|
227
|
+
lNoteAndLine = lLineToNote + lNote;
|
|
228
|
+
}
|
|
229
|
+
const lTransitionFrom = `\n${pIndent} "${pTransition.from}" -> "self_tr_${pTransition.from}_${pTransition.to}_${pTransition.id}" [label="${lLabel}" arrowhead=none class="${lClass}"${lTailPorts}${lTail}${lColorAttribute}${lFontColorAttribute}${lPenWidth}]`;
|
|
217
230
|
const lTransitionTo = `\n${pIndent} "self_tr_${pTransition.from}_${pTransition.to}_${pTransition.id}" -> "${pTransition.to}" [class="${lClass}"${lHead}${lHeadPorts}${lColorAttribute}${lPenWidth}]`;
|
|
218
|
-
return lTransitionFrom + lTransitionTo;
|
|
231
|
+
return lTransitionFrom + lTransitionTo + lNoteAndLine;
|
|
232
|
+
}
|
|
233
|
+
if (pTransition.note) {
|
|
234
|
+
const lNoteName = `note_${lTransitionName}`;
|
|
235
|
+
const lNoteNodeName = `i_${lNoteName}`;
|
|
236
|
+
const lNoteNode = `\n${pIndent} "${lNoteNodeName}" [shape=point style=invis margin=0 width=0 height=0 fixedsize=true]`;
|
|
237
|
+
const lTransitionFrom = `\n${pIndent} "${pTransition.from}" -> "${lNoteNodeName}" [arrowhead=none${lTail}${lColorAttribute}${lPenWidth}]`;
|
|
238
|
+
const lTransitionTo = `\n${pIndent} "${lNoteNodeName}" -> "${pTransition.to}" [label="${lLabel}"${lHead}${lColorAttribute}${lFontColorAttribute}${lPenWidth}]`;
|
|
239
|
+
const lLineToNote = `\n${pIndent} "${lNoteNodeName}" -> "${lNoteName}" [style=dashed arrowtail=none arrowhead=none weight=0]`;
|
|
240
|
+
const lNote = `\n${pIndent} "${lNoteName}" [label="${noteToLabel(pTransition.note)}" shape=note fontsize=10 color=black fontcolor=black fillcolor="#ffffcc" penwidth=1.0]`;
|
|
241
|
+
return lNoteNode + lTransitionFrom + lTransitionTo + lLineToNote + lNote;
|
|
219
242
|
}
|
|
220
243
|
return `\n${pIndent} "${pTransition.from}" -> "${pTransition.to}" [label="${lLabel}" class="${lClass}"${lTail}${lHead}${lColorAttribute}${lFontColorAttribute}${lPenWidth}]`;
|
|
221
244
|
}
|
|
@@ -233,19 +256,23 @@ export default function renderDot(pStateMachine, pOptions = {}, pIndent = "") {
|
|
|
233
256
|
const lNodeAttributes = buildNodeAttributes(pOptions.dotNodeAttrs || []);
|
|
234
257
|
const lEdgeAttributes = buildEdgeAttributes(pOptions.dotEdgeAttrs || []);
|
|
235
258
|
const lModel = new StateMachineModel(pStateMachine);
|
|
259
|
+
gRenderedTransitions = new Set();
|
|
236
260
|
const lStates = states(pStateMachine.states, pIndent, pOptions, lModel);
|
|
237
|
-
const
|
|
238
|
-
lModel.flattenedTransitions
|
|
261
|
+
const lRemainingTransitions = transitions(
|
|
262
|
+
lModel.flattenedTransitions.filter(
|
|
263
|
+
(pTransition) => !gRenderedTransitions.has(pTransition.id),
|
|
264
|
+
),
|
|
239
265
|
pIndent,
|
|
240
266
|
pOptions,
|
|
241
267
|
lModel,
|
|
242
268
|
);
|
|
269
|
+
gRenderedTransitions = new Set();
|
|
243
270
|
return `digraph "state transitions" {
|
|
244
271
|
${lGraphAttributes}
|
|
245
272
|
node [${lNodeAttributes}]
|
|
246
273
|
edge [${lEdgeAttributes}]
|
|
247
274
|
|
|
248
|
-
${lStates}${
|
|
275
|
+
${lStates}${lRemainingTransitions}
|
|
249
276
|
}
|
|
250
277
|
`;
|
|
251
278
|
}
|
package/dist/render/dot/utl.mjs
CHANGED
|
@@ -42,7 +42,8 @@ export function isVertical(pDirection) {
|
|
|
42
42
|
export function isCompositeSelf(pStateMachineModel, pTransition) {
|
|
43
43
|
return (
|
|
44
44
|
pTransition.from === pTransition.to &&
|
|
45
|
-
pStateMachineModel.findStateByName(pTransition.from)
|
|
45
|
+
(pStateMachineModel.findStateByName(pTransition.from)?.statemachine ??
|
|
46
|
+
false) &&
|
|
46
47
|
pTransition.type !== "internal"
|
|
47
48
|
);
|
|
48
49
|
}
|
|
@@ -94,7 +95,7 @@ export function getTransitionPorts(pOptions, pModel, pTransition) {
|
|
|
94
95
|
if (isVertical(lDirection)) {
|
|
95
96
|
lTailPorts = ' tailport="e" headport="e"';
|
|
96
97
|
lHeadPorts = ' tailport="w"';
|
|
97
|
-
} else if (pModel.findStateByName(pTransition.from)
|
|
98
|
+
} else if (pModel.findStateByName(pTransition.from)?.parent ?? false) {
|
|
98
99
|
lTailPorts = ' tailport="n" headport="n"';
|
|
99
100
|
lHeadPorts = ' tailport="s"';
|
|
100
101
|
}
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
function
|
|
2
|
-
let lReturnValue = [];
|
|
1
|
+
function flattenStatesToMap(pStates, pMap, pParent = "") {
|
|
3
2
|
pStates
|
|
4
3
|
.filter((pState) => Boolean(pState.statemachine))
|
|
5
4
|
.forEach((pState) => {
|
|
6
5
|
if (Object.hasOwn(pState.statemachine, "states")) {
|
|
7
|
-
|
|
8
|
-
flattenStates(pState.statemachine.states, true),
|
|
9
|
-
);
|
|
6
|
+
flattenStatesToMap(pState.statemachine.states, pMap, pState.name);
|
|
10
7
|
}
|
|
11
8
|
});
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
pStates.forEach((pState) =>
|
|
10
|
+
pMap.set(pState.name, {
|
|
14
11
|
name: pState.name,
|
|
15
12
|
type: pState.type,
|
|
16
13
|
statemachine: Boolean(pState.statemachine),
|
|
17
|
-
|
|
18
|
-
})
|
|
14
|
+
parent: pParent,
|
|
15
|
+
}),
|
|
19
16
|
);
|
|
20
17
|
}
|
|
21
18
|
function flattenTransitions(pStateMachine) {
|
|
@@ -38,17 +35,18 @@ export default class StateMachineModel {
|
|
|
38
35
|
_flattenedTransitions;
|
|
39
36
|
_flattenedStates;
|
|
40
37
|
constructor(pStateMachine) {
|
|
41
|
-
this._flattenedStates =
|
|
38
|
+
this._flattenedStates = new Map();
|
|
39
|
+
flattenStatesToMap(pStateMachine.states ?? [], this._flattenedStates);
|
|
42
40
|
this._flattenedTransitions = flattenTransitions(pStateMachine);
|
|
43
41
|
}
|
|
44
42
|
get flattenedTransitions() {
|
|
45
43
|
return this._flattenedTransitions;
|
|
46
44
|
}
|
|
47
45
|
findStateByName(pName) {
|
|
48
|
-
return this._flattenedStates.
|
|
46
|
+
return this._flattenedStates.get(pName);
|
|
49
47
|
}
|
|
50
48
|
findStatesByTypes(pTypes) {
|
|
51
|
-
return this._flattenedStates.filter((pState) =>
|
|
49
|
+
return Array.from(this._flattenedStates.values()).filter((pState) =>
|
|
52
50
|
pTypes.includes(pState.type),
|
|
53
51
|
);
|
|
54
52
|
}
|
|
@@ -70,4 +68,16 @@ export default class StateMachineModel {
|
|
|
70
68
|
(pTransition) => pTransition.to === pToStateName,
|
|
71
69
|
);
|
|
72
70
|
}
|
|
71
|
+
getMaximumTransitionId() {
|
|
72
|
+
return Math.max(...this._flattenedTransitions.map(({ id }) => id));
|
|
73
|
+
}
|
|
74
|
+
findTransitionsToSiblings(pStateName, pExcludeIds) {
|
|
75
|
+
return this._flattenedTransitions.filter(
|
|
76
|
+
(pTransition) =>
|
|
77
|
+
!pExcludeIds.has(pTransition.id) &&
|
|
78
|
+
pTransition.from === pStateName &&
|
|
79
|
+
this._flattenedStates.get(pTransition.to)?.parent ===
|
|
80
|
+
this._flattenedStates.get(pStateName)?.parent,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
73
83
|
}
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import StateMachineModel from "../state-machine-model.mjs";
|
|
2
|
+
import { Counter } from "../counter.mjs";
|
|
2
3
|
import utl from "./utl.mjs";
|
|
3
4
|
function fuseTransitionAttribute(pIncomingThing, pOutgoingThing, pJoinChar) {
|
|
4
5
|
return pIncomingThing
|
|
5
6
|
? `${pIncomingThing}${pJoinChar}${pOutgoingThing}`
|
|
6
7
|
: pOutgoingThing;
|
|
7
8
|
}
|
|
8
|
-
function fuseIncomingToOutgoing(
|
|
9
|
+
function fuseIncomingToOutgoing(
|
|
10
|
+
pIncomingTransition,
|
|
11
|
+
pOutgoingTransition,
|
|
12
|
+
pCounter,
|
|
13
|
+
) {
|
|
9
14
|
const lReturnValue = {
|
|
10
15
|
...pIncomingTransition,
|
|
11
16
|
...pOutgoingTransition,
|
|
12
17
|
from: pIncomingTransition.from,
|
|
13
18
|
to: pOutgoingTransition.to,
|
|
19
|
+
id: pCounter.next(),
|
|
14
20
|
};
|
|
15
21
|
if (pOutgoingTransition.action) {
|
|
16
22
|
lReturnValue.action = fuseTransitionAttribute(
|
|
@@ -32,13 +38,14 @@ function fuseTransitions(
|
|
|
32
38
|
pTransitions,
|
|
33
39
|
pPseudoStateNames,
|
|
34
40
|
pOutgoingTransitionMap,
|
|
41
|
+
pCounter,
|
|
35
42
|
) {
|
|
36
43
|
return pTransitions.reduce((pAll, pTransition) => {
|
|
37
44
|
pPseudoStateNames.forEach((pStateName, pIndex) => {
|
|
38
45
|
if (pStateName === pTransition.to && pOutgoingTransitionMap[pStateName]) {
|
|
39
46
|
pAll = pAll.concat(
|
|
40
47
|
pOutgoingTransitionMap[pStateName].map((pOutgoingTransition) =>
|
|
41
|
-
fuseIncomingToOutgoing(pTransition, pOutgoingTransition),
|
|
48
|
+
fuseIncomingToOutgoing(pTransition, pOutgoingTransition, pCounter),
|
|
42
49
|
),
|
|
43
50
|
);
|
|
44
51
|
} else {
|
|
@@ -52,6 +59,7 @@ function deSugarPseudoStates(
|
|
|
52
59
|
pMachine,
|
|
53
60
|
pPseudoStateNames,
|
|
54
61
|
pOutgoingTransitionMap,
|
|
62
|
+
pCounter,
|
|
55
63
|
) {
|
|
56
64
|
const lMachine = structuredClone(pMachine);
|
|
57
65
|
if (lMachine.transitions && pPseudoStateNames.length > 0) {
|
|
@@ -59,6 +67,7 @@ function deSugarPseudoStates(
|
|
|
59
67
|
lMachine.transitions,
|
|
60
68
|
pPseudoStateNames,
|
|
61
69
|
pOutgoingTransitionMap,
|
|
70
|
+
pCounter,
|
|
62
71
|
);
|
|
63
72
|
}
|
|
64
73
|
lMachine.states = lMachine.states.map((pState) =>
|
|
@@ -69,6 +78,7 @@ function deSugarPseudoStates(
|
|
|
69
78
|
pState.statemachine,
|
|
70
79
|
pPseudoStateNames,
|
|
71
80
|
pOutgoingTransitionMap,
|
|
81
|
+
pCounter,
|
|
72
82
|
),
|
|
73
83
|
}
|
|
74
84
|
: pState,
|
|
@@ -117,10 +127,12 @@ export default (
|
|
|
117
127
|
},
|
|
118
128
|
{},
|
|
119
129
|
);
|
|
130
|
+
const lMaximumTransitionId = lModel.getMaximumTransitionId();
|
|
120
131
|
const lMachine = deSugarPseudoStates(
|
|
121
132
|
pMachine,
|
|
122
133
|
lPseudoStateNames,
|
|
123
134
|
lOutgoingTransitionMap,
|
|
135
|
+
new Counter(lMaximumTransitionId),
|
|
124
136
|
);
|
|
125
137
|
return removeStatesCascading(lMachine, lPseudoStateNames);
|
|
126
138
|
};
|
package/dist/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "12.0.
|
|
1
|
+
export const version = "12.0.20";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "state-machine-cat",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.20",
|
|
4
4
|
"description": "write beautiful state charts",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -44,8 +44,7 @@
|
|
|
44
44
|
"ajv": "8.17.1",
|
|
45
45
|
"fast-xml-parser": "4.5.1",
|
|
46
46
|
"he": "1.2.0",
|
|
47
|
-
"
|
|
48
|
-
"traverse": "0.6.8"
|
|
47
|
+
"neotraverse": "0.6.18"
|
|
49
48
|
},
|
|
50
49
|
"engines": {
|
|
51
50
|
"node": "^18.17||>=20"
|
|
@@ -83,6 +83,10 @@ export interface IState {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
export interface ITransition {
|
|
86
|
+
/**
|
|
87
|
+
* The id of the transition. Unique within the root state machine.
|
|
88
|
+
*/
|
|
89
|
+
id: number;
|
|
86
90
|
/**
|
|
87
91
|
* The name of the IState the transition is from
|
|
88
92
|
*/
|
|
@@ -91,10 +95,6 @@ export interface ITransition {
|
|
|
91
95
|
* The name of the IState the transition is to
|
|
92
96
|
*/
|
|
93
97
|
to: string;
|
|
94
|
-
/**
|
|
95
|
-
* The id of the transition. Unique within the root state machine.
|
|
96
|
-
*/
|
|
97
|
-
id: number;
|
|
98
98
|
/**
|
|
99
99
|
* A display label to represent this transition. Parsers can parse this
|
|
100
100
|
* label into events conditions and actions.
|