mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-03 01:50:23 +08:00
fix(diagram-engine): slack packs to column top; paragraphs set flush-left
The poster's two ugliest defects were engine policy, not model declarations: - A column stretched by its siblings distributed the slack into gaps (and, via grow, into boxes), producing huge panels with three lines floating in the middle. Slack policy now differs by axis: a ROW still spreads and centres (a flowchart layer reads as a pyramid), a COLUMN packs to the top and leaves leftover space at the bottom — where a reader expects it. - Multi-line body text rendered dead-centre (FALLBACK_BOX's verticalAlign=middle). Typography's basic rule, applied by content: a paragraph (explicit breaks or wrap-length text) sets align=left, verticalAlign=top with padding; a short label stays centred. Rectangles only — inside a rhombus or cloud the safe text area IS the middle. - Prompts corrected: stretch is about width, content keeps natural height, and columns are balanced by moving content — not by inflating boxes. 565 tests green; the same poster declaration re-rendered without the giant hollow panels.
This commit is contained in:
@@ -69,6 +69,18 @@ export function esc(s: string): string {
|
||||
// tags DO need handling is the measure pass (layout.ts autoBoxSize), which must not
|
||||
// count markup as text.
|
||||
|
||||
/**
|
||||
* Is this label a paragraph rather than a short caption?
|
||||
*
|
||||
* Typography's basic rule: labels centre, paragraphs set flush left. The split is by
|
||||
* content — explicit line breaks, or enough text that draw.io will wrap it — because
|
||||
* the model declares WHAT the text is, never how to align it.
|
||||
*/
|
||||
function isParagraph(label: string): boolean {
|
||||
const plain = label.replace(/<[^<>]+>/g, "")
|
||||
return /\n/.test(label) || /<br/i.test(label) || plain.length > 60
|
||||
}
|
||||
|
||||
/** Resolve a catalog name to a style. Injected so the engine does not own the catalog. */
|
||||
export type StyleResolver = (
|
||||
name: string,
|
||||
@@ -168,6 +180,14 @@ function styleFor(
|
||||
n.role || n.group
|
||||
? themedStyle(n.role ?? "body", hue(n.group), "leaf")
|
||||
: undefined,
|
||||
// Typography, decided by the content: a PARAGRAPH sets left and top —
|
||||
// a three-line body floating dead-centre in its box was the poster's
|
||||
// second-ugliest defect — while a short label stays centred. Only for
|
||||
// rectangles: inside a rhombus or a cloud the safe text area is the
|
||||
// middle, which is exactly where centring puts it.
|
||||
isParagraph(n.label) && !n.shape
|
||||
? "align=left;verticalAlign=top;spacingLeft=10;spacingRight=10;spacingTop=8;"
|
||||
: undefined,
|
||||
n.fill ? `fillColor=${n.fill};` : undefined,
|
||||
n.stroke ? `strokeColor=${n.stroke};` : undefined,
|
||||
n.bold ? "fontStyle=1;" : undefined,
|
||||
|
||||
Reference in New Issue
Block a user