Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | export type GraphNode = { id: string label: string version?: string sprint?: string | null status?: string /** Import graph: canonical language key (typescript, python, …). */ fileType?: string /** Import graph: resolved fill color for canvas. */ color?: string meta?: Record<string, string> } export type GraphEdge = { from: string to: string } export type GraphModel = { nodes: GraphNode[] edges: GraphEdge[] } /** Escape Meridian node ids for Mermaid (US-0162 → US_0162). */ export function mermaidNodeId(id: string): string { return id.replace(/[^A-Za-z0-9_]/g, "_") } export function escapeMermaidLabel(text: string): string { return text.replace(/"/g, "'").replace(/\n/g, " ").slice(0, 80) } export function toMermaidFlowchart(model: GraphModel, direction: "LR" | "TD" = "LR"): string { const lines = [`flowchart ${direction}`] const nodeIds = new Set(model.nodes.map((n) => n.id)) for (const node of model.nodes) { const mid = mermaidNodeId(node.id) const label = escapeMermaidLabel(`${node.id} ${node.label}`.trim()) lines.push(` ${mid}["${label}"]`) } for (const edge of model.edges) { if (!nodeIds.has(edge.from) || !nodeIds.has(edge.to)) { continue } lines.push(` ${mermaidNodeId(edge.from)} --> ${mermaidNodeId(edge.to)}`) } if (model.nodes.length === 0) { lines.push(' empty["No nodes in filter"]') } return lines.join("\n") } |