flowchart-sequence-designer 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -202,7 +202,7 @@ function nextId(prefix, existing) {
202
202
  let max = 0;
203
203
  for (const item of existing) {
204
204
  const match = re.exec(item.id);
205
- if (match) {
205
+ if (match?.[1]) {
206
206
  const n = parseInt(match[1], 10);
207
207
  if (n > max) max = n;
208
208
  }
@@ -426,9 +426,15 @@ function escapeXML(s) {
426
426
  }
427
427
  function sanitizeForSVG(s) {
428
428
  let clean = s;
429
- clean = clean.replace(/<\/?[a-zA-Z][^>]*>/g, "");
430
- clean = clean.replace(/\b(?:javascript|data|vbscript)\s*:/gi, "");
431
- clean = clean.replace(/\bon[a-z]+\s*=/gi, "");
429
+ while (/<[a-zA-Z/][^>]{0,500}>/g.test(clean)) {
430
+ clean = clean.replace(/<[a-zA-Z/][^>]{0,500}>/g, "");
431
+ }
432
+ while (/\b(?:javascript|data|vbscript)\s*:/gi.test(clean)) {
433
+ clean = clean.replace(/\b(?:javascript|data|vbscript)\s*:/gi, "");
434
+ }
435
+ while (/\bon[a-z]+\s*=/gi.test(clean)) {
436
+ clean = clean.replace(/\bon[a-z]+\s*=/gi, "");
437
+ }
432
438
  clean = clean.replace(/\x00/g, "");
433
439
  return escapeXML(clean);
434
440
  }
@@ -767,9 +773,15 @@ var MAX_IMPORT_LENGTH = 2 * 1024 * 1024;
767
773
  function sanitizeLabel(raw) {
768
774
  let s = raw;
769
775
  s = s.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
770
- s = s.replace(/<\/?[a-zA-Z][^>]*>/g, "");
771
- s = s.replace(/\b(?:javascript|data|vbscript)\s*:/gi, "");
772
- s = s.replace(/\bon[a-z]+\s*=/gi, "");
776
+ while (/<[a-zA-Z/][^>]{0,500}>/g.test(s)) {
777
+ s = s.replace(/<[a-zA-Z/][^>]{0,500}>/g, "");
778
+ }
779
+ while (/\b(?:javascript|data|vbscript)\s*:/gi.test(s)) {
780
+ s = s.replace(/\b(?:javascript|data|vbscript)\s*:/gi, "");
781
+ }
782
+ while (/\bon[a-z]+\s*=/gi.test(s)) {
783
+ s = s.replace(/\bon[a-z]+\s*=/gi, "");
784
+ }
773
785
  if (s.length > MAX_LABEL_LENGTH) {
774
786
  s = s.slice(0, MAX_LABEL_LENGTH);
775
787
  }
@@ -785,11 +797,11 @@ function sanitizeURL(url) {
785
797
  // src/importers/mermaid.ts
786
798
  function parseNodeDecl(raw) {
787
799
  const patterns = [
788
- [/^(\w+)\{\{?"?(.+?)"?\}?\}$/, "diamond"],
789
- [/^(\w+)\(\("?(.+?)"?\)\)$/, "circle"],
790
- [/^(\w+)\[\/(.+?)\/\]$/, "parallelogram"],
791
- [/^(\w+)\[["']?(.+?)["']?\]$/, "rectangle"],
792
- [/^(\w+)\("?(.+?)"?\)$/, "rectangle"]
800
+ [/^(\w+)\{\{?"?([^}"]+)"?\}?\}$/, "diamond"],
801
+ [/^(\w+)\(\("?([^)"]+)"?\)\)$/, "circle"],
802
+ [/^(\w+)\[\/([^/\]]+)\/\]$/, "parallelogram"],
803
+ [/^(\w+)\[["']?([^\]"']+)["']?\]$/, "rectangle"],
804
+ [/^(\w+)\("?([^)"]+)"?\)$/, "rectangle"]
793
805
  ];
794
806
  for (const [re, shape] of patterns) {
795
807
  const m = raw.match(re);
@@ -797,7 +809,7 @@ function parseNodeDecl(raw) {
797
809
  }
798
810
  return null;
799
811
  }
800
- var EDGE_RE = /^(.+?)\s*(-\.->|-\.-|-->|---)(?:\|(.+?)\|)?\s*(.+)$/;
812
+ var EDGE_RE = /^(\S+)\s*(-\.->|-\.-|-->|---)(?:\|([^|]+)\|)?\s*(.+)$/;
801
813
  function detectStyle(connector) {
802
814
  return connector.startsWith("-.") ? "dashed" : "solid";
803
815
  }
@@ -915,7 +927,7 @@ function parseSequence(lines, title) {
915
927
  safeAddActor(actorMatch[1].trim());
916
928
  continue;
917
929
  }
918
- const msgMatch = trimmed.match(/^(.+?)\s*(-->>|->>|-->|->)\s*(.+?):\s*(.+)$/);
930
+ const msgMatch = trimmed.match(/^(\w+)\s*(-->>|->>|-->|->)\s*(\w+):\s*(.+)$/);
919
931
  if (msgMatch) {
920
932
  const from = safeAddActor(msgMatch[1].trim());
921
933
  const arrow = msgMatch[2];
@@ -940,7 +952,7 @@ function fromMermaid(mermaid) {
940
952
  if (mermaid.length > MAX_IMPORT_LENGTH) {
941
953
  throw new Error(`Import aborted: input exceeds the maximum of ${MAX_IMPORT_LENGTH} characters`);
942
954
  }
943
- const cleaned = mermaid.replace(/mermaid\.initialize\([\s\S]*?\)\s*;?/g, "");
955
+ const cleaned = mermaid.replace(/mermaid\.initialize\([^)]*\)\s*;?/g, "");
944
956
  const rawLines = cleaned.split("\n");
945
957
  let startIdx = 0;
946
958
  let title;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/model.ts","../src/core/ids.ts","../src/exporters/mermaid.ts","../src/exporters/plantuml.ts","../src/exporters/json.ts","../src/exporters/svg.ts","../src/core/flowchart.ts","../src/core/sequence.ts","../src/core/sanitize.ts","../src/importers/mermaid.ts","../src/importers/json.ts"],"sourcesContent":["/**\n * Headless entry point. Builders, the underlying `Model`, and every\n * exporter/importer are exported here. The editor React components live in\n * the `/ui` subpath export — `import { DiagramEditor } from\n * 'flowchart-sequence-designer/ui'` — so server-side or CLI consumers can\n * pull in this entry without dragging React along.\n */\n\n// Builders\nexport { flowchart, FlowchartBuilder } from './core/flowchart.js';\nexport { sequence, SequenceBuilder } from './core/sequence.js';\n\n// Model\nexport { Model } from './core/model.js';\n\n// Exporters\nexport { toMermaid } from './exporters/mermaid.js';\nexport { toPlantUML } from './exporters/plantuml.js';\nexport { toJSON } from './exporters/json.js';\nexport { toSVG, toPNG } from './exporters/svg.js';\n\n// Importers\nexport { fromMermaid } from './importers/mermaid.js';\nexport { fromJSON } from './importers/json.js';\n\n// Security utilities\nexport { sanitizeLabel, sanitizeURL } from './core/sanitize.js';\n\n// Types\nexport type {\n DiagramType,\n DiagramVariant,\n DiagramModel,\n DiagramNode,\n DiagramEdge,\n DiagramEdge as Edge,\n DiagramNode as Node,\n NodeShape,\n ExportFormat,\n SequenceMessage,\n} from './core/types.js';\n","import type {\n DiagramModel,\n DiagramNode,\n DiagramEdge,\n DiagramType,\n DiagramVariant,\n SequenceMessage,\n ValidationError,\n} from './types.js';\n\n/**\n * Mutable builder around a `DiagramModel`. Every public mutator returns\n * `this` so callers can chain (`new Model('flowchart').addNode(...).addEdge(...)`).\n * Call `.toJSON()` to extract a deep-cloned plain model suitable for\n * serialization or for handing to the editor components.\n *\n * All add/update operations validate immediately and throw on collisions or\n * dangling references. For non-throwing, batch-style structural checks call\n * `.validate()` instead.\n */\nexport class Model {\n private data: DiagramModel;\n\n /**\n * Create an empty model.\n *\n * @param type Top-level kind — `flowchart` or `sequence`.\n * @param title Optional human-readable title.\n * @param variant Optional UI variant (flowchart models only).\n */\n constructor(type: DiagramType, title?: string, variant?: DiagramVariant) {\n this.data = {\n type,\n ...(variant ? { variant } : {}),\n title,\n nodes: [],\n edges: [],\n actors: [],\n messages: [],\n };\n }\n\n /**\n * Rehydrate a `Model` from a previously serialized `DiagramModel`. The\n * incoming data is deep-cloned, so future mutations on the returned `Model`\n * do not affect the caller's object.\n */\n static fromData(data: DiagramModel): Model {\n const m = new Model(data.type, data.title, data.variant);\n m.data = structuredClone(data);\n return m;\n }\n\n /** Set the UI variant. No-op semantics for sequence models. */\n setVariant(variant: DiagramVariant): this {\n this.data.variant = variant;\n return this;\n }\n\n /**\n * Append a node. Throws if a node with the same id already exists. The\n * input is shallow-cloned, so later mutations of the caller's object do\n * not leak in.\n */\n addNode(node: DiagramNode): this {\n if (this.data.nodes.find((n) => n.id === node.id)) {\n throw new Error(`Node with id \"${node.id}\" already exists`);\n }\n this.data.nodes.push({ ...node });\n return this;\n }\n\n /**\n * Patch an existing node in place. Throws if the id is not found. The id\n * field itself cannot be patched — to rename, remove + re-add.\n */\n updateNode(id: string, patch: Partial<Omit<DiagramNode, 'id'>>): this {\n const node = this.data.nodes.find((n) => n.id === id);\n if (!node) throw new Error(`Node \"${id}\" not found`);\n const { __proto__, constructor, ...safe } = patch as Record<string, unknown>;\n Object.assign(node, safe);\n return this;\n }\n\n /**\n * Remove a node and every edge that referenced it as `from` or `to`. Safe\n * to call on a missing id (no-op).\n */\n removeNode(id: string): this {\n this.data.nodes = this.data.nodes.filter((n) => n.id !== id);\n this.data.edges = this.data.edges.filter((e) => e.from !== id && e.to !== id);\n return this;\n }\n\n /**\n * Append an edge. Throws on duplicate id or if either endpoint references\n * an unknown node — the model never holds dangling edges from this entry\n * point. (Importers can still construct dangling edges; call `validate()`\n * to detect them.)\n */\n addEdge(edge: DiagramEdge): this {\n if (this.data.edges.find((e) => e.id === edge.id)) {\n throw new Error(`Edge with id \"${edge.id}\" already exists`);\n }\n if (!this.data.nodes.find((n) => n.id === edge.from)) {\n throw new Error(`Edge \"${edge.id}\" references unknown source node \"${edge.from}\"`);\n }\n if (!this.data.nodes.find((n) => n.id === edge.to)) {\n throw new Error(`Edge \"${edge.id}\" references unknown target node \"${edge.to}\"`);\n }\n this.data.edges.push({ ...edge });\n return this;\n }\n\n /**\n * Surface structural problems without throwing. Returns an array of\n * `ValidationError`s; empty array means the model is well-formed. Used by\n * the editor's status banner and by external tooling.\n */\n validate(): ValidationError[] {\n const errors: ValidationError[] = [];\n const nodeIds = new Set<string>();\n for (const n of this.data.nodes) {\n if (nodeIds.has(n.id))\n errors.push({\n kind: 'duplicate-node-id',\n id: n.id,\n message: `Duplicate node id \"${n.id}\"`,\n });\n nodeIds.add(n.id);\n }\n const edgeIds = new Set<string>();\n for (const e of this.data.edges) {\n if (edgeIds.has(e.id))\n errors.push({\n kind: 'duplicate-edge-id',\n id: e.id,\n message: `Duplicate edge id \"${e.id}\"`,\n });\n edgeIds.add(e.id);\n if (!nodeIds.has(e.from))\n errors.push({\n kind: 'dangling-from',\n id: e.id,\n message: `Edge \"${e.id}\" references unknown source node \"${e.from}\"`,\n });\n if (!nodeIds.has(e.to))\n errors.push({\n kind: 'dangling-to',\n id: e.id,\n message: `Edge \"${e.id}\" references unknown target node \"${e.to}\"`,\n });\n }\n return errors;\n }\n\n /** Remove an edge by id. Safe to call on a missing id (no-op). */\n removeEdge(id: string): this {\n this.data.edges = this.data.edges.filter((e) => e.id !== id);\n return this;\n }\n\n /** Append a sequence actor. Duplicate names are silently ignored. */\n addActor(name: string): this {\n if (!this.data.actors!.includes(name)) {\n this.data.actors!.push(name);\n }\n return this;\n }\n\n /**\n * Append a sequence message. The actors referenced by `from`/`to` are not\n * validated here — callers are expected to register them via `addActor()`\n * first.\n */\n addMessage(message: SequenceMessage): this {\n this.data.messages!.push({ ...message });\n return this;\n }\n\n /**\n * Return a deep-cloned plain `DiagramModel`. Safe to mutate by the caller;\n * mutations do not flow back into this `Model`.\n */\n toJSON(): DiagramModel {\n return structuredClone(this.data);\n }\n}\n","/**\n * Mint the next available ID for a given prefix by scanning the existing\n * entities in a model.\n *\n * Avoids the classic collision pitfall of a module-level counter starting at\n * zero: if the model already contains `e1..e6` (e.g. from a preset or an\n * imported diagram), a counter that started at zero would produce a duplicate\n * `e1` on first use. By deriving from the model itself, generated IDs are\n * collision-proof against presets, imports, and concurrent editor instances.\n *\n * @example\n * nextId('node', model.nodes) // → 'node7' if model has node1..node6\n * nextId('e', model.edges) // → 'e1' if model has no edges yet\n * nextId('m', model.messages) // → 'm5' if model has m1..m4\n */\n/**\n * Returns a stateful id generator seeded from the current model. Use this\n * when a single operation needs to mint several IDs in succession (e.g.\n * duplicate or paste) — calling `nextId()` repeatedly against the same\n * snapshot would produce duplicates because the snapshot doesn't reflect\n * the freshly minted IDs.\n *\n * @example\n * const newNodeId = makeIdSource('node', model.nodes);\n * const a = newNodeId(); // → 'node7'\n * const b = newNodeId(); // → 'node8'\n */\nexport function makeIdSource(prefix: string, existing: Iterable<{ id: string }>): () => string {\n const first = nextId(prefix, existing);\n let counter = parseInt(first.slice(prefix.length), 10);\n return () => `${prefix}${counter++}`;\n}\n\nexport function nextId(prefix: string, existing: Iterable<{ id: string }>): string {\n const escaped = prefix.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const re = new RegExp(`^${escaped}(\\\\d+)$`);\n let max = 0;\n for (const item of existing) {\n const match = re.exec(item.id);\n if (match) {\n const n = parseInt(match[1]!, 10);\n if (n > max) max = n;\n }\n }\n return `${prefix}${max + 1}`;\n}\n","import type { DiagramModel, DiagramNode, DiagramEdge, SequenceMessage } from '../core/types.js';\n\nconst SHAPE_OPEN: Record<string, string> = {\n rectangle: '[',\n diamond: '{',\n circle: '((',\n parallelogram: '[/',\n};\nconst SHAPE_CLOSE: Record<string, string> = {\n rectangle: ']',\n diamond: '}',\n circle: '))',\n parallelogram: '/]',\n};\n\nfunction formatNode(node: DiagramNode): string {\n const shape = node.shape ?? 'rectangle';\n const open = SHAPE_OPEN[shape] ?? '[';\n const close = SHAPE_CLOSE[shape] ?? ']';\n return ` ${node.id}${open}\"${node.label}\"${close}`;\n}\n\nfunction edgeArrow(edge: DiagramEdge): string {\n const style = edge.style ?? 'solid';\n const arrowhead = edge.arrowhead ?? 'arrow';\n // Mermaid flowcharts only have solid and dashed; dotted collapses to dashed.\n if (style === 'dashed' || style === 'dotted') return arrowhead === 'none' ? '-.-' : '-.->';\n return arrowhead === 'none' ? '---' : '-->';\n}\n\nfunction formatEdge(edge: DiagramEdge): string {\n const arrow = edgeArrow(edge);\n return edge.label\n ? ` ${edge.from} ${arrow}|\"${edge.label}\"| ${edge.to}`\n : ` ${edge.from} ${arrow} ${edge.to}`;\n}\n\nfunction exportFlowchart(model: DiagramModel): string {\n const lines: string[] = ['graph TD'];\n if (model.title) lines.unshift(`---\\ntitle: ${model.title}\\n---`);\n for (const node of model.nodes) lines.push(formatNode(node));\n for (const edge of model.edges) lines.push(formatEdge(edge));\n return lines.join('\\n');\n}\n\nfunction msgArrow(msg: SequenceMessage): string {\n return msg.style === 'dashed' ? '-->>' : '->>';\n}\n\nfunction exportSequence(model: DiagramModel): string {\n const lines: string[] = ['sequenceDiagram'];\n if (model.title) lines.unshift(`---\\ntitle: ${model.title}\\n---`);\n for (const actor of model.actors ?? []) lines.push(` participant ${actor}`);\n for (const msg of model.messages ?? []) {\n lines.push(` ${msg.from}${msgArrow(msg)}${msg.to}: ${msg.label}`);\n }\n return lines.join('\\n');\n}\n\n/**\n * Serialize a `DiagramModel` to Mermaid source. Dispatches between\n * `graph TD` (flowchart) and `sequenceDiagram` based on `model.type`.\n *\n * **Round-trip notes (flowchart):**\n * - Node shapes `rectangle`, `diamond`, `circle`, `parallelogram` map to\n * `[ ]`, `{ }`, `(( ))`, `[/ /]` respectively.\n * - Edge style `solid` → `-->`, `dashed` and `dotted` → `-.->` (Mermaid\n * collapses dotted to dashed). `arrowhead: 'none'` strips the head.\n * - `waypoint`, `metadata`, and `variant` are **dropped** — Mermaid has no\n * way to encode routing or arbitrary metadata.\n *\n * **Round-trip notes (sequence):**\n * - Message style `solid` → `->>`, `dashed` → `-->>`.\n */\nexport function toMermaid(model: DiagramModel): string {\n return model.type === 'sequence' ? exportSequence(model) : exportFlowchart(model);\n}\n","import type { DiagramModel, DiagramNode, DiagramEdge, SequenceMessage } from '../core/types.js';\n\nfunction nodeShape(node: DiagramNode): [string, string] {\n switch (node.shape) {\n case 'diamond':\n return ['<>', '<>'];\n case 'circle':\n return ['(', ')'];\n case 'parallelogram':\n return ['/', '/'];\n default:\n return ['[', ']'];\n }\n}\n\nfunction exportFlowchart(model: DiagramModel): string {\n const lines: string[] = ['@startuml'];\n if (model.title) lines.push(`title ${model.title}`);\n lines.push('');\n\n for (const node of model.nodes) {\n const [open, close] = nodeShape(node);\n lines.push(`state \"${node.label}\" as ${node.id} ${open}${close}`);\n }\n lines.push('');\n\n for (const edge of model.edges) {\n const arrow =\n edge.style === 'dashed' ? '-[dashed]->' : edge.style === 'dotted' ? '-[dotted]->' : '-->';\n const label = edge.label ? ` : ${edge.label}` : '';\n lines.push(`${edge.from} ${arrow} ${edge.to}${label}`);\n }\n\n lines.push('@enduml');\n return lines.join('\\n');\n}\n\nfunction msgArrow(msg: SequenceMessage): string {\n return msg.style === 'dashed' ? '-->' : '->';\n}\n\nfunction exportSequence(model: DiagramModel): string {\n const lines: string[] = ['@startuml'];\n if (model.title) lines.push(`title ${model.title}`);\n lines.push('');\n\n for (const actor of model.actors ?? []) {\n lines.push(`participant ${actor}`);\n }\n lines.push('');\n\n for (const msg of model.messages ?? []) {\n lines.push(`${msg.from} ${msgArrow(msg)} ${msg.to} : ${msg.label}`);\n }\n\n lines.push('@enduml');\n return lines.join('\\n');\n}\n\n/**\n * Serialize a `DiagramModel` to PlantUML source. Dispatches between the\n * state-diagram form (flowchart) and the sequence-diagram form based on\n * `model.type`.\n *\n * **Round-trip notes (flowchart):**\n * - Edge style maps `solid` → `-->`, `dashed` → `-[dashed]->`,\n * `dotted` → `-[dotted]->`.\n * - Node shapes are emitted via the `state \"..\" as id < >` syntax; some\n * shape information is lossy (PlantUML state diagrams don't distinguish\n * every shape this package supports).\n * - `waypoint`, `metadata`, and `variant` are **dropped**.\n *\n * **Round-trip notes (sequence):**\n * - Actor order is preserved; message style `solid` → `->`, `dashed` → `-->`.\n */\nexport function toPlantUML(model: DiagramModel): string {\n return model.type === 'sequence' ? exportSequence(model) : exportFlowchart(model);\n}\n","import type { DiagramModel } from '../core/types.js';\n\n/**\n * Serialize a `DiagramModel` to pretty-printed JSON. This is the canonical\n * round-trip format: every field — including `variant`, `waypoint`,\n * `metadata.group`, and `metadata.answers` — survives a round trip through\n * `toJSON` + `fromJSON` unchanged.\n */\nexport function toJSON(model: DiagramModel): string {\n return JSON.stringify(model, null, 2);\n}\n","import type { DiagramModel, DiagramNode, DiagramEdge } from '../core/types.js';\n\n// Layout constants — kept in sync with src/ui/DiagramEditor.tsx\nconst NODE_H = 48;\nconst Q_BASE_H = 68;\nconst Q_ANS_ROW_H = 80;\nconst Q_CARD_PAD = 8;\nconst MIN_NODE_W = 120;\nconst MAX_NODE_W = 320;\nconst MIN_Q_W = 220;\nconst PADDING = 48;\nconst H_GAP = 80;\nconst V_GAP = 96;\n\nfunction estimateTextW(text: string, pxPerChar = 7.5): number {\n return text.length * pxPerChar;\n}\n\nfunction nodeWidth(label: string): number {\n return Math.min(MAX_NODE_W, Math.max(MIN_NODE_W, Math.ceil(estimateTextW(label) + 48)));\n}\n\nfunction answerCardW(ans: string): number {\n return Math.max(86, Math.ceil(Math.max(estimateTextW(ans, 7.5) + 20, 56) + 32));\n}\n\nfunction questionNodeW(node: DiagramNode): number {\n const answers = (node.metadata?.answers as string[] | undefined) ?? [];\n const headerW = estimateTextW(node.label, 8) + 80;\n if (answers.length === 0) return Math.max(MIN_Q_W, Math.ceil(headerW));\n const cardsW =\n answers.reduce((s, a) => s + answerCardW(a), 0) +\n (answers.length - 1) * Q_CARD_PAD +\n 2 * Q_CARD_PAD;\n return Math.max(MIN_Q_W, Math.ceil(Math.max(headerW, cardsW)));\n}\n\nfunction questionNodeH(answers: string[]): number {\n return Q_BASE_H + (answers.length === 0 ? 48 : Q_ANS_ROW_H);\n}\n\nfunction bezierPath(x1: number, y1: number, x2: number, y2: number): string {\n const dy = y2 - y1;\n const dyAbs = Math.abs(dy);\n const dxAbs = Math.abs(x2 - x1);\n const base = dy > 0 ? dyAbs * 0.55 : Math.max(90, dyAbs * 0.5 + dxAbs * 0.28);\n const curve = Math.max(36, Math.min(220, base));\n return `M ${x1} ${y1} C ${x1} ${y1 + curve}, ${x2} ${y2 - curve}, ${x2} ${y2}`;\n}\n\ninterface LayoutBox {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nfunction isQuestion(node: DiagramNode, variant: DiagramModel['variant']): boolean {\n return variant === 'question' && !!node.metadata?.answers;\n}\n\n/** Honor x/y on nodes if present; otherwise BFS-layer fallback. */\nfunction computeLayout(model: DiagramModel): Map<string, LayoutBox> {\n const boxes = new Map<string, LayoutBox>();\n const sized = model.nodes.map((n) => {\n const w = isQuestion(n, model.variant) ? questionNodeW(n) : nodeWidth(n.label);\n const h = isQuestion(n, model.variant)\n ? questionNodeH((n.metadata?.answers as string[] | undefined) ?? [])\n : NODE_H;\n return { node: n, w, h };\n });\n\n const allPositioned = sized.every(\n (s) => typeof s.node.x === 'number' && typeof s.node.y === 'number',\n );\n if (allPositioned) {\n for (const s of sized) {\n boxes.set(s.node.id, { x: s.node.x as number, y: s.node.y as number, w: s.w, h: s.h });\n }\n return boxes;\n }\n\n // BFS-layer fallback for un-positioned graphs (e.g. fresh imports).\n const inDeg = new Map(model.nodes.map((n) => [n.id, 0]));\n for (const e of model.edges) inDeg.set(e.to, (inDeg.get(e.to) ?? 0) + 1);\n\n const layers = new Map<string, number>();\n const queue = model.nodes.filter((n) => (inDeg.get(n.id) ?? 0) === 0).map((n) => n.id);\n for (const id of queue) layers.set(id, 0);\n let head = 0;\n while (head < queue.length) {\n const cur = queue[head++]!;\n const layer = layers.get(cur) ?? 0;\n for (const e of model.edges) {\n if (e.from === cur) {\n const next = layers.get(e.to) ?? -1;\n if (next < layer + 1) {\n layers.set(e.to, layer + 1);\n queue.push(e.to);\n }\n }\n }\n }\n model.nodes.forEach((n) => {\n if (!layers.has(n.id)) layers.set(n.id, 0);\n });\n\n const byLayer = new Map<number, typeof sized>();\n for (const s of sized) {\n const layer = layers.get(s.node.id) ?? 0;\n if (!byLayer.has(layer)) byLayer.set(layer, []);\n byLayer.get(layer)!.push(s);\n }\n\n let y = PADDING;\n for (const layer of [...byLayer.keys()].sort((a, b) => a - b)) {\n const row = byLayer.get(layer)!;\n let x = PADDING;\n let maxH = 0;\n for (const s of row) {\n boxes.set(s.node.id, { x, y, w: s.w, h: s.h });\n x += s.w + H_GAP;\n maxH = Math.max(maxH, s.h);\n }\n y += maxH + V_GAP;\n }\n return boxes;\n}\n\nfunction escapeXML(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n/**\n * Defence-in-depth sanitizer for SVG output. Strips dangerous patterns\n * before XML-escaping. Prevents script injection even if escapeXML were\n * somehow bypassed or if the SVG is consumed by a less-strict parser.\n */\nfunction sanitizeForSVG(s: string): string {\n let clean = s;\n // Strip HTML/XML tags\n clean = clean.replace(/<\\/?[a-zA-Z][^>]*>/g, '');\n // Strip javascript:/data:/vbscript: URIs\n clean = clean.replace(/\\b(?:javascript|data|vbscript)\\s*:/gi, '');\n // Strip on* event handlers\n clean = clean.replace(/\\bon[a-z]+\\s*=/gi, '');\n // Strip null bytes\n // eslint-disable-next-line no-control-regex\n clean = clean.replace(/\\x00/g, '');\n return escapeXML(clean);\n}\n\n// Match canvas: indigo/slate palette, light theme by default.\nconst COLORS = {\n bg: '#fafbfc',\n dot: '#dbe3ee',\n nodeFill: '#ffffff',\n nodeStroke: '#cbd5e1',\n edge: '#94a3b8',\n text: '#1e293b',\n textSub: '#94a3b8',\n amber: '#d97706',\n amberSoft: '#fef9ee',\n amberLine: '#fde68a',\n amberCardBg: '#fffdf7',\n};\n\nfunction renderStandardNode(node: DiagramNode, box: LayoutBox): string {\n const cx = box.x + box.w / 2;\n const cy = box.y + box.h / 2;\n const shape = node.shape ?? 'rectangle';\n const label = `<text x=\"${cx}\" y=\"${cy + 4.5}\" text-anchor=\"middle\" font-family=\"ui-sans-serif,system-ui,-apple-system,sans-serif\" font-size=\"13\" font-weight=\"500\" fill=\"${COLORS.text}\">${sanitizeForSVG(node.label)}</text>`;\n\n let shapeEl: string;\n if (shape === 'diamond') {\n const pts = `${cx},${box.y} ${box.x + box.w},${cy} ${cx},${box.y + box.h} ${box.x},${cy}`;\n shapeEl = `<polygon points=\"${pts}\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1.25\" filter=\"url(#nodeShadow)\"/>`;\n } else if (shape === 'circle') {\n const r = Math.min(box.w, box.h) / 2 - 1;\n shapeEl = `<circle cx=\"${cx}\" cy=\"${cy}\" r=\"${r}\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1.25\" filter=\"url(#nodeShadow)\"/>`;\n } else if (shape === 'parallelogram') {\n const pts = `${box.x + 14},${box.y} ${box.x + box.w},${box.y} ${box.x + box.w - 14},${box.y + box.h} ${box.x},${box.y + box.h}`;\n shapeEl = `<polygon points=\"${pts}\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1.25\" filter=\"url(#nodeShadow)\"/>`;\n } else {\n shapeEl = `<rect x=\"${box.x}\" y=\"${box.y}\" width=\"${box.w}\" height=\"${box.h}\" rx=\"14\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1.25\" filter=\"url(#nodeShadow)\"/>`;\n }\n return shapeEl + label;\n}\n\nfunction renderQuestionNode(node: DiagramNode, box: LayoutBox): string {\n const answers = (node.metadata?.answers as string[] | undefined) ?? [];\n const clipId = `qhdr-${node.id.replace(/[^a-zA-Z0-9_-]/g, '_')}`;\n const x = box.x,\n y = box.y,\n w = box.w,\n h = box.h;\n const parts: string[] = [];\n\n // Card body\n parts.push(\n `<rect x=\"${x}\" y=\"${y}\" width=\"${w}\" height=\"${h}\" rx=\"14\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.amberLine}\" stroke-width=\"1.5\" filter=\"url(#nodeShadow)\"/>`,\n );\n\n // Header tint (clipped to top rounded corners)\n parts.push(\n `<defs><clipPath id=\"${clipId}\"><rect x=\"${x}\" y=\"${y}\" width=\"${w}\" height=\"${Q_BASE_H}\" rx=\"14\"/></clipPath></defs>`,\n );\n parts.push(\n `<rect x=\"${x}\" y=\"${y}\" width=\"${w}\" height=\"${Q_BASE_H}\" fill=\"${COLORS.amberSoft}\" clip-path=\"url(#${clipId})\"/>`,\n );\n\n // Amber left accent\n parts.push(\n `<rect x=\"${x}\" y=\"${y}\" width=\"4\" height=\"${Q_BASE_H}\" rx=\"2\" fill=\"${COLORS.amber}\"/>`,\n );\n\n // ? badge\n parts.push(\n `<rect x=\"${x + 12}\" y=\"${y + 14}\" width=\"28\" height=\"28\" rx=\"8\" fill=\"${COLORS.amber}\"/>`,\n );\n parts.push(\n `<text x=\"${x + 26}\" y=\"${y + 33}\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"900\" fill=\"white\">?</text>`,\n );\n\n // QUESTION label + node label\n parts.push(\n `<text x=\"${x + 50}\" y=\"${y + 27}\" font-family=\"ui-sans-serif,system-ui,sans-serif\" font-size=\"9\" font-weight=\"700\" fill=\"${COLORS.textSub}\" letter-spacing=\"0.6\">QUESTION</text>`,\n );\n parts.push(\n `<text x=\"${x + 50}\" y=\"${y + 42}\" font-family=\"ui-sans-serif,system-ui,sans-serif\" font-size=\"13\" font-weight=\"700\" fill=\"${COLORS.text}\">${sanitizeForSVG(node.label)}</text>`,\n );\n\n // Divider\n parts.push(\n `<line x1=\"${x}\" y1=\"${y + Q_BASE_H}\" x2=\"${x + w}\" y2=\"${y + Q_BASE_H}\" stroke=\"${COLORS.amberLine}\" stroke-width=\"1\"/>`,\n );\n\n if (answers.length === 0) {\n parts.push(\n `<text x=\"${x + w / 2}\" y=\"${y + Q_BASE_H + 22}\" text-anchor=\"middle\" font-size=\"10\" fill=\"${COLORS.amber}\" opacity=\"0.4\" font-weight=\"600\">No answers yet</text>`,\n );\n } else {\n const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n answers.forEach((ans, i) => {\n const prevW = answers.slice(0, i).reduce((s, a) => s + answerCardW(a) + Q_CARD_PAD, 0);\n const cW = answerCardW(ans);\n const cardX = x + Q_CARD_PAD + prevW;\n const cardY = y + Q_BASE_H + 7;\n const cardH = Q_ANS_ROW_H - 20;\n const cx = cardX + cW / 2;\n const letter = i < 26 ? letters[i]! : `${i + 1}`;\n const maxChars = Math.max(2, Math.floor((cW - 20) / 7.5));\n const displayAns = ans.length > maxChars ? ans.slice(0, maxChars - 1) + '…' : ans;\n\n parts.push(\n `<rect x=\"${cardX}\" y=\"${cardY}\" width=\"${cW}\" height=\"${cardH}\" rx=\"8\" fill=\"${COLORS.amberCardBg}\" stroke=\"${COLORS.amberLine}\" stroke-width=\"1\"/>`,\n );\n parts.push(\n `<rect x=\"${cx - 11}\" y=\"${cardY + 7}\" width=\"22\" height=\"22\" rx=\"6\" fill=\"#fef3c7\"/>`,\n );\n parts.push(\n `<text x=\"${cx}\" y=\"${cardY + 22}\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"800\" fill=\"${COLORS.amber}\">${sanitizeForSVG(letter)}</text>`,\n );\n parts.push(\n `<text x=\"${cx}\" y=\"${cardY + 46}\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"500\" fill=\"#374151\" font-family=\"ui-sans-serif,system-ui,sans-serif\">${sanitizeForSVG(displayAns)}</text>`,\n );\n });\n }\n\n return parts.join('');\n}\n\nfunction renderEdge(\n edge: DiagramEdge,\n boxes: Map<string, LayoutBox>,\n variant: DiagramModel['variant'],\n nodes: DiagramNode[],\n): string {\n const fromBox = boxes.get(edge.from);\n const toBox = boxes.get(edge.to);\n if (!fromBox || !toBox) return '';\n\n let x1: number, y1: number;\n const fromNode = nodes.find((n) => n.id === edge.from);\n\n if (fromNode && isQuestion(fromNode, variant)) {\n const answers = (fromNode.metadata?.answers as string[] | undefined) ?? [];\n const idx = answers.indexOf(edge.label ?? '');\n if (idx >= 0) {\n const prevW = answers.slice(0, idx).reduce((s, a) => s + answerCardW(a) + Q_CARD_PAD, 0);\n const cW = answerCardW(answers[idx]!);\n x1 = fromBox.x + Q_CARD_PAD + prevW + cW / 2;\n y1 = fromBox.y + Q_BASE_H + Q_ANS_ROW_H - 8;\n } else {\n x1 = fromBox.x + fromBox.w / 2;\n y1 = fromBox.y + fromBox.h;\n }\n } else {\n x1 = fromBox.x + fromBox.w / 2;\n y1 = fromBox.y + fromBox.h;\n }\n const x2 = toBox.x + toBox.w / 2;\n const y2 = toBox.y;\n\n const dash =\n edge.style === 'dashed'\n ? ' stroke-dasharray=\"6,4\"'\n : edge.style === 'dotted'\n ? ' stroke-dasharray=\"2,3\"'\n : '';\n const marker = edge.arrowhead === 'none' ? '' : ' marker-end=\"url(#arrow)\"';\n const d = bezierPath(x1, y1, x2, y2);\n\n let out = `<path d=\"${d}\" fill=\"none\" stroke=\"${COLORS.edge}\" stroke-width=\"1.5\"${dash}${marker}/>`;\n\n if (edge.label) {\n const midX = (x1 + x2) / 2;\n const midY = (y1 + y2) / 2;\n const labelW = estimateTextW(edge.label, 7) + 14;\n out += `<rect x=\"${midX - labelW / 2}\" y=\"${midY - 11}\" width=\"${labelW}\" height=\"18\" rx=\"9\" fill=\"${COLORS.bg}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1\"/>`;\n out += `<text x=\"${midX}\" y=\"${midY + 2}\" text-anchor=\"middle\" font-family=\"ui-sans-serif,system-ui,sans-serif\" font-size=\"11\" fill=\"${COLORS.text}\">${sanitizeForSVG(edge.label)}</text>`;\n }\n return out;\n}\n\n/**\n * Render a `DiagramModel` to a standalone SVG string. The output mirrors the\n * editor canvas: dot-grid background, soft drop-shadowed nodes, smooth\n * cubic-bezier edges. No external assets — the result is fully inline and\n * pasteable into HTML, README files, or PR descriptions.\n *\n * Layout is computed identically to the editor's hit-test pass (same width\n * estimation, padding, and question-card sizing), so an exported SVG matches\n * what you see on screen.\n *\n * Works in Node, Bun, and the browser (no DOM APIs needed).\n */\nexport function toSVG(model: DiagramModel): string {\n const boxes = computeLayout(model);\n let maxX = 0,\n maxY = 0;\n for (const b of boxes.values()) {\n maxX = Math.max(maxX, b.x + b.w);\n maxY = Math.max(maxY, b.y + b.h);\n }\n const width = maxX + PADDING;\n const height = maxY + PADDING + (model.title ? 32 : 0);\n\n const defs = [\n `<defs>`,\n `<pattern id=\"dotgrid\" x=\"0\" y=\"0\" width=\"24\" height=\"24\" patternUnits=\"userSpaceOnUse\">`,\n `<circle cx=\"12\" cy=\"12\" r=\"1.1\" fill=\"${COLORS.dot}\"/>`,\n `</pattern>`,\n `<filter id=\"nodeShadow\" x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">`,\n `<feDropShadow dx=\"0\" dy=\"3\" stdDeviation=\"5\" flood-color=\"rgba(15,23,42,0.09)\"/>`,\n `</filter>`,\n `<marker id=\"arrow\" markerWidth=\"9\" markerHeight=\"7\" refX=\"8.5\" refY=\"3.5\" orient=\"auto\" markerUnits=\"strokeWidth\">`,\n `<path d=\"M0,0.5 L9,3.5 L0,6.5 L2.2,3.5 Z\" fill=\"${COLORS.edge}\"/>`,\n `</marker>`,\n `</defs>`,\n ].join('');\n\n const titleEl = model.title\n ? `<text x=\"${width / 2}\" y=\"22\" text-anchor=\"middle\" font-family=\"ui-sans-serif,system-ui,sans-serif\" font-size=\"15\" font-weight=\"700\" fill=\"${COLORS.text}\">${sanitizeForSVG(model.title)}</text>`\n : '';\n\n const edges = model.edges.map((e) => renderEdge(e, boxes, model.variant, model.nodes)).join('\\n');\n const nodes = model.nodes\n .map((n) => {\n const b = boxes.get(n.id)!;\n return isQuestion(n, model.variant) ? renderQuestionNode(n, b) : renderStandardNode(n, b);\n })\n .join('\\n');\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">\\n${defs}\\n<rect width=\"${width}\" height=\"${height}\" fill=\"${COLORS.bg}\"/>\\n<rect width=\"${width}\" height=\"${height}\" fill=\"url(#dotgrid)\"/>\\n${titleEl}\\n${edges}\\n${nodes}\\n</svg>`;\n}\n\n/**\n * Render a `DiagramModel` to a PNG `Blob`. Routes the SVG output through an\n * `<img>` and a `<canvas>` at `devicePixelRatio` scale, so the result is\n * crisp on hi-DPI displays.\n *\n * **Browser-only.** Throws if called in a Node/Bun environment (the Canvas\n * API is not available). For server-side PNG rendering, pipe `toSVG()` output\n * through a library like `@resvg/resvg-js`.\n */\nexport async function toPNG(model: DiagramModel): Promise<Blob> {\n if (typeof document === 'undefined') {\n throw new Error(\n 'toPNG requires a browser environment. For Node/Bun server use, pipe toSVG() through @resvg/resvg-js.',\n );\n }\n const svg = toSVG(model);\n const blob = new Blob([svg], { type: 'image/svg+xml' });\n const url = URL.createObjectURL(blob);\n\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n const scale = window.devicePixelRatio || 2;\n canvas.width = img.naturalWidth * scale;\n canvas.height = img.naturalHeight * scale;\n const ctx = canvas.getContext('2d')!;\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n canvas.toBlob(\n (b) => (b ? resolve(b) : reject(new Error('Canvas toBlob failed'))),\n 'image/png',\n );\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('SVG image load failed'));\n };\n img.src = url;\n });\n}\n","import { Model } from './model.js';\nimport type { DiagramEdge, DiagramNode, NodeShape } from './types.js';\nimport { nextId } from './ids.js';\nimport { toMermaid } from '../exporters/mermaid.js';\nimport { toPlantUML } from '../exporters/plantuml.js';\nimport { toJSON } from '../exporters/json.js';\nimport { toSVG, toPNG } from '../exporters/svg.js';\n\n/**\n * Fluent builder for flowchart-type diagrams. Wraps `Model` with shorter\n * method names tuned for one-shot construction in tests and scripts, and\n * with convenience exporters for every supported `ExportFormat`.\n *\n * @example\n * ```ts\n * const svg = flowchart('Login')\n * .node('start', 'Begin', { shape: 'circle' })\n * .node('check', 'Authenticated?', { shape: 'diamond' })\n * .edge('start', 'check')\n * .toSVG();\n * ```\n */\nexport class FlowchartBuilder {\n private model: Model;\n\n /** @param title Optional human-readable diagram title. */\n constructor(title?: string) {\n this.model = new Model('flowchart', title);\n }\n\n /**\n * Append a node. Defaults `shape` to `rectangle` when omitted from `options`.\n * Throws on duplicate id.\n */\n node(id: string, label: string, options: Partial<Omit<DiagramNode, 'id' | 'label'>> = {}): this {\n this.model.addNode({ id, label, shape: options.shape ?? 'rectangle', ...options });\n return this;\n }\n\n /**\n * Append an edge with an auto-generated id. The id is derived from the\n * current edge list to avoid collisions with imported models.\n */\n edge(\n from: string,\n to: string,\n options: Partial<Omit<DiagramEdge, 'id' | 'from' | 'to'>> = {},\n ): this {\n this.model.addEdge({ id: nextId('e', this.model.toJSON().edges), from, to, ...options });\n return this;\n }\n\n /** Remove a node and every edge that references it. */\n removeNode(id: string): this {\n this.model.removeNode(id);\n return this;\n }\n\n /** Remove an edge by id. */\n removeEdge(id: string): this {\n this.model.removeEdge(id);\n return this;\n }\n\n /** Patch an existing node. See `Model.updateNode`. */\n updateNode(id: string, patch: Partial<Omit<DiagramNode, 'id'>>): this {\n this.model.updateNode(id, patch);\n return this;\n }\n\n /** Return the underlying `Model` for advanced operations or validation. */\n getModel(): Model {\n return this.model;\n }\n\n /** Serialize as Mermaid `flowchart TD` source. */\n toMermaid(): string {\n return toMermaid(this.model.toJSON());\n }\n\n /** Serialize as PlantUML activity-diagram source. */\n toPlantUML(): string {\n return toPlantUML(this.model.toJSON());\n }\n\n /** Serialize as the package's JSON shape (full round-trip fidelity). */\n toJSON(): string {\n return toJSON(this.model.toJSON());\n }\n\n /** Render to a standalone SVG string. */\n toSVG(): string {\n return toSVG(this.model.toJSON());\n }\n\n /** Render to a PNG `Blob`. Browser-only (uses the Canvas API). */\n toPNG(): Promise<Blob> {\n return toPNG(this.model.toJSON());\n }\n}\n\n/** Convenience constructor — `flowchart('My Diagram')` is `new FlowchartBuilder('My Diagram')`. */\nexport function flowchart(title?: string): FlowchartBuilder {\n return new FlowchartBuilder(title);\n}\n","import { Model } from './model.js';\nimport type { SequenceMessage } from './types.js';\nimport { nextId } from './ids.js';\nimport { toMermaid } from '../exporters/mermaid.js';\nimport { toPlantUML } from '../exporters/plantuml.js';\nimport { toJSON } from '../exporters/json.js';\n\n/**\n * Fluent builder for sequence-type diagrams. Mirrors `FlowchartBuilder` but\n * over `actors`/`messages` instead of `nodes`/`edges`.\n *\n * @example\n * ```ts\n * const puml = sequence('Checkout')\n * .actor('User')\n * .message('User', 'Server', 'POST /pay')\n * .replyMessage('Server', 'User', '200 OK')\n * .toPlantUML();\n * ```\n */\nexport class SequenceBuilder {\n private model: Model;\n\n /** @param title Optional human-readable diagram title. */\n constructor(title?: string) {\n this.model = new Model('sequence', title);\n }\n\n /** Register an actor. Duplicates are silently ignored. */\n actor(name: string): this {\n this.model.addActor(name);\n return this;\n }\n\n /**\n * Append a message. Both endpoints are auto-registered as actors if not\n * already present. The id is derived from the current message list.\n */\n message(\n from: string,\n to: string,\n label: string,\n options: Partial<Pick<SequenceMessage, 'style'>> = {},\n ): this {\n this.model.addActor(from);\n this.model.addActor(to);\n const messages = this.model.toJSON().messages ?? [];\n this.model.addMessage({\n id: nextId('m', messages),\n from,\n to,\n label,\n style: options.style ?? 'solid',\n });\n return this;\n }\n\n /** Convenience for a `dashed`-style return message. */\n replyMessage(from: string, to: string, label: string): this {\n return this.message(from, to, label, { style: 'dashed' });\n }\n\n /** Return the underlying `Model` for advanced operations or validation. */\n getModel(): Model {\n return this.model;\n }\n\n /** Serialize as Mermaid `sequenceDiagram` source. */\n toMermaid(): string {\n return toMermaid(this.model.toJSON());\n }\n\n /** Serialize as PlantUML sequence-diagram source. */\n toPlantUML(): string {\n return toPlantUML(this.model.toJSON());\n }\n\n /** Serialize as the package's JSON shape (full round-trip fidelity). */\n toJSON(): string {\n return toJSON(this.model.toJSON());\n }\n}\n\n/** Convenience constructor — `sequence('My Diagram')` is `new SequenceBuilder('My Diagram')`. */\nexport function sequence(title?: string): SequenceBuilder {\n return new SequenceBuilder(title);\n}\n","/**\n * Centralized input sanitization for all user-provided text that flows\n * into SVG output, labels, or any rendering context.\n *\n * Defence-in-depth: even though `escapeXML()` prevents most injection,\n * stripping dangerous patterns at the source stops payloads from reaching\n * any downstream consumer (clipboard, third-party renderers, etc.).\n */\n\n/** Maximum characters allowed in a single label/text field. */\nexport const MAX_LABEL_LENGTH = 2000;\n\n/** Maximum number of nodes allowed in a single diagram. */\nexport const MAX_NODES = 500;\n\n/** Maximum number of edges allowed in a single diagram. */\nexport const MAX_EDGES = 2000;\n\n/** Maximum number of actors in a sequence diagram. */\nexport const MAX_ACTORS = 100;\n\n/** Maximum number of messages in a sequence diagram. */\nexport const MAX_MESSAGES = 2000;\n\n/** Maximum raw input length for importers (bytes). ~2 MB */\nexport const MAX_IMPORT_LENGTH = 2 * 1024 * 1024;\n\n/**\n * Strip dangerous content from user-supplied text. Removes:\n * - HTML tags (`<script>`, `<img>`, `<foreignObject>`, etc.)\n * - `javascript:`, `data:`, `vbscript:` URI schemes\n * - `on*` event handler attributes (onerror, onclick, etc.)\n * - Null bytes and other control characters\n */\nexport function sanitizeLabel(raw: string): string {\n let s = raw;\n // Remove null bytes and ASCII control chars (except \\n, \\r, \\t)\n // eslint-disable-next-line no-control-regex\n s = s.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '');\n // Strip HTML/XML tags\n s = s.replace(/<\\/?[a-zA-Z][^>]*>/g, '');\n // Strip javascript:/data:/vbscript: URIs (case-insensitive, whitespace-tolerant)\n s = s.replace(/\\b(?:javascript|data|vbscript)\\s*:/gi, '');\n // Strip on* event handlers (e.g. onerror=, onclick=)\n s = s.replace(/\\bon[a-z]+\\s*=/gi, '');\n // Enforce length limit\n if (s.length > MAX_LABEL_LENGTH) {\n s = s.slice(0, MAX_LABEL_LENGTH);\n }\n return s;\n}\n\n/**\n * Validate a URL is safe for use in href attributes.\n * Only allows http:, https:, and mailto: protocols.\n * Returns the URL if safe, or `undefined` if dangerous.\n */\nexport function sanitizeURL(url: string): string | undefined {\n const trimmed = url.trim();\n // Allow relative URLs (start with / or #)\n if (trimmed.startsWith('/') || trimmed.startsWith('#')) return trimmed;\n // Allow http(s) and mailto\n if (/^https?:\\/\\//i.test(trimmed) || /^mailto:/i.test(trimmed)) return trimmed;\n // Block everything else (javascript:, data:, vbscript:, etc.)\n return undefined;\n}\n","import { Model } from '../core/model.js';\nimport type { NodeShape } from '../core/types.js';\nimport { nextId } from '../core/ids.js';\nimport {\n sanitizeLabel,\n MAX_NODES,\n MAX_EDGES,\n MAX_ACTORS,\n MAX_MESSAGES,\n MAX_IMPORT_LENGTH,\n} from '../core/sanitize.js';\n\n// Detects shape from Mermaid node syntax\nfunction parseNodeDecl(raw: string): { id: string; label: string; shape: NodeShape } | null {\n // diamond: id{label}, circle: id((label)), parallelogram: id[/label/], default: id[label] or id(\"label\")\n const patterns: [RegExp, NodeShape][] = [\n [/^(\\w+)\\{\\{?\"?(.+?)\"?\\}?\\}$/, 'diamond'],\n [/^(\\w+)\\(\\(\"?(.+?)\"?\\)\\)$/, 'circle'],\n [/^(\\w+)\\[\\/(.+?)\\/\\]$/, 'parallelogram'],\n [/^(\\w+)\\[[\"']?(.+?)[\"']?\\]$/, 'rectangle'],\n [/^(\\w+)\\(\"?(.+?)\"?\\)$/, 'rectangle'],\n ];\n for (const [re, shape] of patterns) {\n const m = raw.match(re);\n if (m) return { id: m[1]!, label: sanitizeLabel(m[2]!.replace(/^[\"']|[\"']$/g, '')), shape };\n }\n return null;\n}\n\n// Mermaid flowchart edge connector: solid (-->, ---), dashed (-.->, -.-), or with labels.\n// Anchored so node IDs ending in `{`/`[`/`(` cannot bleed into the connector.\nconst EDGE_RE = /^(.+?)\\s*(-\\.->|-\\.-|-->|---)(?:\\|(.+?)\\|)?\\s*(.+)$/;\n\nfunction detectStyle(connector: string): 'solid' | 'dashed' {\n return connector.startsWith('-.') ? 'dashed' : 'solid';\n}\n\nfunction detectArrowhead(connector: string): 'arrow' | 'none' {\n return connector.endsWith('>') ? 'arrow' : 'none';\n}\n\nfunction parseFlowchart(lines: string[]): Model {\n const model = new Model('flowchart');\n const nodeMap = new Map<string, boolean>();\n const groupStack: string[] = [];\n let edgeCount = 0;\n\n const ensureNode = (id: string, group?: string) => {\n if (!nodeMap.has(id)) {\n if (nodeMap.size >= MAX_NODES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_NODES} nodes`);\n nodeMap.set(id, true);\n const metadata = group ? { group } : undefined;\n model.addNode({ id, label: id, shape: 'rectangle', ...(metadata ? { metadata } : {}) });\n }\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n // Skip Mermaid comments, config blocks, header directives, and click handlers.\n if (\n trimmed.startsWith('%%') ||\n trimmed.startsWith('graph') ||\n trimmed.startsWith('flowchart') ||\n trimmed.startsWith('click ') ||\n trimmed.startsWith('classDef ') ||\n trimmed.startsWith('class ') ||\n trimmed.startsWith('style ') ||\n trimmed.startsWith('linkStyle ')\n )\n continue;\n\n // Subgraphs: track current group so contained nodes get metadata.group set.\n const subgraphOpen = trimmed.match(/^subgraph\\s+(\\S+)/i);\n if (subgraphOpen) {\n groupStack.push(subgraphOpen[1]!);\n continue;\n }\n if (/^end\\b/i.test(trimmed)) {\n groupStack.pop();\n continue;\n }\n\n const currentGroup = groupStack[groupStack.length - 1];\n\n const edgeMatch = trimmed.match(EDGE_RE);\n if (edgeMatch) {\n const fromRaw = edgeMatch[1]!.trim();\n const connector = edgeMatch[2]!;\n const label = edgeMatch[3]?.replace(/^[\"']|[\"']$/g, '');\n const sanitizedLabel = label ? sanitizeLabel(label) : undefined;\n const toRaw = edgeMatch[4]!.trim();\n const style = detectStyle(connector);\n const arrowhead = detectArrowhead(connector);\n\n const fromNode = parseNodeDecl(fromRaw);\n const toNode = parseNodeDecl(toRaw);\n\n if (fromNode && !nodeMap.has(fromNode.id)) {\n if (nodeMap.size >= MAX_NODES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_NODES} nodes`);\n nodeMap.set(fromNode.id, true);\n const metadata = currentGroup ? { group: currentGroup } : undefined;\n model.addNode({ ...fromNode, ...(metadata ? { metadata } : {}) });\n } else if (!fromNode) {\n ensureNode(fromRaw.replace(/\\W.*/, ''), currentGroup);\n }\n if (toNode && !nodeMap.has(toNode.id)) {\n if (nodeMap.size >= MAX_NODES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_NODES} nodes`);\n nodeMap.set(toNode.id, true);\n const metadata = currentGroup ? { group: currentGroup } : undefined;\n model.addNode({ ...toNode, ...(metadata ? { metadata } : {}) });\n } else if (!toNode) {\n ensureNode(toRaw.replace(/\\W.*/, ''), currentGroup);\n }\n\n if (edgeCount >= MAX_EDGES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_EDGES} edges`);\n edgeCount++;\n const fromId = fromNode?.id ?? fromRaw.replace(/\\W.*/, '');\n const toId = toNode?.id ?? toRaw.replace(/\\W.*/, '');\n model.addEdge({\n id: nextId('e', model.toJSON().edges),\n from: fromId,\n to: toId,\n ...(sanitizedLabel ? { label: sanitizedLabel } : {}),\n style,\n ...(arrowhead === 'none' ? { arrowhead } : {}),\n });\n continue;\n }\n\n const nodeDecl = parseNodeDecl(trimmed);\n if (nodeDecl && !nodeMap.has(nodeDecl.id)) {\n if (nodeMap.size >= MAX_NODES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_NODES} nodes`);\n nodeMap.set(nodeDecl.id, true);\n const metadata = currentGroup ? { group: currentGroup } : undefined;\n model.addNode({ ...nodeDecl, ...(metadata ? { metadata } : {}) });\n }\n }\n\n return model;\n}\n\nfunction parseSequence(lines: string[], title?: string): Model {\n const model = new Model('sequence', title);\n let actorCount = 0;\n let messageCount = 0;\n\n const safeAddActor = (name: string) => {\n const safeName = sanitizeLabel(name);\n if (!model.toJSON().actors?.includes(safeName)) {\n if (actorCount >= MAX_ACTORS)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_ACTORS} actors`);\n actorCount++;\n }\n model.addActor(safeName);\n return safeName;\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('sequenceDiagram') || trimmed.startsWith('%%')) continue;\n\n const participantMatch = trimmed.match(/^participant\\s+(.+)$/i);\n if (participantMatch) {\n safeAddActor(participantMatch[1]!.trim());\n continue;\n }\n\n const actorMatch = trimmed.match(/^actor\\s+(.+)$/i);\n if (actorMatch) {\n safeAddActor(actorMatch[1]!.trim());\n continue;\n }\n\n // Sequence message arrows: ->, ->>, -->, -->> (-- prefix = dashed)\n const msgMatch = trimmed.match(/^(.+?)\\s*(-->>|->>|-->|->)\\s*(.+?):\\s*(.+)$/);\n if (msgMatch) {\n const from = safeAddActor(msgMatch[1]!.trim());\n const arrow = msgMatch[2]!;\n const to = safeAddActor(msgMatch[3]!.trim());\n const label = sanitizeLabel(msgMatch[4]!.trim());\n if (messageCount >= MAX_MESSAGES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_MESSAGES} messages`);\n messageCount++;\n const messages = model.toJSON().messages ?? [];\n model.addMessage({\n id: nextId('m', messages),\n from,\n to,\n label,\n style: arrow.startsWith('--') ? 'dashed' : 'solid',\n });\n }\n }\n\n return model;\n}\n\n/**\n * Parse Mermaid source into a `Model`. Auto-detects `flowchart` /\n * `sequenceDiagram` from the directive line and dispatches accordingly.\n *\n * **What is preserved:**\n * - Flowcharts: node shapes (`[]` / `{}` / `(())` / `[/]`), node labels,\n * edge connectors (`-->`, `-.->`, `---`, `-.-`), edge labels, and\n * `subgraph` grouping (stored on `node.metadata.group`).\n * - Sequence: actor declarations, message arrows (`->>`, `-->>`), labels.\n * - Frontmatter `title: ...` blocks are lifted into `model.title`.\n *\n * **What is dropped or normalized:**\n * - `mermaid.initialize(...)` blocks, `%%{init: ...}%%` directives, and\n * click handlers — stripped before parsing.\n * - Dotted edges collapse to `dashed` (Mermaid's dot/dash style is lossy).\n * - Node positions, `waypoint`, and any package-specific metadata other\n * than `group` are not present in Mermaid and so cannot round-trip.\n */\nexport function fromMermaid(mermaid: string): Model {\n if (mermaid.length > MAX_IMPORT_LENGTH) {\n throw new Error(`Import aborted: input exceeds the maximum of ${MAX_IMPORT_LENGTH} characters`);\n }\n // Strip mermaid.initialize(...) and similar JS-style config blocks that\n // sometimes appear in copy-pasted snippets — anything between `init` and `)`.\n const cleaned = mermaid.replace(/mermaid\\.initialize\\([\\s\\S]*?\\)\\s*;?/g, '');\n const rawLines = cleaned.split('\\n');\n\n // Strip frontmatter\n let startIdx = 0;\n let title: string | undefined;\n if (rawLines[0]?.trim() === '---') {\n const endFm = rawLines.findIndex((l, i) => i > 0 && l.trim() === '---');\n if (endFm !== -1) {\n const fmLines = rawLines.slice(1, endFm);\n for (const fl of fmLines) {\n const tm = fl.match(/^title:\\s*(.+)$/);\n if (tm) title = tm[1]!.trim();\n }\n startIdx = endFm + 1;\n }\n }\n\n const lines = rawLines.slice(startIdx);\n const firstContent = lines.find((l) => l.trim());\n\n if (firstContent?.trim().startsWith('sequenceDiagram')) {\n const m = parseSequence(lines, title);\n return m;\n }\n\n const m = parseFlowchart(lines);\n if (title) {\n // patch title via internal JSON round-trip\n const data = m.toJSON();\n data.title = title;\n return Model.fromData(data);\n }\n return m;\n}\n","import { Model } from '../core/model.js';\nimport type { DiagramModel } from '../core/types.js';\nimport {\n sanitizeLabel,\n MAX_NODES,\n MAX_EDGES,\n MAX_ACTORS,\n MAX_MESSAGES,\n MAX_IMPORT_LENGTH,\n} from '../core/sanitize.js';\n\n/**\n * Deep-strip prototype-pollution keys (`__proto__`, `constructor`,\n * `prototype`) from any parsed JSON value before it enters the model.\n */\nfunction stripDangerousKeys(obj: unknown): unknown {\n if (Array.isArray(obj)) return obj.map(stripDangerousKeys);\n if (obj !== null && typeof obj === 'object') {\n const clean: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n clean[key] = stripDangerousKeys(val);\n }\n return clean;\n }\n return obj;\n}\n\n/**\n * Rehydrate a `Model` from the package's JSON shape. Accepts either the raw\n * JSON string or an already-parsed `DiagramModel` (handy when the caller has\n * received the data from a typed source).\n *\n * Validates the top-level structure and ensures nodes/edges contain only\n * expected shapes. All labels are sanitized to strip dangerous content.\n * Prototype-pollution keys are stripped from parsed JSON.\n * Resource limits are enforced to prevent browser-tab crashes.\n *\n * @throws If `json` is not a valid `DiagramModel` shape.\n */\nexport function fromJSON(json: string | DiagramModel): Model {\n if (typeof json === 'string' && json.length > MAX_IMPORT_LENGTH) {\n throw new Error(`Import aborted: input exceeds the maximum of ${MAX_IMPORT_LENGTH} characters`);\n }\n const raw = typeof json === 'string' ? JSON.parse(json) : json;\n const data = stripDangerousKeys(raw) as DiagramModel;\n\n // Structural validation\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n throw new Error('Invalid DiagramModel JSON: expected an object');\n }\n if (data.type !== 'flowchart' && data.type !== 'sequence') {\n throw new Error(`Invalid DiagramModel JSON: unknown type \"${data.type}\"`);\n }\n if (!Array.isArray(data.nodes) || !Array.isArray(data.edges)) {\n throw new Error('Invalid DiagramModel JSON: nodes and edges must be arrays');\n }\n\n // Resource limits\n if (data.nodes.length > MAX_NODES) {\n throw new Error(\n `Import aborted: diagram has ${data.nodes.length} nodes, maximum is ${MAX_NODES}`,\n );\n }\n if (data.edges.length > MAX_EDGES) {\n throw new Error(\n `Import aborted: diagram has ${data.edges.length} edges, maximum is ${MAX_EDGES}`,\n );\n }\n if (data.actors && data.actors.length > MAX_ACTORS) {\n throw new Error(\n `Import aborted: diagram has ${data.actors.length} actors, maximum is ${MAX_ACTORS}`,\n );\n }\n if (data.messages && data.messages.length > MAX_MESSAGES) {\n throw new Error(\n `Import aborted: diagram has ${data.messages.length} messages, maximum is ${MAX_MESSAGES}`,\n );\n }\n\n // Validate node shape (must have id + label at minimum)\n for (const node of data.nodes) {\n if (\n typeof node !== 'object' ||\n node === null ||\n typeof node.id !== 'string' ||\n typeof node.label !== 'string'\n ) {\n throw new Error('Invalid DiagramModel JSON: each node must have string id and label');\n }\n node.label = sanitizeLabel(node.label);\n }\n\n // Validate edge shape (must have id, from, to)\n for (const edge of data.edges) {\n if (\n typeof edge !== 'object' ||\n edge === null ||\n typeof edge.id !== 'string' ||\n typeof edge.from !== 'string' ||\n typeof edge.to !== 'string'\n ) {\n throw new Error('Invalid DiagramModel JSON: each edge must have string id, from, and to');\n }\n if (edge.label) edge.label = sanitizeLabel(edge.label);\n }\n\n // Sanitize sequence fields\n if (data.actors) {\n data.actors = data.actors.map((a) => (typeof a === 'string' ? sanitizeLabel(a) : a));\n }\n if (data.messages) {\n for (const msg of data.messages) {\n if (typeof msg === 'object' && msg !== null && typeof msg.label === 'string') {\n msg.label = sanitizeLabel(msg.label);\n }\n }\n }\n\n return Model.fromData(data);\n}\n"],"mappings":"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","names":["exportFlowchart","msgArrow","exportSequence","m"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/model.ts","../src/core/ids.ts","../src/exporters/mermaid.ts","../src/exporters/plantuml.ts","../src/exporters/json.ts","../src/exporters/svg.ts","../src/core/flowchart.ts","../src/core/sequence.ts","../src/core/sanitize.ts","../src/importers/mermaid.ts","../src/importers/json.ts"],"sourcesContent":["/**\n * Headless entry point. Builders, the underlying `Model`, and every\n * exporter/importer are exported here. The editor React components live in\n * the `/ui` subpath export — `import { DiagramEditor } from\n * 'flowchart-sequence-designer/ui'` — so server-side or CLI consumers can\n * pull in this entry without dragging React along.\n */\n\n// Builders\nexport { flowchart, FlowchartBuilder } from './core/flowchart.js';\nexport { sequence, SequenceBuilder } from './core/sequence.js';\n\n// Model\nexport { Model } from './core/model.js';\n\n// Exporters\nexport { toMermaid } from './exporters/mermaid.js';\nexport { toPlantUML } from './exporters/plantuml.js';\nexport { toJSON } from './exporters/json.js';\nexport { toSVG, toPNG } from './exporters/svg.js';\n\n// Importers\nexport { fromMermaid } from './importers/mermaid.js';\nexport { fromJSON } from './importers/json.js';\n\n// Security utilities\nexport { sanitizeLabel, sanitizeURL } from './core/sanitize.js';\n\n// Types\nexport type {\n DiagramType,\n DiagramVariant,\n DiagramModel,\n DiagramNode,\n DiagramEdge,\n DiagramEdge as Edge,\n DiagramNode as Node,\n NodeShape,\n ExportFormat,\n SequenceMessage,\n} from './core/types.js';\n","import type {\n DiagramModel,\n DiagramNode,\n DiagramEdge,\n DiagramType,\n DiagramVariant,\n SequenceMessage,\n ValidationError,\n} from './types.js';\n\n/**\n * Mutable builder around a `DiagramModel`. Every public mutator returns\n * `this` so callers can chain (`new Model('flowchart').addNode(...).addEdge(...)`).\n * Call `.toJSON()` to extract a deep-cloned plain model suitable for\n * serialization or for handing to the editor components.\n *\n * All add/update operations validate immediately and throw on collisions or\n * dangling references. For non-throwing, batch-style structural checks call\n * `.validate()` instead.\n */\nexport class Model {\n private data: DiagramModel;\n\n /**\n * Create an empty model.\n *\n * @param type Top-level kind — `flowchart` or `sequence`.\n * @param title Optional human-readable title.\n * @param variant Optional UI variant (flowchart models only).\n */\n constructor(type: DiagramType, title?: string, variant?: DiagramVariant) {\n this.data = {\n type,\n ...(variant ? { variant } : {}),\n title,\n nodes: [],\n edges: [],\n actors: [],\n messages: [],\n };\n }\n\n /**\n * Rehydrate a `Model` from a previously serialized `DiagramModel`. The\n * incoming data is deep-cloned, so future mutations on the returned `Model`\n * do not affect the caller's object.\n */\n static fromData(data: DiagramModel): Model {\n const m = new Model(data.type, data.title, data.variant);\n m.data = structuredClone(data);\n return m;\n }\n\n /** Set the UI variant. No-op semantics for sequence models. */\n setVariant(variant: DiagramVariant): this {\n this.data.variant = variant;\n return this;\n }\n\n /**\n * Append a node. Throws if a node with the same id already exists. The\n * input is shallow-cloned, so later mutations of the caller's object do\n * not leak in.\n */\n addNode(node: DiagramNode): this {\n if (this.data.nodes.find((n) => n.id === node.id)) {\n throw new Error(`Node with id \"${node.id}\" already exists`);\n }\n this.data.nodes.push({ ...node });\n return this;\n }\n\n /**\n * Patch an existing node in place. Throws if the id is not found. The id\n * field itself cannot be patched — to rename, remove + re-add.\n */\n updateNode(id: string, patch: Partial<Omit<DiagramNode, 'id'>>): this {\n const node = this.data.nodes.find((n) => n.id === id);\n if (!node) throw new Error(`Node \"${id}\" not found`);\n const { __proto__, constructor, ...safe } = patch as Record<string, unknown>;\n Object.assign(node, safe);\n return this;\n }\n\n /**\n * Remove a node and every edge that referenced it as `from` or `to`. Safe\n * to call on a missing id (no-op).\n */\n removeNode(id: string): this {\n this.data.nodes = this.data.nodes.filter((n) => n.id !== id);\n this.data.edges = this.data.edges.filter((e) => e.from !== id && e.to !== id);\n return this;\n }\n\n /**\n * Append an edge. Throws on duplicate id or if either endpoint references\n * an unknown node — the model never holds dangling edges from this entry\n * point. (Importers can still construct dangling edges; call `validate()`\n * to detect them.)\n */\n addEdge(edge: DiagramEdge): this {\n if (this.data.edges.find((e) => e.id === edge.id)) {\n throw new Error(`Edge with id \"${edge.id}\" already exists`);\n }\n if (!this.data.nodes.find((n) => n.id === edge.from)) {\n throw new Error(`Edge \"${edge.id}\" references unknown source node \"${edge.from}\"`);\n }\n if (!this.data.nodes.find((n) => n.id === edge.to)) {\n throw new Error(`Edge \"${edge.id}\" references unknown target node \"${edge.to}\"`);\n }\n this.data.edges.push({ ...edge });\n return this;\n }\n\n /**\n * Surface structural problems without throwing. Returns an array of\n * `ValidationError`s; empty array means the model is well-formed. Used by\n * the editor's status banner and by external tooling.\n */\n validate(): ValidationError[] {\n const errors: ValidationError[] = [];\n const nodeIds = new Set<string>();\n for (const n of this.data.nodes) {\n if (nodeIds.has(n.id))\n errors.push({\n kind: 'duplicate-node-id',\n id: n.id,\n message: `Duplicate node id \"${n.id}\"`,\n });\n nodeIds.add(n.id);\n }\n const edgeIds = new Set<string>();\n for (const e of this.data.edges) {\n if (edgeIds.has(e.id))\n errors.push({\n kind: 'duplicate-edge-id',\n id: e.id,\n message: `Duplicate edge id \"${e.id}\"`,\n });\n edgeIds.add(e.id);\n if (!nodeIds.has(e.from))\n errors.push({\n kind: 'dangling-from',\n id: e.id,\n message: `Edge \"${e.id}\" references unknown source node \"${e.from}\"`,\n });\n if (!nodeIds.has(e.to))\n errors.push({\n kind: 'dangling-to',\n id: e.id,\n message: `Edge \"${e.id}\" references unknown target node \"${e.to}\"`,\n });\n }\n return errors;\n }\n\n /** Remove an edge by id. Safe to call on a missing id (no-op). */\n removeEdge(id: string): this {\n this.data.edges = this.data.edges.filter((e) => e.id !== id);\n return this;\n }\n\n /** Append a sequence actor. Duplicate names are silently ignored. */\n addActor(name: string): this {\n if (!this.data.actors!.includes(name)) {\n this.data.actors!.push(name);\n }\n return this;\n }\n\n /**\n * Append a sequence message. The actors referenced by `from`/`to` are not\n * validated here — callers are expected to register them via `addActor()`\n * first.\n */\n addMessage(message: SequenceMessage): this {\n this.data.messages!.push({ ...message });\n return this;\n }\n\n /**\n * Return a deep-cloned plain `DiagramModel`. Safe to mutate by the caller;\n * mutations do not flow back into this `Model`.\n */\n toJSON(): DiagramModel {\n return structuredClone(this.data);\n }\n}\n","/**\n * Mint the next available ID for a given prefix by scanning the existing\n * entities in a model.\n *\n * Avoids the classic collision pitfall of a module-level counter starting at\n * zero: if the model already contains `e1..e6` (e.g. from a preset or an\n * imported diagram), a counter that started at zero would produce a duplicate\n * `e1` on first use. By deriving from the model itself, generated IDs are\n * collision-proof against presets, imports, and concurrent editor instances.\n *\n * @example\n * nextId('node', model.nodes) // → 'node7' if model has node1..node6\n * nextId('e', model.edges) // → 'e1' if model has no edges yet\n * nextId('m', model.messages) // → 'm5' if model has m1..m4\n */\n/**\n * Returns a stateful id generator seeded from the current model. Use this\n * when a single operation needs to mint several IDs in succession (e.g.\n * duplicate or paste) — calling `nextId()` repeatedly against the same\n * snapshot would produce duplicates because the snapshot doesn't reflect\n * the freshly minted IDs.\n *\n * @example\n * const newNodeId = makeIdSource('node', model.nodes);\n * const a = newNodeId(); // → 'node7'\n * const b = newNodeId(); // → 'node8'\n */\nexport function makeIdSource(prefix: string, existing: Iterable<{ id: string }>): () => string {\n const first = nextId(prefix, existing);\n let counter = parseInt(first.slice(prefix.length), 10);\n return () => `${prefix}${counter++}`;\n}\n\nexport function nextId(prefix: string, existing: Iterable<{ id: string }>): string {\n const escaped = prefix.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const re = new RegExp(`^${escaped}(\\\\d+)$`);\n let max = 0;\n for (const item of existing) {\n const match = re.exec(item.id);\n if (match?.[1]) {\n const n = parseInt(match[1], 10);\n if (n > max) max = n;\n }\n }\n return `${prefix}${max + 1}`;\n}\n","import type { DiagramModel, DiagramNode, DiagramEdge, SequenceMessage } from '../core/types.js';\n\nconst SHAPE_OPEN: Record<string, string> = {\n rectangle: '[',\n diamond: '{',\n circle: '((',\n parallelogram: '[/',\n};\nconst SHAPE_CLOSE: Record<string, string> = {\n rectangle: ']',\n diamond: '}',\n circle: '))',\n parallelogram: '/]',\n};\n\nfunction formatNode(node: DiagramNode): string {\n const shape = node.shape ?? 'rectangle';\n const open = SHAPE_OPEN[shape] ?? '[';\n const close = SHAPE_CLOSE[shape] ?? ']';\n return ` ${node.id}${open}\"${node.label}\"${close}`;\n}\n\nfunction edgeArrow(edge: DiagramEdge): string {\n const style = edge.style ?? 'solid';\n const arrowhead = edge.arrowhead ?? 'arrow';\n // Mermaid flowcharts only have solid and dashed; dotted collapses to dashed.\n if (style === 'dashed' || style === 'dotted') return arrowhead === 'none' ? '-.-' : '-.->';\n return arrowhead === 'none' ? '---' : '-->';\n}\n\nfunction formatEdge(edge: DiagramEdge): string {\n const arrow = edgeArrow(edge);\n return edge.label\n ? ` ${edge.from} ${arrow}|\"${edge.label}\"| ${edge.to}`\n : ` ${edge.from} ${arrow} ${edge.to}`;\n}\n\nfunction exportFlowchart(model: DiagramModel): string {\n const lines: string[] = ['graph TD'];\n if (model.title) lines.unshift(`---\\ntitle: ${model.title}\\n---`);\n for (const node of model.nodes) lines.push(formatNode(node));\n for (const edge of model.edges) lines.push(formatEdge(edge));\n return lines.join('\\n');\n}\n\nfunction msgArrow(msg: SequenceMessage): string {\n return msg.style === 'dashed' ? '-->>' : '->>';\n}\n\nfunction exportSequence(model: DiagramModel): string {\n const lines: string[] = ['sequenceDiagram'];\n if (model.title) lines.unshift(`---\\ntitle: ${model.title}\\n---`);\n for (const actor of model.actors ?? []) lines.push(` participant ${actor}`);\n for (const msg of model.messages ?? []) {\n lines.push(` ${msg.from}${msgArrow(msg)}${msg.to}: ${msg.label}`);\n }\n return lines.join('\\n');\n}\n\n/**\n * Serialize a `DiagramModel` to Mermaid source. Dispatches between\n * `graph TD` (flowchart) and `sequenceDiagram` based on `model.type`.\n *\n * **Round-trip notes (flowchart):**\n * - Node shapes `rectangle`, `diamond`, `circle`, `parallelogram` map to\n * `[ ]`, `{ }`, `(( ))`, `[/ /]` respectively.\n * - Edge style `solid` → `-->`, `dashed` and `dotted` → `-.->` (Mermaid\n * collapses dotted to dashed). `arrowhead: 'none'` strips the head.\n * - `waypoint`, `metadata`, and `variant` are **dropped** — Mermaid has no\n * way to encode routing or arbitrary metadata.\n *\n * **Round-trip notes (sequence):**\n * - Message style `solid` → `->>`, `dashed` → `-->>`.\n */\nexport function toMermaid(model: DiagramModel): string {\n return model.type === 'sequence' ? exportSequence(model) : exportFlowchart(model);\n}\n","import type { DiagramModel, DiagramNode, DiagramEdge, SequenceMessage } from '../core/types.js';\n\nfunction nodeShape(node: DiagramNode): [string, string] {\n switch (node.shape) {\n case 'diamond':\n return ['<>', '<>'];\n case 'circle':\n return ['(', ')'];\n case 'parallelogram':\n return ['/', '/'];\n default:\n return ['[', ']'];\n }\n}\n\nfunction exportFlowchart(model: DiagramModel): string {\n const lines: string[] = ['@startuml'];\n if (model.title) lines.push(`title ${model.title}`);\n lines.push('');\n\n for (const node of model.nodes) {\n const [open, close] = nodeShape(node);\n lines.push(`state \"${node.label}\" as ${node.id} ${open}${close}`);\n }\n lines.push('');\n\n for (const edge of model.edges) {\n const arrow =\n edge.style === 'dashed' ? '-[dashed]->' : edge.style === 'dotted' ? '-[dotted]->' : '-->';\n const label = edge.label ? ` : ${edge.label}` : '';\n lines.push(`${edge.from} ${arrow} ${edge.to}${label}`);\n }\n\n lines.push('@enduml');\n return lines.join('\\n');\n}\n\nfunction msgArrow(msg: SequenceMessage): string {\n return msg.style === 'dashed' ? '-->' : '->';\n}\n\nfunction exportSequence(model: DiagramModel): string {\n const lines: string[] = ['@startuml'];\n if (model.title) lines.push(`title ${model.title}`);\n lines.push('');\n\n for (const actor of model.actors ?? []) {\n lines.push(`participant ${actor}`);\n }\n lines.push('');\n\n for (const msg of model.messages ?? []) {\n lines.push(`${msg.from} ${msgArrow(msg)} ${msg.to} : ${msg.label}`);\n }\n\n lines.push('@enduml');\n return lines.join('\\n');\n}\n\n/**\n * Serialize a `DiagramModel` to PlantUML source. Dispatches between the\n * state-diagram form (flowchart) and the sequence-diagram form based on\n * `model.type`.\n *\n * **Round-trip notes (flowchart):**\n * - Edge style maps `solid` → `-->`, `dashed` → `-[dashed]->`,\n * `dotted` → `-[dotted]->`.\n * - Node shapes are emitted via the `state \"..\" as id < >` syntax; some\n * shape information is lossy (PlantUML state diagrams don't distinguish\n * every shape this package supports).\n * - `waypoint`, `metadata`, and `variant` are **dropped**.\n *\n * **Round-trip notes (sequence):**\n * - Actor order is preserved; message style `solid` → `->`, `dashed` → `-->`.\n */\nexport function toPlantUML(model: DiagramModel): string {\n return model.type === 'sequence' ? exportSequence(model) : exportFlowchart(model);\n}\n","import type { DiagramModel } from '../core/types.js';\n\n/**\n * Serialize a `DiagramModel` to pretty-printed JSON. This is the canonical\n * round-trip format: every field — including `variant`, `waypoint`,\n * `metadata.group`, and `metadata.answers` — survives a round trip through\n * `toJSON` + `fromJSON` unchanged.\n */\nexport function toJSON(model: DiagramModel): string {\n return JSON.stringify(model, null, 2);\n}\n","import type { DiagramModel, DiagramNode, DiagramEdge } from '../core/types.js';\n\n// Layout constants — kept in sync with src/ui/DiagramEditor.tsx\nconst NODE_H = 48;\nconst Q_BASE_H = 68;\nconst Q_ANS_ROW_H = 80;\nconst Q_CARD_PAD = 8;\nconst MIN_NODE_W = 120;\nconst MAX_NODE_W = 320;\nconst MIN_Q_W = 220;\nconst PADDING = 48;\nconst H_GAP = 80;\nconst V_GAP = 96;\n\nfunction estimateTextW(text: string, pxPerChar = 7.5): number {\n return text.length * pxPerChar;\n}\n\nfunction nodeWidth(label: string): number {\n return Math.min(MAX_NODE_W, Math.max(MIN_NODE_W, Math.ceil(estimateTextW(label) + 48)));\n}\n\nfunction answerCardW(ans: string): number {\n return Math.max(86, Math.ceil(Math.max(estimateTextW(ans, 7.5) + 20, 56) + 32));\n}\n\nfunction questionNodeW(node: DiagramNode): number {\n const answers = (node.metadata?.answers as string[] | undefined) ?? [];\n const headerW = estimateTextW(node.label, 8) + 80;\n if (answers.length === 0) return Math.max(MIN_Q_W, Math.ceil(headerW));\n const cardsW =\n answers.reduce((s, a) => s + answerCardW(a), 0) +\n (answers.length - 1) * Q_CARD_PAD +\n 2 * Q_CARD_PAD;\n return Math.max(MIN_Q_W, Math.ceil(Math.max(headerW, cardsW)));\n}\n\nfunction questionNodeH(answers: string[]): number {\n return Q_BASE_H + (answers.length === 0 ? 48 : Q_ANS_ROW_H);\n}\n\nfunction bezierPath(x1: number, y1: number, x2: number, y2: number): string {\n const dy = y2 - y1;\n const dyAbs = Math.abs(dy);\n const dxAbs = Math.abs(x2 - x1);\n const base = dy > 0 ? dyAbs * 0.55 : Math.max(90, dyAbs * 0.5 + dxAbs * 0.28);\n const curve = Math.max(36, Math.min(220, base));\n return `M ${x1} ${y1} C ${x1} ${y1 + curve}, ${x2} ${y2 - curve}, ${x2} ${y2}`;\n}\n\ninterface LayoutBox {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nfunction isQuestion(node: DiagramNode, variant: DiagramModel['variant']): boolean {\n return variant === 'question' && !!node.metadata?.answers;\n}\n\n/** Honor x/y on nodes if present; otherwise BFS-layer fallback. */\nfunction computeLayout(model: DiagramModel): Map<string, LayoutBox> {\n const boxes = new Map<string, LayoutBox>();\n const sized = model.nodes.map((n) => {\n const w = isQuestion(n, model.variant) ? questionNodeW(n) : nodeWidth(n.label);\n const h = isQuestion(n, model.variant)\n ? questionNodeH((n.metadata?.answers as string[] | undefined) ?? [])\n : NODE_H;\n return { node: n, w, h };\n });\n\n const allPositioned = sized.every(\n (s) => typeof s.node.x === 'number' && typeof s.node.y === 'number',\n );\n if (allPositioned) {\n for (const s of sized) {\n boxes.set(s.node.id, { x: s.node.x as number, y: s.node.y as number, w: s.w, h: s.h });\n }\n return boxes;\n }\n\n // BFS-layer fallback for un-positioned graphs (e.g. fresh imports).\n const inDeg = new Map(model.nodes.map((n) => [n.id, 0]));\n for (const e of model.edges) inDeg.set(e.to, (inDeg.get(e.to) ?? 0) + 1);\n\n const layers = new Map<string, number>();\n const queue = model.nodes.filter((n) => (inDeg.get(n.id) ?? 0) === 0).map((n) => n.id);\n for (const id of queue) layers.set(id, 0);\n let head = 0;\n while (head < queue.length) {\n const cur = queue[head++]!;\n const layer = layers.get(cur) ?? 0;\n for (const e of model.edges) {\n if (e.from === cur) {\n const next = layers.get(e.to) ?? -1;\n if (next < layer + 1) {\n layers.set(e.to, layer + 1);\n queue.push(e.to);\n }\n }\n }\n }\n model.nodes.forEach((n) => {\n if (!layers.has(n.id)) layers.set(n.id, 0);\n });\n\n const byLayer = new Map<number, typeof sized>();\n for (const s of sized) {\n const layer = layers.get(s.node.id) ?? 0;\n if (!byLayer.has(layer)) byLayer.set(layer, []);\n byLayer.get(layer)!.push(s);\n }\n\n let y = PADDING;\n for (const layer of [...byLayer.keys()].sort((a, b) => a - b)) {\n const row = byLayer.get(layer)!;\n let x = PADDING;\n let maxH = 0;\n for (const s of row) {\n boxes.set(s.node.id, { x, y, w: s.w, h: s.h });\n x += s.w + H_GAP;\n maxH = Math.max(maxH, s.h);\n }\n y += maxH + V_GAP;\n }\n return boxes;\n}\n\nfunction escapeXML(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n/**\n * Defence-in-depth sanitizer for SVG output. Strips dangerous patterns\n * before XML-escaping. Prevents script injection even if escapeXML were\n * somehow bypassed or if the SVG is consumed by a less-strict parser.\n */\nfunction sanitizeForSVG(s: string): string {\n let clean = s;\n // Strip HTML/XML tags (loop to handle nested constructions)\n // Requires letter or / after < to avoid matching plain text like \"x < y > z\"\n while (/<[a-zA-Z/][^>]{0,500}>/g.test(clean)) {\n clean = clean.replace(/<[a-zA-Z/][^>]{0,500}>/g, '');\n }\n // Strip javascript:/data:/vbscript: URIs (loop for incomplete multi-char sanitization)\n while (/\\b(?:javascript|data|vbscript)\\s*:/gi.test(clean)) {\n clean = clean.replace(/\\b(?:javascript|data|vbscript)\\s*:/gi, '');\n }\n // Strip on* event handlers (loop for incomplete multi-char sanitization)\n while (/\\bon[a-z]+\\s*=/gi.test(clean)) {\n clean = clean.replace(/\\bon[a-z]+\\s*=/gi, '');\n }\n // Strip null bytes\n // eslint-disable-next-line no-control-regex\n clean = clean.replace(/\\x00/g, '');\n return escapeXML(clean);\n}\n\n// Match canvas: indigo/slate palette, light theme by default.\nconst COLORS = {\n bg: '#fafbfc',\n dot: '#dbe3ee',\n nodeFill: '#ffffff',\n nodeStroke: '#cbd5e1',\n edge: '#94a3b8',\n text: '#1e293b',\n textSub: '#94a3b8',\n amber: '#d97706',\n amberSoft: '#fef9ee',\n amberLine: '#fde68a',\n amberCardBg: '#fffdf7',\n};\n\nfunction renderStandardNode(node: DiagramNode, box: LayoutBox): string {\n const cx = box.x + box.w / 2;\n const cy = box.y + box.h / 2;\n const shape = node.shape ?? 'rectangle';\n const label = `<text x=\"${cx}\" y=\"${cy + 4.5}\" text-anchor=\"middle\" font-family=\"ui-sans-serif,system-ui,-apple-system,sans-serif\" font-size=\"13\" font-weight=\"500\" fill=\"${COLORS.text}\">${sanitizeForSVG(node.label)}</text>`;\n\n let shapeEl: string;\n if (shape === 'diamond') {\n const pts = `${cx},${box.y} ${box.x + box.w},${cy} ${cx},${box.y + box.h} ${box.x},${cy}`;\n shapeEl = `<polygon points=\"${pts}\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1.25\" filter=\"url(#nodeShadow)\"/>`;\n } else if (shape === 'circle') {\n const r = Math.min(box.w, box.h) / 2 - 1;\n shapeEl = `<circle cx=\"${cx}\" cy=\"${cy}\" r=\"${r}\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1.25\" filter=\"url(#nodeShadow)\"/>`;\n } else if (shape === 'parallelogram') {\n const pts = `${box.x + 14},${box.y} ${box.x + box.w},${box.y} ${box.x + box.w - 14},${box.y + box.h} ${box.x},${box.y + box.h}`;\n shapeEl = `<polygon points=\"${pts}\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1.25\" filter=\"url(#nodeShadow)\"/>`;\n } else {\n shapeEl = `<rect x=\"${box.x}\" y=\"${box.y}\" width=\"${box.w}\" height=\"${box.h}\" rx=\"14\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1.25\" filter=\"url(#nodeShadow)\"/>`;\n }\n return shapeEl + label;\n}\n\nfunction renderQuestionNode(node: DiagramNode, box: LayoutBox): string {\n const answers = (node.metadata?.answers as string[] | undefined) ?? [];\n const clipId = `qhdr-${node.id.replace(/[^a-zA-Z0-9_-]/g, '_')}`;\n const x = box.x,\n y = box.y,\n w = box.w,\n h = box.h;\n const parts: string[] = [];\n\n // Card body\n parts.push(\n `<rect x=\"${x}\" y=\"${y}\" width=\"${w}\" height=\"${h}\" rx=\"14\" fill=\"${COLORS.nodeFill}\" stroke=\"${COLORS.amberLine}\" stroke-width=\"1.5\" filter=\"url(#nodeShadow)\"/>`,\n );\n\n // Header tint (clipped to top rounded corners)\n parts.push(\n `<defs><clipPath id=\"${clipId}\"><rect x=\"${x}\" y=\"${y}\" width=\"${w}\" height=\"${Q_BASE_H}\" rx=\"14\"/></clipPath></defs>`,\n );\n parts.push(\n `<rect x=\"${x}\" y=\"${y}\" width=\"${w}\" height=\"${Q_BASE_H}\" fill=\"${COLORS.amberSoft}\" clip-path=\"url(#${clipId})\"/>`,\n );\n\n // Amber left accent\n parts.push(\n `<rect x=\"${x}\" y=\"${y}\" width=\"4\" height=\"${Q_BASE_H}\" rx=\"2\" fill=\"${COLORS.amber}\"/>`,\n );\n\n // ? badge\n parts.push(\n `<rect x=\"${x + 12}\" y=\"${y + 14}\" width=\"28\" height=\"28\" rx=\"8\" fill=\"${COLORS.amber}\"/>`,\n );\n parts.push(\n `<text x=\"${x + 26}\" y=\"${y + 33}\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"900\" fill=\"white\">?</text>`,\n );\n\n // QUESTION label + node label\n parts.push(\n `<text x=\"${x + 50}\" y=\"${y + 27}\" font-family=\"ui-sans-serif,system-ui,sans-serif\" font-size=\"9\" font-weight=\"700\" fill=\"${COLORS.textSub}\" letter-spacing=\"0.6\">QUESTION</text>`,\n );\n parts.push(\n `<text x=\"${x + 50}\" y=\"${y + 42}\" font-family=\"ui-sans-serif,system-ui,sans-serif\" font-size=\"13\" font-weight=\"700\" fill=\"${COLORS.text}\">${sanitizeForSVG(node.label)}</text>`,\n );\n\n // Divider\n parts.push(\n `<line x1=\"${x}\" y1=\"${y + Q_BASE_H}\" x2=\"${x + w}\" y2=\"${y + Q_BASE_H}\" stroke=\"${COLORS.amberLine}\" stroke-width=\"1\"/>`,\n );\n\n if (answers.length === 0) {\n parts.push(\n `<text x=\"${x + w / 2}\" y=\"${y + Q_BASE_H + 22}\" text-anchor=\"middle\" font-size=\"10\" fill=\"${COLORS.amber}\" opacity=\"0.4\" font-weight=\"600\">No answers yet</text>`,\n );\n } else {\n const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n answers.forEach((ans, i) => {\n const prevW = answers.slice(0, i).reduce((s, a) => s + answerCardW(a) + Q_CARD_PAD, 0);\n const cW = answerCardW(ans);\n const cardX = x + Q_CARD_PAD + prevW;\n const cardY = y + Q_BASE_H + 7;\n const cardH = Q_ANS_ROW_H - 20;\n const cx = cardX + cW / 2;\n const letter = i < 26 ? letters[i]! : `${i + 1}`;\n const maxChars = Math.max(2, Math.floor((cW - 20) / 7.5));\n const displayAns = ans.length > maxChars ? ans.slice(0, maxChars - 1) + '…' : ans;\n\n parts.push(\n `<rect x=\"${cardX}\" y=\"${cardY}\" width=\"${cW}\" height=\"${cardH}\" rx=\"8\" fill=\"${COLORS.amberCardBg}\" stroke=\"${COLORS.amberLine}\" stroke-width=\"1\"/>`,\n );\n parts.push(\n `<rect x=\"${cx - 11}\" y=\"${cardY + 7}\" width=\"22\" height=\"22\" rx=\"6\" fill=\"#fef3c7\"/>`,\n );\n parts.push(\n `<text x=\"${cx}\" y=\"${cardY + 22}\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"800\" fill=\"${COLORS.amber}\">${sanitizeForSVG(letter)}</text>`,\n );\n parts.push(\n `<text x=\"${cx}\" y=\"${cardY + 46}\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"500\" fill=\"#374151\" font-family=\"ui-sans-serif,system-ui,sans-serif\">${sanitizeForSVG(displayAns)}</text>`,\n );\n });\n }\n\n return parts.join('');\n}\n\nfunction renderEdge(\n edge: DiagramEdge,\n boxes: Map<string, LayoutBox>,\n variant: DiagramModel['variant'],\n nodes: DiagramNode[],\n): string {\n const fromBox = boxes.get(edge.from);\n const toBox = boxes.get(edge.to);\n if (!fromBox || !toBox) return '';\n\n let x1: number, y1: number;\n const fromNode = nodes.find((n) => n.id === edge.from);\n\n if (fromNode && isQuestion(fromNode, variant)) {\n const answers = (fromNode.metadata?.answers as string[] | undefined) ?? [];\n const idx = answers.indexOf(edge.label ?? '');\n if (idx >= 0) {\n const prevW = answers.slice(0, idx).reduce((s, a) => s + answerCardW(a) + Q_CARD_PAD, 0);\n const cW = answerCardW(answers[idx]!);\n x1 = fromBox.x + Q_CARD_PAD + prevW + cW / 2;\n y1 = fromBox.y + Q_BASE_H + Q_ANS_ROW_H - 8;\n } else {\n x1 = fromBox.x + fromBox.w / 2;\n y1 = fromBox.y + fromBox.h;\n }\n } else {\n x1 = fromBox.x + fromBox.w / 2;\n y1 = fromBox.y + fromBox.h;\n }\n const x2 = toBox.x + toBox.w / 2;\n const y2 = toBox.y;\n\n const dash =\n edge.style === 'dashed'\n ? ' stroke-dasharray=\"6,4\"'\n : edge.style === 'dotted'\n ? ' stroke-dasharray=\"2,3\"'\n : '';\n const marker = edge.arrowhead === 'none' ? '' : ' marker-end=\"url(#arrow)\"';\n const d = bezierPath(x1, y1, x2, y2);\n\n let out = `<path d=\"${d}\" fill=\"none\" stroke=\"${COLORS.edge}\" stroke-width=\"1.5\"${dash}${marker}/>`;\n\n if (edge.label) {\n const midX = (x1 + x2) / 2;\n const midY = (y1 + y2) / 2;\n const labelW = estimateTextW(edge.label, 7) + 14;\n out += `<rect x=\"${midX - labelW / 2}\" y=\"${midY - 11}\" width=\"${labelW}\" height=\"18\" rx=\"9\" fill=\"${COLORS.bg}\" stroke=\"${COLORS.nodeStroke}\" stroke-width=\"1\"/>`;\n out += `<text x=\"${midX}\" y=\"${midY + 2}\" text-anchor=\"middle\" font-family=\"ui-sans-serif,system-ui,sans-serif\" font-size=\"11\" fill=\"${COLORS.text}\">${sanitizeForSVG(edge.label)}</text>`;\n }\n return out;\n}\n\n/**\n * Render a `DiagramModel` to a standalone SVG string. The output mirrors the\n * editor canvas: dot-grid background, soft drop-shadowed nodes, smooth\n * cubic-bezier edges. No external assets — the result is fully inline and\n * pasteable into HTML, README files, or PR descriptions.\n *\n * Layout is computed identically to the editor's hit-test pass (same width\n * estimation, padding, and question-card sizing), so an exported SVG matches\n * what you see on screen.\n *\n * Works in Node, Bun, and the browser (no DOM APIs needed).\n */\nexport function toSVG(model: DiagramModel): string {\n const boxes = computeLayout(model);\n let maxX = 0,\n maxY = 0;\n for (const b of boxes.values()) {\n maxX = Math.max(maxX, b.x + b.w);\n maxY = Math.max(maxY, b.y + b.h);\n }\n const width = maxX + PADDING;\n const height = maxY + PADDING + (model.title ? 32 : 0);\n\n const defs = [\n `<defs>`,\n `<pattern id=\"dotgrid\" x=\"0\" y=\"0\" width=\"24\" height=\"24\" patternUnits=\"userSpaceOnUse\">`,\n `<circle cx=\"12\" cy=\"12\" r=\"1.1\" fill=\"${COLORS.dot}\"/>`,\n `</pattern>`,\n `<filter id=\"nodeShadow\" x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">`,\n `<feDropShadow dx=\"0\" dy=\"3\" stdDeviation=\"5\" flood-color=\"rgba(15,23,42,0.09)\"/>`,\n `</filter>`,\n `<marker id=\"arrow\" markerWidth=\"9\" markerHeight=\"7\" refX=\"8.5\" refY=\"3.5\" orient=\"auto\" markerUnits=\"strokeWidth\">`,\n `<path d=\"M0,0.5 L9,3.5 L0,6.5 L2.2,3.5 Z\" fill=\"${COLORS.edge}\"/>`,\n `</marker>`,\n `</defs>`,\n ].join('');\n\n const titleEl = model.title\n ? `<text x=\"${width / 2}\" y=\"22\" text-anchor=\"middle\" font-family=\"ui-sans-serif,system-ui,sans-serif\" font-size=\"15\" font-weight=\"700\" fill=\"${COLORS.text}\">${sanitizeForSVG(model.title)}</text>`\n : '';\n\n const edges = model.edges.map((e) => renderEdge(e, boxes, model.variant, model.nodes)).join('\\n');\n const nodes = model.nodes\n .map((n) => {\n const b = boxes.get(n.id)!;\n return isQuestion(n, model.variant) ? renderQuestionNode(n, b) : renderStandardNode(n, b);\n })\n .join('\\n');\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">\\n${defs}\\n<rect width=\"${width}\" height=\"${height}\" fill=\"${COLORS.bg}\"/>\\n<rect width=\"${width}\" height=\"${height}\" fill=\"url(#dotgrid)\"/>\\n${titleEl}\\n${edges}\\n${nodes}\\n</svg>`;\n}\n\n/**\n * Render a `DiagramModel` to a PNG `Blob`. Routes the SVG output through an\n * `<img>` and a `<canvas>` at `devicePixelRatio` scale, so the result is\n * crisp on hi-DPI displays.\n *\n * **Browser-only.** Throws if called in a Node/Bun environment (the Canvas\n * API is not available). For server-side PNG rendering, pipe `toSVG()` output\n * through a library like `@resvg/resvg-js`.\n */\nexport async function toPNG(model: DiagramModel): Promise<Blob> {\n if (typeof document === 'undefined') {\n throw new Error(\n 'toPNG requires a browser environment. For Node/Bun server use, pipe toSVG() through @resvg/resvg-js.',\n );\n }\n const svg = toSVG(model);\n const blob = new Blob([svg], { type: 'image/svg+xml' });\n const url = URL.createObjectURL(blob);\n\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n const scale = window.devicePixelRatio || 2;\n canvas.width = img.naturalWidth * scale;\n canvas.height = img.naturalHeight * scale;\n const ctx = canvas.getContext('2d')!;\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n canvas.toBlob(\n (b) => (b ? resolve(b) : reject(new Error('Canvas toBlob failed'))),\n 'image/png',\n );\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('SVG image load failed'));\n };\n img.src = url;\n });\n}\n","import { Model } from './model.js';\nimport type { DiagramEdge, DiagramNode, NodeShape } from './types.js';\nimport { nextId } from './ids.js';\nimport { toMermaid } from '../exporters/mermaid.js';\nimport { toPlantUML } from '../exporters/plantuml.js';\nimport { toJSON } from '../exporters/json.js';\nimport { toSVG, toPNG } from '../exporters/svg.js';\n\n/**\n * Fluent builder for flowchart-type diagrams. Wraps `Model` with shorter\n * method names tuned for one-shot construction in tests and scripts, and\n * with convenience exporters for every supported `ExportFormat`.\n *\n * @example\n * ```ts\n * const svg = flowchart('Login')\n * .node('start', 'Begin', { shape: 'circle' })\n * .node('check', 'Authenticated?', { shape: 'diamond' })\n * .edge('start', 'check')\n * .toSVG();\n * ```\n */\nexport class FlowchartBuilder {\n private model: Model;\n\n /** @param title Optional human-readable diagram title. */\n constructor(title?: string) {\n this.model = new Model('flowchart', title);\n }\n\n /**\n * Append a node. Defaults `shape` to `rectangle` when omitted from `options`.\n * Throws on duplicate id.\n */\n node(id: string, label: string, options: Partial<Omit<DiagramNode, 'id' | 'label'>> = {}): this {\n this.model.addNode({ id, label, shape: options.shape ?? 'rectangle', ...options });\n return this;\n }\n\n /**\n * Append an edge with an auto-generated id. The id is derived from the\n * current edge list to avoid collisions with imported models.\n */\n edge(\n from: string,\n to: string,\n options: Partial<Omit<DiagramEdge, 'id' | 'from' | 'to'>> = {},\n ): this {\n this.model.addEdge({ id: nextId('e', this.model.toJSON().edges), from, to, ...options });\n return this;\n }\n\n /** Remove a node and every edge that references it. */\n removeNode(id: string): this {\n this.model.removeNode(id);\n return this;\n }\n\n /** Remove an edge by id. */\n removeEdge(id: string): this {\n this.model.removeEdge(id);\n return this;\n }\n\n /** Patch an existing node. See `Model.updateNode`. */\n updateNode(id: string, patch: Partial<Omit<DiagramNode, 'id'>>): this {\n this.model.updateNode(id, patch);\n return this;\n }\n\n /** Return the underlying `Model` for advanced operations or validation. */\n getModel(): Model {\n return this.model;\n }\n\n /** Serialize as Mermaid `flowchart TD` source. */\n toMermaid(): string {\n return toMermaid(this.model.toJSON());\n }\n\n /** Serialize as PlantUML activity-diagram source. */\n toPlantUML(): string {\n return toPlantUML(this.model.toJSON());\n }\n\n /** Serialize as the package's JSON shape (full round-trip fidelity). */\n toJSON(): string {\n return toJSON(this.model.toJSON());\n }\n\n /** Render to a standalone SVG string. */\n toSVG(): string {\n return toSVG(this.model.toJSON());\n }\n\n /** Render to a PNG `Blob`. Browser-only (uses the Canvas API). */\n toPNG(): Promise<Blob> {\n return toPNG(this.model.toJSON());\n }\n}\n\n/** Convenience constructor — `flowchart('My Diagram')` is `new FlowchartBuilder('My Diagram')`. */\nexport function flowchart(title?: string): FlowchartBuilder {\n return new FlowchartBuilder(title);\n}\n","import { Model } from './model.js';\nimport type { SequenceMessage } from './types.js';\nimport { nextId } from './ids.js';\nimport { toMermaid } from '../exporters/mermaid.js';\nimport { toPlantUML } from '../exporters/plantuml.js';\nimport { toJSON } from '../exporters/json.js';\n\n/**\n * Fluent builder for sequence-type diagrams. Mirrors `FlowchartBuilder` but\n * over `actors`/`messages` instead of `nodes`/`edges`.\n *\n * @example\n * ```ts\n * const puml = sequence('Checkout')\n * .actor('User')\n * .message('User', 'Server', 'POST /pay')\n * .replyMessage('Server', 'User', '200 OK')\n * .toPlantUML();\n * ```\n */\nexport class SequenceBuilder {\n private model: Model;\n\n /** @param title Optional human-readable diagram title. */\n constructor(title?: string) {\n this.model = new Model('sequence', title);\n }\n\n /** Register an actor. Duplicates are silently ignored. */\n actor(name: string): this {\n this.model.addActor(name);\n return this;\n }\n\n /**\n * Append a message. Both endpoints are auto-registered as actors if not\n * already present. The id is derived from the current message list.\n */\n message(\n from: string,\n to: string,\n label: string,\n options: Partial<Pick<SequenceMessage, 'style'>> = {},\n ): this {\n this.model.addActor(from);\n this.model.addActor(to);\n const messages = this.model.toJSON().messages ?? [];\n this.model.addMessage({\n id: nextId('m', messages),\n from,\n to,\n label,\n style: options.style ?? 'solid',\n });\n return this;\n }\n\n /** Convenience for a `dashed`-style return message. */\n replyMessage(from: string, to: string, label: string): this {\n return this.message(from, to, label, { style: 'dashed' });\n }\n\n /** Return the underlying `Model` for advanced operations or validation. */\n getModel(): Model {\n return this.model;\n }\n\n /** Serialize as Mermaid `sequenceDiagram` source. */\n toMermaid(): string {\n return toMermaid(this.model.toJSON());\n }\n\n /** Serialize as PlantUML sequence-diagram source. */\n toPlantUML(): string {\n return toPlantUML(this.model.toJSON());\n }\n\n /** Serialize as the package's JSON shape (full round-trip fidelity). */\n toJSON(): string {\n return toJSON(this.model.toJSON());\n }\n}\n\n/** Convenience constructor — `sequence('My Diagram')` is `new SequenceBuilder('My Diagram')`. */\nexport function sequence(title?: string): SequenceBuilder {\n return new SequenceBuilder(title);\n}\n","/**\n * Centralized input sanitization for all user-provided text that flows\n * into SVG output, labels, or any rendering context.\n *\n * Defence-in-depth: even though `escapeXML()` prevents most injection,\n * stripping dangerous patterns at the source stops payloads from reaching\n * any downstream consumer (clipboard, third-party renderers, etc.).\n */\n\n/** Maximum characters allowed in a single label/text field. */\nexport const MAX_LABEL_LENGTH = 2000;\n\n/** Maximum number of nodes allowed in a single diagram. */\nexport const MAX_NODES = 500;\n\n/** Maximum number of edges allowed in a single diagram. */\nexport const MAX_EDGES = 2000;\n\n/** Maximum number of actors in a sequence diagram. */\nexport const MAX_ACTORS = 100;\n\n/** Maximum number of messages in a sequence diagram. */\nexport const MAX_MESSAGES = 2000;\n\n/** Maximum raw input length for importers (bytes). ~2 MB */\nexport const MAX_IMPORT_LENGTH = 2 * 1024 * 1024;\n\n/**\n * Strip dangerous content from user-supplied text. Removes:\n * - HTML tags (`<script>`, `<img>`, `<foreignObject>`, etc.)\n * - `javascript:`, `data:`, `vbscript:` URI schemes\n * - `on*` event handler attributes (onerror, onclick, etc.)\n * - Null bytes and other control characters\n */\nexport function sanitizeLabel(raw: string): string {\n let s = raw;\n // Remove null bytes and ASCII control chars (except \\n, \\r, \\t)\n // eslint-disable-next-line no-control-regex\n s = s.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '');\n // Strip HTML/XML tags (loop to handle nested constructions)\n // Requires letter or / after < to avoid matching plain text like \"x < y > z\"\n while (/<[a-zA-Z/][^>]{0,500}>/g.test(s)) {\n s = s.replace(/<[a-zA-Z/][^>]{0,500}>/g, '');\n }\n // Strip javascript:/data:/vbscript: URIs (loop for incomplete multi-char sanitization)\n while (/\\b(?:javascript|data|vbscript)\\s*:/gi.test(s)) {\n s = s.replace(/\\b(?:javascript|data|vbscript)\\s*:/gi, '');\n }\n // Strip on* event handlers (loop for incomplete multi-char sanitization)\n while (/\\bon[a-z]+\\s*=/gi.test(s)) {\n s = s.replace(/\\bon[a-z]+\\s*=/gi, '');\n }\n // Enforce length limit\n if (s.length > MAX_LABEL_LENGTH) {\n s = s.slice(0, MAX_LABEL_LENGTH);\n }\n return s;\n}\n\n/**\n * Validate a URL is safe for use in href attributes.\n * Only allows http:, https:, and mailto: protocols.\n * Returns the URL if safe, or `undefined` if dangerous.\n */\nexport function sanitizeURL(url: string): string | undefined {\n const trimmed = url.trim();\n // Allow relative URLs (start with / or #)\n if (trimmed.startsWith('/') || trimmed.startsWith('#')) return trimmed;\n // Allow http(s) and mailto\n if (/^https?:\\/\\//i.test(trimmed) || /^mailto:/i.test(trimmed)) return trimmed;\n // Block everything else (javascript:, data:, vbscript:, etc.)\n return undefined;\n}\n","import { Model } from '../core/model.js';\nimport type { NodeShape } from '../core/types.js';\nimport { nextId } from '../core/ids.js';\nimport {\n sanitizeLabel,\n MAX_NODES,\n MAX_EDGES,\n MAX_ACTORS,\n MAX_MESSAGES,\n MAX_IMPORT_LENGTH,\n} from '../core/sanitize.js';\n\n// Detects shape from Mermaid node syntax\nfunction parseNodeDecl(raw: string): { id: string; label: string; shape: NodeShape } | null {\n // diamond: id{label}, circle: id((label)), parallelogram: id[/label/], default: id[label] or id(\"label\")\n const patterns: [RegExp, NodeShape][] = [\n [/^(\\w+)\\{\\{?\"?([^}\"]+)\"?\\}?\\}$/, 'diamond'],\n [/^(\\w+)\\(\\(\"?([^)\"]+)\"?\\)\\)$/, 'circle'],\n [/^(\\w+)\\[\\/([^/\\]]+)\\/\\]$/, 'parallelogram'],\n [/^(\\w+)\\[[\"']?([^\\]\"']+)[\"']?\\]$/, 'rectangle'],\n [/^(\\w+)\\(\"?([^)\"]+)\"?\\)$/, 'rectangle'],\n ];\n for (const [re, shape] of patterns) {\n const m = raw.match(re);\n if (m) return { id: m[1]!, label: sanitizeLabel(m[2]!.replace(/^[\"']|[\"']$/g, '')), shape };\n }\n return null;\n}\n\n// Mermaid flowchart edge connector: solid (-->, ---), dashed (-.->, -.-), or with labels.\n// Uses \\S+ for node IDs to prevent polynomial backtracking (no overlap with \\s*).\nconst EDGE_RE = /^(\\S+)\\s*(-\\.->|-\\.-|-->|---)(?:\\|([^|]+)\\|)?\\s*(.+)$/;\n\nfunction detectStyle(connector: string): 'solid' | 'dashed' {\n return connector.startsWith('-.') ? 'dashed' : 'solid';\n}\n\nfunction detectArrowhead(connector: string): 'arrow' | 'none' {\n return connector.endsWith('>') ? 'arrow' : 'none';\n}\n\nfunction parseFlowchart(lines: string[]): Model {\n const model = new Model('flowchart');\n const nodeMap = new Map<string, boolean>();\n const groupStack: string[] = [];\n let edgeCount = 0;\n\n const ensureNode = (id: string, group?: string) => {\n if (!nodeMap.has(id)) {\n if (nodeMap.size >= MAX_NODES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_NODES} nodes`);\n nodeMap.set(id, true);\n const metadata = group ? { group } : undefined;\n model.addNode({ id, label: id, shape: 'rectangle', ...(metadata ? { metadata } : {}) });\n }\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n // Skip Mermaid comments, config blocks, header directives, and click handlers.\n if (\n trimmed.startsWith('%%') ||\n trimmed.startsWith('graph') ||\n trimmed.startsWith('flowchart') ||\n trimmed.startsWith('click ') ||\n trimmed.startsWith('classDef ') ||\n trimmed.startsWith('class ') ||\n trimmed.startsWith('style ') ||\n trimmed.startsWith('linkStyle ')\n )\n continue;\n\n // Subgraphs: track current group so contained nodes get metadata.group set.\n const subgraphOpen = trimmed.match(/^subgraph\\s+(\\S+)/i);\n if (subgraphOpen) {\n groupStack.push(subgraphOpen[1]!);\n continue;\n }\n if (/^end\\b/i.test(trimmed)) {\n groupStack.pop();\n continue;\n }\n\n const currentGroup = groupStack[groupStack.length - 1];\n\n const edgeMatch = trimmed.match(EDGE_RE);\n if (edgeMatch) {\n const fromRaw = edgeMatch[1]!.trim();\n const connector = edgeMatch[2]!;\n const label = edgeMatch[3]?.replace(/^[\"']|[\"']$/g, '');\n const sanitizedLabel = label ? sanitizeLabel(label) : undefined;\n const toRaw = edgeMatch[4]!.trim();\n const style = detectStyle(connector);\n const arrowhead = detectArrowhead(connector);\n\n const fromNode = parseNodeDecl(fromRaw);\n const toNode = parseNodeDecl(toRaw);\n\n if (fromNode && !nodeMap.has(fromNode.id)) {\n if (nodeMap.size >= MAX_NODES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_NODES} nodes`);\n nodeMap.set(fromNode.id, true);\n const metadata = currentGroup ? { group: currentGroup } : undefined;\n model.addNode({ ...fromNode, ...(metadata ? { metadata } : {}) });\n } else if (!fromNode) {\n ensureNode(fromRaw.replace(/\\W.*/, ''), currentGroup);\n }\n if (toNode && !nodeMap.has(toNode.id)) {\n if (nodeMap.size >= MAX_NODES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_NODES} nodes`);\n nodeMap.set(toNode.id, true);\n const metadata = currentGroup ? { group: currentGroup } : undefined;\n model.addNode({ ...toNode, ...(metadata ? { metadata } : {}) });\n } else if (!toNode) {\n ensureNode(toRaw.replace(/\\W.*/, ''), currentGroup);\n }\n\n if (edgeCount >= MAX_EDGES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_EDGES} edges`);\n edgeCount++;\n const fromId = fromNode?.id ?? fromRaw.replace(/\\W.*/, '');\n const toId = toNode?.id ?? toRaw.replace(/\\W.*/, '');\n model.addEdge({\n id: nextId('e', model.toJSON().edges),\n from: fromId,\n to: toId,\n ...(sanitizedLabel ? { label: sanitizedLabel } : {}),\n style,\n ...(arrowhead === 'none' ? { arrowhead } : {}),\n });\n continue;\n }\n\n const nodeDecl = parseNodeDecl(trimmed);\n if (nodeDecl && !nodeMap.has(nodeDecl.id)) {\n if (nodeMap.size >= MAX_NODES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_NODES} nodes`);\n nodeMap.set(nodeDecl.id, true);\n const metadata = currentGroup ? { group: currentGroup } : undefined;\n model.addNode({ ...nodeDecl, ...(metadata ? { metadata } : {}) });\n }\n }\n\n return model;\n}\n\nfunction parseSequence(lines: string[], title?: string): Model {\n const model = new Model('sequence', title);\n let actorCount = 0;\n let messageCount = 0;\n\n const safeAddActor = (name: string) => {\n const safeName = sanitizeLabel(name);\n if (!model.toJSON().actors?.includes(safeName)) {\n if (actorCount >= MAX_ACTORS)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_ACTORS} actors`);\n actorCount++;\n }\n model.addActor(safeName);\n return safeName;\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('sequenceDiagram') || trimmed.startsWith('%%')) continue;\n\n const participantMatch = trimmed.match(/^participant\\s+(.+)$/i);\n if (participantMatch) {\n safeAddActor(participantMatch[1]!.trim());\n continue;\n }\n\n const actorMatch = trimmed.match(/^actor\\s+(.+)$/i);\n if (actorMatch) {\n safeAddActor(actorMatch[1]!.trim());\n continue;\n }\n\n // Sequence message arrows: ->, ->>, -->, -->> (-- prefix = dashed)\n // Uses negated char classes to prevent polynomial backtracking.\n const msgMatch = trimmed.match(/^(\\w+)\\s*(-->>|->>|-->|->)\\s*(\\w+):\\s*(.+)$/);\n if (msgMatch) {\n const from = safeAddActor(msgMatch[1]!.trim());\n const arrow = msgMatch[2]!;\n const to = safeAddActor(msgMatch[3]!.trim());\n const label = sanitizeLabel(msgMatch[4]!.trim());\n if (messageCount >= MAX_MESSAGES)\n throw new Error(`Import aborted: diagram exceeds the maximum of ${MAX_MESSAGES} messages`);\n messageCount++;\n const messages = model.toJSON().messages ?? [];\n model.addMessage({\n id: nextId('m', messages),\n from,\n to,\n label,\n style: arrow.startsWith('--') ? 'dashed' : 'solid',\n });\n }\n }\n\n return model;\n}\n\n/**\n * Parse Mermaid source into a `Model`. Auto-detects `flowchart` /\n * `sequenceDiagram` from the directive line and dispatches accordingly.\n *\n * **What is preserved:**\n * - Flowcharts: node shapes (`[]` / `{}` / `(())` / `[/]`), node labels,\n * edge connectors (`-->`, `-.->`, `---`, `-.-`), edge labels, and\n * `subgraph` grouping (stored on `node.metadata.group`).\n * - Sequence: actor declarations, message arrows (`->>`, `-->>`), labels.\n * - Frontmatter `title: ...` blocks are lifted into `model.title`.\n *\n * **What is dropped or normalized:**\n * - `mermaid.initialize(...)` blocks, `%%{init: ...}%%` directives, and\n * click handlers — stripped before parsing.\n * - Dotted edges collapse to `dashed` (Mermaid's dot/dash style is lossy).\n * - Node positions, `waypoint`, and any package-specific metadata other\n * than `group` are not present in Mermaid and so cannot round-trip.\n */\nexport function fromMermaid(mermaid: string): Model {\n if (mermaid.length > MAX_IMPORT_LENGTH) {\n throw new Error(`Import aborted: input exceeds the maximum of ${MAX_IMPORT_LENGTH} characters`);\n }\n // Strip mermaid.initialize(...) and similar JS-style config blocks that\n // sometimes appear in copy-pasted snippets. Uses [^)]* to avoid backtracking.\n const cleaned = mermaid.replace(/mermaid\\.initialize\\([^)]*\\)\\s*;?/g, '');\n const rawLines = cleaned.split('\\n');\n\n // Strip frontmatter\n let startIdx = 0;\n let title: string | undefined;\n if (rawLines[0]?.trim() === '---') {\n const endFm = rawLines.findIndex((l, i) => i > 0 && l.trim() === '---');\n if (endFm !== -1) {\n const fmLines = rawLines.slice(1, endFm);\n for (const fl of fmLines) {\n const tm = fl.match(/^title:\\s*(.+)$/);\n if (tm) title = tm[1]!.trim();\n }\n startIdx = endFm + 1;\n }\n }\n\n const lines = rawLines.slice(startIdx);\n const firstContent = lines.find((l) => l.trim());\n\n if (firstContent?.trim().startsWith('sequenceDiagram')) {\n const m = parseSequence(lines, title);\n return m;\n }\n\n const m = parseFlowchart(lines);\n if (title) {\n // patch title via internal JSON round-trip\n const data = m.toJSON();\n data.title = title;\n return Model.fromData(data);\n }\n return m;\n}\n","import { Model } from '../core/model.js';\nimport type { DiagramModel } from '../core/types.js';\nimport {\n sanitizeLabel,\n MAX_NODES,\n MAX_EDGES,\n MAX_ACTORS,\n MAX_MESSAGES,\n MAX_IMPORT_LENGTH,\n} from '../core/sanitize.js';\n\n/**\n * Deep-strip prototype-pollution keys (`__proto__`, `constructor`,\n * `prototype`) from any parsed JSON value before it enters the model.\n */\nfunction stripDangerousKeys(obj: unknown): unknown {\n if (Array.isArray(obj)) return obj.map(stripDangerousKeys);\n if (obj !== null && typeof obj === 'object') {\n const clean: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n clean[key] = stripDangerousKeys(val);\n }\n return clean;\n }\n return obj;\n}\n\n/**\n * Rehydrate a `Model` from the package's JSON shape. Accepts either the raw\n * JSON string or an already-parsed `DiagramModel` (handy when the caller has\n * received the data from a typed source).\n *\n * Validates the top-level structure and ensures nodes/edges contain only\n * expected shapes. All labels are sanitized to strip dangerous content.\n * Prototype-pollution keys are stripped from parsed JSON.\n * Resource limits are enforced to prevent browser-tab crashes.\n *\n * @throws If `json` is not a valid `DiagramModel` shape.\n */\nexport function fromJSON(json: string | DiagramModel): Model {\n if (typeof json === 'string' && json.length > MAX_IMPORT_LENGTH) {\n throw new Error(`Import aborted: input exceeds the maximum of ${MAX_IMPORT_LENGTH} characters`);\n }\n const raw = typeof json === 'string' ? JSON.parse(json) : json;\n const data = stripDangerousKeys(raw) as DiagramModel;\n\n // Structural validation\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n throw new Error('Invalid DiagramModel JSON: expected an object');\n }\n if (data.type !== 'flowchart' && data.type !== 'sequence') {\n throw new Error(`Invalid DiagramModel JSON: unknown type \"${data.type}\"`);\n }\n if (!Array.isArray(data.nodes) || !Array.isArray(data.edges)) {\n throw new Error('Invalid DiagramModel JSON: nodes and edges must be arrays');\n }\n\n // Resource limits\n if (data.nodes.length > MAX_NODES) {\n throw new Error(\n `Import aborted: diagram has ${data.nodes.length} nodes, maximum is ${MAX_NODES}`,\n );\n }\n if (data.edges.length > MAX_EDGES) {\n throw new Error(\n `Import aborted: diagram has ${data.edges.length} edges, maximum is ${MAX_EDGES}`,\n );\n }\n if (data.actors && data.actors.length > MAX_ACTORS) {\n throw new Error(\n `Import aborted: diagram has ${data.actors.length} actors, maximum is ${MAX_ACTORS}`,\n );\n }\n if (data.messages && data.messages.length > MAX_MESSAGES) {\n throw new Error(\n `Import aborted: diagram has ${data.messages.length} messages, maximum is ${MAX_MESSAGES}`,\n );\n }\n\n // Validate node shape (must have id + label at minimum)\n for (const node of data.nodes) {\n if (\n typeof node !== 'object' ||\n node === null ||\n typeof node.id !== 'string' ||\n typeof node.label !== 'string'\n ) {\n throw new Error('Invalid DiagramModel JSON: each node must have string id and label');\n }\n node.label = sanitizeLabel(node.label);\n }\n\n // Validate edge shape (must have id, from, to)\n for (const edge of data.edges) {\n if (\n typeof edge !== 'object' ||\n edge === null ||\n typeof edge.id !== 'string' ||\n typeof edge.from !== 'string' ||\n typeof edge.to !== 'string'\n ) {\n throw new Error('Invalid DiagramModel JSON: each edge must have string id, from, and to');\n }\n if (edge.label) edge.label = sanitizeLabel(edge.label);\n }\n\n // Sanitize sequence fields\n if (data.actors) {\n data.actors = data.actors.map((a) => (typeof a === 'string' ? sanitizeLabel(a) : a));\n }\n if (data.messages) {\n for (const msg of data.messages) {\n if (typeof msg === 'object' && msg !== null && typeof msg.label === 'string') {\n msg.label = sanitizeLabel(msg.label);\n }\n }\n }\n\n return Model.fromData(data);\n}\n"],"mappings":"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","names":["exportFlowchart","msgArrow","exportSequence","m"]}
package/dist/index.js CHANGED
@@ -163,7 +163,7 @@ function nextId(prefix, existing) {
163
163
  let max = 0;
164
164
  for (const item of existing) {
165
165
  const match = re.exec(item.id);
166
- if (match) {
166
+ if (match?.[1]) {
167
167
  const n = parseInt(match[1], 10);
168
168
  if (n > max) max = n;
169
169
  }
@@ -387,9 +387,15 @@ function escapeXML(s) {
387
387
  }
388
388
  function sanitizeForSVG(s) {
389
389
  let clean = s;
390
- clean = clean.replace(/<\/?[a-zA-Z][^>]*>/g, "");
391
- clean = clean.replace(/\b(?:javascript|data|vbscript)\s*:/gi, "");
392
- clean = clean.replace(/\bon[a-z]+\s*=/gi, "");
390
+ while (/<[a-zA-Z/][^>]{0,500}>/g.test(clean)) {
391
+ clean = clean.replace(/<[a-zA-Z/][^>]{0,500}>/g, "");
392
+ }
393
+ while (/\b(?:javascript|data|vbscript)\s*:/gi.test(clean)) {
394
+ clean = clean.replace(/\b(?:javascript|data|vbscript)\s*:/gi, "");
395
+ }
396
+ while (/\bon[a-z]+\s*=/gi.test(clean)) {
397
+ clean = clean.replace(/\bon[a-z]+\s*=/gi, "");
398
+ }
393
399
  clean = clean.replace(/\x00/g, "");
394
400
  return escapeXML(clean);
395
401
  }
@@ -728,9 +734,15 @@ var MAX_IMPORT_LENGTH = 2 * 1024 * 1024;
728
734
  function sanitizeLabel(raw) {
729
735
  let s = raw;
730
736
  s = s.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
731
- s = s.replace(/<\/?[a-zA-Z][^>]*>/g, "");
732
- s = s.replace(/\b(?:javascript|data|vbscript)\s*:/gi, "");
733
- s = s.replace(/\bon[a-z]+\s*=/gi, "");
737
+ while (/<[a-zA-Z/][^>]{0,500}>/g.test(s)) {
738
+ s = s.replace(/<[a-zA-Z/][^>]{0,500}>/g, "");
739
+ }
740
+ while (/\b(?:javascript|data|vbscript)\s*:/gi.test(s)) {
741
+ s = s.replace(/\b(?:javascript|data|vbscript)\s*:/gi, "");
742
+ }
743
+ while (/\bon[a-z]+\s*=/gi.test(s)) {
744
+ s = s.replace(/\bon[a-z]+\s*=/gi, "");
745
+ }
734
746
  if (s.length > MAX_LABEL_LENGTH) {
735
747
  s = s.slice(0, MAX_LABEL_LENGTH);
736
748
  }
@@ -746,11 +758,11 @@ function sanitizeURL(url) {
746
758
  // src/importers/mermaid.ts
747
759
  function parseNodeDecl(raw) {
748
760
  const patterns = [
749
- [/^(\w+)\{\{?"?(.+?)"?\}?\}$/, "diamond"],
750
- [/^(\w+)\(\("?(.+?)"?\)\)$/, "circle"],
751
- [/^(\w+)\[\/(.+?)\/\]$/, "parallelogram"],
752
- [/^(\w+)\[["']?(.+?)["']?\]$/, "rectangle"],
753
- [/^(\w+)\("?(.+?)"?\)$/, "rectangle"]
761
+ [/^(\w+)\{\{?"?([^}"]+)"?\}?\}$/, "diamond"],
762
+ [/^(\w+)\(\("?([^)"]+)"?\)\)$/, "circle"],
763
+ [/^(\w+)\[\/([^/\]]+)\/\]$/, "parallelogram"],
764
+ [/^(\w+)\[["']?([^\]"']+)["']?\]$/, "rectangle"],
765
+ [/^(\w+)\("?([^)"]+)"?\)$/, "rectangle"]
754
766
  ];
755
767
  for (const [re, shape] of patterns) {
756
768
  const m = raw.match(re);
@@ -758,7 +770,7 @@ function parseNodeDecl(raw) {
758
770
  }
759
771
  return null;
760
772
  }
761
- var EDGE_RE = /^(.+?)\s*(-\.->|-\.-|-->|---)(?:\|(.+?)\|)?\s*(.+)$/;
773
+ var EDGE_RE = /^(\S+)\s*(-\.->|-\.-|-->|---)(?:\|([^|]+)\|)?\s*(.+)$/;
762
774
  function detectStyle(connector) {
763
775
  return connector.startsWith("-.") ? "dashed" : "solid";
764
776
  }
@@ -876,7 +888,7 @@ function parseSequence(lines, title) {
876
888
  safeAddActor(actorMatch[1].trim());
877
889
  continue;
878
890
  }
879
- const msgMatch = trimmed.match(/^(.+?)\s*(-->>|->>|-->|->)\s*(.+?):\s*(.+)$/);
891
+ const msgMatch = trimmed.match(/^(\w+)\s*(-->>|->>|-->|->)\s*(\w+):\s*(.+)$/);
880
892
  if (msgMatch) {
881
893
  const from = safeAddActor(msgMatch[1].trim());
882
894
  const arrow = msgMatch[2];
@@ -901,7 +913,7 @@ function fromMermaid(mermaid) {
901
913
  if (mermaid.length > MAX_IMPORT_LENGTH) {
902
914
  throw new Error(`Import aborted: input exceeds the maximum of ${MAX_IMPORT_LENGTH} characters`);
903
915
  }
904
- const cleaned = mermaid.replace(/mermaid\.initialize\([\s\S]*?\)\s*;?/g, "");
916
+ const cleaned = mermaid.replace(/mermaid\.initialize\([^)]*\)\s*;?/g, "");
905
917
  const rawLines = cleaned.split("\n");
906
918
  let startIdx = 0;
907
919
  let title;