state-machine-cat 10.1.1 → 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/README.md +1 -1
- package/bin/smcat.mjs +5 -0
- package/dist/commonjs/bundle.js +64 -64
- package/package.json +33 -32
- 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 +2 -1
- package/types/state-machine-cat.d.ts +41 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "state-machine-cat",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.3",
|
|
4
4
|
"description": "write beautiful state charts",
|
|
5
5
|
"main": "./dist/commonjs/index.js",
|
|
6
6
|
"module": "./src/index.mjs",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"depcruise:view-report": "wireit",
|
|
41
41
|
"depcruise:github-actions:markdown": "wireit",
|
|
42
42
|
"depcruise:github-actions:mermaid": "wireit",
|
|
43
|
+
"depcruise:github-actions:mermaid:affected": "wireit",
|
|
43
44
|
"depcruise:github-actions:mermaid:diff": "wireit",
|
|
44
45
|
"lint": "wireit",
|
|
45
46
|
"lint:eslint": "wireit",
|
|
@@ -89,11 +90,6 @@
|
|
|
89
90
|
"policy": "wanted",
|
|
90
91
|
"because": "fast-xml-parser 4 has some breaking changes we still need to grok (why? how?)"
|
|
91
92
|
},
|
|
92
|
-
{
|
|
93
|
-
"package": "husky",
|
|
94
|
-
"policy": "pin",
|
|
95
|
-
"because": "(npm7 & husky don't play nice together - and it might be it's not going to be solved satisfactorily) https://github.com/typicode/husky/issues/822 "
|
|
96
|
-
},
|
|
97
93
|
{
|
|
98
94
|
"package": "viz.js",
|
|
99
95
|
"policy": "pin",
|
|
@@ -243,13 +239,13 @@
|
|
|
243
239
|
]
|
|
244
240
|
},
|
|
245
241
|
"depcruise:graph:dev": {
|
|
246
|
-
"command": "depcruise-fmt node_modules/.cache/depcruise-cache.json --output-type dot --include-only '^(bin|src|package\\.json)' --prefix vscode://file/$(pwd)/ | dot -Tsvg | depcruise-wrap-stream-in-html | browser",
|
|
242
|
+
"command": "depcruise-fmt node_modules/.cache/depcruise-cache.json --output-type dot --include-only '^(bin|src|package\\.json)' --prefix vscode://file/$(pwd)/ --highlight \"$(watskeburt develop)\"| dot -Tsvg | depcruise-wrap-stream-in-html | browser",
|
|
247
243
|
"dependencies": [
|
|
248
244
|
"depcruise:json"
|
|
249
245
|
]
|
|
250
246
|
},
|
|
251
247
|
"depcruise:graph:dev:flat": {
|
|
252
|
-
"command": "depcruise-fmt node_modules/.cache/depcruise-cache.json --output-type flat --include-only '^(bin|src|package\\.json)' --prefix vscode://file/$(pwd)/ | twopi -Tsvg | depcruise-wrap-stream-in-html | browser",
|
|
248
|
+
"command": "depcruise-fmt node_modules/.cache/depcruise-cache.json --output-type flat --include-only '^(bin|src|package\\.json)' --prefix vscode://file/$(pwd)/ --highlight \"$(watskeburt develop)\"| twopi -Tsvg | depcruise-wrap-stream-in-html | browser",
|
|
253
249
|
"dependencies": [
|
|
254
250
|
"depcruise:json"
|
|
255
251
|
]
|
|
@@ -272,8 +268,14 @@
|
|
|
272
268
|
"depcruise:json"
|
|
273
269
|
]
|
|
274
270
|
},
|
|
271
|
+
"depcruise:github-actions:mermaid:affected": {
|
|
272
|
+
"command": "echo '\n\n```mermaid' >> $GITHUB_STEP_SUMMARY && depcruise-fmt node_modules/.cache/depcruise-cache.json --include-only --reaches '$(watskeburt $SHA -T regex)' --output-type mermaid >> $GITHUB_STEP_SUMMARY && echo '```\n\n' >> $GITHUB_STEP_SUMMARY",
|
|
273
|
+
"dependencies": [
|
|
274
|
+
"depcruise:json"
|
|
275
|
+
]
|
|
276
|
+
},
|
|
275
277
|
"depcruise:github-actions:mermaid:diff": {
|
|
276
|
-
"command": "echo '\n\n```mermaid' >> $GITHUB_STEP_SUMMARY && depcruise-fmt node_modules/.cache/depcruise-cache.json --include-only '^(bin|src)' --
|
|
278
|
+
"command": "echo '\n\n```mermaid' >> $GITHUB_STEP_SUMMARY && depcruise-fmt node_modules/.cache/depcruise-cache.json --include-only '^(bin|src)' --highlight '$(watskeburt $SHA -T regex)' --output-type mermaid >> $GITHUB_STEP_SUMMARY && echo '```\n\n' >> $GITHUB_STEP_SUMMARY",
|
|
277
279
|
"dependencies": [
|
|
278
280
|
"depcruise:json"
|
|
279
281
|
]
|
|
@@ -294,7 +296,7 @@
|
|
|
294
296
|
]
|
|
295
297
|
},
|
|
296
298
|
"lint:prettier": {
|
|
297
|
-
"command": "prettier --check \"bin/*.mjs\" \"{src,test}/**/*.{js,mjs}\" \"{config,test}/**/*.{js,json}\" \"tools/*.{js,mjs,json}\" \"types
|
|
299
|
+
"command": "prettier --check \"bin/*.mjs\" \"{src,test}/**/*.{js,mjs}\" \"{config,test}/**/*.{js,json}\" \"tools/*.{js,mjs,json}\" \"{src,types}/**/*.{ts,mts}\" \"*.{json,yml,md}\" \"docs/{smcat-online-interpreter.js,*.md}\"",
|
|
298
300
|
"files": [
|
|
299
301
|
"bin/*.mjs",
|
|
300
302
|
"{src,test}/**/*.{js,mjs}",
|
|
@@ -312,15 +314,15 @@
|
|
|
312
314
|
]
|
|
313
315
|
},
|
|
314
316
|
"lint:types:tsc": {
|
|
315
|
-
"command": "tsc --noEmit --strict --types --noUnusedLocals --noUnusedParameters --pretty types/*.d.ts",
|
|
317
|
+
"command": "tsc --noEmit --strict --types --noUnusedLocals --noUnusedParameters --pretty types/*.d.ts src/cli/*.d.mts src/cli/*.d.ts src/parse/scxml/*.d.ts",
|
|
316
318
|
"files": [
|
|
317
319
|
"types/*.d.ts"
|
|
318
320
|
]
|
|
319
321
|
},
|
|
320
322
|
"lint:types:eslint": {
|
|
321
|
-
"command": "eslint types/*.d.ts",
|
|
323
|
+
"command": "eslint types/*.d.ts src/cli/*.d.mts src/cli/*.d.ts src/parse/scxml/*.d.ts",
|
|
322
324
|
"files": [
|
|
323
|
-
"types
|
|
325
|
+
"{src,types}/**/*.d.{ts,mts}",
|
|
324
326
|
".eslintrc.json"
|
|
325
327
|
]
|
|
326
328
|
},
|
|
@@ -340,10 +342,10 @@
|
|
|
340
342
|
]
|
|
341
343
|
},
|
|
342
344
|
"lint:fix:prettier": {
|
|
343
|
-
"command": "prettier --loglevel warn --write \"bin/*.mjs\" \"{src,test}/**/*.{js,mjs}\" \"{config,test}/**/*.{js,json}\" \"tools/*.{js,mjs,json}\" \"types
|
|
345
|
+
"command": "prettier --loglevel warn --write \"bin/*.mjs\" \"{src,test}/**/*.{js,mjs}\" \"{config,test}/**/*.{js,json}\" \"tools/*.{js,mjs,json}\" \"{src,types}/**/*.{ts,mts}\" \"*.{json,yml,md}\" \"docs/{smcat-online-interpreter.js,*.md}\"",
|
|
344
346
|
"files": [
|
|
345
347
|
"bin/*.mjs",
|
|
346
|
-
"{src,test}/**/*.{js,mjs}",
|
|
348
|
+
"{src,test}/**/*.{js,mjs,ts,mts}",
|
|
347
349
|
"{config,test}/**/*.{js,json}",
|
|
348
350
|
"tools/*.{js,mjs,json}",
|
|
349
351
|
"types/*.ts",
|
|
@@ -352,20 +354,20 @@
|
|
|
352
354
|
]
|
|
353
355
|
},
|
|
354
356
|
"lint:fix:types": {
|
|
355
|
-
"command": "eslint --fix types/*.d.ts",
|
|
357
|
+
"command": "eslint --fix types/*.d.ts src/cli/*.d.mts src/cli/*.d.ts src/parse/scxml/*.d.ts",
|
|
356
358
|
"files": [
|
|
357
|
-
"types
|
|
359
|
+
"{src,types}/**/*.d.{ts,mts}",
|
|
358
360
|
".eslintrc.json"
|
|
359
361
|
]
|
|
360
362
|
},
|
|
361
363
|
"test": {
|
|
362
|
-
"command": "mocha
|
|
364
|
+
"command": "mocha",
|
|
363
365
|
"files": [
|
|
364
366
|
"{src,test}/**/*.{js,mjs,json}"
|
|
365
367
|
]
|
|
366
368
|
},
|
|
367
369
|
"test:cover": {
|
|
368
|
-
"command": "c8 --all --check-coverage --statements 100 --branches 99.1 --functions 100 --lines 100 --exclude \"{bin/*,config/**/*,coverage/**/*,docs/**/*,public/**/*,test/**/*,tools/**/*,types/**/*,dist/commonjs/*,src/**/*{template,-parser}.{mjs,cjs,js},tmp*}\" --reporter text-summary --reporter html --reporter lcov mocha
|
|
370
|
+
"command": "c8 --all --check-coverage --statements 100 --branches 99.1 --functions 100 --lines 100 --exclude \"{bin/*,config/**/*,coverage/**/*,docs/**/*,public/**/*,test/**/*,tools/**/*,types/**/*,dist/commonjs/*,src/**/*.d.{ts,mts},src/**/*{template,-parser}.{mjs,cjs,js},tmp*}\" --reporter text-summary --reporter html --reporter lcov mocha",
|
|
369
371
|
"output": [
|
|
370
372
|
"coverage/lcov.info"
|
|
371
373
|
],
|
|
@@ -394,7 +396,7 @@
|
|
|
394
396
|
},
|
|
395
397
|
"dependencies": {
|
|
396
398
|
"ajv": "8.11.0",
|
|
397
|
-
"chalk": "5.1.
|
|
399
|
+
"chalk": "5.1.2",
|
|
398
400
|
"commander": "9.4.1",
|
|
399
401
|
"fast-xml-parser": "3.21.1",
|
|
400
402
|
"get-stream": "6.0.1",
|
|
@@ -407,16 +409,16 @@
|
|
|
407
409
|
"wrap-ansi": "8.0.1"
|
|
408
410
|
},
|
|
409
411
|
"devDependencies": {
|
|
410
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
411
|
-
"@typescript-eslint/parser": "5.
|
|
412
|
+
"@typescript-eslint/eslint-plugin": "5.42.1",
|
|
413
|
+
"@typescript-eslint/parser": "5.42.1",
|
|
412
414
|
"c8": "7.12.0",
|
|
413
|
-
"chai": "4.3.
|
|
415
|
+
"chai": "4.3.7",
|
|
414
416
|
"chai-as-promised": "7.1.1",
|
|
415
417
|
"chai-json-schema": "1.5.1",
|
|
416
418
|
"chai-xml": "0.4.0",
|
|
417
|
-
"dependency-cruiser": "11.
|
|
418
|
-
"esbuild": "0.15.
|
|
419
|
-
"eslint": "8.
|
|
419
|
+
"dependency-cruiser": "11.18.0",
|
|
420
|
+
"esbuild": "0.15.13",
|
|
421
|
+
"eslint": "8.27.0",
|
|
420
422
|
"eslint-config-moving-meadow": "4.0.2",
|
|
421
423
|
"eslint-config-prettier": "8.5.0",
|
|
422
424
|
"eslint-plugin-budapestian": "5.0.1",
|
|
@@ -426,18 +428,18 @@
|
|
|
426
428
|
"eslint-plugin-node": "11.1.0",
|
|
427
429
|
"eslint-plugin-security": "1.5.0",
|
|
428
430
|
"eslint-plugin-unicorn": "44.0.2",
|
|
429
|
-
"husky": "8.0.
|
|
431
|
+
"husky": "8.0.2",
|
|
430
432
|
"is-pdf": "1.0.0",
|
|
431
433
|
"is-png": "3.0.1",
|
|
432
434
|
"lint-staged": "13.0.3",
|
|
433
|
-
"mocha": "10.
|
|
435
|
+
"mocha": "10.1.0",
|
|
434
436
|
"npm-run-all": "4.1.5",
|
|
435
437
|
"peggy": "2.0.1",
|
|
436
438
|
"prettier": "2.7.1",
|
|
437
439
|
"query-string": "7.1.1",
|
|
438
440
|
"typescript": "4.8.4",
|
|
439
|
-
"upem": "7.3.
|
|
440
|
-
"watskeburt": "0.
|
|
441
|
+
"upem": "7.3.1",
|
|
442
|
+
"watskeburt": "0.8.1",
|
|
441
443
|
"wireit": "0.7.2",
|
|
442
444
|
"xml-name-validator": "4.0.0"
|
|
443
445
|
},
|
|
@@ -471,8 +473,7 @@
|
|
|
471
473
|
"{src,test}/**/*.{js,cjs}": [
|
|
472
474
|
"eslint --cache --cache-location .cache --fix",
|
|
473
475
|
"prettier --loglevel warn --write",
|
|
474
|
-
"depcruise --output-type err-long --config config/dependency-cruiser.js"
|
|
475
|
-
"git add"
|
|
476
|
+
"depcruise --output-type err-long --config config/dependency-cruiser.js"
|
|
476
477
|
]
|
|
477
478
|
}
|
|
478
479
|
}
|
package/src/cli/actions.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import getStream from "get-stream";
|
|
2
3
|
import smcat from "../index-node.mjs";
|
|
3
4
|
import { getOutStream, getInStream } from "./file-name-to-stream.mjs";
|
|
@@ -31,7 +32,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
31
32
|
`;
|
|
32
33
|
|
|
33
34
|
export default {
|
|
35
|
+
/** @type {string} */
|
|
34
36
|
LICENSE,
|
|
37
|
+
/**
|
|
38
|
+
* @param {import("./cli").ICLIRenderOptions} pOptions
|
|
39
|
+
*/
|
|
35
40
|
transform(pOptions) {
|
|
36
41
|
return getStream(getInStream(pOptions.inputFrom)).then((pInput) => {
|
|
37
42
|
const lOutput = smcat.render(pInput, {
|
|
@@ -54,6 +59,10 @@ export default {
|
|
|
54
59
|
});
|
|
55
60
|
},
|
|
56
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @param {any} pError
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
57
66
|
formatError(pError) {
|
|
58
67
|
if (Boolean(pError.location)) {
|
|
59
68
|
return `\n syntax error on line ${pError.location.start.line}, column ${pError.location.start.column}:\n ${pError.message}\n\n`;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/* eslint-disable security/detect-non-literal-fs-filename */
|
|
2
|
-
|
|
3
|
-
import * as fs from "node:fs";
|
|
3
|
+
import fs from "node:fs";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
6
|
* @param {string} pOutputTo
|
|
8
|
-
* @returns {
|
|
7
|
+
* @returns {NodeJS.WritableStream}
|
|
9
8
|
*/
|
|
10
9
|
export function getOutStream(pOutputTo) {
|
|
11
10
|
if ("-" === pOutputTo) {
|
|
@@ -13,10 +12,10 @@ export function getOutStream(pOutputTo) {
|
|
|
13
12
|
}
|
|
14
13
|
return fs.createWriteStream(pOutputTo);
|
|
15
14
|
}
|
|
15
|
+
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
17
|
* @param {string} pInputFrom
|
|
19
|
-
* @returns {
|
|
18
|
+
* @returns {NodeJS.ReadableStream}
|
|
20
19
|
*/
|
|
21
20
|
export function getInStream(pInputFrom) {
|
|
22
21
|
if ("-" === pInputFrom) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
// seems eslint-plugin-import and eslint-plugin-node can't handle exports
|
|
2
3
|
// fields yet. No man overboard not checking against this, because dependency-cruiser
|
|
3
4
|
// will also find them
|
|
@@ -7,6 +8,10 @@ import indentString from "indent-string";
|
|
|
7
8
|
import wrapAnsi from "wrap-ansi";
|
|
8
9
|
import dotToVectorNative from "../render/vector/dot-to-vector-native.mjs";
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} pString
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
10
15
|
function wrapAndIndent(pString) {
|
|
11
16
|
const lDogmaticMaxConsoleWidth = 78;
|
|
12
17
|
const lDefaultIndent = 2;
|
|
@@ -16,6 +21,10 @@ function wrapAndIndent(pString) {
|
|
|
16
21
|
return indentString(wrapAnsi(pString, lMaxWidth), lDefaultIndent);
|
|
17
22
|
}
|
|
18
23
|
|
|
24
|
+
/**
|
|
25
|
+
* @param {boolean} pDotIsAvailable
|
|
26
|
+
* @return {string}
|
|
27
|
+
*/
|
|
19
28
|
export default (pDotIsAvailable = dotToVectorNative.isAvailable({})) => {
|
|
20
29
|
const lDescription =
|
|
21
30
|
"Write beautiful state charts - https://github.com/sverweij/state-machine-cat";
|
package/src/cli/normalize.mjs
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-check
|
|
2
|
+
/* eslint-disable security/detect-object-injection, no-inline-comments */
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import options from "../options.mjs";
|
|
4
5
|
import { parse as parseAttributes } from "./attributes-parser.mjs";
|
|
5
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {{[extension: string]: string}} DictionaryType
|
|
9
|
+
*/
|
|
10
|
+
|
|
6
11
|
const INPUT_EXTENSIONS = {
|
|
7
12
|
".smcat": "smcat",
|
|
8
13
|
".scxml": "scxml",
|
|
@@ -11,16 +16,18 @@ const INPUT_EXTENSIONS = {
|
|
|
11
16
|
".ast": "json",
|
|
12
17
|
};
|
|
13
18
|
const OUTPUT_EXTENSIONS = {
|
|
14
|
-
".
|
|
19
|
+
".ast": "json",
|
|
15
20
|
".dot": "dot",
|
|
21
|
+
".eps": "eps",
|
|
16
22
|
".json": "json",
|
|
17
|
-
".
|
|
23
|
+
".pdf": "pdf",
|
|
24
|
+
".png": "png",
|
|
25
|
+
".ps": "ps",
|
|
26
|
+
".ps2": "ps2",
|
|
18
27
|
".scjson": "scjson",
|
|
19
28
|
".scxml": "scxml",
|
|
29
|
+
".smcat": "smcat",
|
|
20
30
|
".svg": "svg",
|
|
21
|
-
".ps": "ps",
|
|
22
|
-
".ps2": "ps2",
|
|
23
|
-
".eps": "eps",
|
|
24
31
|
};
|
|
25
32
|
|
|
26
33
|
/**
|
|
@@ -31,7 +38,7 @@ const OUTPUT_EXTENSIONS = {
|
|
|
31
38
|
* When in doubt returns pDefault
|
|
32
39
|
*
|
|
33
40
|
* @param {string} pString - filename
|
|
34
|
-
* @param {
|
|
41
|
+
* @param {DictionaryType} pExtensionMap - a dictionary with
|
|
35
42
|
* extension : classification pairs
|
|
36
43
|
* @param {string} pDefault - the default to return when the extension
|
|
37
44
|
* does not occur in the extension map
|
|
@@ -42,15 +49,26 @@ function classifyExtension(pString, pExtensionMap, pDefault) {
|
|
|
42
49
|
return pExtensionMap[path.extname(pString)] || pDefault;
|
|
43
50
|
}
|
|
44
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @param {import("../../types/state-machine-cat").OutputType} pOutputType
|
|
54
|
+
* @returns {import("../../types/state-machine-cat").OutputType}
|
|
55
|
+
*/
|
|
45
56
|
function outputType2Extension(pOutputType) {
|
|
46
57
|
const lExceptions = {
|
|
47
|
-
oldsvg: "svg",
|
|
48
|
-
oldps2: "ps",
|
|
49
58
|
oldeps: "eps",
|
|
59
|
+
oldps: "ps",
|
|
60
|
+
oldps2: "ps",
|
|
61
|
+
oldsvg: "svg",
|
|
50
62
|
ps2: "ps",
|
|
51
63
|
};
|
|
52
64
|
return lExceptions[pOutputType] || pOutputType;
|
|
53
65
|
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {string} pInputFrom
|
|
69
|
+
* @param {import("../../types/state-machine-cat").OutputType} pOutputType
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
54
72
|
function deriveOutputFromInput(pInputFrom, pOutputType) {
|
|
55
73
|
const lExtension = outputType2Extension(pOutputType);
|
|
56
74
|
|
|
@@ -66,16 +84,28 @@ function deriveOutputFromInput(pInputFrom, pOutputType) {
|
|
|
66
84
|
.concat(lExtension);
|
|
67
85
|
}
|
|
68
86
|
|
|
87
|
+
/**
|
|
88
|
+
* @param {string|undefined} pOutputTo
|
|
89
|
+
* @param {string} pInputFrom
|
|
90
|
+
* @param {import("../../types/state-machine-cat").OutputType} pOutputType
|
|
91
|
+
* @returns {string}
|
|
92
|
+
*/
|
|
69
93
|
function determineOutputTo(pOutputTo, pInputFrom, pOutputType) {
|
|
70
|
-
return
|
|
71
|
-
? pOutputTo
|
|
72
|
-
: deriveOutputFromInput(pInputFrom, pOutputType);
|
|
94
|
+
return pOutputTo ? pOutputTo : deriveOutputFromInput(pInputFrom, pOutputType);
|
|
73
95
|
}
|
|
74
96
|
|
|
97
|
+
/**
|
|
98
|
+
* @param {import("../../types/state-machine-cat").InputType|undefined} pInputType
|
|
99
|
+
* @param {string} pInputFrom
|
|
100
|
+
* @returns {import("../../types/state-machine-cat").InputType}
|
|
101
|
+
*/
|
|
75
102
|
function determineInputType(pInputType, pInputFrom) {
|
|
76
103
|
if (pInputType) {
|
|
77
104
|
return pInputType;
|
|
78
105
|
}
|
|
106
|
+
// @ts-expect-error we can safely cast this to InputType. classifyExtension
|
|
107
|
+
// can probably use treatment with a generic, but with jsdoc annotations
|
|
108
|
+
// if at all possible would likely be awkward.
|
|
79
109
|
return classifyExtension(
|
|
80
110
|
pInputFrom,
|
|
81
111
|
INPUT_EXTENSIONS,
|
|
@@ -103,9 +133,16 @@ function determineParameter(pOptions, pParameter) {
|
|
|
103
133
|
: options.getAllowedValues()[pParameter].default;
|
|
104
134
|
}
|
|
105
135
|
|
|
136
|
+
/**
|
|
137
|
+
* @param {Partial<import("./cli").ILooseCLIRenderOptions>} pOptions
|
|
138
|
+
* @param {keyof import("./cli").ILooseCLIRenderOptions} pDotAttributes
|
|
139
|
+
* @returns {import("../../types/state-machine-cat").dotAttributesType}
|
|
140
|
+
*/
|
|
106
141
|
function determineDotAttributes(pOptions, pDotAttributes) {
|
|
107
|
-
return
|
|
108
|
-
|
|
142
|
+
return Boolean(pOptions?.[pDotAttributes]) &&
|
|
143
|
+
typeof pOptions[pDotAttributes] === "string"
|
|
144
|
+
? // @ts-expect-error parseAttributes expects a string - which we can guarantee (see above) - but tsc can't/ doesn't see it
|
|
145
|
+
parseAttributes(pOptions[pDotAttributes])
|
|
109
146
|
: [];
|
|
110
147
|
}
|
|
111
148
|
|
|
@@ -114,38 +151,39 @@ function determineDotAttributes(pOptions, pDotAttributes) {
|
|
|
114
151
|
*
|
|
115
152
|
* - guesses the input type when not given
|
|
116
153
|
* - guesses the output type when not given
|
|
117
|
-
* -
|
|
154
|
+
* - guesses the filename to output to when not given
|
|
118
155
|
* - translates parserOutput to a regular output type
|
|
119
156
|
*
|
|
120
157
|
* @param {string} pArgument an argument (containing the filename to parse)
|
|
121
|
-
* @param {
|
|
122
|
-
* @return {
|
|
158
|
+
* @param {import("./cli").ILooseCLIRenderOptions} pLooseOptions
|
|
159
|
+
* @return {import("./cli").ICLIRenderOptions}
|
|
160
|
+
* the passed options object, but normalized
|
|
123
161
|
*/
|
|
124
|
-
export default function normalize(pArgument = "-",
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
pOptions.inputType,
|
|
130
|
-
lReturnValue.inputFrom
|
|
131
|
-
);
|
|
132
|
-
lReturnValue.outputType = determineOutputType(
|
|
133
|
-
pOptions.outputType,
|
|
134
|
-
pOptions.outputTo
|
|
162
|
+
export default function normalize(pArgument = "-", pLooseOptions = {}) {
|
|
163
|
+
const lNormalizedInputFrom = pArgument || "-";
|
|
164
|
+
const lNormalizedInputType = determineInputType(
|
|
165
|
+
pLooseOptions.inputType,
|
|
166
|
+
lNormalizedInputFrom
|
|
135
167
|
);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
lReturnValue.outputType
|
|
168
|
+
const lNormalizedOutputType = determineOutputType(
|
|
169
|
+
pLooseOptions.outputType,
|
|
170
|
+
pLooseOptions.outputTo
|
|
140
171
|
);
|
|
141
|
-
lReturnValue.engine = determineParameter(pOptions, "engine");
|
|
142
|
-
lReturnValue.direction = determineParameter(pOptions, "direction");
|
|
143
|
-
lReturnValue.dotGraphAttrs = determineDotAttributes(
|
|
144
|
-
pOptions,
|
|
145
|
-
"dotGraphAttrs"
|
|
146
|
-
);
|
|
147
|
-
lReturnValue.dotNodeAttrs = determineDotAttributes(pOptions, "dotNodeAttrs");
|
|
148
|
-
lReturnValue.dotEdgeAttrs = determineDotAttributes(pOptions, "dotEdgeAttrs");
|
|
149
172
|
|
|
150
|
-
return
|
|
173
|
+
return {
|
|
174
|
+
inputFrom: lNormalizedInputFrom,
|
|
175
|
+
inputType: lNormalizedInputType,
|
|
176
|
+
outputType: lNormalizedOutputType,
|
|
177
|
+
outputTo: determineOutputTo(
|
|
178
|
+
pLooseOptions.outputTo,
|
|
179
|
+
lNormalizedInputFrom,
|
|
180
|
+
lNormalizedOutputType
|
|
181
|
+
),
|
|
182
|
+
engine: determineParameter(pLooseOptions, "engine"),
|
|
183
|
+
direction: determineParameter(pLooseOptions, "direction"),
|
|
184
|
+
dotGraphAttrs: determineDotAttributes(pLooseOptions, "dotGraphAttrs"),
|
|
185
|
+
dotNodeAttrs: determineDotAttributes(pLooseOptions, "dotNodeAttrs"),
|
|
186
|
+
dotEdgeAttrs: determineDotAttributes(pLooseOptions, "dotEdgeAttrs"),
|
|
187
|
+
desugar: pLooseOptions?.desugar ?? false,
|
|
188
|
+
};
|
|
151
189
|
}
|
package/src/cli/validations.mjs
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import smcat from "../index-node.mjs";
|
|
3
4
|
import { parse as parseAttributes } from "./attributes-parser.mjs";
|
|
4
5
|
|
|
5
6
|
const allowedValues = smcat.getAllowedValues();
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @param {{name: string}} pValue
|
|
10
|
+
* @returns {string}
|
|
11
|
+
*/
|
|
7
12
|
function getName(pValue) {
|
|
8
13
|
return pValue.name;
|
|
9
14
|
}
|
|
@@ -13,14 +18,22 @@ const VALID_INPUT_TYPES = allowedValues.inputType.values.map(getName);
|
|
|
13
18
|
const VALID_ENGINES = allowedValues.engine.values.map(getName);
|
|
14
19
|
const VALID_DIRECTIONS = allowedValues.direction.values.map(getName);
|
|
15
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} pFilename
|
|
23
|
+
* @returns {boolean}
|
|
24
|
+
*/
|
|
16
25
|
function isStdout(pFilename) {
|
|
17
26
|
return "-" === pFilename;
|
|
18
27
|
}
|
|
19
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} pFilename
|
|
31
|
+
* @returns {boolean}
|
|
32
|
+
*/
|
|
20
33
|
function fileExists(pFilename) {
|
|
21
34
|
try {
|
|
22
35
|
if (!isStdout(pFilename)) {
|
|
23
|
-
fs.accessSync(pFilename, fs.R_OK);
|
|
36
|
+
fs.accessSync(pFilename, fs.constants.R_OK);
|
|
24
37
|
}
|
|
25
38
|
return true;
|
|
26
39
|
} catch (pError) {
|
|
@@ -28,6 +41,15 @@ function fileExists(pFilename) {
|
|
|
28
41
|
}
|
|
29
42
|
}
|
|
30
43
|
|
|
44
|
+
/**
|
|
45
|
+
* This function is shaped so it can serve as a validation function in a
|
|
46
|
+
* commander option.
|
|
47
|
+
*
|
|
48
|
+
* @param {keyof import("../../types/state-machine-cat").IRenderOptions} pOption
|
|
49
|
+
* @param {string[]} pValidValues
|
|
50
|
+
* @param {string} pError
|
|
51
|
+
* @returns {never|keyof import("../../types/state-machine-cat").IRenderOptions}
|
|
52
|
+
*/
|
|
31
53
|
function validOption(pOption, pValidValues, pError) {
|
|
32
54
|
if (pValidValues.includes(pOption)) {
|
|
33
55
|
return pOption;
|
|
@@ -78,6 +100,10 @@ export default {
|
|
|
78
100
|
}
|
|
79
101
|
},
|
|
80
102
|
|
|
103
|
+
/**
|
|
104
|
+
* @param {import("./cli").ICLIRenderOptions} pOptions
|
|
105
|
+
* @returns {never|import("./cli").ICLIRenderOptions}
|
|
106
|
+
*/
|
|
81
107
|
validateArguments(pOptions) {
|
|
82
108
|
if (!pOptions.inputFrom) {
|
|
83
109
|
throw new Error(`\n error: Please specify an input file.\n\n`);
|
package/src/index-node.mjs
CHANGED
|
@@ -1,52 +1,18 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import options from "./options.mjs";
|
|
2
3
|
import parse from "./parse/index.mjs";
|
|
3
4
|
import desugar from "./transform/desugar.mjs";
|
|
4
5
|
import getRenderFunction from "./render/index-node.mjs";
|
|
5
6
|
import { version } from "./version.mjs";
|
|
6
7
|
|
|
7
|
-
const KNOWN_OPTIONS = [
|
|
8
|
-
"outputType",
|
|
9
|
-
"inputType",
|
|
10
|
-
"engine",
|
|
11
|
-
"direction",
|
|
12
|
-
"dotNodeAttrs",
|
|
13
|
-
"dotEdgeAttrs",
|
|
14
|
-
"desugar",
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
function isKnownOption(pKnownOptions) {
|
|
18
|
-
return (pCandidateString) => pKnownOptions.includes(pCandidateString);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Remove all attributes from the input object (which'd typically be
|
|
23
|
-
* originating from commander) that are not known options options so
|
|
24
|
-
* a clean object can be passed through.
|
|
25
|
-
*
|
|
26
|
-
* @param {any} pOptions - an options object e.g. as output from commander
|
|
27
|
-
* @param {string[]} pKnownOptions - a list of known options
|
|
28
|
-
* @return {any} - an options object that only contains stuff we care about
|
|
29
|
-
*/
|
|
30
|
-
function ejectUnknownOptions(pOptions, pKnownOptions) {
|
|
31
|
-
return Object.keys(pOptions)
|
|
32
|
-
.filter(isKnownOption(pKnownOptions))
|
|
33
|
-
.reduce((pAll, pKey) => {
|
|
34
|
-
// eslint-disable-next-line security/detect-object-injection
|
|
35
|
-
pAll[pKey] = pOptions[pKey];
|
|
36
|
-
return pAll;
|
|
37
|
-
}, {});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
8
|
export default {
|
|
41
9
|
/**
|
|
42
|
-
* Translates the input script to an
|
|
10
|
+
* Translates the input script to an output-script.
|
|
43
11
|
*
|
|
44
|
-
* @param {string} pScript
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* string with the rendered content if
|
|
49
|
-
* no callback was passed and no error was found
|
|
12
|
+
* @param {string|import("../types/state-machine-cat").IStateMachine} pScript
|
|
13
|
+
* The script to translate
|
|
14
|
+
* @param {import("../types/state-machine-cat").IRenderOptions} pOptions
|
|
15
|
+
* options influencing parsing & rendering.
|
|
50
16
|
* @throws {Error} if an error occurred and no callback
|
|
51
17
|
* function was passed: the error
|
|
52
18
|
*
|
|
@@ -54,13 +20,15 @@ export default {
|
|
|
54
20
|
*
|
|
55
21
|
*/
|
|
56
22
|
render(pScript, pOptions) {
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
const lDesugar = options.getOptionValue(lOptions, "desugar");
|
|
23
|
+
const lStateMachine = parse.getAST(pScript, pOptions);
|
|
24
|
+
const lDesugar = options.getOptionValue(pOptions, "desugar");
|
|
60
25
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
26
|
+
// @ts-expect-error should be cast to OutputTypeType - or the getOptionValue
|
|
27
|
+
// function should be refactored to be more explicit in type it returns
|
|
28
|
+
// when we ask for outputType
|
|
29
|
+
return getRenderFunction(options.getOptionValue(pOptions, "outputType"))(
|
|
30
|
+
lDesugar ? desugar(lStateMachine) : lStateMachine,
|
|
31
|
+
pOptions
|
|
64
32
|
);
|
|
65
33
|
},
|
|
66
34
|
|
|
@@ -79,7 +47,7 @@ export default {
|
|
|
79
47
|
* - the possible values in an array of objects, each of which
|
|
80
48
|
* has the properties:
|
|
81
49
|
* - name: the value
|
|
82
|
-
*
|
|
50
|
+
* @returns {import("../types/state-machine-cat").IAllowedValues}
|
|
83
51
|
*/
|
|
84
52
|
getAllowedValues() {
|
|
85
53
|
return options.getAllowedValues();
|
package/src/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/* eslint-disable budapestian/global-constant-pattern */
|
|
2
3
|
import options from "./options.mjs";
|
|
3
4
|
import parse from "./parse/index.mjs";
|
|
@@ -8,12 +9,11 @@ import { version as _version } from "./version.mjs";
|
|
|
8
9
|
/**
|
|
9
10
|
* Translates the input script to an output-script.
|
|
10
11
|
*
|
|
11
|
-
* @param {string} pScript
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* no callback was passed and no error was found
|
|
12
|
+
* @param {string|import("../types/state-machine-cat").IStateMachine} pScript
|
|
13
|
+
* The script to translate
|
|
14
|
+
* @param {import("../types/state-machine-cat").IRenderOptions} pOptions
|
|
15
|
+
* options influencing parsing & rendering.
|
|
16
|
+
* @return {string}
|
|
17
17
|
* @throws {Error} if an error occurred and no callback
|
|
18
18
|
* function was passed: the error
|
|
19
19
|
*
|
|
@@ -21,11 +21,11 @@ import { version as _version } from "./version.mjs";
|
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
23
|
export function render(pScript, pOptions) {
|
|
24
|
-
const
|
|
24
|
+
const lStateMachine = parse.getAST(pScript, pOptions);
|
|
25
25
|
const lDesugar = options.getOptionValue(pOptions, "desugar");
|
|
26
26
|
|
|
27
27
|
return getRenderFunction(options.getOptionValue(pOptions, "outputType"))(
|
|
28
|
-
lDesugar ? desugar(
|
|
28
|
+
lDesugar ? desugar(lStateMachine) : lStateMachine,
|
|
29
29
|
pOptions
|
|
30
30
|
);
|
|
31
31
|
}
|
|
@@ -45,7 +45,7 @@ export const version = _version;
|
|
|
45
45
|
* - the possible values in an array of objects, each of which
|
|
46
46
|
* has the properties:
|
|
47
47
|
* - name: the value
|
|
48
|
-
*
|
|
48
|
+
* @returns {import("../types/state-machine-cat").IAllowedValues}
|
|
49
49
|
*/
|
|
50
50
|
export function getAllowedValues() {
|
|
51
51
|
return options.getAllowedValues();
|