sfn-diagram 1.9.0 → 1.9.1
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/bin.js +60 -14
- package/dist/ci.cjs +13 -5
- package/dist/ci.js +13 -5
- package/dist/element-auto.cjs +13 -5
- package/dist/element-auto.js +13 -5
- package/dist/element.cjs +13 -5
- package/dist/element.js +13 -5
- package/dist/index.cjs +13 -5
- package/dist/index.js +13 -5
- package/dist/png.cjs +39 -3
- package/dist/png.d.cts +3 -1
- package/dist/png.d.ts +3 -1
- package/dist/png.js +39 -3
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -6,7 +6,7 @@ import { parse } from "yaml";
|
|
|
6
6
|
import dagre from "@dagrejs/dagre";
|
|
7
7
|
import { curveBasis, line } from "d3-shape";
|
|
8
8
|
import { minimatch } from "minimatch";
|
|
9
|
-
import { homedir } from "node:os";
|
|
9
|
+
import { homedir, totalmem } from "node:os";
|
|
10
10
|
import { execFileSync } from "node:child_process";
|
|
11
11
|
// src/config/withoutUndefined.ts
|
|
12
12
|
/**
|
|
@@ -2837,7 +2837,8 @@ function parseAsl(params) {
|
|
|
2837
2837
|
});
|
|
2838
2838
|
return {
|
|
2839
2839
|
edges: assignEdgeIds({ edges }),
|
|
2840
|
-
nodes
|
|
2840
|
+
nodes,
|
|
2841
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2841
2842
|
};
|
|
2842
2843
|
}
|
|
2843
2844
|
/**
|
|
@@ -9081,11 +9082,15 @@ ${playbackRules(palette)}
|
|
|
9081
9082
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
9082
9083
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
9083
9084
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
9084
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
9085
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
9086
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
9087
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
9088
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
9085
9089
|
*/
|
|
9086
9090
|
const MERMAID_LABEL_ENTITIES = {
|
|
9087
9091
|
"#": "#35;",
|
|
9088
9092
|
"\"": "#quot;",
|
|
9093
|
+
":": "#58;",
|
|
9089
9094
|
";": "#59;",
|
|
9090
9095
|
"<": "#60;",
|
|
9091
9096
|
">": "#62;",
|
|
@@ -9280,7 +9285,7 @@ var MermaidRenderer = class {
|
|
|
9280
9285
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
9281
9286
|
*/
|
|
9282
9287
|
escapeLabel(label) {
|
|
9283
|
-
return label.replace(/[#"
|
|
9288
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
9284
9289
|
}
|
|
9285
9290
|
/**
|
|
9286
9291
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -9356,10 +9361,13 @@ var MermaidRenderer = class {
|
|
|
9356
9361
|
/**
|
|
9357
9362
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
9358
9363
|
* first top-level state nothing else transitions to.
|
|
9364
|
+
*
|
|
9365
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
9366
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
9359
9367
|
*/
|
|
9360
9368
|
findStartState(params) {
|
|
9361
9369
|
const { asl, root } = params;
|
|
9362
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
9370
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
9363
9371
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
9364
9372
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
9365
9373
|
}
|
|
@@ -9880,7 +9888,7 @@ function buildDiagramGraph(params) {
|
|
|
9880
9888
|
edges: parsed.edges,
|
|
9881
9889
|
mode: options.catchHandling,
|
|
9882
9890
|
nodes: parsed.nodes,
|
|
9883
|
-
startStateId:
|
|
9891
|
+
startStateId: parsed.startId
|
|
9884
9892
|
});
|
|
9885
9893
|
return {
|
|
9886
9894
|
edges,
|
|
@@ -15086,6 +15094,33 @@ function resolvePngFontOptions(params) {
|
|
|
15086
15094
|
};
|
|
15087
15095
|
}
|
|
15088
15096
|
// src/exporters/resvgEngine.ts
|
|
15097
|
+
/** Bytes per pixel in resvg's RGBA output pixmap. */
|
|
15098
|
+
const PIXMAP_BYTES_PER_PIXEL = 4;
|
|
15099
|
+
/** Bytes in a GiB, for error messages. */
|
|
15100
|
+
const GIB = 2 ** 30;
|
|
15101
|
+
/**
|
|
15102
|
+
* Rounded intrinsic width below which {@link maxIntrinsicAspect} reads the exact size,
|
|
15103
|
+
* keeping the rounding bound within about 1% where it is used.
|
|
15104
|
+
*/
|
|
15105
|
+
const EXACT_SIZE_BELOW_WIDTH = 100;
|
|
15106
|
+
/**
|
|
15107
|
+
* The largest height-to-width ratio the SVG's intrinsic size can have, or 0 when it has
|
|
15108
|
+
* no width.
|
|
15109
|
+
*
|
|
15110
|
+
* resvg's `width` and `height` getters round to whole pixels, so each true side lies
|
|
15111
|
+
* within 0.5 of its getter and `(height + 0.5) / (width - 0.5)` bounds the true ratio
|
|
15112
|
+
* from above. That bound is loose for a narrow SVG (3x at 1 x 1) and missing when the
|
|
15113
|
+
* width rounds to 0, so below {@link EXACT_SIZE_BELOW_WIDTH} the exact size is read
|
|
15114
|
+
* from the serialized root element instead. Every SVG this package generates is wider.
|
|
15115
|
+
*/
|
|
15116
|
+
function maxIntrinsicAspect(params) {
|
|
15117
|
+
const { intrinsic } = params;
|
|
15118
|
+
if (intrinsic.width >= EXACT_SIZE_BELOW_WIDTH) return (intrinsic.height + .5) / (intrinsic.width - .5);
|
|
15119
|
+
const root = /<svg\b[^>]*>/.exec(intrinsic.toString())?.[0] ?? "";
|
|
15120
|
+
const exactWidth = Number(/\swidth="([^"]*)"/.exec(root)?.[1]);
|
|
15121
|
+
const exactHeight = Number(/\sheight="([^"]*)"/.exec(root)?.[1]);
|
|
15122
|
+
return exactWidth > 0 && exactHeight > 0 ? exactHeight / exactWidth : 0;
|
|
15123
|
+
}
|
|
15089
15124
|
/**
|
|
15090
15125
|
* Lazily load `@resvg/resvg-js`, which is an optional peer dependency. Keeping
|
|
15091
15126
|
* it out of the static import graph means SVG/Mermaid-only consumers never
|
|
@@ -15113,7 +15148,14 @@ async function loadResvg() {
|
|
|
15113
15148
|
async function renderResvgPng(params) {
|
|
15114
15149
|
const { backgroundColor, fontDirs, fontFamily, fontFiles, loadSystemFonts, preferredFamily, scale = 1, svg, width } = params;
|
|
15115
15150
|
if (!Number.isFinite(scale) || scale <= 0) throw new Error(`PNG export 'scale' must be a positive finite number, got ${scale}.`);
|
|
15116
|
-
const { renderAsync } = await loadResvg();
|
|
15151
|
+
const { Resvg, renderAsync } = await loadResvg();
|
|
15152
|
+
const aspect = maxIntrinsicAspect({ intrinsic: new Resvg(svg, { font: { loadSystemFonts: false } }) });
|
|
15153
|
+
const targetWidth = Math.round(width * scale);
|
|
15154
|
+
const targetHeight = Math.ceil(targetWidth * aspect);
|
|
15155
|
+
const pixmapBytes = targetWidth * targetHeight * PIXMAP_BYTES_PER_PIXEL;
|
|
15156
|
+
const constrained = process.constrainedMemory?.() ?? 0;
|
|
15157
|
+
const memoryBytes = constrained > 0 ? Math.min(constrained, totalmem()) : totalmem();
|
|
15158
|
+
if (pixmapBytes > memoryBytes) throw new Error(`PNG export is too large: at scale ${scale} the image would be ${targetWidth} x ${targetHeight} pixels, which needs ${(pixmapBytes / GIB).toFixed(1)} GiB of memory, more than the ${(memoryBytes / GIB).toFixed(1)} GiB available.${scale > 1 ? " Use a smaller scale." : ""}`);
|
|
15117
15159
|
const font = resolvePngFontOptions({
|
|
15118
15160
|
fontDirs,
|
|
15119
15161
|
fontFamily,
|
|
@@ -16214,7 +16256,7 @@ function isTerraformInput(params) {
|
|
|
16214
16256
|
* as Terraform. Extraction warnings go to stderr.
|
|
16215
16257
|
*/
|
|
16216
16258
|
function resolveDefinitionSource(params) {
|
|
16217
|
-
const { path, resolveCfn, resource, source } = params;
|
|
16259
|
+
const { path, reportWarnings, resolveCfn, resource, source } = params;
|
|
16218
16260
|
if (isTerraformInput({
|
|
16219
16261
|
path,
|
|
16220
16262
|
source
|
|
@@ -16223,7 +16265,7 @@ function resolveDefinitionSource(params) {
|
|
|
16223
16265
|
config: source,
|
|
16224
16266
|
resourceId: resource ?? void 0
|
|
16225
16267
|
});
|
|
16226
|
-
writeExtractionWarnings({ warnings });
|
|
16268
|
+
if (reportWarnings) writeExtractionWarnings({ warnings });
|
|
16227
16269
|
return aslDefinition;
|
|
16228
16270
|
}
|
|
16229
16271
|
if (!resolveCfn && !isCfnTemplate(source)) return source;
|
|
@@ -16231,7 +16273,7 @@ function resolveDefinitionSource(params) {
|
|
|
16231
16273
|
resourceId: resource ?? void 0,
|
|
16232
16274
|
template: source
|
|
16233
16275
|
});
|
|
16234
|
-
writeExtractionWarnings({ warnings });
|
|
16276
|
+
if (reportWarnings) writeExtractionWarnings({ warnings });
|
|
16235
16277
|
return aslDefinition;
|
|
16236
16278
|
}
|
|
16237
16279
|
/**
|
|
@@ -16502,7 +16544,7 @@ async function runCommentGitlab(argv) {
|
|
|
16502
16544
|
* not be read, parsed, rendered or written, or if `--check` found an error.
|
|
16503
16545
|
*/
|
|
16504
16546
|
async function renderOneInput(params) {
|
|
16505
|
-
const { args, baselineIsLive, baselineSource, cache, definitionText, historySource, labelInput, options, outputPath, source, theme, writeAtomically } = params;
|
|
16547
|
+
const { args, baselineIsLive, baselineSource, cache, definitionText, historySource, labelInput, options, outputPath, reportStatic, source, theme, writeAtomically } = params;
|
|
16506
16548
|
/** Write this render's output, honouring the atomic-write choice once. */
|
|
16507
16549
|
const emit = (content) => writeOutput({
|
|
16508
16550
|
atomic: writeAtomically,
|
|
@@ -16525,12 +16567,14 @@ async function renderOneInput(params) {
|
|
|
16525
16567
|
try {
|
|
16526
16568
|
definitionSource = resolveDefinitionSource({
|
|
16527
16569
|
path: source.kind === "file" ? source.path : null,
|
|
16570
|
+
reportWarnings: reportStatic,
|
|
16528
16571
|
resolveCfn: args.resolveCfn,
|
|
16529
16572
|
resource: args.resource,
|
|
16530
16573
|
source: aslSource
|
|
16531
16574
|
});
|
|
16532
16575
|
if (baselineSource !== null) baselineDefinition = resolveDefinitionSource({
|
|
16533
16576
|
path: baselineIsLive ? null : args.diff,
|
|
16577
|
+
reportWarnings: reportStatic,
|
|
16534
16578
|
resolveCfn: args.resolveCfn && !baselineIsLive,
|
|
16535
16579
|
resource: baselineIsLive ? null : args.resource,
|
|
16536
16580
|
source: baselineSource
|
|
@@ -16590,7 +16634,7 @@ async function renderOneInput(params) {
|
|
|
16590
16634
|
...redact ? { redact } : {},
|
|
16591
16635
|
...svgOptions
|
|
16592
16636
|
});
|
|
16593
|
-
if (result.metadata.diff) writeDiffSummary(result.metadata.diff);
|
|
16637
|
+
if (result.metadata.diff && reportStatic) writeDiffSummary(result.metadata.diff);
|
|
16594
16638
|
if (result.metadata.execution) writeExecutionSummary(result.metadata.execution);
|
|
16595
16639
|
emit(result.html);
|
|
16596
16640
|
return 0;
|
|
@@ -16603,7 +16647,7 @@ async function renderOneInput(params) {
|
|
|
16603
16647
|
layout: options.layout,
|
|
16604
16648
|
theme
|
|
16605
16649
|
});
|
|
16606
|
-
writeDiffSummary(result.metadata);
|
|
16650
|
+
if (reportStatic) writeDiffSummary(result.metadata);
|
|
16607
16651
|
emit(result.code);
|
|
16608
16652
|
return 0;
|
|
16609
16653
|
}
|
|
@@ -16612,7 +16656,7 @@ async function renderOneInput(params) {
|
|
|
16612
16656
|
before: baselineDefinition,
|
|
16613
16657
|
...svgOptions
|
|
16614
16658
|
});
|
|
16615
|
-
writeDiffSummary(result.metadata);
|
|
16659
|
+
if (reportStatic) writeDiffSummary(result.metadata);
|
|
16616
16660
|
emit(result.svg);
|
|
16617
16661
|
return 0;
|
|
16618
16662
|
}
|
|
@@ -17335,6 +17379,7 @@ async function renderResolvedBatch(params) {
|
|
|
17335
17379
|
labelInput,
|
|
17336
17380
|
options,
|
|
17337
17381
|
outputPath: item.outputPath,
|
|
17382
|
+
reportStatic: true,
|
|
17338
17383
|
source: item.source,
|
|
17339
17384
|
theme,
|
|
17340
17385
|
writeAtomically: false
|
|
@@ -17404,6 +17449,7 @@ async function runFollow(params) {
|
|
|
17404
17449
|
labelInput: false,
|
|
17405
17450
|
options,
|
|
17406
17451
|
outputPath,
|
|
17452
|
+
reportStatic: ticks === 1,
|
|
17407
17453
|
source,
|
|
17408
17454
|
theme,
|
|
17409
17455
|
writeAtomically: true
|
package/dist/ci.cjs
CHANGED
|
@@ -2690,7 +2690,8 @@ function parseAsl(params) {
|
|
|
2690
2690
|
});
|
|
2691
2691
|
return {
|
|
2692
2692
|
edges: assignEdgeIds({ edges }),
|
|
2693
|
-
nodes
|
|
2693
|
+
nodes,
|
|
2694
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2694
2695
|
};
|
|
2695
2696
|
}
|
|
2696
2697
|
/**
|
|
@@ -6043,11 +6044,15 @@ function resolveViewerTheme(params) {
|
|
|
6043
6044
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
6044
6045
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
6045
6046
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
6046
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
6047
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
6048
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
6049
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
6050
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
6047
6051
|
*/
|
|
6048
6052
|
const MERMAID_LABEL_ENTITIES = {
|
|
6049
6053
|
"#": "#35;",
|
|
6050
6054
|
"\"": "#quot;",
|
|
6055
|
+
":": "#58;",
|
|
6051
6056
|
";": "#59;",
|
|
6052
6057
|
"<": "#60;",
|
|
6053
6058
|
">": "#62;",
|
|
@@ -6242,7 +6247,7 @@ var MermaidRenderer = class {
|
|
|
6242
6247
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
6243
6248
|
*/
|
|
6244
6249
|
escapeLabel(label) {
|
|
6245
|
-
return label.replace(/[#"
|
|
6250
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
6246
6251
|
}
|
|
6247
6252
|
/**
|
|
6248
6253
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -6318,10 +6323,13 @@ var MermaidRenderer = class {
|
|
|
6318
6323
|
/**
|
|
6319
6324
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
6320
6325
|
* first top-level state nothing else transitions to.
|
|
6326
|
+
*
|
|
6327
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
6328
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
6321
6329
|
*/
|
|
6322
6330
|
findStartState(params) {
|
|
6323
6331
|
const { asl, root } = params;
|
|
6324
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
6332
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
6325
6333
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
6326
6334
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
6327
6335
|
}
|
|
@@ -6991,7 +6999,7 @@ function buildDiagramGraph(params) {
|
|
|
6991
6999
|
edges: parsed.edges,
|
|
6992
7000
|
mode: options.catchHandling,
|
|
6993
7001
|
nodes: parsed.nodes,
|
|
6994
|
-
startStateId:
|
|
7002
|
+
startStateId: parsed.startId
|
|
6995
7003
|
});
|
|
6996
7004
|
return {
|
|
6997
7005
|
edges,
|
package/dist/ci.js
CHANGED
|
@@ -2667,7 +2667,8 @@ function parseAsl(params) {
|
|
|
2667
2667
|
});
|
|
2668
2668
|
return {
|
|
2669
2669
|
edges: assignEdgeIds({ edges }),
|
|
2670
|
-
nodes
|
|
2670
|
+
nodes,
|
|
2671
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2671
2672
|
};
|
|
2672
2673
|
}
|
|
2673
2674
|
/**
|
|
@@ -6020,11 +6021,15 @@ function resolveViewerTheme(params) {
|
|
|
6020
6021
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
6021
6022
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
6022
6023
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
6023
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
6024
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
6025
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
6026
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
6027
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
6024
6028
|
*/
|
|
6025
6029
|
const MERMAID_LABEL_ENTITIES = {
|
|
6026
6030
|
"#": "#35;",
|
|
6027
6031
|
"\"": "#quot;",
|
|
6032
|
+
":": "#58;",
|
|
6028
6033
|
";": "#59;",
|
|
6029
6034
|
"<": "#60;",
|
|
6030
6035
|
">": "#62;",
|
|
@@ -6219,7 +6224,7 @@ var MermaidRenderer = class {
|
|
|
6219
6224
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
6220
6225
|
*/
|
|
6221
6226
|
escapeLabel(label) {
|
|
6222
|
-
return label.replace(/[#"
|
|
6227
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
6223
6228
|
}
|
|
6224
6229
|
/**
|
|
6225
6230
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -6295,10 +6300,13 @@ var MermaidRenderer = class {
|
|
|
6295
6300
|
/**
|
|
6296
6301
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
6297
6302
|
* first top-level state nothing else transitions to.
|
|
6303
|
+
*
|
|
6304
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
6305
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
6298
6306
|
*/
|
|
6299
6307
|
findStartState(params) {
|
|
6300
6308
|
const { asl, root } = params;
|
|
6301
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
6309
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
6302
6310
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
6303
6311
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
6304
6312
|
}
|
|
@@ -6968,7 +6976,7 @@ function buildDiagramGraph(params) {
|
|
|
6968
6976
|
edges: parsed.edges,
|
|
6969
6977
|
mode: options.catchHandling,
|
|
6970
6978
|
nodes: parsed.nodes,
|
|
6971
|
-
startStateId:
|
|
6979
|
+
startStateId: parsed.startId
|
|
6972
6980
|
});
|
|
6973
6981
|
return {
|
|
6974
6982
|
edges,
|
package/dist/element-auto.cjs
CHANGED
|
@@ -2851,7 +2851,8 @@ function parseAsl(params) {
|
|
|
2851
2851
|
});
|
|
2852
2852
|
return {
|
|
2853
2853
|
edges: assignEdgeIds({ edges }),
|
|
2854
|
-
nodes
|
|
2854
|
+
nodes,
|
|
2855
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2855
2856
|
};
|
|
2856
2857
|
}
|
|
2857
2858
|
/**
|
|
@@ -9214,11 +9215,15 @@ function buildMermaidScopes(params) {
|
|
|
9214
9215
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
9215
9216
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
9216
9217
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
9217
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
9218
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
9219
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
9220
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
9221
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
9218
9222
|
*/
|
|
9219
9223
|
const MERMAID_LABEL_ENTITIES = {
|
|
9220
9224
|
"#": "#35;",
|
|
9221
9225
|
"\"": "#quot;",
|
|
9226
|
+
":": "#58;",
|
|
9222
9227
|
";": "#59;",
|
|
9223
9228
|
"<": "#60;",
|
|
9224
9229
|
">": "#62;",
|
|
@@ -9413,7 +9418,7 @@ var MermaidRenderer = class {
|
|
|
9413
9418
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
9414
9419
|
*/
|
|
9415
9420
|
escapeLabel(label) {
|
|
9416
|
-
return label.replace(/[#"
|
|
9421
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
9417
9422
|
}
|
|
9418
9423
|
/**
|
|
9419
9424
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -9489,10 +9494,13 @@ var MermaidRenderer = class {
|
|
|
9489
9494
|
/**
|
|
9490
9495
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
9491
9496
|
* first top-level state nothing else transitions to.
|
|
9497
|
+
*
|
|
9498
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
9499
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
9492
9500
|
*/
|
|
9493
9501
|
findStartState(params) {
|
|
9494
9502
|
const { asl, root } = params;
|
|
9495
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
9503
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
9496
9504
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
9497
9505
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
9498
9506
|
}
|
|
@@ -10162,7 +10170,7 @@ function buildDiagramGraph(params) {
|
|
|
10162
10170
|
edges: parsed.edges,
|
|
10163
10171
|
mode: options.catchHandling,
|
|
10164
10172
|
nodes: parsed.nodes,
|
|
10165
|
-
startStateId:
|
|
10173
|
+
startStateId: parsed.startId
|
|
10166
10174
|
});
|
|
10167
10175
|
return {
|
|
10168
10176
|
edges,
|
package/dist/element-auto.js
CHANGED
|
@@ -2829,7 +2829,8 @@ function parseAsl(params) {
|
|
|
2829
2829
|
});
|
|
2830
2830
|
return {
|
|
2831
2831
|
edges: assignEdgeIds({ edges }),
|
|
2832
|
-
nodes
|
|
2832
|
+
nodes,
|
|
2833
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2833
2834
|
};
|
|
2834
2835
|
}
|
|
2835
2836
|
/**
|
|
@@ -9192,11 +9193,15 @@ function buildMermaidScopes(params) {
|
|
|
9192
9193
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
9193
9194
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
9194
9195
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
9195
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
9196
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
9197
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
9198
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
9199
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
9196
9200
|
*/
|
|
9197
9201
|
const MERMAID_LABEL_ENTITIES = {
|
|
9198
9202
|
"#": "#35;",
|
|
9199
9203
|
"\"": "#quot;",
|
|
9204
|
+
":": "#58;",
|
|
9200
9205
|
";": "#59;",
|
|
9201
9206
|
"<": "#60;",
|
|
9202
9207
|
">": "#62;",
|
|
@@ -9391,7 +9396,7 @@ var MermaidRenderer = class {
|
|
|
9391
9396
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
9392
9397
|
*/
|
|
9393
9398
|
escapeLabel(label) {
|
|
9394
|
-
return label.replace(/[#"
|
|
9399
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
9395
9400
|
}
|
|
9396
9401
|
/**
|
|
9397
9402
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -9467,10 +9472,13 @@ var MermaidRenderer = class {
|
|
|
9467
9472
|
/**
|
|
9468
9473
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
9469
9474
|
* first top-level state nothing else transitions to.
|
|
9475
|
+
*
|
|
9476
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
9477
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
9470
9478
|
*/
|
|
9471
9479
|
findStartState(params) {
|
|
9472
9480
|
const { asl, root } = params;
|
|
9473
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
9481
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
9474
9482
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
9475
9483
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
9476
9484
|
}
|
|
@@ -10140,7 +10148,7 @@ function buildDiagramGraph(params) {
|
|
|
10140
10148
|
edges: parsed.edges,
|
|
10141
10149
|
mode: options.catchHandling,
|
|
10142
10150
|
nodes: parsed.nodes,
|
|
10143
|
-
startStateId:
|
|
10151
|
+
startStateId: parsed.startId
|
|
10144
10152
|
});
|
|
10145
10153
|
return {
|
|
10146
10154
|
edges,
|
package/dist/element.cjs
CHANGED
|
@@ -2852,7 +2852,8 @@ function parseAsl(params) {
|
|
|
2852
2852
|
});
|
|
2853
2853
|
return {
|
|
2854
2854
|
edges: assignEdgeIds({ edges }),
|
|
2855
|
-
nodes
|
|
2855
|
+
nodes,
|
|
2856
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2856
2857
|
};
|
|
2857
2858
|
}
|
|
2858
2859
|
/**
|
|
@@ -9215,11 +9216,15 @@ function buildMermaidScopes(params) {
|
|
|
9215
9216
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
9216
9217
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
9217
9218
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
9218
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
9219
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
9220
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
9221
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
9222
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
9219
9223
|
*/
|
|
9220
9224
|
const MERMAID_LABEL_ENTITIES = {
|
|
9221
9225
|
"#": "#35;",
|
|
9222
9226
|
"\"": "#quot;",
|
|
9227
|
+
":": "#58;",
|
|
9223
9228
|
";": "#59;",
|
|
9224
9229
|
"<": "#60;",
|
|
9225
9230
|
">": "#62;",
|
|
@@ -9414,7 +9419,7 @@ var MermaidRenderer = class {
|
|
|
9414
9419
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
9415
9420
|
*/
|
|
9416
9421
|
escapeLabel(label) {
|
|
9417
|
-
return label.replace(/[#"
|
|
9422
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
9418
9423
|
}
|
|
9419
9424
|
/**
|
|
9420
9425
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -9490,10 +9495,13 @@ var MermaidRenderer = class {
|
|
|
9490
9495
|
/**
|
|
9491
9496
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
9492
9497
|
* first top-level state nothing else transitions to.
|
|
9498
|
+
*
|
|
9499
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
9500
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
9493
9501
|
*/
|
|
9494
9502
|
findStartState(params) {
|
|
9495
9503
|
const { asl, root } = params;
|
|
9496
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
9504
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
9497
9505
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
9498
9506
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
9499
9507
|
}
|
|
@@ -10163,7 +10171,7 @@ function buildDiagramGraph(params) {
|
|
|
10163
10171
|
edges: parsed.edges,
|
|
10164
10172
|
mode: options.catchHandling,
|
|
10165
10173
|
nodes: parsed.nodes,
|
|
10166
|
-
startStateId:
|
|
10174
|
+
startStateId: parsed.startId
|
|
10167
10175
|
});
|
|
10168
10176
|
return {
|
|
10169
10177
|
edges,
|
package/dist/element.js
CHANGED
|
@@ -2829,7 +2829,8 @@ function parseAsl(params) {
|
|
|
2829
2829
|
});
|
|
2830
2830
|
return {
|
|
2831
2831
|
edges: assignEdgeIds({ edges }),
|
|
2832
|
-
nodes
|
|
2832
|
+
nodes,
|
|
2833
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2833
2834
|
};
|
|
2834
2835
|
}
|
|
2835
2836
|
/**
|
|
@@ -9192,11 +9193,15 @@ function buildMermaidScopes(params) {
|
|
|
9192
9193
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
9193
9194
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
9194
9195
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
9195
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
9196
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
9197
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
9198
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
9199
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
9196
9200
|
*/
|
|
9197
9201
|
const MERMAID_LABEL_ENTITIES = {
|
|
9198
9202
|
"#": "#35;",
|
|
9199
9203
|
"\"": "#quot;",
|
|
9204
|
+
":": "#58;",
|
|
9200
9205
|
";": "#59;",
|
|
9201
9206
|
"<": "#60;",
|
|
9202
9207
|
">": "#62;",
|
|
@@ -9391,7 +9396,7 @@ var MermaidRenderer = class {
|
|
|
9391
9396
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
9392
9397
|
*/
|
|
9393
9398
|
escapeLabel(label) {
|
|
9394
|
-
return label.replace(/[#"
|
|
9399
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
9395
9400
|
}
|
|
9396
9401
|
/**
|
|
9397
9402
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -9467,10 +9472,13 @@ var MermaidRenderer = class {
|
|
|
9467
9472
|
/**
|
|
9468
9473
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
9469
9474
|
* first top-level state nothing else transitions to.
|
|
9475
|
+
*
|
|
9476
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
9477
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
9470
9478
|
*/
|
|
9471
9479
|
findStartState(params) {
|
|
9472
9480
|
const { asl, root } = params;
|
|
9473
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
9481
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
9474
9482
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
9475
9483
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
9476
9484
|
}
|
|
@@ -10140,7 +10148,7 @@ function buildDiagramGraph(params) {
|
|
|
10140
10148
|
edges: parsed.edges,
|
|
10141
10149
|
mode: options.catchHandling,
|
|
10142
10150
|
nodes: parsed.nodes,
|
|
10143
|
-
startStateId:
|
|
10151
|
+
startStateId: parsed.startId
|
|
10144
10152
|
});
|
|
10145
10153
|
return {
|
|
10146
10154
|
edges,
|
package/dist/index.cjs
CHANGED
|
@@ -2878,7 +2878,8 @@ function parseAsl(params) {
|
|
|
2878
2878
|
});
|
|
2879
2879
|
return {
|
|
2880
2880
|
edges: assignEdgeIds({ edges }),
|
|
2881
|
-
nodes
|
|
2881
|
+
nodes,
|
|
2882
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2882
2883
|
};
|
|
2883
2884
|
}
|
|
2884
2885
|
/**
|
|
@@ -6604,11 +6605,15 @@ ${playbackRules(palette)}
|
|
|
6604
6605
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
6605
6606
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
6606
6607
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
6607
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
6608
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
6609
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
6610
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
6611
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
6608
6612
|
*/
|
|
6609
6613
|
const MERMAID_LABEL_ENTITIES = {
|
|
6610
6614
|
"#": "#35;",
|
|
6611
6615
|
"\"": "#quot;",
|
|
6616
|
+
":": "#58;",
|
|
6612
6617
|
";": "#59;",
|
|
6613
6618
|
"<": "#60;",
|
|
6614
6619
|
">": "#62;",
|
|
@@ -6803,7 +6808,7 @@ var MermaidRenderer = class {
|
|
|
6803
6808
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
6804
6809
|
*/
|
|
6805
6810
|
escapeLabel(label) {
|
|
6806
|
-
return label.replace(/[#"
|
|
6811
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
6807
6812
|
}
|
|
6808
6813
|
/**
|
|
6809
6814
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -6879,10 +6884,13 @@ var MermaidRenderer = class {
|
|
|
6879
6884
|
/**
|
|
6880
6885
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
6881
6886
|
* first top-level state nothing else transitions to.
|
|
6887
|
+
*
|
|
6888
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
6889
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
6882
6890
|
*/
|
|
6883
6891
|
findStartState(params) {
|
|
6884
6892
|
const { asl, root } = params;
|
|
6885
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
6893
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
6886
6894
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
6887
6895
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
6888
6896
|
}
|
|
@@ -8308,7 +8316,7 @@ function buildDiagramGraph(params) {
|
|
|
8308
8316
|
edges: parsed.edges,
|
|
8309
8317
|
mode: options.catchHandling,
|
|
8310
8318
|
nodes: parsed.nodes,
|
|
8311
|
-
startStateId:
|
|
8319
|
+
startStateId: parsed.startId
|
|
8312
8320
|
});
|
|
8313
8321
|
return {
|
|
8314
8322
|
edges,
|
package/dist/index.js
CHANGED
|
@@ -2855,7 +2855,8 @@ function parseAsl(params) {
|
|
|
2855
2855
|
});
|
|
2856
2856
|
return {
|
|
2857
2857
|
edges: assignEdgeIds({ edges }),
|
|
2858
|
-
nodes
|
|
2858
|
+
nodes,
|
|
2859
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2859
2860
|
};
|
|
2860
2861
|
}
|
|
2861
2862
|
/**
|
|
@@ -6581,11 +6582,15 @@ ${playbackRules(palette)}
|
|
|
6581
6582
|
* Mermaid numeric-entity escapes for characters that are significant to
|
|
6582
6583
|
* `stateDiagram-v2` syntax: `#` introduces an entity itself, `"` and `;` end a
|
|
6583
6584
|
* label or statement early, `<`/`>` and `{`/`}` are HTML/composite-state
|
|
6584
|
-
* syntax, and a backtick can break Markdown-flavoured label rendering.
|
|
6585
|
+
* syntax, and a backtick can break Markdown-flavoured label rendering. Mermaid
|
|
6586
|
+
* up to at least 11.4.1 also rejects a `:` inside a state description or an
|
|
6587
|
+
* edge label (`A: Rejected (error: X)`), and renderers that bundle an older
|
|
6588
|
+
* Mermaid (a self-managed GitLab, an editor preview) are still in use.
|
|
6585
6589
|
*/
|
|
6586
6590
|
const MERMAID_LABEL_ENTITIES = {
|
|
6587
6591
|
"#": "#35;",
|
|
6588
6592
|
"\"": "#quot;",
|
|
6593
|
+
":": "#58;",
|
|
6589
6594
|
";": "#59;",
|
|
6590
6595
|
"<": "#60;",
|
|
6591
6596
|
">": "#62;",
|
|
@@ -6780,7 +6785,7 @@ var MermaidRenderer = class {
|
|
|
6780
6785
|
* a literal `-->` inside a label, so no separate arrow rule is needed.
|
|
6781
6786
|
*/
|
|
6782
6787
|
escapeLabel(label) {
|
|
6783
|
-
return label.replace(/[#"
|
|
6788
|
+
return label.replace(/[#":;<>{}`]/g, (character) => MERMAID_LABEL_ENTITIES[character]).replace(/\n/g, " ");
|
|
6784
6789
|
}
|
|
6785
6790
|
/**
|
|
6786
6791
|
* Build the lines of one scope: its `[*]` entry, state label lines, nested
|
|
@@ -6856,10 +6861,13 @@ var MermaidRenderer = class {
|
|
|
6856
6861
|
/**
|
|
6857
6862
|
* Find the start state from the ASL definition's StartAt or, without one, the
|
|
6858
6863
|
* first top-level state nothing else transitions to.
|
|
6864
|
+
*
|
|
6865
|
+
* StartAt is resolved to a node id the way the parser resolved it, because the id
|
|
6866
|
+
* can differ from the name (a sanitized character, or a discriminator).
|
|
6859
6867
|
*/
|
|
6860
6868
|
findStartState(params) {
|
|
6861
6869
|
const { asl, root } = params;
|
|
6862
|
-
if (asl?.StartAt) return asl.StartAt;
|
|
6870
|
+
if (asl?.StartAt) return buildIdResolver({ definition: asl }).resolve("", asl.StartAt);
|
|
6863
6871
|
const targetIds = new Set(root.transitions.filter((edge) => edge.from !== edge.to).map((edge) => edge.to));
|
|
6864
6872
|
return root.memberIds.find((id) => !targetIds.has(id)) ?? root.memberIds[0];
|
|
6865
6873
|
}
|
|
@@ -8285,7 +8293,7 @@ function buildDiagramGraph(params) {
|
|
|
8285
8293
|
edges: parsed.edges,
|
|
8286
8294
|
mode: options.catchHandling,
|
|
8287
8295
|
nodes: parsed.nodes,
|
|
8288
|
-
startStateId:
|
|
8296
|
+
startStateId: parsed.startId
|
|
8289
8297
|
});
|
|
8290
8298
|
return {
|
|
8291
8299
|
edges,
|
package/dist/png.cjs
CHANGED
|
@@ -23,6 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
let d3_shape = require("d3-shape");
|
|
24
24
|
let _dagrejs_dagre = require("@dagrejs/dagre");
|
|
25
25
|
_dagrejs_dagre = __toESM(_dagrejs_dagre, 1);
|
|
26
|
+
let node_os = require("node:os");
|
|
26
27
|
let node_fs = require("node:fs");
|
|
27
28
|
let node_path = require("node:path");
|
|
28
29
|
// src/config/withoutUndefined.ts
|
|
@@ -2634,7 +2635,8 @@ function parseAsl(params) {
|
|
|
2634
2635
|
});
|
|
2635
2636
|
return {
|
|
2636
2637
|
edges: assignEdgeIds({ edges }),
|
|
2637
|
-
nodes
|
|
2638
|
+
nodes,
|
|
2639
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2638
2640
|
};
|
|
2639
2641
|
}
|
|
2640
2642
|
/**
|
|
@@ -6337,7 +6339,7 @@ function buildDiagramGraph(params) {
|
|
|
6337
6339
|
edges: parsed.edges,
|
|
6338
6340
|
mode: options.catchHandling,
|
|
6339
6341
|
nodes: parsed.nodes,
|
|
6340
|
-
startStateId:
|
|
6342
|
+
startStateId: parsed.startId
|
|
6341
6343
|
});
|
|
6342
6344
|
return {
|
|
6343
6345
|
edges,
|
|
@@ -7330,6 +7332,33 @@ function resolvePngFontOptions(params) {
|
|
|
7330
7332
|
};
|
|
7331
7333
|
}
|
|
7332
7334
|
// src/exporters/resvgEngine.ts
|
|
7335
|
+
/** Bytes per pixel in resvg's RGBA output pixmap. */
|
|
7336
|
+
const PIXMAP_BYTES_PER_PIXEL = 4;
|
|
7337
|
+
/** Bytes in a GiB, for error messages. */
|
|
7338
|
+
const GIB = 2 ** 30;
|
|
7339
|
+
/**
|
|
7340
|
+
* Rounded intrinsic width below which {@link maxIntrinsicAspect} reads the exact size,
|
|
7341
|
+
* keeping the rounding bound within about 1% where it is used.
|
|
7342
|
+
*/
|
|
7343
|
+
const EXACT_SIZE_BELOW_WIDTH = 100;
|
|
7344
|
+
/**
|
|
7345
|
+
* The largest height-to-width ratio the SVG's intrinsic size can have, or 0 when it has
|
|
7346
|
+
* no width.
|
|
7347
|
+
*
|
|
7348
|
+
* resvg's `width` and `height` getters round to whole pixels, so each true side lies
|
|
7349
|
+
* within 0.5 of its getter and `(height + 0.5) / (width - 0.5)` bounds the true ratio
|
|
7350
|
+
* from above. That bound is loose for a narrow SVG (3x at 1 x 1) and missing when the
|
|
7351
|
+
* width rounds to 0, so below {@link EXACT_SIZE_BELOW_WIDTH} the exact size is read
|
|
7352
|
+
* from the serialized root element instead. Every SVG this package generates is wider.
|
|
7353
|
+
*/
|
|
7354
|
+
function maxIntrinsicAspect(params) {
|
|
7355
|
+
const { intrinsic } = params;
|
|
7356
|
+
if (intrinsic.width >= EXACT_SIZE_BELOW_WIDTH) return (intrinsic.height + .5) / (intrinsic.width - .5);
|
|
7357
|
+
const root = /<svg\b[^>]*>/.exec(intrinsic.toString())?.[0] ?? "";
|
|
7358
|
+
const exactWidth = Number(/\swidth="([^"]*)"/.exec(root)?.[1]);
|
|
7359
|
+
const exactHeight = Number(/\sheight="([^"]*)"/.exec(root)?.[1]);
|
|
7360
|
+
return exactWidth > 0 && exactHeight > 0 ? exactHeight / exactWidth : 0;
|
|
7361
|
+
}
|
|
7333
7362
|
/**
|
|
7334
7363
|
* Lazily load `@resvg/resvg-js`, which is an optional peer dependency. Keeping
|
|
7335
7364
|
* it out of the static import graph means SVG/Mermaid-only consumers never
|
|
@@ -7357,7 +7386,14 @@ async function loadResvg() {
|
|
|
7357
7386
|
async function renderResvgPng(params) {
|
|
7358
7387
|
const { backgroundColor, fontDirs, fontFamily, fontFiles, loadSystemFonts, preferredFamily, scale = 1, svg, width } = params;
|
|
7359
7388
|
if (!Number.isFinite(scale) || scale <= 0) throw new Error(`PNG export 'scale' must be a positive finite number, got ${scale}.`);
|
|
7360
|
-
const { renderAsync } = await loadResvg();
|
|
7389
|
+
const { Resvg, renderAsync } = await loadResvg();
|
|
7390
|
+
const aspect = maxIntrinsicAspect({ intrinsic: new Resvg(svg, { font: { loadSystemFonts: false } }) });
|
|
7391
|
+
const targetWidth = Math.round(width * scale);
|
|
7392
|
+
const targetHeight = Math.ceil(targetWidth * aspect);
|
|
7393
|
+
const pixmapBytes = targetWidth * targetHeight * PIXMAP_BYTES_PER_PIXEL;
|
|
7394
|
+
const constrained = process.constrainedMemory?.() ?? 0;
|
|
7395
|
+
const memoryBytes = constrained > 0 ? Math.min(constrained, (0, node_os.totalmem)()) : (0, node_os.totalmem)();
|
|
7396
|
+
if (pixmapBytes > memoryBytes) throw new Error(`PNG export is too large: at scale ${scale} the image would be ${targetWidth} x ${targetHeight} pixels, which needs ${(pixmapBytes / GIB).toFixed(1)} GiB of memory, more than the ${(memoryBytes / GIB).toFixed(1)} GiB available.${scale > 1 ? " Use a smaller scale." : ""}`);
|
|
7361
7397
|
const font = resolvePngFontOptions({
|
|
7362
7398
|
fontDirs,
|
|
7363
7399
|
fontFamily,
|
package/dist/png.d.cts
CHANGED
|
@@ -779,7 +779,9 @@ interface PngExportOptions {
|
|
|
779
779
|
loadSystemFonts?: boolean;
|
|
780
780
|
/**
|
|
781
781
|
* Multiplier applied to the diagram's rendered size. `resvg` only. Must be a
|
|
782
|
-
* positive finite number; anything else throws.
|
|
782
|
+
* positive finite number; anything else throws. Also throws when the resulting
|
|
783
|
+
* image would need more memory than the process can have (the machine's, or a
|
|
784
|
+
* container's limit), since resvg would otherwise abort the process.
|
|
783
785
|
* @default 1
|
|
784
786
|
*/
|
|
785
787
|
scale?: number;
|
package/dist/png.d.ts
CHANGED
|
@@ -779,7 +779,9 @@ interface PngExportOptions {
|
|
|
779
779
|
loadSystemFonts?: boolean;
|
|
780
780
|
/**
|
|
781
781
|
* Multiplier applied to the diagram's rendered size. `resvg` only. Must be a
|
|
782
|
-
* positive finite number; anything else throws.
|
|
782
|
+
* positive finite number; anything else throws. Also throws when the resulting
|
|
783
|
+
* image would need more memory than the process can have (the machine's, or a
|
|
784
|
+
* container's limit), since resvg would otherwise abort the process.
|
|
783
785
|
* @default 1
|
|
784
786
|
*/
|
|
785
787
|
scale?: number;
|
package/dist/png.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { curveBasis, line } from "d3-shape";
|
|
2
2
|
import dagre from "@dagrejs/dagre";
|
|
3
|
+
import { totalmem } from "node:os";
|
|
3
4
|
import { closeSync, fstatSync, openSync, readSync, readdirSync, statSync } from "node:fs";
|
|
4
5
|
import { delimiter, join } from "node:path";
|
|
5
6
|
// src/config/withoutUndefined.ts
|
|
@@ -2611,7 +2612,8 @@ function parseAsl(params) {
|
|
|
2611
2612
|
});
|
|
2612
2613
|
return {
|
|
2613
2614
|
edges: assignEdgeIds({ edges }),
|
|
2614
|
-
nodes
|
|
2615
|
+
nodes,
|
|
2616
|
+
startId: resolver.resolve("", definition.StartAt)
|
|
2615
2617
|
};
|
|
2616
2618
|
}
|
|
2617
2619
|
/**
|
|
@@ -6314,7 +6316,7 @@ function buildDiagramGraph(params) {
|
|
|
6314
6316
|
edges: parsed.edges,
|
|
6315
6317
|
mode: options.catchHandling,
|
|
6316
6318
|
nodes: parsed.nodes,
|
|
6317
|
-
startStateId:
|
|
6319
|
+
startStateId: parsed.startId
|
|
6318
6320
|
});
|
|
6319
6321
|
return {
|
|
6320
6322
|
edges,
|
|
@@ -7307,6 +7309,33 @@ function resolvePngFontOptions(params) {
|
|
|
7307
7309
|
};
|
|
7308
7310
|
}
|
|
7309
7311
|
// src/exporters/resvgEngine.ts
|
|
7312
|
+
/** Bytes per pixel in resvg's RGBA output pixmap. */
|
|
7313
|
+
const PIXMAP_BYTES_PER_PIXEL = 4;
|
|
7314
|
+
/** Bytes in a GiB, for error messages. */
|
|
7315
|
+
const GIB = 2 ** 30;
|
|
7316
|
+
/**
|
|
7317
|
+
* Rounded intrinsic width below which {@link maxIntrinsicAspect} reads the exact size,
|
|
7318
|
+
* keeping the rounding bound within about 1% where it is used.
|
|
7319
|
+
*/
|
|
7320
|
+
const EXACT_SIZE_BELOW_WIDTH = 100;
|
|
7321
|
+
/**
|
|
7322
|
+
* The largest height-to-width ratio the SVG's intrinsic size can have, or 0 when it has
|
|
7323
|
+
* no width.
|
|
7324
|
+
*
|
|
7325
|
+
* resvg's `width` and `height` getters round to whole pixels, so each true side lies
|
|
7326
|
+
* within 0.5 of its getter and `(height + 0.5) / (width - 0.5)` bounds the true ratio
|
|
7327
|
+
* from above. That bound is loose for a narrow SVG (3x at 1 x 1) and missing when the
|
|
7328
|
+
* width rounds to 0, so below {@link EXACT_SIZE_BELOW_WIDTH} the exact size is read
|
|
7329
|
+
* from the serialized root element instead. Every SVG this package generates is wider.
|
|
7330
|
+
*/
|
|
7331
|
+
function maxIntrinsicAspect(params) {
|
|
7332
|
+
const { intrinsic } = params;
|
|
7333
|
+
if (intrinsic.width >= EXACT_SIZE_BELOW_WIDTH) return (intrinsic.height + .5) / (intrinsic.width - .5);
|
|
7334
|
+
const root = /<svg\b[^>]*>/.exec(intrinsic.toString())?.[0] ?? "";
|
|
7335
|
+
const exactWidth = Number(/\swidth="([^"]*)"/.exec(root)?.[1]);
|
|
7336
|
+
const exactHeight = Number(/\sheight="([^"]*)"/.exec(root)?.[1]);
|
|
7337
|
+
return exactWidth > 0 && exactHeight > 0 ? exactHeight / exactWidth : 0;
|
|
7338
|
+
}
|
|
7310
7339
|
/**
|
|
7311
7340
|
* Lazily load `@resvg/resvg-js`, which is an optional peer dependency. Keeping
|
|
7312
7341
|
* it out of the static import graph means SVG/Mermaid-only consumers never
|
|
@@ -7334,7 +7363,14 @@ async function loadResvg() {
|
|
|
7334
7363
|
async function renderResvgPng(params) {
|
|
7335
7364
|
const { backgroundColor, fontDirs, fontFamily, fontFiles, loadSystemFonts, preferredFamily, scale = 1, svg, width } = params;
|
|
7336
7365
|
if (!Number.isFinite(scale) || scale <= 0) throw new Error(`PNG export 'scale' must be a positive finite number, got ${scale}.`);
|
|
7337
|
-
const { renderAsync } = await loadResvg();
|
|
7366
|
+
const { Resvg, renderAsync } = await loadResvg();
|
|
7367
|
+
const aspect = maxIntrinsicAspect({ intrinsic: new Resvg(svg, { font: { loadSystemFonts: false } }) });
|
|
7368
|
+
const targetWidth = Math.round(width * scale);
|
|
7369
|
+
const targetHeight = Math.ceil(targetWidth * aspect);
|
|
7370
|
+
const pixmapBytes = targetWidth * targetHeight * PIXMAP_BYTES_PER_PIXEL;
|
|
7371
|
+
const constrained = process.constrainedMemory?.() ?? 0;
|
|
7372
|
+
const memoryBytes = constrained > 0 ? Math.min(constrained, totalmem()) : totalmem();
|
|
7373
|
+
if (pixmapBytes > memoryBytes) throw new Error(`PNG export is too large: at scale ${scale} the image would be ${targetWidth} x ${targetHeight} pixels, which needs ${(pixmapBytes / GIB).toFixed(1)} GiB of memory, more than the ${(memoryBytes / GIB).toFixed(1)} GiB available.${scale > 1 ? " Use a smaller scale." : ""}`);
|
|
7338
7374
|
const font = resolvePngFontOptions({
|
|
7339
7375
|
fontDirs,
|
|
7340
7376
|
fontFamily,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sfn-diagram",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Generate SVG, Mermaid, HTML, and PNG diagrams from AWS Step Functions ASL definitions, CloudFormation/CDK templates, Terraform configs, or live AWS state machines",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@9.15.9",
|