2.5 KB68 lines
Blame
1import { getConfig, log } from './mermaidUtils.js';
2import ZenUml from '@zenuml/core';
3
4const regexp = /^\s*zenuml/;
5
6// Create a Zen UML container outside the svg first for rendering, otherwise the Zen UML diagram cannot be rendered properly
7function createTemporaryZenumlContainer(id: string) {
8 const container = document.createElement('div');
9 container.id = `container-${id}`;
10 container.style.display = 'flex';
11 container.innerHTML = `<div id="zenUMLApp-${id}"></div>`;
12 const app = container.querySelector(`#zenUMLApp-${id}`)!;
13 return { container, app };
14}
15
16// Create a foreignObject to wrap the Zen UML container in the svg
17function createForeignObject(id: string) {
18 const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
19 foreignObject.setAttribute('x', '0');
20 foreignObject.setAttribute('y', '0');
21 foreignObject.setAttribute('width', '100%');
22 foreignObject.setAttribute('height', '100%');
23 const { container, app } = createTemporaryZenumlContainer(id);
24 foreignObject.appendChild(container);
25 return { foreignObject, container, app };
26}
27
28/**
29 * Draws a Zen UML in the tag with id: id based on the graph definition in text.
30 *
31 * @param text - The text of the diagram
32 * @param id - The id of the diagram which will be used as a DOM element id¨
33 */
34export const draw = async function (text: string, id: string) {
35 log.info('draw with Zen UML renderer', ZenUml);
36
37 text = text.replace(regexp, '');
38 const { securityLevel } = getConfig();
39 // Handle root and Document for when rendering in sandbox mode
40 let sandboxElement: HTMLIFrameElement | null = null;
41 if (securityLevel === 'sandbox') {
42 sandboxElement = document.getElementById('i' + id) as HTMLIFrameElement;
43 }
44
45 const root = securityLevel === 'sandbox' ? sandboxElement?.contentWindow?.document : document;
46
47 const svgContainer = root?.querySelector(`svg#${id}`);
48
49 if (!root || !svgContainer) {
50 log.error('Cannot find root or svgContainer');
51 return;
52 }
53
54 const { foreignObject, container, app } = createForeignObject(id);
55 svgContainer.appendChild(foreignObject);
56 const zenuml = new ZenUml(app);
57 // default is a theme name. More themes to be added and will be configurable in the future
58 await zenuml.render(text, { theme: 'default', mode: 'static' });
59
60 const { width, height } = window.getComputedStyle(container);
61 log.debug('zenuml diagram size', width, height);
62 svgContainer.setAttribute('style', `width: ${width}; height: ${height};`);
63};
64
65export default {
66 draw,
67};
68