state-machine-cat 10.1.8 → 10.1.9

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.
@@ -36,16 +36,19 @@ peg$SyntaxError.prototype.format = function (sources) {
36
36
  }
37
37
  }
38
38
  var s = this.location.start;
39
- var loc = this.location.source + ":" + s.line + ":" + s.column;
39
+ var offset_s = (this.location.source && (typeof this.location.source.offset === "function"))
40
+ ? this.location.source.offset(s)
41
+ : s;
42
+ var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
40
43
  if (src) {
41
44
  var e = this.location.end;
42
- var filler = peg$padEnd("", s.line.toString().length, ' ');
45
+ var filler = peg$padEnd("", offset_s.line.toString().length, ' ');
43
46
  var line = src[s.line - 1];
44
47
  var last = s.line === e.line ? e.column : line.length + 1;
45
48
  var hatLen = (last - s.column) || 1;
46
49
  str += "\n --> " + loc + "\n"
47
50
  + filler + " |\n"
48
- + s.line + " | " + line + "\n"
51
+ + offset_s.line + " | " + line + "\n"
49
52
  + filler + " | " + peg$padEnd("", s.column - 1, ' ')
50
53
  + peg$padEnd("", hatLen, "^");
51
54
  }
@@ -270,10 +273,10 @@ function peg$parse(input, options) {
270
273
  return details;
271
274
  }
272
275
  }
273
- function peg$computeLocation(startPos, endPos) {
276
+ function peg$computeLocation(startPos, endPos, offset) {
274
277
  var startPosDetails = peg$computePosDetails(startPos);
275
278
  var endPosDetails = peg$computePosDetails(endPos);
276
- return {
279
+ var res = {
277
280
  source: peg$source,
278
281
  start: {
279
282
  offset: startPos,
@@ -286,6 +289,11 @@ function peg$parse(input, options) {
286
289
  column: endPosDetails.column
287
290
  }
288
291
  };
292
+ if (offset && peg$source && (typeof peg$source.offset === "function")) {
293
+ res.start = peg$source.offset(res.start);
294
+ res.end = peg$source.offset(res.end);
295
+ }
296
+ return res;
289
297
  }
290
298
  function peg$fail(expected) {
291
299
  if (peg$currPos < peg$maxFailPos) {
@@ -1,6 +1,7 @@
1
1
  import fastxml from "fast-xml-parser";
2
2
  import he from "he";
3
3
  import castArray from "lodash/castArray.js";
4
+ import traverse from "traverse";
4
5
  import utl from "../../transform/utl.mjs";
5
6
  import parserHelpers from "../parser-helpers.mjs";
6
7
  import { normalizeMachine } from "./normalize-machine.mjs";
@@ -118,19 +119,40 @@ function mapMachine(pSCXMLStateMachine) {
118
119
  }
119
120
  return lReturnValue;
120
121
  }
122
+ function deDuplicateAttributesAndTags(pObject, pAttributeNamePrefix) {
123
+ return traverse(pObject).map(function deDuplicate() {
124
+ if (this.key?.startsWith(pAttributeNamePrefix)) {
125
+ const pUnprefixedAttributeName = this.key.slice(pAttributeNamePrefix.length);
126
+ if (this.parent.keys.includes(pUnprefixedAttributeName)) {
127
+ this.remove();
128
+ }
129
+ else {
130
+ this.parent.node[pUnprefixedAttributeName] = this.node;
131
+ this.remove();
132
+ }
133
+ }
134
+ });
135
+ }
121
136
  export function parse(pSCXMLString) {
122
137
  const lTrimmedSCXMLString = pSCXMLString.trim();
123
- if (fastxml.validate(lTrimmedSCXMLString) === true) {
124
- const lXMLAsJSON = fastxml.parse(lTrimmedSCXMLString, {
125
- attributeNamePrefix: "",
126
- ignoreAttributes: false,
127
- tagValueProcessor: (pTagValue) => he.decode(pTagValue),
128
- stopNodes: ["onentry", "onexit", "transition"],
129
- });
130
- return mapMachine(lXMLAsJSON?.scxml ?? {
131
- xmlns: "http://www.w3.org/2005/07/scxml",
132
- version: "1.0",
133
- });
138
+ const lAttributeNamePrefix = "@_";
139
+ let lXMLAsJSON = {};
140
+ const lXMLParser = new fastxml.XMLParser({
141
+ attributeNamePrefix: lAttributeNamePrefix,
142
+ ignoreAttributes: false,
143
+ parseTagValue: true,
144
+ processEntities: false,
145
+ tagValueProcessor: (_pTagName, pTagValue) => he.decode(pTagValue),
146
+ stopNodes: ["*.onentry", "*.onexit", "*.transition"],
147
+ });
148
+ try {
149
+ lXMLAsJSON = deDuplicateAttributesAndTags(lXMLParser.parse(lTrimmedSCXMLString, true), lAttributeNamePrefix);
150
+ }
151
+ catch (pError) {
152
+ throw new Error("That doesn't look like valid xml ...\n");
134
153
  }
135
- throw new Error("That doesn't look like valid xml ...\n");
154
+ return mapMachine(lXMLAsJSON?.scxml ?? {
155
+ xmlns: "http://www.w3.org/2005/07/scxml",
156
+ version: "1.0",
157
+ });
136
158
  }
@@ -37,16 +37,19 @@ peg$SyntaxError.prototype.format = function (sources) {
37
37
  }
38
38
  }
39
39
  var s = this.location.start;
40
- var loc = this.location.source + ":" + s.line + ":" + s.column;
40
+ var offset_s = (this.location.source && (typeof this.location.source.offset === "function"))
41
+ ? this.location.source.offset(s)
42
+ : s;
43
+ var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
41
44
  if (src) {
42
45
  var e = this.location.end;
43
- var filler = peg$padEnd("", s.line.toString().length, ' ');
46
+ var filler = peg$padEnd("", offset_s.line.toString().length, ' ');
44
47
  var line = src[s.line - 1];
45
48
  var last = s.line === e.line ? e.column : line.length + 1;
46
49
  var hatLen = (last - s.column) || 1;
47
50
  str += "\n --> " + loc + "\n"
48
51
  + filler + " |\n"
49
- + s.line + " | " + line + "\n"
52
+ + offset_s.line + " | " + line + "\n"
50
53
  + filler + " | " + peg$padEnd("", s.column - 1, ' ')
51
54
  + peg$padEnd("", hatLen, "^");
52
55
  }
@@ -339,15 +342,15 @@ function peg$parse(input, options) {
339
342
  parserHelpers.setIfNotEmpty(trans, 'note', notes);
340
343
  return trans;
341
344
  };
342
- var peg$f20 = function (from, to) {
345
+ var peg$f20 = function (from_, to) {
343
346
  return {
344
- from: from,
347
+ from: from_,
345
348
  to: to
346
349
  };
347
350
  };
348
- var peg$f21 = function (to, from) {
351
+ var peg$f21 = function (to, from_) {
349
352
  return {
350
- from: from,
353
+ from: from_,
351
354
  to: to
352
355
  };
353
356
  };
@@ -481,10 +484,10 @@ function peg$parse(input, options) {
481
484
  return details;
482
485
  }
483
486
  }
484
- function peg$computeLocation(startPos, endPos) {
487
+ function peg$computeLocation(startPos, endPos, offset) {
485
488
  var startPosDetails = peg$computePosDetails(startPos);
486
489
  var endPosDetails = peg$computePosDetails(endPos);
487
- return {
490
+ var res = {
488
491
  source: peg$source,
489
492
  start: {
490
493
  offset: startPos,
@@ -497,6 +500,11 @@ function peg$parse(input, options) {
497
500
  column: endPosDetails.column
498
501
  }
499
502
  };
503
+ if (offset && peg$source && (typeof peg$source.offset === "function")) {
504
+ res.start = peg$source.offset(res.start);
505
+ res.end = peg$source.offset(res.end);
506
+ }
507
+ return res;
500
508
  }
501
509
  function peg$fail(expected) {
502
510
  if (peg$currPos < peg$maxFailPos) {
@@ -1 +1 @@
1
- export const version = "10.1.6";
1
+ export const version = "10.1.9";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "state-machine-cat",
3
- "version": "10.1.8",
3
+ "version": "10.1.9",
4
4
  "description": "write beautiful state charts",
5
5
  "main": "./dist/commonjs/index.js",
6
6
  "module": "./dist/esm/index.mjs",
@@ -23,6 +23,7 @@
23
23
  "scripts": {
24
24
  "build": "make clean dist pages",
25
25
  "build:cli": "make cli-build && rm -rf dist/esm && tsc",
26
+ "build:fromscratch": "make clean dist pages cli-build && rm -rf dist/esm && tsc",
26
27
  "check": "wireit",
27
28
  "cachefolder": "wireit",
28
29
  "depcruise": "wireit",
@@ -70,7 +71,7 @@
70
71
  "upem-outdated": "npm outdated --json --long | upem --dry-run",
71
72
  "upem:install": "npm install",
72
73
  "upem:update": "npm outdated --json --long | upem | pbcopy && pbpaste",
73
- "version": "run-s build depcruise:graph scm:stage"
74
+ "version": "run-s build:fromscratch depcruise:graph scm:stage"
74
75
  },
75
76
  "files": [
76
77
  "bin/",
@@ -85,11 +86,6 @@
85
86
  ],
86
87
  "upem": {
87
88
  "policies": [
88
- {
89
- "package": "fast-xml-parser",
90
- "policy": "wanted",
91
- "because": "fast-xml-parser 4 has some breaking changes we still need to grok (why? how?)"
92
- },
93
89
  {
94
90
  "package": "viz.js",
95
91
  "policy": "pin",
@@ -375,13 +371,14 @@
375
371
  "ajv": "8.12.0",
376
372
  "chalk": "5.2.0",
377
373
  "commander": "10.0.0",
378
- "fast-xml-parser": "3.21.1",
374
+ "fast-xml-parser": "4.1.2",
379
375
  "get-stream": "6.0.1",
380
376
  "handlebars": "4.7.7",
381
377
  "he": "1.2.0",
382
378
  "indent-string": "5.0.0",
383
379
  "lodash": "4.17.21",
384
380
  "semver": "^7.3.8",
381
+ "traverse": "0.6.7",
385
382
  "viz.js": "1.8.2",
386
383
  "wrap-ansi": "8.1.0"
387
384
  },
@@ -391,15 +388,15 @@
391
388
  "@types/he": "1.2.0",
392
389
  "@types/lodash": "4.14.191",
393
390
  "@types/mocha": "10.0.1",
394
- "@typescript-eslint/eslint-plugin": "5.52.0",
395
- "@typescript-eslint/parser": "5.52.0",
391
+ "@typescript-eslint/eslint-plugin": "5.53.0",
392
+ "@typescript-eslint/parser": "5.53.0",
396
393
  "c8": "7.13.0",
397
394
  "chai": "4.3.7",
398
395
  "chai-as-promised": "7.1.1",
399
396
  "chai-json-schema": "1.5.1",
400
397
  "chai-xml": "0.4.0",
401
- "dependency-cruiser": "12.9.0",
402
- "esbuild": "0.17.8",
398
+ "dependency-cruiser": "12.10.0",
399
+ "esbuild": "0.17.10",
403
400
  "eslint": "8.34.0",
404
401
  "eslint-config-moving-meadow": "4.0.2",
405
402
  "eslint-config-prettier": "8.6.0",
@@ -416,13 +413,13 @@
416
413
  "lint-staged": "13.1.2",
417
414
  "mocha": "10.2.0",
418
415
  "npm-run-all": "4.1.5",
419
- "peggy": "2.0.1",
416
+ "peggy": "3.0.0",
420
417
  "prettier": "2.8.4",
421
418
  "query-string": "8.1.0",
422
419
  "ts-node": "10.9.1",
423
420
  "typescript": "4.9.5",
424
421
  "upem": "7.3.2",
425
- "watskeburt": "0.9.2",
422
+ "watskeburt": "0.10.0",
426
423
  "wireit": "0.9.5",
427
424
  "xml-name-validator": "4.0.0"
428
425
  },
@@ -1,4 +1,4 @@
1
- // Generated by Peggy 2.0.1.
1
+ // Generated by Peggy 3.0.0.
2
2
  //
3
3
  // https://peggyjs.org/
4
4
 
@@ -43,16 +43,19 @@ peg$SyntaxError.prototype.format = function(sources) {
43
43
  }
44
44
  }
45
45
  var s = this.location.start;
46
- var loc = this.location.source + ":" + s.line + ":" + s.column;
46
+ var offset_s = (this.location.source && (typeof this.location.source.offset === "function"))
47
+ ? this.location.source.offset(s)
48
+ : s;
49
+ var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
47
50
  if (src) {
48
51
  var e = this.location.end;
49
- var filler = peg$padEnd("", s.line.toString().length, ' ');
52
+ var filler = peg$padEnd("", offset_s.line.toString().length, ' ');
50
53
  var line = src[s.line - 1];
51
54
  var last = s.line === e.line ? e.column : line.length + 1;
52
55
  var hatLen = (last - s.column) || 1;
53
56
  str += "\n --> " + loc + "\n"
54
57
  + filler + " |\n"
55
- + s.line + " | " + line + "\n"
58
+ + offset_s.line + " | " + line + "\n"
56
59
  + filler + " | " + peg$padEnd("", s.column - 1, ' ')
57
60
  + peg$padEnd("", hatLen, "^");
58
61
  } else {
@@ -327,11 +330,11 @@ function peg$parse(input, options) {
327
330
  }
328
331
  }
329
332
 
330
- function peg$computeLocation(startPos, endPos) {
333
+ function peg$computeLocation(startPos, endPos, offset) {
331
334
  var startPosDetails = peg$computePosDetails(startPos);
332
335
  var endPosDetails = peg$computePosDetails(endPos);
333
336
 
334
- return {
337
+ var res = {
335
338
  source: peg$source,
336
339
  start: {
337
340
  offset: startPos,
@@ -344,6 +347,11 @@ function peg$parse(input, options) {
344
347
  column: endPosDetails.column
345
348
  }
346
349
  };
350
+ if (offset && peg$source && (typeof peg$source.offset === "function")) {
351
+ res.start = peg$source.offset(res.start);
352
+ res.end = peg$source.offset(res.end);
353
+ }
354
+ return res;
347
355
  }
348
356
 
349
357
  function peg$fail(expected) {
@@ -1,7 +1,9 @@
1
+ /* eslint-disable no-invalid-this */
1
2
  /* eslint-disable security/detect-object-injection */
2
3
  import fastxml from "fast-xml-parser";
3
4
  import he from "he";
4
5
  import castArray from "lodash/castArray.js";
6
+ import traverse from "traverse";
5
7
  import utl from "../../transform/utl.mjs";
6
8
  import parserHelpers from "../parser-helpers.mjs";
7
9
  import { normalizeMachine } from "./normalize-machine.mjs";
@@ -26,11 +28,6 @@ function extractActionsFromInvokes(pInvokeTriggers) {
26
28
  });
27
29
  }
28
30
 
29
- /**
30
- * @param {import("./scxml").INormalizedSCXMLState} pState
31
- * @returns {{type: string; body: string;}[]}
32
- */
33
-
34
31
  /**
35
32
  * @param {import("./scxml").INormalizedSCXMLState} pState
36
33
  * @returns {any[]}
@@ -54,7 +51,7 @@ function deriveActions(pState) {
54
51
 
55
52
  /**
56
53
  * @param {import("../../..").StateType} pType
57
- * param {import("./scxml").ISCXMLHistoryState} pState
54
+ * @param {import("./scxml").ISCXMLHistoryState} pState
58
55
  * @param {any} pState
59
56
  * @returns {import("../../..").StateType}
60
57
  */
@@ -64,7 +61,6 @@ function deriveStateType(pType, pState) {
64
61
 
65
62
  /**
66
63
  * @param {import("../../../types/state-machine-cat").StateType} pType
67
- * returns {(pState: import("./scxml").INormalizedSCXMLState) => import("../../..").IState}
68
64
  * @returns {(any) => import("../../..").IState}
69
65
  */
70
66
  function mapState(pType) {
@@ -121,7 +117,6 @@ function extractTransitionAttributesFromObject(pTransition) {
121
117
  }
122
118
 
123
119
  /**
124
- *
125
120
  * @param {import("./scxml").ISCXMLTransition} pTransition
126
121
  * @returns {{action?: string; label?: string;event?: string; cond?: string; type?: string}}
127
122
  */
@@ -223,6 +218,41 @@ function mapMachine(pSCXMLStateMachine) {
223
218
  return lReturnValue;
224
219
  }
225
220
 
221
+ /**
222
+ * This funky looking replace exists to make the output of the fast-xml-parser
223
+ * backwards compatible with its version 3 that in case of conflicts between
224
+ * attribute names and tag names gave preference to the attribute name (version 4
225
+ * does the opposite). The previous behaviour was undocumented and for fast-xml-parser
226
+ * likely a kind of edge case (normal people probably don't pass an empty attributeNamePrefix).
227
+ *
228
+ * @param {any} pObject
229
+ * @param {string} pAttributeNamePrefix
230
+ * @returns {any} the object, but
231
+ * - with attributes that have the same name as tags in the same parent removed,
232
+ * - attributes that don't have an equally named tag get their key renamed back
233
+ * to the one without the pAttributeNamePrefix
234
+ */
235
+ function deDuplicateAttributesAndTags(pObject, pAttributeNamePrefix) {
236
+ // - 'traverse' relies on the 'this' property a 'normal' function provides,
237
+ // so this is not an arrow function.
238
+ // - while it looks iffy to have a map function without a return statement
239
+ // it's canonical traverse use (as per https://github.com/ljharb/js-traverse/blob/v0.6.7/README.md)
240
+ // eslint-disable-next-line array-callback-return
241
+ return traverse(pObject).map(function deDuplicate() {
242
+ if (this.key?.startsWith(pAttributeNamePrefix)) {
243
+ const pUnprefixedAttributeName = this.key.slice(
244
+ pAttributeNamePrefix.length
245
+ );
246
+ if (this.parent.keys.includes(pUnprefixedAttributeName)) {
247
+ this.remove();
248
+ } else {
249
+ this.parent.node[pUnprefixedAttributeName] = this.node;
250
+ this.remove();
251
+ }
252
+ }
253
+ });
254
+ }
255
+
226
256
  /**
227
257
  * Parses SCXML into a state machine AST.
228
258
  *
@@ -231,22 +261,31 @@ function mapMachine(pSCXMLStateMachine) {
231
261
  */
232
262
  export function parse(pSCXMLString) {
233
263
  const lTrimmedSCXMLString = pSCXMLString.trim();
264
+ const lAttributeNamePrefix = "@_";
265
+ /** @type {import("./scxml").ISCXMLAsJSON} */
266
+ let lXMLAsJSON = {};
234
267
 
235
- if (fastxml.validate(lTrimmedSCXMLString) === true) {
236
- /** @type {import("./scxml").ISCXMLAsJSON} */
237
- const lXMLAsJSON = fastxml.parse(lTrimmedSCXMLString, {
238
- attributeNamePrefix: "",
239
- ignoreAttributes: false,
240
- tagValueProcessor: (pTagValue) => he.decode(pTagValue),
241
- stopNodes: ["onentry", "onexit", "transition"],
242
- });
243
-
244
- return mapMachine(
245
- lXMLAsJSON?.scxml ?? {
246
- xmlns: "http://www.w3.org/2005/07/scxml",
247
- version: "1.0",
248
- }
268
+ const lXMLParser = new fastxml.XMLParser({
269
+ attributeNamePrefix: lAttributeNamePrefix,
270
+ ignoreAttributes: false,
271
+ parseTagValue: true,
272
+ processEntities: false,
273
+ tagValueProcessor: (_pTagName, pTagValue) => he.decode(pTagValue),
274
+ stopNodes: ["*.onentry", "*.onexit", "*.transition"],
275
+ });
276
+
277
+ try {
278
+ lXMLAsJSON = deDuplicateAttributesAndTags(
279
+ lXMLParser.parse(lTrimmedSCXMLString, true),
280
+ lAttributeNamePrefix
249
281
  );
282
+ } catch (pError) {
283
+ throw new Error("That doesn't look like valid xml ...\n");
250
284
  }
251
- throw new Error("That doesn't look like valid xml ...\n");
285
+ return mapMachine(
286
+ lXMLAsJSON?.scxml ?? {
287
+ xmlns: "http://www.w3.org/2005/07/scxml",
288
+ version: "1.0",
289
+ }
290
+ );
252
291
  }
@@ -1,4 +1,4 @@
1
- // Generated by Peggy 2.0.1.
1
+ // Generated by Peggy 3.0.0.
2
2
  //
3
3
  // https://peggyjs.org/
4
4
 
@@ -45,16 +45,19 @@ peg$SyntaxError.prototype.format = function(sources) {
45
45
  }
46
46
  }
47
47
  var s = this.location.start;
48
- var loc = this.location.source + ":" + s.line + ":" + s.column;
48
+ var offset_s = (this.location.source && (typeof this.location.source.offset === "function"))
49
+ ? this.location.source.offset(s)
50
+ : s;
51
+ var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
49
52
  if (src) {
50
53
  var e = this.location.end;
51
- var filler = peg$padEnd("", s.line.toString().length, ' ');
54
+ var filler = peg$padEnd("", offset_s.line.toString().length, ' ');
52
55
  var line = src[s.line - 1];
53
56
  var last = s.line === e.line ? e.column : line.length + 1;
54
57
  var hatLen = (last - s.column) || 1;
55
58
  str += "\n --> " + loc + "\n"
56
59
  + filler + " |\n"
57
- + s.line + " | " + line + "\n"
60
+ + offset_s.line + " | " + line + "\n"
58
61
  + filler + " | " + peg$padEnd("", s.column - 1, ' ')
59
62
  + peg$padEnd("", hatLen, "^");
60
63
  } else {
@@ -386,15 +389,15 @@ function peg$parse(input, options) {
386
389
 
387
390
  return trans;
388
391
  };
389
- var peg$f20 = function(from, to) {
392
+ var peg$f20 = function(from_, to) {
390
393
  return {
391
- from: from,
394
+ from: from_,
392
395
  to: to
393
396
  }
394
397
  };
395
- var peg$f21 = function(to, from) {
398
+ var peg$f21 = function(to, from_) {
396
399
  return {
397
- from: from,
400
+ from: from_,
398
401
  to: to
399
402
  }
400
403
  };
@@ -554,11 +557,11 @@ function peg$parse(input, options) {
554
557
  }
555
558
  }
556
559
 
557
- function peg$computeLocation(startPos, endPos) {
560
+ function peg$computeLocation(startPos, endPos, offset) {
558
561
  var startPosDetails = peg$computePosDetails(startPos);
559
562
  var endPosDetails = peg$computePosDetails(endPos);
560
563
 
561
- return {
564
+ var res = {
562
565
  source: peg$source,
563
566
  start: {
564
567
  offset: startPos,
@@ -571,6 +574,11 @@ function peg$parse(input, options) {
571
574
  column: endPosDetails.column
572
575
  }
573
576
  };
577
+ if (offset && peg$source && (typeof peg$source.offset === "function")) {
578
+ res.start = peg$source.offset(res.start);
579
+ res.end = peg$source.offset(res.end);
580
+ }
581
+ return res;
574
582
  }
575
583
 
576
584
  function peg$fail(expected) {