Profiles
Where a source labels its own parts, reading beats guessing. Eight of them do, each in its own way, and each is read by the names it writes rather than from the picture it drew.
A profile recognises its source, reads what that source names, and hands the result to the same layout and the same emitter as everything else. None of them writes draw.io itself.
What a profile does not name, the picture reader draws around it: each hands back the subtrees it read, the parser skips those, and the rest is appended. A PlantUML diagram with a title is read as a diagram and keeps its title, where one stray line used to send the whole file down the picture path.
The order they are tried in
| Source | Recognised by | What it hands over |
|---|---|---|
| draw.io | a diagram in the root's content attribute | The diagram itself. Nothing is converted |
| Miro | data-widget-id on each item's group | Each sticker, card, table, connector and mind-map branch as the board names it, and the canvas colour |
| Mermaid | aria-roledescription="flowchart-v2" | Nodes with their own words inside them; each edge's id holds the keys of the two nodes it joins |
| Graphviz | <g class="graph"> with titled parts | A node's name, an edge's from->to, a cluster's own title |
| PlantUML | <g class="entity" data-qualified-name> | Each entity by name, and which two a link joins |
| D2 | data-d2-version | Every name, base64-encoded into the class of the group that draws it |
| Excalidraw | svg-source:excalidraw | The whole scene the file carries, including where on a shape each arrow attaches |
| Inkscape | inkscape:connection-start | Only which two objects each connector joins. The drawing is read as a picture |
draw.io: handed back, not converted
draw.io's own SVG export - .drawio.svg - is a picture with the diagram tucked
inside the root element's content attribute. That diagram is returned as it
is, whether it is plain XML or base64 of raw deflate of the URI-encoded XML.
This is what makes the roundtrip worth having. The first conversion of a drawing is lossy and always will be; every trip after it is exact, because the file carries the diagram and the diagram is what comes back. A carried diagram that does not read is reported, and the picture converted instead.
Miro: a board, not a picture
Miro tags every board item with its own id, which is why a reader for it can be precise - and exactly why it does not generalise. A sticker comes out as a sticker with its words inside it, a connector as an edge glued to the shapes it joins. The page is painted the colour of the board's own canvas, so a white card has something to stand against.
A widget that cannot be read is reported. A board in which none of them reads is converted as a picture, with a note saying so.
Mermaid, Graphviz, PlantUML, D2
These four share what they read of an SVG's own drawing, and differ only in where the names are:
- Mermaid names its nodes and edges, and an edge's id holds the keys of both nodes it joins, so each edge is glued to the two nodes it names rather than to whatever lies nearest. Mermaid's other diagram types - sequence, class - name nothing, and are read as pictures.
- Graphviz titles every part of itself. Edges join the nodes their titles
name, labels belong to the parts they title, and the white polygon behind the
graph becomes no cell at all. Graphviz states its size in points, so its
drawing is a third larger than its own coordinates say - a root
viewBoxis a map like a transform, and is read as one. - PlantUML names each entity and says which two a link joins. A class comes out as one box carrying its name and its members, and a composition as the filled diamond UML draws it with. What a class paints besides its box and its words - its badge, the rules between compartments - is reported rather than drawn. Sequence diagrams name nothing and are read as pictures.
- D2 encodes every name in base64 into the class of the group that draws it, and names an edge for the two nodes it joins and the way it points. This profile matters more than the others: D2 draws every connector through a mask, which cannot be drawn natively, so a D2 drawing read as a picture comes out with no edges at all.
Excalidraw: the scene, not the sketch
Excalidraw sketches. Every shape is several overlapping strokes and nothing in the drawing is named, so reading its picture would be guesswork over guesswork.
But an Excalidraw file exported with its scene carries Excalidraw's own model - base64, then a byte-string JSON, then zlib - and that model says more than any other source here: not only which shape an arrow joins, but where on that shape it attaches. Freehand strokes, embedded pictures and frames come from the scene too. A drawing exported without its scene is a picture, and is read as one.
Inkscape: the other way round
Inkscape produces artwork rather than diagrams, so the picture reader draws it and the profile adds one thing: Inkscape's connector tool records which two objects each connector runs between, and those ends are glued to them.
That matters most where the shapes are outlines rather than filled boxes, which no geometry would confidently glue an arrow to. The drawing says which box each arrow joins, so the arrows follow their boxes however the boxes were drawn.
Adding one
A profile is worth writing when a source labels its own parts and the labels mean something. It needs a way to recognise its source, a reading of the names into the scene, a corpus file in the repository to be tested against, and a side by side render showing it draws what the source drew. The order of the list above follows market demand, not difficulty.