Pre-release - MIT - your file stays local

Any SVG, a diagram you can edit.

draw.io opens an SVG file as one flat image. accent-draw opens it as a diagram. Each box is a box, each label is in its box, and each arrow connects the two shapes at its ends. Open the demo, select a file, and edit the result.

$ accent-draw board.svg board.drawio

flow.drawio
Draft Review Publish Move the box: its label and both arrows move with it.

The pipeline

Five stages, each with one job

It is easy to show a drawing again. It is difficult to find the diagram in it. An SVG file says "a rectangle here, some text there, a path with an arrowhead". draw.io must know "this box, with this label, and an arrow from it to that box". A usual SVG file does not tell which text is the label of which box. One stage finds this, and you can test that stage alone.

  1. recognise

    Some sources give names to their parts: Miro, Mermaid, Graphviz, PlantUML, D2, Excalidraw and Inkscape. accent-draw reads these names. An SVG file that contains a draw.io diagram goes back without a change.

  2. parse

    The parser reads all other parts of the SVG: the style rules, the transforms, the viewBox, nested svg elements, use and defs, and the units. A rectangle stays a rectangle, and an arrowhead stays an arrowhead.

  3. scene

    The scene is a list of shapes, text, arrows, frames and groups. It contains no draw.io data. A test checks each file in the corpus against the rules of the scene.

  4. layout

    The layout finds what the source did not tell. It finds the label of each box, the frame around other shapes, and the shapes at the ends of each arrow. It adds only the data that the source did not give. It does not change what a profile read.

  5. emit

    The emitter writes the scene as an mxGraphModel. The cell ids are stable and all numbers have one format. Thus the same input gives the same bytes, and a change gives a diff that you can read.

Measured

Four numbers that support this page

We took each number from this repository. We did not make the numbers larger for this page. The numbers are the profiles and the tests that run for each change. They are also the size of the file that your browser downloads, and the data that the page sends.

8 sources that accent-draw reads by the names of their parts
340 tests that run for each change
368 KB the converter, compressed with gzip - the only download
0 bytes of your drawing that the page sends

What you get

What the conversion does

The list is short. We made the code around each item on it.

Each box keeps its label, and each arrow keeps its boxes

When you move a box in draw.io, its label moves with it. The label is part of the cell, not a separate text box on top of it. The arrows also move with the box. Each connected arrow has the fixed points exitX/exitY and entryX/entryY. Without these points, draw.io gives the arrow a new route, and the arrow loses its route from the source.

Eight sources, read by name

When a source gives names to its parts, accent-draw reads the names and does not guess. It reads a Miro board item by item. It reads a Mermaid flowchart and a Graphviz drawing by the names on their nodes and edges. It reads an Excalidraw file from the scene in the file, not from the sketch. The parser reads the parts that a profile does not name.

Each change is in a note

Some parts cannot become a draw.io cell: a filter, a mask or a pattern. Each of these parts becomes an image, and a note in the result tells you about it. An SVG file that contains no shape, text or arrow causes an error. You do not get an empty diagram that looks correct.

The second round trip loses nothing

The first conversion is an approximation, and it will always be one. But draw.io can export a .drawio.svg file, which contains the diagram. accent-draw does not convert the image in such a file. It gives back the diagram in the file, compressed or not. Thus each round trip after the first is exact.

It runs where you are

The library does not use files, the clock, random numbers or threads. Thus the same code is a command for a shell script and a WebAssembly module in a web page. The demo on this site uses the WebAssembly module. Your browser downloads the converter one time, and your file stays in the browser tab.

The same bytes each time

The cell ids are stable and all numbers have one format. Thus two conversions of the same SVG file give the same file, and a diff shows a real change. The browser and the command line give the same result. For each change, a test converts the corpus with both and compares the bytes.

Why this is difficult

A Miro export gives the structure to the reader. Each item on the board is a group, and each group has the id of its item. Thus a Miro reader can be exact. But for the same reason, a Miro reader does not work on other files. The Miro reader in this repository read a plain SVG file with a rectangle, a circle and some text. It wrote an empty diagram and told you that the conversion was correct.

For other files, accent-draw must find the structure from the positions of the parts. Some shapes are on top of other shapes: which shape is the box, and which is its border? An outline has no fill: is it a frame, or only a line in the drawing? The stroke of an arrow stops before its arrowhead: which of two near boxes does the arrow touch?

These decisions cause most errors. Thus one stage makes all of them. Each limit in that stage changes with the font size or the stroke width. No limit is a fixed number of pixels. A corpus of real exports tests the stage.

draw.io has its own rules. A <b> tag in a label removes the color of the label. draw.io moves a connected arrow to a new route if the arrow has no fixed points. A label is at the center if the style does not tell a different position. A label also has two units of space on each side.

You cannot see these problems in the XML, but you can see them in an image. Thus for each change, we look at the source SVG file and the diagram side by side.

Try it on your drawing

The demo has nine samples. Seven come from the sources that accent-draw reads by name, and two name no parts. You can also use your own file. The converter runs in the page, and the page sends no data.