state-machine-cat 12.0.17 → 12.0.18

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/dist/index.mjs CHANGED
@@ -4,11 +4,12 @@ import desugar from "./transform/desugar.mjs";
4
4
  import getRenderFunction from "./render/index.mjs";
5
5
  import { version as _version } from "./version.mjs";
6
6
  export function render(pScript, pOptions) {
7
- const lStateMachine = parse.getAST(pScript, pOptions);
8
- const lDesugar = options.getOptionValue(pOptions, "desugar");
9
- return getRenderFunction(options.getOptionValue(pOptions, "outputType"))(
7
+ const lOptions = pOptions ?? {};
8
+ const lStateMachine = parse.getAST(pScript, lOptions);
9
+ const lDesugar = options.getOptionValue(lOptions, "desugar");
10
+ return getRenderFunction(options.getOptionValue(lOptions, "outputType"))(
10
11
  lDesugar ? desugar(lStateMachine) : lStateMachine,
11
- pOptions,
12
+ lOptions,
12
13
  );
13
14
  }
14
15
  export const version = _version;
package/dist/options.mjs CHANGED
@@ -8,7 +8,6 @@ const ALLOWED_VALUES = Object.freeze({
8
8
  values: [
9
9
  { name: "ast" },
10
10
  { name: "dot" },
11
- { name: "ndot" },
12
11
  { name: "eps" },
13
12
  { name: "json" },
14
13
  { name: "oldeps" },
@@ -36,19 +36,25 @@ const EDGE_ATTRIBUTES = [
36
36
  function toNameValueString(pAttribute) {
37
37
  return `${pAttribute.name}=${pAttribute.value}`;
38
38
  }
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(" ");
45
+ }
46
+ export function buildNodeAttributes(pDotNodeAttributes) {
47
+ return NODE_ATTRIBUTES.concat(pDotNodeAttributes || [])
48
+ .map(toNameValueString)
49
+ .join(" ");
50
+ }
51
+ export function buildEdgeAttributes(pDotEdgeAttributes) {
52
+ return EDGE_ATTRIBUTES.concat(pDotEdgeAttributes || [])
53
+ .map(toNameValueString)
54
+ .join(" ");
55
+ }
39
56
  export default {
40
- buildGraphAttributes: (pEngine, pDirection, pDotGraphAttributes) =>
41
- GENERIC_GRAPH_ATTRIBUTES.concat(GRAPH_ATTRIBUTES[pEngine] || [])
42
- .concat(DIRECTION_ATTRIBUTES[pDirection] || [])
43
- .concat(pDotGraphAttributes || [])
44
- .map(toNameValueString)
45
- .join(" "),
46
- buildNodeAttributes: (pDotNodeAttributes) =>
47
- NODE_ATTRIBUTES.concat(pDotNodeAttributes || [])
48
- .map(toNameValueString)
49
- .join(" "),
50
- buildEdgeAttributes: (pDotEdgeAttributes) =>
51
- EDGE_ATTRIBUTES.concat(pDotEdgeAttributes || [])
52
- .map(toNameValueString)
53
- .join(" "),
57
+ buildGraphAttributes,
58
+ buildNodeAttributes,
59
+ buildEdgeAttributes,
54
60
  };
@@ -1,150 +1,251 @@
1
- import options from "../../options.mjs";
1
+ import he from "he";
2
+ import { getOptionValue } from "../../options.mjs";
2
3
  import StateMachineModel from "../../state-machine-model.mjs";
3
- import attributebuilder from "./attributebuilder.mjs";
4
- import stateTransformers from "./state-transformers.mjs";
5
- import transitionTransformers from "./transition-transformers.mjs";
6
- import renderDotFromAST from "./render-dot-from-ast.mjs";
7
- import utl from "./utl.mjs";
8
- function addExternalSelfTransitions(pStateMachineModel) {
9
- return (pState) => {
10
- if (Object.hasOwn(pState, "statemachine")) {
11
- pState.nestedExternalSelfTransitions = pStateMachineModel
12
- .findExternalSelfTransitions(pState.name)
13
- .map((pTransition) => pTransition.name);
14
- }
15
- return pState;
16
- };
17
- }
18
- function transformStates(
19
- pStates,
20
- pDirection,
21
- pNodeAttributes,
22
- pStateMachineModel,
23
- ) {
24
- pStates
25
- .filter((pState) => pState.statemachine)
26
- .forEach((pState) => {
27
- pState.statemachine.states = transformStates(
28
- pState.statemachine.states,
29
- pDirection,
30
- pNodeAttributes,
31
- pStateMachineModel,
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=1 style=rounded" : "";
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}" label= <${lLabelTag}
61
+ ${pIndent} >${pState.colorAttribute}${pState.fontColorAttribute}${lActiveAttribute}]${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}" label= <
84
+ ${lLabelTag}
85
+ ${pIndent} > style=${lStyle} penwidth=${lPenWidth}${pState.colorAttribute}${pState.fontColorAttribute}
86
+ ${pIndent} "${pState.name}" [shape=point style=invis margin=0 width=0 height=0 fixedsize=true]
87
+ ${states(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}" label="H"${pState.colorAttribute}${pState.fontColorAttribute}${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}" label="H*"${pState.colorAttribute}${pState.fontColorAttribute}${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}`,
32
109
  );
33
- });
34
- return pStates
35
- .map(stateTransformers.setLabel)
36
- .map(stateTransformers.nameNote)
37
- .map(stateTransformers.classifyState)
38
- .map(stateTransformers.escapeStateStrings)
39
- .map(stateTransformers.flattenNote)
40
- .map(stateTransformers.flattenActions)
41
- .map(stateTransformers.flagParallelChildren)
42
- .map(stateTransformers.tipForkJoinStates(pDirection))
43
- .map(stateTransformers.recolor(pNodeAttributes))
44
- .map(addExternalSelfTransitions(pStateMachineModel));
45
- }
46
- function splitStates(pStateMachine) {
47
- pStateMachine.initialStates = pStateMachine.states.filter(
48
- stateTransformers.isType("initial"),
49
- );
50
- pStateMachine.regularStates = pStateMachine.states.filter(
51
- (pState) =>
52
- stateTransformers.isType("regular")(pState) && !pState.statemachine,
53
- );
54
- pStateMachine.historyStates = pStateMachine.states.filter(
55
- stateTransformers.isType("history"),
56
- );
57
- pStateMachine.deepHistoryStates = pStateMachine.states.filter(
58
- stateTransformers.isType("deephistory"),
59
- );
60
- pStateMachine.choiceStates = pStateMachine.states.filter(
61
- stateTransformers.isType("choice"),
62
- );
63
- pStateMachine.forkjoinStates = pStateMachine.states.filter(
64
- stateTransformers.isOneOfTypes(["fork", "join", "forkjoin"]),
65
- );
66
- pStateMachine.junctionStates = pStateMachine.states.filter(
67
- stateTransformers.isType("junction"),
68
- );
69
- pStateMachine.terminateStates = pStateMachine.states.filter(
70
- stateTransformers.isType("terminate"),
71
- );
72
- pStateMachine.finalStates = pStateMachine.states.filter(
73
- stateTransformers.isType("final"),
74
- );
75
- pStateMachine.compositeStates = pStateMachine.states.filter(
76
- (pState) => pState.statemachine,
77
- );
78
- return pStateMachine;
79
- }
80
- function addEndTypes(pStateMachineModel) {
81
- return (pTransition) => {
82
- if (pStateMachineModel.findStateByName(pTransition.from).statemachine) {
83
- pTransition.fromComposite = true;
84
- }
85
- if (pStateMachineModel.findStateByName(pTransition.to).statemachine) {
86
- pTransition.toComposite = true;
87
- }
88
- return pTransition;
89
- };
90
- }
91
- function addCompositeSelfFlag(pStateMachineModel) {
92
- return (pTransition) => {
93
- let lAdditionalAttributes = {};
94
- if (utl.isCompositeSelf(pStateMachineModel, pTransition)) {
95
- if (pStateMachineModel.findStateByName(pTransition.from).hasParent) {
96
- lAdditionalAttributes = { hasParent: true, isCompositeSelf: true };
97
- } else {
98
- lAdditionalAttributes = { isCompositeSelf: true };
110
+ if (pActive) {
111
+ lReturnValue = `<i>${lReturnValue}</i>`;
99
112
  }
100
- }
101
- return { ...pTransition, ...lAdditionalAttributes };
102
- };
103
- }
104
- function nameTransition() {
105
- return (pTransition) => {
106
- pTransition.name = `tr_${pTransition.from}_${pTransition.to}_${pTransition.id}`;
107
- if (pTransition.note) {
108
- pTransition.noteName = `note_${pTransition.name}`;
109
- }
110
- return pTransition;
111
- };
112
- }
113
- function transformTransitions(pStateMachineModel, pDirection) {
114
- return pStateMachineModel.flattenedTransitions
115
- .map(nameTransition())
116
- .map(transitionTransformers.escapeTransitionStrings)
117
- .map(transitionTransformers.classifyTransition)
118
- .map(stateTransformers.flattenNote)
119
- .map(addEndTypes(pStateMachineModel))
120
- .map(addCompositeSelfFlag(pStateMachineModel))
121
- .map(transitionTransformers.addPorts(pDirection));
122
- }
123
- export default (pStateMachine, pOptions) => {
124
- pOptions = pOptions || {};
125
- let lStateMachine = structuredClone(pStateMachine);
126
- const lStateMachineModel = new StateMachineModel(lStateMachine);
127
- lStateMachine.transitions = transformTransitions(
128
- lStateMachineModel,
129
- pOptions.direction,
130
- );
131
- lStateMachine.states = transformStates(
132
- lStateMachine.states,
133
- pOptions.direction,
134
- pOptions.dotNodeAttrs,
135
- lStateMachineModel,
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,
136
122
  );
137
- lStateMachine = splitStates(lStateMachine);
138
- lStateMachine.graphAttributes = attributebuilder.buildGraphAttributes(
139
- options.getOptionValue(pOptions, "engine"),
140
- options.getOptionValue(pOptions, "direction"),
141
- pOptions.dotGraphAttrs,
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}"${pState.colorAttribute}${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, pOptions, pIndent);
167
+ return (
168
+ (STATE_TYPE2FUNCTION.get(pState.type) ?? regular)(
169
+ lState,
170
+ pIndent,
171
+ pOptions,
172
+ pModel,
173
+ ) + "\n"
142
174
  );
143
- lStateMachine.nodeAttributes = attributebuilder.buildNodeAttributes(
144
- pOptions.dotNodeAttrs,
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 lColorAttribute = pTransition.color
184
+ ? ` color="${pTransition.color}"`
185
+ : "";
186
+ const lFontColorAttribute = pTransition.color
187
+ ? ` fontcolor="${pTransition.color}"`
188
+ : "";
189
+ const lPenWidth = pTransition.width ? ` penwidth=${pTransition.width}` : "";
190
+ const lClass = pTransition.class
191
+ ? `transition${pTransition.type ? " " + pTransition.type + " " : " "}${pTransition.class}`
192
+ : `transition${pTransition.type ? " " + pTransition.type : ""}`;
193
+ const lTail = pModel.findStateByName(pTransition.from)?.statemachine
194
+ ? ` ltail="cluster_${pTransition.from}"`
195
+ : "";
196
+ const lHead = pModel.findStateByName(pTransition.to)?.statemachine
197
+ ? ` lhead="cluster_${pTransition.to}"`
198
+ : "";
199
+ 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
+ if (isCompositeSelf(pModel, pTransition)) {
211
+ const { lTailPorts, lHeadPorts } = getTransitionPorts(
212
+ pOptions,
213
+ pModel,
214
+ pTransition,
215
+ );
216
+ const lTransitionFrom = `\n${pIndent} "${pTransition.from}" -> "self_tr_${pTransition.from}_${pTransition.to}_${pTransition.id}" [label="${lLabel}" arrowhead=none class="${lClass}"${lTailPorts}${lTail}${lColorAttribute}${lFontColorAttribute}]`;
217
+ const lTransitionTo = `\n${pIndent} "self_tr_${pTransition.from}_${pTransition.to}_${pTransition.id}" -> "${pTransition.to}" [class="${lClass}"${lHead}${lHeadPorts}${lColorAttribute}${lPenWidth}]`;
218
+ return lTransitionFrom + lTransitionTo;
219
+ }
220
+ return `\n${pIndent} "${pTransition.from}" -> "${pTransition.to}" [label="${lLabel}" class="${lClass}"${lTail}${lHead}${lColorAttribute}${lFontColorAttribute}${lPenWidth}]`;
221
+ }
222
+ function transitions(pTransitions, pIndent, pOptions, pModel) {
223
+ return pTransitions
224
+ .map((pTransition) => transition(pTransition, pIndent, pOptions, pModel))
225
+ .join("");
226
+ }
227
+ export default function renderDot(pStateMachine, pOptions = {}, pIndent = "") {
228
+ const lGraphAttributes = buildGraphAttributes(
229
+ getOptionValue(pOptions, "engine"),
230
+ getOptionValue(pOptions, "direction"),
231
+ pOptions?.dotGraphAttrs || [],
145
232
  );
146
- lStateMachine.edgeAttributes = attributebuilder.buildEdgeAttributes(
147
- pOptions.dotEdgeAttrs,
233
+ const lNodeAttributes = buildNodeAttributes(pOptions.dotNodeAttrs || []);
234
+ const lEdgeAttributes = buildEdgeAttributes(pOptions.dotEdgeAttrs || []);
235
+ const lModel = new StateMachineModel(pStateMachine);
236
+ const lStates = states(pStateMachine.states, pIndent, pOptions, lModel);
237
+ const lTransitions = transitions(
238
+ lModel.flattenedTransitions,
239
+ pIndent,
240
+ pOptions,
241
+ lModel,
148
242
  );
149
- return renderDotFromAST(lStateMachine);
150
- };
243
+ return `digraph "state transitions" {
244
+ ${lGraphAttributes}
245
+ node [${lNodeAttributes}]
246
+ edge [${lEdgeAttributes}]
247
+
248
+ ${lStates}${lTransitions}
249
+ }
250
+ `;
251
+ }
@@ -1,31 +1,102 @@
1
- function escapeString(pString) {
1
+ import he from "he";
2
+ import { getOptionValue } from "../../options.mjs";
3
+ function getStateColor(pState, pNodeAttributes) {
4
+ const lNodeColor = (pNodeAttributes || []).find(
5
+ (pAttribute) => pAttribute.name === "color",
6
+ )?.value;
7
+ if (
8
+ lNodeColor &&
9
+ !pState.color &&
10
+ [
11
+ "initial",
12
+ "fork",
13
+ "join",
14
+ "junction",
15
+ "forkjoin",
16
+ "terminate",
17
+ "final",
18
+ ].includes(pState.type)
19
+ ) {
20
+ return lNodeColor;
21
+ }
22
+ return pState.color ?? "black";
23
+ }
24
+ export function escapeString(pString) {
2
25
  return pString
3
26
  .replace(/\\/g, "\\\\")
4
27
  .replace(/\n\s*/g, "\\l")
5
28
  .replace(/"/g, '\\"')
6
29
  .concat("\\l");
7
30
  }
8
- function escapeLabelString(pString) {
31
+ export function escapeLabelString(pString) {
9
32
  return pString
10
33
  .replace(/\\/g, "\\\\")
11
34
  .replace(/\n\s*/g, " \\l")
12
35
  .replace(/"/g, '\\"')
13
36
  .concat(" \\l");
14
37
  }
15
- function isVertical(pDirection) {
38
+ export function isVertical(pDirection) {
16
39
  const lDirection = pDirection || "top-down";
17
40
  return lDirection === "top-down" || lDirection === "bottom-top";
18
41
  }
19
- function isCompositeSelf(pStateMachineModel, pTransition) {
42
+ export function isCompositeSelf(pStateMachineModel, pTransition) {
20
43
  return (
21
44
  pTransition.from === pTransition.to &&
22
45
  pStateMachineModel.findStateByName(pTransition.from).statemachine &&
23
46
  pTransition.type !== "internal"
24
47
  );
25
48
  }
26
- export default {
27
- escapeString,
28
- escapeLabelString,
29
- isVertical,
30
- isCompositeSelf,
31
- };
49
+ export function noteToLabel(pNote) {
50
+ return pNote.map(escapeString).join("");
51
+ }
52
+ export function stateNote(pState, pIndent) {
53
+ if (pState.note) {
54
+ const lNoteName = `note_${pState.name}`;
55
+ let lReturnValue = `\n${pIndent} "${lNoteName}" [color=black fontcolor=black label="${noteToLabel(pState.note)}" shape=note fontsize=10 fillcolor="#ffffcc" penwidth=1.0]`;
56
+ lReturnValue += `\n${pIndent} "${pState.name}" -> "${lNoteName}" [style=dashed arrowtail=none arrowhead=none]`;
57
+ return lReturnValue;
58
+ }
59
+ return "";
60
+ }
61
+ export function normalizeState(pState, pOptions, pIndent) {
62
+ const lReturnValue = structuredClone(pState);
63
+ lReturnValue.colorAttribute = pState.color ? ` color="${pState.color}"` : "";
64
+ lReturnValue.fontColorAttribute = pState.color
65
+ ? ` fontcolor="${pState.color}"`
66
+ : "";
67
+ lReturnValue.color = getStateColor(pState, pOptions.dotNodeAttrs);
68
+ lReturnValue.class = pState.class
69
+ ? `state ${pState.type} ${pState.class}`
70
+ : `state ${pState.type}`;
71
+ lReturnValue.label = he.escape(pState.label ?? pState.name);
72
+ lReturnValue.noteText = stateNote(pState, pIndent);
73
+ if (
74
+ !pState.isParallelArea &&
75
+ pState.type === "parallel" &&
76
+ (pState.statemachine?.states ?? []).length > 0
77
+ ) {
78
+ lReturnValue.statemachine.states = pState.statemachine.states.map(
79
+ (pChildState) => ({
80
+ ...pChildState,
81
+ isParallelArea: pChildState.type === "regular",
82
+ }),
83
+ );
84
+ }
85
+ return lReturnValue;
86
+ }
87
+ export function formatActionType(pString) {
88
+ return pString === "activity" ? "" : `${pString}/ `;
89
+ }
90
+ export function getTransitionPorts(pOptions, pModel, pTransition) {
91
+ let lTailPorts = ' tailport="n" headport="n"';
92
+ let lHeadPorts = ' tailport="n"';
93
+ const lDirection = getOptionValue(pOptions, "direction");
94
+ if (isVertical(lDirection)) {
95
+ lTailPorts = ' tailport="e" headport="e"';
96
+ lHeadPorts = ' tailport="w"';
97
+ } else if (pModel.findStateByName(pTransition.from).hasParent) {
98
+ lTailPorts = ' tailport="n" headport="n"';
99
+ lHeadPorts = ' tailport="s"';
100
+ }
101
+ return { lTailPorts, lHeadPorts };
102
+ }
@@ -1,6 +1,5 @@
1
1
  import smcatRendererAsImported from "./smcat.mjs";
2
2
  import renderDot from "./dot/index.mjs";
3
- import renderNDot from "./ndot/index.mjs";
4
3
  import vector from "./vector/vector-native-dot-with-fallback.mjs";
5
4
  import oldVector from "./vector/vector-with-wasm.mjs";
6
5
  import scjson from "./scjson/index.mjs";
@@ -10,8 +9,8 @@ export default function getRenderFunction(pOutputType) {
10
9
  const lOutputType2RenderFunctionMap = new Map([
11
10
  ["smcat", smcat],
12
11
  ["dot", renderDot],
13
- ["ndot", renderNDot],
14
12
  ["svg", vector],
13
+ ["dot", renderDot],
15
14
  ["eps", vector],
16
15
  ["ps", vector],
17
16
  ["ps2", vector],
package/dist/version.mjs CHANGED
@@ -1 +1 @@
1
- export const version = "12.0.17";
1
+ export const version = "12.0.18";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "state-machine-cat",
3
- "version": "12.0.17",
3
+ "version": "12.0.18",
4
4
  "description": "write beautiful state charts",
5
5
  "main": "./dist/index.mjs",
6
6
  "module": "./dist/index.mjs",
@@ -16,10 +16,6 @@
16
16
  "imports": {
17
17
  "#*": "./src/*"
18
18
  },
19
- "sideEffects": [
20
- "dist/render/dot/dot.states.template.cjs",
21
- "dist/render/dot/dot.template.cjs"
22
- ],
23
19
  "files": [
24
20
  "dist/",
25
21
  "types/",
@@ -47,7 +43,6 @@
47
43
  "@hpcc-js/wasm-graphviz": "1.7.0",
48
44
  "ajv": "8.17.1",
49
45
  "fast-xml-parser": "4.5.1",
50
- "handlebars": "4.7.8",
51
46
  "he": "1.2.0",
52
47
  "semver": "^7.6.2",
53
48
  "traverse": "0.6.8"