support flowchart.js

VNote supports flowchart.js in all for renderers.
This commit is contained in:
Le Tan 2017-06-30 20:36:27 +08:00
parent 9278149941
commit f911c60c79
19 changed files with 195 additions and 48 deletions

View File

@ -314,6 +314,7 @@ If you prefer command line on macOS, you could follow these steps.
- [mermaid 7.0.0](https://github.com/knsv/mermaid) (MIT License) - [mermaid 7.0.0](https://github.com/knsv/mermaid) (MIT License)
- [MathJax](https://www.mathjax.org/) (Apache-2.0) - [MathJax](https://www.mathjax.org/) (Apache-2.0)
- [showdown](https://github.com/showdownjs/showdown) (Unknown) - [showdown](https://github.com/showdownjs/showdown) (Unknown)
- [flowchart.js](https://github.com/adrai/flowchart.js) (MIT License)
# License (代码许可) # License (代码许可)
VNote is licensed under the [MIT license](http://opensource.org/licenses/MIT). VNote is licensed under the [MIT license](http://opensource.org/licenses/MIT).

View File

@ -23,29 +23,21 @@ var updateHtml = function(html) {
if (code.parentElement.tagName.toLowerCase() == 'pre') { if (code.parentElement.tagName.toLowerCase() == 'pre') {
if (VEnableMermaid && code.classList.contains('language-mermaid')) { if (VEnableMermaid && code.classList.contains('language-mermaid')) {
// Mermaid code block. // Mermaid code block.
mermaidParserErr = false; if (renderMermaidOne(code)) {
mermaidIdx++;
try {
// Do not increment mermaidIdx here.
var graph = mermaidAPI.render('mermaid-diagram-' + mermaidIdx, code.innerText, function(){});
} catch (err) {
content.setLog("err: " + err);
continue;
}
if (mermaidParserErr || typeof graph == "undefined") {
continue;
}
var graphDiv = document.createElement('div');
graphDiv.classList.add(VMermaidDivClass);
graphDiv.innerHTML = graph;
var preNode = code.parentNode;
preNode.classList.add(VMermaidDivClass);
preNode.replaceChild(graphDiv, code);
// replaceChild() will decrease codes.length. // replaceChild() will decrease codes.length.
--i; --i;
} else { continue;
hljs.highlightBlock(code);
} }
} else if (VEnableFlowchart && code.classList.contains('language-flowchart')) {
// Flowchart code block.
if (renderFlowchartOne(code)) {
// replaceChild() will decrease codes.length.
--i;
continue;
}
}
hljs.highlightBlock(code);
} }
} }

View File

@ -93,6 +93,7 @@ var updateText = function(text) {
handleToc(needToc); handleToc(needToc);
insertImageCaption(); insertImageCaption();
renderMermaid('lang-mermaid'); renderMermaid('lang-mermaid');
renderFlowchart('lang-flowchart');
// If you add new logics after handling MathJax, please pay attention to // If you add new logics after handling MathJax, please pay attention to
// finishLoading logic. // finishLoading logic.

View File

@ -2,6 +2,7 @@ var content;
var keyState = 0; var keyState = 0;
var VMermaidDivClass = 'mermaid-diagram'; var VMermaidDivClass = 'mermaid-diagram';
var VFlowchartDivClass = 'flowchart-diagram';
if (typeof VEnableMermaid == 'undefined') { if (typeof VEnableMermaid == 'undefined') {
VEnableMermaid = false; VEnableMermaid = false;
} else if (VEnableMermaid) { } else if (VEnableMermaid) {
@ -10,6 +11,10 @@ if (typeof VEnableMermaid == 'undefined') {
}); });
} }
if (typeof VEnableFlowchart == 'undefined') {
VEnableFlowchart = false;
}
if (typeof VEnableMathjax == 'undefined') { if (typeof VEnableMathjax == 'undefined') {
VEnableMathjax = false; VEnableMathjax = false;
} }
@ -199,11 +204,23 @@ var renderMermaid = function(className) {
if (!VEnableMermaid) { if (!VEnableMermaid) {
return; return;
} }
var codes = document.getElementsByTagName('code'); var codes = document.getElementsByTagName('code');
mermaidIdx = 0; mermaidIdx = 0;
for (var i = 0; i < codes.length; ++i) { for (var i = 0; i < codes.length; ++i) {
var code = codes[i]; var code = codes[i];
if (code.classList.contains(className)) { if (code.classList.contains(className)) {
if (renderMermaidOne(code)) {
// replaceChild() will decrease codes.length.
--i;
}
}
}
};
// Render @code as Mermaid graph.
// Returns true if succeeded.
var renderMermaidOne = function(code) {
// Mermaid code block. // Mermaid code block.
mermaidParserErr = false; mermaidParserErr = false;
mermaidIdx++; mermaidIdx++;
@ -212,21 +229,77 @@ var renderMermaid = function(className) {
var graph = mermaidAPI.render('mermaid-diagram-' + mermaidIdx, code.innerText, function(){}); var graph = mermaidAPI.render('mermaid-diagram-' + mermaidIdx, code.innerText, function(){});
} catch (err) { } catch (err) {
content.setLog("err: " + err); content.setLog("err: " + err);
continue; return false;
} }
if (mermaidParserErr || typeof graph == "undefined") { if (mermaidParserErr || typeof graph == "undefined") {
continue; return false;
} }
var graphDiv = document.createElement('div'); var graphDiv = document.createElement('div');
graphDiv.classList.add(VMermaidDivClass); graphDiv.classList.add(VMermaidDivClass);
graphDiv.innerHTML = graph; graphDiv.innerHTML = graph;
var preNode = code.parentNode; var preNode = code.parentNode;
preNode.classList.add(VMermaidDivClass); preNode.classList.add(VMermaidDivClass);
preNode.replaceChild(graphDiv, code); preNode.replaceChild(graphDiv, code);
return true;
};
var flowchartIdx = 0;
// @className, the class name of the flowchart code block, such as 'lang-flowchart'.
var renderFlowchart = function(className) {
if (!VEnableFlowchart) {
return;
}
var codes = document.getElementsByTagName('code');
flowchartIdx = 0;
for (var i = 0; i < codes.length; ++i) {
var code = codes[i];
if (code.classList.contains(className)) {
if (renderFlowchartOne(code, flowchartIdx)) {
// replaceChild() will decrease codes.length. // replaceChild() will decrease codes.length.
--i; --i;
} }
} }
}
};
// Render @code as Flowchart.js graph.
// Returns true if succeeded.
var renderFlowchartOne = function(code) {
// Flowchart code block.
flowchartIdx++;
try {
var graph = flowchart.parse(code.innerText);
} catch (err) {
content.setLog("err: " + err);
return false;
}
if (typeof graph == "undefined") {
return false;
}
var graphDiv = document.createElement('div');
graphDiv.id = 'flowchart-diagram-' + flowchartIdx;
graphDiv.classList.add(VFlowchartDivClass);
var preNode = code.parentNode;
preNode.replaceChild(graphDiv, code);
// Draw on it after adding it to page.
try {
graph.drawSVG(graphDiv.id);
} catch (err) {
content.setLog("err: " + err);
preNode.replaceChild(code, graphDiv);
delete graphDiv;
return false;
}
preNode.classList.add(VMermaidDivClass);
return true;
}; };
var isImageBlock = function(img) { var isImageBlock = function(img) {

View File

@ -48,6 +48,7 @@ var updateText = function(text) {
handleToc(needToc); handleToc(needToc);
insertImageCaption(); insertImageCaption();
renderMermaid('lang-mermaid'); renderMermaid('lang-mermaid');
renderFlowchart('lang-flowchart');
// If you add new logics after handling MathJax, please pay attention to // If you add new logics after handling MathJax, please pay attention to
// finishLoading logic. // finishLoading logic.

View File

@ -49,7 +49,7 @@ var mdHasTocSection = function(markdown) {
return n != -1; return n != -1;
}; };
var highlightCodeBlocks = function(doc, enableMermaid) { var highlightCodeBlocks = function(doc, enableMermaid, enableFlowchart) {
var codes = doc.getElementsByTagName('code'); var codes = doc.getElementsByTagName('code');
for (var i = 0; i < codes.length; ++i) { for (var i = 0; i < codes.length; ++i) {
var code = codes[i]; var code = codes[i];
@ -57,6 +57,9 @@ var highlightCodeBlocks = function(doc, enableMermaid) {
if (enableMermaid && code.classList.contains('language-mermaid')) { if (enableMermaid && code.classList.contains('language-mermaid')) {
// Mermaid code block. // Mermaid code block.
continue; continue;
} if (enableFlowchart && code.classList.contains('language-flowchart')) {
// Flowchart code block.
continue;
} else { } else {
hljs.highlightBlock(code); hljs.highlightBlock(code);
} }
@ -70,8 +73,9 @@ var updateText = function(text) {
placeholder.innerHTML = html; placeholder.innerHTML = html;
handleToc(needToc); handleToc(needToc);
insertImageCaption(); insertImageCaption();
highlightCodeBlocks(document, VEnableMermaid); highlightCodeBlocks(document, VEnableMermaid, VEnableFlowchart);
renderMermaid('language-mermaid'); renderMermaid('language-mermaid');
renderFlowchart('language-flowchart');
// If you add new logics after handling MathJax, please pay attention to // If you add new logics after handling MathJax, please pay attention to
// finishLoading logic. // finishLoading logic.
@ -92,7 +96,7 @@ var highlightText = function(text, id, timeStamp) {
var parser = new DOMParser(); var parser = new DOMParser();
var htmlDoc = parser.parseFromString("<div id=\"showdown-container\">" + html + "</div>", 'text/html'); var htmlDoc = parser.parseFromString("<div id=\"showdown-container\">" + html + "</div>", 'text/html');
highlightCodeBlocks(htmlDoc, false); highlightCodeBlocks(htmlDoc, false, false);
html = htmlDoc.getElementById('showdown-container').innerHTML; html = htmlDoc.getElementById('showdown-container').innerHTML;

View File

@ -161,6 +161,14 @@ pre.mermaid-diagram {
overflow-y: hidden; overflow-y: hidden;
} }
div.flowchart-diagram {
overflow-y: hidden;
}
pre.flowchart-diagram {
overflow-y: hidden;
}
.img-package { .img-package {
text-align: center; text-align: center;
} }

View File

@ -20,6 +20,9 @@ markdown_converter=2
enable_mermaid=false enable_mermaid=false
enable_mathjax=false enable_mathjax=false
; Enable flowchart.js
enable_flowchart=false
; -1 - calculate the factor ; -1 - calculate the factor
web_zoom_factor=-1 web_zoom_factor=-1

View File

@ -0,0 +1,6 @@
# [flowchart.js](https://github.com/adrai/flowchart.js)
v1.6.6
Adriano Raiano
# [Raphael](https://github.com/DmitryBaranovskiy/raphael)
v2.2.7

File diff suppressed because one or more lines are too long

3
src/utils/flowchart.js/raphael.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -529,11 +529,17 @@ QString VUtils::generateHtmlTemplate(MarkdownConverterType p_conType, bool p_exp
} }
if (vconfig.getEnableMermaid()) { if (vconfig.getEnableMermaid()) {
extraFile += "<link rel=\"stylesheet\" type=\"text/css\" href=\"qrc" + VNote::c_mermaidCssFile + extraFile += "<link rel=\"stylesheet\" type=\"text/css\" href=\"qrc" + VNote::c_mermaidCssFile + "\"/>\n" +
"\"/>\n" + "<script src=\"qrc" + VNote::c_mermaidApiJsFile + "\"></script>\n" + "<script src=\"qrc" + VNote::c_mermaidApiJsFile + "\"></script>\n" +
"<script>var VEnableMermaid = true;</script>\n"; "<script>var VEnableMermaid = true;</script>\n";
} }
if (vconfig.getEnableFlowchart()) {
extraFile += "<script src=\"qrc" + VNote::c_raphaelJsFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_flowchartJsFile + "\"></script>\n" +
"<script>var VEnableFlowchart = true;</script>\n";
}
if (vconfig.getEnableMathjax()) { if (vconfig.getEnableMathjax()) {
extraFile += "<script type=\"text/x-mathjax-config\">" extraFile += "<script type=\"text/x-mathjax-config\">"
"MathJax.Hub.Config({\n" "MathJax.Hub.Config({\n"

View File

@ -113,6 +113,8 @@ void VConfigManager::initialize()
m_enableMermaid = getConfigFromSettings("global", "enable_mermaid").toBool(); m_enableMermaid = getConfigFromSettings("global", "enable_mermaid").toBool();
m_enableFlowchart = getConfigFromSettings("global", "enable_flowchart").toBool();
m_enableMathjax = getConfigFromSettings("global", "enable_mathjax").toBool(); m_enableMathjax = getConfigFromSettings("global", "enable_mathjax").toBool();
m_webZoomFactor = getConfigFromSettings("global", "web_zoom_factor").toReal(); m_webZoomFactor = getConfigFromSettings("global", "web_zoom_factor").toReal();

View File

@ -152,6 +152,9 @@ public:
inline bool getEnableMermaid() const; inline bool getEnableMermaid() const;
inline void setEnableMermaid(bool p_enabled); inline void setEnableMermaid(bool p_enabled);
inline bool getEnableFlowchart() const;
inline void setEnableFlowchart(bool p_enabled);
inline bool getEnableMathjax() const; inline bool getEnableMathjax() const;
inline void setEnableMathjax(bool p_enabled); inline void setEnableMathjax(bool p_enabled);
@ -303,6 +306,9 @@ private:
// Enable Mermaid. // Enable Mermaid.
bool m_enableMermaid; bool m_enableMermaid;
// Enable flowchart.js.
bool m_enableFlowchart;
// Enable Mathjax. // Enable Mathjax.
bool m_enableMathjax; bool m_enableMathjax;
@ -729,6 +735,21 @@ inline void VConfigManager::setEnableMermaid(bool p_enabled)
setConfigToSettings("global", "enable_mermaid", m_enableMermaid); setConfigToSettings("global", "enable_mermaid", m_enableMermaid);
} }
inline bool VConfigManager::getEnableFlowchart() const
{
return m_enableFlowchart;
}
inline void VConfigManager::setEnableFlowchart(bool p_enabled)
{
if (m_enableFlowchart == p_enabled) {
return;
}
m_enableFlowchart = p_enabled;
setConfigToSettings("global", "enable_flowchart", m_enableFlowchart);
}
inline bool VConfigManager::getEnableMathjax() const inline bool VConfigManager::getEnableMathjax() const
{ {
return m_enableMathjax; return m_enableMathjax;

View File

@ -457,6 +457,16 @@ void VMainWindow::initMarkdownMenu()
mermaidAct->setChecked(vconfig.getEnableMermaid()); mermaidAct->setChecked(vconfig.getEnableMermaid());
QAction *flowchartAct = new QAction(tr("&Flowchart.js"), this);
flowchartAct->setToolTip(tr("Enable Flowchart.js for flowchart diagram"));
flowchartAct->setCheckable(true);
connect(flowchartAct, &QAction::triggered,
this, [this](bool p_enabled){
vconfig.setEnableFlowchart(p_enabled);
});
markdownMenu->addAction(flowchartAct);
flowchartAct->setChecked(vconfig.getEnableFlowchart());
QAction *mathjaxAct = new QAction(tr("Math&Jax"), this); QAction *mathjaxAct = new QAction(tr("Math&Jax"), this);
mathjaxAct->setToolTip(tr("Enable MathJax for math support in Markdown")); mathjaxAct->setToolTip(tr("Enable MathJax for math support in Markdown"));
mathjaxAct->setCheckable(true); mathjaxAct->setCheckable(true);

View File

@ -40,6 +40,9 @@ const QString VNote::c_mermaidCssFile = ":/utils/mermaid/mermaid.css";
const QString VNote::c_mermaidDarkCssFile = ":/utils/mermaid/mermaid.dark.css"; const QString VNote::c_mermaidDarkCssFile = ":/utils/mermaid/mermaid.dark.css";
const QString VNote::c_mermaidForestCssFile = ":/utils/mermaid/mermaid.forest.css"; const QString VNote::c_mermaidForestCssFile = ":/utils/mermaid/mermaid.forest.css";
const QString VNote::c_flowchartJsFile = ":/utils/flowchart.js/flowchart.min.js";
const QString VNote::c_raphaelJsFile = ":/utils/flowchart.js/raphael.min.js";
const QString VNote::c_mathjaxJsFile = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML"; const QString VNote::c_mathjaxJsFile = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML";
const QString VNote::c_shortcutsDocFile_en = ":/resources/docs/shortcuts_en.md"; const QString VNote::c_shortcutsDocFile_en = ":/resources/docs/shortcuts_en.md";

View File

@ -57,6 +57,10 @@ public:
static const QString c_mermaidDarkCssFile; static const QString c_mermaidDarkCssFile;
static const QString c_mermaidForestCssFile; static const QString c_mermaidForestCssFile;
// flowchart.js
static const QString c_flowchartJsFile;
static const QString c_raphaelJsFile;
// Mathjax // Mathjax
static const QString c_mathjaxJsFile; static const QString c_mathjaxJsFile;

View File

@ -109,5 +109,7 @@
<file>utils/markdown-it/markdown-it-footnote.min.js</file> <file>utils/markdown-it/markdown-it-footnote.min.js</file>
<file>resources/icons/arrow_dropup.svg</file> <file>resources/icons/arrow_dropup.svg</file>
<file>resources/icons/vnote_update.svg</file> <file>resources/icons/vnote_update.svg</file>
<file>utils/flowchart.js/flowchart.min.js</file>
<file>utils/flowchart.js/raphael.min.js</file>
</qresource> </qresource>
</RCC> </RCC>