A simple method to extends DrawIO based on Placeholder and WebComponent.

Placeholder

Check out this article: placeholders

  • Draw a simple rectangle with label Hello %name%!
  • Edit the rectangle’s data (right click on the rectangle)
  • Add a property with name name and value <name-comp>world</name-comp>
    • A Webcomponent <name-comp> will be rendered, and the default value is world
  • Check the placeholder’s value
  • Apply it to rectangle

image

Render

We can get the source-code of drawio file by cat command:

> cat a.drawio
<mxfile host="65bd71144e">
    <diagram id="wvjVHeBDJ11HY7uDms1G" name="Page-1">
        <mxGraphModel dx="957" dy="646" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
            <root>
                <mxCell id="0"/>
                <mxCell id="1" parent="0"/>
                <object label="Hello %name%!" name="&lt;name-comp&gt;world&lt;/name-comp&gt;" placeholders="1" id="2">
                    <mxCell style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
                        <mxGeometry x="200" y="120" width="120" height="60" as="geometry"/>
                    </mxCell>
                </object>
            </root>
        </mxGraphModel>
    </diagram>
</mxfile>%

And render it by viewer.js from jgraph/drawio

and enable Custom Element’s render

var graph = new Graph(document.getElementById('root'));

graph.setEnabled(false);
graph.setTooltips(false)

graph.isHtmlLabel = function (cell) {
  return true;
};

graph.isTableCell = function (cell) {
  console.log('istablecell');
  return true;
};

function loadXml(graph, xml) {
  graph.getModel().beginUpdate();
  try {
    var root = mxUtils.parseXml(xml);
    var dec = new mxCodec(root);
    dec.decode(root.documentElement, graph.getModel());
  } finally {
    graph.getModel().endUpdate();
  }
}

window.DOM_PURIFY_CONFIG = {
  // Original Config
  "ADD_TAGS": ["use"],
  "FORBID_TAGS": ["form"],
  "ALLOWED_URI_REGEXP": /^((?!javascript:).)*$/i,
  "ADD_ATTR": ["target", "content"],
  "IN_PLACE": false,
  // new custom element
  // https://github.com/cure53/DOMPurify
  CUSTOM_ELEMENT_HANDLING: {
    tagNameCheck: () => true,
    attributeNameCheck: () => true,
    allowCustomizedBuiltInElements: true,
  },
}

// drawiofile is refer to a.drawio
const xml = drawioFile.match(/<mxGraphModel[\s\S]*<\/mxGraphModel>/);
loadXml(graph, xml[0]);

WebComponent

Create a WebComponent like this:

class NameComp extends HTMLElement {
  connectedCallback() {
    const names = ['Alice', 'Bob', 'World'];
    let i = 0;
    setInterval(() => {
      this.innerHTML = names[i++%3];
    }, 1000)
  }
}
customElements.define('name-comp', NameComp)

Online Demo

Finnally, we can get a online demo:

Demo

We extends the drawio by a WebComponent, and see the page will be updated every second.