mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-08-09 10:22:51 +03:00
- Adds support for handling drawings as embeds, based on image extension. - Adds additional attribute to drawio elements within editor to prevent tinymce replacing embeds with a placeholder. - Updates how contenteditable is applied to drawio blocks within editor, to use proper filters instead of using the SetContent event.
116 lines
3.4 KiB
JavaScript
116 lines
3.4 KiB
JavaScript
let iFrame = null;
|
|
let lastApprovedOrigin;
|
|
let onInit, onSave;
|
|
|
|
/**
|
|
* Show the draw.io editor.
|
|
* @param {String} drawioUrl
|
|
* @param {Function} onInitCallback - Must return a promise with the xml to load for the editor.
|
|
* @param {Function} onSaveCallback - Is called with the drawing data on save.
|
|
*/
|
|
function show(drawioUrl, onInitCallback, onSaveCallback) {
|
|
onInit = onInitCallback;
|
|
onSave = onSaveCallback;
|
|
|
|
iFrame = document.createElement('iframe');
|
|
iFrame.setAttribute('frameborder', '0');
|
|
window.addEventListener('message', drawReceive);
|
|
iFrame.setAttribute('src', drawioUrl);
|
|
iFrame.setAttribute('class', 'fullscreen');
|
|
iFrame.style.backgroundColor = '#FFFFFF';
|
|
document.body.appendChild(iFrame);
|
|
lastApprovedOrigin = (new URL(drawioUrl)).origin;
|
|
}
|
|
|
|
function close() {
|
|
drawEventClose();
|
|
}
|
|
|
|
/**
|
|
* Receive and handle a message event from the draw.io window.
|
|
* @param {MessageEvent} event
|
|
*/
|
|
function drawReceive(event) {
|
|
if (!event.data || event.data.length < 1) return;
|
|
if (event.origin !== lastApprovedOrigin) return;
|
|
|
|
const message = JSON.parse(event.data);
|
|
if (message.event === 'init') {
|
|
drawEventInit();
|
|
} else if (message.event === 'exit') {
|
|
drawEventClose();
|
|
} else if (message.event === 'save') {
|
|
drawEventSave(message);
|
|
} else if (message.event === 'export') {
|
|
drawEventExport(message);
|
|
} else if (message.event === 'configure') {
|
|
drawEventConfigure();
|
|
}
|
|
}
|
|
|
|
function drawEventExport(message) {
|
|
if (onSave) {
|
|
onSave(message.data);
|
|
}
|
|
}
|
|
|
|
function drawEventSave(message) {
|
|
drawPostMessage({action: 'export', format: 'xmlsvg', xml: message.xml, spin: 'Updating drawing'});
|
|
}
|
|
|
|
function drawEventInit() {
|
|
if (!onInit) return;
|
|
onInit().then(xml => {
|
|
drawPostMessage({action: 'load', autosave: 1, xml: xml});
|
|
});
|
|
}
|
|
|
|
function drawEventConfigure() {
|
|
const config = {};
|
|
window.$events.emitPublic(iFrame, 'editor-drawio::configure', {config});
|
|
drawPostMessage({action: 'configure', config});
|
|
}
|
|
|
|
function drawEventClose() {
|
|
window.removeEventListener('message', drawReceive);
|
|
if (iFrame) document.body.removeChild(iFrame);
|
|
}
|
|
|
|
function drawPostMessage(data) {
|
|
iFrame.contentWindow.postMessage(JSON.stringify(data), lastApprovedOrigin);
|
|
}
|
|
|
|
async function upload(imageData, pageUploadedToId) {
|
|
let data = {
|
|
image: imageData,
|
|
uploaded_to: pageUploadedToId,
|
|
};
|
|
const resp = await window.$http.post(window.baseUrl(`/images/drawio`), data);
|
|
return resp.data;
|
|
}
|
|
|
|
/**
|
|
* Load an existing image, by fetching it as Base64 from the system.
|
|
* @param drawingId
|
|
* @returns {Promise<string>}
|
|
*/
|
|
async function load(drawingId) {
|
|
const resp = await window.$http.get(window.baseUrl(`/images/drawio/base64/${drawingId}`));
|
|
return resp.data.content;
|
|
}
|
|
|
|
|
|
function buildDrawingContentHtml(drawing) {
|
|
const isSvg = drawing.url.split('.').pop().toLowerCase() === 'svg';
|
|
const image = `<img src="${drawing.url}">`;
|
|
const embed = `<embed src="${drawing.url}" type="image/svg+xml">`;
|
|
return `<div drawio-diagram="${drawing.id}">${isSvg ? embed : image}</div>`
|
|
}
|
|
|
|
function buildDrawingContentNode(drawing) {
|
|
const div = document.createElement('div');
|
|
div.innerHTML = buildDrawingContentHtml(drawing);
|
|
return div.children[0];
|
|
}
|
|
|
|
export default {show, close, upload, load, buildDrawingContentHtml, buildDrawingContentNode}; |