BPMN

The entry point @tiptap-pro/extension-diagrams/bpmn draws diagrams stored as BPMN 2.0 XML with bpmn-js. It also connects the bpmn-js modeler, so you can change those diagrams there. It draws no charts.
New tab

Quick start

import { Diagrams } from '@tiptap-pro/extension-diagrams'
import { bpmnDiagramRenderer } from '@tiptap-pro/extension-diagrams/bpmn'
import rendererUrl from '@tiptap-pro/extension-diagrams/bpmn-renderer?url&no-inline'
import viewerUrl from 'bpmn-js/dist/bpmn-viewer.production.min.js?url&no-inline'

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

editor.commands.insertFlowDiagram({ source: bpmnXml, format: 'bpmn', title: 'Payment check' })

bpmn-js is not a dependency of the package. Install it yourself, serve its bundles as files, and accept its own license.

Options

OptionTypeDescription
viewerUrlstringRequired. A bpmn-js bundle: bpmn-js/dist/bpmn-viewer.production.min.js. The modeler bundle works too
rendererUrlstringRequired. @tiptap-pro/extension-diagrams/bpmn-renderer, served as a file. With Vite, ?url&no-inline
scriptNoncestring | nullFor pages with a nonce-based Content Security Policy
idstringDefault 'bpmn'
labelstringDefault 'BPMN'

How it draws

bpmn-js runs in one iframe per page, with sandbox="allow-scripts" and a policy that allows no network request. The iframe is laid out off screen, because bpmn-js measures labels while it draws. It loads for the first BPMN diagram, and each drawing is cached by source.

  • Layout. The XML must carry its layout (BPMN DI), as a modeler saves it. A process without a layout does not draw.
  • Colors. A diagram is drawn black on white, on a page of its own. The --tt-flow-diagram-* custom properties do not reach it.
  • PNG, WebP, JPEG and Word exports. Labels are SVG text, so the file looks like the diagram in the editor.
  • On a server. A BPMN diagram cannot be exported, because bpmn-js lays out text in a browser.

The bpmn.io attribution

The Renderer's rules ask for a "Powered by bpmn.io" link with the bpmn.io logo. It is shown below the diagram and drawn into every exported file. rendererRules cannot remove it. See Rules of your Renderer.

What a BPMN source is

  • The root element is definitions in the namespace http://www.omg.org/spec/BPMN/20100524/MODEL, under any prefix. The root element declares the namespace.
  • The XML ends with the closing tag of that root element, such as </bpmn:definitions>.
  • The document stores it as written, layout included. Only a byte-order mark and the white space around the XML are removed.
  • Empty source is allowed, for a process you have not modeled yet.
  • Pasting BPMN XML as text gives a BPMN diagram.
  • detectDiagramInput returns { kind: 'bpmn' } for it.

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

Editing in the modeler

connectBpmnEditor runs the bpmn-js modeler in an iframe you created, sandboxed with scripts only, and opens a diagram in it. You build the dialog, the iframe and the buttons. The package gives you the XML when you ask for it.

import { connectBpmnEditor } from '@tiptap-pro/extension-diagrams/bpmn'
import rendererUrl from '@tiptap-pro/extension-diagrams/bpmn-renderer?url&no-inline'
import fontUrl from 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css?url&no-inline'
import bpmnStyleUrl from 'bpmn-js/dist/assets/bpmn-js.css?url&no-inline'
import diagramStyleUrl from 'bpmn-js/dist/assets/diagram-js.css?url&no-inline'
import modelerUrl from 'bpmn-js/dist/bpmn-modeler.production.min.js?url&no-inline'

const frame = document.createElement('iframe')
dialog.append(frame)

const connection = connectBpmnEditor(frame, {
  modelerUrl,
  rendererUrl,
  styleUrls: [diagramStyleUrl, bpmnStyleUrl, fontUrl],
  source: diagram.source,
  onReady: () => (saveButton.disabled = false),
})

saveButton.onclick = async () => {
  const source = await connection.save()
  editor.commands.updateFlowDiagram({ pos, source, format: 'bpmn' })
  connection.destroy()
  dialog.close()
}

connectBpmnEditor(frame, options)

OptionTypeDescription
modelerUrlstringRequired. The bpmn-js modeler bundle, bpmn-js/dist/bpmn-modeler.production.min.js
rendererUrlstringRequired. @tiptap-pro/extension-diagrams/bpmn-renderer, the same file the Renderer uses
styleUrlsreadonly string[]Required. The modeler's stylesheets: diagram-js.css, bpmn-js.css and bpmn-font/css/bpmn-embedded.css
scriptNoncestring | nullFor pages with a nonce-based Content Security Policy
sourcestringThe BPMN XML to open. Empty opens a new process with a start event
onReady()() => voidCalled when the diagram is open and can be edited
onChange()() => voidCalled after every change in the modeler
onError(message)(message) => voidCalled when the modeler did not load, or could not open the source

It returns { save, destroy }:

FunctionReturns
save()A Promise of the diagram as it is now, as BPMN XML. It rejects when the modeler sends something that is not BPMN
destroy()Nothing. Stops listening and empties the iframe. The iframe stays yours

Use the embedded font stylesheet, because the modeler's fonts must come from a data: URL or from the origin of a stylesheet.

The modeler works on a copy. If others change the same diagram while it is open, the next save replaces their changes.