/** * Pure geometry + edge-styling helpers for the drawio SVG preview. * * Dependency-free (no React, no DOM globals) so it compiles under any TS `lib` * and runs in the Node test harness (mocha + ts-node/esm). The renderer parses * drawio XML into `CellData` plain objects, then calls these functions to derive * the SVG viewBox, node rectangles, and edge paths/markers. * * GH-482: the preview must honor the drawio XML geometry 1:1 — node positions and * sizes map verbatim to the SVG viewBox (no re-layout), and edge waypoints are * drawn through their exact baked points. */ export type StyleMap = Record; export type CellData = { id: string; value: string; style: StyleMap; parentId: string; isVertex: boolean; isEdge: boolean; sourceId: string; targetId: string; geometry: { x: number; y: number; width: number; height: number; relative: boolean; }; sourcePoint?: { x: number; y: number; }; targetPoint?: { x: number; y: number; }; waypoints?: Array<{ x: number; y: number; }>; }; export type Point = { x: number; y: number; }; export type ViewBox = { minX: number; minY: number; width: number; height: number; }; /** * Resolve a cell's absolute top-left position by accumulating ancestor offsets. * Nested cells (table rows, row fields) carry geometry relative to their parent, * so the absolute coordinate is the sum up to the root layers ('0'/'1'). */ export declare function absPos(id: string, map: Map): Point; /** * Compute the drawio coordinate-space bounds over ALL positioned cells, plus a * margin, so the SVG viewBox maps 1:1 onto the editor canvas (GH-482). Every node * then renders at its EXACT mxGeometry without any re-layout. */ export declare function computeViewBox(cells: CellData[], map: Map, margin?: number): ViewBox; /** * Point on a cell's border where an edge toward `other` should attach. Rectangles * use the box border; rhombus/diamond shapes meet the slanted side so the arrow * touches the actual outline, not a bounding-box corner (GH-427). */ export declare function connPoint(cell: CellData, map: Map, other: Point): Point; /** True when the edge carries explicit baked waypoints to honor verbatim. */ export declare function hasWaypoints(edge: CellData): boolean; /** * Build an SVG path through verbatim waypoints (GH-482): source → wp[0] → … → * target. Since nodes are no longer repositioned, baked waypoints are trustworthy * (the GH-427 "stale coords" problem only existed because of the removed reflow). */ export declare function waypointPath(source: Point, waypoints: Point[], target: Point): string; /** * Clean orthogonal (elbow) route between two border anchors when an edge has NO * waypoints. Uses a single vertical riser at the horizontal midpoint; degrades to * a straight segment when the anchors are essentially aligned. */ export declare function orthogonalPath(source: Point, target: Point): string; /** Angle (degrees) of the vector a→b, for orienting an arrowhead. */ export declare function angleDeg(ax: number, ay: number, bx: number, by: number): number; /** * ER crow's-foot marker paths (cardinality). Returns '' for non-ER markers so the * caller can fall back to a directional arrowhead. */ export declare function crowFootPath(type: string): string; /** * Rotation (degrees) for a crow's-foot marker anchored on a table/row border. The * marker path splays its feet at local x=0 and converges at +x, so on the RIGHT * border (line exits to +x) it draws unrotated (apex →+x, outside); on the LEFT * border it rotates 180 (apex →−x, outside); on the TOP border it rotates 270 * (apex →−y, upward); on the BOTTOM border it rotates 90 (apex →+y, downward), for * vertical links (GH-565). Decided purely by which side of the table the anchor * sits on. Shared by the CLI headless painter and the web-console viewer (GH-727 * follow-up) — do not re-duplicate this into either caller. * * `sourceAnchorX` is the x of the edge's OWN source anchor (not necessarily this * marker's anchor) — it's the fallback comparison point when no table cell is * found for `cell`, matching each caller's original closed-over behavior. */ export declare function crowFootRotation(anchor: Point, cell: CellData | undefined, cellMap: Map, sourceAnchorX: number): number; export type ArrowHead = { d: string; filled: boolean; }; /** * Directional arrowhead path for non-ER edges (flowchart, sequence). drawio uses * `endArrow`/`startArrow=classic|block|open|diamond|oval|none|...`. Returns a small * marker pointing along +X (the caller rotates it to the edge direction); `filled` * distinguishes solid markers from open/hollow ones. `none`/'' → no marker (GH-481). */ export declare function arrowHeadPath(type: string): ArrowHead | null; export type EdgeStroke = { stroke: string; strokeWidth: number; /** SVG `stroke-dasharray` value, or undefined for a solid line. */ dashArray?: string; }; /** * Resolve an edge's stroke from its parsed drawio style: color, width, and dash * pattern. `dashed=1` → dashed; `dashed=1;dashPattern=1 4` (dotted) → fine dots * (GH-481 edge-style completeness). */ export declare function edgeStroke(style: StyleMap): EdgeStroke; /** * Wrap a content `` group into a standalone, width/height-stamped SVG string * for off-screen capture (e.g. PDF export). `inner` is the serialized inner markup * (the translated `` and its children); `viewBox` sets the coordinate space. */ export declare function wrapContentSvg(inner: string, viewBox: ViewBox): string; /** * Classify an edge into a render layer so plain-shape (flowchart) edges paint ABOVE * their nodes while ER/table relations paint BELOW (tables have opaque fills that * would otherwise hide a line drawn beneath them). Tables are detected via the * caller-supplied id set (GH-480 above-shapes edge layering). */ export declare function classifyEdgeLayer(edge: CellData, tableIds: Set, map: Map): 'above' | 'below';