state-machine-cat 12.0.17 → 12.0.19
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/index.mjs +5 -4
- package/dist/options.mjs +0 -1
- package/dist/parse/scxml/index.mjs +1 -1
- package/dist/render/dot/attributebuilder.mjs +20 -14
- package/dist/render/dot/index.mjs +263 -142
- package/dist/render/dot/utl.mjs +83 -11
- package/dist/render/index-node.mjs +1 -2
- package/dist/state-machine-model.mjs +19 -12
- package/dist/version.mjs +1 -1
- package/package.json +2 -8
- package/dist/render/dot/dot.states.template.cjs +0 -1
- package/dist/render/dot/dot.template.cjs +0 -1
- package/dist/render/dot/render-dot-from-ast.mjs +0 -44
- package/dist/render/dot/state-transformers.mjs +0 -119
- package/dist/render/dot/transition-transformers.mjs +0 -45
- package/dist/render/ndot/attributebuilder.mjs +0 -60
- package/dist/render/ndot/index.mjs +0 -243
- package/dist/render/ndot/utl.mjs +0 -77
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import he from "he";
|
|
2
|
-
import { getOptionValue } from "../../options.mjs";
|
|
3
|
-
import StateMachineModel from "../../state-machine-model.mjs";
|
|
4
|
-
import {
|
|
5
|
-
buildGraphAttributes,
|
|
6
|
-
buildNodeAttributes,
|
|
7
|
-
buildEdgeAttributes,
|
|
8
|
-
} from "./attributebuilder.mjs";
|
|
9
|
-
import {
|
|
10
|
-
escapeLabelString,
|
|
11
|
-
formatActionType,
|
|
12
|
-
getTransitionPorts,
|
|
13
|
-
isCompositeSelf,
|
|
14
|
-
isVertical,
|
|
15
|
-
noteToLabel,
|
|
16
|
-
normalizeState,
|
|
17
|
-
stateNote,
|
|
18
|
-
} from "./utl.mjs";
|
|
19
|
-
function initial(pState, pIndent) {
|
|
20
|
-
const lActiveAttribute = pState.active ? " penwidth=3.0" : "";
|
|
21
|
-
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}`;
|
|
22
|
-
}
|
|
23
|
-
function regularStateActions(pActions, pIndent) {
|
|
24
|
-
return pActions
|
|
25
|
-
.map((pAction) =>
|
|
26
|
-
he.escape(`${formatActionType(pAction.type)}${pAction.body}`),
|
|
27
|
-
)
|
|
28
|
-
.map((pActionString, pIndex) => {
|
|
29
|
-
let lReturnValue = `<tr><td align="left" cellpadding="2">${pActionString}</td></tr>`;
|
|
30
|
-
if (pIndex === 0) {
|
|
31
|
-
lReturnValue = `<hr/>${lReturnValue}`;
|
|
32
|
-
}
|
|
33
|
-
return `\n${pIndent} ${lReturnValue}`;
|
|
34
|
-
})
|
|
35
|
-
.join("");
|
|
36
|
-
}
|
|
37
|
-
function compositeStateActions(pActions, pIndent) {
|
|
38
|
-
return pActions
|
|
39
|
-
.map((pAction) =>
|
|
40
|
-
he.escape(`${formatActionType(pAction.type)}${pAction.body}`),
|
|
41
|
-
)
|
|
42
|
-
.map((pActionString, pIndex) => {
|
|
43
|
-
let lReturnValue = `<tr><td align="left">${pActionString}</td></tr>`;
|
|
44
|
-
if (pIndex === 0) {
|
|
45
|
-
lReturnValue = `<hr/>${lReturnValue}`;
|
|
46
|
-
}
|
|
47
|
-
return `\n${pIndent} ${lReturnValue}`;
|
|
48
|
-
})
|
|
49
|
-
.join("");
|
|
50
|
-
}
|
|
51
|
-
function atomicRegular(pState, pIndent) {
|
|
52
|
-
const lActiveAttribute = pState.active ? " peripheries=2 penwidth=3.0" : "";
|
|
53
|
-
const lCellPadding = (pState.actions?.length ?? 0) > 0 ? 2 : 7;
|
|
54
|
-
const lActions = regularStateActions(pState?.actions ?? [], pIndent);
|
|
55
|
-
const lLabel = pState.active ? `<i>${pState.label}</i>` : pState.label;
|
|
56
|
-
const lLabelTag = `
|
|
57
|
-
${pIndent} <table align="center" cellborder="0" border="2" style="rounded" width="48">
|
|
58
|
-
${pIndent} <tr><td width="48" cellpadding="${lCellPadding}">${lLabel}</td></tr>${lActions}
|
|
59
|
-
${pIndent} </table>`;
|
|
60
|
-
return `${pIndent} "${pState.name}" [margin=0 class="${pState.class}" color="${pState.color}"${lActiveAttribute} label= <${lLabelTag}
|
|
61
|
-
${pIndent} >]${pState.noteText}`;
|
|
62
|
-
}
|
|
63
|
-
function compositeRegular(pState, pIndent, pOptions, pModel) {
|
|
64
|
-
const lPenWidth = pState.isParallelArea
|
|
65
|
-
? "1.0"
|
|
66
|
-
: pState.active
|
|
67
|
-
? "3.0"
|
|
68
|
-
: "2.0";
|
|
69
|
-
const lStyle = pState.isParallelArea ? "dashed" : "rounded";
|
|
70
|
-
const lActions = compositeStateActions(pState?.actions ?? [], pIndent);
|
|
71
|
-
const lLabel = pState.active ? `<i>${pState.label}</i>` : pState.label;
|
|
72
|
-
const lLabelTag = `${pIndent} <table cellborder="0" border="0">
|
|
73
|
-
${pIndent} <tr><td>${lLabel}</td></tr>${lActions}
|
|
74
|
-
${pIndent} </table>`;
|
|
75
|
-
const lSelfTransitionHelperPoints = pModel
|
|
76
|
-
.findExternalSelfTransitions(pState.name)
|
|
77
|
-
.map(
|
|
78
|
-
(pTransition) =>
|
|
79
|
-
`${pIndent} "self_tr_${pTransition.from}_${pTransition.to}_${pTransition.id}" [shape=point style=invis width=0 height=0 fixedsize=true]\n`,
|
|
80
|
-
)
|
|
81
|
-
.join("");
|
|
82
|
-
return `${lSelfTransitionHelperPoints}${pIndent} subgraph "cluster_${pState.name}" {
|
|
83
|
-
${pIndent} class="${pState.class}" color="${pState.color}" label= <
|
|
84
|
-
${lLabelTag}
|
|
85
|
-
${pIndent} > style=${lStyle} penwidth=${lPenWidth}
|
|
86
|
-
${pIndent} "${pState.name}" [shape=point style=invis margin=0 width=0 height=0 fixedsize=true]
|
|
87
|
-
${machine(pState.statemachine ?? { states: [] }, `${pIndent} `, pOptions, pModel)}
|
|
88
|
-
${pIndent} }${pState.noteText}`;
|
|
89
|
-
}
|
|
90
|
-
function regular(pState, pIndent, pOptions, pModel) {
|
|
91
|
-
if (pState.statemachine) {
|
|
92
|
-
return compositeRegular(pState, pIndent, pOptions, pModel);
|
|
93
|
-
}
|
|
94
|
-
return atomicRegular(pState, pIndent);
|
|
95
|
-
}
|
|
96
|
-
function history(pState, pIndent) {
|
|
97
|
-
const lActiveAttribute = pState.active ? " peripheries=2 penwidth=3.0" : "";
|
|
98
|
-
return `${pIndent} "${pState.name}" [shape=circle class="${pState.class}" color="${pState.color}" label="H"${lActiveAttribute}]${pState.noteText}`;
|
|
99
|
-
}
|
|
100
|
-
function deepHistory(pState, pIndent) {
|
|
101
|
-
const lActiveAttribute = pState.active ? " peripheries=2 penwidth=3.0" : "";
|
|
102
|
-
return `${pIndent} "${pState.name}" [shape=circle class="${pState.class}" color="${pState.color}" label="H*"${lActiveAttribute}]${pState.noteText}`;
|
|
103
|
-
}
|
|
104
|
-
function choiceActions(pActions, pActive) {
|
|
105
|
-
return pActions
|
|
106
|
-
.map((pAction) => {
|
|
107
|
-
let lReturnValue = he.escape(
|
|
108
|
-
`${formatActionType(pAction.type)}${pAction.body}`,
|
|
109
|
-
);
|
|
110
|
-
if (pActive) {
|
|
111
|
-
lReturnValue = `<i>${lReturnValue}</i>`;
|
|
112
|
-
}
|
|
113
|
-
return lReturnValue;
|
|
114
|
-
})
|
|
115
|
-
.join("\\n");
|
|
116
|
-
}
|
|
117
|
-
function choice(pState, pIndent) {
|
|
118
|
-
const lActiveAttribute = pState.active ? "penwidth=3.0 " : "";
|
|
119
|
-
const lActions = choiceActions(
|
|
120
|
-
pState?.actions ?? [],
|
|
121
|
-
pState?.active ?? false,
|
|
122
|
-
);
|
|
123
|
-
const lLabelTag = lActions;
|
|
124
|
-
const lDiamond = `${pIndent} "${pState.name}" [shape=diamond fixedsize=true width=0.35 height=0.35 fontsize=10 label=" " class="${pState.class}" color="${pState.color}"${lActiveAttribute}]`;
|
|
125
|
-
const lLabelConstruct = `${pIndent} "${pState.name}" -> "${pState.name}" [color="#FFFFFF01" fontcolor="${pState.color}" class="${pState.class}" label=<${lLabelTag}>]`;
|
|
126
|
-
return `${lDiamond}\n${lLabelConstruct}${pState.noteText}`;
|
|
127
|
-
}
|
|
128
|
-
function forkjoin(pState, pIndent, pOptions) {
|
|
129
|
-
const lActiveAttribute = pState.active ? "penwidth=3.0 " : "";
|
|
130
|
-
const lDirection = getOptionValue(pOptions, "direction");
|
|
131
|
-
const lSizingExtras = isVertical(lDirection) ? " height=0.1" : " width=0.1";
|
|
132
|
-
return `${pIndent} "${pState.name}" [shape=rect fixedsize=true label=" " style=filled class="${pState.class}" color="${pState.color}" fillcolor="${pState.color}"${lActiveAttribute}${lSizingExtras}]${pState.noteText}`;
|
|
133
|
-
}
|
|
134
|
-
function junction(pState, pIndent) {
|
|
135
|
-
const lActiveAttribute = pState.active ? " penwidth=3.0" : "";
|
|
136
|
-
const lNote = stateNote(pState, pIndent);
|
|
137
|
-
return `${pIndent} "${pState.name}" [shape=circle fixedsize=true height=0.15 label="" style=filled class="${pState.class}" color="${pState.color}" fillcolor="${pState.color}"${lActiveAttribute}]${lNote}`;
|
|
138
|
-
}
|
|
139
|
-
function terminate(pState, pIndent) {
|
|
140
|
-
const lLabelTag = `
|
|
141
|
-
${pIndent} <table align="center" cellborder="0" border="0">
|
|
142
|
-
${pIndent} <tr><td cellpadding="0"><font color="${pState.color}" point-size="20">X</font></td></tr>
|
|
143
|
-
${pIndent} <tr><td cellpadding="0"><font color="${pState.color}">${pState.label}</font></td></tr>
|
|
144
|
-
${pIndent} </table>`;
|
|
145
|
-
return `${pIndent} "${pState.name}" [label= <${lLabelTag}
|
|
146
|
-
${pIndent} > class="${pState.class}"]${pState.noteText}`;
|
|
147
|
-
}
|
|
148
|
-
function final(pState, pIndent) {
|
|
149
|
-
const lActiveAttribute = pState.active ? " peripheries=2 penwidth=3.0" : "";
|
|
150
|
-
return `${pIndent} "${pState.name}" [shape=circle style=filled class="${pState.class}" color="${pState.color}" fillcolor="${pState.color}" fixedsize=true height=0.15 peripheries=2 label=""${lActiveAttribute}]${pState.noteText}`;
|
|
151
|
-
}
|
|
152
|
-
const STATE_TYPE2FUNCTION = new Map([
|
|
153
|
-
["initial", initial],
|
|
154
|
-
["regular", regular],
|
|
155
|
-
["history", history],
|
|
156
|
-
["deephistory", deepHistory],
|
|
157
|
-
["choice", choice],
|
|
158
|
-
["fork", forkjoin],
|
|
159
|
-
["forkjoin", forkjoin],
|
|
160
|
-
["join", forkjoin],
|
|
161
|
-
["junction", junction],
|
|
162
|
-
["terminate", terminate],
|
|
163
|
-
["final", final],
|
|
164
|
-
]);
|
|
165
|
-
function state(pState, pIndent, pOptions, pModel) {
|
|
166
|
-
const lState = normalizeState(pState, pIndent);
|
|
167
|
-
return (
|
|
168
|
-
(STATE_TYPE2FUNCTION.get(pState.type) ?? regular)(
|
|
169
|
-
lState,
|
|
170
|
-
pIndent,
|
|
171
|
-
pOptions,
|
|
172
|
-
pModel,
|
|
173
|
-
) + "\n"
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
function states(pStates, pIndent, pOptions, pModel) {
|
|
177
|
-
return pStates
|
|
178
|
-
.map((pState) => state(pState, pIndent, pOptions, pModel))
|
|
179
|
-
.join("");
|
|
180
|
-
}
|
|
181
|
-
function transition(pTransition, pIndent, pOptions, pModel) {
|
|
182
|
-
const lLabel = `${escapeLabelString(pTransition.label ?? " ")}`;
|
|
183
|
-
const lColor = pTransition.color ?? "black";
|
|
184
|
-
const lPenWidth = pTransition.width ? ` penwidth=${pTransition.width}` : "";
|
|
185
|
-
const lClass = pTransition.class
|
|
186
|
-
? `transition${pTransition.type ? " " + pTransition.type + " " : " "}${pTransition.class}`
|
|
187
|
-
: `transition${pTransition.type ? " " + pTransition.type : ""}`;
|
|
188
|
-
const lTail = pModel.findStateByName(pTransition.from)?.statemachine
|
|
189
|
-
? `ltail="cluster_${pTransition.from}" `
|
|
190
|
-
: "";
|
|
191
|
-
const lHead = pModel.findStateByName(pTransition.to)?.statemachine
|
|
192
|
-
? `lhead="cluster_${pTransition.to}" `
|
|
193
|
-
: "";
|
|
194
|
-
const lTransitionName = `tr_${pTransition.from}_${pTransition.to}_${pTransition.id}`;
|
|
195
|
-
if (pTransition.note) {
|
|
196
|
-
const lNoteName = `note_${lTransitionName}`;
|
|
197
|
-
const lNoteNodeName = `i_${lNoteName}`;
|
|
198
|
-
const lNoteNode = `\n${pIndent} "${lNoteNodeName}" [shape=point style=invis margin=0 width=0 height=0 fixedsize=true]`;
|
|
199
|
-
const lTransitionFrom = `\n${pIndent} "${pTransition.from}" -> "${lNoteNodeName}" [arrowhead=none ${lTail}color="${lColor}"]`;
|
|
200
|
-
const lTransitionTo = `\n${pIndent} "${lNoteNodeName}" -> "${pTransition.to}" [label="${lLabel}" ${lHead}color="${lColor}" fontcolor="${lColor}"]`;
|
|
201
|
-
const lLineToNote = `\n${pIndent} "${lNoteNodeName}" -> "${lNoteName}" [style=dashed arrowtail=none arrowhead=none weight=0]`;
|
|
202
|
-
const lNote = `\n${pIndent} "${lNoteName}" [label="${noteToLabel(pTransition.note)}" shape=note fontsize=10 color=black fontcolor=black fillcolor="#ffffcc" penwidth=1.0]`;
|
|
203
|
-
return lNoteNode + lTransitionFrom + lTransitionTo + lLineToNote + lNote;
|
|
204
|
-
}
|
|
205
|
-
if (isCompositeSelf(pModel, pTransition)) {
|
|
206
|
-
const { lTailPorts, lHeadPorts } = getTransitionPorts(
|
|
207
|
-
pOptions,
|
|
208
|
-
pModel,
|
|
209
|
-
pTransition,
|
|
210
|
-
);
|
|
211
|
-
const lTransitionFrom = `\n${pIndent} "${pTransition.from}" -> "self_tr_${pTransition.from}_${pTransition.to}_${pTransition.id}" [label="${lLabel}" arrowhead=none ${lTailPorts}${lTail}color="${lColor}" fontcolor="${lColor}" class="${lClass}"]`;
|
|
212
|
-
const lTransitionTo = `\n${pIndent} "self_tr_${pTransition.from}_${pTransition.to}_${pTransition.id}" -> "${pTransition.to}" [${lHead}${lHeadPorts}color="${lColor}" ${lPenWidth}class="${lClass}"]`;
|
|
213
|
-
return lTransitionFrom + lTransitionTo;
|
|
214
|
-
}
|
|
215
|
-
return `\n${pIndent} "${pTransition.from}" -> "${pTransition.to}" [label="${lLabel}" ${lTail}${lHead}color="${lColor}" fontcolor="${lColor}"${lPenWidth} class="${lClass}"]`;
|
|
216
|
-
}
|
|
217
|
-
function transitions(pTransitions, pIndent, pOptions, pModel) {
|
|
218
|
-
return pTransitions
|
|
219
|
-
.map((pTransition) => transition(pTransition, pIndent, pOptions, pModel))
|
|
220
|
-
.join("");
|
|
221
|
-
}
|
|
222
|
-
function machine(pStateMachine, pIndent, pOptions, pModel) {
|
|
223
|
-
return `${states(pStateMachine.states, pIndent, pOptions, pModel)}${transitions(pStateMachine.transitions || [], pIndent, pOptions, pModel)}`;
|
|
224
|
-
}
|
|
225
|
-
export default function renderDot(pStateMachine, pOptions = {}, pIndent = "") {
|
|
226
|
-
const lGraphAttributes = buildGraphAttributes(
|
|
227
|
-
getOptionValue(pOptions, "engine"),
|
|
228
|
-
getOptionValue(pOptions, "direction"),
|
|
229
|
-
pOptions?.dotGraphAttrs || [],
|
|
230
|
-
);
|
|
231
|
-
const lNodeAttributes = buildNodeAttributes(pOptions.dotNodeAttrs || []);
|
|
232
|
-
const lEdgeAttributes = buildEdgeAttributes(pOptions.dotNodeAttrs || []);
|
|
233
|
-
const lModel = new StateMachineModel(pStateMachine);
|
|
234
|
-
const lMachine = machine(pStateMachine, pIndent, pOptions, lModel);
|
|
235
|
-
return `digraph "state transitions" {
|
|
236
|
-
${lGraphAttributes}
|
|
237
|
-
node [${lNodeAttributes}]
|
|
238
|
-
edge [${lEdgeAttributes}]
|
|
239
|
-
|
|
240
|
-
${lMachine}
|
|
241
|
-
}
|
|
242
|
-
`;
|
|
243
|
-
}
|
package/dist/render/ndot/utl.mjs
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import he from "he";
|
|
2
|
-
import { getOptionValue } from "../../options.mjs";
|
|
3
|
-
export function escapeString(pString) {
|
|
4
|
-
return pString
|
|
5
|
-
.replace(/\\/g, "\\\\")
|
|
6
|
-
.replace(/\n\s*/g, "\\l")
|
|
7
|
-
.replace(/"/g, '\\"')
|
|
8
|
-
.concat("\\l");
|
|
9
|
-
}
|
|
10
|
-
export function escapeLabelString(pString) {
|
|
11
|
-
return pString
|
|
12
|
-
.replace(/\\/g, "\\\\")
|
|
13
|
-
.replace(/\n\s*/g, " \\l")
|
|
14
|
-
.replace(/"/g, '\\"')
|
|
15
|
-
.concat(" \\l");
|
|
16
|
-
}
|
|
17
|
-
export function isVertical(pDirection) {
|
|
18
|
-
const lDirection = pDirection || "top-down";
|
|
19
|
-
return lDirection === "top-down" || lDirection === "bottom-top";
|
|
20
|
-
}
|
|
21
|
-
export function isCompositeSelf(pStateMachineModel, pTransition) {
|
|
22
|
-
return (
|
|
23
|
-
pTransition.from === pTransition.to &&
|
|
24
|
-
pStateMachineModel.findStateByName(pTransition.from).statemachine &&
|
|
25
|
-
pTransition.type !== "internal"
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
export function noteToLabel(pNote) {
|
|
29
|
-
return pNote.map(escapeString).join("");
|
|
30
|
-
}
|
|
31
|
-
export function stateNote(pState, pIndent) {
|
|
32
|
-
if (pState.note) {
|
|
33
|
-
const lNoteName = `note_${pState.name}`;
|
|
34
|
-
let lReturnValue = `\n${pIndent} "${lNoteName}" [color=black fontcolor=black label="${noteToLabel(pState.note)}" shape=note fontsize=10 fillcolor="#ffffcc" penwidth=1.0]`;
|
|
35
|
-
lReturnValue += `\n${pIndent} "${pState.name}" -> "${lNoteName}" [style=dashed arrowtail=none arrowhead=none]`;
|
|
36
|
-
return lReturnValue;
|
|
37
|
-
}
|
|
38
|
-
return "";
|
|
39
|
-
}
|
|
40
|
-
export function normalizeState(pState, pIndent) {
|
|
41
|
-
const lReturnValue = structuredClone(pState);
|
|
42
|
-
lReturnValue.color = pState.color ?? "black";
|
|
43
|
-
lReturnValue.class = pState.class
|
|
44
|
-
? `state ${pState.type} ${pState.class}`
|
|
45
|
-
: `state ${pState.type}`;
|
|
46
|
-
lReturnValue.label = he.escape(pState.label ?? pState.name);
|
|
47
|
-
lReturnValue.noteText = stateNote(pState, pIndent);
|
|
48
|
-
if (
|
|
49
|
-
!pState.isParallelArea &&
|
|
50
|
-
pState.type === "parallel" &&
|
|
51
|
-
(pState.statemachine?.states ?? []).length > 0
|
|
52
|
-
) {
|
|
53
|
-
lReturnValue.statemachine.states = pState.statemachine.states.map(
|
|
54
|
-
(pChildState) => ({
|
|
55
|
-
...pChildState,
|
|
56
|
-
isParallelArea: pChildState.type === "regular",
|
|
57
|
-
}),
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
return lReturnValue;
|
|
61
|
-
}
|
|
62
|
-
export function formatActionType(pString) {
|
|
63
|
-
return pString === "activity" ? "" : `${pString}/ `;
|
|
64
|
-
}
|
|
65
|
-
export function getTransitionPorts(pOptions, pModel, pTransition) {
|
|
66
|
-
let lTailPorts = 'tailport="n" headport="n" ';
|
|
67
|
-
let lHeadPorts = 'tailport="n" ';
|
|
68
|
-
const lDirection = getOptionValue(pOptions, "direction");
|
|
69
|
-
if (isVertical(lDirection)) {
|
|
70
|
-
lTailPorts = 'tailport="e" headport="e" ';
|
|
71
|
-
lHeadPorts = 'tailport="w" ';
|
|
72
|
-
} else if (pModel.findStateByName(pTransition.from).hasParent) {
|
|
73
|
-
lTailPorts = 'tailport="n" headport="n" ';
|
|
74
|
-
lHeadPorts = 'tailport="s" ';
|
|
75
|
-
}
|
|
76
|
-
return { lTailPorts, lHeadPorts };
|
|
77
|
-
}
|