compasso 0.4.0 → 0.5.0

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.
Files changed (100) hide show
  1. package/README.md +115 -5
  2. package/dist/{chunk-ZBDABVIO.js → chunk-2NDET6O5.js} +3 -3
  3. package/dist/{chunk-ZBDABVIO.js.map → chunk-2NDET6O5.js.map} +1 -1
  4. package/dist/{chunk-Q6DVTCXD.js → chunk-3RGYLVTN.js} +18 -6
  5. package/dist/chunk-3RGYLVTN.js.map +1 -0
  6. package/dist/chunk-BM7UJBK5.js +680 -0
  7. package/dist/chunk-BM7UJBK5.js.map +1 -0
  8. package/dist/chunk-DVLWT565.js +372 -0
  9. package/dist/chunk-DVLWT565.js.map +1 -0
  10. package/dist/{chunk-F47C6ZEB.js → chunk-JBDA7E2O.js} +3 -3
  11. package/dist/{chunk-F47C6ZEB.js.map → chunk-JBDA7E2O.js.map} +1 -1
  12. package/dist/chunk-MIJTBYX2.js +982 -0
  13. package/dist/chunk-MIJTBYX2.js.map +1 -0
  14. package/dist/{chunk-JP4N42AY.js → chunk-PJHLWSGD.js} +3 -3
  15. package/dist/{chunk-JP4N42AY.js.map → chunk-PJHLWSGD.js.map} +1 -1
  16. package/dist/{chunk-LRHHUJFZ.js → chunk-RDH4XHA2.js} +3 -3
  17. package/dist/{chunk-LRHHUJFZ.js.map → chunk-RDH4XHA2.js.map} +1 -1
  18. package/dist/{chunk-UJVU7B44.js → chunk-WEHUSHVI.js} +31 -51
  19. package/dist/chunk-WEHUSHVI.js.map +1 -0
  20. package/dist/{chunk-RWPGGWO5.js → chunk-Z66YUOUM.js} +34 -10
  21. package/dist/chunk-Z66YUOUM.js.map +1 -0
  22. package/dist/core/index.cjs +247 -0
  23. package/dist/core/index.cjs.map +1 -1
  24. package/dist/core/index.d.cts +94 -2
  25. package/dist/core/index.d.ts +94 -2
  26. package/dist/core/index.js +1 -1
  27. package/dist/ecomap/index.cjs +34 -11
  28. package/dist/ecomap/index.cjs.map +1 -1
  29. package/dist/ecomap/index.d.cts +12 -0
  30. package/dist/ecomap/index.d.ts +12 -0
  31. package/dist/ecomap/index.js +2 -2
  32. package/dist/fault-tree/index.d.cts +2 -2
  33. package/dist/fault-tree/index.d.ts +2 -2
  34. package/dist/fault-tree/index.js +2 -2
  35. package/dist/fishbone/index.js +2 -2
  36. package/dist/genogram/index.cjs +57 -7
  37. package/dist/genogram/index.cjs.map +1 -1
  38. package/dist/genogram/index.d.cts +22 -6
  39. package/dist/genogram/index.d.ts +22 -6
  40. package/dist/genogram/index.js +2 -2
  41. package/dist/geometry-P-XGqGe7.d.cts +8 -0
  42. package/dist/geometry-P-XGqGe7.d.ts +8 -0
  43. package/dist/grid-BMgUSly1.d.cts +79 -0
  44. package/dist/grid-BMgUSly1.d.ts +79 -0
  45. package/dist/index.cjs +2360 -395
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.cts +14 -7
  48. package/dist/index.d.ts +14 -7
  49. package/dist/index.js +10 -8
  50. package/dist/{kinship-DqEklrDN.d.ts → kinship-BF90HyyS.d.ts} +1 -1
  51. package/dist/{kinship-Dy_ijjJV.d.cts → kinship-BOUss5cT.d.cts} +1 -1
  52. package/dist/{labels-RtFw9tX1.d.cts → labels-B0aOMbHy.d.cts} +12 -0
  53. package/dist/{labels-RtFw9tX1.d.ts → labels-B0aOMbHy.d.ts} +12 -0
  54. package/dist/labels-Br8yjc3C.d.cts +29 -0
  55. package/dist/labels-Br8yjc3C.d.ts +29 -0
  56. package/dist/{labels-DNqRkWuI.d.ts → labels-CuLbFyrz.d.ts} +1 -1
  57. package/dist/labels-D1v1RWZd.d.cts +97 -0
  58. package/dist/labels-D1v1RWZd.d.ts +97 -0
  59. package/dist/{labels-CBQ_3Ec9.d.cts → labels-DhQe7I8m.d.cts} +1 -1
  60. package/dist/layered-DmZluAqe.d.cts +72 -0
  61. package/dist/layered-DmZluAqe.d.ts +72 -0
  62. package/dist/locales/pt-br.cjs +53 -0
  63. package/dist/locales/pt-br.cjs.map +1 -1
  64. package/dist/locales/pt-br.d.cts +11 -5
  65. package/dist/locales/pt-br.d.ts +11 -5
  66. package/dist/locales/pt-br.js +50 -1
  67. package/dist/locales/pt-br.js.map +1 -1
  68. package/dist/org-chart/index.cjs +138 -94
  69. package/dist/org-chart/index.cjs.map +1 -1
  70. package/dist/org-chart/index.d.cts +24 -33
  71. package/dist/org-chart/index.d.ts +24 -33
  72. package/dist/org-chart/index.js +2 -2
  73. package/dist/pedigree/index.d.cts +6 -6
  74. package/dist/pedigree/index.d.ts +6 -6
  75. package/dist/pedigree/index.js +2 -2
  76. package/dist/phylo/index.d.cts +2 -2
  77. package/dist/phylo/index.d.ts +2 -2
  78. package/dist/phylo/index.js +2 -2
  79. package/dist/prisma/index.cjs +882 -0
  80. package/dist/prisma/index.cjs.map +1 -0
  81. package/dist/prisma/index.d.cts +174 -0
  82. package/dist/prisma/index.d.ts +174 -0
  83. package/dist/prisma/index.js +4 -0
  84. package/dist/prisma/index.js.map +1 -0
  85. package/dist/{text-DuO_PwYw.d.cts → text-DDVzpwPZ.d.cts} +1 -8
  86. package/dist/{text-DuO_PwYw.d.ts → text-DDVzpwPZ.d.ts} +1 -8
  87. package/dist/{types-BnMG7TCd.d.cts → types-jE2fdM1t.d.cts} +8 -0
  88. package/dist/{types-BnMG7TCd.d.ts → types-jE2fdM1t.d.ts} +8 -0
  89. package/dist/uml/index.cjs +1214 -0
  90. package/dist/uml/index.cjs.map +1 -0
  91. package/dist/uml/index.d.cts +189 -0
  92. package/dist/uml/index.d.ts +189 -0
  93. package/dist/uml/index.js +4 -0
  94. package/dist/uml/index.js.map +1 -0
  95. package/package.json +28 -2
  96. package/dist/chunk-O3BT2O42.js +0 -145
  97. package/dist/chunk-O3BT2O42.js.map +0 -1
  98. package/dist/chunk-Q6DVTCXD.js.map +0 -1
  99. package/dist/chunk-RWPGGWO5.js.map +0 -1
  100. package/dist/chunk-UJVU7B44.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/phylo/labels.ts","../src/phylo/validate.ts","../src/phylo/layout.ts","../src/phylo/svg.ts","../src/phylo/render.ts"],"names":["round"],"mappings":"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","file":"chunk-JP4N42AY.js","sourcesContent":["// Display vocabularies — every human-readable string the phylo tree emits, gathered in\n// overridable packs so the diagram localizes without touching the engine. English\n// defaults here; `compasso/locales/pt-br` ships a Brazilian Portuguese pack.\n//\n// Title labels are woven into element/node <title>s by the LAYOUT (verbatim-preserving:\n// a branch's actual length / a clade's actual support always rides the title, even when\n// the drawn diagram omits them). Svg labels are drawn by the EMITTER (legend, aria).\n\nimport type { PhyloMode } from \"./types\";\n\n/** Labels woven into <title>s by the LAYOUT (verbatim-preserving). */\nexport interface PhyloTitleLabels {\n /** \"branch length\" → \"branch length: 0.123\" when a length is present. */\n branchLength: string;\n /** \"support\" → \"support: 95\" when a support value is present. */\n support: string;\n clade: string;\n tip: string;\n root: string;\n}\n\nexport const PHYLO_TITLE_LABELS_EN: PhyloTitleLabels = {\n branchLength: \"branch length\",\n support: \"support\",\n clade: \"clade\",\n tip: \"tip\",\n root: \"root\",\n};\n\n/** Labels drawn by the SVG EMITTER (legend entries, accessibility text). */\nexport interface PhyloSvgLabels {\n support: string;\n scaleBar: string;\n alignedTip: string;\n /** Aria label switches on the layout's render mode. */\n ariaLabel: Record<PhyloMode, string>;\n}\n\nexport const PHYLO_SVG_LABELS_EN: PhyloSvgLabels = {\n support: \"Support value (bootstrap/posterior)\",\n scaleBar: \"Scale: substitutions per site\",\n alignedTip: \"Aligned tip (true position dotted)\",\n ariaLabel: {\n cladogram: \"Phylogenetic tree (cladogram)\",\n phylogram: \"Phylogenetic tree (phylogram)\",\n },\n};\n","// Phylo validation — the MIDDLE doctrine. A phylogenetic tree is not a safety artifact\n// like a fault tree (an incomplete/exploratory tree is a legitimate thing to draw), but\n// unlike a genogram a tree MUST be a tree to lay out (a cycle or a forest has no\n// root-anchored x). So we throw PhyloValidationError carrying a MINIMAL closed code set\n// that rejects only what makes layout impossible or ambiguous — never what is merely\n// incomplete. The shape (sorted kebab-case { code, message } issues, three-phase gating)\n// is the fault-tree's, verbatim.\n//\n// Every problem is reported, not just the first: issues are aggregated, deduplicated and\n// sorted deterministically (by code, then message — byte comparison, no locale collation),\n// each carrying a STABLE kebab-case `code`. Validation runs in THREE phases, each gated on\n// the prior being clean ENOUGH for the next to be meaningful (NOT on \"zero issues so far\",\n// so a defect in one phase never hides an honest issue from a later one):\n// (0) duplicate ids (per namespace). The lookup maps below are first-occurrence-wins, so\n// every reference rule would otherwise depend on array order — violating this\n// function's documented order-invariance. Any duplicate-id issue → report ONLY those\n// and stop (the duplicate already forces a throw, present in every permutation).\n// (1) reference + structural-tree rules: unknown-endpoint (an edge to a phantom node),\n// unknown-root, multiple-parents (a node with ≥2 incoming edges — a DAG, not a tree),\n// negative-length (a meaningless distance — reject, never clamp), tip-with-children\n// (a declared isTip flag contradicting topology). All evaluated once ids are\n// unambiguous; none requires a clean graph walk.\n// (2) graph rules: cycle (a back-edge in the parent→child walk) and disconnected-node\n// (a node unreachable from root). Gated ONLY on the reference-INTEGRITY subset that\n// corrupts the traversal itself — duplicate-id (ambiguous first-wins node),\n// unknown-endpoint (walks a phantom node), unknown-root (the BFS frontier roots at a\n// non-node), multiple-parents (the child-set is ambiguous). negative-length and\n// tip-with-children leave the graph fully walkable, so they do NOT suppress the graph\n// phase: a negative length alongside an unreachable node reports BOTH in one throw.\n//\n// Tolerated, by design (drawn as declared, never converted):\n// - empty labels (drawn empty; the <title> is still present);\n// - missing support (null/absent — drawn unlabeled);\n// - a single-node tree (root only, no edges — a valid degenerate tree, one tip);\n// - null lengths (phylogram → 0) and zero-length branches (a node directly above its\n// parent's x — a real polytomy/zero-support resolution, NOT an error);\n// - unbalanced / ladderized topology (declared child order honored, never auto-sorted).\n\nimport type { PhyloInput, PhyloNode } from \"./types\";\n\n/** Stable machine-readable issue codes (kebab-case; part of the public contract). */\nexport type PhyloIssueCode =\n | \"duplicate-id\"\n | \"unknown-endpoint\"\n | \"unknown-root\"\n | \"multiple-parents\"\n | \"cycle\"\n | \"disconnected-node\"\n | \"tip-with-children\"\n | \"negative-length\";\n\nexport interface PhyloIssue {\n code: PhyloIssueCode;\n message: string;\n}\n\n/** Thrown by computePhyloLayout / phyloSvg on a structurally un-layout-able tree. */\nexport class PhyloValidationError extends Error {\n readonly issues: readonly PhyloIssue[];\n\n constructor(issues: readonly PhyloIssue[]) {\n super(`invalid phylo tree: ${issues.map((i) => i.message).join(\"; \")}`);\n this.name = \"PhyloValidationError\";\n this.issues = issues;\n }\n}\n\n/**\n * Deduplicate + deterministic order: by code, then message (byte comparison — stable\n * across engines; no locale-dependent collation). Shared by every phase that returns.\n */\nfunction sortIssues(issues: readonly PhyloIssue[]): readonly PhyloIssue[] {\n const unique = new Map<string, PhyloIssue>();\n for (const issue of issues) unique.set(`${issue.code} ${issue.message}`, issue);\n return [...unique.values()].sort((a, b) =>\n a.code !== b.code ? (a.code < b.code ? -1 : 1) : a.message < b.message ? -1 : a.message > b.message ? 1 : 0,\n );\n}\n\n/**\n * Computes ALL validation issues for the input, deduplicated and deterministically\n * sorted (code, then message) — array order of `nodes`/`edges` never changes the result.\n * Empty input (no nodes AND no edges) is valid by definition (the renderer's\n * empty-but-valid SVG case) and reports no issues.\n */\nexport function phyloIssues(input: PhyloInput): readonly PhyloIssue[] {\n if (input.nodes.length === 0 && input.edges.length === 0) return [];\n\n const issues: PhyloIssue[] = [];\n const push = (code: PhyloIssueCode, message: string): void => {\n issues.push({ code, message });\n };\n\n // ── R1: duplicate ids (per namespace — hooks must be unique). Any duplicate makes the\n // structure ambiguous, so this is phase 0 and short-circuits the rest (below). ─────\n const nodeById = new Map<number, PhyloNode>();\n const dupNodeIds = new Set<number>();\n for (const n of input.nodes) {\n if (nodeById.has(n.id)) dupNodeIds.add(n.id);\n else nodeById.set(n.id, n);\n }\n for (const id of [...dupNodeIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate node id ${id}`);\n }\n const dupEdgeIds = new Set<number>();\n const seenEdgeIds = new Set<number>();\n for (const e of input.edges) {\n if (seenEdgeIds.has(e.id)) dupEdgeIds.add(e.id);\n else seenEdgeIds.add(e.id);\n }\n for (const id of [...dupEdgeIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate edge id ${id}`);\n }\n\n // ── Phase 0: duplicate ids short-circuit everything else (see module header). ────────\n if (issues.length > 0) {\n return sortIssues(issues);\n }\n\n // ── R2: the declared root must be an existing node. ──────────────────────────────────\n if (!nodeById.has(input.rootId)) {\n push(\"unknown-root\", `rootId ${input.rootId} is not a declared node`);\n }\n\n // ── Per-edge reference / structural rules. The child→parent map drives the graph\n // phase: built only from edges with BOTH endpoints declared (a phantom endpoint\n // would seed a non-existent node). ────────────────────────────────────────────────\n const incomingByChild = new Map<number, number[]>(); // child id → parent ids (declared edges only)\n for (const e of [...input.edges].sort((a, b) => a.id - b.id)) {\n const knownParent = nodeById.has(e.parentId);\n const knownChild = nodeById.has(e.childId);\n if (!knownParent) push(\"unknown-endpoint\", `edge ${e.id} parentId ${e.parentId} is not a declared node`);\n if (!knownChild) push(\"unknown-endpoint\", `edge ${e.id} childId ${e.childId} is not a declared node`);\n // R4 — a non-finite or negative distance is meaningless. Reject (never clamp): drawing\n // it would silently reinterpret the data AND a non-finite length poisons the phylogram\n // scale (cumulative dist → Infinity, scale → 0, x → padLeft + Infinity·0 = NaN, and the\n // whole SVG emits viewBox=\"0 0 NaN …\"). `Number.isFinite` is false for NaN/+Inf/-Inf,\n // so the one guard covers every corrupt SPECIFIED value; null stays valid (→ 0 in the\n // phylogram, the legitimate \"unspecified\" branch).\n if (e.length !== null && (!Number.isFinite(e.length) || e.length < 0)) {\n push(\"negative-length\", `edge ${e.id} has non-finite or negative length ${e.length}`);\n }\n if (knownParent && knownChild) {\n const arr = incomingByChild.get(e.childId) ?? [];\n arr.push(e.parentId);\n incomingByChild.set(e.childId, arr);\n }\n }\n\n // R3 — a tree node has at most ONE parent; ≥2 incoming edges is a DAG (un-layout-able\n // with a single root-anchored x). Reported per child, ascending.\n const childIdsWithEdges = new Set<number>();\n for (const e of input.edges) childIdsWithEdges.add(e.childId);\n for (const [childId, parents] of [...incomingByChild.entries()].sort((a, b) => a[0] - b[0])) {\n if (parents.length > 1) {\n push(\"multiple-parents\", `node ${childId} has ${parents.length} parents`);\n }\n }\n\n // R5 — isTip is DERIVED: a node with an outgoing edge is internal, a node with none is a\n // tip. A declared isTip flag that contradicts the topology is reported (honesty rule —\n // we draw the declared topology, we never invent or suppress a leaf because of a flag).\n const hasChildren = new Set<number>();\n for (const e of input.edges) {\n if (nodeById.has(e.parentId)) hasChildren.add(e.parentId);\n }\n for (const n of [...nodeById.values()].sort((a, b) => a.id - b.id)) {\n if (n.isTip === true && hasChildren.has(n.id)) {\n push(\"tip-with-children\", `node ${n.id} is declared a tip but has children`);\n } else if (n.isTip === false && !hasChildren.has(n.id)) {\n push(\"tip-with-children\", `node ${n.id} is declared internal but has no children`);\n }\n }\n\n // ── Graph rules (cycle, disconnected-node) — phase 2. Gated ONLY on the reference-\n // INTEGRITY codes that corrupt the traversal (see the module header), NOT on every\n // phase-1 issue: a negative length or a contradicted tip flag leaves the graph fully\n // walkable, so suppressing the graph phase for them would hide an honest issue. ─────\n const GRAPH_BLOCKING: ReadonlySet<PhyloIssueCode> = new Set<PhyloIssueCode>([\n \"duplicate-id\",\n \"unknown-endpoint\",\n \"unknown-root\",\n \"multiple-parents\",\n ]);\n if (!issues.some((i) => GRAPH_BLOCKING.has(i.code))) {\n // Children of a node in declared edge order (stable-sorted by edge id), declared edges\n // only — every endpoint is known here (no unknown-endpoint survived the gate).\n const childrenOf = new Map<number, number[]>();\n for (const e of [...input.edges].sort((a, b) => a.id - b.id)) {\n const arr = childrenOf.get(e.parentId) ?? [];\n arr.push(e.childId);\n childrenOf.set(e.parentId, arr);\n }\n\n // R6 — cycle detection over the parent→child graph (coloring DFS, start nodes\n // ascending, children in declared order). Each distinct cycle is reported once,\n // rotated to start at its smallest node id so the message is array-order-independent.\n const color = new Map<number, 0 | 1 | 2>(); // 0/absent=white, 1=gray, 2=black\n const seenCycles = new Set<string>();\n const dfs = (start: number): void => {\n const stack: { id: number; nextChild: number }[] = [{ id: start, nextChild: 0 }];\n color.set(start, 1);\n while (stack.length > 0) {\n const frame = stack[stack.length - 1]!;\n const children = childrenOf.get(frame.id) ?? [];\n if (frame.nextChild >= children.length) {\n color.set(frame.id, 2);\n stack.pop();\n continue;\n }\n const child = children[frame.nextChild]!;\n frame.nextChild += 1;\n const c = color.get(child) ?? 0;\n if (c === 1) {\n const from = stack.findIndex((f) => f.id === child);\n const cycle = stack.slice(from).map((f) => f.id);\n const minIdx = cycle.indexOf(Math.min(...cycle));\n const rotated = [...cycle.slice(minIdx), ...cycle.slice(0, minIdx)];\n const key = rotated.join(\">\");\n if (!seenCycles.has(key)) {\n seenCycles.add(key);\n push(\"cycle\", `cycle: ${[...rotated, rotated[0]!].join(\" → \")}`);\n }\n } else if (c === 0) {\n color.set(child, 1);\n stack.push({ id: child, nextChild: 0 });\n }\n }\n };\n for (const n of [...nodeById.values()].sort((a, b) => a.id - b.id)) {\n if ((color.get(n.id) ?? 0) === 0) dfs(n.id);\n }\n\n // R7 — every declared node must be reachable from the root (a forest has no single\n // root-anchored x). Silently dropping a declared component violates honesty.\n const reachable = new Set<number>();\n const queue: number[] = [input.rootId];\n while (queue.length > 0) {\n const id = queue.shift()!;\n if (reachable.has(id)) continue;\n reachable.add(id);\n for (const childId of childrenOf.get(id) ?? []) queue.push(childId);\n }\n for (const n of [...nodeById.values()].sort((a, b) => a.id - b.id)) {\n if (!reachable.has(n.id)) push(\"disconnected-node\", `node ${n.id} is unreachable from the root`);\n }\n }\n\n return sortIssues(issues);\n}\n\n/** Throws PhyloValidationError (carrying ALL issues) when the input is un-layout-able. */\nexport function validatePhylo(input: PhyloInput): void {\n const issues = phyloIssues(input);\n if (issues.length > 0) throw new PhyloValidationError(issues);\n}\n","// PURE phylo layout — the single source of truth for positioning and connector routing.\n// The emitter (./svg.ts) draws EXACTLY what this computes, so web / PDF / image pipelines\n// can never drift. Deliberately PURE — no DOM, no Node APIs, no clock, no randomness —\n// so the same input always yields the same layout, byte for byte.\n//\n// HONESTY RULE: this module only POSITIONS the declared topology. Validation\n// (./validate.ts) THROWS on an un-layout-able tree (cycle, forest, DAG) rather than\n// repairing it. A branch length absent from the cladogram x is NEVER lost: it always\n// rides the branch element's <title>. A tip is DERIVED (no outgoing edge); we never\n// invent or suppress a leaf.\n//\n// LAYOUT — the classic tidy-tree (the textbook phylogeny algorithm):\n// * Tip ordering: one DFS from rootId, children in DECLARED edge order (stable-sorted\n// by edge id for determinism — the cladistics \"declared order is the analyst's\n// ladderization choice, never auto-sorted\"). Tips numbered 0..L-1 in DFS-visit order.\n// * Leaf y: tip i → y = top + i·ROW_SLOT + ROW_SLOT/2. Equal disjoint slots ⇒ no\n// vertical overlap by construction (the genogram's column bands, transposed 90°).\n// * Internal y = midpoint of its children's y ((min+max)/2), computed post-order.\n// Horizontal:\n// * cladogram: x = padLeft + depth·LEVEL_W; tips right-aligned to maxDepth's x; a dotted\n// EXTENSION segment fills from a tip's true depth-x to the alignment line (FigTree).\n// * phylogram: x = padLeft + cumulativeLength(root→node)·SCALE, SCALE = drawW/maxRootTip\n// (fit-to-width). null/0 lengths contribute 0 ⇒ a node sits directly above its parent\n// (a zero-length branch — valid, NOT an error). Tips not right-aligned unless alignTips.\n// Edges = rectangular elbows (orthogonal, harness-clean): one shared VERTICAL \"clade bar\"\n// per parent spanning min→max child y at the parent's x, plus one HORIZONTAL \"branch\" per\n// child from parentX to childX at childY. Overlap proof: tips own disjoint y-bands; an\n// internal node's y is strictly between its children's bands ⇒ clade bars nest without\n// overlap; branches live at distinct child-y's. Same inductive structure as the fault\n// tree, transposed.\n\nimport { clampLabel, estimateTextWidth, type Point } from \"../core\";\nimport { PHYLO_TITLE_LABELS_EN, type PhyloTitleLabels } from \"./labels\";\nimport { validatePhylo } from \"./validate\";\nimport type { PhyloInput, PhyloMode, PhyloNode } from \"./types\";\n\nexport { PhyloValidationError, phyloIssues, validatePhylo, type PhyloIssue, type PhyloIssueCode } from \"./validate\";\n// Re-exported so the overlap harness (and decorating callers) measure with the EXACT\n// metrics the layout reserved space with — the shared-metrics contract.\nexport { estimateTextWidth };\nexport type { Point };\n\n// ── Type metrics (shared by layout AND the emitter, so geometry == render) ───────────\n/** Tip-label font size (px). */\nexport const PHYLO_LABEL_FONT = 12;\n/** Vertical slot per tip (px) — equal slots guarantee vertical disjointness. */\nexport const PHYLO_ROW_SLOT = 22;\n/** Support-value font size (px) — drawn just left of an internal node. */\nexport const PHYLO_SUPPORT_FONT = 10;\n/** Gap from a tip point to the start of its label text. */\nexport const PHYLO_LABEL_GAP = 8;\n\n// ── Geometry constants ───────────────────────────────────────────────────────────────\nconst PADDING = 32;\n/** Horizontal level width per topological depth (cladogram x; phylogram fallback). */\nconst PHYLO_LEVEL_W = 72;\n/** Tip dot radius (a small filled marker at each node point). */\nconst PHYLO_TIP_R = 2.5;\n/** Reserved gap to the left of an internal node for its support text (when showSupport). */\nconst SUPPORT_GAP = 4;\n/** Vertical gap reserved below the tree for the scale bar assembly. */\nconst SCALEBAR_ZONE = 34;\n/** Drawn length cap (in px) of the available width for the tree body. */\nconst MIN_DRAW_W = PHYLO_LEVEL_W; // a degenerate single-depth tree still gets one level\n/** Phylogram-only x nudge (px) for an INTERNAL child whose zero/null branch lands it at\n * exactly its parent's x. Without it, the child's clade bar and the parent's clade bar are\n * two collinear verticals (double-drawn line, ambiguous polytomy). One pixel right gives\n * the child's bar its own vertical while preserving the \"directly above the parent\" read; a\n * TIP at the parent's x needs no nudge (a tip has no clade bar). PRESENTATION-only — the\n * verbatim 0/null length still rides the branch element's <title>. */\nconst PHYLO_ZERO_NUDGE = 1;\n\n// ── Namespaced element-id blocks (one element kind per numeric block; every\n// data-edge-id stays traceable to its source node) ─────────────────────────────────\nexport const PHYLO_CLADEBAR_ID_BASE = 1_000_000; // + parent node id (the vertical bar)\nexport const PHYLO_BRANCH_ID_BASE = 2_000_000; // + child node id (the horizontal branch)\nexport const PHYLO_EXTENSION_ID_BASE = 3_000_000; // + tip node id (dotted right-align extension)\nexport const PHYLO_ROOTSTUB_ID_BASE = 4_000_000; // + root id (the short left stub into the root)\nexport const PHYLO_SCALEBAR_ID = 5_000_000; // the labelled scale-bar segment\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\n// ── Positioned layout ─────────────────────────────────────────────────────────────────\n\nexport interface PhyloLayoutNode {\n nodeId: number;\n isTip: boolean;\n /** Node point center. */\n cx: number;\n cy: number;\n /** Bootstrap/posterior; null when absent (always in the <title> regardless). */\n support: number | null;\n /** Tip label as a single clamped line, drawn right of the tip point; [] for internals. */\n labelLines: string[];\n /** x where the tip label text starts (after PHYLO_LABEL_GAP); the tip's drawn-x for an\n * aligned tip is the alignment line, so the label always clears the tip point. */\n labelLeft: number;\n /** Edges from the root (a tip in cladogram mode keeps its TRUE depth here). */\n depth: number;\n /** Verbatim <title> text (node.title ?? label + branch-length/support). */\n title: string;\n}\n\nexport type PhyloElementKind = \"clade-bar\" | \"branch\" | \"extension\" | \"root-stub\" | \"scale-bar\";\n\nexport interface PhyloElement {\n /** Namespaced id (PHYLO_*_ID_BASE + parent/child/tip/root id, or PHYLO_SCALEBAR_ID). */\n edgeId: number;\n kind: PhyloElementKind;\n /** Consecutive pairs axis-aligned (clade-bar = V, branch/extension/scale-bar = H). */\n points: Point[];\n /** Drawn dotted (extension + scale-bar ticks are NOT here — only the extension leader). */\n dotted: boolean;\n /** Branch: the verbatim length for the <title>; null otherwise / unspecified. */\n length: number | null;\n title: string;\n}\n\nexport interface PhyloScaleBar {\n /** Branch-length value the bar represents (a nice round step). */\n length: number;\n /** Bar's left x and baseline y. */\n x: number;\n y: number;\n /** Drawn pixel length of the bar (length·SCALE). */\n pxLength: number;\n /** Displayed numeric label (the value, trimmed of trailing zeros). */\n valueLabel: string;\n}\n\nexport interface PhyloLayout {\n width: number;\n height: number;\n mode: PhyloMode;\n /** DFS pre-order (root first, then children in declared edge order). */\n nodes: PhyloLayoutNode[];\n elements: PhyloElement[];\n /** Present only in phylogram mode with scaleBar !== false and a non-degenerate scale. */\n scaleBar: PhyloScaleBar | null;\n /** True when the layout reserved left-margin space for support text AND any internal\n * node carries a support value — the emitter draws support text iff this is set. */\n showSupport: boolean;\n}\n\nexport interface PhyloLayoutOptions {\n /** \"cladogram\" (default) | \"phylogram\". */\n mode?: PhyloMode;\n /** Dotted tip-alignment extensions. cladogram default true; phylogram default false. */\n alignTips?: boolean;\n /** Reserve left margin + draw support text at internal nodes. Default false. */\n showSupport?: boolean;\n /** Draw the phylogram scale bar (ignored in cladogram). Default true. */\n scaleBar?: boolean;\n /** Cap each tip's DISPLAY label (compact preview); verbatim text stays in `title`. */\n maxLabelChars?: number;\n /** Locale pack for node/branch <title>s — English default. */\n titleLabels?: PhyloTitleLabels;\n}\n\n// ── niceScaleStep — the largest power-of-ten × {1, 2, 5} that is ≤ maxLen/4. A pure\n// function so the scale bar is a stable, \"nice\" round number regardless of the data's\n// exact range (the standard FigTree/ggtree scale-bar value). maxLen ≤ 0 → 0. ─────────\nexport function niceScaleStep(maxLen: number): number {\n if (!(maxLen > 0)) return 0;\n const target = maxLen / 4;\n const exp = Math.floor(Math.log10(target));\n const pow = Math.pow(10, exp);\n // A small relative tolerance so a value imperceptibly below a boundary (e.g. 0.2/4 =\n // 0.04999999999999999 from float rounding) still selects the intended \"nice\" step —\n // the scale value is presentation-only and snapping to the boundary is the honest read.\n const tol = target * 1e-9;\n for (const mult of [5, 2, 1]) {\n const step = mult * pow;\n if (step <= target + tol) return step;\n }\n // target < pow (only when log10 rounding leaves a gap) → the next decade down's 5×.\n return 5 * Math.pow(10, exp - 1);\n}\n\n/** Trims a numeric scale value to a short label (\"0.50\" → \"0.5\", \"1.0\" → \"1\"). */\nfunction trimNumber(n: number): string {\n if (Number.isInteger(n)) return String(n);\n return String(Number(n.toPrecision(6))).replace(/0+$/, \"\").replace(/\\.$/, \"\");\n}\n\n// ── Internal working node ──────────────────────────────────────────────────────────────\n\ninterface Work {\n node: PhyloNode;\n children: Work[];\n depth: number;\n /** Cumulative root→node branch length (phylogram); 0 for null/zero lengths. */\n dist: number;\n /** Length of the edge INTO this node (the root's is null). */\n inLength: number | null;\n cx: number;\n cy: number;\n}\n\nfunction nodeTitle(\n node: PhyloNode,\n isTip: boolean,\n isRoot: boolean,\n inLength: number | null,\n labels: PhyloTitleLabels,\n): string {\n if (node.title !== undefined) return node.title;\n const role = isRoot ? labels.root : isTip ? labels.tip : labels.clade;\n const head = node.label === \"\" ? role : node.label;\n const parts: string[] = [head];\n if (inLength !== null) parts.push(`${labels.branchLength}: ${trimNumber(inLength)}`);\n if (!isTip && node.support !== undefined && node.support !== null) {\n parts.push(`${labels.support}: ${trimNumber(node.support)}`);\n }\n return parts.join(\" · \");\n}\n\n/**\n * Deterministic, overlap-proof phylo layout (pure function of the inputs). Validates\n * first and THROWS PhyloValidationError on an un-layout-able tree — never sanitizes.\n * Empty input (no nodes, no edges) yields an empty, padded layout; `rootId` is ignored\n * in that one case.\n */\nexport function computePhyloLayout(input: PhyloInput, opts: PhyloLayoutOptions = {}): PhyloLayout {\n const mode: PhyloMode = opts.mode ?? \"cladogram\";\n if (input.nodes.length === 0 && input.edges.length === 0) {\n return { width: PADDING * 2, height: PADDING * 2, mode, nodes: [], elements: [], scaleBar: null, showSupport: false };\n }\n validatePhylo(input);\n\n const titleLabels = opts.titleLabels ?? PHYLO_TITLE_LABELS_EN;\n const alignTips = opts.alignTips ?? (mode === \"cladogram\");\n const showSupport = opts.showSupport ?? false;\n const wantScaleBar = (opts.scaleBar ?? true) && mode === \"phylogram\";\n\n const nodeById = new Map(input.nodes.map((n) => [n.id, n]));\n // Children of a node in declared edge order (stable by edge id) — the validated tree\n // guarantees every endpoint exists and each node has ≤1 parent.\n const childrenOf = new Map<number, number[]>();\n const inLengthByChild = new Map<number, number | null>();\n for (const e of [...input.edges].sort((a, b) => a.id - b.id)) {\n (childrenOf.get(e.parentId) ?? childrenOf.set(e.parentId, []).get(e.parentId)!).push(e.childId);\n inLengthByChild.set(e.childId, e.length);\n }\n\n // ── Build the working tree by DFS from the root (children in declared order). ─────────\n const allWork: Work[] = [];\n const build = (nodeId: number, depth: number, dist: number): Work => {\n const node = nodeById.get(nodeId)!;\n const inLength = inLengthByChild.get(nodeId) ?? null;\n const work: Work = { node, children: [], depth, dist, inLength, cx: 0, cy: 0 };\n allWork.push(work);\n for (const childId of childrenOf.get(nodeId) ?? []) {\n const childLen = inLengthByChild.get(childId);\n const add = childLen === null || childLen === undefined ? 0 : Math.max(0, childLen);\n work.children.push(build(childId, depth + 1, dist + add));\n }\n return work;\n };\n const root = build(input.rootId, 0, 0);\n\n const isTip = (w: Work): boolean => w.children.length === 0;\n\n // ── Vertical: equal leaf slots in DFS order; internal y = midpoint of children. ───────\n const top = PADDING;\n let tipIndex = 0;\n const assignY = (w: Work): void => {\n if (isTip(w)) {\n w.cy = top + tipIndex * PHYLO_ROW_SLOT + PHYLO_ROW_SLOT / 2;\n tipIndex += 1;\n return;\n }\n for (const c of w.children) assignY(c);\n const ys = w.children.map((c) => c.cy);\n w.cy = (Math.min(...ys) + Math.max(...ys)) / 2;\n };\n assignY(root);\n const tipCount = tipIndex;\n\n // ── Horizontal: depth-x (cladogram) or cumulative-length-x (phylogram, fit-to-width). ─\n const maxDepth = allWork.reduce((m, w) => Math.max(m, w.depth), 0);\n const maxDist = allWork.reduce((m, w) => Math.max(m, w.dist), 0);\n\n // Left margin: PADDING + reserved support-text width (only when showSupport AND any\n // internal node actually carries a support value — measured space, the house rule).\n const supportNodes = allWork.filter(\n (w) => !isTip(w) && w.node.support !== undefined && w.node.support !== null,\n );\n // Effective flag: support text is drawn ONLY when requested AND at least one internal\n // node actually carries a value (the layout reserves the margin for exactly that text).\n const effectiveShowSupport = showSupport && supportNodes.length > 0;\n const supportMargin = effectiveShowSupport\n ? supportNodes.reduce(\n (m, w) => Math.max(m, estimateTextWidth(trimNumber(w.node.support as number), PHYLO_SUPPORT_FONT)),\n 0,\n ) + SUPPORT_GAP\n : 0;\n const padLeft = PADDING + supportMargin;\n\n // Tip-label widths reserve real space on the right so the canvas always contains them.\n const tipLabelW = allWork\n .filter(isTip)\n .reduce((m, w) => Math.max(m, estimateTextWidth(clampLabel(w.node.label, opts.maxLabelChars), PHYLO_LABEL_FONT)), 0);\n const labelReserve = (tipCount > 0 ? PHYLO_LABEL_GAP + tipLabelW : 0) + PADDING;\n\n // Phylogram scale: fit the deepest root-to-tip distance to the available draw width\n // (the genogram's fit-to-container ethos). The width tracks topological depth so a deep\n // tree gets room; MIN_DRAW_W keeps a shallow tree (e.g. a single split) drawable.\n const phylogramScaled = mode === \"phylogram\" && maxDist > 0;\n const drawW = Math.max(MIN_DRAW_W, maxDepth * PHYLO_LEVEL_W);\n const scale = phylogramScaled ? drawW / maxDist : 0;\n\n const xOf = (w: Work): number => {\n if (phylogramScaled) return padLeft + w.dist * scale;\n return padLeft + w.depth * PHYLO_LEVEL_W; // cladogram (or degenerate phylogram)\n };\n for (const w of allWork) w.cx = xOf(w);\n\n // Phylogram-only de-collinearity nudge. A zero/null-length branch lands an INTERNAL child\n // at exactly its parent's x, so the child's clade bar and the parent's clade bar become\n // two collinear verticals (a double-drawn line that reads as an ambiguous polytomy). We\n // push such a child PHYLO_ZERO_NUDGE px right of the parent's FINAL x so its bar lives on\n // its own vertical — preserving the \"directly above the parent\" read (one pixel). A TIP at\n // the parent's x is fine (no clade bar), so it is never nudged. Pre-order so a chain of\n // zero-length internals each clears its own (already-nudged) parent — the monotone\n // cx(child) ≥ cx(parent) invariant is preserved, strictly. Purely positional: the verbatim\n // 0/null length is untouched (it still rides the branch element's <title>).\n if (phylogramScaled) {\n const nudge = (w: Work): void => {\n for (const c of w.children) {\n if (!isTip(c) && c.cx <= w.cx + 1e-6) c.cx = w.cx + PHYLO_ZERO_NUDGE;\n nudge(c);\n }\n };\n nudge(root);\n }\n\n // The alignment line for right-aligned tips. `alignTips` defaults true in cladogram\n // (the defining right-aligned look) and false in phylogram (the x IS the data); setting\n // it false in cladogram drops both the alignment AND the dotted extensions. Internals\n // keep their computed x; only TIPS are pushed to the line. In cladogram the line is the\n // deepest depth-x; in phylogram (alignTips:true) it is the rightmost tip's own x.\n const tipsAligned = alignTips;\n const maxTipX = allWork.filter(isTip).reduce((m, w) => Math.max(m, w.cx), padLeft);\n const alignX = phylogramScaled ? maxTipX : padLeft + maxDepth * PHYLO_LEVEL_W;\n const tipDrawX = (w: Work): number => (tipsAligned ? alignX : w.cx);\n\n // ── Canvas size. ──────────────────────────────────────────────────────────────────────\n const rightmost = tipsAligned ? alignX : allWork.reduce((m, w) => Math.max(m, w.cx), padLeft);\n const treeBottom = top + (tipCount > 0 ? tipCount * PHYLO_ROW_SLOT : PHYLO_ROW_SLOT);\n const scaleBarPx = wantScaleBar && maxDist > 0 ? niceScaleStep(maxDist) * scale : 0;\n const hasScaleBar = wantScaleBar && maxDist > 0 && scaleBarPx > 0;\n const width = Math.ceil(rightmost + labelReserve);\n const height = Math.ceil(treeBottom + (hasScaleBar ? SCALEBAR_ZONE : 0) + PADDING / 2);\n\n // ── Emit nodes (DFS pre-order) + elements. ────────────────────────────────────────────\n const nodes: PhyloLayoutNode[] = [];\n const elements: PhyloElement[] = [];\n\n const branchTitle = (w: Work): string => {\n if (w.inLength !== null) return `${titleLabels.branchLength}: ${trimNumber(w.inLength)}`;\n return titleLabels.branchLength;\n };\n\n // Root stub: a short horizontal lead-in to the root point (left of it), so a root with\n // a single child still reads as a tree origin. Drawn from padLeft − stub to the root x.\n const ROOT_STUB = 14;\n const rootDrawX = isTip(root) ? tipDrawX(root) : root.cx;\n elements.push({\n edgeId: PHYLO_ROOTSTUB_ID_BASE + root.node.id,\n kind: \"root-stub\",\n points: [\n { x: round(Math.max(PADDING / 2, rootDrawX - ROOT_STUB)), y: round(root.cy) },\n { x: round(rootDrawX), y: round(root.cy) },\n ],\n dotted: false,\n length: null,\n title: titleLabels.root,\n });\n\n const emit = (w: Work): void => {\n const tip = isTip(w);\n const isRoot = w === root;\n const drawX = tip ? tipDrawX(w) : w.cx;\n const support = w.node.support === undefined ? null : w.node.support;\n const labelLine = tip && w.node.label !== \"\" ? [clampLabel(w.node.label, opts.maxLabelChars)] : [];\n nodes.push({\n nodeId: w.node.id,\n isTip: tip,\n cx: round(drawX),\n cy: round(w.cy),\n support,\n labelLines: labelLine,\n labelLeft: round(drawX + PHYLO_TIP_R + PHYLO_LABEL_GAP),\n depth: w.depth,\n title: nodeTitle(w.node, tip, isRoot, w.inLength, titleLabels),\n });\n\n // Aligned tip → a dotted EXTENSION from its true branch-end x to the alignment line.\n if (tip && tipsAligned && w.cx < alignX - 1e-6) {\n elements.push({\n edgeId: PHYLO_EXTENSION_ID_BASE + w.node.id,\n kind: \"extension\",\n points: [\n { x: round(w.cx), y: round(w.cy) },\n { x: round(alignX), y: round(w.cy) },\n ],\n dotted: true,\n length: null,\n title: titleLabels.tip,\n });\n }\n\n if (w.children.length === 0) return;\n\n // One shared VERTICAL clade bar at the parent's x, spanning min→max child y.\n const childYs = w.children.map((c) => c.cy);\n const barTop = Math.min(...childYs);\n const barBottom = Math.max(...childYs);\n if (barBottom - barTop > 1e-6) {\n elements.push({\n edgeId: PHYLO_CLADEBAR_ID_BASE + w.node.id,\n kind: \"clade-bar\",\n points: [\n { x: round(w.cx), y: round(barTop) },\n { x: round(w.cx), y: round(barBottom) },\n ],\n dotted: false,\n length: null,\n title: isRoot ? titleLabels.root : titleLabels.clade,\n });\n }\n\n // One HORIZONTAL branch per child: parentX → childX at childY (the rectangular elbow).\n for (const c of w.children) {\n elements.push({\n edgeId: PHYLO_BRANCH_ID_BASE + c.node.id,\n kind: \"branch\",\n points: [\n { x: round(w.cx), y: round(c.cy) },\n { x: round(c.cx), y: round(c.cy) },\n ],\n dotted: false,\n length: c.inLength,\n title: branchTitle(c),\n });\n }\n for (const c of w.children) emit(c);\n };\n emit(root);\n\n // ── Scale bar (phylogram only): a labelled horizontal segment in the dead space below\n // the tree. Its value is a niceScaleStep of the deepest distance. ───────────────────\n let scaleBar: PhyloScaleBar | null = null;\n if (hasScaleBar) {\n const stepLen = niceScaleStep(maxDist);\n const barX = padLeft;\n const barY = treeBottom + SCALEBAR_ZONE / 2;\n scaleBar = {\n length: stepLen,\n x: round(barX),\n y: round(barY),\n pxLength: round(scaleBarPx),\n valueLabel: trimNumber(stepLen),\n };\n elements.push({\n edgeId: PHYLO_SCALEBAR_ID,\n kind: \"scale-bar\",\n points: [\n { x: round(barX), y: round(barY) },\n { x: round(barX + scaleBarPx), y: round(barY) },\n ],\n dotted: false,\n length: stepLen,\n title: `${titleLabels.branchLength}: ${trimNumber(stepLen)}`,\n });\n }\n\n return { width, height, mode, nodes, elements, scaleBar, showSupport: effectiveShowSupport };\n}\n","// Phylo SVG emitter — turns a computed PhyloLayout (./layout.ts) into a SELF-CONTAINED\n// SVG string. Pure (layout in, string out) and deterministic; it draws EXACTLY what the\n// layout computed (the overlap harness proves the layout; this emitter is pinned to it).\n//\n// Hard requirements (house rules):\n// - XML-ESCAPING of EVERY interpolated text — labels/titles are author-controlled and\n// the SVG may be injected via innerHTML or embedded in PDFs;\n// - LITERAL presentation attributes only (hex colors, explicit font-family, inline\n// dasharray): a standalone SVG has no stylesheet, no currentColor, no <defs>/<marker>;\n// - every coordinate goes through round() — 2-decimal, byte-deterministic output.\n//\n// Drawing: rectangular (\"square elbow\") tree — a vertical clade bar per internal node + a\n// horizontal branch per child; aligned tips get a dotted extension leader; a small filled\n// dot marks each node point; tip labels sit left-anchored to the right of the tip; support\n// values (when showSupport baked the margin in) draw text-anchor:end just left of the\n// internal node. The phylogram scale bar is a first-class drawn element below the tree.\n//\n// Hooks: `<g data-node-id=\"n<id>\">` per node (direct-child verbatim <title>);\n// `<g data-edge-id=\"<n>\">` per element (namespaced ids, see ./layout.ts).\n\nimport { FONT_FAMILY, legendBlock, xmlEscape, LEGEND_SWATCH_W, type LegendEntry } from \"../core\";\nimport {\n PHYLO_LABEL_FONT,\n PHYLO_SUPPORT_FONT,\n type PhyloElement,\n type PhyloLayout,\n type PhyloLayoutNode,\n} from \"./layout\";\nimport { PHYLO_SVG_LABELS_EN, type PhyloSvgLabels } from \"./labels\";\n\n// Literal ink colors (zinc ramp on white — matches every other compasso emitter).\nconst GLYPH_STROKE = \"#52525b\";\nconst LABEL_FILL = \"#3f3f46\";\nconst EDGE_INK = \"#71717a\";\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\nexport interface PhyloSvgOptions {\n /** Set false to suppress the legend (compact preview); default true. */\n legend?: boolean;\n /** Display vocabulary (legend/accessibility) — English default; see locale packs. */\n labels?: PhyloSvgLabels;\n}\n\n// ── Node points + tip labels + support text ───────────────────────────────────────────\n\nfunction nodeSvg(n: PhyloLayoutNode, showSupport: boolean): string {\n const pieces: string[] = [`<title>${xmlEscape(n.title)}</title>`];\n // A small filled dot marks every node point (tip and internal).\n pieces.push(`<circle cx=\"${n.cx}\" cy=\"${n.cy}\" r=\"2.5\" fill=\"${GLYPH_STROKE}\"/>`);\n // Tip label: single clamped line, left-anchored right of the tip point.\n if (n.labelLines.length > 0) {\n pieces.push(\n `<text x=\"${n.labelLeft}\" y=\"${round(n.cy + PHYLO_LABEL_FONT * 0.32)}\" font-family=\"${FONT_FAMILY}\" font-size=\"${PHYLO_LABEL_FONT}\" fill=\"${LABEL_FILL}\">${xmlEscape(n.labelLines[0]!)}</text>`,\n );\n }\n // Internal support value: text-anchor:end just left of the node (margin reserved in\n // the layout). Drawn only when requested AND the value is present.\n if (showSupport && !n.isTip && n.support !== null) {\n pieces.push(\n `<text x=\"${round(n.cx - 4)}\" y=\"${round(n.cy - 3)}\" text-anchor=\"end\" font-family=\"${FONT_FAMILY}\" font-size=\"${PHYLO_SUPPORT_FONT}\" fill=\"${LABEL_FILL}\">${xmlEscape(String(n.support))}</text>`,\n );\n }\n return `<g data-node-id=\"n${n.nodeId}\">${pieces.join(\"\")}</g>`;\n}\n\n// ── Connector elements (clade bars, branches, dotted extensions, root stub, scale bar) ──\n\nfunction elementSvg(el: PhyloElement): string {\n const a = el.points[0]!;\n const b = el.points[1]!;\n const dash = el.dotted ? ` stroke-dasharray=\"2,3\"` : \"\";\n const opacity = el.kind === \"extension\" ? \"0.5\" : \"0.75\";\n return (\n `<g data-edge-id=\"${el.edgeId}\"><title>${xmlEscape(el.title)}</title>` +\n `<line x1=\"${a.x}\" y1=\"${a.y}\" x2=\"${b.x}\" y2=\"${b.y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"${opacity}\"${dash}/></g>`\n );\n}\n\n// ── Scale-bar value label (drawn separately from its segment element) ──────────────────\n\nfunction scaleBarLabelSvg(layout: PhyloLayout): string {\n const bar = layout.scaleBar;\n if (bar === null) return \"\";\n // Small end ticks frame the bar; the value sits centered above it.\n const tick = (x: number): string =>\n `<line x1=\"${x}\" y1=\"${round(bar.y - 3)}\" x2=\"${x}\" y2=\"${round(bar.y + 3)}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>`;\n return (\n tick(bar.x) +\n tick(round(bar.x + bar.pxLength)) +\n `<text x=\"${round(bar.x + bar.pxLength / 2)}\" y=\"${round(bar.y - 6)}\" text-anchor=\"middle\" font-family=\"${FONT_FAMILY}\" font-size=\"${PHYLO_SUPPORT_FONT}\" fill=\"${LABEL_FILL}\">${xmlEscape(bar.valueLabel)}</text>`\n );\n}\n\n// ── Legend mini-swatches ───────────────────────────────────────────────────────────────\n\nfunction supportSwatch(x: number, y: number): string {\n const cx = round(x + LEGEND_SWATCH_W / 2);\n return (\n `<circle cx=\"${cx}\" cy=\"${y}\" r=\"2.5\" fill=\"${GLYPH_STROKE}\"/>` +\n `<text x=\"${round(cx + 5)}\" y=\"${round(y + PHYLO_SUPPORT_FONT * 0.32)}\" font-family=\"${FONT_FAMILY}\" font-size=\"${PHYLO_SUPPORT_FONT}\" fill=\"${LABEL_FILL}\">95</text>`\n );\n}\n\nfunction scaleSwatch(x: number, y: number): string {\n return `<line x1=\"${round(x)}\" y1=\"${y}\" x2=\"${round(x + LEGEND_SWATCH_W)}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>`;\n}\n\nfunction alignedTipSwatch(x: number, y: number): string {\n return `<line x1=\"${round(x)}\" y1=\"${y}\" x2=\"${round(x + LEGEND_SWATCH_W)}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.5\" stroke-dasharray=\"2,3\"/>`;\n}\n\n/**\n * Emits a self-contained SVG for a computed phylo layout. Pure + deterministic.\n * Coordinates come straight from the layout; all interpolated text is XML-escaped; all\n * presentation attributes are literal. The legend is minimal and used-keys-only: a phylo\n * tree is self-labelling (tips carry names), so often it has zero entries.\n *\n * `showSupport` is read off the layout's reserved margin: the emitter draws the support\n * text only when a support value was reserved (any internal node has a non-null support\n * AND the support margin > PADDING). This keeps the emitter pinned to the layout — it\n * never reserves what the layout didn't, nor draws what it can't fit.\n */\nexport function phyloLayoutSvg(layout: PhyloLayout, opts: PhyloSvgOptions = {}): string {\n const labels = opts.labels ?? PHYLO_SVG_LABELS_EN;\n // showSupport is a layout-affecting option (it reserves left margin), so the layout\n // bakes the resolved flag in — the emitter reads it off the layout and never re-decides.\n const showSupport = layout.showSupport;\n\n const parts: string[] = [];\n\n // Connectors first, then node points/labels — points sit on top.\n for (const el of layout.elements) parts.push(elementSvg(el));\n parts.push(scaleBarLabelSvg(layout));\n for (const n of layout.nodes) parts.push(nodeSvg(n, showSupport));\n\n // ── Used-keys-only legend (core legendBlock; `legend:false` suppresses). ──────────────\n let width = layout.width;\n let height = layout.height;\n if (opts.legend !== false && layout.nodes.length > 0) {\n const entries: LegendEntry[] = [];\n if (showSupport) entries.push({ swatch: supportSwatch, label: labels.support });\n if (layout.scaleBar !== null) entries.push({ swatch: scaleSwatch, label: labels.scaleBar });\n if (layout.elements.some((e) => e.kind === \"extension\")) {\n entries.push({ swatch: alignedTipSwatch, label: labels.alignedTip });\n }\n const block = legendBlock(entries, layout.height);\n if (block.svg !== \"\") {\n parts.push(block.svg);\n width = Math.max(width, block.width);\n height = block.height;\n }\n }\n\n const w = Math.ceil(width);\n const h = Math.ceil(height);\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${w} ${h}\" width=\"${w}\" height=\"${h}\" role=\"img\" aria-label=\"${xmlEscape(labels.ariaLabel[layout.mode])}\">` +\n parts.join(\"\") +\n `</svg>`\n );\n}\n","// One-call phylo render: input → { svg, layout }. Thin, honest wiring: validate (throw on\n// an un-layout-able tree — never repair), compute the pure layout, emit. Callers needing\n// finer control use computePhyloLayout + phyloLayoutSvg directly (the layout result\n// supports hit-testing / decorating the diagram).\n\nimport { computePhyloLayout, type PhyloLayout, type PhyloLayoutOptions } from \"./layout\";\nimport { phyloLayoutSvg } from \"./svg\";\nimport type { PhyloSvgLabels } from \"./labels\";\nimport type { PhyloInput } from \"./types\";\n\nexport interface PhyloRenderOptions extends PhyloLayoutOptions {\n /** Set false to suppress the legend (compact preview); default true. */\n legend?: boolean;\n /** Display vocabulary for the emitter (legend/accessibility) — English default. */\n svgLabels?: PhyloSvgLabels;\n}\n\nexport interface PhyloRenderResult {\n /** Self-contained SVG (numeric width/height + matching viewBox — PDF-embedder safe). */\n svg: string;\n /** The computed layout, for callers that decorate or hit-test the diagram. */\n layout: PhyloLayout;\n}\n\n/**\n * Renders a phylo input to a self-contained SVG string. Deterministic: same data → same\n * SVG (array order never matters; a node's children are drawn in declared edge order, the\n * analyst's ladderization choice, never auto-sorted). Throws PhyloValidationError —\n * carrying EVERY issue, deterministically sorted — on an un-layout-able tree (cycle,\n * forest, DAG, dangling reference). Empty input yields an empty-but-valid SVG.\n */\nexport function phyloSvg(input: PhyloInput, opts: PhyloRenderOptions = {}): PhyloRenderResult {\n const layout = computePhyloLayout(input, {\n ...(opts.mode !== undefined ? { mode: opts.mode } : {}),\n ...(opts.alignTips !== undefined ? { alignTips: opts.alignTips } : {}),\n ...(opts.showSupport !== undefined ? { showSupport: opts.showSupport } : {}),\n ...(opts.scaleBar !== undefined ? { scaleBar: opts.scaleBar } : {}),\n ...(opts.maxLabelChars !== undefined ? { maxLabelChars: opts.maxLabelChars } : {}),\n ...(opts.titleLabels !== undefined ? { titleLabels: opts.titleLabels } : {}),\n });\n const svg = phyloLayoutSvg(layout, {\n ...(opts.legend === false ? { legend: false } : {}),\n ...(opts.svgLabels !== undefined ? { labels: opts.svgLabels } : {}),\n });\n return { svg, layout };\n}\n"]}
1
+ {"version":3,"sources":["../src/phylo/labels.ts","../src/phylo/validate.ts","../src/phylo/layout.ts","../src/phylo/svg.ts","../src/phylo/render.ts"],"names":["round"],"mappings":"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","file":"chunk-PJHLWSGD.js","sourcesContent":["// Display vocabularies — every human-readable string the phylo tree emits, gathered in\n// overridable packs so the diagram localizes without touching the engine. English\n// defaults here; `compasso/locales/pt-br` ships a Brazilian Portuguese pack.\n//\n// Title labels are woven into element/node <title>s by the LAYOUT (verbatim-preserving:\n// a branch's actual length / a clade's actual support always rides the title, even when\n// the drawn diagram omits them). Svg labels are drawn by the EMITTER (legend, aria).\n\nimport type { PhyloMode } from \"./types\";\n\n/** Labels woven into <title>s by the LAYOUT (verbatim-preserving). */\nexport interface PhyloTitleLabels {\n /** \"branch length\" → \"branch length: 0.123\" when a length is present. */\n branchLength: string;\n /** \"support\" → \"support: 95\" when a support value is present. */\n support: string;\n clade: string;\n tip: string;\n root: string;\n}\n\nexport const PHYLO_TITLE_LABELS_EN: PhyloTitleLabels = {\n branchLength: \"branch length\",\n support: \"support\",\n clade: \"clade\",\n tip: \"tip\",\n root: \"root\",\n};\n\n/** Labels drawn by the SVG EMITTER (legend entries, accessibility text). */\nexport interface PhyloSvgLabels {\n support: string;\n scaleBar: string;\n alignedTip: string;\n /** Aria label switches on the layout's render mode. */\n ariaLabel: Record<PhyloMode, string>;\n}\n\nexport const PHYLO_SVG_LABELS_EN: PhyloSvgLabels = {\n support: \"Support value (bootstrap/posterior)\",\n scaleBar: \"Scale: substitutions per site\",\n alignedTip: \"Aligned tip (true position dotted)\",\n ariaLabel: {\n cladogram: \"Phylogenetic tree (cladogram)\",\n phylogram: \"Phylogenetic tree (phylogram)\",\n },\n};\n","// Phylo validation — the MIDDLE doctrine. A phylogenetic tree is not a safety artifact\n// like a fault tree (an incomplete/exploratory tree is a legitimate thing to draw), but\n// unlike a genogram a tree MUST be a tree to lay out (a cycle or a forest has no\n// root-anchored x). So we throw PhyloValidationError carrying a MINIMAL closed code set\n// that rejects only what makes layout impossible or ambiguous — never what is merely\n// incomplete. The shape (sorted kebab-case { code, message } issues, three-phase gating)\n// is the fault-tree's, verbatim.\n//\n// Every problem is reported, not just the first: issues are aggregated, deduplicated and\n// sorted deterministically (by code, then message — byte comparison, no locale collation),\n// each carrying a STABLE kebab-case `code`. Validation runs in THREE phases, each gated on\n// the prior being clean ENOUGH for the next to be meaningful (NOT on \"zero issues so far\",\n// so a defect in one phase never hides an honest issue from a later one):\n// (0) duplicate ids (per namespace). The lookup maps below are first-occurrence-wins, so\n// every reference rule would otherwise depend on array order — violating this\n// function's documented order-invariance. Any duplicate-id issue → report ONLY those\n// and stop (the duplicate already forces a throw, present in every permutation).\n// (1) reference + structural-tree rules: unknown-endpoint (an edge to a phantom node),\n// unknown-root, multiple-parents (a node with ≥2 incoming edges — a DAG, not a tree),\n// negative-length (a meaningless distance — reject, never clamp), tip-with-children\n// (a declared isTip flag contradicting topology). All evaluated once ids are\n// unambiguous; none requires a clean graph walk.\n// (2) graph rules: cycle (a back-edge in the parent→child walk) and disconnected-node\n// (a node unreachable from root). Gated ONLY on the reference-INTEGRITY subset that\n// corrupts the traversal itself — duplicate-id (ambiguous first-wins node),\n// unknown-endpoint (walks a phantom node), unknown-root (the BFS frontier roots at a\n// non-node), multiple-parents (the child-set is ambiguous). negative-length and\n// tip-with-children leave the graph fully walkable, so they do NOT suppress the graph\n// phase: a negative length alongside an unreachable node reports BOTH in one throw.\n//\n// Tolerated, by design (drawn as declared, never converted):\n// - empty labels (drawn empty; the <title> is still present);\n// - missing support (null/absent — drawn unlabeled);\n// - a single-node tree (root only, no edges — a valid degenerate tree, one tip);\n// - null lengths (phylogram → 0) and zero-length branches (a node directly above its\n// parent's x — a real polytomy/zero-support resolution, NOT an error);\n// - unbalanced / ladderized topology (declared child order honored, never auto-sorted).\n\nimport type { PhyloInput, PhyloNode } from \"./types\";\n\n/** Stable machine-readable issue codes (kebab-case; part of the public contract). */\nexport type PhyloIssueCode =\n | \"duplicate-id\"\n | \"unknown-endpoint\"\n | \"unknown-root\"\n | \"multiple-parents\"\n | \"cycle\"\n | \"disconnected-node\"\n | \"tip-with-children\"\n | \"negative-length\";\n\nexport interface PhyloIssue {\n code: PhyloIssueCode;\n message: string;\n}\n\n/** Thrown by computePhyloLayout / phyloSvg on a structurally un-layout-able tree. */\nexport class PhyloValidationError extends Error {\n readonly issues: readonly PhyloIssue[];\n\n constructor(issues: readonly PhyloIssue[]) {\n super(`invalid phylo tree: ${issues.map((i) => i.message).join(\"; \")}`);\n this.name = \"PhyloValidationError\";\n this.issues = issues;\n }\n}\n\n/**\n * Deduplicate + deterministic order: by code, then message (byte comparison — stable\n * across engines; no locale-dependent collation). Shared by every phase that returns.\n */\nfunction sortIssues(issues: readonly PhyloIssue[]): readonly PhyloIssue[] {\n const unique = new Map<string, PhyloIssue>();\n for (const issue of issues) unique.set(`${issue.code} ${issue.message}`, issue);\n return [...unique.values()].sort((a, b) =>\n a.code !== b.code ? (a.code < b.code ? -1 : 1) : a.message < b.message ? -1 : a.message > b.message ? 1 : 0,\n );\n}\n\n/**\n * Computes ALL validation issues for the input, deduplicated and deterministically\n * sorted (code, then message) — array order of `nodes`/`edges` never changes the result.\n * Empty input (no nodes AND no edges) is valid by definition (the renderer's\n * empty-but-valid SVG case) and reports no issues.\n */\nexport function phyloIssues(input: PhyloInput): readonly PhyloIssue[] {\n if (input.nodes.length === 0 && input.edges.length === 0) return [];\n\n const issues: PhyloIssue[] = [];\n const push = (code: PhyloIssueCode, message: string): void => {\n issues.push({ code, message });\n };\n\n // ── R1: duplicate ids (per namespace — hooks must be unique). Any duplicate makes the\n // structure ambiguous, so this is phase 0 and short-circuits the rest (below). ─────\n const nodeById = new Map<number, PhyloNode>();\n const dupNodeIds = new Set<number>();\n for (const n of input.nodes) {\n if (nodeById.has(n.id)) dupNodeIds.add(n.id);\n else nodeById.set(n.id, n);\n }\n for (const id of [...dupNodeIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate node id ${id}`);\n }\n const dupEdgeIds = new Set<number>();\n const seenEdgeIds = new Set<number>();\n for (const e of input.edges) {\n if (seenEdgeIds.has(e.id)) dupEdgeIds.add(e.id);\n else seenEdgeIds.add(e.id);\n }\n for (const id of [...dupEdgeIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate edge id ${id}`);\n }\n\n // ── Phase 0: duplicate ids short-circuit everything else (see module header). ────────\n if (issues.length > 0) {\n return sortIssues(issues);\n }\n\n // ── R2: the declared root must be an existing node. ──────────────────────────────────\n if (!nodeById.has(input.rootId)) {\n push(\"unknown-root\", `rootId ${input.rootId} is not a declared node`);\n }\n\n // ── Per-edge reference / structural rules. The child→parent map drives the graph\n // phase: built only from edges with BOTH endpoints declared (a phantom endpoint\n // would seed a non-existent node). ────────────────────────────────────────────────\n const incomingByChild = new Map<number, number[]>(); // child id → parent ids (declared edges only)\n for (const e of [...input.edges].sort((a, b) => a.id - b.id)) {\n const knownParent = nodeById.has(e.parentId);\n const knownChild = nodeById.has(e.childId);\n if (!knownParent) push(\"unknown-endpoint\", `edge ${e.id} parentId ${e.parentId} is not a declared node`);\n if (!knownChild) push(\"unknown-endpoint\", `edge ${e.id} childId ${e.childId} is not a declared node`);\n // R4 — a non-finite or negative distance is meaningless. Reject (never clamp): drawing\n // it would silently reinterpret the data AND a non-finite length poisons the phylogram\n // scale (cumulative dist → Infinity, scale → 0, x → padLeft + Infinity·0 = NaN, and the\n // whole SVG emits viewBox=\"0 0 NaN …\"). `Number.isFinite` is false for NaN/+Inf/-Inf,\n // so the one guard covers every corrupt SPECIFIED value; null stays valid (→ 0 in the\n // phylogram, the legitimate \"unspecified\" branch).\n if (e.length !== null && (!Number.isFinite(e.length) || e.length < 0)) {\n push(\"negative-length\", `edge ${e.id} has non-finite or negative length ${e.length}`);\n }\n if (knownParent && knownChild) {\n const arr = incomingByChild.get(e.childId) ?? [];\n arr.push(e.parentId);\n incomingByChild.set(e.childId, arr);\n }\n }\n\n // R3 — a tree node has at most ONE parent; ≥2 incoming edges is a DAG (un-layout-able\n // with a single root-anchored x). Reported per child, ascending.\n const childIdsWithEdges = new Set<number>();\n for (const e of input.edges) childIdsWithEdges.add(e.childId);\n for (const [childId, parents] of [...incomingByChild.entries()].sort((a, b) => a[0] - b[0])) {\n if (parents.length > 1) {\n push(\"multiple-parents\", `node ${childId} has ${parents.length} parents`);\n }\n }\n\n // R5 — isTip is DERIVED: a node with an outgoing edge is internal, a node with none is a\n // tip. A declared isTip flag that contradicts the topology is reported (honesty rule —\n // we draw the declared topology, we never invent or suppress a leaf because of a flag).\n const hasChildren = new Set<number>();\n for (const e of input.edges) {\n if (nodeById.has(e.parentId)) hasChildren.add(e.parentId);\n }\n for (const n of [...nodeById.values()].sort((a, b) => a.id - b.id)) {\n if (n.isTip === true && hasChildren.has(n.id)) {\n push(\"tip-with-children\", `node ${n.id} is declared a tip but has children`);\n } else if (n.isTip === false && !hasChildren.has(n.id)) {\n push(\"tip-with-children\", `node ${n.id} is declared internal but has no children`);\n }\n }\n\n // ── Graph rules (cycle, disconnected-node) — phase 2. Gated ONLY on the reference-\n // INTEGRITY codes that corrupt the traversal (see the module header), NOT on every\n // phase-1 issue: a negative length or a contradicted tip flag leaves the graph fully\n // walkable, so suppressing the graph phase for them would hide an honest issue. ─────\n const GRAPH_BLOCKING: ReadonlySet<PhyloIssueCode> = new Set<PhyloIssueCode>([\n \"duplicate-id\",\n \"unknown-endpoint\",\n \"unknown-root\",\n \"multiple-parents\",\n ]);\n if (!issues.some((i) => GRAPH_BLOCKING.has(i.code))) {\n // Children of a node in declared edge order (stable-sorted by edge id), declared edges\n // only — every endpoint is known here (no unknown-endpoint survived the gate).\n const childrenOf = new Map<number, number[]>();\n for (const e of [...input.edges].sort((a, b) => a.id - b.id)) {\n const arr = childrenOf.get(e.parentId) ?? [];\n arr.push(e.childId);\n childrenOf.set(e.parentId, arr);\n }\n\n // R6 — cycle detection over the parent→child graph (coloring DFS, start nodes\n // ascending, children in declared order). Each distinct cycle is reported once,\n // rotated to start at its smallest node id so the message is array-order-independent.\n const color = new Map<number, 0 | 1 | 2>(); // 0/absent=white, 1=gray, 2=black\n const seenCycles = new Set<string>();\n const dfs = (start: number): void => {\n const stack: { id: number; nextChild: number }[] = [{ id: start, nextChild: 0 }];\n color.set(start, 1);\n while (stack.length > 0) {\n const frame = stack[stack.length - 1]!;\n const children = childrenOf.get(frame.id) ?? [];\n if (frame.nextChild >= children.length) {\n color.set(frame.id, 2);\n stack.pop();\n continue;\n }\n const child = children[frame.nextChild]!;\n frame.nextChild += 1;\n const c = color.get(child) ?? 0;\n if (c === 1) {\n const from = stack.findIndex((f) => f.id === child);\n const cycle = stack.slice(from).map((f) => f.id);\n const minIdx = cycle.indexOf(Math.min(...cycle));\n const rotated = [...cycle.slice(minIdx), ...cycle.slice(0, minIdx)];\n const key = rotated.join(\">\");\n if (!seenCycles.has(key)) {\n seenCycles.add(key);\n push(\"cycle\", `cycle: ${[...rotated, rotated[0]!].join(\" → \")}`);\n }\n } else if (c === 0) {\n color.set(child, 1);\n stack.push({ id: child, nextChild: 0 });\n }\n }\n };\n for (const n of [...nodeById.values()].sort((a, b) => a.id - b.id)) {\n if ((color.get(n.id) ?? 0) === 0) dfs(n.id);\n }\n\n // R7 — every declared node must be reachable from the root (a forest has no single\n // root-anchored x). Silently dropping a declared component violates honesty.\n const reachable = new Set<number>();\n const queue: number[] = [input.rootId];\n while (queue.length > 0) {\n const id = queue.shift()!;\n if (reachable.has(id)) continue;\n reachable.add(id);\n for (const childId of childrenOf.get(id) ?? []) queue.push(childId);\n }\n for (const n of [...nodeById.values()].sort((a, b) => a.id - b.id)) {\n if (!reachable.has(n.id)) push(\"disconnected-node\", `node ${n.id} is unreachable from the root`);\n }\n }\n\n return sortIssues(issues);\n}\n\n/** Throws PhyloValidationError (carrying ALL issues) when the input is un-layout-able. */\nexport function validatePhylo(input: PhyloInput): void {\n const issues = phyloIssues(input);\n if (issues.length > 0) throw new PhyloValidationError(issues);\n}\n","// PURE phylo layout — the single source of truth for positioning and connector routing.\n// The emitter (./svg.ts) draws EXACTLY what this computes, so web / PDF / image pipelines\n// can never drift. Deliberately PURE — no DOM, no Node APIs, no clock, no randomness —\n// so the same input always yields the same layout, byte for byte.\n//\n// HONESTY RULE: this module only POSITIONS the declared topology. Validation\n// (./validate.ts) THROWS on an un-layout-able tree (cycle, forest, DAG) rather than\n// repairing it. A branch length absent from the cladogram x is NEVER lost: it always\n// rides the branch element's <title>. A tip is DERIVED (no outgoing edge); we never\n// invent or suppress a leaf.\n//\n// LAYOUT — the classic tidy-tree (the textbook phylogeny algorithm):\n// * Tip ordering: one DFS from rootId, children in DECLARED edge order (stable-sorted\n// by edge id for determinism — the cladistics \"declared order is the analyst's\n// ladderization choice, never auto-sorted\"). Tips numbered 0..L-1 in DFS-visit order.\n// * Leaf y: tip i → y = top + i·ROW_SLOT + ROW_SLOT/2. Equal disjoint slots ⇒ no\n// vertical overlap by construction (the genogram's column bands, transposed 90°).\n// * Internal y = midpoint of its children's y ((min+max)/2), computed post-order.\n// Horizontal:\n// * cladogram: x = padLeft + depth·LEVEL_W; tips right-aligned to maxDepth's x; a dotted\n// EXTENSION segment fills from a tip's true depth-x to the alignment line (FigTree).\n// * phylogram: x = padLeft + cumulativeLength(root→node)·SCALE, SCALE = drawW/maxRootTip\n// (fit-to-width). null/0 lengths contribute 0 ⇒ a node sits directly above its parent\n// (a zero-length branch — valid, NOT an error). Tips not right-aligned unless alignTips.\n// Edges = rectangular elbows (orthogonal, harness-clean): one shared VERTICAL \"clade bar\"\n// per parent spanning min→max child y at the parent's x, plus one HORIZONTAL \"branch\" per\n// child from parentX to childX at childY. Overlap proof: tips own disjoint y-bands; an\n// internal node's y is strictly between its children's bands ⇒ clade bars nest without\n// overlap; branches live at distinct child-y's. Same inductive structure as the fault\n// tree, transposed.\n\nimport { clampLabel, estimateTextWidth, type Point } from \"../core\";\nimport { PHYLO_TITLE_LABELS_EN, type PhyloTitleLabels } from \"./labels\";\nimport { validatePhylo } from \"./validate\";\nimport type { PhyloInput, PhyloMode, PhyloNode } from \"./types\";\n\nexport { PhyloValidationError, phyloIssues, validatePhylo, type PhyloIssue, type PhyloIssueCode } from \"./validate\";\n// Re-exported so the overlap harness (and decorating callers) measure with the EXACT\n// metrics the layout reserved space with — the shared-metrics contract.\nexport { estimateTextWidth };\nexport type { Point };\n\n// ── Type metrics (shared by layout AND the emitter, so geometry == render) ───────────\n/** Tip-label font size (px). */\nexport const PHYLO_LABEL_FONT = 12;\n/** Vertical slot per tip (px) — equal slots guarantee vertical disjointness. */\nexport const PHYLO_ROW_SLOT = 22;\n/** Support-value font size (px) — drawn just left of an internal node. */\nexport const PHYLO_SUPPORT_FONT = 10;\n/** Gap from a tip point to the start of its label text. */\nexport const PHYLO_LABEL_GAP = 8;\n\n// ── Geometry constants ───────────────────────────────────────────────────────────────\nconst PADDING = 32;\n/** Horizontal level width per topological depth (cladogram x; phylogram fallback). */\nconst PHYLO_LEVEL_W = 72;\n/** Tip dot radius (a small filled marker at each node point). */\nconst PHYLO_TIP_R = 2.5;\n/** Reserved gap to the left of an internal node for its support text (when showSupport). */\nconst SUPPORT_GAP = 4;\n/** Vertical gap reserved below the tree for the scale bar assembly. */\nconst SCALEBAR_ZONE = 34;\n/** Drawn length cap (in px) of the available width for the tree body. */\nconst MIN_DRAW_W = PHYLO_LEVEL_W; // a degenerate single-depth tree still gets one level\n/** Phylogram-only x nudge (px) for an INTERNAL child whose zero/null branch lands it at\n * exactly its parent's x. Without it, the child's clade bar and the parent's clade bar are\n * two collinear verticals (double-drawn line, ambiguous polytomy). One pixel right gives\n * the child's bar its own vertical while preserving the \"directly above the parent\" read; a\n * TIP at the parent's x needs no nudge (a tip has no clade bar). PRESENTATION-only — the\n * verbatim 0/null length still rides the branch element's <title>. */\nconst PHYLO_ZERO_NUDGE = 1;\n\n// ── Namespaced element-id blocks (one element kind per numeric block; every\n// data-edge-id stays traceable to its source node) ─────────────────────────────────\nexport const PHYLO_CLADEBAR_ID_BASE = 1_000_000; // + parent node id (the vertical bar)\nexport const PHYLO_BRANCH_ID_BASE = 2_000_000; // + child node id (the horizontal branch)\nexport const PHYLO_EXTENSION_ID_BASE = 3_000_000; // + tip node id (dotted right-align extension)\nexport const PHYLO_ROOTSTUB_ID_BASE = 4_000_000; // + root id (the short left stub into the root)\nexport const PHYLO_SCALEBAR_ID = 5_000_000; // the labelled scale-bar segment\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\n// ── Positioned layout ─────────────────────────────────────────────────────────────────\n\nexport interface PhyloLayoutNode {\n nodeId: number;\n isTip: boolean;\n /** Node point center. */\n cx: number;\n cy: number;\n /** Bootstrap/posterior; null when absent (always in the <title> regardless). */\n support: number | null;\n /** Tip label as a single clamped line, drawn right of the tip point; [] for internals. */\n labelLines: string[];\n /** x where the tip label text starts (after PHYLO_LABEL_GAP); the tip's drawn-x for an\n * aligned tip is the alignment line, so the label always clears the tip point. */\n labelLeft: number;\n /** Edges from the root (a tip in cladogram mode keeps its TRUE depth here). */\n depth: number;\n /** Verbatim <title> text (node.title ?? label + branch-length/support). */\n title: string;\n}\n\nexport type PhyloElementKind = \"clade-bar\" | \"branch\" | \"extension\" | \"root-stub\" | \"scale-bar\";\n\nexport interface PhyloElement {\n /** Namespaced id (PHYLO_*_ID_BASE + parent/child/tip/root id, or PHYLO_SCALEBAR_ID). */\n edgeId: number;\n kind: PhyloElementKind;\n /** Consecutive pairs axis-aligned (clade-bar = V, branch/extension/scale-bar = H). */\n points: Point[];\n /** Drawn dotted (extension + scale-bar ticks are NOT here — only the extension leader). */\n dotted: boolean;\n /** Branch: the verbatim length for the <title>; null otherwise / unspecified. */\n length: number | null;\n title: string;\n}\n\nexport interface PhyloScaleBar {\n /** Branch-length value the bar represents (a nice round step). */\n length: number;\n /** Bar's left x and baseline y. */\n x: number;\n y: number;\n /** Drawn pixel length of the bar (length·SCALE). */\n pxLength: number;\n /** Displayed numeric label (the value, trimmed of trailing zeros). */\n valueLabel: string;\n}\n\nexport interface PhyloLayout {\n width: number;\n height: number;\n mode: PhyloMode;\n /** DFS pre-order (root first, then children in declared edge order). */\n nodes: PhyloLayoutNode[];\n elements: PhyloElement[];\n /** Present only in phylogram mode with scaleBar !== false and a non-degenerate scale. */\n scaleBar: PhyloScaleBar | null;\n /** True when the layout reserved left-margin space for support text AND any internal\n * node carries a support value — the emitter draws support text iff this is set. */\n showSupport: boolean;\n}\n\nexport interface PhyloLayoutOptions {\n /** \"cladogram\" (default) | \"phylogram\". */\n mode?: PhyloMode;\n /** Dotted tip-alignment extensions. cladogram default true; phylogram default false. */\n alignTips?: boolean;\n /** Reserve left margin + draw support text at internal nodes. Default false. */\n showSupport?: boolean;\n /** Draw the phylogram scale bar (ignored in cladogram). Default true. */\n scaleBar?: boolean;\n /** Cap each tip's DISPLAY label (compact preview); verbatim text stays in `title`. */\n maxLabelChars?: number;\n /** Locale pack for node/branch <title>s — English default. */\n titleLabels?: PhyloTitleLabels;\n}\n\n// ── niceScaleStep — the largest power-of-ten × {1, 2, 5} that is ≤ maxLen/4. A pure\n// function so the scale bar is a stable, \"nice\" round number regardless of the data's\n// exact range (the standard FigTree/ggtree scale-bar value). maxLen ≤ 0 → 0. ─────────\nexport function niceScaleStep(maxLen: number): number {\n if (!(maxLen > 0)) return 0;\n const target = maxLen / 4;\n const exp = Math.floor(Math.log10(target));\n const pow = Math.pow(10, exp);\n // A small relative tolerance so a value imperceptibly below a boundary (e.g. 0.2/4 =\n // 0.04999999999999999 from float rounding) still selects the intended \"nice\" step —\n // the scale value is presentation-only and snapping to the boundary is the honest read.\n const tol = target * 1e-9;\n for (const mult of [5, 2, 1]) {\n const step = mult * pow;\n if (step <= target + tol) return step;\n }\n // target < pow (only when log10 rounding leaves a gap) → the next decade down's 5×.\n return 5 * Math.pow(10, exp - 1);\n}\n\n/** Trims a numeric scale value to a short label (\"0.50\" → \"0.5\", \"1.0\" → \"1\"). */\nfunction trimNumber(n: number): string {\n if (Number.isInteger(n)) return String(n);\n return String(Number(n.toPrecision(6))).replace(/0+$/, \"\").replace(/\\.$/, \"\");\n}\n\n// ── Internal working node ──────────────────────────────────────────────────────────────\n\ninterface Work {\n node: PhyloNode;\n children: Work[];\n depth: number;\n /** Cumulative root→node branch length (phylogram); 0 for null/zero lengths. */\n dist: number;\n /** Length of the edge INTO this node (the root's is null). */\n inLength: number | null;\n cx: number;\n cy: number;\n}\n\nfunction nodeTitle(\n node: PhyloNode,\n isTip: boolean,\n isRoot: boolean,\n inLength: number | null,\n labels: PhyloTitleLabels,\n): string {\n if (node.title !== undefined) return node.title;\n const role = isRoot ? labels.root : isTip ? labels.tip : labels.clade;\n const head = node.label === \"\" ? role : node.label;\n const parts: string[] = [head];\n if (inLength !== null) parts.push(`${labels.branchLength}: ${trimNumber(inLength)}`);\n if (!isTip && node.support !== undefined && node.support !== null) {\n parts.push(`${labels.support}: ${trimNumber(node.support)}`);\n }\n return parts.join(\" · \");\n}\n\n/**\n * Deterministic, overlap-proof phylo layout (pure function of the inputs). Validates\n * first and THROWS PhyloValidationError on an un-layout-able tree — never sanitizes.\n * Empty input (no nodes, no edges) yields an empty, padded layout; `rootId` is ignored\n * in that one case.\n */\nexport function computePhyloLayout(input: PhyloInput, opts: PhyloLayoutOptions = {}): PhyloLayout {\n const mode: PhyloMode = opts.mode ?? \"cladogram\";\n if (input.nodes.length === 0 && input.edges.length === 0) {\n return { width: PADDING * 2, height: PADDING * 2, mode, nodes: [], elements: [], scaleBar: null, showSupport: false };\n }\n validatePhylo(input);\n\n const titleLabels = opts.titleLabels ?? PHYLO_TITLE_LABELS_EN;\n const alignTips = opts.alignTips ?? (mode === \"cladogram\");\n const showSupport = opts.showSupport ?? false;\n const wantScaleBar = (opts.scaleBar ?? true) && mode === \"phylogram\";\n\n const nodeById = new Map(input.nodes.map((n) => [n.id, n]));\n // Children of a node in declared edge order (stable by edge id) — the validated tree\n // guarantees every endpoint exists and each node has ≤1 parent.\n const childrenOf = new Map<number, number[]>();\n const inLengthByChild = new Map<number, number | null>();\n for (const e of [...input.edges].sort((a, b) => a.id - b.id)) {\n (childrenOf.get(e.parentId) ?? childrenOf.set(e.parentId, []).get(e.parentId)!).push(e.childId);\n inLengthByChild.set(e.childId, e.length);\n }\n\n // ── Build the working tree by DFS from the root (children in declared order). ─────────\n const allWork: Work[] = [];\n const build = (nodeId: number, depth: number, dist: number): Work => {\n const node = nodeById.get(nodeId)!;\n const inLength = inLengthByChild.get(nodeId) ?? null;\n const work: Work = { node, children: [], depth, dist, inLength, cx: 0, cy: 0 };\n allWork.push(work);\n for (const childId of childrenOf.get(nodeId) ?? []) {\n const childLen = inLengthByChild.get(childId);\n const add = childLen === null || childLen === undefined ? 0 : Math.max(0, childLen);\n work.children.push(build(childId, depth + 1, dist + add));\n }\n return work;\n };\n const root = build(input.rootId, 0, 0);\n\n const isTip = (w: Work): boolean => w.children.length === 0;\n\n // ── Vertical: equal leaf slots in DFS order; internal y = midpoint of children. ───────\n const top = PADDING;\n let tipIndex = 0;\n const assignY = (w: Work): void => {\n if (isTip(w)) {\n w.cy = top + tipIndex * PHYLO_ROW_SLOT + PHYLO_ROW_SLOT / 2;\n tipIndex += 1;\n return;\n }\n for (const c of w.children) assignY(c);\n const ys = w.children.map((c) => c.cy);\n w.cy = (Math.min(...ys) + Math.max(...ys)) / 2;\n };\n assignY(root);\n const tipCount = tipIndex;\n\n // ── Horizontal: depth-x (cladogram) or cumulative-length-x (phylogram, fit-to-width). ─\n const maxDepth = allWork.reduce((m, w) => Math.max(m, w.depth), 0);\n const maxDist = allWork.reduce((m, w) => Math.max(m, w.dist), 0);\n\n // Left margin: PADDING + reserved support-text width (only when showSupport AND any\n // internal node actually carries a support value — measured space, the house rule).\n const supportNodes = allWork.filter(\n (w) => !isTip(w) && w.node.support !== undefined && w.node.support !== null,\n );\n // Effective flag: support text is drawn ONLY when requested AND at least one internal\n // node actually carries a value (the layout reserves the margin for exactly that text).\n const effectiveShowSupport = showSupport && supportNodes.length > 0;\n const supportMargin = effectiveShowSupport\n ? supportNodes.reduce(\n (m, w) => Math.max(m, estimateTextWidth(trimNumber(w.node.support as number), PHYLO_SUPPORT_FONT)),\n 0,\n ) + SUPPORT_GAP\n : 0;\n const padLeft = PADDING + supportMargin;\n\n // Tip-label widths reserve real space on the right so the canvas always contains them.\n const tipLabelW = allWork\n .filter(isTip)\n .reduce((m, w) => Math.max(m, estimateTextWidth(clampLabel(w.node.label, opts.maxLabelChars), PHYLO_LABEL_FONT)), 0);\n const labelReserve = (tipCount > 0 ? PHYLO_LABEL_GAP + tipLabelW : 0) + PADDING;\n\n // Phylogram scale: fit the deepest root-to-tip distance to the available draw width\n // (the genogram's fit-to-container ethos). The width tracks topological depth so a deep\n // tree gets room; MIN_DRAW_W keeps a shallow tree (e.g. a single split) drawable.\n const phylogramScaled = mode === \"phylogram\" && maxDist > 0;\n const drawW = Math.max(MIN_DRAW_W, maxDepth * PHYLO_LEVEL_W);\n const scale = phylogramScaled ? drawW / maxDist : 0;\n\n const xOf = (w: Work): number => {\n if (phylogramScaled) return padLeft + w.dist * scale;\n return padLeft + w.depth * PHYLO_LEVEL_W; // cladogram (or degenerate phylogram)\n };\n for (const w of allWork) w.cx = xOf(w);\n\n // Phylogram-only de-collinearity nudge. A zero/null-length branch lands an INTERNAL child\n // at exactly its parent's x, so the child's clade bar and the parent's clade bar become\n // two collinear verticals (a double-drawn line that reads as an ambiguous polytomy). We\n // push such a child PHYLO_ZERO_NUDGE px right of the parent's FINAL x so its bar lives on\n // its own vertical — preserving the \"directly above the parent\" read (one pixel). A TIP at\n // the parent's x is fine (no clade bar), so it is never nudged. Pre-order so a chain of\n // zero-length internals each clears its own (already-nudged) parent — the monotone\n // cx(child) ≥ cx(parent) invariant is preserved, strictly. Purely positional: the verbatim\n // 0/null length is untouched (it still rides the branch element's <title>).\n if (phylogramScaled) {\n const nudge = (w: Work): void => {\n for (const c of w.children) {\n if (!isTip(c) && c.cx <= w.cx + 1e-6) c.cx = w.cx + PHYLO_ZERO_NUDGE;\n nudge(c);\n }\n };\n nudge(root);\n }\n\n // The alignment line for right-aligned tips. `alignTips` defaults true in cladogram\n // (the defining right-aligned look) and false in phylogram (the x IS the data); setting\n // it false in cladogram drops both the alignment AND the dotted extensions. Internals\n // keep their computed x; only TIPS are pushed to the line. In cladogram the line is the\n // deepest depth-x; in phylogram (alignTips:true) it is the rightmost tip's own x.\n const tipsAligned = alignTips;\n const maxTipX = allWork.filter(isTip).reduce((m, w) => Math.max(m, w.cx), padLeft);\n const alignX = phylogramScaled ? maxTipX : padLeft + maxDepth * PHYLO_LEVEL_W;\n const tipDrawX = (w: Work): number => (tipsAligned ? alignX : w.cx);\n\n // ── Canvas size. ──────────────────────────────────────────────────────────────────────\n const rightmost = tipsAligned ? alignX : allWork.reduce((m, w) => Math.max(m, w.cx), padLeft);\n const treeBottom = top + (tipCount > 0 ? tipCount * PHYLO_ROW_SLOT : PHYLO_ROW_SLOT);\n const scaleBarPx = wantScaleBar && maxDist > 0 ? niceScaleStep(maxDist) * scale : 0;\n const hasScaleBar = wantScaleBar && maxDist > 0 && scaleBarPx > 0;\n const width = Math.ceil(rightmost + labelReserve);\n const height = Math.ceil(treeBottom + (hasScaleBar ? SCALEBAR_ZONE : 0) + PADDING / 2);\n\n // ── Emit nodes (DFS pre-order) + elements. ────────────────────────────────────────────\n const nodes: PhyloLayoutNode[] = [];\n const elements: PhyloElement[] = [];\n\n const branchTitle = (w: Work): string => {\n if (w.inLength !== null) return `${titleLabels.branchLength}: ${trimNumber(w.inLength)}`;\n return titleLabels.branchLength;\n };\n\n // Root stub: a short horizontal lead-in to the root point (left of it), so a root with\n // a single child still reads as a tree origin. Drawn from padLeft − stub to the root x.\n const ROOT_STUB = 14;\n const rootDrawX = isTip(root) ? tipDrawX(root) : root.cx;\n elements.push({\n edgeId: PHYLO_ROOTSTUB_ID_BASE + root.node.id,\n kind: \"root-stub\",\n points: [\n { x: round(Math.max(PADDING / 2, rootDrawX - ROOT_STUB)), y: round(root.cy) },\n { x: round(rootDrawX), y: round(root.cy) },\n ],\n dotted: false,\n length: null,\n title: titleLabels.root,\n });\n\n const emit = (w: Work): void => {\n const tip = isTip(w);\n const isRoot = w === root;\n const drawX = tip ? tipDrawX(w) : w.cx;\n const support = w.node.support === undefined ? null : w.node.support;\n const labelLine = tip && w.node.label !== \"\" ? [clampLabel(w.node.label, opts.maxLabelChars)] : [];\n nodes.push({\n nodeId: w.node.id,\n isTip: tip,\n cx: round(drawX),\n cy: round(w.cy),\n support,\n labelLines: labelLine,\n labelLeft: round(drawX + PHYLO_TIP_R + PHYLO_LABEL_GAP),\n depth: w.depth,\n title: nodeTitle(w.node, tip, isRoot, w.inLength, titleLabels),\n });\n\n // Aligned tip → a dotted EXTENSION from its true branch-end x to the alignment line.\n if (tip && tipsAligned && w.cx < alignX - 1e-6) {\n elements.push({\n edgeId: PHYLO_EXTENSION_ID_BASE + w.node.id,\n kind: \"extension\",\n points: [\n { x: round(w.cx), y: round(w.cy) },\n { x: round(alignX), y: round(w.cy) },\n ],\n dotted: true,\n length: null,\n title: titleLabels.tip,\n });\n }\n\n if (w.children.length === 0) return;\n\n // One shared VERTICAL clade bar at the parent's x, spanning min→max child y.\n const childYs = w.children.map((c) => c.cy);\n const barTop = Math.min(...childYs);\n const barBottom = Math.max(...childYs);\n if (barBottom - barTop > 1e-6) {\n elements.push({\n edgeId: PHYLO_CLADEBAR_ID_BASE + w.node.id,\n kind: \"clade-bar\",\n points: [\n { x: round(w.cx), y: round(barTop) },\n { x: round(w.cx), y: round(barBottom) },\n ],\n dotted: false,\n length: null,\n title: isRoot ? titleLabels.root : titleLabels.clade,\n });\n }\n\n // One HORIZONTAL branch per child: parentX → childX at childY (the rectangular elbow).\n for (const c of w.children) {\n elements.push({\n edgeId: PHYLO_BRANCH_ID_BASE + c.node.id,\n kind: \"branch\",\n points: [\n { x: round(w.cx), y: round(c.cy) },\n { x: round(c.cx), y: round(c.cy) },\n ],\n dotted: false,\n length: c.inLength,\n title: branchTitle(c),\n });\n }\n for (const c of w.children) emit(c);\n };\n emit(root);\n\n // ── Scale bar (phylogram only): a labelled horizontal segment in the dead space below\n // the tree. Its value is a niceScaleStep of the deepest distance. ───────────────────\n let scaleBar: PhyloScaleBar | null = null;\n if (hasScaleBar) {\n const stepLen = niceScaleStep(maxDist);\n const barX = padLeft;\n const barY = treeBottom + SCALEBAR_ZONE / 2;\n scaleBar = {\n length: stepLen,\n x: round(barX),\n y: round(barY),\n pxLength: round(scaleBarPx),\n valueLabel: trimNumber(stepLen),\n };\n elements.push({\n edgeId: PHYLO_SCALEBAR_ID,\n kind: \"scale-bar\",\n points: [\n { x: round(barX), y: round(barY) },\n { x: round(barX + scaleBarPx), y: round(barY) },\n ],\n dotted: false,\n length: stepLen,\n title: `${titleLabels.branchLength}: ${trimNumber(stepLen)}`,\n });\n }\n\n return { width, height, mode, nodes, elements, scaleBar, showSupport: effectiveShowSupport };\n}\n","// Phylo SVG emitter — turns a computed PhyloLayout (./layout.ts) into a SELF-CONTAINED\n// SVG string. Pure (layout in, string out) and deterministic; it draws EXACTLY what the\n// layout computed (the overlap harness proves the layout; this emitter is pinned to it).\n//\n// Hard requirements (house rules):\n// - XML-ESCAPING of EVERY interpolated text — labels/titles are author-controlled and\n// the SVG may be injected via innerHTML or embedded in PDFs;\n// - LITERAL presentation attributes only (hex colors, explicit font-family, inline\n// dasharray): a standalone SVG has no stylesheet, no currentColor, no <defs>/<marker>;\n// - every coordinate goes through round() — 2-decimal, byte-deterministic output.\n//\n// Drawing: rectangular (\"square elbow\") tree — a vertical clade bar per internal node + a\n// horizontal branch per child; aligned tips get a dotted extension leader; a small filled\n// dot marks each node point; tip labels sit left-anchored to the right of the tip; support\n// values (when showSupport baked the margin in) draw text-anchor:end just left of the\n// internal node. The phylogram scale bar is a first-class drawn element below the tree.\n//\n// Hooks: `<g data-node-id=\"n<id>\">` per node (direct-child verbatim <title>);\n// `<g data-edge-id=\"<n>\">` per element (namespaced ids, see ./layout.ts).\n\nimport { FONT_FAMILY, legendBlock, xmlEscape, LEGEND_SWATCH_W, type LegendEntry } from \"../core\";\nimport {\n PHYLO_LABEL_FONT,\n PHYLO_SUPPORT_FONT,\n type PhyloElement,\n type PhyloLayout,\n type PhyloLayoutNode,\n} from \"./layout\";\nimport { PHYLO_SVG_LABELS_EN, type PhyloSvgLabels } from \"./labels\";\n\n// Literal ink colors (zinc ramp on white — matches every other compasso emitter).\nconst GLYPH_STROKE = \"#52525b\";\nconst LABEL_FILL = \"#3f3f46\";\nconst EDGE_INK = \"#71717a\";\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\nexport interface PhyloSvgOptions {\n /** Set false to suppress the legend (compact preview); default true. */\n legend?: boolean;\n /** Display vocabulary (legend/accessibility) — English default; see locale packs. */\n labels?: PhyloSvgLabels;\n}\n\n// ── Node points + tip labels + support text ───────────────────────────────────────────\n\nfunction nodeSvg(n: PhyloLayoutNode, showSupport: boolean): string {\n const pieces: string[] = [`<title>${xmlEscape(n.title)}</title>`];\n // A small filled dot marks every node point (tip and internal).\n pieces.push(`<circle cx=\"${n.cx}\" cy=\"${n.cy}\" r=\"2.5\" fill=\"${GLYPH_STROKE}\"/>`);\n // Tip label: single clamped line, left-anchored right of the tip point.\n if (n.labelLines.length > 0) {\n pieces.push(\n `<text x=\"${n.labelLeft}\" y=\"${round(n.cy + PHYLO_LABEL_FONT * 0.32)}\" font-family=\"${FONT_FAMILY}\" font-size=\"${PHYLO_LABEL_FONT}\" fill=\"${LABEL_FILL}\">${xmlEscape(n.labelLines[0]!)}</text>`,\n );\n }\n // Internal support value: text-anchor:end just left of the node (margin reserved in\n // the layout). Drawn only when requested AND the value is present.\n if (showSupport && !n.isTip && n.support !== null) {\n pieces.push(\n `<text x=\"${round(n.cx - 4)}\" y=\"${round(n.cy - 3)}\" text-anchor=\"end\" font-family=\"${FONT_FAMILY}\" font-size=\"${PHYLO_SUPPORT_FONT}\" fill=\"${LABEL_FILL}\">${xmlEscape(String(n.support))}</text>`,\n );\n }\n return `<g data-node-id=\"n${n.nodeId}\">${pieces.join(\"\")}</g>`;\n}\n\n// ── Connector elements (clade bars, branches, dotted extensions, root stub, scale bar) ──\n\nfunction elementSvg(el: PhyloElement): string {\n const a = el.points[0]!;\n const b = el.points[1]!;\n const dash = el.dotted ? ` stroke-dasharray=\"2,3\"` : \"\";\n const opacity = el.kind === \"extension\" ? \"0.5\" : \"0.75\";\n return (\n `<g data-edge-id=\"${el.edgeId}\"><title>${xmlEscape(el.title)}</title>` +\n `<line x1=\"${a.x}\" y1=\"${a.y}\" x2=\"${b.x}\" y2=\"${b.y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"${opacity}\"${dash}/></g>`\n );\n}\n\n// ── Scale-bar value label (drawn separately from its segment element) ──────────────────\n\nfunction scaleBarLabelSvg(layout: PhyloLayout): string {\n const bar = layout.scaleBar;\n if (bar === null) return \"\";\n // Small end ticks frame the bar; the value sits centered above it.\n const tick = (x: number): string =>\n `<line x1=\"${x}\" y1=\"${round(bar.y - 3)}\" x2=\"${x}\" y2=\"${round(bar.y + 3)}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>`;\n return (\n tick(bar.x) +\n tick(round(bar.x + bar.pxLength)) +\n `<text x=\"${round(bar.x + bar.pxLength / 2)}\" y=\"${round(bar.y - 6)}\" text-anchor=\"middle\" font-family=\"${FONT_FAMILY}\" font-size=\"${PHYLO_SUPPORT_FONT}\" fill=\"${LABEL_FILL}\">${xmlEscape(bar.valueLabel)}</text>`\n );\n}\n\n// ── Legend mini-swatches ───────────────────────────────────────────────────────────────\n\nfunction supportSwatch(x: number, y: number): string {\n const cx = round(x + LEGEND_SWATCH_W / 2);\n return (\n `<circle cx=\"${cx}\" cy=\"${y}\" r=\"2.5\" fill=\"${GLYPH_STROKE}\"/>` +\n `<text x=\"${round(cx + 5)}\" y=\"${round(y + PHYLO_SUPPORT_FONT * 0.32)}\" font-family=\"${FONT_FAMILY}\" font-size=\"${PHYLO_SUPPORT_FONT}\" fill=\"${LABEL_FILL}\">95</text>`\n );\n}\n\nfunction scaleSwatch(x: number, y: number): string {\n return `<line x1=\"${round(x)}\" y1=\"${y}\" x2=\"${round(x + LEGEND_SWATCH_W)}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>`;\n}\n\nfunction alignedTipSwatch(x: number, y: number): string {\n return `<line x1=\"${round(x)}\" y1=\"${y}\" x2=\"${round(x + LEGEND_SWATCH_W)}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.5\" stroke-dasharray=\"2,3\"/>`;\n}\n\n/**\n * Emits a self-contained SVG for a computed phylo layout. Pure + deterministic.\n * Coordinates come straight from the layout; all interpolated text is XML-escaped; all\n * presentation attributes are literal. The legend is minimal and used-keys-only: a phylo\n * tree is self-labelling (tips carry names), so often it has zero entries.\n *\n * `showSupport` is read off the layout's reserved margin: the emitter draws the support\n * text only when a support value was reserved (any internal node has a non-null support\n * AND the support margin > PADDING). This keeps the emitter pinned to the layout — it\n * never reserves what the layout didn't, nor draws what it can't fit.\n */\nexport function phyloLayoutSvg(layout: PhyloLayout, opts: PhyloSvgOptions = {}): string {\n const labels = opts.labels ?? PHYLO_SVG_LABELS_EN;\n // showSupport is a layout-affecting option (it reserves left margin), so the layout\n // bakes the resolved flag in — the emitter reads it off the layout and never re-decides.\n const showSupport = layout.showSupport;\n\n const parts: string[] = [];\n\n // Connectors first, then node points/labels — points sit on top.\n for (const el of layout.elements) parts.push(elementSvg(el));\n parts.push(scaleBarLabelSvg(layout));\n for (const n of layout.nodes) parts.push(nodeSvg(n, showSupport));\n\n // ── Used-keys-only legend (core legendBlock; `legend:false` suppresses). ──────────────\n let width = layout.width;\n let height = layout.height;\n if (opts.legend !== false && layout.nodes.length > 0) {\n const entries: LegendEntry[] = [];\n if (showSupport) entries.push({ swatch: supportSwatch, label: labels.support });\n if (layout.scaleBar !== null) entries.push({ swatch: scaleSwatch, label: labels.scaleBar });\n if (layout.elements.some((e) => e.kind === \"extension\")) {\n entries.push({ swatch: alignedTipSwatch, label: labels.alignedTip });\n }\n const block = legendBlock(entries, layout.height);\n if (block.svg !== \"\") {\n parts.push(block.svg);\n width = Math.max(width, block.width);\n height = block.height;\n }\n }\n\n const w = Math.ceil(width);\n const h = Math.ceil(height);\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${w} ${h}\" width=\"${w}\" height=\"${h}\" role=\"img\" aria-label=\"${xmlEscape(labels.ariaLabel[layout.mode])}\">` +\n parts.join(\"\") +\n `</svg>`\n );\n}\n","// One-call phylo render: input → { svg, layout }. Thin, honest wiring: validate (throw on\n// an un-layout-able tree — never repair), compute the pure layout, emit. Callers needing\n// finer control use computePhyloLayout + phyloLayoutSvg directly (the layout result\n// supports hit-testing / decorating the diagram).\n\nimport { computePhyloLayout, type PhyloLayout, type PhyloLayoutOptions } from \"./layout\";\nimport { phyloLayoutSvg } from \"./svg\";\nimport type { PhyloSvgLabels } from \"./labels\";\nimport type { PhyloInput } from \"./types\";\n\nexport interface PhyloRenderOptions extends PhyloLayoutOptions {\n /** Set false to suppress the legend (compact preview); default true. */\n legend?: boolean;\n /** Display vocabulary for the emitter (legend/accessibility) — English default. */\n svgLabels?: PhyloSvgLabels;\n}\n\nexport interface PhyloRenderResult {\n /** Self-contained SVG (numeric width/height + matching viewBox — PDF-embedder safe). */\n svg: string;\n /** The computed layout, for callers that decorate or hit-test the diagram. */\n layout: PhyloLayout;\n}\n\n/**\n * Renders a phylo input to a self-contained SVG string. Deterministic: same data → same\n * SVG (array order never matters; a node's children are drawn in declared edge order, the\n * analyst's ladderization choice, never auto-sorted). Throws PhyloValidationError —\n * carrying EVERY issue, deterministically sorted — on an un-layout-able tree (cycle,\n * forest, DAG, dangling reference). Empty input yields an empty-but-valid SVG.\n */\nexport function phyloSvg(input: PhyloInput, opts: PhyloRenderOptions = {}): PhyloRenderResult {\n const layout = computePhyloLayout(input, {\n ...(opts.mode !== undefined ? { mode: opts.mode } : {}),\n ...(opts.alignTips !== undefined ? { alignTips: opts.alignTips } : {}),\n ...(opts.showSupport !== undefined ? { showSupport: opts.showSupport } : {}),\n ...(opts.scaleBar !== undefined ? { scaleBar: opts.scaleBar } : {}),\n ...(opts.maxLabelChars !== undefined ? { maxLabelChars: opts.maxLabelChars } : {}),\n ...(opts.titleLabels !== undefined ? { titleLabels: opts.titleLabels } : {}),\n });\n const svg = phyloLayoutSvg(layout, {\n ...(opts.legend === false ? { legend: false } : {}),\n ...(opts.svgLabels !== undefined ? { labels: opts.svgLabels } : {}),\n });\n return { svg, layout };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { legendBlock, xmlEscape, FONT_FAMILY, LEGEND_SWATCH_W, wrapLabelBalanced, clampLabel, estimateTextWidth, wrapLabel, CHAR_W } from './chunk-O3BT2O42.js';
1
+ import { legendBlock, xmlEscape, FONT_FAMILY, LEGEND_SWATCH_W, wrapLabelBalanced, clampLabel, estimateTextWidth, wrapLabel, CHAR_W } from './chunk-DVLWT565.js';
2
2
 
3
3
  // src/fault-tree/types.ts
4
4
  var FAULT_TREE_EVENT_KINDS = [
@@ -699,5 +699,5 @@ function faultTreeSvg(input, opts = {}) {
699
699
  }
700
700
 
701
701
  export { CODE_FONT, FAULT_TREE_EVENT_KINDS, FAULT_TREE_SVG_LABELS_EN, FAULT_TREE_TITLE_LABELS_EN, FT_BUS_ID_BASE, FT_CONDITION_ID_BASE, FT_DROP_ID_BASE, FT_LABEL_FONT, FT_LABEL_LINE_H, FT_RISER_ID_BASE, FT_STEM_ID_BASE, FaultTreeValidationError, GATE_TYPES, LABEL_GAP, computeFaultTreeLayout, faultTreeIssues, faultTreeLayoutSvg, faultTreeSvg, validateFaultTree };
702
- //# sourceMappingURL=chunk-LRHHUJFZ.js.map
703
- //# sourceMappingURL=chunk-LRHHUJFZ.js.map
702
+ //# sourceMappingURL=chunk-RDH4XHA2.js.map
703
+ //# sourceMappingURL=chunk-RDH4XHA2.js.map