mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-01 17:10:24 +08:00
feat(diagram-engine): flex knobs (grow/align/pad) + inline rich-text labels
The expressiveness gap between engine output and hand-written XML came down to two missing capabilities, both generic: - Block layout inside a box: nested containers already existed, but there was no way to split space by weight, pin a child to an edge, or tighten padding. Added grow (flex-grow over the parent's leftover flow-axis space, TeX's glue), align (start/center/end/stretch on the cross axis) and pad (per-group interior padding). All three round-trip via dai_grow/dai_align/ dai_pad markers. - Inline rich text: labels already render HTML (html=1 on every style, esc() entities decode back), but the measure pass counted markup as text. The visibleText() strip makes autoBoxSize measure what draw.io draws: <br> is a line, other inline tags are invisible. Graphviz (HTML-like table labels), D2 (grid containers + markdown-in-shape) and TeX (box+glue) converged on exactly this design: nested boxes for block structure, proportional glue, a small inline set for text — never full HTML. Prompts teach the composition with a comparison-card recipe; verified by rebuilding the CoT poster end to end in the real editor.
This commit is contained in:
@@ -29,6 +29,7 @@ import {
|
||||
isPinned,
|
||||
MARKER,
|
||||
type NodeKind,
|
||||
readAlign,
|
||||
readCell,
|
||||
readDir,
|
||||
readIntMarker,
|
||||
@@ -360,6 +361,19 @@ function zoneOf(style: string): string | undefined {
|
||||
return v ? decodeURIComponent(v) : undefined
|
||||
}
|
||||
|
||||
/** The flex fields stamped on a cell, as sparse properties ready to spread. */
|
||||
function flexOf(style: string): {
|
||||
grow?: number
|
||||
align?: "start" | "end" | "stretch"
|
||||
} {
|
||||
const grow = readIntMarker(style, MARKER.grow)
|
||||
const align = readAlign(style)
|
||||
return {
|
||||
...(grow !== null && grow > 0 ? { grow } : {}),
|
||||
...(align ? { align } : {}),
|
||||
}
|
||||
}
|
||||
|
||||
function boxShape(style: string): BoxShape | undefined {
|
||||
const shape = styleValue(style, "shape")
|
||||
if (shape === "parallelogram") return "data"
|
||||
@@ -1070,6 +1084,7 @@ export function parseDiagram(xml: string, pageIndex = 0): ParseResult {
|
||||
shape: boxShape(c.style),
|
||||
role: roleOf(c.style),
|
||||
group: zoneOf(c.style),
|
||||
...flexOf(c.style),
|
||||
// A lifeline's style is chrome the renderer rebuilds, so keeping it verbatim
|
||||
// would re-emit a lifeline that no longer matches the new message count.
|
||||
style: lifeline ? undefined : c.style,
|
||||
@@ -1215,12 +1230,15 @@ export function parseDiagram(xml: string, pageIndex = 0): ParseResult {
|
||||
}
|
||||
return node
|
||||
}
|
||||
const markedPad = readIntMarker(c.style, MARKER.pad)
|
||||
const node: GroupNode = {
|
||||
kind: "group",
|
||||
...common,
|
||||
dir: dir === "col" ? "col" : "row",
|
||||
role: roleOf(c.style),
|
||||
group: zoneOf(c.style),
|
||||
...flexOf(c.style),
|
||||
...(markedPad !== null ? { pad: markedPad } : {}),
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user