draw.io

The entry point @tiptap-pro/extension-diagrams/drawio draws diagrams stored as draw.io XML. It also connects the draw.io editor, so you can change those diagrams there. It draws no charts.
New tab

Quick start

import { Diagrams } from '@tiptap-pro/extension-diagrams'
import { drawioDiagramRenderer } from '@tiptap-pro/extension-diagrams/drawio'
import rendererUrl from '@tiptap-pro/extension-diagrams/drawio-renderer?url&no-inline'
import viewerUrl from './vendor/drawio/viewer-static.min.js?url'

Diagrams.configure({
  diagramRenderers: [drawioDiagramRenderer({ viewerUrl, rendererUrl })],
})

Options

OptionTypeDescription
viewerUrlstringRequired. The draw.io viewer, viewer-static.min.js from a draw.io release (src/main/webapp/js/ in the jgraph/drawio repository). It is not on npm, so serve it yourself
rendererUrlstringRequired. @tiptap-pro/extension-diagrams/drawio-renderer, served as a file. With Vite, ?url&no-inline
scriptNoncestring | nullFor pages with a nonce-based Content Security Policy
idstringDefault 'drawio'
labelstringDefault 'draw.io'

What a draw.io source is

A diagram with format: 'drawio' holds draw.io XML:

editor.commands.insertFlowDiagram({ source: drawioXml, format: 'drawio', title: 'Order process' })
  • The source is an <mxfile> or a bare <mxGraphModel>.
  • The document stores an <mxfile> whose pages are plain XML, so you can read and compare the stored text.
  • A bare model becomes a file with one page.
  • A page that draw.io compressed is uncompressed. A page that cannot be uncompressed is kept as it is.
  • Pasting draw.io XML as text gives a draw.io diagram.

insertFlowDiagram and updateFlowDiagram return false for anything else, and for source longer than 1,000,000 characters.

updateFlowDiagram({ source, format }) changes a diagram's format, for example when a Mermaid diagram comes back from the draw.io editor. A new format needs a new source in the same call.

How it draws

The draw.io viewer runs in one hidden iframe per page, with sandbox="allow-scripts" and a policy that allows no network request. It loads the first time a draw.io diagram is drawn, and is about 4.4 MB, or 940 kB compressed. Drawing takes tens of milliseconds, and the result is cached by source.

What the diagram looks like

  • Colors. A diagram keeps the colors it was drawn with. The --tt-flow-diagram-* custom properties do not reach it.
  • Background. A diagram is drawn on its own background, or on white.
  • Color scheme. The SVG follows the page's light or dark color scheme where draw.io supports it.
  • HTML labels are drawn.
  • Links in labels do nothing, because the diagram is shown as an image.
  • Stencil shapes from AWS, Azure, Cisco and other libraries draw as empty boxes. The viewer cannot load their files in the sandbox.
  • Images in a diagram must be data: URLs.

In an export

  • PNG, WebP, JPEG and Word. Labels are plain text. Bold, colors and line breaks written as HTML inside a label are lost.
  • On a server. A draw.io diagram cannot be exported, because the viewer lays out text in a browser.

Editing in the draw.io editor

The entry point connects the draw.io editor in its JSON embed mode. You build the dialog and the iframe, and the package gives you what the editor saves.

import { connectDrawioEditor, drawioEditorUrl } from '@tiptap-pro/extension-diagrams/drawio'

const frame = document.createElement('iframe')
frame.src = drawioEditorUrl() // https://embed.diagrams.net/?embed=1&proto=json…
dialog.append(frame)

const connection = connectDrawioEditor(frame, {
  source: diagram.source,
  title: diagram.title ?? undefined,
  onSave: (source) => editor.commands.updateFlowDiagram({ pos, source, format: 'drawio' }),
  onExit: () => {
    connection.destroy()
    dialog.close()
  },
})

drawioEditorUrl(options?)

Builds the editor URL.

OptionTypeDescription
basestringThe draw.io editor. Default https://embed.diagrams.net/. Point it at your own copy to keep diagrams off a third-party origin
saveAndExitbooleanOffers Save and Exit next to Save. Default true
paramsRecord<string, string>Adds editor URL parameters, such as lang

connectDrawioEditor(frame, options)

Opens a diagram in the editor in frame. Returns { destroy }.

OptionTypeDescription
sourcestringThe draw.io XML to open. Empty opens a blank page
mermaidstringMermaid source to open instead. The editor converts it to draw.io shapes, and a subgraph to a swimlane
titlestringShown in the editor's title bar
onSave(source, { exit })(source, { exit }) => voidRequired. Called with the XML on Save, and with exit: true on Save and Exit
onExit()() => voidRequired. Called when the editor closes, also after Save and Exit
onAutosave(source)(source) => voidWhen set, called with the XML after every change
onError(message)(message) => voidCalled when the editor could not open the source, or sent something that is not draw.io XML
  • The diagram is posted only to the origin of the iframe's URL.
  • Messages are read only from that iframe and origin.
  • What onSave receives is normalized like any stored draw.io source. See What a draw.io source is.
  • The editor works on a copy. If others change the same diagram while it is open, the next save replaces their changes.

From Mermaid to draw.io

Open a Mermaid diagram with the mermaid option and save it with format: 'drawio'. It becomes a draw.io diagram. You can go back to Mermaid only with undo.

Hosting the editor yourself

The draw.io editor is a static web app, published as the jgraph/drawio Docker image:

docker run --rm -p 8080:8080 jgraph/drawio
frame.src = drawioEditorUrl({ base: 'http://localhost:8080/' })
  • The diagram is posted only to that origin, so nothing reaches draw.io's servers.
  • Serve it over HTTPS if your page is served over HTTPS.
  • Nothing else changes. The embed protocol is the same as on embed.diagrams.net.
  • Editing then works without an internet connection. Web fonts in labels and online shape libraries still need the network.
  • Pin the image to a tag. Update it together with the viewer you serve as viewerUrl, so the editor and the viewer read the same XML.