schematex 0.6.0 → 0.6.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/ai/ai-sdk.cjs +9 -9
- package/dist/ai/ai-sdk.d.cts +4 -4
- package/dist/ai/ai-sdk.d.ts +4 -4
- package/dist/ai/ai-sdk.js +4 -4
- package/dist/ai/index.cjs +15 -15
- package/dist/ai/index.d.cts +3 -3
- package/dist/ai/index.d.ts +3 -3
- package/dist/ai/index.js +4 -4
- package/dist/{api-qVDutqXH.d.cts → api-BEJTXyBA.d.cts} +1 -1
- package/dist/{api-XWHHAhQI.d.ts → api-DFrSR3lw.d.ts} +1 -1
- package/dist/browser.cjs +10 -10
- package/dist/browser.d.cts +3 -3
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +4 -4
- package/dist/{chunk-25ZON47K.cjs → chunk-4XR7X7XW.cjs} +96 -26
- package/dist/chunk-4XR7X7XW.cjs.map +1 -0
- package/dist/{chunk-LGABFD3L.js → chunk-522WB2EH.js} +2 -2
- package/dist/{chunk-LGABFD3L.js.map → chunk-522WB2EH.js.map} +1 -1
- package/dist/{chunk-7AFW2J6J.js → chunk-I2GQYOZ5.js} +94 -24
- package/dist/chunk-I2GQYOZ5.js.map +1 -0
- package/dist/{chunk-EPKIJEH7.js → chunk-MFAMNFPA.js} +63 -6
- package/dist/chunk-MFAMNFPA.js.map +1 -0
- package/dist/{chunk-P63S7P6N.js → chunk-OTSVMKII.js} +116 -3
- package/dist/chunk-OTSVMKII.js.map +1 -0
- package/dist/{chunk-ECD5XHBM.cjs → chunk-R6VX5YTJ.cjs} +2 -2
- package/dist/{chunk-ECD5XHBM.cjs.map → chunk-R6VX5YTJ.cjs.map} +1 -1
- package/dist/{chunk-YVDUEUFV.cjs → chunk-SSLNPHCL.cjs} +118 -5
- package/dist/chunk-SSLNPHCL.cjs.map +1 -0
- package/dist/{chunk-SUIDD2C5.cjs → chunk-XNCOSVNG.cjs} +63 -6
- package/dist/chunk-XNCOSVNG.cjs.map +1 -0
- package/dist/{diagnostics-DRxhodP6.d.ts → diagnostics-B-ffSEhl.d.cts} +8 -0
- package/dist/{diagnostics-DRxhodP6.d.cts → diagnostics-B-ffSEhl.d.ts} +8 -0
- package/dist/diagrams/blockdiagram/index.cjs +5 -5
- package/dist/diagrams/blockdiagram/index.d.cts +1 -1
- package/dist/diagrams/blockdiagram/index.d.ts +1 -1
- package/dist/diagrams/blockdiagram/index.js +1 -1
- package/dist/diagrams/circuit/index.d.cts +1 -1
- package/dist/diagrams/circuit/index.d.ts +1 -1
- package/dist/diagrams/ecomap/index.d.cts +1 -1
- package/dist/diagrams/ecomap/index.d.ts +1 -1
- package/dist/diagrams/entity/index.d.cts +1 -1
- package/dist/diagrams/entity/index.d.ts +1 -1
- package/dist/diagrams/fishbone/index.d.cts +1 -1
- package/dist/diagrams/fishbone/index.d.ts +1 -1
- package/dist/diagrams/flowchart/index.d.cts +2 -2
- package/dist/diagrams/flowchart/index.d.ts +2 -2
- package/dist/diagrams/genogram/index.d.cts +1 -1
- package/dist/diagrams/genogram/index.d.ts +1 -1
- package/dist/diagrams/ladder/index.d.cts +1 -1
- package/dist/diagrams/ladder/index.d.ts +1 -1
- package/dist/diagrams/logic/index.d.cts +1 -1
- package/dist/diagrams/logic/index.d.ts +1 -1
- package/dist/diagrams/orgchart/index.d.cts +1 -1
- package/dist/diagrams/orgchart/index.d.ts +1 -1
- package/dist/diagrams/pedigree/index.d.cts +1 -1
- package/dist/diagrams/pedigree/index.d.ts +1 -1
- package/dist/diagrams/phylo/index.d.cts +1 -1
- package/dist/diagrams/phylo/index.d.ts +1 -1
- package/dist/diagrams/sld/index.cjs +7 -7
- package/dist/diagrams/sld/index.d.cts +1 -1
- package/dist/diagrams/sld/index.d.ts +1 -1
- package/dist/diagrams/sld/index.js +1 -1
- package/dist/diagrams/sociogram/index.d.cts +1 -1
- package/dist/diagrams/sociogram/index.d.ts +1 -1
- package/dist/diagrams/timing/index.d.cts +1 -1
- package/dist/diagrams/timing/index.d.ts +1 -1
- package/dist/diagrams/venn/index.d.cts +1 -1
- package/dist/diagrams/venn/index.d.ts +1 -1
- package/dist/{index-C7SN-FB3.d.ts → index-DPWdYfNx.d.ts} +1 -1
- package/dist/{index-BRIkOPnd.d.cts → index-S0njakQ2.d.cts} +1 -1
- package/dist/index.cjs +26 -26
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +5 -5
- package/dist/react.cjs +4 -4
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +3 -3
- package/dist/{tools-DdhP1kWY.d.cts → tools-CeGGMCs7.d.cts} +2 -2
- package/dist/{tools-BVeUNdsU.d.ts → tools-kK_enDwb.d.ts} +2 -2
- package/package.json +1 -1
- package/dist/chunk-25ZON47K.cjs.map +0 -1
- package/dist/chunk-7AFW2J6J.js.map +0 -1
- package/dist/chunk-EPKIJEH7.js.map +0 -1
- package/dist/chunk-P63S7P6N.js.map +0 -1
- package/dist/chunk-SUIDD2C5.cjs.map +0 -1
- package/dist/chunk-YVDUEUFV.cjs.map +0 -1
|
@@ -216,6 +216,7 @@ function parseBlockDiagram(text2) {
|
|
|
216
216
|
title: title2,
|
|
217
217
|
blocks,
|
|
218
218
|
sums,
|
|
219
|
+
signals: Array.from(signals.values()),
|
|
219
220
|
connections
|
|
220
221
|
};
|
|
221
222
|
}
|
|
@@ -230,6 +231,45 @@ var FIRST_ROW_OFFSET = 110;
|
|
|
230
231
|
var COL_GAP = 60;
|
|
231
232
|
var LEFT_PAD = 30;
|
|
232
233
|
var RIGHT_PAD = 30;
|
|
234
|
+
function approxTextWidth(text2, pxPerChar = 7) {
|
|
235
|
+
return text2.length * pxPerChar;
|
|
236
|
+
}
|
|
237
|
+
function extendPathBounds(path2, bounds) {
|
|
238
|
+
const nums = path2.match(/-?\d+(?:\.\d+)?/g)?.map(Number) ?? [];
|
|
239
|
+
for (let i = 0; i < nums.length - 1; i += 2) {
|
|
240
|
+
bounds.maxX = Math.max(bounds.maxX, nums[i] ?? 0);
|
|
241
|
+
bounds.maxY = Math.max(bounds.maxY, nums[i + 1] ?? 0);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function estimateContentBounds(nodes, edges) {
|
|
245
|
+
const bounds = { maxX: 0, maxY: 0 };
|
|
246
|
+
for (const n of nodes) {
|
|
247
|
+
if (n.kind === "block") {
|
|
248
|
+
bounds.maxX = Math.max(bounds.maxX, n.x + n.width);
|
|
249
|
+
bounds.maxY = Math.max(bounds.maxY, n.y + n.height);
|
|
250
|
+
} else if (n.kind === "sum") {
|
|
251
|
+
bounds.maxX = Math.max(bounds.maxX, n.cx + n.r);
|
|
252
|
+
bounds.maxY = Math.max(bounds.maxY, n.cy + n.r);
|
|
253
|
+
} else {
|
|
254
|
+
const labelWidth = approxTextWidth(n.label);
|
|
255
|
+
bounds.maxX = Math.max(bounds.maxX, n.x + (n.isInput ? 20 : 6 + labelWidth));
|
|
256
|
+
bounds.maxY = Math.max(bounds.maxY, n.y + 12);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
for (const e of edges) {
|
|
260
|
+
extendPathBounds(e.path, bounds);
|
|
261
|
+
if (e.label) {
|
|
262
|
+
const half = approxTextWidth(e.label, 6) / 2;
|
|
263
|
+
bounds.maxX = Math.max(bounds.maxX, e.midX + half);
|
|
264
|
+
bounds.maxY = Math.max(bounds.maxY, e.midY + 12);
|
|
265
|
+
}
|
|
266
|
+
if (e.polarity) {
|
|
267
|
+
bounds.maxX = Math.max(bounds.maxX, e.polarity.x + 10);
|
|
268
|
+
bounds.maxY = Math.max(bounds.maxY, e.polarity.y + 10);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return bounds;
|
|
272
|
+
}
|
|
233
273
|
function layoutBlockDiagram(ast) {
|
|
234
274
|
const nodeIds = /* @__PURE__ */ new Set();
|
|
235
275
|
for (const b of ast.blocks) nodeIds.add(b.id);
|
|
@@ -350,6 +390,7 @@ function layoutBlockDiagram(ast) {
|
|
|
350
390
|
const totalWidth = colX.length ? colX[colX.length - 1] + BLOCK_W / 2 + RIGHT_PAD : 400;
|
|
351
391
|
const fbById = /* @__PURE__ */ new Map();
|
|
352
392
|
for (const f of fbInfos) fbById.set(f.id, f);
|
|
393
|
+
const signalById = new Map((ast.signals ?? []).map((s) => [s.id, s]));
|
|
353
394
|
const nodes = [];
|
|
354
395
|
const branchCount = /* @__PURE__ */ new Map();
|
|
355
396
|
for (const e of ast.connections) {
|
|
@@ -412,6 +453,23 @@ function layoutBlockDiagram(ast) {
|
|
|
412
453
|
isInput: false
|
|
413
454
|
});
|
|
414
455
|
}
|
|
456
|
+
for (const [id, signal] of signalById) {
|
|
457
|
+
if (!nodeIds.has(id) || id === "in" || id === "out") continue;
|
|
458
|
+
if (nodes.some((n) => n.id === id)) continue;
|
|
459
|
+
const c = col.get(id) ?? 0;
|
|
460
|
+
const cx = colX[Math.min(c, colX.length - 1)];
|
|
461
|
+
const hasIncoming = (incoming.get(id) ?? []).length > 0;
|
|
462
|
+
const hasOutgoing = (outgoing.get(id) ?? []).length > 0;
|
|
463
|
+
nodes.push({
|
|
464
|
+
kind: "port",
|
|
465
|
+
id,
|
|
466
|
+
label: signal.label,
|
|
467
|
+
x: cx,
|
|
468
|
+
y: forwardY,
|
|
469
|
+
isInput: !hasIncoming || hasOutgoing,
|
|
470
|
+
hasBranch: hasBranchOf(id)
|
|
471
|
+
});
|
|
472
|
+
}
|
|
415
473
|
const anchors = /* @__PURE__ */ new Map();
|
|
416
474
|
for (const n of nodes) {
|
|
417
475
|
if (n.kind === "block") {
|
|
@@ -579,10 +637,9 @@ function layoutBlockDiagram(ast) {
|
|
|
579
637
|
}
|
|
580
638
|
const totalTopSpace = maxAboveRow > 0 ? FIRST_ROW_OFFSET + (maxAboveRow - 1) * ROW_GAP + 60 : 30;
|
|
581
639
|
const totalBottomSpace = maxBelowRow > 0 ? FIRST_ROW_OFFSET + (maxBelowRow - 1) * ROW_GAP + 60 : 100;
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
totalTopSpace + totalBottomSpace
|
|
640
|
+
const bounds = estimateContentBounds(nodes, edges);
|
|
641
|
+
const height = Math.ceil(
|
|
642
|
+
Math.max(bounds.maxY + 36, totalTopSpace + 40, maxBelowRow > 0 ? forwardY + totalBottomSpace : 160)
|
|
586
643
|
);
|
|
587
644
|
return {
|
|
588
645
|
width: totalWidth,
|
|
@@ -803,5 +860,5 @@ var blockdiagram = {
|
|
|
803
860
|
};
|
|
804
861
|
|
|
805
862
|
export { blockdiagram, layoutBlockDiagram, parseBlockDiagram, renderBlockDiagram };
|
|
806
|
-
//# sourceMappingURL=chunk-
|
|
807
|
-
//# sourceMappingURL=chunk-
|
|
863
|
+
//# sourceMappingURL=chunk-MFAMNFPA.js.map
|
|
864
|
+
//# sourceMappingURL=chunk-MFAMNFPA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/diagrams/blockdiagram/parser.ts","../src/diagrams/blockdiagram/layout.ts","../src/diagrams/blockdiagram/renderer.ts","../src/diagrams/blockdiagram/index.ts"],"names":["text","title","i","path"],"mappings":"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","file":"chunk-MFAMNFPA.js","sourcesContent":["import type {\n BlockAST,\n BlockNode,\n BlockEdge,\n BlockSignal,\n SummingJunction,\n BlockRole,\n} from \"../../core/types\";\nimport { matchQuotedTitle } from \"../../core/quotes\";\n\nexport class BlockDiagramParseError extends Error {\n constructor(\n message: string,\n public line?: number,\n public column?: number,\n public source?: string\n ) {\n super(line !== undefined ? `Line ${line}: ${message}` : message);\n this.name = \"BlockDiagramParseError\";\n }\n}\n\nconst ROLE_VALUES = new Set<BlockRole>([\n \"plant\",\n \"controller\",\n \"sensor\",\n \"actuator\",\n \"reference\",\n \"disturbance\",\n \"generic\",\n]);\n\ntype SignalDecl = BlockSignal;\n\ninterface ParsedAttrs {\n name?: string;\n role?: BlockRole;\n discrete?: boolean;\n label?: string;\n route?: \"above\" | \"below\";\n}\n\nfunction parseAttrs(s: string): ParsedAttrs {\n // Inside [ ... ] — comma-separated key:value or bare flags like \"discrete\"\n const result: ParsedAttrs = {};\n // Split at commas not inside quotes\n const parts: string[] = [];\n let cur = \"\";\n let inQuote = false;\n for (const ch of s) {\n if (ch === '\"') inQuote = !inQuote;\n if (ch === \",\" && !inQuote) {\n parts.push(cur);\n cur = \"\";\n } else {\n cur += ch;\n }\n }\n if (cur.trim()) parts.push(cur);\n\n for (const raw of parts) {\n const p = raw.trim();\n if (!p) continue;\n if (p === \"discrete\") {\n result.discrete = true;\n continue;\n }\n if (p.startsWith('\"') && p.endsWith('\"')) {\n result.label = p.slice(1, -1);\n continue;\n }\n const m = p.match(/^(\\w+)\\s*:\\s*(.+)$/);\n if (!m) continue;\n const key = m[1].toLowerCase();\n let val = m[2].trim();\n if (val.startsWith('\"') && val.endsWith('\"')) val = val.slice(1, -1);\n if (key === \"name\") result.name = val;\n else if (key === \"role\") {\n if (ROLE_VALUES.has(val as BlockRole)) result.role = val as BlockRole;\n } else if (key === \"label\") result.label = val;\n else if (key === \"route\") {\n if (val === \"above\" || val === \"below\") result.route = val;\n }\n }\n return result;\n}\n\nexport function parseBlockDiagram(text: string): BlockAST {\n const lines = text.split(\"\\n\").map((l) => l.replace(/\\r$/, \"\"));\n let title: string | undefined;\n const blocks: BlockNode[] = [];\n const sums: SummingJunction[] = [];\n const connections: BlockEdge[] = [];\n const signals = new Map<string, SignalDecl>();\n\n for (let i = 0; i < lines.length; i++) {\n const rawLine = lines[i] ?? \"\";\n const lineNo = i + 1;\n const line = rawLine.replace(/#.*$/, \"\").trim();\n if (!line) continue;\n\n // Header: blockdiagram \"Title\"\n if (/^blockdiagram\\b/i.test(line)) {\n const t = matchQuotedTitle(line);\n if (t !== undefined) title = t;\n continue;\n }\n\n // block: ID = block(\"label\") [role: X, name: \"Y\"]\n const blockMatch = line.match(\n /^([A-Za-z_]\\w*)\\s*=\\s*block\\s*\\(\\s*\"([^\"]*)\"\\s*\\)\\s*(?:\\[([^\\]]*)\\])?\\s*$/\n );\n if (blockMatch) {\n const id = blockMatch[1];\n const label = blockMatch[2];\n const attrs = blockMatch[3] ? parseAttrs(blockMatch[3]) : {};\n const node: BlockNode = { id, label, role: attrs.role ?? \"generic\" };\n if (attrs.route) node.route = attrs.route;\n blocks.push(node);\n continue;\n }\n\n // sum: ID = sum(+a, -b, ...)\n const sumMatch = line.match(\n /^([A-Za-z_]\\w*)\\s*=\\s*sum\\s*\\(([^)]*)\\)\\s*$/\n );\n if (sumMatch) {\n const id = sumMatch[1];\n const rawInputs = sumMatch[2]\n .split(\",\")\n .map((x) => x.trim())\n .filter(Boolean);\n const inputs: string[] = [];\n for (const tok of rawInputs) {\n if (tok.startsWith(\"+\") || tok.startsWith(\"-\")) inputs.push(tok);\n else inputs.push(\"+\" + tok);\n }\n sums.push({ id, inputs });\n continue;\n }\n\n // signal: ID = signal(\"label\") [discrete]\n const sigMatch = line.match(\n /^([A-Za-z_]\\w*)\\s*=\\s*signal\\s*\\(\\s*\"([^\"]*)\"\\s*\\)\\s*(?:\\[([^\\]]*)\\])?\\s*$/\n );\n if (sigMatch) {\n const id = sigMatch[1];\n const label = sigMatch[2];\n const attrs = sigMatch[3] ? parseAttrs(sigMatch[3]) : {};\n signals.set(id, { id, label, discrete: !!attrs.discrete });\n continue;\n }\n\n // Connection chain: `A -> B -> C [label_or_attrs]`. Inline `[id] -> [id]` (D2/Mermaid) auto-declares.\n const arrowIdx = line.indexOf(\"->\");\n if (arrowIdx >= 0) {\n let body = line;\n let tailAttrs: ParsedAttrs = {};\n // Trailing `[...]` must be preceded by whitespace, else it's an inline endpoint.\n if (body.endsWith(\"]\")) {\n let bracketStart = -1;\n let depth = 0;\n let inQuote = false;\n for (let i = body.length - 1; i >= 1; i--) {\n const ch = body[i];\n if (ch === '\"') inQuote = !inQuote;\n else if (!inQuote && ch === \"]\") depth++;\n else if (!inQuote && ch === \"[\") {\n depth--;\n if (depth === 0) {\n if (/\\s/.test(body[i - 1] ?? \"\")) bracketStart = i;\n break;\n }\n }\n }\n if (bracketStart >= 0) {\n const inner = body.slice(bracketStart + 1, -1).trim();\n const isBareId = /^[A-Za-z_]\\w*$/.test(inner);\n if (!isBareId) {\n body = body.slice(0, bracketStart).trim();\n if (inner.startsWith('\"') && inner.endsWith('\"') && !inner.slice(1, -1).includes(',')) {\n tailAttrs.label = inner.slice(1, -1);\n } else {\n tailAttrs = parseAttrs(inner);\n }\n }\n }\n }\n const parts = body.split(\"->\").map((x) => x.trim()).filter(Boolean);\n if (parts.length < 2) {\n throw new BlockDiagramParseError(`Invalid connection: ${line}`, lineNo, undefined, line);\n }\n const endpoints = parts.map((p) => {\n const m = /^\\[([A-Za-z_]\\w*)\\]$/.exec(p);\n return m ? m[1] : p;\n });\n for (const ep of endpoints) {\n if (!/^[A-Za-z_]\\w*$/.test(ep)) continue;\n const exists =\n blocks.some((b) => b.id === ep) ||\n sums.some((s) => s.id === ep) ||\n signals.has(ep);\n if (!exists) {\n blocks.push({ id: ep, label: ep, role: \"generic\" });\n }\n }\n for (let i = 0; i < endpoints.length - 1; i++) {\n const from = endpoints[i];\n const to = endpoints[i + 1];\n const isLast = i === endpoints.length - 2;\n const edge: BlockEdge = { from, to };\n if (isLast && tailAttrs.label) edge.label = tailAttrs.label;\n if (isLast && tailAttrs.discrete) edge.discrete = true;\n connections.push(edge);\n }\n continue;\n }\n }\n\n // Post-process: if edge endpoints reference a signal id, inline the signal.\n // A signal is a pass-through label. Merge edges X->sig and sig->Y into X->Y,\n // using signal's label (unless edge already has one) and discrete flag.\n if (signals.size > 0) {\n const merged: BlockEdge[] = [];\n const bySource = new Map<string, BlockEdge[]>();\n const byTarget = new Map<string, BlockEdge[]>();\n for (const e of connections) {\n if (!bySource.has(e.from)) bySource.set(e.from, []);\n bySource.get(e.from)!.push(e);\n if (!byTarget.has(e.to)) byTarget.set(e.to, []);\n byTarget.get(e.to)!.push(e);\n }\n\n const consumed = new Set<BlockEdge>();\n for (const sigId of signals.keys()) {\n const sig = signals.get(sigId)!;\n const incoming = byTarget.get(sigId) ?? [];\n const outgoing = bySource.get(sigId) ?? [];\n // For each incoming/outgoing pair, make a merged edge\n for (const ine of incoming) {\n for (const oute of outgoing) {\n consumed.add(ine);\n consumed.add(oute);\n merged.push({\n from: ine.from,\n to: oute.to,\n label: ine.label ?? oute.label ?? sig.label,\n discrete: sig.discrete || ine.discrete || oute.discrete,\n });\n }\n }\n }\n // Keep edges not consumed\n for (const e of connections) {\n if (!consumed.has(e)) merged.push(e);\n }\n connections.length = 0;\n connections.push(...merged);\n }\n\n return {\n type: \"blockdiagram\",\n title,\n blocks,\n sums,\n signals: Array.from(signals.values()),\n connections,\n };\n}\n","import type { BlockAST, BlockEdge, BlockNode, SummingJunction } from \"../../core/types\";\n\nexport interface LaidBlock {\n kind: \"block\";\n id: string;\n label: string;\n role: string;\n x: number;\n y: number;\n width: number;\n height: number;\n hasBranch?: boolean;\n}\n\nexport interface LaidSum {\n kind: \"sum\";\n id: string;\n cx: number;\n cy: number;\n r: number;\n hasBranch?: boolean;\n}\n\nexport interface LaidPort {\n kind: \"port\";\n id: string;\n label: string;\n x: number;\n y: number;\n isInput: boolean;\n hasBranch?: boolean;\n}\n\nexport type LaidNode = LaidBlock | LaidSum | LaidPort;\n\nexport interface LaidEdgePolarity {\n sign: \"+\" | \"-\";\n pin: \"left\" | \"top\" | \"right\" | \"bottom\";\n x: number;\n y: number;\n}\n\nexport interface LaidEdge {\n from: string;\n to: string;\n label?: string;\n discrete: boolean;\n path: string;\n midX: number;\n midY: number;\n isFeedback: boolean;\n /** Polarity sign to draw near the target if target is a sum */\n polarity?: LaidEdgePolarity;\n}\n\nexport interface BlockDiagramLayout {\n width: number;\n height: number;\n nodes: LaidNode[];\n edges: LaidEdge[];\n title?: string;\n /** Offset applied to all y coords (>0 when feedforward rows exist above FWD_Y) */\n topOffset: number;\n}\n\nconst BLOCK_W = 100;\nconst BLOCK_H = 54;\nconst SUM_R = 12;\nconst FWD_Y = 110;\nconst ROW_GAP = 80;\nconst FIRST_ROW_OFFSET = 110;\nconst COL_GAP = 60;\nconst LEFT_PAD = 30;\nconst RIGHT_PAD = 30;\n\nfunction approxTextWidth(text: string, pxPerChar = 7): number {\n return text.length * pxPerChar;\n}\n\nfunction extendPathBounds(path: string, bounds: { maxX: number; maxY: number }): void {\n const nums = path.match(/-?\\d+(?:\\.\\d+)?/g)?.map(Number) ?? [];\n for (let i = 0; i < nums.length - 1; i += 2) {\n bounds.maxX = Math.max(bounds.maxX, nums[i] ?? 0);\n bounds.maxY = Math.max(bounds.maxY, nums[i + 1] ?? 0);\n }\n}\n\nfunction estimateContentBounds(nodes: LaidNode[], edges: LaidEdge[]): { maxX: number; maxY: number } {\n const bounds = { maxX: 0, maxY: 0 };\n\n for (const n of nodes) {\n if (n.kind === \"block\") {\n bounds.maxX = Math.max(bounds.maxX, n.x + n.width);\n bounds.maxY = Math.max(bounds.maxY, n.y + n.height);\n } else if (n.kind === \"sum\") {\n bounds.maxX = Math.max(bounds.maxX, n.cx + n.r);\n bounds.maxY = Math.max(bounds.maxY, n.cy + n.r);\n } else {\n const labelWidth = approxTextWidth(n.label);\n bounds.maxX = Math.max(bounds.maxX, n.x + (n.isInput ? 20 : 6 + labelWidth));\n bounds.maxY = Math.max(bounds.maxY, n.y + 12);\n }\n }\n\n for (const e of edges) {\n extendPathBounds(e.path, bounds);\n if (e.label) {\n const half = approxTextWidth(e.label, 6) / 2;\n bounds.maxX = Math.max(bounds.maxX, e.midX + half);\n bounds.maxY = Math.max(bounds.maxY, e.midY + 12);\n }\n if (e.polarity) {\n bounds.maxX = Math.max(bounds.maxX, e.polarity.x + 10);\n bounds.maxY = Math.max(bounds.maxY, e.polarity.y + 10);\n }\n }\n\n return bounds;\n}\n\ninterface Track {\n /** row index (1, 2, ...); 0 means forward path */\n row: number;\n /** above = y < FWD_Y; below = y > FWD_Y */\n side: \"above\" | \"below\";\n /** Occupied col ranges [minCol, maxCol] for collision detection */\n ranges: Array<[number, number]>;\n}\n\nexport function layoutBlockDiagram(ast: BlockAST): BlockDiagramLayout {\n const nodeIds = new Set<string>();\n for (const b of ast.blocks) nodeIds.add(b.id);\n for (const s of ast.sums) nodeIds.add(s.id);\n for (const e of ast.connections) {\n nodeIds.add(e.from);\n nodeIds.add(e.to);\n }\n\n const outgoing = new Map<string, BlockEdge[]>();\n const incoming = new Map<string, BlockEdge[]>();\n for (const id of nodeIds) {\n outgoing.set(id, []);\n incoming.set(id, []);\n }\n for (const e of ast.connections) {\n outgoing.get(e.from)!.push(e);\n incoming.get(e.to)!.push(e);\n }\n\n // Entry points\n const hasIn = nodeIds.has(\"in\");\n const entries: string[] = [];\n if (hasIn) entries.push(\"in\");\n for (const id of nodeIds) {\n if (id === \"in\" || id === \"out\") continue;\n if ((incoming.get(id) ?? []).length === 0 && !entries.includes(id)) {\n entries.push(id);\n }\n }\n\n // BFS forward (first-visit col assignment — back-edges become feedback)\n const col = new Map<string, number>();\n const queue: string[] = [];\n for (const e of entries) {\n col.set(e, 0);\n queue.push(e);\n }\n while (queue.length > 0) {\n const cur = queue.shift()!;\n const c = col.get(cur)!;\n for (const edge of outgoing.get(cur) ?? []) {\n if (!col.has(edge.to)) {\n col.set(edge.to, c + 1);\n queue.push(edge.to);\n }\n }\n }\n // Any unreached node\n for (const id of nodeIds) {\n if (!col.has(id)) col.set(id, 1);\n }\n\n // Feedback detection: outgoing edges are ALL going backward\n const isFeedback = new Set<string>();\n for (const id of nodeIds) {\n if (id === \"in\" || id === \"out\") continue;\n const myCol = col.get(id)!;\n const outs = outgoing.get(id) ?? [];\n if (outs.length === 0) continue;\n const allBack = outs.every((e) => (col.get(e.to) ?? myCol) < myCol);\n if (allBack) isFeedback.add(id);\n }\n\n // For each feedback node, compute loop range [minCol, maxCol]\n const blockById = new Map<string, BlockNode>();\n for (const b of ast.blocks) blockById.set(b.id, b);\n\n interface FbInfo {\n id: string;\n range: [number, number];\n side: \"above\" | \"below\";\n row: number; // depth\n }\n const fbInfos: FbInfo[] = [];\n for (const id of isFeedback) {\n const outs = outgoing.get(id) ?? [];\n const ins = incoming.get(id) ?? [];\n // targets (forward nodes it feeds back into)\n const targetCols = outs.map((e) => col.get(e.to) ?? 0);\n const sourceCols = ins.map((e) => col.get(e.from) ?? 0);\n const minC = Math.min(...targetCols, ...sourceCols);\n const maxC = Math.max(...targetCols, ...sourceCols);\n const bn = blockById.get(id);\n const side: \"above\" | \"below\" = bn?.route === \"above\" ? \"above\" : \"below\";\n fbInfos.push({ id, range: [minC, maxC], side, row: 0 });\n }\n\n // Sort by range width desc (outermost first), break ties by min col\n fbInfos.sort((a, b) => {\n const wa = a.range[1] - a.range[0];\n const wb = b.range[1] - b.range[0];\n if (wa !== wb) return wb - wa;\n return a.range[0] - b.range[0];\n });\n\n // Assign tracks per side, greedy interval-overlap depth\n const tracks: Record<\"above\" | \"below\", Track[]> = { above: [], below: [] };\n for (const fb of fbInfos) {\n let row = 1;\n while (true) {\n // check if any existing block on this (side, row) has overlapping range\n const occupied = tracks[fb.side].find((t) => t.row === row);\n const conflict =\n occupied?.ranges.some(\n ([a, b]) => !(fb.range[1] < a || fb.range[0] > b)\n ) ?? false;\n if (!conflict) {\n if (occupied) occupied.ranges.push(fb.range);\n else\n tracks[fb.side].push({ row, side: fb.side, ranges: [fb.range] });\n fb.row = row;\n break;\n }\n row++;\n }\n }\n\n const maxBelowRow = tracks.below.reduce((m, t) => Math.max(m, t.row), 0);\n const maxAboveRow = tracks.above.reduce((m, t) => Math.max(m, t.row), 0);\n\n // Compute y per (side, row)\n const yFor = (side: \"above\" | \"below\", row: number): number => {\n const step = FIRST_ROW_OFFSET + (row - 1) * ROW_GAP;\n return side === \"above\" ? FWD_Y - step : FWD_Y + step;\n };\n\n // For the feedforward row(s) to have room, shift all y by topOffset\n const topOffset = maxAboveRow > 0 ? (FIRST_ROW_OFFSET + (maxAboveRow - 1) * ROW_GAP) + 30 : 30;\n const forwardY = FWD_Y + (topOffset - 30);\n\n // Remap y helper\n const rowY = (side: \"above\" | \"below\", row: number): number =>\n yFor(side, row) + (topOffset - 30);\n\n // Normalize columns\n let maxFwdCol = 0;\n for (const id of nodeIds) {\n if (!isFeedback.has(id)) maxFwdCol = Math.max(maxFwdCol, col.get(id) ?? 0);\n }\n const colCount = maxFwdCol + 1;\n const colContent = new Array(colCount).fill(BLOCK_W);\n\n const colX: number[] = [];\n {\n let x = LEFT_PAD;\n for (let i = 0; i < colCount; i++) {\n const w = i === 0 && hasIn ? 30 : colContent[i];\n colX.push(x + w / 2);\n x += w + COL_GAP;\n }\n }\n const totalWidth = colX.length\n ? colX[colX.length - 1] + BLOCK_W / 2 + RIGHT_PAD\n : 400;\n\n // Lookup for feedback row info\n const fbById = new Map<string, FbInfo>();\n for (const f of fbInfos) fbById.set(f.id, f);\n const signalById = new Map((ast.signals ?? []).map((s) => [s.id, s]));\n\n const nodes: LaidNode[] = [];\n const branchCount = new Map<string, number>();\n for (const e of ast.connections) {\n branchCount.set(e.from, (branchCount.get(e.from) ?? 0) + 1);\n }\n const hasBranchOf = (id: string) => (branchCount.get(id) ?? 0) > 1;\n\n for (const b of ast.blocks) {\n const c = col.get(b.id) ?? 0;\n const cx = colX[Math.min(c, colX.length - 1)];\n let cy = forwardY;\n const fb = fbById.get(b.id);\n if (fb) cy = rowY(fb.side, fb.row);\n nodes.push({\n kind: \"block\",\n id: b.id,\n label: b.label,\n role: b.role ?? \"generic\",\n x: cx - BLOCK_W / 2,\n y: cy - BLOCK_H / 2,\n width: BLOCK_W,\n height: BLOCK_H,\n hasBranch: hasBranchOf(b.id),\n });\n }\n\n for (const s of ast.sums) {\n const c = col.get(s.id) ?? 0;\n const cx = colX[Math.min(c, colX.length - 1)];\n let cy = forwardY;\n const fb = fbById.get(s.id);\n if (fb) cy = rowY(fb.side, fb.row);\n nodes.push({\n kind: \"sum\",\n id: s.id,\n cx,\n cy,\n r: SUM_R,\n hasBranch: hasBranchOf(s.id),\n });\n }\n\n if (hasIn) {\n nodes.push({\n kind: \"port\",\n id: \"in\",\n label: \"in\",\n x: LEFT_PAD,\n y: forwardY,\n isInput: true,\n hasBranch: hasBranchOf(\"in\"),\n });\n }\n if (nodeIds.has(\"out\")) {\n const outCol = col.get(\"out\") ?? maxFwdCol;\n const cx = colX[Math.min(outCol, colX.length - 1)];\n nodes.push({\n kind: \"port\",\n id: \"out\",\n label: \"out\",\n x: cx,\n y: forwardY,\n isInput: false,\n });\n }\n for (const [id, signal] of signalById) {\n if (!nodeIds.has(id) || id === \"in\" || id === \"out\") continue;\n if (nodes.some((n) => n.id === id)) continue;\n const c = col.get(id) ?? 0;\n const cx = colX[Math.min(c, colX.length - 1)];\n const hasIncoming = (incoming.get(id) ?? []).length > 0;\n const hasOutgoing = (outgoing.get(id) ?? []).length > 0;\n nodes.push({\n kind: \"port\",\n id,\n label: signal.label,\n x: cx,\n y: forwardY,\n isInput: !hasIncoming || hasOutgoing,\n hasBranch: hasBranchOf(id),\n });\n }\n\n // Anchor lookup\n interface Anchor {\n left: { x: number; y: number };\n right: { x: number; y: number };\n top: { x: number; y: number };\n bottom: { x: number; y: number };\n cx: number;\n cy: number;\n }\n const anchors = new Map<string, Anchor>();\n for (const n of nodes) {\n if (n.kind === \"block\") {\n anchors.set(n.id, {\n left: { x: n.x, y: n.y + n.height / 2 },\n right: { x: n.x + n.width, y: n.y + n.height / 2 },\n top: { x: n.x + n.width / 2, y: n.y },\n bottom: { x: n.x + n.width / 2, y: n.y + n.height },\n cx: n.x + n.width / 2,\n cy: n.y + n.height / 2,\n });\n } else if (n.kind === \"sum\") {\n anchors.set(n.id, {\n left: { x: n.cx - n.r, y: n.cy },\n right: { x: n.cx + n.r, y: n.cy },\n top: { x: n.cx, y: n.cy - n.r },\n bottom: { x: n.cx, y: n.cy + n.r },\n cx: n.cx,\n cy: n.cy,\n });\n } else {\n anchors.set(n.id, {\n left: { x: n.x - 10, y: n.y },\n right: { x: n.x + (n.isInput ? 20 : 0), y: n.y },\n top: { x: n.x, y: n.y - 10 },\n bottom: { x: n.x, y: n.y + 10 },\n cx: n.x,\n cy: n.y,\n });\n }\n }\n\n // Build sum-input-polarity lookup\n const sumPolarity = new Map<string, Map<string, \"+\" | \"-\">>();\n for (const s of ast.sums) {\n const m = new Map<string, \"+\" | \"-\">();\n for (const tok of s.inputs) {\n const sign = tok.startsWith(\"-\") ? \"-\" : \"+\";\n const srcId = tok.replace(/^[+-]/, \"\");\n m.set(srcId, sign);\n }\n sumPolarity.set(s.id, m);\n }\n\n // Build edges\n const edges: LaidEdge[] = [];\n // Track horizontal-track offsets for feedback paths to avoid overlap\n const sumById = new Map<string, SummingJunction>();\n for (const s of ast.sums) sumById.set(s.id, s);\n\n for (const e of ast.connections) {\n const fromA = anchors.get(e.from);\n const toA = anchors.get(e.to);\n if (!fromA || !toA) continue;\n\n const fromFb = fbById.get(e.from);\n const toFb = fbById.get(e.to);\n const fromCol = col.get(e.from) ?? 0;\n const toCol = col.get(e.to) ?? 0;\n\n // Determine pin on target when target is a sum: left (from forward earlier),\n // bottom (from below feedback), top (from above feedforward), or right (rare, output)\n let polarity: LaidEdgePolarity | undefined;\n if (sumById.has(e.to)) {\n const pm = sumPolarity.get(e.to);\n const sign = pm?.get(e.from) ?? \"+\";\n let pin: \"left\" | \"top\" | \"bottom\" | \"right\" = \"left\";\n if (fromFb?.side === \"below\") pin = \"bottom\";\n else if (fromFb?.side === \"above\") pin = \"top\";\n else if (fromCol < toCol) pin = \"left\";\n else pin = \"bottom\";\n const sumNode = nodes.find(\n (n) => n.kind === \"sum\" && n.id === e.to\n ) as LaidSum | undefined;\n if (sumNode) {\n let px = sumNode.cx, py = sumNode.cy;\n if (pin === \"left\") {\n px = sumNode.cx - sumNode.r - 8;\n py = sumNode.cy + 6;\n } else if (pin === \"bottom\") {\n px = sumNode.cx - sumNode.r - 2;\n py = sumNode.cy + sumNode.r + 10;\n } else if (pin === \"top\") {\n px = sumNode.cx - sumNode.r - 2;\n py = sumNode.cy - sumNode.r - 2;\n }\n polarity = { sign, pin, x: px, y: py };\n }\n }\n\n // Route\n let path: string;\n let midX: number, midY: number;\n let isFb = false;\n\n const fromIsFbSide = fromFb?.side;\n const toIsFbSide = toFb?.side;\n\n if (fromIsFbSide && toIsFbSide === fromIsFbSide) {\n // within same feedback row\n const sx = fromA.left.x;\n const sy = fromA.left.y;\n const tx = toA.right.x;\n const ty = toA.right.y;\n path = `M ${sx} ${sy} L ${tx} ${ty}`;\n midX = (sx + tx) / 2;\n midY = sy - 6;\n isFb = true;\n } else if (!fromIsFbSide && toIsFbSide === \"below\") {\n // forward → below feedback: branch down from source.bottom\n const sx = fromA.bottom.x;\n const sy = fromA.bottom.y;\n const tx = toA.right.x;\n const ty = toA.right.y;\n path = `M ${sx} ${sy} L ${sx} ${ty} L ${tx} ${ty}`;\n midX = sx;\n midY = (sy + ty) / 2;\n isFb = true;\n } else if (!fromIsFbSide && toIsFbSide === \"above\") {\n // forward → above feedforward: branch up from source.top\n const sx = fromA.top.x;\n const sy = fromA.top.y;\n const tx = toA.right.x;\n const ty = toA.right.y;\n path = `M ${sx} ${sy} L ${sx} ${ty} L ${tx} ${ty}`;\n midX = sx;\n midY = (sy + ty) / 2;\n isFb = true;\n } else if (fromIsFbSide === \"below\" && !toIsFbSide) {\n // below feedback → forward target (bottom pin if sum)\n const sx = fromA.left.x;\n const sy = fromA.left.y;\n const tx = toA.bottom.x;\n const ty = toA.bottom.y;\n path = `M ${sx} ${sy} L ${tx} ${sy} L ${tx} ${ty}`;\n midX = (sx + tx) / 2;\n midY = sy - 6;\n isFb = true;\n } else if (fromIsFbSide === \"above\" && !toIsFbSide) {\n // above feedforward → forward target (top pin if sum)\n const sx = fromA.left.x;\n const sy = fromA.left.y;\n const tx = toA.top.x;\n const ty = toA.top.y;\n path = `M ${sx} ${sy} L ${tx} ${sy} L ${tx} ${ty}`;\n midX = (sx + tx) / 2;\n midY = sy - 6;\n isFb = true;\n } else if (toCol < fromCol) {\n // generic back-edge fallback (below)\n const sx = fromA.right.x;\n const sy = fromA.right.y;\n const tx = toA.bottom.x;\n const ty = toA.bottom.y;\n const dipY = Math.max(sy, ty) + 60;\n path = `M ${sx} ${sy} L ${sx} ${dipY} L ${tx} ${dipY} L ${tx} ${ty}`;\n midX = (sx + tx) / 2;\n midY = dipY + 10;\n isFb = true;\n } else {\n // forward edge\n const sx = fromA.right.x;\n const sy = fromA.right.y;\n const tx = toA.left.x;\n const ty = toA.left.y;\n if (Math.abs(sy - ty) < 0.5) {\n path = `M ${sx} ${sy} L ${tx} ${ty}`;\n } else {\n const midXH = (sx + tx) / 2;\n path = `M ${sx} ${sy} L ${midXH} ${sy} L ${midXH} ${ty} L ${tx} ${ty}`;\n }\n midX = (sx + tx) / 2;\n midY = sy - 8;\n }\n\n edges.push({\n from: e.from,\n to: e.to,\n label: e.label,\n discrete: !!e.discrete,\n path,\n midX,\n midY,\n isFeedback: isFb,\n polarity,\n });\n }\n\n // Total canvas height: enough for top rows + forward + bottom rows.\n // Use rendered content extents for the common compact closed-loop case so\n // gallery cards do not inherit a large generic fallback gutter.\n const totalTopSpace =\n maxAboveRow > 0\n ? FIRST_ROW_OFFSET + (maxAboveRow - 1) * ROW_GAP + 60\n : 30;\n const totalBottomSpace =\n maxBelowRow > 0\n ? FIRST_ROW_OFFSET + (maxBelowRow - 1) * ROW_GAP + 60\n : 100;\n const bounds = estimateContentBounds(nodes, edges);\n const height = Math.ceil(\n Math.max(bounds.maxY + 36, totalTopSpace + 40, maxBelowRow > 0 ? forwardY + totalBottomSpace : 160)\n );\n\n return {\n width: totalWidth,\n height,\n nodes,\n edges,\n title: ast.title,\n topOffset,\n };\n}\n","import type { BlockAST } from \"../../core/types\";\nimport { layoutBlockDiagram } from \"./layout\";\nimport {\n svgRoot,\n defs,\n group,\n el,\n circle,\n path as pathEl,\n text,\n title as titleEl,\n desc,\n} from \"../../core/svg\";\n\nconst ROLE_FILL: Record<string, string> = {\n plant: \"#ffffff\",\n controller: \"#E3F2FD\",\n sensor: \"#F3E5F5\",\n actuator: \"#E8F5E9\",\n filter: \"#FFF8E1\",\n reference: \"#ffffff\",\n disturbance: \"#FFF3E0\",\n generic: \"#ffffff\",\n};\n\nexport function renderBlockDiagram(ast: BlockAST): string {\n const layout = layoutBlockDiagram(ast);\n const titleOffset = ast.title ? 26 : 0;\n const { width } = layout;\n const height = layout.height + titleOffset;\n\n const css = `\n.schematex-bd { font-family: system-ui, -apple-system, sans-serif; }\n.schematex-bd-block { stroke: #333; stroke-width: 2; }\n.schematex-bd-tf { font: italic 14px serif; fill: #111; }\n.schematex-bd-block-name { font: 10px sans-serif; fill: #666; }\n.schematex-bd-sum { fill: #fff; stroke: #333; stroke-width: 2; }\n.schematex-bd-sum-sign { font: bold 11px sans-serif; fill: #333; }\n.schematex-bd-signal { stroke: #333; stroke-width: 2; fill: none; }\n.schematex-bd-signal-discrete { stroke: #333; stroke-width: 2; fill: none; stroke-dasharray: 6 4; }\n.schematex-bd-signal-label { font: italic 12px serif; fill: #333; }\n.schematex-bd-port-label { font: italic 13px serif; fill: #111; }\n.schematex-bd-title { font: bold 15px sans-serif; fill: #111; }\n.schematex-bd-branch { fill: #333; stroke: none; }\n`.trim();\n\n const arrowDef = el(\n \"marker\",\n {\n id: \"lt-bd-arrow\",\n markerWidth: 10,\n markerHeight: 8,\n refX: 9,\n refY: 4,\n orient: \"auto\",\n },\n [el(\"polygon\", { points: \"0 0, 10 4, 0 8\", fill: \"#333\" })]\n );\n\n const nodeSvgs: string[] = [];\n const edgeSvgs: string[] = [];\n const branchSvgs: string[] = [];\n\n for (const n of layout.nodes) {\n if (n.kind === \"block\") {\n const fill = ROLE_FILL[n.role] ?? \"#fff\";\n nodeSvgs.push(\n group(\n {\n transform: `translate(${n.x}, ${n.y})`,\n \"data-block-id\": n.id,\n \"data-block-role\": n.role,\n },\n [\n el(\"rect\", {\n width: n.width,\n height: n.height,\n fill,\n class: \"schematex-bd-block\",\n rx: 2,\n }),\n text(\n {\n x: n.width / 2,\n y: n.height / 2 + 5,\n \"text-anchor\": \"middle\",\n class: \"schematex-bd-tf\",\n },\n n.label\n ),\n ]\n )\n );\n if (n.hasBranch) {\n branchSvgs.push(\n circle({\n cx: n.x + n.width,\n cy: n.y + n.height / 2,\n r: 3.5,\n class: \"schematex-bd-branch\",\n })\n );\n }\n } else if (n.kind === \"sum\") {\n nodeSvgs.push(\n group({ \"data-sum-id\": n.id }, [\n circle({\n cx: n.cx,\n cy: n.cy,\n r: n.r,\n class: \"schematex-bd-sum\",\n }),\n ])\n );\n if (n.hasBranch) {\n branchSvgs.push(\n circle({\n cx: n.cx + n.r,\n cy: n.cy,\n r: 3.5,\n class: \"schematex-bd-branch\",\n })\n );\n }\n } else if (n.kind === \"port\") {\n nodeSvgs.push(\n group({ \"data-port-id\": n.id }, [\n text(\n {\n x: n.isInput ? n.x - 4 : n.x + 4,\n y: n.y + 4,\n \"text-anchor\": n.isInput ? \"end\" : \"start\",\n class: \"schematex-bd-port-label\",\n },\n n.label\n ),\n ])\n );\n }\n }\n\n for (const e of layout.edges) {\n const cls = e.discrete\n ? \"schematex-bd-signal-discrete\"\n : \"schematex-bd-signal\";\n edgeSvgs.push(\n pathEl({\n d: e.path,\n class: cls,\n \"marker-end\": \"url(#lt-bd-arrow)\",\n \"data-from\": e.from,\n \"data-to\": e.to,\n })\n );\n if (e.label) {\n edgeSvgs.push(\n text(\n {\n x: e.midX,\n y: e.midY,\n \"text-anchor\": \"middle\",\n class: \"schematex-bd-signal-label\",\n },\n e.label\n )\n );\n }\n if (e.polarity) {\n edgeSvgs.push(\n text(\n {\n x: e.polarity.x,\n y: e.polarity.y,\n \"text-anchor\": \"middle\",\n class: \"schematex-bd-sum-sign\",\n },\n e.polarity.sign === \"-\" ? \"−\" : \"+\"\n )\n );\n }\n }\n\n const titleSvg = ast.title\n ? text(\n {\n x: width / 2,\n y: 18,\n \"text-anchor\": \"middle\",\n class: \"schematex-bd-title\",\n },\n ast.title\n )\n : \"\";\n\n return svgRoot(\n {\n class: \"schematex-bd\",\n viewBox: `0 0 ${width} ${height}`,\n width,\n height,\n role: \"img\",\n \"data-diagram-type\": \"blockdiagram\",\n },\n [\n titleEl(ast.title ?? \"Block Diagram\"),\n desc(\n `Block diagram with ${ast.blocks.length} blocks, ${ast.sums.length} summing junctions, ${ast.connections.length} signals`\n ),\n defs([el(\"style\", {}, css), arrowDef]),\n titleSvg,\n group({ transform: `translate(0, ${titleOffset})` }, [\n group({ class: \"schematex-bd-signals\" }, edgeSvgs),\n group({ class: \"schematex-bd-nodes\" }, nodeSvgs),\n group({ class: \"schematex-bd-branches\" }, branchSvgs),\n ]),\n ]\n );\n}\n","import type { DiagramPlugin } from \"../../core/types\";\nimport { parseBlockDiagram } from \"./parser\";\nimport { renderBlockDiagram } from \"./renderer\";\n\nexport const blockdiagram: DiagramPlugin = {\n type: \"blockdiagram\",\n detect(text: string): boolean {\n const first = text.trim().split(\"\\n\")[0]?.trim().toLowerCase() ?? \"\";\n return first.startsWith(\"blockdiagram\");\n },\n parse: parseBlockDiagram,\n\n render(text: string): string {\n const ast = parseBlockDiagram(text);\n return renderBlockDiagram(ast);\n },\n};\n\nexport { parseBlockDiagram } from \"./parser\";\nexport { renderBlockDiagram } from \"./renderer\";\nexport { layoutBlockDiagram } from \"./layout\";\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseResult, renderResult } from './chunk-
|
|
1
|
+
import { parseResult, renderResult } from './chunk-I2GQYOZ5.js';
|
|
2
2
|
|
|
3
3
|
// src/ai/registry.ts
|
|
4
4
|
var DIAGRAM_REGISTRY = [
|
|
@@ -482,6 +482,25 @@ var EXAMPLES = [
|
|
|
482
482
|
"dsl": 'bpmn\ndirection: LR\ntitle: "Pizza order"\n\npool "Customer" blackbox\n\npool "Pizzeria" {\n lane "Clerk" {\n A: start message "Order received"\n B: task user "Take order"\n }\n lane "Chef" {\n C: task manual "Make pizza"\n G1: gateway xor "Pizza ok?"\n D: task manual "Rework"\n }\n lane "Delivery" {\n E: task send "Deliver"\n F: end "Done"\n }\n}\n\nflows\nA --> B\nB --> C\nC --> G1\nG1 --? "yes" --> E\nG1 --* "no" --> D\nD --> C\nE --> F\n"Customer" ~~> A : "Place order"\nE ~~> "Customer" : "Pizza delivered"',
|
|
483
483
|
"notes": 'This is the OMG-tutorial *hello world* for BPMN \u2014 every BPM textbook and certification course uses some version of it. It\'s a deceptively rich example: in 12 elements it covers every concept that distinguishes BPMN from a generic flowchart.\n\n**Black-box pool.** The customer\'s internal process is unknown (and irrelevant) to the pizzeria, so Customer is rendered as an empty rectangle with no flow objects. Schematex enforces this \u2014 adding a lane or a task inside a `blackbox` pool fails the parse. Black-box pools exist purely as message-flow endpoints.\n\n**Message flows cross pools, sequence flows do not.** The two `~~>` connectors are dashed with an open arrowhead and a small unfilled circle at the source. That\'s the *only* legal way information crosses a pool boundary in BPMN. Schematex\'s parser will reject `A --> "Customer"` with a clear error.\n\n**Rework loop.** `D --> C` creates a back-edge. The layout\'s longest-path layering would normally fail on cycles; Schematex\'s DFS-based cycle-break tags `D \u2192 C` as a back edge, runs longest-path on the remaining DAG, then routes the loop manually. This is exactly how real processes look \u2014 quality gates always have a "go back and redo it" branch.\n\n**Task markers communicate intent.** `start message` (envelope) means "wait for an inbound message before starting"; `task manual` means a person performs the work without software ("hand-toss the dough"); `task send` means "send a message and continue". An LLM picking markers correctly turns a vague flowchart into a precise process spec.'
|
|
484
484
|
},
|
|
485
|
+
{
|
|
486
|
+
"slug": "bpmn-refund-escalation-compensation",
|
|
487
|
+
"diagram": "bpmn",
|
|
488
|
+
"title": "Refund escalation workflow",
|
|
489
|
+
"description": "BPMN process for refund handling across Support, Risk, Finance, and an external payment processor, with SLA timer escalation and customer-facing message flows.",
|
|
490
|
+
"standard": "OMG BPMN 2.0.2 / ISO/IEC 19510:2013",
|
|
491
|
+
"tags": [
|
|
492
|
+
"bpmn",
|
|
493
|
+
"refund",
|
|
494
|
+
"escalation",
|
|
495
|
+
"timer",
|
|
496
|
+
"finance",
|
|
497
|
+
"support"
|
|
498
|
+
],
|
|
499
|
+
"complexity": 3,
|
|
500
|
+
"featured": false,
|
|
501
|
+
"dsl": 'bpmn\ndirection: LR\ntitle: "Refund escalation"\n\npool "Customer" blackbox\npool "Payment Processor" blackbox\n\npool "Merchant" {\n lane "Support" {\n S: start message "Refund request"\n TRIAGE: task user "Triage request"\n DOCS: gateway xor "Enough evidence?"\n ASK: task send "Ask for documents"\n SLA: intermediate timer "48h SLA"\n ESC: task user "Escalate case"\n }\n lane "Risk" {\n RISK: task user "Risk review"\n G1: gateway xor "Policy breach?"\n DENY: task send "Deny refund"\n }\n lane "Finance" {\n CALC: task service "Calculate amount"\n APPROVE: task user "Approve refund"\n ISSUE: task send "Issue refund"\n ENDOK: end message "Refund sent"\n ENDDENY: end message "Denied"\n }\n}\n\nflows\nS --> TRIAGE\nTRIAGE --> DOCS\nDOCS --? "missing" --> ASK\nASK --> SLA\nSLA --> ESC\nESC --> RISK\nDOCS --* "complete" --> RISK\nRISK --> G1\nG1 --? "yes" --> DENY\nDENY --> ENDDENY\nG1 --* "no" --> CALC\nCALC --> APPROVE\nAPPROVE --> ISSUE\nISSUE --> ENDOK\n"Customer" ~~> S : "Refund request"\nASK ~~> "Customer" : "Need documents"\nDENY ~~> "Customer" : "Denial notice"\nISSUE ~~> "Payment Processor" : "Refund API"\n"Payment Processor" ~~> ENDOK : "Refund confirmed"',
|
|
502
|
+
"notes": "## Scenario\n\nRefund handling is a process-governance problem: support receives the customer request, risk decides whether policy blocks the refund, finance approves and issues the money movement, and the payment processor confirms settlement. BPMN is the right notation because lanes and message flows are part of the meaning.\n\n## Annotation key\n\n- The `48h SLA` timer event makes escalation a timed process milestone rather than a vague task.\n- Message flows (`~~>`) cross pool boundaries for customer and processor communication.\n- The XOR gateway separates policy denial from the refund issuance path."
|
|
503
|
+
},
|
|
485
504
|
{
|
|
486
505
|
"slug": "breadboard-blink-led",
|
|
487
506
|
"diagram": "breadboard",
|
|
@@ -773,6 +792,25 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
773
792
|
"dsl": 'entity-structure "Acme Inc. \u2014 post Series A"\nentity acme "Acme Inc." corp@DE\nentity founders "Founders (2)" individual\nentity seed "Seed Fund I" lp@DE\nentity lead "Sequoia Series A" lp@DE\nentity angels "Angel group" individual\nentity esop "Employee Option Pool" trust@DE\nfounders -> acme : 45%\nseed -> acme : 12%\nlead -> acme : 22%\nangels -> acme : 6%\nesop -> acme : 15%',
|
|
774
793
|
"notes": "## Scenario\n\nA startup attorney or CFO documents the post-Series A ownership table for a 409A valuation, board consent, or investor report. The cap table diagram makes the dilution story visual \u2014 founders can immediately see their post-money percentage, and the VC can verify their ownership stake before signing the term sheet.\n\n## Annotation key\n\n- `-> acme : 45%` \u2014 ownership arrow with percentage label; all percentages should sum to 100%\n- `individual` \u2014 natural person (founder, angel)\n- `lp` \u2014 institutional investor entity (fund/LP)\n- `trust` \u2014 the ESOP/option pool (typically a Delaware trust or reserved pool)\n- `corp@DE` \u2014 the issuer (Delaware C-corp)\n\n## How to read\n\nAcme Inc. (Delaware C-corp) sits at the bottom as the issuer. Five shareholder classes flow down with their ownership arrows: founders at 45%, the lead Series A investor at 22%, the employee option pool at 15%, the seed fund at 12%, and angels at 6%. Percentages sum to 100%, representing a clean fully-diluted cap table on the day of Series A close."
|
|
775
794
|
},
|
|
795
|
+
{
|
|
796
|
+
"slug": "erd-billing-ledger-audit-trail",
|
|
797
|
+
"diagram": "erd",
|
|
798
|
+
"title": "Billing ledger and audit trail",
|
|
799
|
+
"description": "Crow's-foot ERD for an immutable SaaS billing ledger with customers, invoices, payments, refunds, ledger entries, and audit events.",
|
|
800
|
+
"standard": "Crow's-foot ERD",
|
|
801
|
+
"tags": [
|
|
802
|
+
"erd",
|
|
803
|
+
"billing",
|
|
804
|
+
"ledger",
|
|
805
|
+
"audit-trail",
|
|
806
|
+
"finance",
|
|
807
|
+
"schema"
|
|
808
|
+
],
|
|
809
|
+
"complexity": 3,
|
|
810
|
+
"featured": false,
|
|
811
|
+
"dsl": 'erd\ntitle: "Billing Ledger"\ndirection: LR\n\ntable Customer {\n customer_id uuid PK\n email varchar UK\n billing_currency char NN\n}\ntable Subscription {\n subscription_id uuid PK\n customer_id uuid FK -> Customer.customer_id\n status varchar NN\n current_period_end timestamptz\n}\ntable Invoice {\n invoice_id uuid PK\n customer_id uuid FK -> Customer.customer_id\n subscription_id uuid FK -> Subscription.subscription_id\n number varchar UK\n total_cents bigint NN\n status varchar NN\n}\ntable Payment {\n payment_id uuid PK\n invoice_id uuid FK -> Invoice.invoice_id\n provider_ref varchar UK\n amount_cents bigint NN\n captured_at timestamptz\n}\ntable Refund {\n refund_id uuid PK\n payment_id uuid FK -> Payment.payment_id\n amount_cents bigint NN\n reason varchar\n}\ntable LedgerEntry {\n entry_id uuid PK\n customer_id uuid FK -> Customer.customer_id\n invoice_id uuid FK -> Invoice.invoice_id\n payment_id uuid FK -> Payment.payment_id\n refund_id uuid FK -> Refund.refund_id\n entry_type varchar NN\n amount_cents bigint NN\n posted_at timestamptz NN\n}\ntable AuditEvent {\n event_id uuid PK\n actor_id uuid\n entity_type varchar NN\n entity_id uuid NN\n action varchar NN\n created_at timestamptz NN\n}\n\nref Subscription.customer_id many-mandatory -- one-mandatory Customer.customer_id : "belongs to"\nref Invoice.customer_id many-mandatory -- one-mandatory Customer.customer_id : "billed to"\nref Invoice.subscription_id many-optional .. one-optional Subscription.subscription_id : "for plan"\nref Payment.invoice_id many-optional -- one-mandatory Invoice.invoice_id : "settles"\nref Refund.payment_id many-optional -- one-mandatory Payment.payment_id : "reverses"\nref LedgerEntry.customer_id many-mandatory -- one-mandatory Customer.customer_id : "posts for"\nref LedgerEntry.invoice_id many-optional .. one-optional Invoice.invoice_id : "source invoice"\nref LedgerEntry.payment_id many-optional .. one-optional Payment.payment_id : "source payment"\nref LedgerEntry.refund_id many-optional .. one-optional Refund.refund_id : "source refund"',
|
|
812
|
+
"notes": "## Scenario\n\nBilling schemas become risky when money movement and auditability are mixed into mutable order tables. This ERD separates commercial objects from immutable ledger entries, making it clear which facts can change and which entries are accounting evidence.\n\n## Annotation key\n\n- `LedgerEntry` points optionally to invoices, payments, and refunds because each entry has exactly one accounting source.\n- Solid `--` relationships show identifying operational ownership.\n- Dashed `..` relationships show optional audit/source references that should not control the lifecycle of the ledger row."
|
|
813
|
+
},
|
|
776
814
|
{
|
|
777
815
|
"slug": "erd-ecommerce-schema",
|
|
778
816
|
"diagram": "erd",
|
|
@@ -940,6 +978,24 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
940
978
|
"dsl": "flowchart TD\n commit([Push to main]) --> build[Build artifact]\n build --> unit{Unit tests pass?}\n unit -->|No| fail([Fail build])\n unit -->|Yes| scan[Security scan]\n scan --> vuln{High-severity CVEs?}\n vuln -->|Yes| fail\n vuln -->|No| stage[Deploy to staging]\n stage --> smoke{Smoke tests green?}\n smoke -->|No| fail\n smoke -->|Yes| approve{Manual approval?}\n approve -->|No| wait([Await approver])\n approve -->|Yes| prod[Deploy to production]\n prod --> health{Post-deploy health check?}\n health -->|Yes| done([Release complete])\n health -->|No| rollback[Automatic rollback]\n rollback --> done",
|
|
941
979
|
"notes": "## Scenario\n\nA platform engineer is documenting the team's trunk-based pipeline for a new-hire runbook. The diagram makes the four automated gates (tests \u2192 scan \u2192 smoke \u2192 post-deploy health) and the single human gate (manual approval) obvious at a glance, and shows that every failure path terminates the pipeline rather than silently continuing.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; start and terminal nodes\n- `{\u2026}` \u2014 diamond; automated or manual gate\n- `[\u2026]` \u2014 rectangle; build / deploy / scan step\n- `-->|Yes/No|` \u2014 branch labels on each gate\n\n## How to read\n\nStart at *Push to main*. Every diamond is a gate \u2014 a *No* on any of unit tests, CVE scan, or smoke tests terminates at *Fail build*. Manual approval is the only human gate; it can park the pipeline at *Await approver* without failing. The post-deploy health check guards production: a failure triggers automatic rollback, which still completes at *Release complete* because the rollback itself is a successful outcome."
|
|
942
980
|
},
|
|
981
|
+
{
|
|
982
|
+
"slug": "flowchart-insurance-claim-adjudication",
|
|
983
|
+
"diagram": "flowchart",
|
|
984
|
+
"title": "Insurance claim adjudication",
|
|
985
|
+
"description": "ISO-style flowchart for a claims team triaging coverage, fraud risk, document completeness, manual review, and payment or denial outcomes.",
|
|
986
|
+
"standard": "ISO 5807:1985",
|
|
987
|
+
"tags": [
|
|
988
|
+
"flowchart",
|
|
989
|
+
"insurance",
|
|
990
|
+
"claims",
|
|
991
|
+
"adjudication",
|
|
992
|
+
"manual-review"
|
|
993
|
+
],
|
|
994
|
+
"complexity": 3,
|
|
995
|
+
"featured": false,
|
|
996
|
+
"dsl": "flowchart LR\n start([Claim submitted])\n intake[/Capture FNOL data/]\n docs{Documents complete?}\n request[Request missing documents]\n coverage{Policy active on loss date?}\n deny1[Issue coverage denial]\n fraud{Fraud score high?}\n review[[Manual SIU review]]\n liability{Liability accepted?}\n estimate[Calculate covered amount]\n approve{Adjuster approval?}\n pay[(Payment ledger)]\n denial[Send denial letter]\n close([Close claim])\n\n start --> intake\n intake --> docs\n docs -->|No| request\n request -.->|Resubmitted| docs\n docs -->|Yes| coverage\n coverage -->|No| deny1\n deny1 --> close\n coverage -->|Yes| fraud\n fraud -->|Yes| review\n review --> liability\n fraud -->|No| liability\n liability -->|No| denial\n denial --> close\n liability -->|Yes| estimate\n estimate --> approve\n approve -->|Needs changes| estimate\n approve -->|Approved| pay\n pay --> close",
|
|
997
|
+
"notes": "## Scenario\n\nClaim adjudication is not a straight line. The same claim can bounce for missing documents, route to special investigation, return for estimate changes, or close through denial. A flowchart is appropriate here because the core question is operational routing, not ownership lanes or event semantics.\n\n## Annotation key\n\n- Parallelogram `[/.../]` marks intake data capture.\n- `[[...]]` marks a predefined manual review subprocess.\n- Dotted retry edge shows a resubmission loop without making it the main path."
|
|
998
|
+
},
|
|
943
999
|
{
|
|
944
1000
|
"slug": "flowchart-order-fulfillment",
|
|
945
1001
|
"diagram": "flowchart",
|
|
@@ -1406,6 +1462,26 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1406
1462
|
"dsl": 'network "DC Fabric"\n layout: spine-leaf\n spines: sp1 sp2\n leaves: lf1 lf2 lf3 lf4\n server h1\n server h2\n server h3\n lf1 -- h1 : 25G\n lf2 -- h2 : 25G\n lf4 -- h3 : 25G',
|
|
1407
1463
|
"notes": "## Scenario\n\nA data-center architect wants the fabric drawn without hand-typing every spine-to-leaf cable. In `layout: spine-leaf` mode you declare the spines and leaves, and the engine **auto-meshes every leaf to every spine** \u2014 here that's 2 \xD7 4 = 8 generated links \u2014 leaving you to add only the host attachments.\n\n## What the diagram shows\n\n- **`spines:` / `leaves:`** declare the two fabric rows. The devices don't need a separate `kind` line \u2014 spines become L3 switches, leaves become switches.\n- **Auto-mesh** \u2014 every spine\u2194leaf link is generated; you never type them. Add or remove a leaf and the mesh updates.\n- **Host attachments** \u2014 `lf1 -- h1 : 25G` hangs a server below its leaf at 25 Gbps.\n\n## Annotation key\n\n| Element | Meaning |\n|---|---|\n| Top row | Spine switches |\n| Middle row | Leaf switches (fully meshed to spines) |\n| Bottom row | Hosts, under their leaf |\n\nThis is the modern east-west fabric; for a traditional north-south campus use `layout: tiered` with `tier:` bands instead."
|
|
1408
1464
|
},
|
|
1465
|
+
{
|
|
1466
|
+
"slug": "network-zero-trust-cloud-vpc",
|
|
1467
|
+
"diagram": "network",
|
|
1468
|
+
"title": "Zero-trust cloud VPC topology",
|
|
1469
|
+
"description": "Network topology for a zero-trust SaaS VPC with VPN entry, DMZ, private application subnet, database subnet, firewall segmentation, and annotated VPN/fiber/trunk links.",
|
|
1470
|
+
"standard": "Cisco-convention topology icons + security-zone topology",
|
|
1471
|
+
"tags": [
|
|
1472
|
+
"network",
|
|
1473
|
+
"zero-trust",
|
|
1474
|
+
"vpc",
|
|
1475
|
+
"dmz",
|
|
1476
|
+
"vpn",
|
|
1477
|
+
"firewall",
|
|
1478
|
+
"cloud"
|
|
1479
|
+
],
|
|
1480
|
+
"complexity": 3,
|
|
1481
|
+
"featured": false,
|
|
1482
|
+
"dsl": 'network "Zero-trust SaaS VPC"\n layout: tiered\n internet inet "Internet"\n cloud idp "Identity Provider"\n vpngw vpn "Client VPN" tier: edge\n firewall fw "Segmentation FW" tier: edge\n loadbalancer alb "Public ALB" tier: distribution\n\n zone dmz "DMZ" {\n proxy edgeproxy "Reverse Proxy" tier: distribution\n }\n subnet appnet "10.20.10.0/24" {\n server api1 "API 1" ip: 10.20.10.11\n server api2 "API 2" ip: 10.20.10.12\n }\n subnet dbnet "10.20.30.0/24" {\n storage db "Postgres HA" ip: 10.20.30.20\n }\n zone admin "Admin Zone" {\n laptop admin1 "Admin Laptop"\n }\n\n inet -- alb : fiber 10G\n inet -- vpn : vpn\n idp -- vpn : vpn "OIDC"\n vpn -- fw : vpn "device posture"\n alb -- edgeproxy : 1G\n edgeproxy -- fw : trunk vlan: 110\n fw -- api1 : access vlan: 210 1G\n fw -- api2 : access vlan: 210 1G\n fw -- db : access vlan: 230 1G\n admin1 -- vpn : wireless vpn',
|
|
1483
|
+
"notes": "## Scenario\n\nZero-trust diagrams need to show both the physical/logical topology and the policy boundary: public traffic reaches only the DMZ, administrators enter through VPN and identity checks, and application servers reach the database through a segmented firewall path.\n\n## Annotation key\n\n- `zone` and `subnet` groups distinguish security policy from IP address space.\n- VPN links are dashed and annotated, making identity/device-posture paths visible.\n- VLAN labels document segmentation at the firewall boundary."
|
|
1484
|
+
},
|
|
1409
1485
|
{
|
|
1410
1486
|
"slug": "orgchart-matrix-reporting",
|
|
1411
1487
|
"diagram": "orgchart",
|
|
@@ -1951,6 +2027,25 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1951
2027
|
"dsl": "sequence\n participant Factory\n Factory -> *Worker : \xABcreate\xBB\n o-> Worker : external trigger\n Worker -x : fire-and-forget\n destroy Worker",
|
|
1952
2028
|
"notes": 'UML interactions model not just messages but the *birth and death* of participants \u2014 the part most text-to-diagram tools skip. This tiny diagram shows all four markers.\n\n**Create.** `Factory -> *Worker` \u2014 the `*` prefix creates `Worker`; its arrow lands on the *side of the new participant\'s box*, which appears partway down rather than at the top, the UML convention for "instantiated here."\n\n**Found and lost.** `o-> Worker` is a *found* message \u2014 it starts from a filled circle, meaning "from outside the modelled scope" (an external trigger). `Worker -x` is a *lost* message \u2014 it ends at a circle, a fire-and-forget whose receiver isn\'t shown.\n\n**Destroy.** `destroy Worker` terminates the lifeline with the \u2715 marker, so the diagram shows exactly when the object ceases to exist.'
|
|
1953
2029
|
},
|
|
2030
|
+
{
|
|
2031
|
+
"slug": "sequence-retry-timeout-circuit-breaker",
|
|
2032
|
+
"diagram": "sequence",
|
|
2033
|
+
"title": "Retry, timeout, and circuit breaker",
|
|
2034
|
+
"description": "UML sequence diagram for a gateway calling a payment service through a circuit breaker, with retry attempts, timeout handling, a break fragment for an open breaker, and an asynchronous fallback event.",
|
|
2035
|
+
"standard": "OMG UML 2.5.1",
|
|
2036
|
+
"tags": [
|
|
2037
|
+
"sequence",
|
|
2038
|
+
"uml",
|
|
2039
|
+
"retry",
|
|
2040
|
+
"timeout",
|
|
2041
|
+
"circuit-breaker",
|
|
2042
|
+
"resilience"
|
|
2043
|
+
],
|
|
2044
|
+
"complexity": 3,
|
|
2045
|
+
"featured": false,
|
|
2046
|
+
"dsl": 'sequence "Checkout payment resilience"\n autonumber 1 1\n actor Client\n boundary API as "Checkout API"\n control Breaker as "Circuit Breaker"\n participant Payment as "Payment Provider"\n queue Jobs as "Fallback Queue"\n\n Client ->+ API : POST /checkout/pay\n API -> Breaker : allowRequest()\n alt [breaker closed]\n Breaker --> API : permit\n loop (1,3)\n API ->+ Payment : authorize(amount)\n alt [response before timeout]\n Payment -->- API : auth result\n break [authorized]\n API -->- Client : 200 Authorized\n end\n else [timeout]\n API -> Breaker : recordFailure(timeout)\n API ->> Jobs : enqueue retry context\n end\n end\n API -->- Client : 202 Pending verification\n else [breaker open]\n Breaker --> API : reject\n API ->> Jobs : enqueue deferred payment\n API -->- Client : 503 Retry later\n end',
|
|
2047
|
+
"notes": "## Scenario\n\nA checkout API must protect itself from a slow or failing payment provider. The diagram makes the resilience policy reviewable: the gateway checks the breaker, retries bounded attempts, records timeouts, and falls back to asynchronous recovery instead of blocking the customer forever.\n\n## Annotation key\n\n- `loop (1,3)` documents the bounded retry policy.\n- `alt` separates fast responses, timeouts, and open-breaker rejection.\n- `break [authorized]` exits the retry loop once a successful authorization arrives.\n- `->>` marks asynchronous fallback work queued outside the request path."
|
|
2048
|
+
},
|
|
1954
2049
|
{
|
|
1955
2050
|
"slug": "sfc-bake-cool-concurrent",
|
|
1956
2051
|
"diagram": "sfc",
|
|
@@ -2224,6 +2319,24 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
2224
2319
|
"dsl": 'state "E-Commerce Order Lifecycle"\n\ninitial i\ni -> Pending\n\nPending -> Confirmed : place_order [items_in_stock] / reserveInventory()\nPending -> Cancelled : cancel\n\nchoice PayRoute\nConfirmed -> PayRoute : pay\nPayRoute -> Processing : [method == "card"]\nPayRoute -> Processing : [method == "wallet"]\nPayRoute -> AwaitingTransfer : [method == "bank_transfer"]\n\nAwaitingTransfer -> Processing : transfer_received [amount_correct]\nAwaitingTransfer -> Cancelled : transfer_timeout\n\ncomposite Processing {\n initial pi\n final pf\n\n pi -> Picking\n Picking -> Packing : picked / updateWarehouse()\n Packing -> Shipped : label_printed\n Shipped -> pf : carrier_confirmed\n}\n\nProcessing -> Delivered : delivered / notifyCustomer()\nProcessing -> Failed : fulfillment_error\n\nDelivered -> Refunded : return_request [within_30_days] / initiateRefund()\nFailed -> Pending : retry [attempt < 3]\nFailed -> Cancelled : retry [attempt >= 3]\n\nfinal f\nDelivered -> f\nRefunded -> f\nCancelled -> f\n\nnote right_of AwaitingTransfer : SLA: 48 h before timeout.',
|
|
2225
2320
|
"notes": 'Order state machines are one of the most common backend design artifacts, and one of the most commonly under-specified. Teams often start with a simple enum (`PENDING / PAID / SHIPPED / DELIVERED`) and then bolt on edge cases over time: partial shipments, payment holds, carrier errors, refund windows. Six months later the enum has twelve values, the transition logic is scattered across three services, and nobody can explain what sequence of events gets an order from `FAILED` to `CANCELLED` versus from `FAILED` back to `PENDING`. A UML state diagram catches all of this upfront.\n\n**Guard conditions on `place_order`.** The transition from `Pending` to `Confirmed` carries `[items_in_stock]` \u2014 a guard. Guards are boolean predicates that must be true for the transition to fire even when the trigger event (`place_order`) occurs. If the guard is false, the trigger is silently absorbed and the system stays in `Pending`. In practice this means inventory is checked synchronously during order placement, and the transition only proceeds if stock is available. The action `/ reserveInventory()` fires when the transition does go through, atomically.\n\n**Choice pseudo-state for payment routing.** `PayRoute` is a UML choice pseudo-state (drawn as a diamond). When the `pay` trigger fires from `Confirmed`, the machine immediately evaluates the guards on all outgoing transitions from `PayRoute`. If `method == "card"` or `method == "wallet"`, control goes directly to `Processing`. If `method == "bank_transfer"`, it goes to `AwaitingTransfer` \u2014 a waiting state with its own 48-hour SLA note. Choice pseudo-states do not dwell; they route. This is the correct model for "take different paths based on a value computed at runtime."\n\n**Composite state for fulfillment.** `Processing` is a composite state \u2014 it contains its own internal state machine with `Picking`, `Packing`, and `Shipped`. From the outside, the system is "in Processing" whether it\'s picking, packing, or confirming with the carrier. From the inside, the sub-machine tracks exactly where the warehouse is. The composite state has its own `initial` and `final` pseudo-states: the machine enters at `pi` (starts picking) and exits through `pf` (carrier confirmed), which fires the outer transition to `Delivered`. Cross-composite transitions to `Failed` are also valid \u2014 a fulfillment error at any sub-state terminates the Processing phase and moves to the outer `Failed` state.\n\n**Retry with bounded attempts.** `Failed` has two outgoing transitions back to `Pending` and `Cancelled`, both triggered by `retry` but guarded on `attempt`. This is the explicit model for "retry up to N times, then give up." Without the state diagram, this logic typically lives in a cron job or a dead-letter queue processor that nobody fully understands. Here it is the specification: anyone reading the diagram knows the retry policy without digging through queue configurations.\n\n**Final state convergence.** `Delivered`, `Refunded`, and `Cancelled` all transition to the same `final` pseudo-state. In implementation, "final" might mean the order record is archived, the event bus receives an `order.closed` event, and no further state transitions are accepted. The model is silent on what happens after final \u2014 that\'s intentional. The state machine is done; downstream processes (analytics, accounting, data retention) are separate concerns.'
|
|
2226
2321
|
},
|
|
2322
|
+
{
|
|
2323
|
+
"slug": "state-subscription-lifecycle",
|
|
2324
|
+
"diagram": "state",
|
|
2325
|
+
"title": "SaaS subscription lifecycle",
|
|
2326
|
+
"description": "UML statechart for a subscription moving through trial, active service, payment recovery, pause, cancellation, and reactivation.",
|
|
2327
|
+
"standard": "OMG UML 2.5.1",
|
|
2328
|
+
"tags": [
|
|
2329
|
+
"statechart",
|
|
2330
|
+
"subscription",
|
|
2331
|
+
"billing",
|
|
2332
|
+
"lifecycle",
|
|
2333
|
+
"guards"
|
|
2334
|
+
],
|
|
2335
|
+
"complexity": 3,
|
|
2336
|
+
"featured": false,
|
|
2337
|
+
"dsl": 'state "Subscription Lifecycle" [direction: LR]\n\ninitial start\nstart -> Trialing\n\nTrialing -> Active : trial_end [payment_method_valid] / startBilling()\nTrialing -> Incomplete : trial_end [payment_method_missing] / requestPaymentMethod()\nTrialing -> Cancelled : cancel\n\ncomposite Active {\n entry / provisionWorkspace()\n exit / syncEntitlements()\n initial ai\n ai -> Current\n Current -> GracePeriod : invoice_failed\n GracePeriod -> Current : payment_succeeded / restoreAccess()\n GracePeriod -> PastDue : grace_expired\n PastDue -> Current : payment_succeeded / clearDunning()\n final af\n Current -> af : cancel_at_period_end\n}\n\nActive -> Paused : pause [plan_allows_pause] / suspendBilling()\nPaused -> Active : resume / resumeBilling()\nActive -> Cancelled : cancel_now / revokeAccess()\nIncomplete -> Active : payment_method_added / retryInvoice()\nIncomplete -> Cancelled : expires\nActive -> Cancelled : period_end\nCancelled -> Active : reactivate [within_retention_window] / restoreSubscription()\n\nfinal done\nCancelled -> done : purge_after_retention\n\nnote right_of Active : Composite state keeps dunning detail inside active service.',
|
|
2338
|
+
"notes": "## Scenario\n\nSubscription logic is where simple status enums drift out of sync with billing providers. This statechart makes the product contract explicit: trial conversion, incomplete setup, dunning recovery, pause, cancellation, and reactivation are separate transitions with guards and actions.\n\n## Annotation key\n\n- `Active` is a composite state because payment recovery happens while the product is still notionally active.\n- Guard labels such as `[payment_method_valid]` document provider-dependent branching.\n- Entry and exit actions mark entitlement provisioning and sync points."
|
|
2339
|
+
},
|
|
2227
2340
|
{
|
|
2228
2341
|
"slug": "state-traffic-light",
|
|
2229
2342
|
"diagram": "state",
|
|
@@ -3068,5 +3181,5 @@ function repairHint(type) {
|
|
|
3068
3181
|
}
|
|
3069
3182
|
|
|
3070
3183
|
export { DIAGRAM_REGISTRY, DIAGRAM_SINCE, getAllDiagramTypes, getDiagramMeta, getDiagramSince, getExamples, getSyntax, listDiagrams, renderDsl, resolveDiagramType, validateDsl };
|
|
3071
|
-
//# sourceMappingURL=chunk-
|
|
3072
|
-
//# sourceMappingURL=chunk-
|
|
3184
|
+
//# sourceMappingURL=chunk-OTSVMKII.js.map
|
|
3185
|
+
//# sourceMappingURL=chunk-OTSVMKII.js.map
|