mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
InplacePreview: support online PlantUML in-place preview
This commit is contained in:
parent
3b2852aa67
commit
d66fd7c1c5
@ -6,6 +6,11 @@ var content;
|
||||
|
||||
var VMermaidDivClass = 'mermaid-diagram';
|
||||
var VFlowchartDivClass = 'flowchart-diagram';
|
||||
var VPlantUMLDivClass = 'plantuml-diagram';
|
||||
|
||||
if (typeof VPlantUMLServer == 'undefined') {
|
||||
VPlantUMLServer = 'http://www.plantuml.com/plantuml';
|
||||
}
|
||||
|
||||
new QWebChannel(qt.webChannelTransport,
|
||||
function(channel) {
|
||||
@ -128,69 +133,26 @@ var previewDiagram = function(identifier, id, timeStamp, lang, text) {
|
||||
|
||||
var div = null;
|
||||
if (lang == 'flow' || lang == 'flowchart') {
|
||||
flowchartIdx++;
|
||||
try {
|
||||
var graph = flowchart.parse(text);
|
||||
} catch (err) {
|
||||
content.setLog("err: " + err);
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof graph == "undefined") {
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||
return;
|
||||
}
|
||||
|
||||
div = document.createElement('div');
|
||||
div.id = 'flowchart-diagram-' + flowchartIdx;
|
||||
div.classList.add(VFlowchartDivClass);
|
||||
|
||||
contentDiv.appendChild(div);
|
||||
|
||||
// Draw on it after adding it to page.
|
||||
try {
|
||||
graph.drawSVG(div.id);
|
||||
} catch (err) {
|
||||
content.setLog("err: " + err);
|
||||
contentDiv.removeChild(div);
|
||||
delete div;
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||
return;
|
||||
}
|
||||
div = renderFlowchartOne(identifier, id, timeStamp, text);
|
||||
} else if (lang == 'mermaid') {
|
||||
mermaidParserErr = false;
|
||||
mermaidIdx++;
|
||||
try {
|
||||
// Do not increment mermaidIdx here.
|
||||
var graph = mermaidAPI.render('mermaid-diagram-' + mermaidIdx,
|
||||
text,
|
||||
function(){});
|
||||
} catch (err) {
|
||||
content.setLog("err: " + err);
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||
div = renderMermaidOne(identifier, id, timeStamp, text);
|
||||
} else if (lang == 'puml') {
|
||||
renderPlantUMLOne(identifier, id, timeStamp, text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mermaidParserErr || typeof graph == "undefined") {
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||
return;
|
||||
}
|
||||
|
||||
div = document.createElement('div');
|
||||
div.classList.add(VMermaidDivClass);
|
||||
div.innerHTML = graph;
|
||||
contentDiv.appendChild(div);
|
||||
}
|
||||
|
||||
if (!div) {
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||
return;
|
||||
}
|
||||
|
||||
// For Flowchart.js, we need to add addtitional height. Since Mermaid is not
|
||||
// supported now, we just add it simply here.
|
||||
domtoimage.toPng(div, { height: div.clientHeight + 30 }).then(function (dataUrl) {
|
||||
// For Flowchart.js, we need to add addtitional height.
|
||||
var dtiOpt = {};
|
||||
if (lang == 'flow' || lang == 'flowchart') {
|
||||
dtiOpt = { height: div.clientHeight + 30 };
|
||||
}
|
||||
|
||||
domtoimage.toPng(div, dtiOpt).then(function (dataUrl) {
|
||||
var png = dataUrl.substring(dataUrl.indexOf(',') + 1);
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'png', png);
|
||||
|
||||
@ -203,3 +165,102 @@ var previewDiagram = function(identifier, id, timeStamp, lang, text) {
|
||||
delete div;
|
||||
});
|
||||
};
|
||||
|
||||
var renderMermaidOne = function(identifier, id, timeStamp, text) {
|
||||
mermaidParserErr = false;
|
||||
mermaidIdx++;
|
||||
try {
|
||||
// Do not increment mermaidIdx here.
|
||||
var graph = mermaidAPI.render('mermaid-diagram-' + mermaidIdx,
|
||||
text,
|
||||
function(){});
|
||||
} catch (err) {
|
||||
content.setLog("err: " + err);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mermaidParserErr || typeof graph == "undefined") {
|
||||
return null;
|
||||
}
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.classList.add(VMermaidDivClass);
|
||||
div.innerHTML = graph;
|
||||
contentDiv.appendChild(div);
|
||||
return div;
|
||||
};
|
||||
|
||||
var renderFlowchartOne = function(identifier, id, timeStamp, text) {
|
||||
flowchartIdx++;
|
||||
try {
|
||||
var graph = flowchart.parse(text);
|
||||
} catch (err) {
|
||||
content.setLog("err: " + err);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof graph == "undefined") {
|
||||
return null;
|
||||
}
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.id = 'flowchart-diagram-' + flowchartIdx;
|
||||
div.classList.add(VFlowchartDivClass);
|
||||
|
||||
contentDiv.appendChild(div);
|
||||
|
||||
// Draw on it after adding it to page.
|
||||
try {
|
||||
graph.drawSVG(div.id);
|
||||
} catch (err) {
|
||||
content.setLog("err: " + err);
|
||||
contentDiv.removeChild(div);
|
||||
delete div;
|
||||
return null;
|
||||
}
|
||||
|
||||
return div;
|
||||
};
|
||||
|
||||
var renderPlantUMLOne = function(identifier, id, timeStamp, text) {
|
||||
var format = 'svg';
|
||||
var s = unescape(encodeURIComponent(text));
|
||||
var arr = [];
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
arr.push(s.charCodeAt(i));
|
||||
}
|
||||
|
||||
var compressor = new Zopfli.RawDeflate(arr);
|
||||
var compressed = compressor.compress();
|
||||
var url = VPlantUMLServer + "/" + format + "/" + encode64_(compressed);
|
||||
|
||||
if (format == 'png') {
|
||||
httpGet(url, 'blob', function(resp) {
|
||||
var blob = resp;
|
||||
var reader = new FileReader();
|
||||
reader.onload = function () {
|
||||
var dataUrl = reader.result;
|
||||
var png = dataUrl.substring(dataUrl.indexOf(',') + 1);
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'png', png);
|
||||
};
|
||||
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
} else if (format == 'svg') {
|
||||
httpGet(url, 'text', function(resp) {
|
||||
content.diagramResultReady(identifier, id, timeStamp, 'svg', resp);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var httpGet = function(url, type, callback) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("GET", url);
|
||||
xmlHttp.responseType = type;
|
||||
|
||||
xmlHttp.onload = function() {
|
||||
callback(xmlHttp.response);
|
||||
};
|
||||
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
@ -942,6 +942,11 @@ QString VUtils::generateMathJaxPreviewTemplate()
|
||||
" messageStyle: \"none\"});\n"
|
||||
"</script>\n";
|
||||
|
||||
// PlantUML.
|
||||
extraFile += "<script type=\"text/javascript\" src=\"" + VNote::c_plantUMLJsFile + "\"></script>\n" +
|
||||
"<script type=\"text/javascript\" src=\"" + VNote::c_plantUMLZopfliJsFile + "\"></script>\n" +
|
||||
"<script>var VPlantUMLServer = '" + g_config->getPlantUMLServer() + "';</script>\n";
|
||||
|
||||
templ.replace(HtmlHolder::c_extraHolder, extraFile);
|
||||
|
||||
return templ;
|
||||
|
@ -124,8 +124,7 @@ void VLivePreviewHelper::checkLang(const QString &p_lang,
|
||||
if (m_flowchartEnabled && (p_lang == "flow" || p_lang == "flowchart")) {
|
||||
p_livePreview = p_inplacePreview = true;
|
||||
} else if (m_plantUMLMode != PlantUMLMode::DisablePlantUML && p_lang == "puml") {
|
||||
p_livePreview = true;
|
||||
p_inplacePreview = m_plantUMLMode == PlantUMLMode::LocalPlantUML;
|
||||
p_livePreview = p_inplacePreview = true;
|
||||
} else if (m_graphvizEnabled && p_lang == "dot") {
|
||||
p_livePreview = p_inplacePreview = true;
|
||||
} else if (m_mermaidEnabled && p_lang == "mermaid") {
|
||||
@ -380,14 +379,12 @@ void VLivePreviewHelper::localAsyncResultReady(int p_id,
|
||||
}
|
||||
|
||||
CodeBlockPreviewInfo &cb = m_codeBlocks[idx];
|
||||
const QString &text = cb.codeBlock().m_text;
|
||||
|
||||
QSharedPointer<CodeBlockImageCacheEntry> entry(new CodeBlockImageCacheEntry(p_timeStamp,
|
||||
p_format,
|
||||
p_result,
|
||||
background,
|
||||
getScaleFactor(cb)));
|
||||
m_cache.insert(text, entry);
|
||||
m_cache.insert(cb.codeBlock().m_text, entry);
|
||||
|
||||
cb.setImageData(p_format, p_result);
|
||||
cb.updateInplacePreview(m_editor, m_doc, entry->m_image, QString(), background);
|
||||
@ -425,7 +422,8 @@ void VLivePreviewHelper::processForInplacePreview(int p_idx)
|
||||
m_timeStamp,
|
||||
"svg",
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
} else if (vcb.m_lang == "puml" && m_plantUMLMode == PlantUMLMode::LocalPlantUML) {
|
||||
} else if (vcb.m_lang == "puml") {
|
||||
if (m_plantUMLMode == PlantUMLMode::LocalPlantUML) {
|
||||
if (!m_plantUMLHelper) {
|
||||
m_plantUMLHelper = new VPlantUMLHelper(this);
|
||||
connect(m_plantUMLHelper, &VPlantUMLHelper::resultReady,
|
||||
@ -436,6 +434,13 @@ void VLivePreviewHelper::processForInplacePreview(int p_idx)
|
||||
m_timeStamp,
|
||||
"svg",
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
} else {
|
||||
m_mathJaxHelper->previewDiagram(m_mathJaxID,
|
||||
p_idx,
|
||||
m_timeStamp,
|
||||
vcb.m_lang,
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
}
|
||||
} else if (vcb.m_lang == "flow"
|
||||
|| vcb.m_lang == "flowchart") {
|
||||
m_mathJaxHelper->previewDiagram(m_mathJaxID,
|
||||
@ -497,16 +502,21 @@ void VLivePreviewHelper::mathjaxPreviewResultReady(int p_identitifer,
|
||||
}
|
||||
|
||||
CodeBlockPreviewInfo &cb = m_codeBlocks[p_id];
|
||||
const QString &text = cb.codeBlock().m_text;
|
||||
const VCodeBlock &vcb = cb.codeBlock();
|
||||
|
||||
QString background;
|
||||
if (vcb.m_lang == "puml") {
|
||||
background = g_config->getEditorPreviewImageBg();
|
||||
}
|
||||
|
||||
QSharedPointer<CodeBlockImageCacheEntry> entry(new CodeBlockImageCacheEntry(p_timeStamp,
|
||||
p_format,
|
||||
p_data,
|
||||
"",
|
||||
background,
|
||||
getScaleFactor(cb)));
|
||||
m_cache.insert(text, entry);
|
||||
m_cache.insert(vcb.m_text, entry);
|
||||
|
||||
cb.updateInplacePreview(m_editor, m_doc, entry->m_image);
|
||||
cb.updateInplacePreview(m_editor, m_doc, entry->m_image, QString(), background);
|
||||
|
||||
if (cb.inplacePreview()) {
|
||||
entry->m_imageName = cb.inplacePreview()->m_name;
|
||||
|
@ -60,7 +60,13 @@ void VMathJaxPreviewHelper::doInit()
|
||||
TimeStamp p_timeStamp,
|
||||
const QString &p_format,
|
||||
const QString &p_data) {
|
||||
QByteArray ba = QByteArray::fromBase64(p_data.toUtf8());
|
||||
QByteArray ba;
|
||||
if (p_format == "png") {
|
||||
ba = QByteArray::fromBase64(p_data.toUtf8());
|
||||
} else {
|
||||
ba = p_data.toUtf8();
|
||||
}
|
||||
|
||||
emit diagramPreviewResultReady(p_identifier, p_id, p_timeStamp, p_format, ba);
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user