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.
- package/README.md +115 -5
- package/dist/{chunk-ZBDABVIO.js → chunk-2NDET6O5.js} +3 -3
- package/dist/{chunk-ZBDABVIO.js.map → chunk-2NDET6O5.js.map} +1 -1
- package/dist/{chunk-Q6DVTCXD.js → chunk-3RGYLVTN.js} +18 -6
- package/dist/chunk-3RGYLVTN.js.map +1 -0
- package/dist/chunk-BM7UJBK5.js +680 -0
- package/dist/chunk-BM7UJBK5.js.map +1 -0
- package/dist/chunk-DVLWT565.js +372 -0
- package/dist/chunk-DVLWT565.js.map +1 -0
- package/dist/{chunk-F47C6ZEB.js → chunk-JBDA7E2O.js} +3 -3
- package/dist/{chunk-F47C6ZEB.js.map → chunk-JBDA7E2O.js.map} +1 -1
- package/dist/chunk-MIJTBYX2.js +982 -0
- package/dist/chunk-MIJTBYX2.js.map +1 -0
- package/dist/{chunk-JP4N42AY.js → chunk-PJHLWSGD.js} +3 -3
- package/dist/{chunk-JP4N42AY.js.map → chunk-PJHLWSGD.js.map} +1 -1
- package/dist/{chunk-LRHHUJFZ.js → chunk-RDH4XHA2.js} +3 -3
- package/dist/{chunk-LRHHUJFZ.js.map → chunk-RDH4XHA2.js.map} +1 -1
- package/dist/{chunk-UJVU7B44.js → chunk-WEHUSHVI.js} +31 -51
- package/dist/chunk-WEHUSHVI.js.map +1 -0
- package/dist/{chunk-RWPGGWO5.js → chunk-Z66YUOUM.js} +34 -10
- package/dist/chunk-Z66YUOUM.js.map +1 -0
- package/dist/core/index.cjs +247 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +94 -2
- package/dist/core/index.d.ts +94 -2
- package/dist/core/index.js +1 -1
- package/dist/ecomap/index.cjs +34 -11
- package/dist/ecomap/index.cjs.map +1 -1
- package/dist/ecomap/index.d.cts +12 -0
- package/dist/ecomap/index.d.ts +12 -0
- package/dist/ecomap/index.js +2 -2
- package/dist/fault-tree/index.d.cts +2 -2
- package/dist/fault-tree/index.d.ts +2 -2
- package/dist/fault-tree/index.js +2 -2
- package/dist/fishbone/index.js +2 -2
- package/dist/genogram/index.cjs +57 -7
- package/dist/genogram/index.cjs.map +1 -1
- package/dist/genogram/index.d.cts +22 -6
- package/dist/genogram/index.d.ts +22 -6
- package/dist/genogram/index.js +2 -2
- package/dist/geometry-P-XGqGe7.d.cts +8 -0
- package/dist/geometry-P-XGqGe7.d.ts +8 -0
- package/dist/grid-BMgUSly1.d.cts +79 -0
- package/dist/grid-BMgUSly1.d.ts +79 -0
- package/dist/index.cjs +2360 -395
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -7
- package/dist/index.d.ts +14 -7
- package/dist/index.js +10 -8
- package/dist/{kinship-DqEklrDN.d.ts → kinship-BF90HyyS.d.ts} +1 -1
- package/dist/{kinship-Dy_ijjJV.d.cts → kinship-BOUss5cT.d.cts} +1 -1
- package/dist/{labels-RtFw9tX1.d.cts → labels-B0aOMbHy.d.cts} +12 -0
- package/dist/{labels-RtFw9tX1.d.ts → labels-B0aOMbHy.d.ts} +12 -0
- package/dist/labels-Br8yjc3C.d.cts +29 -0
- package/dist/labels-Br8yjc3C.d.ts +29 -0
- package/dist/{labels-DNqRkWuI.d.ts → labels-CuLbFyrz.d.ts} +1 -1
- package/dist/labels-D1v1RWZd.d.cts +97 -0
- package/dist/labels-D1v1RWZd.d.ts +97 -0
- package/dist/{labels-CBQ_3Ec9.d.cts → labels-DhQe7I8m.d.cts} +1 -1
- package/dist/layered-DmZluAqe.d.cts +72 -0
- package/dist/layered-DmZluAqe.d.ts +72 -0
- package/dist/locales/pt-br.cjs +53 -0
- package/dist/locales/pt-br.cjs.map +1 -1
- package/dist/locales/pt-br.d.cts +11 -5
- package/dist/locales/pt-br.d.ts +11 -5
- package/dist/locales/pt-br.js +50 -1
- package/dist/locales/pt-br.js.map +1 -1
- package/dist/org-chart/index.cjs +138 -94
- package/dist/org-chart/index.cjs.map +1 -1
- package/dist/org-chart/index.d.cts +24 -33
- package/dist/org-chart/index.d.ts +24 -33
- package/dist/org-chart/index.js +2 -2
- package/dist/pedigree/index.d.cts +6 -6
- package/dist/pedigree/index.d.ts +6 -6
- package/dist/pedigree/index.js +2 -2
- package/dist/phylo/index.d.cts +2 -2
- package/dist/phylo/index.d.ts +2 -2
- package/dist/phylo/index.js +2 -2
- package/dist/prisma/index.cjs +882 -0
- package/dist/prisma/index.cjs.map +1 -0
- package/dist/prisma/index.d.cts +174 -0
- package/dist/prisma/index.d.ts +174 -0
- package/dist/prisma/index.js +4 -0
- package/dist/prisma/index.js.map +1 -0
- package/dist/{text-DuO_PwYw.d.cts → text-DDVzpwPZ.d.cts} +1 -8
- package/dist/{text-DuO_PwYw.d.ts → text-DDVzpwPZ.d.ts} +1 -8
- package/dist/{types-BnMG7TCd.d.cts → types-jE2fdM1t.d.cts} +8 -0
- package/dist/{types-BnMG7TCd.d.ts → types-jE2fdM1t.d.ts} +8 -0
- package/dist/uml/index.cjs +1214 -0
- package/dist/uml/index.cjs.map +1 -0
- package/dist/uml/index.d.cts +189 -0
- package/dist/uml/index.d.ts +189 -0
- package/dist/uml/index.js +4 -0
- package/dist/uml/index.js.map +1 -0
- package/package.json +28 -2
- package/dist/chunk-O3BT2O42.js +0 -145
- package/dist/chunk-O3BT2O42.js.map +0 -1
- package/dist/chunk-Q6DVTCXD.js.map +0 -1
- package/dist/chunk-RWPGGWO5.js.map +0 -1
- package/dist/chunk-UJVU7B44.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/uml/types.ts","../src/uml/validate.ts","../src/uml/labels.ts","../src/uml/layout.ts","../src/uml/svg.ts","../src/uml/render.ts"],"names":["raw","portPts","pts","edgeId","round"],"mappings":"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","file":"chunk-MIJTBYX2.js","sourcesContent":["// UML class diagram input model — declared facts only.\n// compasso does NOT compute UML positions: the caller supplies (col, row) for\n// every class. packGrid guarantees zero box overlap; edges route in box-free\n// gutter channels. This is the honest, overlap-provable answer for a general\n// graph where auto-layout cannot be proven overlap-free (see docs/design/prisma-uml.md).\n\n// ── Visibility ────────────────────────────────────────────────────────────────\n\nexport const UML_VISIBILITIES = [\"public\", \"private\", \"protected\", \"package\"] as const;\nexport type UmlVisibility = (typeof UML_VISIBILITIES)[number];\n\n/** Universal OMG notation glyphs — NOT localized. */\nexport const UML_VIS_GLYPH: Record<UmlVisibility, string> = {\n public: \"+\",\n private: \"-\",\n protected: \"#\",\n package: \"~\",\n};\n\n// ── Feature (attribute / operation line) ──────────────────────────────────────\n\nexport interface UmlFeature {\n /** null = no visibility marker drawn. */\n visibility: UmlVisibility | null;\n /**\n * Verbatim signature text — drawn AS GIVEN, NEVER parsed.\n * e.g. \"name: String\" / \"getName(): String\".\n */\n text: string;\n /** When true, a <line> underline is drawn under the text run. */\n isStatic?: boolean;\n}\n\n// ── Class ─────────────────────────────────────────────────────────────────────\n\nexport interface UmlClass {\n id: number;\n /** Verbatim name; italic rendering when isAbstract. */\n name: string;\n /**\n * «interface»/«enumeration»/«abstract» line above name; verbatim, drawn only\n * when declared (not null). Caller includes the guillemets when desired.\n */\n stereotype: string | null;\n isAbstract?: boolean;\n attributes: UmlFeature[];\n operations: UmlFeature[];\n /**\n * DECLARED grid cell (the escape hatch for a general graph).\n * Non-negative integers required on every class.\n */\n col: number;\n row: number;\n /** <title> override. */\n title?: string;\n}\n\n// ── Relationship ──────────────────────────────────────────────────────────────\n\nexport const UML_RELATIONSHIPS = [\n \"association\",\n \"directed-association\",\n \"aggregation\",\n \"composition\",\n \"generalization\",\n \"realization\",\n \"dependency\",\n] as const;\nexport type UmlRelationshipKind = (typeof UML_RELATIONSHIPS)[number];\n\nexport interface UmlRelationship {\n id: number;\n kind: UmlRelationshipKind;\n /** Direction per-kind via RELATION_GLYPHS; generalization: source=subclass, target=superclass. */\n sourceId: number;\n targetId: number;\n /** Verbatim multiplicity strings — NEVER parsed/validated. null = none drawn. */\n sourceMultiplicity: string | null;\n targetMultiplicity: string | null;\n /** Verbatim role names at the ends. null = none drawn. */\n sourceRole: string | null;\n targetRole: string | null;\n /** Verbatim relationship name drawn at mid-edge. null = none drawn. */\n label: string | null;\n /** <title> override. */\n title?: string;\n}\n\n// ── Glyph map ─────────────────────────────────────────────────────────────────\n\n/**\n * The five distinct glyph shapes used for UML relationship ends.\n * \"none\" = plain line terminus (no arrowhead or decoration).\n */\nexport type GlyphKind =\n | \"none\"\n | \"open-arrow\"\n | \"hollow-triangle\"\n | \"hollow-diamond\"\n | \"solid-diamond\";\n\n/**\n * RELATION_GLYPHS — the single source of truth mapping a relationship kind to\n * its standard UML end decorations and line style.\n * The caller picks a KIND and the standard glyph follows — they cannot mis-state\n * a glyph (the honesty-rule encoding).\n *\n * Glyph placement convention:\n * - aggregation/composition: diamond at the WHOLE (source side)\n * - generalization/realization: triangle at the SUPERTYPE (target side)\n * - directed-association/dependency: open-arrow at the TARGET\n */\nexport const RELATION_GLYPHS: Record<\n UmlRelationshipKind,\n { sourceEnd: GlyphKind; targetEnd: GlyphKind; line: \"solid\" | \"dashed\" }\n> = {\n association: { sourceEnd: \"none\", targetEnd: \"none\", line: \"solid\" },\n \"directed-association\": { sourceEnd: \"none\", targetEnd: \"open-arrow\", line: \"solid\" },\n aggregation: { sourceEnd: \"hollow-diamond\", targetEnd: \"none\", line: \"solid\" },\n composition: { sourceEnd: \"solid-diamond\", targetEnd: \"none\", line: \"solid\" },\n generalization: { sourceEnd: \"none\", targetEnd: \"hollow-triangle\", line: \"solid\" },\n realization: { sourceEnd: \"none\", targetEnd: \"hollow-triangle\", line: \"dashed\" },\n dependency: { sourceEnd: \"none\", targetEnd: \"open-arrow\", line: \"dashed\" },\n};\n\n// ── Input ─────────────────────────────────────────────────────────────────────\n\nexport interface UmlInput {\n classes: UmlClass[];\n relationships: UmlRelationship[];\n}\n","// UML class-diagram validation — REJECT-WITH-CODES, never repair.\n// A class diagram is an authoritative model artifact; drawing a structurally\n// invalid diagram misstates the model. Three-phase pipeline:\n// (0) duplicate-id — short-circuit. First-occurrence-wins maps make every\n// downstream rule depend on array order; we report ONLY duplicates and stop.\n// (1) reference / semantic rules: unknown-endpoint, negative-cell, cell-collision,\n// self-generalization.\n// (2) graph rules (generalization-cycle) — gated on duplicate-id + unknown-endpoint\n// (phantom/ambiguous nodes corrupt traversal). Self-association is LEGAL and\n// drawn as a side-loop — it is NEVER a graph error here.\n//\n// Empty input (no classes AND no relationships) → valid empty SVG, never throws.\n\nimport type { UmlClass, UmlInput, UmlRelationship, UmlRelationshipKind } from \"./types\";\n\nexport type UmlIssueCode =\n | \"duplicate-id\"\n | \"unknown-endpoint\"\n | \"negative-cell\"\n | \"cell-collision\"\n | \"self-generalization\"\n | \"generalization-cycle\"\n | \"too-many-side-edges\";\n\nexport interface UmlIssue {\n code: UmlIssueCode;\n message: string;\n}\n\nexport class UmlValidationError extends Error {\n readonly issues: readonly UmlIssue[];\n constructor(issues: readonly UmlIssue[]) {\n super(`invalid UML class diagram: ${issues.map((i) => i.message).join(\"; \")}`);\n this.name = \"UmlValidationError\";\n this.issues = issues;\n }\n}\n\nfunction sortIssues(issues: readonly UmlIssue[]): readonly UmlIssue[] {\n const unique = new Map<string, UmlIssue>();\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\n ? a.code < b.code\n ? -1\n : 1\n : a.message < b.message\n ? -1\n : a.message > b.message\n ? 1\n : 0,\n );\n}\n\nconst GRAPH_BLOCKING: ReadonlySet<UmlIssueCode> = new Set<UmlIssueCode>([\n \"duplicate-id\",\n \"unknown-endpoint\",\n]);\n\n/** Inheritance-only edge kinds: the cycle check only walks these. */\nconst INHERITANCE_KINDS: ReadonlySet<UmlRelationshipKind> = new Set<UmlRelationshipKind>([\n \"generalization\",\n \"realization\",\n]);\n\n/**\n * Computes ALL validation issues for the input, deduplicated and sorted deterministically.\n * Empty input → []. Empty SVG is always valid.\n */\nexport function umlIssues(input: UmlInput): readonly UmlIssue[] {\n if (input.classes.length === 0 && input.relationships.length === 0) return [];\n\n const issues: UmlIssue[] = [];\n const push = (code: UmlIssueCode, message: string): void => {\n issues.push({ code, message });\n };\n\n // ── Phase 0: duplicate ids (classes namespace + relationships namespace) ─────\n const classById = new Map<number, UmlClass>();\n const dupClassIds = new Set<number>();\n for (const c of input.classes) {\n if (classById.has(c.id)) dupClassIds.add(c.id);\n else classById.set(c.id, c);\n }\n for (const id of [...dupClassIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate class id ${id}`);\n }\n\n const relById = new Map<number, UmlRelationship>();\n const dupRelIds = new Set<number>();\n for (const r of input.relationships) {\n if (relById.has(r.id)) dupRelIds.add(r.id);\n else relById.set(r.id, r);\n }\n for (const id of [...dupRelIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate relationship id ${id}`);\n }\n\n // Duplicate ids short-circuit: downstream rules depend on first-occurrence-wins maps.\n if (issues.length > 0) return sortIssues(issues);\n\n const rels = [...relById.values()].sort((a, b) => a.id - b.id);\n\n // ── Phase 1: reference / semantic rules ──────────────────────────────────────\n\n // unknown-endpoint\n for (const r of rels) {\n if (!classById.has(r.sourceId)) {\n push(\"unknown-endpoint\", `relationship ${r.id} sourceId ${r.sourceId} is not a declared class`);\n }\n if (!classById.has(r.targetId)) {\n push(\"unknown-endpoint\", `relationship ${r.id} targetId ${r.targetId} is not a declared class`);\n }\n }\n\n // negative-cell: col/row must be non-negative integers (catches NaN, Infinity, floats)\n for (const c of [...classById.values()].sort((a, b) => a.id - b.id)) {\n if (!Number.isInteger(c.col) || c.col < 0) {\n push(\"negative-cell\", `class ${c.id} col ${c.col} must be a non-negative integer`);\n }\n if (!Number.isInteger(c.row) || c.row < 0) {\n push(\"negative-cell\", `class ${c.id} row ${c.row} must be a non-negative integer`);\n }\n }\n\n // cell-collision: two classes same (col, row)\n const cellKey = (c: UmlClass): string => `${c.col},${c.row}`;\n const cellToClasses = new Map<string, number[]>();\n for (const c of [...classById.values()].sort((a, b) => a.id - b.id)) {\n const key = cellKey(c);\n const arr = cellToClasses.get(key) ?? [];\n arr.push(c.id);\n cellToClasses.set(key, arr);\n }\n for (const [key, ids] of [...cellToClasses.entries()].sort()) {\n if (ids.length > 1) {\n push(\n \"cell-collision\",\n `classes ${ids.sort((a, b) => a - b).join(\", \")} all declare cell (${key})`,\n );\n }\n }\n\n // self-generalization: generalization/realization from a class to itself.\n // Self-ASSOCIATION is LEGAL (reflexive reference) and never flagged here.\n for (const r of rels) {\n if (\n (r.kind === \"generalization\" || r.kind === \"realization\") &&\n r.sourceId === r.targetId\n ) {\n push(\n \"self-generalization\",\n `relationship ${r.id} is a ${r.kind} from class ${r.sourceId} to itself`,\n );\n }\n }\n\n // ── Phase 2: generalization-cycle — gated on GRAPH_BLOCKING codes ────────────\n if (!issues.some((i) => GRAPH_BLOCKING.has(i.code))) {\n // Adjacency: source → target over generalization/realization only.\n // Self-associations (sourceId === targetId) are already legal; self-generalizations\n // were caught above. The DFS skips self-edges defensively.\n const inheritanceChildren = new Map<number, number[]>();\n for (const r of rels) {\n if (!INHERITANCE_KINDS.has(r.kind)) continue;\n if (r.sourceId === r.targetId) continue; // self-generalization already flagged\n const arr = inheritanceChildren.get(r.sourceId) ?? [];\n arr.push(r.targetId);\n inheritanceChildren.set(r.sourceId, arr);\n }\n for (const arr of inheritanceChildren.values()) arr.sort((a, b) => a - b);\n\n // Iterative coloring DFS — identical pattern to org-chart/validate.ts.\n const color = new Map<number, 0 | 1 | 2>(); // 0/absent=white, 1=gray, 2=black\n const seenCycles = new Set<string>();\n\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 = inheritanceChildren.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(\n \"generalization-cycle\",\n `generalization cycle: ${[...rotated, rotated[0]!].join(\" → \")}`,\n );\n }\n } else if (c === 0) {\n color.set(child, 1);\n stack.push({ id: child, nextChild: 0 });\n }\n }\n };\n\n for (const c of [...classById.values()].sort((a, b) => a.id - b.id)) {\n if ((color.get(c.id) ?? 0) === 0) dfs(c.id);\n }\n }\n\n return sortIssues(issues);\n}\n\n/** Throws UmlValidationError (carrying ALL issues) when the input is invalid. */\nexport function validateUml(input: UmlInput): void {\n const issues = umlIssues(input);\n if (issues.length > 0) throw new UmlValidationError(issues);\n}\n\n/**\n * Build a `too-many-side-edges` issue. A box side can hold only finitely many incident-edge\n * ports: the router spreads N ports along the side as a symmetric zigzag of pitch `pitch`, so the\n * outermost port sits `floor(N/2)·pitch` from the side midpoint (up AND down). Beyond the side's\n * CLEAR vertical band the outermost port's stub/glyph spills past the box and crosses a neighbour —\n * a segment-through-box / glyph-box hit. N arrowhead glyphs simply cannot fit on one short box\n * edge; the honest, house-consistent answer is to REJECT (mirroring org-chart's\n * `too-many-matrix-edges`), never to mis-draw. The message names the class + side + observed\n * count + capacity so the author knows which fan-in to split. `boxH`/`rowGap`/`pitch` are the\n * measured geometry the router uses, so the cap is the TRUE clean capacity for THAT box.\n *\n * The clear band is `boxH/2 + rowGap/2 − glyphHalf`:\n * - `boxH/2` — the box's own half-height (ports start on the box edge).\n * - `rowGap/2` — only HALF the box-free row gutter, NOT the whole gap. The gutter above (and\n * below) the box is SHARED with the neighbouring row's box, which may ALSO fan in on the same\n * side and spill its own ports DOWN (resp. up) into that same gutter. If each box could claim\n * the WHOLE gutter, two adjacent boxes' outermost ports/glyphs would meet in the middle of the\n * shared gutter (a glyph-glyph hit between edges targeting DIFFERENT boxes — the residual #4\n * class). Capping each box at half the gutter guarantees the two spills meet at most at the\n * gutter midline, never overlapping.\n * - `−glyphHalf` — the outermost port carries a glyph whose AABB extends `glyphHalf` PAST the\n * port-y; reserving it keeps the glyph (not just the port stub) inside the half-gutter, so it\n * can never dip across the midline into the neighbour's half (nor into a full-column-wide\n * neighbour box).\n * floor(N/2) ≤ K ⇒ N ≤ 2K+1, with K = floor((boxH/2 + rowGap/2 − glyphHalf) / pitch). K is\n * clamped ≥ 0 so a sub-glyph box still admits the single centre port (offset 0).\n */\nexport function sideCapacity(boxH: number, rowGap: number, pitch: number, glyphHalf: number): number {\n const clear = boxH / 2 + rowGap / 2 - glyphHalf;\n const k = Math.max(0, Math.floor(clear / pitch));\n return 2 * k + 1;\n}\n\n/** Construct the `too-many-side-edges` issue for an over-capacity box side. */\nexport function sideCapacityIssue(\n classId: number,\n side: \"left\" | \"right\",\n count: number,\n capacity: number,\n): UmlIssue {\n return {\n code: \"too-many-side-edges\",\n message: `class ${classId} has ${count} edges on its ${side} side — at most ${capacity} fit without a port stub spilling through a neighbouring box`,\n };\n}\n","// UML class-diagram display vocabularies. Split into TitleLabels (woven into <title>s\n// by the layout) and SvgLabels (drawn by the emitter: legend, aria). English defaults\n// here; pt-BR in src/locales/pt-br.ts (anti-drift import pattern in tests).\n\nimport type { UmlRelationshipKind, UmlVisibility } from \"./types\";\n\n/** Labels woven into element/box <title>s by the LAYOUT (verbatim-preserving). */\nexport interface UmlTitleLabels {\n /** Display name for each relationship kind (in <title>s). */\n kinds: Record<UmlRelationshipKind, string>;\n /** Display name for each visibility level (in feature <title>s). */\n visibilities: Record<UmlVisibility, string>;\n}\n\nexport const UML_TITLE_LABELS_EN: UmlTitleLabels = {\n kinds: {\n association: \"association\",\n \"directed-association\": \"directed association\",\n aggregation: \"aggregation\",\n composition: \"composition\",\n generalization: \"generalization\",\n realization: \"realization\",\n dependency: \"dependency\",\n },\n visibilities: {\n public: \"public\",\n private: \"private\",\n protected: \"protected\",\n package: \"package\",\n },\n};\n\n/** Labels drawn by the SVG EMITTER (legend entries, accessibility text). */\nexport interface UmlSvgLabels {\n legend: Record<UmlRelationshipKind, string>;\n ariaLabel: string;\n}\n\nexport const UML_SVG_LABELS_EN: UmlSvgLabels = {\n legend: {\n association: \"Association\",\n \"directed-association\": \"Directed association\",\n aggregation: \"Aggregation\",\n composition: \"Composition\",\n generalization: \"Generalization\",\n realization: \"Realization\",\n dependency: \"Dependency\",\n },\n ariaLabel: \"UML class diagram\",\n};\n","// UML class-diagram layout — DECLARED-POSITION model.\n//\n// The caller supplies (col, row) for every class. packGrid guarantees zero box overlap.\n// Edges route in box-free gutter channels between grid cells; every routed segment runs\n// on a gutter centerline (never inside a cell) or is a port stub terminating ON the box\n// perimeter, so segment-through-box-interior is provably zero.\n//\n// ── The routing thesis (uniform across ALL edge cases) ───────────────────────\n// An edge NEVER transits cell airspace. It:\n// 1. exits its source box on a SIDE (left or right) into the ADJACENT vertical gutter,\n// 2. travels ONLY on gutter centerlines (vertical gutters between columns, horizontal\n// gutters between rows), turning only at gutter intersections,\n// 3. enters the target on a SIDE (left or right) from an adjacent vertical gutter.\n// Because every box exits/enters horizontally, the terminal (glyph-bearing) segment is\n// ALWAYS normal to a vertical side → the glyph faces left/right and can never be\n// collapsed or rotated by waypoint dedup. The column's/row's own centerline is NEVER a\n// transit lane (a third box may sit on it); only the box-free gutters between cells are.\n//\n// Concrete route (3 gutters, degenerating cleanly):\n// src --H stub--> srcV gutter --V--> H gutter --H--> tgtV gutter --V--> H stub--> tgt\n// For same-column endpoints srcV == tgtV (one vertical gutter beside the column, box-free\n// for the whole column height), so the route runs that single gutter past the intervening\n// box. For same-row endpoints the H gutter sits above/below the shared row.\n//\n// Key invariants (asserted by test/uml/_overlap-harness.ts on an adversarial + fuzzed corpus):\n// - packGrid → disjoint cell AABBs → zero box-box overlap (2-D packSubtree induction).\n// - Every transit leg lies on a gutter centerline (offset by a lane within the box-free\n// strip) → segment-through-box-interior = 0; terminal stubs end on the box perimeter.\n// - allocateLanes per gutter strip (around reserved text AABBs) → no collinear-double-draw.\n// - Per-relationship-id port slots on each side, spaced ≥ max(glyph extent)+2 → parallel\n// edges and their glyph AABBs never overlap.\n// - All segments are axis-aligned → non-orthogonal = 0.\n//\n// Self-association: an orthogonal U in the cell's own right-margin lane, its glyph-bearing\n// end stopped short by glyphInset so the diamond sits OUTSIDE the box; a per-relationship-id\n// lane key keeps parallel self-loops on distinct offsets.\n\nimport {\n allocateLanes,\n estimateTextWidth,\n measureCompartmentBox,\n packGrid,\n type CompartmentMetrics,\n type GridResult,\n type Point,\n} from \"../core\";\nimport { UML_TITLE_LABELS_EN, type UmlTitleLabels } from \"./labels\";\nimport {\n sideCapacity,\n sideCapacityIssue,\n UmlValidationError,\n validateUml,\n type UmlIssue,\n} from \"./validate\";\nimport {\n glyphInset,\n GLYPH_TRI_HALF,\n type Dir,\n} from \"../core\";\nimport {\n RELATION_GLYPHS,\n UML_VIS_GLYPH,\n type GlyphKind,\n type UmlClass,\n type UmlFeature,\n type UmlInput,\n type UmlRelationship,\n} from \"./types\";\n\nexport {\n UmlValidationError,\n umlIssues,\n validateUml,\n sideCapacity,\n sideCapacityIssue,\n type UmlIssue,\n type UmlIssueCode,\n} from \"./validate\";\nexport type { Point };\n\n// ── Geometry constants ───────────────────────────────────────────────────────\n\n/** Canvas padding on all sides. */\nexport const UML_PADDING = 32;\n/** Horizontal gutter between adjacent columns. Box-free channel. */\nexport const UML_COL_GAP = 64;\n/** Vertical gutter between adjacent rows. Box-free channel. */\nexport const UML_ROW_GAP = 56;\n/** Horizontal padding inside a box (each side). */\nexport const UML_BOX_PAD_X = 10;\n/** Vertical padding inside a box (each side). */\nexport const UML_BOX_PAD_Y = 8;\n/** Height of a single text line inside a box. */\nexport const UML_LINE_H = 15;\n/** Minimum box width. */\nexport const UML_MIN_BOX_W = 120;\n/** Font size for the name/stereotype compartment. */\nexport const UML_NAME_FONT = 12;\n/** Font size for attributes and operations. */\nexport const UML_FEAT_FONT = 11;\n/** Padding below/above compartment dividers (reserved for future use; geometry uses 0). */\nexport const UML_SEP_PAD = 4;\n/** Pitch between adjacent port offsets on the same box side. */\nexport const UML_PORT_PITCH = 12;\n/** Width of the self-association side-loop lane (right margin). */\nexport const UML_SELF_LOOP_W = 28;\n/** Font size for edge labels (multiplicity, role, mid-edge label). */\nexport const UML_LABEL_FONT = 10;\n\n// ── Namespaced element-id blocks ─────────────────────────────────────────────\n// One block per element kind; every data-edge-id traces back to its source.\n/** Routing elements (inter-cell routed edge polylines). */\nexport const UML_ASSOC_ROUTE_BASE = 1_000_000;\n/** Glyph polygons (decoration, harness-excluded). */\nexport const UML_GLYPH_BASE = 2_000_000;\n/** Self-association loops. */\nexport const UML_SELF_LOOP_BASE = 3_000_000;\n\n// ── Internal routing constants ────────────────────────────────────────────────\n\n/**\n * Minimum length of a glyph-bearing terminal stub, in addition to the glyph inset.\n * Guarantees the terminal segment is long enough that no dedup can collapse it and\n * the glyph (which sits between the stub end and the box) is fully accounted. Must be\n * ≥ 1 so the stub never degenerates to a point.\n */\nconst MIN_TERMINAL_STUB = 4;\n\n// ── Layout types ──────────────────────────────────────────────────────────────\n\n/** A positioned UML class box with its measurement metrics. */\nexport interface UmlBoxNode {\n classId: number;\n /** Box center x (from packGrid). */\n cx: number;\n /** Box center y (from packGrid). */\n cy: number;\n /** Box left edge = cx - boxW/2. */\n boxW: number;\n /** Box height. */\n boxH: number;\n /** Compartment metrics (3 compartments: header / attributes / operations). */\n metrics: CompartmentMetrics;\n /** Display title (from UmlClass.title or computed). */\n title: string;\n /** Grid column index. */\n col: number;\n /** Grid row index. */\n row: number;\n}\n\n/** A small reserved text AABB (multiplicity / role / mid-edge label). */\nexport interface UmlTextBox {\n relId: number;\n /** Which text this is (for the emitter to draw the right string at the same anchor). */\n slot: \"src-mult\" | \"src-role\" | \"tgt-mult\" | \"tgt-role\" | \"label\";\n /** Verbatim string. */\n text: string;\n /** Top-left x of the reserved AABB. */\n x: number;\n /** Top-left y of the reserved AABB. */\n y: number;\n w: number;\n h: number;\n /** Text anchor: where the emitter places x (left by default). */\n anchor: \"start\" | \"middle\";\n}\n\n/** A routed edge element (inter-cell or self-loop). */\nexport interface UmlEdgeElement {\n edgeId: number;\n relId: number;\n /** Ordered waypoints forming the polyline. */\n points: Point[];\n kind: \"route\" | \"self-loop\";\n /** <title> text — the relationship's `title` override, else the LOCALIZED kind word. */\n title: string;\n}\n\n/** The complete positioned UML layout. */\nexport interface UmlLayout {\n nodes: UmlBoxNode[];\n elements: UmlEdgeElement[];\n /** Reserved text AABBs for multiplicity/role/label (drawn at these anchors by svg.ts). */\n textBoxes: UmlTextBox[];\n /** Total canvas width (before legend). */\n canvasW: number;\n /** Total canvas height (before legend). */\n canvasH: number;\n /** The grid result (column/row widths and heights, for harness). */\n grid: GridResult;\n /** colX[c] = left edge of column c (derived from grid + padding). */\n colX: number[];\n /** rowY[r] = top edge of row r (derived from grid + padding). */\n rowY: number[];\n}\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\n/** Feature line formatted with visibility prefix. */\nfunction featureLine(f: UmlFeature): string {\n const prefix = f.visibility !== null ? UML_VIS_GLYPH[f.visibility] + \" \" : \"\";\n return prefix + f.text;\n}\n\n/**\n * Measures the three-compartment box for a UML class.\n * Compartment 0: stereotype (if any) + name lines.\n * Compartment 1: attributes (features).\n * Compartment 2: operations (features).\n */\nfunction measureClass(cls: UmlClass): CompartmentMetrics {\n const nameLines: string[] = [];\n if (cls.stereotype !== null) nameLines.push(cls.stereotype);\n nameLines.push(cls.name);\n\n const attrLines = cls.attributes.map(featureLine);\n const opLines = cls.operations.map(featureLine);\n\n return measureCompartmentBox(\n [\n { lines: nameLines, font: UML_NAME_FONT },\n { lines: attrLines, font: UML_FEAT_FONT },\n { lines: opLines, font: UML_FEAT_FONT },\n ],\n {\n padX: UML_BOX_PAD_X,\n padY: UML_BOX_PAD_Y,\n lineH: UML_LINE_H,\n minW: UML_MIN_BOX_W,\n sepPad: UML_SEP_PAD,\n },\n );\n}\n\n/** Compute the left/right/top/bottom edge of a box. */\nfunction boxEdges(node: UmlBoxNode): { left: number; right: number; top: number; bottom: number } {\n const left = round(node.cx - node.boxW / 2);\n const right = round(left + node.boxW);\n const top = round(node.cy - node.boxH / 2);\n const bottom = round(top + node.boxH);\n return { left, right, top, bottom };\n}\n\n/**\n * Compute the inset for a glyph end on a given side.\n * Returns 0 for \"none\" glyphs (no inset needed).\n */\nfunction glyphInsetForKind(gk: GlyphKind): number {\n switch (gk) {\n case \"none\": return 0;\n case \"open-arrow\": return glyphInset(\"right\", \"arrow\");\n case \"hollow-triangle\": return glyphInset(\"right\", \"triangle\");\n case \"hollow-diamond\":\n case \"solid-diamond\": return glyphInset(\"right\", \"diamond\");\n }\n}\n\n/**\n * Largest glyph perpendicular half-extent over all kinds (the triangle, half = 8). Two\n * glyph AABBs centered on their ports don't overlap iff their port separation ≥ h1 + h2;\n * spacing every port on a side by ≥ 2·MAX + 2 covers the worst case (two triangles) and\n * keeps glyph AABBs apart regardless of which kinds share the side (design line 205).\n */\nconst MAX_GLYPH_HALF = GLYPH_TRI_HALF;\n/** Per-side port pitch: clears the largest glyph AABB on either neighbour. */\nconst GLYPH_SLOT_PITCH = Math.max(UML_PORT_PITCH, MAX_GLYPH_HALF * 2 + 2);\n\n/**\n * Port offset for a port slot, spread around the side midpoint as a zigzag:\n * slot 0 → 0, slot 1 → +pitch, slot 2 → −pitch, slot 3 → +2·pitch, …\n */\nfunction portOffset(slotIndex: number, slotSize: number): number {\n if (slotIndex === 0) return 0;\n const sign = slotIndex % 2 === 1 ? 1 : -1;\n const dist = Math.ceil(slotIndex / 2);\n return sign * dist * slotSize;\n}\n\n/**\n * Center of a vertical SIDE (left/right) of a box, offset by `dy` along the side.\n * Ports always sit on a vertical side so the terminal stub is horizontal.\n */\nfunction sidePort(node: UmlBoxNode, side: \"left\" | \"right\", dy: number): Point {\n const { left, right } = boxEdges(node);\n const x = side === \"right\" ? right : left;\n return { x, y: round(node.cy + dy) };\n}\n\n/** Left edge (right face of the left box) of the vertical gutter right of `colIdx`. */\nfunction vGutterLeft(colIdx: number, colX: number[], grid: GridResult): number {\n return round(colX[colIdx]! + grid.colW[colIdx]!);\n}\n\n/** Margin from a gutter wall to the first lane (keeps lanes strictly inside the gutter). */\nconst V_GUTTER_MARGIN = 6;\n\n/** Centerline y of the horizontal gutter BELOW row `rowIdx`. */\nfunction horizontalGutterY(rowIdx: number, rowY: number[], grid: GridResult): number {\n return round(rowY[rowIdx]! + grid.rowH[rowIdx]! + UML_ROW_GAP / 2);\n}\n\n/** Move a point `dist` units in the given cardinal direction. */\nfunction moveAlongDir(p: Point, dir: Dir, dist: number): Point {\n switch (dir) {\n case \"right\": return { x: round(p.x + dist), y: p.y };\n case \"left\": return { x: round(p.x - dist), y: p.y };\n case \"down\": return { x: p.x, y: round(p.y + dist) };\n case \"up\": return { x: p.x, y: round(p.y - dist) };\n }\n}\n\n/**\n * Remove only INTERIOR collinear/duplicate points (three consecutive points on the\n * same axis collapse to two; exact duplicates collapse). The FIRST and LAST points\n * (the glyph-bearing terminals) are NEVER dropped, so a terminal stub can never be\n * collapsed and the glyph direction is always the side normal.\n */\nfunction simplifyWaypoints(pts: Point[]): Point[] {\n // First drop exact consecutive duplicates.\n const dedup: Point[] = [pts[0]!];\n for (let i = 1; i < pts.length; i++) {\n const prev = dedup[dedup.length - 1]!;\n const cur = pts[i]!;\n if (Math.abs(cur.x - prev.x) > 1e-6 || Math.abs(cur.y - prev.y) > 1e-6) dedup.push(cur);\n }\n if (dedup.length <= 2) return dedup;\n // Drop interior points that are collinear with their neighbours (keep endpoints).\n const out: Point[] = [dedup[0]!];\n for (let i = 1; i < dedup.length - 1; i++) {\n const a = out[out.length - 1]!;\n const b = dedup[i]!;\n const c = dedup[i + 1]!;\n const abH = Math.abs(a.y - b.y) <= 1e-6;\n const bcH = Math.abs(b.y - c.y) <= 1e-6;\n const abV = Math.abs(a.x - b.x) <= 1e-6;\n const bcV = Math.abs(b.x - c.x) <= 1e-6;\n if ((abH && bcH) || (abV && bcV)) continue; // b is collinear → skip\n out.push(b);\n }\n out.push(dedup[dedup.length - 1]!);\n return out;\n}\n\n// ── Route planning + two-pass lane allocation ────────────────────────────────────\n//\n// The router runs in TWO passes so lanes pack tightly (only y-/x-overlapping legs get\n// distinct lanes, via core/allocateLanes) and never collapse together at a hard clamp:\n// Pass A — build a RoutePlan per edge: exit/entry sides, the two vertical-gutter\n// columns, the source/target port y's, and the horizontal-gutter row.\n// Lane allocation — per (vertical gutter, side) allocate lanes by the leg's y-interval;\n// per horizontal gutter allocate lanes by the H-leg's x-interval.\n// Pass B — assemble the final waypoints from the allocated lane coordinates.\n\n/** Per-edge routing skeleton (Pass A output). */\ninterface RoutePlan {\n rel: UmlRelationship;\n srcNode: UmlBoxNode;\n tgtNode: UmlBoxNode;\n srcSide: \"left\" | \"right\";\n tgtSide: \"left\" | \"right\";\n srcVCol: number; // vertical gutter index (gutter right of this column)\n tgtVCol: number;\n srcInset: number;\n tgtInset: number;\n srcPortY: number;\n tgtPortY: number;\n /** Horizontal-gutter selector: a row gutter index, or a special padding band key. */\n hKind: \"row\" | \"pad-top\";\n hRow: number;\n /**\n * A self-association is a degenerate route: both ports on the SAME box's right side, the\n * connecting leg a single vertical run in the right gutter (ONE V-lane shared by both\n * arms). Routed through the SAME gutter-lane allocator as ordinary edges so its segments\n * are spaced from every route in that gutter (no shared-gutter overlap).\n */\n isSelfLoop: boolean;\n /** Filled by lane allocation (Pass B reads these). */\n srcVx: number;\n tgtVx: number;\n hY: number;\n}\n\n/** Choose exit/entry sides + the two adjacent vertical gutters for an edge. */\nfunction chooseSides(\n srcNode: UmlBoxNode,\n tgtNode: UmlBoxNode,\n maxCol: number,\n): { srcSide: \"left\" | \"right\"; tgtSide: \"left\" | \"right\"; srcVCol: number; tgtVCol: number } {\n const sc = srcNode.col;\n const tc = tgtNode.col;\n if (tc > sc) return { srcSide: \"right\", tgtSide: \"left\", srcVCol: sc, tgtVCol: tc - 1 };\n if (tc < sc) return { srcSide: \"left\", tgtSide: \"right\", srcVCol: sc - 1, tgtVCol: tc };\n // Same column: ONE gutter beside the column (box-free for the whole column height).\n // Prefer the right gutter; fall back to the left gutter for the last (rightmost) column;\n // for a SINGLE-column diagram (no inter-column gutter on either side) route through the\n // open RIGHT MARGIN (gutter index = maxCol; right of the last column, box-free by padding).\n if (sc < maxCol) return { srcSide: \"right\", tgtSide: \"right\", srcVCol: sc, tgtVCol: sc };\n if (sc > 0) return { srcSide: \"left\", tgtSide: \"left\", srcVCol: sc - 1, tgtVCol: sc - 1 };\n return { srcSide: \"right\", tgtSide: \"right\", srcVCol: sc, tgtVCol: sc }; // sc === 0 === maxCol → right margin\n}\n\n/** Base centerline y of the horizontal gutter a plan uses (before its lane offset). */\nfunction hBaseY(plan: RoutePlan, rowY: number[], grid: GridResult): number {\n if (plan.hKind === \"pad-top\") return round(UML_PADDING / 2);\n return horizontalGutterY(plan.hRow, rowY, grid);\n}\n\n/** The box-free y-extent [lo, hi] of the horizontal gutter a plan transits. */\nfunction hBandBounds(plan: RoutePlan, rowY: number[], grid: GridResult): { lo: number; hi: number } {\n if (plan.hKind === \"pad-top\") return { lo: 0, hi: round(rowY[0] ?? UML_PADDING) };\n const lo = round(rowY[plan.hRow]! + grid.rowH[plan.hRow]!);\n const hi = round(rowY[plan.hRow + 1]!);\n return { lo, hi };\n}\n\n/** EPS for \"two horizontal runs share the same y\" / \"two lanes coincide\". Two lanes farther\n * apart than this never read as collinear under the harness (whose y-EPS is far smaller). */\nconst LANE_EPS = 0.5;\n/** EPS for \"two horizontal runs overlap in x\". Kept WELL below the harness's overlap EPS so the\n * allocator never under-counts an x-overlap the harness would flag (any real overlap conflicts). */\nconst X_OVERLAP_EPS = 1e-4;\n\n/**\n * A horizontal run that participates in per-gutter lane de-confliction. `lo`/`hi` are its\n * x-interval; a PINNED run (a port stub) sits at a fixed `y` that the floating main legs must\n * avoid; a FLOATING run (a main gutter leg) has `y === null` and is assigned one by the\n * allocator. Two horizontal runs collinear-overlap iff they share a y (±LANE_EPS) AND their\n * x-intervals overlap — exactly what `collinearOverlaps` flags — so the allocator's job is to\n * give every floating run a y distinct from every pinned/other-floating run it overlaps in x.\n */\ninterface HRun {\n lo: number;\n hi: number;\n /** Fixed y for a pinned stub; null for a floating main leg (assigned by allocateHorizontal). */\n y: number | null;\n /** Setter called with the resolved y (no-op for pinned runs). */\n set: (y: number) => void;\n}\n\n/**\n * Assign every FLOATING run a y inside the gutter band [base − usableHalf, base + usableHalf]\n * such that NO two horizontal runs (floating-vs-floating OR floating-vs-pinned port stub) ever\n * share a y (±LANE_EPS) while overlapping in x — the per-gutter half of the no-collinear-double-\n * draw invariant. Pinned stubs keep their fixed y (a terminal must land ON its port); only the\n * box-free main legs move.\n *\n * Candidate y's are evenly spaced across the band; the count is `floatCount + pinnedInBand + 1`.\n * As long as the resulting spacing `2·usableHalf / candidateCount` exceeds `2·LANE_EPS`, every\n * already-placed run's y lands within LANE_EPS of AT MOST one candidate, so ≤ (float+pinned)\n * candidates are ever blocked and the `+1` guarantees a free track for each floating run (worst\n * case: every run mutually overlaps in x → a clique needing ≤ float+pinned distinct tracks). The\n * spacing condition holds for any realistic diagram (it would take ~50 horizontal runs sharing\n * ONE gutter band to violate it — far past any valid fan-out). Greedy by x-interval (the\n * `allocateLanes` discipline): each floating run takes the lowest candidate y not blocked by an\n * already-placed run it overlaps in x. Over-supplying tracks only ever tightens the spacing —\n * never exhausts the box-free band (the wide-but-correct mode).\n */\nfunction allocateHorizontal(runs: HRun[], base: number, usableHalf: number): void {\n const floating = runs.filter((r) => r.y === null);\n if (floating.length === 0) return;\n const pinned = runs.filter((r) => r.y !== null);\n // Candidate y tracks: strictly more than the max chromatic number of the conflict graph\n // (floating + pinned-in-band), so a free track always exists (spacing argument above).\n const trackCount = floating.length + pinned.length + 1;\n const candidates: number[] =\n trackCount <= 1 || usableHalf <= 0\n ? [base]\n : Array.from({ length: trackCount }, (_, k) =>\n round(base - usableHalf + ((k + 0.5) * (2 * usableHalf)) / trackCount),\n );\n // Placed runs accumulate (pinned first, so floating legs avoid the fixed stub y's).\n const placed: { lo: number; hi: number; y: number }[] = pinned.map((r) => ({ lo: r.lo, hi: r.hi, y: r.y! }));\n // Deterministic order: by x-interval start then span (mirrors allocateLanes' input order).\n const ordered = [...floating].sort((a, b) => a.lo - b.lo || a.hi - b.hi);\n for (const run of ordered) {\n let chosen = candidates[0]!;\n for (const cy of candidates) {\n const collides = placed.some(\n (q) => Math.abs(q.y - cy) <= LANE_EPS && Math.min(run.hi, q.hi) - Math.max(run.lo, q.lo) > X_OVERLAP_EPS,\n );\n if (!collides) {\n chosen = cy;\n break;\n }\n }\n run.set(chosen);\n placed.push({ lo: run.lo, hi: run.hi, y: chosen });\n }\n}\n\n/**\n * Apply the glyph inset to the polyline endpoints so the drawn LINE stops short of the\n * box edge by the glyph length (the polygon is drawn from the inset point to the port).\n * The terminal segment direction is preserved (horizontal), so the glyph faces the side\n * normal. Returns a new point array with the first/last points pulled inward by the inset.\n */\nfunction applyGlyphInsets(\n pts: Point[],\n srcInset: number,\n tgtInset: number,\n): Point[] {\n if (pts.length < 2) return pts;\n const out = pts.map((p) => ({ ...p }));\n if (srcInset > 0) {\n const p0 = out[0]!;\n const p1 = out[1]!;\n // Terminal stub is horizontal: inset along x toward p1.\n const dir: Dir = p1.x >= p0.x ? \"right\" : \"left\";\n out[0] = moveAlongDir(p0, dir, srcInset);\n }\n if (tgtInset > 0) {\n const pn = out[out.length - 1]!;\n const pm = out[out.length - 2]!;\n const dir: Dir = pm.x >= pn.x ? \"right\" : \"left\";\n out[out.length - 1] = moveAlongDir(pn, dir, tgtInset);\n }\n return out;\n}\n\n// ── Text AABB reservation ────────────────────────────────────────────────────\n\n/**\n * Reserve a small text AABB near a port (multiplicity/role) or mid-edge (label), so a\n * long role/label name is accounted for and never silently overflows a cell or a parallel\n * lane (design line 206). The AABBs are placed in the gutter beside the edge terminal; the\n * emitter draws each string at the SAME anchor the layout reserved.\n */\nfunction reserveTextBox(\n relId: number,\n slot: UmlTextBox[\"slot\"],\n text: string,\n anchorX: number,\n anchorY: number,\n anchor: \"start\" | \"middle\",\n): UmlTextBox {\n const w = round(estimateTextWidth(text, UML_LABEL_FONT));\n const h = round(UML_LABEL_FONT * 1.2);\n const x = anchor === \"middle\" ? round(anchorX - w / 2) : round(anchorX);\n // The baseline sits at anchorY + font*0.8 in the emitter; the AABB top is anchorY.\n const y = round(anchorY);\n return { relId, slot, text, x, y, w, h, anchor };\n}\n\n// ── Main layout function ──────────────────────────────────────────────────────\n\n/**\n * Computes the full positioned layout for a UML class diagram.\n *\n * @param input The validated UML diagram input.\n * @param labels Display vocabulary (defaults to English) — woven into <title>s by svg.ts\n * via the kind word; threaded through so localized titles are honored.\n */\nexport function computeUmlLayout(\n input: UmlInput,\n labels: UmlTitleLabels = UML_TITLE_LABELS_EN,\n): UmlLayout {\n validateUml(input);\n\n /** <title> for a relationship: its override, else the localized kind word. */\n const relTitle = (rel: UmlRelationship): string => rel.title ?? labels.kinds[rel.kind];\n\n // Empty input → minimal empty canvas.\n if (input.classes.length === 0) {\n return {\n nodes: [],\n elements: [],\n textBoxes: [],\n canvasW: UML_PADDING * 2,\n canvasH: UML_PADDING * 2,\n grid: { cellX: [], cellY: [], colW: [], rowH: [] },\n colX: [],\n rowY: [],\n };\n }\n\n // Sort classes/relationships by id for determinism.\n const classes = [...input.classes].sort((a, b) => a.id - b.id);\n const rels = [...input.relationships].sort((a, b) => a.id - b.id);\n\n // ── Step 1: Measure each class box ────────────────────────────────────────\n const metricsMap = new Map<number, CompartmentMetrics>();\n for (const cls of classes) metricsMap.set(cls.id, measureClass(cls));\n\n // ── Step 2: packGrid → cell centers ───────────────────────────────────────\n const gridCells = classes.map((cls) => ({\n col: cls.col,\n row: cls.row,\n w: metricsMap.get(cls.id)!.boxW,\n h: metricsMap.get(cls.id)!.boxH,\n }));\n const grid = packGrid(gridCells, { colGap: UML_COL_GAP, rowGap: UML_ROW_GAP });\n\n // Derive colX and rowY (left/top origins) from packGrid output.\n const colX: number[] = [];\n {\n let x = UML_PADDING;\n for (let c = 0; c < grid.colW.length; c++) {\n colX.push(round(x));\n x = round(x + grid.colW[c]! + UML_COL_GAP);\n }\n }\n const rowY: number[] = [];\n {\n let y = UML_PADDING;\n for (let r = 0; r < grid.rowH.length; r++) {\n rowY.push(round(y));\n y = round(y + grid.rowH[r]! + UML_ROW_GAP);\n }\n }\n\n // Build nodes with absolute positions.\n const nodeByClassId = new Map<number, UmlBoxNode>();\n const nodes: UmlBoxNode[] = [];\n for (const cls of classes) {\n const metrics = metricsMap.get(cls.id)!;\n const cx = round(colX[cls.col]! + grid.colW[cls.col]! / 2);\n const cy = round(rowY[cls.row]! + grid.rowH[cls.row]! / 2);\n const title =\n cls.title ??\n (cls.stereotype !== null ? `«${cls.stereotype}» ${cls.name}` : cls.name);\n const node: UmlBoxNode = {\n classId: cls.id,\n cx,\n cy,\n boxW: metrics.boxW,\n boxH: metrics.boxH,\n metrics,\n title,\n col: cls.col,\n row: cls.row,\n };\n nodes.push(node);\n nodeByClassId.set(cls.id, node);\n }\n\n // ── Step 3: Route edges (two-pass) ─────────────────────────────────────────\n\n const maxCol = grid.colW.length - 1;\n const maxRow = grid.rowH.length - 1;\n\n // ── Side-capacity guard (reject-with-code, never mis-draw) ──────────────────\n // Count how many ports each (class, side) would hold — using the EXACT side assignment the\n // router applies below (chooseSides for ordinary edges; both ports on the RIGHT for a\n // self-loop), so the cap matches the layout exactly. A side that holds more ports than its\n // measured CLEAR vertical band can fit at the glyph-safe port pitch is INFEASIBLE: the\n // outermost zigzag port spills past the box and its stub crosses the neighbour box (a\n // segment-through-box hit). We REJECT it (mirroring org-chart's too-many-matrix-edges)\n // rather than draw a lie. The capacity is derived per box from its OWN height + the box-free\n // row gutter, so it is ≥ the true clean capacity the router handles and never rejects a\n // feasible diagram (proven clean ≥10 on the worst-case short box).\n const sideCount = new Map<string, number>();\n const bumpSide = (classId: number, side: \"left\" | \"right\"): void => {\n const key = `${classId}:${side}`;\n sideCount.set(key, (sideCount.get(key) ?? 0) + 1);\n };\n for (const rel of rels) {\n const srcNode = nodeByClassId.get(rel.sourceId);\n const tgtNode = nodeByClassId.get(rel.targetId);\n if (!srcNode || !tgtNode) continue; // validation already caught unknown endpoints\n if (rel.sourceId === rel.targetId) {\n // Self-association: two arm ports, both on the source's RIGHT side.\n bumpSide(srcNode.classId, \"right\");\n bumpSide(srcNode.classId, \"right\");\n continue;\n }\n const { srcSide, tgtSide } = chooseSides(srcNode, tgtNode, maxCol);\n bumpSide(srcNode.classId, srcSide);\n bumpSide(tgtNode.classId, tgtSide);\n }\n {\n const capIssues: UmlIssue[] = [];\n for (const node of nodes) {\n const cap = sideCapacity(node.boxH, UML_ROW_GAP, GLYPH_SLOT_PITCH, MAX_GLYPH_HALF);\n for (const side of [\"left\", \"right\"] as const) {\n const count = sideCount.get(`${node.classId}:${side}`) ?? 0;\n if (count > cap) capIssues.push(sideCapacityIssue(node.classId, side, count, cap));\n }\n }\n if (capIssues.length > 0) {\n // Deterministic order: by classId then side (matches node order + the side tuple above).\n throw new UmlValidationError(capIssues);\n }\n }\n\n // Per-box, per-side port-slot counter. Ports on one side step by GLYPH_SLOT_PITCH so any\n // two glyph AABBs on a side stay apart (worst case: two triangles). Counter is bumped per\n // relationship, so parallel edges between the same pair land on distinct ports.\n const sidePortSlot = new Map<string, number>();\n const nextSidePort = (classId: number, side: \"left\" | \"right\"): number => {\n const key = `${classId}:${side}`;\n const idx = sidePortSlot.get(key) ?? 0;\n sidePortSlot.set(key, idx + 1);\n return idx;\n };\n\n const elements: UmlEdgeElement[] = [];\n const textBoxes: UmlTextBox[] = [];\n\n // ── Pass A: build a RoutePlan per edge (self-loops are degenerate plans) ───────\n const plans: RoutePlan[] = [];\n for (const rel of rels) {\n const srcNode = nodeByClassId.get(rel.sourceId);\n const tgtNode = nodeByClassId.get(rel.targetId);\n if (!srcNode || !tgtNode) continue; // validation already caught unknown endpoints\n\n const glyphs = RELATION_GLYPHS[rel.kind];\n const srcInset = glyphInsetForKind(glyphs.sourceEnd);\n const tgtInset = glyphInsetForKind(glyphs.targetEnd);\n\n if (rel.sourceId === rel.targetId) {\n // Self-association: both ports on the RIGHT side; both arms share ONE V-lane in the\n // right gutter of the class's own column. The two arm ports consume the right-side slot\n // counter (glyph AABBs spaced from every route glyph), and the shared V-lane is packed by\n // the gutter's V-allocator (spaced from every route in that gutter). For the last column\n // the \"right gutter\" is the open right margin (box-free by padding).\n const vCol = srcNode.col;\n const armDy1 = portOffset(nextSidePort(srcNode.classId, \"right\"), GLYPH_SLOT_PITCH);\n const armDy2 = portOffset(nextSidePort(srcNode.classId, \"right\"), GLYPH_SLOT_PITCH);\n plans.push({\n rel, srcNode, tgtNode,\n srcSide: \"right\", tgtSide: \"right\",\n srcVCol: vCol, tgtVCol: vCol,\n srcInset, tgtInset,\n srcPortY: round(srcNode.cy + armDy1),\n tgtPortY: round(srcNode.cy + armDy2),\n hKind: \"row\", hRow: 0, // unused for self-loops (no H-leg)\n isSelfLoop: true,\n srcVx: 0, tgtVx: 0, hY: 0,\n });\n continue;\n }\n\n const { srcSide, tgtSide, srcVCol, tgtVCol } = chooseSides(srcNode, tgtNode, maxCol);\n const srcPortDy = portOffset(nextSidePort(srcNode.classId, srcSide), GLYPH_SLOT_PITCH);\n const tgtPortDy = portOffset(nextSidePort(tgtNode.classId, tgtSide), GLYPH_SLOT_PITCH);\n\n // Horizontal-gutter selection.\n const sr = srcNode.row;\n const tr = tgtNode.row;\n let hKind: \"row\" | \"pad-top\";\n let hRow: number;\n if (sr !== tr) {\n hKind = \"row\"; hRow = Math.min(sr, tr);\n } else if (maxRow >= 1) {\n hKind = \"row\"; hRow = sr < maxRow ? sr : sr - 1;\n } else {\n hKind = \"pad-top\"; hRow = -1; // single-row diagram → box-free top padding band\n }\n\n plans.push({\n rel, srcNode, tgtNode,\n srcSide, tgtSide, srcVCol, tgtVCol,\n srcInset, tgtInset,\n srcPortY: round(srcNode.cy + srcPortDy),\n tgtPortY: round(tgtNode.cy + tgtPortDy),\n hKind, hRow,\n isSelfLoop: false,\n srcVx: 0, tgtVx: 0, hY: 0,\n });\n }\n\n // ── Lane allocation ───────────────────────────────────────────────────────────\n // Vertical legs: per (gutter col, side), allocate by the leg's y-interval. Only legs\n // that OVERLAP in y get distinct lanes (allocateLanes packs the rest), so the half-gutter\n // is never exhausted for non-conflicting legs.\n //\n // The V-leg's far end is its H-gutter lane y, which isn't fixed until H-lanes are packed\n // (a circular dependency). We break it CONSERVATIVELY: the V-leg interval extends to the\n // FAR WALL of the H-gutter band (hBase ± halfBand), which contains every possible H-lane\n // y. Over-reserving only ever yields MORE distinct lanes (a wider, still-correct diagram —\n // the accepted failure mode); it can never miss a real V-leg overlap.\n const hHalfBand = (p: RoutePlan): number =>\n p.hKind === \"pad-top\" ? round(UML_PADDING / 2) : round(UML_ROW_GAP / 2);\n // A V-leg item: its y-interval (extended to the H-gutter band so any H-lane is covered),\n // its glyph inset (so even-spacing clears the largest glyph in the group), and a setter.\n type VItem = { lo: number; hi: number; inset: number; lane: number; set: (x: number) => void };\n const vByKey = new Map<string, VItem[]>();\n const pushV = (col: number, side: \"left\" | \"right\", portY: number, hBase: number, half: number, inset: number, set: (x: number) => void): void => {\n // The V-leg connects portY to the route's H-gutter lane y (`hY`), which `allocateHorizontal`\n // can place ANYWHERE inside the gutter band [hBase − half, hBase + half] (in EITHER direction\n // from portY — a near-band portY can end up with hY on the far side of it). So the V-leg's\n // true y-interval is [min(portY, hY), max(portY, hY)] ⊆ [min(portY, hBase − half), max(portY,\n // hBase + half)]. Reserve that FULL two-sided span — covering the band on BOTH sides of portY,\n // not just the side hBase happens to fall on — so the lane allocator never under-counts a\n // V-leg overlap (the residual: a self-loop V-leg and a route V-leg got the SAME lane because\n // the one-sided extension missed the hY that landed on the opposite side of portY, then the\n // route's H-leg pulled its V-leg back across the self-loop → a sub-px collinear double-draw).\n const lo = Math.min(portY, round(hBase - half));\n const hi = Math.max(portY, round(hBase + half));\n const key = `${col}:${side}`;\n const arr = vByKey.get(key) ?? [];\n arr.push({ lo, hi, inset, lane: 0, set });\n vByKey.set(key, arr);\n };\n for (const p of plans) {\n if (p.isSelfLoop) {\n // ONE shared V-lane: the U's vertical run spans both arm ports. Both srcVx and tgtVx\n // become the same x (the lane), so the U is a clean rectangle in the gutter.\n const lo = Math.min(p.srcPortY, p.tgtPortY);\n const hi = Math.max(p.srcPortY, p.tgtPortY);\n const key = `${p.srcVCol}:right`;\n const arr = vByKey.get(key) ?? [];\n arr.push({ lo, hi, inset: Math.max(p.srcInset, p.tgtInset), lane: 0, set: (x) => { p.srcVx = x; p.tgtVx = x; } });\n vByKey.set(key, arr);\n continue;\n }\n if (p.srcVCol === p.tgtVCol && p.srcSide === p.tgtSide) {\n // SAME-COLUMN edge: both legs share ONE gutter strip on the same side. Route them on a\n // SINGLE shared V-lane (srcVx === tgtVx) so the run is a clean vertical past the\n // intervening box, with the two horizontal port stubs joining it — NO sub-epsilon H jog\n // between two near-coincident lanes (root-cause #1 of the residual collinear-double-draw:\n // two distinct lanes 1.84px apart connected by a 1.84px horizontal jog). The shared lane\n // spans both port y's so its interval covers the whole vertical run.\n const lo = Math.min(p.srcPortY, p.tgtPortY);\n const hi = Math.max(p.srcPortY, p.tgtPortY);\n const key = `${p.srcVCol}:${p.srcSide}`;\n const arr = vByKey.get(key) ?? [];\n arr.push({ lo, hi, inset: Math.max(p.srcInset, p.tgtInset), lane: 0, set: (x) => { p.srcVx = x; p.tgtVx = x; } });\n vByKey.set(key, arr);\n continue;\n }\n const hBase = hBaseY(p, rowY, grid);\n const half = hHalfBand(p);\n pushV(p.srcVCol, p.srcSide, p.srcPortY, hBase, half, p.srcInset, (x) => { p.srcVx = x; });\n pushV(p.tgtVCol, p.tgtSide, p.tgtPortY, hBase, half, p.tgtInset, (x) => { p.tgtVx = x; });\n }\n // Per (gutter, side): allocate lanes by y-interval, then EVEN-SPACE the lanes across the\n // half-gutter band [wall+maxBaseGap, center] (right) / [center, wall−maxBaseGap] (left).\n // Even spacing (not fixed-pitch) means an arbitrary number of legs always fits inside the\n // box-free half-gutter without two lanes ever clamping to the same x (the prior bug). The\n // band's inner edge clears the LARGEST glyph in the group, so every leg's glyph is clear.\n for (const [key, items] of vByKey.entries()) {\n const side = key.endsWith(\":right\") ? \"right\" : \"left\";\n const col = Number(key.slice(0, key.lastIndexOf(\":\")));\n const laneCount = allocateLanes(\n items.map((it) => ({ lo: it.lo, hi: it.hi, set: (l: number) => { it.lane = l; } })),\n );\n const left = vGutterLeft(col, colX, grid);\n const right = round(left + UML_COL_GAP);\n const center = round((left + right) / 2);\n const maxBaseGap = Math.max(...items.map((it) => Math.max(V_GUTTER_MARGIN, it.inset + MIN_TERMINAL_STUB)));\n for (const it of items) {\n let x: number;\n if (side === \"right\") {\n const lo = left + maxBaseGap;\n const hi = center - 1;\n x = laneCount <= 1 ? lo : lo + (it.lane * (hi - lo)) / (laneCount - 1);\n } else {\n const hi = right - maxBaseGap;\n const lo = center + 1;\n x = laneCount <= 1 ? hi : hi - (it.lane * (hi - lo)) / (laneCount - 1);\n }\n it.set(round(x));\n }\n }\n\n // Horizontal runs: per horizontal gutter, de-conflict EVERY horizontal sub-run of EVERY route\n // — not just the \"main\" gutter leg, but also the two terminal PORT STUBS whose port-y can spill\n // into a gutter band when a heavily-fanned box's ports zigzag past its own height. The main leg\n // FLOATS (assigned a band y); a port stub is PINNED at its port-y (the terminal must land ON the\n // port). A floating main leg gets a y distinct from every pinned stub AND every other main leg\n // it overlaps in x → no two routed horizontal segments are ever collinear-coincident (root-cause\n // #2 of the residual: a main leg at hY landing on a foreign route's port-stub at the same y).\n //\n // Each route is keyed by its own gutter (where its main leg lives). A port stub joins the gutter\n // key whose band [base ± usableHalf] CONTAINS its port-y — that is the only band a floating leg\n // could collide with it in. Stubs whose y sits inside a box's own row, or in the bottom padding,\n // fall into no gutter band and conflict with nothing.\n const usableHalfOf = (kind: \"row\" | \"pad-top\"): number =>\n Math.max(0, (kind === \"pad-top\" ? round(UML_PADDING / 2) : round(UML_ROW_GAP / 2)) - 3);\n // Gather each gutter's base + usableHalf so we can bin pinned stubs by their y.\n const gutterKey = (p: RoutePlan): string => (p.hKind === \"pad-top\" ? \"pad-top\" : `row:${p.hRow}`);\n type GutterMeta = { base: number; usableHalf: number };\n const gutterMeta = new Map<string, GutterMeta>();\n for (const p of plans) {\n if (p.isSelfLoop) continue;\n const key = gutterKey(p);\n if (!gutterMeta.has(key)) gutterMeta.set(key, { base: hBaseY(p, rowY, grid), usableHalf: usableHalfOf(p.hKind) });\n }\n const hRunsByKey = new Map<string, HRun[]>();\n const pushRun = (key: string, run: HRun): void => {\n const arr = hRunsByKey.get(key) ?? [];\n arr.push(run);\n hRunsByKey.set(key, arr);\n };\n // Bin a pinned horizontal stub (a terminal at a fixed port-y) into every gutter band whose\n // floating-leg range [base ± usableHalf] contains its y — the only bands a floating leg could\n // collide with it in. A stub inside a box's own row / the bottom padding hits no band.\n const pinStub = (yy: number, a: number, b: number): void => {\n for (const [gk, meta] of gutterMeta.entries()) {\n if (yy >= meta.base - meta.usableHalf - LANE_EPS && yy <= meta.base + meta.usableHalf + LANE_EPS) {\n pushRun(gk, { lo: Math.min(a, b), hi: Math.max(a, b), y: yy, set: () => {} });\n }\n }\n };\n for (const p of plans) {\n if (p.isSelfLoop) {\n // A self-loop is a U: its two horizontal ARMS are port stubs at the two arm port-y's,\n // x-interval [box edge ↔ shared V-lane]. They have NO floating leg (the U closes\n // vertically), so they only ever act as PINNED obstacles the floating main legs avoid.\n const sideX = p.srcSide === \"right\" ? boxEdges(p.srcNode).right : boxEdges(p.srcNode).left;\n pinStub(p.srcPortY, sideX, p.srcVx);\n pinStub(p.tgtPortY, sideX, p.tgtVx);\n continue;\n }\n const key = gutterKey(p);\n // FLOATING main leg — only when the two V-lanes differ (same-column edges share one V-lane,\n // so simplifyWaypoints drops the zero-length main leg; pinning a phantom run there would\n // wrongly block the band). The setter writes p.hY.\n if (Math.abs(p.srcVx - p.tgtVx) > LANE_EPS) {\n pushRun(key, { lo: Math.min(p.srcVx, p.tgtVx), hi: Math.max(p.srcVx, p.tgtVx), y: null, set: (y) => { p.hY = round(y); } });\n } else {\n p.hY = p.srcPortY; // no main leg; keep hY harmless (Pass B collapses the duplicate point)\n }\n // PINNED port stubs at their port-y, x-interval [port.x ↔ vx].\n const srcPortX = p.srcSide === \"right\" ? boxEdges(p.srcNode).right : boxEdges(p.srcNode).left;\n const tgtPortX = p.tgtSide === \"right\" ? boxEdges(p.tgtNode).right : boxEdges(p.tgtNode).left;\n pinStub(p.srcPortY, srcPortX, p.srcVx);\n pinStub(p.tgtPortY, tgtPortX, p.tgtVx);\n }\n for (const [key, runs] of hRunsByKey.entries()) {\n const meta = gutterMeta.get(key)!;\n allocateHorizontal(runs, meta.base, meta.usableHalf);\n }\n\n // ── Pass B: assemble waypoints from the allocated lane coordinates ────────────\n for (const p of plans) {\n const srcPort: Point = sidePort(p.srcNode, p.srcSide, p.srcPortY - p.srcNode.cy);\n const tgtPort: Point = sidePort(p.tgtNode, p.tgtSide, p.tgtPortY - p.tgtNode.cy);\n\n if (p.isSelfLoop) {\n // U: srcArm → V-lane → down/up → tgtArm. The two arms are horizontal at the two port\n // y's; the vertical run is the shared V-lane (srcVx === tgtVx). The glyph-bearing ends\n // are inset so the diamond sits OUTSIDE the box (in the gutter), never inward.\n const raw: Point[] = [\n srcPort,\n { x: p.srcVx, y: srcPort.y },\n { x: p.srcVx, y: tgtPort.y },\n tgtPort,\n ];\n const portPts = simplifyWaypoints(raw);\n const pts = applyGlyphInsets(portPts, p.srcInset, p.tgtInset);\n const edgeId = UML_SELF_LOOP_BASE + p.rel.id;\n elements.push({ edgeId, relId: p.rel.id, points: pts, kind: \"self-loop\", title: relTitle(p.rel) });\n reserveSelfLoopText(p.rel, p, textBoxes);\n continue;\n }\n\n const raw: Point[] = [\n srcPort,\n { x: p.srcVx, y: srcPort.y },\n { x: p.srcVx, y: p.hY },\n { x: p.tgtVx, y: p.hY },\n { x: p.tgtVx, y: tgtPort.y },\n tgtPort,\n ];\n const portPts = simplifyWaypoints(raw);\n const pts = applyGlyphInsets(portPts, p.srcInset, p.tgtInset);\n const edgeId = UML_ASSOC_ROUTE_BASE + p.rel.id;\n elements.push({ edgeId, relId: p.rel.id, points: pts, kind: \"route\", title: relTitle(p.rel) });\n reserveRouteText(p.rel, p, hBandBounds(p, rowY, grid), textBoxes);\n }\n\n // ── Step 4: Compute canvas size (include self-loop margins + text boxes) ────\n let maxRight = 0;\n let maxBottom = 0;\n for (const node of nodes) {\n const { right, bottom } = boxEdges(node);\n if (right > maxRight) maxRight = right;\n if (bottom > maxBottom) maxBottom = bottom;\n }\n for (const el of elements) {\n for (const pt of el.points) {\n if (pt.x > maxRight) maxRight = pt.x;\n if (pt.y > maxBottom) maxBottom = pt.y;\n }\n }\n for (const tb of textBoxes) {\n if (tb.x + tb.w > maxRight) maxRight = tb.x + tb.w;\n if (tb.y + tb.h > maxBottom) maxBottom = tb.y + tb.h;\n }\n\n const canvasW = round(maxRight + UML_PADDING);\n const canvasH = round(maxBottom + UML_PADDING);\n\n return { nodes, elements, textBoxes, canvasW, canvasH, grid, colX, rowY };\n}\n\n/**\n * Reserve text AABBs for a routed edge's multiplicity/role/label.\n *\n * ALL edge text is anchored INSIDE a box-free gutter band (the horizontal row-gutter the\n * edge transits, at p.hY), never in the narrow vertical strips beside a box. The horizontal\n * row-gutter is box-free across the ENTIRE canvas width (no cell occupies it), so a text AABB\n * placed there — at any x, any length — can NEVER overlap a cell interior, regardless of how\n * long the role/label string is (the honesty rule keeps it verbatim; over-long text just runs\n * along the box-free band). This is the design's \"reserve text into gutter space\" requirement.\n * The src/tgt mult+role stack near their V-leg x (where it meets the gutter); the label sits\n * at the gutter's H-leg midpoint. Parallel-edge lane y's (p.hY) already differ per edge.\n */\nfunction reserveRouteText(\n rel: UmlRelationship,\n p: RoutePlan,\n band: { lo: number; hi: number },\n out: UmlTextBox[],\n): void {\n const textH = round(UML_LABEL_FONT * 1.2);\n // Two stacked rows (multiplicity ABOVE the line, role BELOW), both CLAMPED into the box-free\n // band [lo, hi]. The band is ROW_GAP (56) tall (or the top padding) — comfortably fits two\n // 12px rows — so clamping never lets a text AABB poke into an adjacent cell, no matter the\n // edge's H-lane offset or how long the verbatim string is (it runs along the box-free band).\n const clampY = (y: number): number => round(Math.max(band.lo + 1, Math.min(y, band.hi - 1 - textH)));\n const above = clampY(p.hY - textH - 1);\n const below = clampY(p.hY + 1);\n const srcX = round(p.srcVx + 3);\n const tgtX = round(p.tgtVx + 3);\n\n if (rel.sourceMultiplicity !== null) {\n out.push(reserveTextBox(rel.id, \"src-mult\", rel.sourceMultiplicity, srcX, above, \"start\"));\n }\n if (rel.sourceRole !== null) {\n out.push(reserveTextBox(rel.id, \"src-role\", rel.sourceRole, srcX, below, \"start\"));\n }\n if (rel.targetMultiplicity !== null) {\n out.push(reserveTextBox(rel.id, \"tgt-mult\", rel.targetMultiplicity, tgtX, above, \"start\"));\n }\n if (rel.targetRole !== null) {\n out.push(reserveTextBox(rel.id, \"tgt-role\", rel.targetRole, tgtX, below, \"start\"));\n }\n if (rel.label !== null) {\n const midX = round((p.srcVx + p.tgtVx) / 2);\n out.push(reserveTextBox(rel.id, \"label\", rel.label, midX, above, \"middle\"));\n }\n}\n\n/**\n * Reserve text AABBs for a self-loop's multiplicity/role/label, anchored in the box-free\n * vertical gutter strip just RIGHT of the loop's V-lane (never overlapping the loop's OWN box),\n * stacked at each arm's y. The strip is box-free for the full column height. KNOWN LIMITATION\n * (design-accepted, the \"wide-but-non-overlapping\" doctrine): a self-association role/label far\n * wider than the inter-column gutter may read toward the next column — multiplicities (the common\n * case) are short and always fit. Verbatim, never parsed.\n */\nfunction reserveSelfLoopText(rel: UmlRelationship, p: RoutePlan, out: UmlTextBox[]): void {\n const x0 = round(p.srcVx + 3);\n const srcY = p.srcPortY;\n const tgtY = p.tgtPortY;\n if (rel.sourceMultiplicity !== null) {\n out.push(reserveTextBox(rel.id, \"src-mult\", rel.sourceMultiplicity, x0, round(srcY - UML_LABEL_FONT - 1), \"start\"));\n }\n if (rel.sourceRole !== null) {\n out.push(reserveTextBox(rel.id, \"src-role\", rel.sourceRole, x0, round(srcY + 1), \"start\"));\n }\n if (rel.targetMultiplicity !== null) {\n out.push(reserveTextBox(rel.id, \"tgt-mult\", rel.targetMultiplicity, x0, round(tgtY - UML_LABEL_FONT - 1), \"start\"));\n }\n if (rel.targetRole !== null) {\n out.push(reserveTextBox(rel.id, \"tgt-role\", rel.targetRole, x0, round(tgtY + 1), \"start\"));\n }\n if (rel.label !== null) {\n out.push(reserveTextBox(rel.id, \"label\", rel.label, x0, round((srcY + tgtY) / 2 - UML_LABEL_FONT / 2), \"start\"));\n }\n}\n\n// ── One-call wrapper (render.ts) ──────────────────────────────────────────────\n// Exported from index.ts via render.ts.\n","// UML class-diagram SVG emitter — turns a computed UmlLayout into a SELF-CONTAINED SVG\n// string. Pure (layout in, string out) and deterministic; draws EXACTLY what the layout\n// computed (the overlap harness proves the layout; this emitter is pinned to it).\n//\n// House rules (AGENTS.md):\n// - xmlEscape EVERY interpolated string.\n// - Literal presentation attributes only (hex colors, explicit font-family).\n// No CSS, no currentColor, no <defs>, no <marker>.\n// - All glyphs are EXPLICIT <polygon>/<polyline> from core/glyph.\n// - round() every coordinate — 2-decimal, byte-deterministic output.\n\nimport {\n EDGE_STROKE,\n FONT_FAMILY,\n legendBlock,\n xmlEscape,\n LEGEND_SWATCH_W,\n type LegendEntry,\n arrowOpenPoints,\n trianglePoints,\n diamondPoints,\n type Dir,\n} from \"../core\";\nimport {\n UML_BOX_PAD_X,\n UML_FEAT_FONT,\n UML_LABEL_FONT,\n UML_LINE_H,\n UML_NAME_FONT,\n type UmlBoxNode,\n type UmlEdgeElement,\n type UmlLayout,\n type UmlTextBox,\n} from \"./layout\";\nimport { UML_SVG_LABELS_EN, type UmlSvgLabels } from \"./labels\";\nimport {\n RELATION_GLYPHS,\n UML_RELATIONSHIPS,\n UML_VIS_GLYPH,\n type GlyphKind,\n type UmlFeature,\n type UmlInput,\n type UmlRelationship,\n type UmlRelationshipKind,\n} from \"./types\";\n\n// ── Ink colors (zinc ramp on white, matching the house style) ────────────────\nconst GLYPH_STROKE = \"#52525b\";\nconst LABEL_FILL = \"#3f3f46\";\nconst EDGE_INK = \"#71717a\";\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\n// ── Glyph emitters ────────────────────────────────────────────────────────────\n\n/**\n * Emit the glyph polygon/polyline for a relationship end.\n * `tip` = the point where the glyph apex sits (on the box edge).\n * `dir` = the direction from the line toward the box (the tip points in this direction).\n */\nfunction emitGlyph(\n gk: GlyphKind,\n tip: { x: number; y: number },\n dir: Dir,\n): string {\n switch (gk) {\n case \"none\":\n return \"\";\n case \"open-arrow\": {\n const pts = arrowOpenPoints(tip, dir);\n return `<polyline points=\"${pts}\" fill=\"none\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"1.5\"/>`;\n }\n case \"hollow-triangle\": {\n const pts = trianglePoints(tip, dir);\n return `<polygon points=\"${pts}\" fill=\"#fff\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"1.5\"/>`;\n }\n case \"hollow-diamond\": {\n const pts = diamondPoints(tip, dir);\n return `<polygon points=\"${pts}\" fill=\"#fff\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"1.5\"/>`;\n }\n case \"solid-diamond\": {\n const pts = diamondPoints(tip, dir);\n return `<polygon points=\"${pts}\" fill=\"${GLYPH_STROKE}\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"1.5\"/>`;\n }\n }\n}\n\n/** Direction FROM the target box back along the edge (for target glyph). */\nfunction glyphDir(firstPt: { x: number; y: number }, secondPt: { x: number; y: number }): Dir {\n const dx = secondPt.x - firstPt.x;\n const dy = secondPt.y - firstPt.y;\n if (Math.abs(dx) >= Math.abs(dy)) {\n return dx >= 0 ? \"left\" : \"right\"; // target tip faces LEFT when line comes from right\n }\n return dy >= 0 ? \"up\" : \"down\";\n}\n\n// ── Box emitter ────────────────────────────────────────────────────────────────\n\n/** Feature line with optional static underline. */\nfunction featureSvg(\n f: UmlFeature,\n x: number,\n y: number,\n font: number,\n): string {\n const prefix = f.visibility !== null ? UML_VIS_GLYPH[f.visibility] + \" \" : \"\";\n const text = prefix + f.text;\n const baseline = round(y + font * 0.8);\n let out = `<text x=\"${x}\" y=\"${baseline}\" font-family=\"${FONT_FAMILY}\" font-size=\"${font}\" fill=\"${LABEL_FILL}\">${xmlEscape(text)}</text>`;\n if (f.isStatic) {\n // Underline: a <line> just below the text baseline\n const lineY = round(baseline + 1);\n const approxW = round(text.length * font * 0.6);\n out += `<line x1=\"${x}\" y1=\"${lineY}\" x2=\"${round(x + approxW)}\" y2=\"${lineY}\" stroke=\"${LABEL_FILL}\" stroke-width=\"0.8\"/>`;\n }\n return out;\n}\n\nfunction boxSvg(node: UmlBoxNode, cls: { attributes: UmlFeature[]; operations: UmlFeature[]; isAbstract?: boolean; stereotype: string | null }): string {\n const left = round(node.cx - node.boxW / 2);\n const top = round(node.cy - node.boxH / 2);\n const metrics = node.metrics;\n const pieces: string[] = [];\n\n pieces.push(`<title>${xmlEscape(node.title)}</title>`);\n\n // Box rect\n pieces.push(\n `<rect x=\"${left}\" y=\"${top}\" width=\"${node.boxW}\" height=\"${node.boxH}\" rx=\"2\" fill=\"#fff\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"1.5\"/>`,\n );\n\n // Divider lines between compartments\n for (const dy of metrics.dividerYs) {\n const y = round(top + dy);\n pieces.push(\n `<line x1=\"${left}\" y1=\"${y}\" x2=\"${round(left + node.boxW)}\" y2=\"${y}\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"0.75\"/>`,\n );\n }\n\n // Compartment 0: stereotype + name\n const compartment0 = metrics.rows[0]!;\n const textX = round(left + node.boxW / 2); // centered\n let lineIdx = 0;\n\n if (cls.stereotype !== null) {\n // Stereotype line: «...» — render verbatim (caller includes guillemets as desired)\n const stereoY = round(top + compartment0.top + lineIdx * UML_LINE_H + UML_NAME_FONT * 0.8);\n pieces.push(\n `<text x=\"${textX}\" y=\"${stereoY}\" font-family=\"${FONT_FAMILY}\" font-size=\"${UML_NAME_FONT}\" fill=\"${LABEL_FILL}\" text-anchor=\"middle\">${xmlEscape(cls.stereotype)}</text>`,\n );\n lineIdx++;\n }\n\n // Name line: italic if abstract\n const nameY = round(top + compartment0.top + lineIdx * UML_LINE_H + UML_NAME_FONT * 0.8);\n const nameStyle = cls.isAbstract ? ` font-style=\"italic\"` : \"\";\n // Get the class name (last line of compartment 0)\n const nameText = metrics.rows[0]!.lines[lineIdx] ?? \"\";\n pieces.push(\n `<text x=\"${textX}\" y=\"${nameY}\" font-family=\"${FONT_FAMILY}\" font-size=\"${UML_NAME_FONT}\" fill=\"${LABEL_FILL}\" text-anchor=\"middle\"${nameStyle}>${xmlEscape(nameText)}</text>`,\n );\n\n // Compartment 1: attributes (left-aligned)\n const attrCompartment = metrics.rows[1]!;\n const attrX = round(left + UML_BOX_PAD_X);\n for (let i = 0; i < cls.attributes.length; i++) {\n const f = cls.attributes[i]!;\n const fy = round(top + attrCompartment.top + i * UML_LINE_H);\n pieces.push(featureSvg(f, attrX, fy, UML_FEAT_FONT));\n }\n\n // Compartment 2: operations (left-aligned)\n const opCompartment = metrics.rows[2]!;\n const opX = round(left + UML_BOX_PAD_X);\n for (let i = 0; i < cls.operations.length; i++) {\n const f = cls.operations[i]!;\n const fy = round(top + opCompartment.top + i * UML_LINE_H);\n pieces.push(featureSvg(f, opX, fy, UML_FEAT_FONT));\n }\n\n return `<g data-node-id=\"c${node.classId}\">${pieces.join(\"\")}</g>`;\n}\n\n// ── Edge emitter ───────────────────────────────────────────────────────────────\n\nfunction edgeSvg(\n el: UmlEdgeElement,\n rel: UmlRelationship,\n textBoxes: UmlTextBox[],\n): string {\n const glyphs = RELATION_GLYPHS[rel.kind];\n const isDashed = glyphs.line === \"dashed\";\n const stroke = isDashed ? EDGE_STROKE.distant : { width: 1.5, dash: null as null, opacity: 0.7 };\n\n const strokeAttrs = isDashed\n ? `stroke=\"${EDGE_INK}\" stroke-width=\"${stroke.width}\" stroke-dasharray=\"4,4\" opacity=\"${stroke.opacity}\"`\n : `stroke=\"${EDGE_INK}\" stroke-width=\"${stroke.width}\" opacity=\"${stroke.opacity}\"`;\n\n // <title> = the layout-woven localized kind word (or the rel.title override).\n const pts = el.points;\n const pieces: string[] = [`<title>${xmlEscape(el.title)}</title>`];\n\n if (pts.length >= 2) {\n // Main line\n pieces.push(`<polyline points=\"${pts.map((p) => `${p.x},${p.y}`).join(\" \")}\" fill=\"none\" ${strokeAttrs}/>`);\n\n // Source glyph: at the START of the line (pts[0]). The line was inset so pts[0] is the\n // glyph BASE-tip; the glyph points back toward the source box (the side normal).\n if (glyphs.sourceEnd !== \"none\") {\n const tip = pts[0]!;\n const next = pts[1]!;\n const dir = glyphDir(tip, next);\n pieces.push(emitGlyph(glyphs.sourceEnd, tip, dir));\n }\n\n // Target glyph: at the END of the line (pts[last]).\n if (glyphs.targetEnd !== \"none\") {\n const tip = pts[pts.length - 1]!;\n const prev = pts[pts.length - 2]!;\n const dir = glyphDir(tip, prev);\n pieces.push(emitGlyph(glyphs.targetEnd, tip, dir));\n }\n\n // Multiplicity / role / mid-edge label — drawn at the LAYOUT-RESERVED anchors\n // (the same AABBs the overlap harness checks; what layout reserves is what svg draws).\n for (const tb of textBoxes) {\n if (tb.relId !== rel.id) continue;\n const italic = tb.slot === \"src-role\" || tb.slot === \"tgt-role\" ? ` font-style=\"italic\"` : \"\";\n const anchor = tb.anchor === \"middle\" ? ` text-anchor=\"middle\"` : \"\";\n const drawX = tb.anchor === \"middle\" ? round(tb.x + tb.w / 2) : tb.x;\n const baseline = round(tb.y + UML_LABEL_FONT * 0.8);\n pieces.push(\n `<text x=\"${drawX}\" y=\"${baseline}\" font-family=\"${FONT_FAMILY}\" font-size=\"${UML_LABEL_FONT}\" fill=\"${LABEL_FILL}\"${anchor}${italic}>${xmlEscape(tb.text)}</text>`,\n );\n }\n }\n\n return `<g data-edge-id=\"${el.edgeId}\">${pieces.join(\"\")}</g>`;\n}\n\n// ── Legend ─────────────────────────────────────────────────────────────────────\n\nfunction makeSwatchLine(isDashed: boolean): (x: number, y: number) => string {\n return (x, y) => {\n const attrs = isDashed\n ? `stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-dasharray=\"4,4\"`\n : `stroke=\"${EDGE_INK}\" stroke-width=\"1.5\"`;\n return `<line x1=\"${x}\" y1=\"${y}\" x2=\"${x + LEGEND_SWATCH_W}\" y2=\"${y}\" ${attrs}/>`;\n };\n}\n\n// ── Main emitter ──────────────────────────────────────────────────────────────\n\nexport interface UmlSvgOptions {\n /** Set false to suppress the legend (default true). */\n legend?: boolean;\n /** Display vocabulary — English default; see locale packs. */\n labels?: UmlSvgLabels;\n}\n\n/**\n * Emits a self-contained SVG string from a computed UmlLayout + the original input.\n * The input is needed for class attributes/operations/stereotype data that the layout\n * only stores in the metrics.\n */\nexport function umlLayoutSvg(\n layout: UmlLayout,\n input: UmlInput,\n opts: UmlSvgOptions = {},\n): string {\n const labels = opts.labels ?? UML_SVG_LABELS_EN;\n const showLegend = opts.legend !== false;\n\n const classMap = new Map(input.classes.map((c) => [c.id, c]));\n const relMap = new Map(input.relationships.map((r) => [r.id, r]));\n\n const parts: string[] = [];\n\n // Boxes\n for (const node of layout.nodes) {\n const cls = classMap.get(node.classId)!;\n parts.push(boxSvg(node, cls));\n }\n\n // Edges\n for (const el of layout.elements) {\n const rel = relMap.get(el.relId);\n if (!rel) continue;\n parts.push(edgeSvg(el, rel, layout.textBoxes));\n }\n\n let canvasW = layout.canvasW;\n let canvasH = layout.canvasH;\n\n // Legend\n if (showLegend) {\n // Collect which kinds are used\n const usedKinds = new Set<UmlRelationshipKind>(\n input.relationships.map((r) => r.kind),\n );\n const entries: LegendEntry[] = [];\n for (const kind of UML_RELATIONSHIPS) {\n if (!usedKinds.has(kind)) continue;\n const isDashed = RELATION_GLYPHS[kind].line === \"dashed\";\n entries.push({\n swatch: makeSwatchLine(isDashed),\n label: labels.legend[kind],\n });\n }\n if (entries.length > 0) {\n const block = legendBlock(entries, canvasH);\n parts.push(block.svg);\n canvasH = block.height;\n canvasW = Math.max(canvasW, block.width);\n }\n }\n\n const roundedW = round(canvasW);\n const roundedH = round(canvasH);\n\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${roundedW}\" height=\"${roundedH}\" viewBox=\"0 0 ${roundedW} ${roundedH}\" role=\"img\" aria-label=\"${xmlEscape(labels.ariaLabel)}\">` +\n parts.join(\"\") +\n `</svg>`\n );\n}\n","// One-call wrapper — validates, lays out, and emits in one step.\n\nimport { computeUmlLayout, type UmlLayout } from \"./layout\";\nimport { umlLayoutSvg, type UmlSvgOptions } from \"./svg\";\nimport { UML_TITLE_LABELS_EN, type UmlTitleLabels } from \"./labels\";\nimport type { UmlInput } from \"./types\";\n\nexport interface UmlRenderOptions extends UmlSvgOptions {\n /**\n * Title-bar vocabulary woven into each element's `<title>` by the layout (the\n * localized relationship-kind word). Defaults to English; pass the pt-BR pack for\n * localized titles. The `labels` field (UmlSvgLabels) controls the legend + aria.\n */\n titleLabels?: UmlTitleLabels;\n}\n\n/**\n * Renders a UML class diagram to SVG in one call.\n *\n * @returns `{ svg, layout }` — svg is the self-contained SVG string; layout is the\n * positioned model for the overlap harness and decorating callers.\n */\nexport function umlSvg(\n input: UmlInput,\n opts: UmlRenderOptions = {},\n): { svg: string; layout: UmlLayout } {\n const layout = computeUmlLayout(input, opts.titleLabels ?? UML_TITLE_LABELS_EN);\n const svg = umlLayoutSvg(layout, input, opts);\n return { svg, layout };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { estimateTextWidth, clampLabel, legendBlock, xmlEscape, FONT_FAMILY, LEGEND_SWATCH_W } from './chunk-
|
|
1
|
+
import { estimateTextWidth, clampLabel, legendBlock, xmlEscape, FONT_FAMILY, LEGEND_SWATCH_W } from './chunk-DVLWT565.js';
|
|
2
2
|
|
|
3
3
|
// src/phylo/labels.ts
|
|
4
4
|
var PHYLO_TITLE_LABELS_EN = {
|
|
@@ -493,5 +493,5 @@ function phyloSvg(input, opts = {}) {
|
|
|
493
493
|
}
|
|
494
494
|
|
|
495
495
|
export { PHYLO_BRANCH_ID_BASE, PHYLO_CLADEBAR_ID_BASE, PHYLO_EXTENSION_ID_BASE, PHYLO_LABEL_FONT, PHYLO_LABEL_GAP, PHYLO_ROOTSTUB_ID_BASE, PHYLO_ROW_SLOT, PHYLO_SCALEBAR_ID, PHYLO_SUPPORT_FONT, PHYLO_SVG_LABELS_EN, PHYLO_TITLE_LABELS_EN, PhyloValidationError, computePhyloLayout, niceScaleStep, phyloIssues, phyloLayoutSvg, phyloSvg, validatePhylo };
|
|
496
|
-
//# sourceMappingURL=chunk-
|
|
497
|
-
//# sourceMappingURL=chunk-
|
|
496
|
+
//# sourceMappingURL=chunk-PJHLWSGD.js.map
|
|
497
|
+
//# sourceMappingURL=chunk-PJHLWSGD.js.map
|