1function extractXml(data) {
2    return new TextDecoder()
3        .decode(Uint8Array.from(atob(data), (c) => c.charCodeAt(0)))
4        .trim();
5}
6
7async function renderDiagram(xml, container, viewer, computeSizeFn) {
8    try {
9        const result = await viewer.importXML(xml);
10        const { warnings } = result;
11        if (warnings?.length > 0) console.warn(warnings);
12
13        if (!computeSizeFn) return;
14
15        const size = computeSizeFn(viewer);
16        if (!size) return;
17
18        container.style.height = `${size.height}px`;
19        container.style.width = `max(100%,${size.width}px)`;
20    } catch (err) {
21        container.textContent = err;
22        console.error(err.message, err.warnings);
23    }
24}
25
26function computeBpmnDiagramSize(viewer) {
27    const canvas = viewer.get("canvas");
28    const bboxViewport = canvas.getActiveLayer().getBBox();
29    const bboxSvg = canvas.getSize();
30    canvas.viewbox({
31        x: bboxViewport.x - 2,
32        y: bboxViewport.y - 2,
33        width: bboxSvg.width,
34        height: bboxSvg.height,
35    });
36    return {
37        width: bboxViewport.width + 4,
38        height: bboxViewport.height + 4,
39    };
40}
41
42function computeDmnDiagramSize(viewer) {
43    const activeView = viewer.getActiveView();
44
45    if (activeView.type === "drd") {
46        const activeEditor = viewer.getActiveViewer();
47
48        // access active editor components
49        const canvas = activeEditor.get("canvas");
50
51        const bboxViewport = canvas.getActiveLayer().getBBox();
52        const bboxSvg = canvas.getSize();
53        canvas.viewbox({
54            x: bboxViewport.x - 2,
55            y: bboxViewport.y - 2,
56            width: bboxSvg.width,
57            height: bboxSvg.height,
58        });
59        return {
60            width: bboxViewport.width + 4,
61            height: bboxViewport.height + 4,
62        };
63    }
64    return undefined;
65}
66
67async function renderBpmnDiagram(xml, container) {
68    const BpmnViewer = window.BpmnJS.Viewer;
69    const viewer = new BpmnViewer({ container });
70
71    renderDiagram(xml, container, viewer, computeBpmnDiagramSize);
72}
73
74async function renderDmnDiagram(xml, container) {
75    const DmnViewer = window.DmnJSViewer;
76    const viewer = new DmnViewer({ container });
77
78    renderDiagram(xml, container, viewer, computeDmnDiagramSize);
79}
80
81async function exportDataBase64(editor) {
82    try {
83        const options = { format: true };
84        const result = await editor.saveXML(options);
85        const { xml } = result;
86        if (xml.length > 0) {
87            const encoder = new TextEncoder();
88            const data = encoder.encode(xml);
89            return btoa(String.fromCharCode(...data));
90        }
91    } catch (err) {
92        console.error(err);
93        return null;
94    }
95}
96
97function addFormSubmitListener(editor) {
98    const form = document.getElementById("dw__editform");
99    form.addEventListener("submit", async () => {
100        const data = await exportDataBase64(editor);
101        const field = form.querySelector('input[name="plugin_bpmnio_data"]');
102        if (field && data) {
103            field.value = data;
104        }
105    });
106}
107
108async function renderBpmnEditor(xml, container) {
109    const BpmnEditor = window.BpmnJS;
110    const editor = new BpmnEditor({ container });
111    addFormSubmitListener(editor);
112    renderDiagram(xml, container, editor, null);
113}
114
115async function renderDmnEditor(xml, container) {
116    const DmnEditor = window.DmnJS;
117    const editor = new DmnEditor({ container });
118    addFormSubmitListener(editor);
119    renderDiagram(xml, container, editor, null);
120}
121
122function safeRender(tag, type, fn) {
123    try {
124        const root = jQuery(tag);
125        const containerId = "." + type + "_js_container";
126        const container = root.find(containerId)[0];
127        // avoid double rendering
128        if (container.children?.length > 0) return;
129
130        const dataId = "." + type + "_js_data";
131        const data = root.find(dataId)[0];
132        const xml = extractXml(data.textContent);
133
134        if (xml.startsWith("Error:")) {
135            container.textContent = xml;
136            container.style.color = "red";
137            return;
138        }
139
140        fn(xml, container);
141    } catch (err) {
142        console.warn(err.message);
143    }
144}
145
146jQuery(document).ready(function () {
147    jQuery("div[id^=__bpmn_js_]").each((_, tag) =>
148        safeRender(tag, "bpmn", renderBpmnDiagram)
149    );
150    jQuery("div[id^=__dmn_js_]").each((_, tag) =>
151        safeRender(tag, "dmn", renderDmnDiagram)
152    );
153    jQuery("div[id=plugin_bpmnio__bpmn_editor]").each((_, tag) =>
154        safeRender(tag, "bpmn", renderBpmnEditor)
155    );
156    jQuery("div[id=plugin_bpmnio__dmn_editor]").each((_, tag) =>
157        safeRender(tag, "dmn", renderDmnEditor)
158    );
159});
160