markdown: support WaveDrom diagram in language wavedrom code block

In place preview is not supported.
This commit is contained in:
Le Tan 2018-11-30 21:01:31 +08:00
parent 25e79b66b1
commit 12d5bb27ef
28 changed files with 317 additions and 53 deletions

View File

@ -52,7 +52,7 @@ PegHighlighterResult::PegHighlighterResult(const PegMarkdownHighlighter *p_peg,
parseHRuleBlocks(p_peg, p_result);
parseTableBlocks(p_peg, p_result);
parseTableBlocks(p_result);
}
static bool compHLUnit(const HLUnit &p_a, const HLUnit &p_b)
@ -272,8 +272,7 @@ void PegHighlighterResult::parseFencedCodeBlocks(const PegMarkdownHighlighter *p
}
}
void PegHighlighterResult::parseTableBlocks(const PegMarkdownHighlighter *p_peg,
const QSharedPointer<PegParseResult> &p_result)
void PegHighlighterResult::parseTableBlocks(const QSharedPointer<PegParseResult> &p_result)
{
const QVector<VElementRegion> &tableRegs = p_result->m_tableRegions;
const QVector<VElementRegion> &headerRegs = p_result->m_tableHeaderRegions;

View File

@ -113,8 +113,7 @@ private:
const QSharedPointer<PegParseResult> &p_result);
// Parse table blocks from parse results.
void parseTableBlocks(const PegMarkdownHighlighter *p_peg,
const QSharedPointer<PegParseResult> &p_result);
void parseTableBlocks(const QSharedPointer<PegParseResult> &p_result);
#if 0
void parseBlocksElementRegionOne(QHash<int, QVector<VElementRegion>> &p_regs,

View File

@ -122,9 +122,15 @@ As VNote suggests:
### Diagrams
> You need to enable Flowchart.js or Mermaid in the `Markdown` menu.
> You need to enable Flowchart.js or Mermaid or WaveDrom in the `Markdown` menu and restart current opened tabs.
VNote supports [Flowchart.js](http://flowchart.js.org/) and [Mermaid](https://mermaidjs.github.io/) to draw diagrams such as *flowchart* and *sequence diagram*. You should use `flow` or `flowchart` and `mermaid` specified as the language of the fenced code block and write the definition of your diagram within it.
VNote supports the following engines to draw diagrams. You should specify particular language of the fenced code block and write the definition of your diagram within it.
- [Flowchart.js](http://flowchart.js.org/) for *flowchart* with language `flow` or `flowchart`;
- [Mermaid](https://mermaidjs.github.io/) with language `mermaid`;
- [WaveDrom](https://wavedrom.com/) for *digital timing diagram* with language `wavedrom`;
For example,
```flowchart
st=>start: Start:>http://www.google.com[blank]

View File

@ -123,9 +123,15 @@ As VNote suggests:
### 图表
> 需要在`Markdown`菜单中启用Flowchart.js或Mermaid。
> 需要在`Markdown`菜单中启用Flowchart.js或Mermaid或WaveDrom并重新打开当前标签页
VNote支持 [Flowchart.js](http://flowchart.js.org/) 和 [Mermaid](https://mermaidjs.github.io/) 来实现诸如*流程图*和*序列图*等图表。您需要使用代码块,并标明语言为`flow``flowchart``mermaid`,然后在代码块里面定义图表。
VNote支持使用以下引擎来绘制图表。您需要使用代码块并标明特定语言然后在代码块里面定义图表。
- [Flowchart.js](http://flowchart.js.org/),语言为`flow``flowchart`
- [Mermaid](https://mermaidjs.github.io/),语言为`mermaid`
- [WaveDrom](https://wavedrom.com/),数字时序图,语言为`wavedrom`
例如,
```flowchart
st=>start: Start:>http://www.google.com[blank]

View File

@ -2,6 +2,10 @@
marked.setOptions({
highlight: function(code, lang) {
if (lang) {
if (lang === 'wavedrom') {
lang = 'json';
}
if (hljs.getLanguage(lang)) {
return hljs.highlight(lang, code, true).value;
} else {
@ -26,6 +30,8 @@ var updateHtml = function(html) {
var codes = document.getElementsByTagName('code');
mermaidIdx = 0;
flowchartIdx = 0;
wavedromIdx = 0;
plantUMLIdx = 0;
graphvizIdx = 0;
for (var i = 0; i < codes.length; ++i) {
@ -47,6 +53,13 @@ var updateHtml = function(html) {
--i;
continue;
}
} else if (VEnableWavedrom && code.classList.contains('language-wavedrom')) {
// Wavedrom code block.
if (renderWavedromOne(code)) {
// replaceChild() will decrease codes.length.
--i;
continue;
}
} else if (VEnableMathjax && code.classList.contains('language-mathjax')) {
// Mathjax code block.
continue;

View File

@ -44,6 +44,10 @@ var mdit = window.markdownit({
langPrefix: 'lang-',
highlight: function(str, lang) {
if (lang && (!specialCodeBlock(lang) || highlightSpecialBlocks)) {
if (lang === 'wavedrom') {
lang = 'json';
}
if (hljs.getLanguage(lang)) {
return hljs.highlight(lang, str, true).value;
} else {
@ -167,6 +171,7 @@ var updateText = function(text) {
handleMetaData();
renderMermaid('lang-mermaid');
renderFlowchart(['lang-flowchart', 'lang-flow']);
renderWavedrom('lang-wavedrom');
renderPlantUML('lang-puml');
renderGraphviz('lang-dot');
addClassToCodeBlock();

View File

@ -18,6 +18,7 @@ var pendingKeys = [];
var VMermaidDivClass = 'mermaid-diagram';
var VFlowchartDivClass = 'flowchart-diagram';
var VWavedromDivClass = 'wavedrom-diagram';
var VPlantUMLDivClass = 'plantuml-diagram';
var VMetaDataCodeClass = 'markdown-metadata';
var VMarkRectDivClass = 'mark-rect';
@ -40,6 +41,10 @@ if (typeof VEnableMathjax == 'undefined') {
VEnableMathjax = false;
}
if (typeof VEnableWavedrom == 'undefined') {
VEnableWavedrom = false;
}
if (typeof VEnableHighlightLineNumber == 'undefined') {
VEnableHighlightLineNumber = false;
}
@ -707,6 +712,58 @@ var renderFlowchartOne = function(code) {
return true;
};
var wavedromIdx = 0;
var renderWavedrom = function(className) {
if (!VEnableWavedrom) {
return;
}
var codes = document.getElementsByTagName('code');
wavedromIdx = 0;
for (var i = 0; i < codes.length; ++i) {
var code = codes[i];
if (code.classList.contains(className)) {
if (renderWavedromOne(code)) {
// replaceChild() will decrease codes.length.
--i;
}
}
}
};
var renderWavedromOne = function(code) {
// Create a script element.
var script = document.createElement('script');
script.setAttribute('type', 'WaveDrom');
script.textContent = code.textContent;
script.setAttribute('id', 'WaveDrom_JSON_' + wavedromIdx);
var preNode = code.parentNode;
preNode.parentNode.replaceChild(script, preNode);
// Create a div element.
var div = document.createElement('div');
div.setAttribute('id', 'WaveDrom_Display_' + wavedromIdx);
div.classList.add(VWavedromDivClass);
script.insertAdjacentElement('afterend', div);
try {
WaveDrom.RenderWaveForm(wavedromIdx,
WaveDrom.eva(script.getAttribute('id')),
'WaveDrom_Display_');
} catch (err) {
wavedromIdx++;
content.setLog("err: " + err);
return false;
}
script.parentNode.removeChild(script);
wavedromIdx++;
return true;
};
var plantUMLIdx = 0;
var plantUMLCodeClass = 'plantuml_code_';
@ -1365,7 +1422,8 @@ var specialCodeBlock = function(lang) {
|| (VEnableMermaid && lang == 'mermaid')
|| (VEnableFlowchart && (lang == 'flowchart' || lang == 'flow'))
|| (VPlantUMLMode != 0 && lang == 'puml')
|| (VEnableGraphviz && lang == 'dot');
|| (VEnableGraphviz && lang == 'dot')
|| (VEnableWavedrom && lang === 'wavedrom');
};
var handlePlantUMLResult = function(id, timeStamp, format, result) {
@ -1449,6 +1507,7 @@ var previewCodeBlock = function(id, lang, text, isLivePreview) {
|| (lang != 'flow'
&& lang != 'flowchart'
&& lang != 'mermaid'
&& lang != 'wavedrom'
&& (lang != 'puml' || VPlantUMLMode != 1 || !isLivePreview))) {
return;
}
@ -1464,6 +1523,8 @@ var previewCodeBlock = function(id, lang, text, isLivePreview) {
renderFlowchartOne(code);
} else if (lang == 'mermaid') {
renderMermaidOne(code);
} else if (lang == 'wavedrom') {
renderWavedromOne(code);
} else if (lang == 'puml') {
renderPlantUMLOneOnline(code);
}
@ -1873,4 +1934,3 @@ var clearMarkRectDivs = function() {
var startFreshRender = function() {
skipScrollCheckRange = null;
};

View File

@ -18,6 +18,10 @@ renderer.heading = function(text, level) {
marked.setOptions({
highlight: function(code, lang) {
if (lang && (!specialCodeBlock(lang) || highlightSpecialBlocks)) {
if (lang === 'wavedrom') {
lang = 'json';
}
if (hljs.getLanguage(lang)) {
return hljs.highlight(lang, code, true).value;
} else {
@ -63,6 +67,7 @@ var updateText = function(text) {
setupImageView();
renderMermaid('language-mermaid');
renderFlowchart(['language-flowchart', 'language-flow']);
renderWavedrom('language-wavedrom');
renderPlantUML('language-puml');
renderGraphviz('language-dot');
addClassToCodeBlock();

View File

@ -6,6 +6,7 @@ var content;
var VMermaidDivClass = 'mermaid-diagram';
var VFlowchartDivClass = 'flowchart-diagram';
var VWavedromDivClass = 'wavedrom-diagram';
var VPlantUMLDivClass = 'plantuml-diagram';
if (typeof VPlantUMLServer == 'undefined') {
@ -112,6 +113,8 @@ var mermaidIdx = 0;
var flowchartIdx = 0;
var wavedromIdx = 0;
if (typeof mermaidAPI != "undefined") {
mermaidAPI.parseError = function(err, hash) {
mermaidParserErr = true;
@ -135,6 +138,8 @@ var previewDiagram = function(identifier, id, timeStamp, lang, text) {
var div = null;
if (lang == 'flow' || lang == 'flowchart') {
div = renderFlowchartOne(identifier, id, timeStamp, text);
} else if (lang === 'wavedrom') {
div = renderWavedromOne(identifier, id, timeStamp, text);
} else if (lang == 'mermaid') {
div = renderMermaidOne(identifier, id, timeStamp, text);
} else if (lang == 'puml') {
@ -223,6 +228,38 @@ var renderFlowchartOne = function(identifier, id, timeStamp, text) {
return div;
};
var renderWavedromOne = function(identifier, id, timeStamp, text) {
// Create a script element.
var script = document.createElement('script');
script.setAttribute('type', 'WaveDrom');
script.textContent = text;
script.setAttribute('id', 'WaveDrom_JSON_' + wavedromIdx);
contentDiv.appendChild(script);
// Create a div element.
var div = document.createElement('div');
div.setAttribute('id', 'WaveDrom_Display_' + wavedromIdx);
div.classList.add(VWavedromDivClass);
script.insertAdjacentElement('afterend', div);
try {
WaveDrom.RenderWaveForm(wavedromIdx,
WaveDrom.eva(script.getAttribute('id')),
'WaveDrom_Display_');
} catch (err) {
content.setLog("err: " + err);
contentDiv.removeChild(script);
contentDiv.removeChild(div);
wavedromIdx++;
return null;
}
contentDiv.removeChild(script);
wavedromIdx++;
return div;
};
var renderPlantUMLOne = function(identifier, id, timeStamp, text) {
var data = { identifier: identifier,
id: id,

View File

@ -51,6 +51,7 @@ var mdHasTocSection = function(markdown) {
var highlightCodeBlocks = function(doc,
enableMermaid,
enableFlowchart,
enableWavedrom,
enableMathJax,
enablePlantUML,
enableGraphviz) {
@ -58,6 +59,15 @@ var highlightCodeBlocks = function(doc,
for (var i = 0; i < codes.length; ++i) {
var code = codes[i];
if (code.parentElement.tagName.toLowerCase() == 'pre') {
if (code.classList.contains('language-wavedrom')) {
if (enableWavedrom) {
continue;
} else {
code.classList.remove('language-wavedrom');
code.classList.add('language-json');
}
}
if (enableMermaid && code.classList.contains('language-mermaid')) {
// Mermaid code block.
continue;
@ -66,6 +76,9 @@ var highlightCodeBlocks = function(doc,
|| code.classList.contains('language-flow'))) {
// Flowchart code block.
continue;
} else if (enableWavedrom && code.classList.contains('language-wavedrom')) {
// Wavedrom code block.
continue;
} else if (enableMathJax && code.classList.contains('language-mathjax')) {
// MathJax code block.
continue;
@ -103,11 +116,13 @@ var updateText = function(text) {
highlightCodeBlocks(document,
VEnableMermaid,
VEnableFlowchart,
VEnableWavedrom,
VEnableMathjax,
VPlantUMLMode != 0,
VEnableGraphviz);
renderMermaid('language-mermaid');
renderFlowchart(['language-flowchart', 'language-flow']);
renderWavedrom('language-wavedrom');
renderPlantUML('language-puml');
renderGraphviz('language-dot');
addClassToCodeBlock();

View File

@ -196,6 +196,15 @@ div.flowchart-diagram {
color: #222222;
}
div.wavedrom-diagram {
padding: 0px 5px 0px 5px;
margin: 16px 0px 16px 0px;
width: fit-content;
overflow: hidden;
background: #949494;
color: #222222;
}
div.plantuml-diagram {
padding: 5px 5px 0px 5px;
margin: 16px 0px 16px 0px;

View File

@ -194,6 +194,15 @@ div.flowchart-diagram {
color: #6C6C6C;
}
div.wavedrom-diagram {
padding: 0px 5px 0px 5px;
margin: 16px 0px 16px 0px;
width: fit-content;
overflow: hidden;
background: #B0BEC5;
color: #6C6C6C;
}
div.plantuml-diagram {
padding: 5px 5px 0px 5px;
margin: 16px 0px 16px 0px;

View File

@ -190,6 +190,13 @@ div.flowchart-diagram {
overflow: hidden;
}
div.wavedrom-diagram {
padding: 0px 5px 0px 5px;
margin: 16px 0px 16px 0px;
width: fit-content;
overflow: hidden;
}
div.plantuml-diagram {
padding: 5px 5px 0px 5px;
margin: 16px 0px 16px 0px;

View File

@ -192,6 +192,13 @@ div.flowchart-diagram {
overflow: hidden;
}
div.wavedrom-diagram {
padding: 0px 5px 0px 5px;
margin: 16px 0px 16px 0px;
width: fit-content;
overflow: hidden;
}
div.plantuml-diagram {
padding: 5px 5px 0px 5px;
margin: 16px 0px 16px 0px;

View File

@ -541,3 +541,7 @@ ParseAndPaste=P
; Shortcut could be empty
; Need to escape \ and ", use double quotes to quote paths/arguments with spaces
; SHOULD defined in user config file, not here
[markdown]
; Enable WaveDrom
enable_wavedrom=false

View File

@ -813,6 +813,12 @@ QString VUtils::generateHtmlTemplate(const QString &p_template,
}
}
if (g_config->getEnableWavedrom()) {
extraFile += "<script src=\"qrc" + VNote::c_wavedromThemeFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_wavedromJsFile + "\"></script>\n" +
"<script>var VEnableWavedrom = true;</script>\n";
}
int plantUMLMode = g_config->getPlantUMLMode();
if (plantUMLMode != PlantUMLMode::DisablePlantUML) {
if (plantUMLMode == PlantUMLMode::OnlinePlantUML) {
@ -984,6 +990,9 @@ QString VUtils::generateMathJaxPreviewTemplate()
" messageStyle: \"none\"});\n"
"</script>\n";
extraFile += "<script src=\"qrc" + VNote::c_wavedromThemeFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_wavedromJsFile + "\"></script>\n";
// PlantUML.
extraFile += "<script type=\"text/javascript\" src=\"" + VNote::c_plantUMLJsFile + "\"></script>\n" +
"<script type=\"text/javascript\" src=\"" + VNote::c_plantUMLZopfliJsFile + "\"></script>\n" +

View File

@ -0,0 +1,2 @@
# [WaveDrom](https://github.com/wavedrom/wavedrom)
v1.6.2

File diff suppressed because one or more lines are too long

3
src/utils/wavedrom/wavedrom.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -327,26 +327,30 @@ void VConfigManager::initialize()
"highlight_matches_in_page").toBool();
initEditorConfigs();
initMarkdownConfigs();
}
void VConfigManager::initEditorConfigs()
{
m_autoIndent = getConfigFromSettings("editor", "auto_indent").toBool();
const QString section("editor");
m_autoList = getConfigFromSettings("editor", "auto_list").toBool();
m_autoIndent = getConfigFromSettings(section, "auto_indent").toBool();
m_autoQuote = getConfigFromSettings("editor", "auto_quote").toBool();
m_autoList = getConfigFromSettings(section, "auto_list").toBool();
int keyMode = getConfigFromSettings("editor", "key_mode").toInt();
m_autoQuote = getConfigFromSettings(section, "auto_quote").toBool();
int keyMode = getConfigFromSettings(section, "key_mode").toInt();
if (keyMode < 0 || keyMode >= (int)KeyMode::Invalid) {
keyMode = 0;
}
m_keyMode = (KeyMode)keyMode;
m_enableSmartImInVimMode = getConfigFromSettings("editor",
m_enableSmartImInVimMode = getConfigFromSettings(section,
"enable_smart_im_in_vim_mode").toBool();
QString tmpLeader = getConfigFromSettings("editor",
QString tmpLeader = getConfigFromSettings(section,
"vim_leader_key").toString();
if (tmpLeader.isEmpty()) {
m_vimLeaderKey = QChar(' ');
@ -357,16 +361,22 @@ void VConfigManager::initEditorConfigs()
}
}
m_enableTabHighlight = getConfigFromSettings("editor",
m_enableTabHighlight = getConfigFromSettings(section,
"enable_tab_highlight").toBool();
m_parsePasteLocalImage = getConfigFromSettings("editor", "parse_paste_local_image").toBool();
m_parsePasteLocalImage = getConfigFromSettings(section, "parse_paste_local_image").toBool();
m_enableExtraBuffer = getConfigFromSettings("editor", "enable_extra_buffer").toBool();
m_enableExtraBuffer = getConfigFromSettings(section, "enable_extra_buffer").toBool();
m_autoScrollCursorLine = getConfigFromSettings("editor", "auto_scroll_cursor_line").toInt();
m_autoScrollCursorLine = getConfigFromSettings(section, "auto_scroll_cursor_line").toInt();
m_editorFontFamily = getConfigFromSettings("editor", "editor_font_family").toString();
m_editorFontFamily = getConfigFromSettings(section, "editor_font_family").toString();
}
void VConfigManager::initMarkdownConfigs()
{
const QString section("markdown");
m_enableWavedrom = getConfigFromSettings(section, "enable_wavedrom").toBool();
}
void VConfigManager::initSettings()

View File

@ -89,8 +89,6 @@ public:
void initialize();
void initEditorConfigs();
// Read config from the directory config json file into a QJsonObject.
// @path is the directory containing the config json file.
static QJsonObject readDirectoryConfig(const QString &path);
@ -266,6 +264,9 @@ public:
bool getEnableMathjax() const;
void setEnableMathjax(bool p_enabled);
bool getEnableWavedrom() const;
void setEnableWavedrom(bool p_enabled);
bool getEnableGraphviz() const;
void setEnableGraphviz(bool p_enabled);
@ -625,6 +626,10 @@ public:
void setImageBrowsePath(const QString &p_path);
private:
void initEditorConfigs();
void initMarkdownConfigs();
// Look up a config from user and default settings.
QVariant getConfigFromSettings(const QString &section, const QString &key) const;
@ -782,6 +787,9 @@ private:
// Enable Mathjax.
bool m_enableMathjax;
// Enable WaveDrom.
bool m_enableWavedrom;
// Enable Graphviz.
bool m_enableGraphviz;
@ -1605,6 +1613,21 @@ inline void VConfigManager::setEnableMathjax(bool p_enabled)
setConfigToSettings("global", "enable_mathjax", m_enableMathjax);
}
inline bool VConfigManager::getEnableWavedrom() const
{
return m_enableWavedrom;
}
inline void VConfigManager::setEnableWavedrom(bool p_enabled)
{
if (m_enableWavedrom == p_enabled) {
return;
}
m_enableWavedrom = p_enabled;
setConfigToSettings("markdown", "enable_wavedrom", m_enableWavedrom);
}
inline bool VConfigManager::getEnableGraphviz() const
{
return m_enableGraphviz;

View File

@ -104,6 +104,7 @@ VLivePreviewHelper::VLivePreviewHelper(VEditor *p_editor,
m_flowchartEnabled = g_config->getEnableFlowchart();
m_mermaidEnabled = g_config->getEnableMermaid();
m_wavedromEnabled = g_config->getEnableWavedrom();
m_plantUMLMode = g_config->getPlantUMLMode();
m_graphvizEnabled = g_config->getEnableGraphviz();
m_mathjaxEnabled = g_config->getEnableMathjax();
@ -123,6 +124,9 @@ void VLivePreviewHelper::checkLang(const QString &p_lang,
{
if (m_flowchartEnabled && (p_lang == "flow" || p_lang == "flowchart")) {
p_livePreview = p_inplacePreview = true;
} else if (m_wavedromEnabled && p_lang == "wavedrom") {
p_livePreview = true;
p_inplacePreview = false;
} else if (m_plantUMLMode != PlantUMLMode::DisablePlantUML && p_lang == "puml") {
p_livePreview = p_inplacePreview = true;
} else if (m_graphvizEnabled && p_lang == "dot") {

View File

@ -282,6 +282,7 @@ private:
bool m_flowchartEnabled;
bool m_mermaidEnabled;
bool m_wavedromEnabled;
int m_plantUMLMode;
bool m_graphvizEnabled;
bool m_mathjaxEnabled;

View File

@ -453,7 +453,7 @@ QToolBar *VMainWindow::initViewToolBar(QSize p_iconSize)
viewMenu->addAction(menuBarAct);
expandViewAct = new QAction(VIconUtils::toolButtonIcon(":/resources/icons/expand.svg"),
tr("Expand"),
tr("Expand Edit Area"),
this);
VUtils::fixTextWithCaptainShortcut(expandViewAct, "ExpandMode");
expandViewAct->setStatusTip(tr("Expand the edit area"));
@ -933,34 +933,7 @@ void VMainWindow::initMarkdownMenu()
markdownMenu->addSeparator();
QAction *mermaidAct = new QAction(tr("&Mermaid Diagram"), this);
mermaidAct->setToolTip(tr("Enable Mermaid for graph and diagram (re-open current tabs to make it work)"));
mermaidAct->setCheckable(true);
connect(mermaidAct, &QAction::triggered,
this, &VMainWindow::enableMermaid);
markdownMenu->addAction(mermaidAct);
mermaidAct->setChecked(g_config->getEnableMermaid());
QAction *flowchartAct = new QAction(tr("&Flowchart.js"), this);
flowchartAct->setToolTip(tr("Enable Flowchart.js for flowchart diagram (re-open current tabs to make it work)"));
flowchartAct->setCheckable(true);
connect(flowchartAct, &QAction::triggered,
this, [this](bool p_enabled){
g_config->setEnableFlowchart(p_enabled);
VUtils::promptForReopen(this);
});
markdownMenu->addAction(flowchartAct);
flowchartAct->setChecked(g_config->getEnableFlowchart());
QAction *mathjaxAct = new QAction(tr("Math&Jax"), this);
mathjaxAct->setToolTip(tr("Enable MathJax for math support in Markdown (re-open current tabs to make it work)"));
mathjaxAct->setCheckable(true);
connect(mathjaxAct, &QAction::triggered,
this, &VMainWindow::enableMathjax);
markdownMenu->addAction(mathjaxAct);
mathjaxAct->setChecked(g_config->getEnableMathjax());
initMarkdownExtensionMenu(markdownMenu);
markdownMenu->addSeparator();
@ -1683,6 +1656,50 @@ void VMainWindow::initMarkdownitOptionMenu(QMenu *p_menu)
optMenu->addAction(emojiAct);
}
void VMainWindow::initMarkdownExtensionMenu(QMenu *p_menu)
{
QMenu *optMenu = p_menu->addMenu(tr("Extensions"));
optMenu->setToolTipsVisible(true);
QAction *mermaidAct = new QAction(tr("&Mermaid Diagram"), optMenu);
mermaidAct->setToolTip(tr("Enable Mermaid for graph and diagram (re-open current tabs to make it work)"));
mermaidAct->setCheckable(true);
mermaidAct->setChecked(g_config->getEnableMermaid());
connect(mermaidAct, &QAction::triggered,
this, &VMainWindow::enableMermaid);
optMenu->addAction(mermaidAct);
QAction *flowchartAct = new QAction(tr("&Flowchart.js"), optMenu);
flowchartAct->setToolTip(tr("Enable Flowchart.js for flowchart diagram (re-open current tabs to make it work)"));
flowchartAct->setCheckable(true);
flowchartAct->setChecked(g_config->getEnableFlowchart());
connect(flowchartAct, &QAction::triggered,
this, [this](bool p_enabled){
g_config->setEnableFlowchart(p_enabled);
VUtils::promptForReopen(this);
});
optMenu->addAction(flowchartAct);
QAction *mathjaxAct = new QAction(tr("Math&Jax"), optMenu);
mathjaxAct->setToolTip(tr("Enable MathJax for math support in Markdown (re-open current tabs to make it work)"));
mathjaxAct->setCheckable(true);
mathjaxAct->setChecked(g_config->getEnableMathjax());
connect(mathjaxAct, &QAction::triggered,
this, &VMainWindow::enableMathjax);
optMenu->addAction(mathjaxAct);
QAction *wavedromAct = new QAction(tr("&WaveDrom"), optMenu);
wavedromAct->setToolTip(tr("Enable WaveDrom for digital timing diagram (re-open current tabs to make it work)"));
wavedromAct->setCheckable(true);
wavedromAct->setChecked(g_config->getEnableWavedrom());
connect(wavedromAct, &QAction::triggered,
this, [this](bool p_enabled){
g_config->setEnableWavedrom(p_enabled);
VUtils::promptForReopen(this);
});
optMenu->addAction(wavedromAct);
}
void VMainWindow::initRenderBackgroundMenu(QMenu *menu)
{
QActionGroup *renderBackgroundAct = new QActionGroup(this);

View File

@ -258,7 +258,11 @@ private:
void initCodeBlockStyleMenu(QMenu *p_menu);
void initConverterMenu(QMenu *p_menu);
void initMarkdownitOptionMenu(QMenu *p_menu);
void initMarkdownExtensionMenu(QMenu *p_menu);
void initEditorBackgroundMenu(QMenu *menu);
// Init the Line Number submenu in Edit menu.

View File

@ -58,6 +58,9 @@ const QString VNote::c_mermaidForestCssFile = ":/utils/mermaid/mermaid.forest.cs
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_wavedromJsFile = ":/utils/wavedrom/wavedrom.min.js";
const QString VNote::c_wavedromThemeFile = ":/utils/wavedrom/wavedrom-theme.js";
const QString VNote::c_plantUMLJsFile = "http://s.plantuml.com/synchro2.js";
const QString VNote::c_plantUMLZopfliJsFile = "http://s.plantuml.com/zopfli.raw.min.js";

View File

@ -73,6 +73,10 @@ public:
static const QString c_flowchartJsFile;
static const QString c_raphaelJsFile;
// WaveDrom
static const QString c_wavedromJsFile;
static const QString c_wavedromThemeFile;
// PlantUML
static const QString c_plantUMLJsFile;
static const QString c_plantUMLZopfliJsFile;

View File

@ -278,5 +278,7 @@
<file>resources/icons/256x256/vnote.png</file>
<file>utils/markdown-it/markdown-it-container.min.js</file>
<file>resources/icons/table.svg</file>
<file>utils/wavedrom/wavedrom.min.js</file>
<file>utils/wavedrom/wavedrom-theme.js</file>
</qresource>
</RCC>