mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-01 17:10:24 +08:00
feat(diagram-engine): corners, borderless fills, shadows and strikethrough
Four more Tailwind classes, all four verified against draw.io's own source in
public/drawio rather than against a prose reference — which is how three earlier
exclusions turned out to be wrong:
rounded-* mxShape.js:1172-1189 — absoluteArcSize=1 switches arcSize to
absolute pixels and halves it, so the same class is the same
corner on every box. Previously excluded as 'percentage only'
shadow-sm..xl mxShape.js:505-535 — getShadowStyle reads five independent
params, not one flag, so Tailwind's offset+blur rungs map one
to one. Previously excluded as 'six sizes collapse to one'
line-through mxConstants.js:2054 FONT_STRIKETHROUGH: 8, read at both
mxText.js:723 and :1040. The bitmask has four bits, not three
border-none the only one of the four that adds something previously
inexpressible: a fill with no outline
Also fixes an edge style growing 76 characters per re-layout, without bound. The
router recomputes ports on every pass, and appending them to a style recovered
from the canvas — which already carried the previous pass's eight port keys —
grew the string forever. draw.io resolves duplicates last-wins so the arrow
always looked right; a byte-identity check is what caught it.
Two traps found while wiring the readback, both the same shape: a value the
THEME emits being recorded as one the model asked for. strokeColor=none from a
filled or ghost role, and rounded=0 from the fallback style. Either one would
outlive a set_role, since that clears style but keeps text.
Deliberately not included, with reasons in tw.ts: per-side borders and per-corner
radius (both would take the shape slot, and what a node IS matters more than
which of its edges show), per-side padding (draw.io's keys pad the label, not the
room left for children), text-shadow (a bare flag with no offset or blur),
opacity (Tailwind's is any integer, not a scale), tracking/uppercase/leading
(absent from draw.io — zero grep hits, not merely coarse).
615 tests, 90 new. Browser-verified: four shadow rungs visibly differ, radius is
real pixels, terminator + rounded-lg becomes a small-cornered rounded rect while
an untouched terminator stays a stadium.
This commit is contained in:
@@ -348,6 +348,35 @@ describe("edges survive", () => {
|
||||
})
|
||||
expect(renderDiagram(t).xml).not.toContain('as="points"')
|
||||
})
|
||||
|
||||
it("an edge's style does not grow across repeated re-layouts", () => {
|
||||
// The router recomputes the connection points every pass, and an edge recovered from
|
||||
// the canvas already carries the previous pass's set. Appending them added 76
|
||||
// characters per round-trip forever. draw.io resolves duplicate keys last-wins, so
|
||||
// the arrow always LOOKED right — only measuring the string catches it.
|
||||
let t = tree([group("f", "row", [icon("a"), icon("b")], "F")], {
|
||||
links: [{ source: "a", target: "b" }],
|
||||
})
|
||||
const styleOfEdge = (xml: string) =>
|
||||
/<mxCell id="ed1"[^>]*style="([^"]*)"/.exec(xml)?.[1] ?? ""
|
||||
|
||||
const lengths: number[] = []
|
||||
const portCounts: number[] = []
|
||||
let xml = ""
|
||||
for (let pass = 0; pass < 4; pass++) {
|
||||
xml = renderDiagram(t).xml
|
||||
const s = styleOfEdge(xml)
|
||||
lengths.push(s.length)
|
||||
portCounts.push((s.match(/exitX=/g) ?? []).length)
|
||||
t = parseDiagram(xml).tree
|
||||
}
|
||||
|
||||
// Same length every pass, and the port keys stated once rather than accumulating.
|
||||
expect(new Set(lengths).size).toBe(1)
|
||||
expect(portCounts).toEqual([1, 1, 1, 1])
|
||||
// Which is what lets the XML itself reach a fixed point.
|
||||
expect(renderDiagram(parseDiagram(xml).tree).xml).toBe(xml)
|
||||
})
|
||||
})
|
||||
|
||||
describe("foreign cells survive", () => {
|
||||
|
||||
Reference in New Issue
Block a user