Files
sap-architecture/references/drawio-gotchas.md
T
2026-07-24 20:47:16 +00:00

5.9 KiB
Raw Blame History

draw.io / mxGraph authoring gotchas

Encoding and alignment rules that apply whenever this skill writes or edits mxCell XML directly — i.e. during surgical relabels (step 4), when adding cards/edges next to template cells, and in render_semantic.py-derived output. Violations are silent at write time and only visible when the user opens the file: blank icons, "duplicate id" rejections, or connectors cutting through artwork. validate.py mechanically checks §§12 and the structural parts of §7.

Scaffolded SAP templates already satisfy all of this — these rules matter for the cells you add or change.

1. Embedded-image data URIs must OMIT ;base64

draw.io style strings are ;-delimited key=value lists. A standard data URI (data:image/svg+xml;base64,PHN2...) contains a ; — draw.io truncates the image= value at that semicolon and starts parsing base64,PHN2... as a new style key. Result: every icon renders blank, with no error.

  • Correct (draw.io style): image=data:image/svg+xml,PHN2Zy8+; (payload IS still base64-encoded; only the ;base64 marker is dropped — draw.io's own convention, and what the bundled SAP libraries ship.)
  • Incorrect: image=data:image/svg+xml;base64,PHN2Zy8+;
  • Plain SVG/HTML is the opposite: an <image href> requires the standard ;base64 form. If you generate both a .drawio and an SVG preview from the same data, the two encodings must differ.

extract_icon.py / extract_asset.py emit the correct form — this rule bites only when embedding a third-party logo or UI5 icon-font SVG by hand.

2. Root-cell skeleton and reserved ids

Every diagram page must begin with a parentless root cell, then a layer cell parented to it, before any content:

<mxCell id="0" />
<mxCell id="1" parent="0" />

0/1 are mxGraph's defaults, but the SAP corpus frequently uses namespaced equivalents (<prefix>-0, <prefix>-1) — the structure is what matters, and validate.py checks it. Two failure modes for hand-authored pages:

  • Omitting the two root cells entirely → draw.io rejects the file.
  • A content cell reusing the page's root/layer id (easy when deriving ids from numeric counters, colliding with literal 0/1) → "duplicate id", whole file rejected. Namespace generated ids (n-<id>, edge-3, pill-2).

Ids must be unique within a page; each <diagram> page has its own id space.

3. Z-order is document order

Later cells render on top. Emit edges before vertices so connectors sit behind nodes/icons (SAP's files do this; they never rely on opaque icon backings). draw.io resolves an edge's source/target by id even when those cells are declared later — forward references are fine. When inserting new cards into a template, insert them after the edges that touch them.

4. Connectors must attach to facing connection points

Without fixed connection points, draw.io anchors edges center-to-center and a line can cut straight through nodes that sit between endpoints. Give every added edge directional exit/entry on the border side facing the counterpart:

exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;

(source's right edge → target's left edge, for a left-to-right flow; use Y 0/1 with X 0.5 for vertical). Combine with edgeStyle=orthogonalEdgeStyle; rounded=0;orthogonalLoop=1;jettySize=auto; so the router runs segments through the gaps between columns. Z-order alone is never the fix for edges crossing icons. This complements the center-alignment rule in shapes-and-edges.md: aligned centers make the edge straight; facing anchors make it dock on the correct sides.

5. Explicit waypoints

To force a route (e.g. through a routing channel between zones), put bend points inside the edge geometry — intermediate points only; endpoints come from the cells:

<mxGeometry relative="1" as="geometry">
  <Array as="points"><mxPoint x="520" y="140"/><mxPoint x="520" y="260"/></Array>
</mxGeometry>

Keep waypoint coordinates on the 10-px grid like everything else.

6. Image aspect ratio & inscription

imageAspect=1 preserves proportions (0 stretches to the cell box — wide wordmark logos become distorted). The SAP corpus itself uses imageAspect=0 on cells whose geometry was hand-sized to the artwork, so this is not a validator check — it's a rule for logos you embed, where the cell box rarely matches the source aspect exactly. In SVG the equivalent is preserveAspectRatio="xMidYMid meet". Square logos placed on a circular tile must be inscribed: icon side ≤ tile diameter / √2, or the corners poke past the circle (e.g. a 52-px tile fits at most a ~36-px square icon).

7. Structure & page setup

  • Skeleton: <mxfile><diagram id="..." name="..."><mxGraphModel ...><root> + the two reserved cells, then content. Emit uncompressed XML — never the base64-deflate <diagram> payload form.
  • Every vertex needs vertex="1" + <mxGeometry x y width height as="geometry"/>; every edge edge="1" + resolvable source/target (or explicit sourcePoint/targetPoint for floating edges); every cell (except 0) a valid parent.
  • Children of a container (container=1 or any parented vertex) use coordinates relative to the parent, not the canvas. When re-parenting an icon into a card (the "tucked inside a card" pattern), convert its x/y to card-local values.
  • Escape XML in labels/attrs: & < >&amp; &lt; &gt;; html=1 when the label carries HTML.

8. Edge routing extras seen in the SAP corpus

  • entityRelationEdgeStyle — perpendicular jetty stubs; SAP uses it for indirect flows where orthogonal elbows would read as a direct chain.
  • targetPerimeterSpacing=15 — leaves a visual gap before the target border so arrowheads don't kiss the stroke.
  • jumpStyle=none — edge crossings drawn flat, no hop arcs. Don't enable jumps; SAP's published files never use them.