vnote/src/data/extra/web/js/plantuml.js

167 lines
5.0 KiB
JavaScript

class PlantUml extends GraphRenderer {
constructor() {
super();
this.name = 'plantuml';
this.graphDivClass = 'vx-plantuml-graph';
this.extraScripts = [this.scriptFolderPath + '/plantuml/synchro2.js',
this.scriptFolderPath + '/plantuml/zopfli.raw.min.js'];
this.serverUrl = 'http://www.plantuml.com/plantuml';
this.format = 'svg';
this.langs = ['plantuml', 'puml'];
this.useWeb = true;
this.nextLocalGraphIndex = 1;
}
registerInternal() {
this.vnotex.on('basicMarkdownRendered', () => {
this.reset();
this.renderCodeNodes(window.vxOptions.transformSvgToPngEnabled ? 'png' : 'svg');
});
this.vnotex.getWorker('markdownit').addLangsToSkipHighlight(this.langs);
this.useWeb = window.vxOptions.webPlantUml;
if (!this.useWeb) {
this.extraScripts = [];
}
}
// Interface 1.
render(p_node, p_format) {
this.format = p_format;
super.render(p_node, p_classList);
}
// Interface 2.
renderCodeNodes(p_format) {
this.format = p_format;
super.renderCodeNodes();
}
renderOne(p_node, p_idx) {
let func = function(p_plantUml, p_node) {
let plantUml = p_plantUml;
let node = p_node;
return function(p_format, p_data) {
plantUml.handlePlantUmlResult(node, p_format, p_data);
};
};
if (this.useWeb) {
this.renderOnline(this.serverUrl,
this.format,
p_node.textContent,
func(this, p_node));
} else {
this.renderLocal(this.format, p_node.textContent, func(this, p_node));
}
return true;
}
// Render a graph from @p_text in SVG format.
// p_callback(format, data).
renderText(p_text, p_callback) {
console.assert(this.useWeb, "renderText() should be called only when web PlantUml is enabled");
let func = () => {
this.renderOnline(this.serverUrl,
'svg',
p_text,
p_callback);
}
if (!this.initialize(func)) {
return;
}
func();
}
// A helper function to render PlantUml online.
// Send request to @p_serverUrl to render @p_text as format @p_format.
renderOnline(p_serverUrl, p_format, p_text, p_callback) {
let url = this.getPlantUMLOnlineUrl(p_serverUrl, p_format, p_text);
if (p_format == 'png') {
Utils.httpGet(url, 'blob', function(p_resp) {
let blob = p_resp;
let reader = new FileReader();
reader.onload = function () {
let dataUrl = reader.result;
let png = dataUrl.substring(dataUrl.indexOf(',') + 1);
p_callback(p_format, png);
};
reader.readAsDataURL(blob);
});
} else if (p_format == 'svg') {
Utils.httpGet(url, 'text', function(p_resp) {
p_callback(p_format, p_resp);
});
}
}
getPlantUMLOnlineUrl(p_serverUrl, p_format, p_text) {
let s = unescape(encodeURIComponent(p_text));
let arr = [];
for (let i = 0; i < s.length; i++) {
arr.push(s.charCodeAt(i));
}
let compressor = new Zopfli.RawDeflate(arr);
let compressed = compressor.compress();
let url = p_serverUrl + "/" + p_format + "/" + encode64_(compressed);
return url;
}
// A helper function to render PlantUml via local JAR.
renderLocal(p_format, p_text, p_callback) {
this.vnotex.renderGraph(this.id,
this.nextLocalGraphIndex++,
p_format,
'puml',
p_text,
function(id, index, format, data) {
p_callback(format, data);
});
}
handlePlantUmlResult(p_node, p_format, p_result) {
if (p_node && p_result.length > 0) {
let obj = null;
if (p_format == 'svg') {
obj = document.createElement('div');
obj.classList.add(this.graphDivClass);
obj.innerHTML = p_result;
window.vxImageViewer.setupSVGToView(obj.children[0], false);
} else {
obj = document.createElement('div');
obj.classList.add(this.graphDivClass);
let imgObj = document.createElement('img');
obj.appendChild(imgObj);
imgObj.src = "data:image/" + p_format + ";base64, " + p_result;
window.vxImageViewer.setupIMGToView(imgObj);
}
Utils.checkSourceLine(p_node, obj);
Utils.replaceNodeWithPreCheck(p_node, obj);
}
this.finishRenderingOne();
}
}
window.vnotex.registerWorker(new PlantUml());