diff --git a/src/resources/common.js b/src/resources/common.js new file mode 100644 index 00000000..765a5003 --- /dev/null +++ b/src/resources/common.js @@ -0,0 +1,46 @@ +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); +}; + +var getPlantUMLOnlineURL = function(server, format, text) { + 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 = server + "/" + format + "/" + encode64_(compressed); + return url; +}; + +var renderPlantUMLOnline = function(server, format, text, callback, data) { + var url = getPlantUMLOnlineURL(server, format, text); + + 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); + callback(data, format, png); + }; + + reader.readAsDataURL(blob); + }); + } else if (format == 'svg') { + httpGet(url, 'text', function(resp) { + callback(data, format, resp); + }); + } +}; diff --git a/src/resources/markdown_template.html b/src/resources/markdown_template.html index 802f5089..7b426694 100644 --- a/src/resources/markdown_template.html +++ b/src/resources/markdown_template.html @@ -29,6 +29,7 @@ + diff --git a/src/resources/markdown_template.js b/src/resources/markdown_template.js index d3291710..8d07f24f 100644 --- a/src/resources/markdown_template.js +++ b/src/resources/markdown_template.js @@ -22,6 +22,8 @@ var VPlantUMLDivClass = 'plantuml-diagram'; var VMetaDataCodeClass = 'markdown-metadata'; var VMarkRectDivClass = 'mark-rect'; +var VPreviewMode = false; + if (typeof VEnableMermaid == 'undefined') { VEnableMermaid = false; } else if (VEnableMermaid) { @@ -700,10 +702,7 @@ var renderPlantUML = function(className) { var code = codes[i]; if (code.classList.contains(className)) { if (VPlantUMLMode == 1) { - if (renderPlantUMLOneOnline(code)) { - // replaceChild() will decrease codes.length. - --i; - } + renderPlantUMLOneOnline(code); } else { renderPlantUMLOneLocal(code); } @@ -711,37 +710,22 @@ var renderPlantUML = function(className) { } }; -// Render @code as PlantUML graph. -// Returns true if succeeded. +// Render @code as PlantUML graph asynchronously. var renderPlantUMLOneOnline = function(code) { - var s = unescape(encodeURIComponent(code.textContent)); - var arr = []; - for (var i = 0; i < s.length; i++) { - arr.push(s.charCodeAt(i)); - } + ++asyncJobsCount; + code.classList.add(plantUMLCodeClass + plantUMLIdx); - var compressor = new Zopfli.RawDeflate(arr); - var compressed = compressor.compress(); - var url = VPlantUMLServer + "/" + VPlantUMLFormat + "/" + encode64_(compressed); - - var obj = null; - if (VPlantUMLFormat == 'svg') { - var svgObj = document.createElement('object'); - svgObj.type = 'image/svg+xml'; - svgObj.data = url; - - obj = document.createElement('div'); - obj.classList.add(VPlantUMLDivClass); - obj.appendChild(svgObj); - } else { - obj = document.createElement('img'); - obj.src = url; - setupIMGToView(obj); - } - - var preNode = code.parentNode; - preNode.parentNode.replaceChild(obj, preNode); - return true; + data = { index: plantUMLIdx, + setupView: !VPreviewMode + }; + renderPlantUMLOnline(VPlantUMLServer, + VPlantUMLFormat, + code.textContent, + function(data, format, result) { + handlePlantUMLResultExt(data.index, 0, format, result, data.setupView); + }, + data); + plantUMLIdx++; }; var renderPlantUMLOneLocal = function(code) { @@ -1364,6 +1348,10 @@ var specialCodeBlock = function(lang) { }; var handlePlantUMLResult = function(id, timeStamp, format, result) { + handlePlantUMLResultExt(id, timeStamp, format, result, true); +}; + +var handlePlantUMLResultExt = function(id, timeStamp, format, result, isSetupView) { var code = document.getElementsByClassName(plantUMLCodeClass + id)[0]; if (code && result.length > 0) { var obj = null; @@ -1371,11 +1359,15 @@ var handlePlantUMLResult = function(id, timeStamp, format, result) { obj = document.createElement('div'); obj.classList.add(VPlantUMLDivClass); obj.innerHTML = result; - setupSVGToView(obj.children[0], true); + if (isSetupView) { + setupSVGToView(obj.children[0], true); + } } else { obj = document.createElement('img'); obj.src = "data:image/" + format + ";base64, " + result; - setupIMGToView(obj); + if (isSetupView) { + setupIMGToView(obj); + } } var preNode = code.parentNode; @@ -1422,6 +1414,8 @@ var setPreviewEnabled = function(enabled) { previewDiv.innerHTML = ''; } + VPreviewMode = enabled; + clearMarkRectDivs(); }; @@ -1642,18 +1636,8 @@ var performSmartLivePreview = function(lang, text, hints, isRegex) { } var previewNode = previewDiv; - var trectOffset = null; - try { - var objs = previewNode.getElementsByTagName('object'); - if (objs.length > 0) { - var obj = objs[0]; - previewNode = obj.contentDocument.children[0]; - trectOffset = obj.getBoundingClientRect(); - } - } catch (err) { - content.setLog("err: " + err); - return; - } + + // Accessing contentDocument will fail due to crossing orgin. // PlantUML. var targetNode = null; @@ -1724,13 +1708,7 @@ var performSmartLivePreview = function(lang, text, hints, isRegex) { // (left, top) is relative to the viewport. // Should add window.scrollX and window.scrollY to get the real content offset. - var tbrect = targetNode.getBoundingClientRect(); - var trect = { - left: tbrect.left + (trectOffset ? trectOffset.left : 0), - top: tbrect.top + (trectOffset ? trectOffset.top : 0), - width: tbrect.width, - height: tbrect.height - }; + var trect = targetNode.getBoundingClientRect(); var vrect = { left: document.documentElement.scrollLeft || document.body.scrollLeft || window.pageXOffset, diff --git a/src/resources/mathjax_preview.js b/src/resources/mathjax_preview.js index 2830b505..77e4a3bc 100644 --- a/src/resources/mathjax_preview.js +++ b/src/resources/mathjax_preview.js @@ -223,44 +223,20 @@ var renderFlowchartOne = function(identifier, id, timeStamp, text) { }; 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 data = { identifier: identifier, + id: id, + timeStamp: timeStamp + }; - 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); - }); - } + renderPlantUMLOnline(VPlantUMLServer, + 'svg', + text, + function(data, format, result) { + content.diagramResultReady(data.identifier, + data.id, + data.timeStamp, + format, + result); + }, + data); }; - -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); -} diff --git a/src/resources/mathjax_preview_template.html b/src/resources/mathjax_preview_template.html index cb2baaf1..af8ec698 100644 --- a/src/resources/mathjax_preview_template.html +++ b/src/resources/mathjax_preview_template.html @@ -11,6 +11,7 @@ + diff --git a/src/vmdtab.cpp b/src/vmdtab.cpp index e2759fc0..b4ce9db4 100644 --- a/src/vmdtab.cpp +++ b/src/vmdtab.cpp @@ -70,7 +70,7 @@ VMdTab::VMdTab(VFile *p_file, VEditArea *p_editArea, m_livePreviewTimer->setInterval(500); connect(m_livePreviewTimer, &QTimer::timeout, this, [this]() { - QString text = m_webViewer->selectedText(); + QString text = m_webViewer->selectedText().trimmed(); if (text.isEmpty()) { return; } diff --git a/src/vnote.qrc b/src/vnote.qrc index 6edb4a6a..ce77de54 100644 --- a/src/vnote.qrc +++ b/src/vnote.qrc @@ -271,5 +271,6 @@ utils/turndown/turndown-plugin-gfm.js resources/common.css resources/icons/quick_access.svg + resources/common.js