From 7d42febef3564fba9eca07d5eac0186825fb7ff4 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 15 Feb 2023 12:43:28 +0100 Subject: [PATCH] Store draw.io as JSON in chainpad (instead XML) --- bower.json | 3 +- www/drawio/inner.js | 68 +++++++++++++++++++++++++++++++++------------ 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/bower.json b/bower.json index 3cad2a805..583a351b5 100644 --- a/bower.json +++ b/bower.json @@ -51,7 +51,8 @@ "MathJax": "3.0.5", "drawio": "jgraph/drawio#v20.8.18", "js-base64": "^3.7.5", - "pako": "^2.1.0" + "pako": "^2.1.0", + "abdmob/x2js": "x2js#^1.2.0" }, "resolutions": { "bootstrap": "^v4.0.0", diff --git a/www/drawio/inner.js b/www/drawio/inner.js index 621342054..f80f34296 100644 --- a/www/drawio/inner.js +++ b/www/drawio/inner.js @@ -4,18 +4,22 @@ define([ '/customize/messages.js', // translation keys '/bower_components/pako/dist/pako.min.js', '/bower_components/js-base64/base64.js', + '/bower_components/abdmob/x2js/xml2json.min.js', 'less!/drawio/app.less', 'css!/drawio/drawio.css', ], function ( Framework, Messages, pako, - base64) { + base64, + X2JS) { // This is the main initialization loop var onFrameworkReady = function (framework) { + var EMPTY_DRAWIO = ""; var drawioFrame = document.querySelector('#cp-app-drawio-content'); - var lastContent = ''; + var x2js = new X2JS(); + var lastContent = x2js.xml_str2json(EMPTY_DRAWIO); var drawIoInitalized = false; var postMessageToDrawio = function(msg) { @@ -29,18 +33,19 @@ define([ var onDrawioInit = function(data) { drawIoInitalized = true; - + var xmlStr = x2js.json2xml_str(lastContent); postMessageToDrawio({ action: 'load', - xml: lastContent, + xml: xmlStr, autosave: 1 }); }; var onDrawioChange = function(newXml) { - newXml = decompressDrawioXml(newXml); - if (lastContent != newXml) { - lastContent = newXml; + var newXml = decompressDrawioXml(newXml); + var newJson = x2js.xml_str2json(newXml); + if (!deepEqual(lastContent, newJson)) { + lastContent = newJson; framework.localChange(); } } @@ -49,25 +54,34 @@ define([ onDrawioChange(data.xml); } + var onDrawioMerge = function(data) { + + } + + var onDrawioExport = function(data) { + + } + var drawioHandlers = { init: onDrawioInit, autosave: onDrawioAutodave, + merge: onDrawioMerge, + export: onDrawioExport, }; // This is the function from which you will receive updates from CryptPad framework.onContentUpdate(function (newContent) { - lastContent = newContent.content; + lastContent = newContent; + var xmlStr = x2js.json2xml_str(newContent); postMessageToDrawio({ action: 'merge', - xml: newContent.content, + xml: xmlStr, }); }); // This is the function called to get the current state of the data in your app framework.setContentGetter(function () { - return { - content: lastContent - }; + return lastContent; }); // This is called when the history is synced. "onContentUpdate" has already been called with the full content and the loading screen is being removed. @@ -116,16 +130,16 @@ define([ var parser = new DOMParser(); var doc = parser.parseFromString(xmlDocStr, "application/xml"); - doc.firstChild.removeAttribute('modified'); - doc.firstChild.removeAttribute('agent'); - doc.firstChild.removeAttribute('etag'); - var errorNode = doc.querySelector("parsererror"); if (errorNode) { console.error("error while parsing", errorNode); return xmlStr; } + doc.firstChild.removeAttribute('modified'); + doc.firstChild.removeAttribute('agent'); + doc.firstChild.removeAttribute('etag'); + var diagrams = doc.querySelectorAll('diagram'); diagrams.forEach(function(diagram) { @@ -140,13 +154,31 @@ define([ }); - return new XMLSerializer().serializeToString(doc); + var result = new XMLSerializer().serializeToString(doc); + return result; + } + + var validateXml = function(xmlStr) { + var doc = parser.parseFromString(xmlStr, "application/xml"); + + var errorNode = doc.querySelector("parsererror"); + if (errorNode) { + console.error("error while parsing, rejecting patch", errorNode); + return false; + } + + return true; + }; + + var deepEqual = function(o1, o2) { + return JSON.stringify(o1) == JSON.stringify(o2); } // Framework initialization Framework.create({ toolbarContainer: '#cme_toolbox', - contentContainer: '#cp-app-drawio-editor' + contentContainer: '#cp-app-drawio-editor', + // validateContent: validateXml, }, function (framework) { onFrameworkReady(framework); });