mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
support PlantUML
This commit is contained in:
parent
a6087d98a6
commit
9850d9a2a2
@ -899,10 +899,32 @@ VMarkdownTab::VMarkdownTab(QWidget *p_parent)
|
|||||||
QLabel *colorColumnLabel = new QLabel(tr("Color column:"));
|
QLabel *colorColumnLabel = new QLabel(tr("Color column:"));
|
||||||
colorColumnLabel->setToolTip(m_colorColumnEdit->toolTip());
|
colorColumnLabel->setToolTip(m_colorColumnEdit->toolTip());
|
||||||
|
|
||||||
|
// PlantUML.
|
||||||
|
m_plantUMLModeCombo = VUtils::getComboBox();
|
||||||
|
m_plantUMLModeCombo->setToolTip(tr("Enable PlantUML support in Markdown"));
|
||||||
|
m_plantUMLModeCombo->addItem(tr("Disabled"), PlantUMLMode::DisablePlantUML);
|
||||||
|
m_plantUMLModeCombo->addItem(tr("Online Service"), PlantUMLMode::OnlinePlantUML);
|
||||||
|
m_plantUMLModeCombo->addItem(tr("Local JAR"), PlantUMLMode::LocalPlantUML);
|
||||||
|
|
||||||
|
m_plantUMLServerEdit = new VLineEdit();
|
||||||
|
m_plantUMLServerEdit->setToolTip(tr("Server address for online PlantUML"));
|
||||||
|
|
||||||
|
m_plantUMLJarEdit = new VLineEdit();
|
||||||
|
m_plantUMLJarEdit->setToolTip(tr("Location to the PlantUML JAR executable for local PlantUML"));
|
||||||
|
|
||||||
|
m_plantUMLDotEdit = new VLineEdit();
|
||||||
|
m_plantUMLDotEdit->setPlaceholderText(tr("Empty to detect automatically"));
|
||||||
|
m_plantUMLDotEdit->setToolTip(tr("Location to the GraphViz executable for local PlantUML "
|
||||||
|
"(empty to let PlantUML detect it automatically)"));
|
||||||
|
|
||||||
QFormLayout *mainLayout = new QFormLayout();
|
QFormLayout *mainLayout = new QFormLayout();
|
||||||
mainLayout->addRow(tr("Note open mode:"), m_openModeCombo);
|
mainLayout->addRow(tr("Note open mode:"), m_openModeCombo);
|
||||||
mainLayout->addRow(tr("Heading sequence:"), headingSequenceLayout);
|
mainLayout->addRow(tr("Heading sequence:"), headingSequenceLayout);
|
||||||
mainLayout->addRow(colorColumnLabel, m_colorColumnEdit);
|
mainLayout->addRow(colorColumnLabel, m_colorColumnEdit);
|
||||||
|
mainLayout->addRow(tr("PlantUML:"), m_plantUMLModeCombo);
|
||||||
|
mainLayout->addRow(tr("PlantUML server:"), m_plantUMLServerEdit);
|
||||||
|
mainLayout->addRow(tr("PlantUML JAR:"), m_plantUMLJarEdit);
|
||||||
|
mainLayout->addRow(tr("Graphviz executable:"), m_plantUMLDotEdit);
|
||||||
|
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
}
|
}
|
||||||
@ -921,6 +943,10 @@ bool VMarkdownTab::loadConfiguration()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!loadPlantUML()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,6 +964,10 @@ bool VMarkdownTab::saveConfiguration()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!savePlantUML()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,3 +1039,20 @@ bool VMarkdownTab::saveColorColumn()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VMarkdownTab::loadPlantUML()
|
||||||
|
{
|
||||||
|
m_plantUMLModeCombo->setCurrentIndex(m_plantUMLModeCombo->findData(g_config->getPlantUMLMode()));
|
||||||
|
m_plantUMLServerEdit->setText(g_config->getPlantUMLServer());
|
||||||
|
m_plantUMLJarEdit->setText(g_config->getPlantUMLJar());
|
||||||
|
m_plantUMLDotEdit->setText(g_config->getPlantUMLDot());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VMarkdownTab::savePlantUML()
|
||||||
|
{
|
||||||
|
g_config->setPlantUMLMode(m_plantUMLModeCombo->currentData().toInt());
|
||||||
|
g_config->setPlantUMLServer(m_plantUMLServerEdit->text());
|
||||||
|
g_config->setPlantUMLJar(m_plantUMLJarEdit->text());
|
||||||
|
g_config->setPlantUMLDot(m_plantUMLDotEdit->text());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -157,6 +157,9 @@ private:
|
|||||||
bool loadColorColumn();
|
bool loadColorColumn();
|
||||||
bool saveColorColumn();
|
bool saveColorColumn();
|
||||||
|
|
||||||
|
bool loadPlantUML();
|
||||||
|
bool savePlantUML();
|
||||||
|
|
||||||
// Default note open mode for markdown.
|
// Default note open mode for markdown.
|
||||||
QComboBox *m_openModeCombo;
|
QComboBox *m_openModeCombo;
|
||||||
|
|
||||||
@ -166,6 +169,12 @@ private:
|
|||||||
|
|
||||||
// Color column in code block.
|
// Color column in code block.
|
||||||
VLineEdit *m_colorColumnEdit;
|
VLineEdit *m_colorColumnEdit;
|
||||||
|
|
||||||
|
// PlantUML.
|
||||||
|
QComboBox *m_plantUMLModeCombo;
|
||||||
|
VLineEdit *m_plantUMLServerEdit;
|
||||||
|
VLineEdit *m_plantUMLJarEdit;
|
||||||
|
VLineEdit *m_plantUMLDotEdit;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VSettingsDialog : public QDialog
|
class VSettingsDialog : public QDialog
|
||||||
|
@ -108,7 +108,10 @@ As VNote suggests:
|
|||||||
- `lang` is optional to specify the language of the code;
|
- `lang` is optional to specify the language of the code;
|
||||||
|
|
||||||
### Diagrams
|
### Diagrams
|
||||||
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 `flowchart` and `mermaid` specified as the language of the fenced code block and write the definition of your diagram within it.
|
|
||||||
|
> You need to enable Flowchart.js or Mermaid in the `Markdown` menu.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
```flowchart
|
```flowchart
|
||||||
st=>start: Start:>http://www.google.com[blank]
|
st=>start: Start:>http://www.google.com[blank]
|
||||||
@ -124,7 +127,22 @@ VNote supports [Flowchart.js](http://flowchart.js.org/) and [Mermaid](https://me
|
|||||||
cond(no)->sub1(right)->op1
|
cond(no)->sub1(right)->op1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### UML
|
||||||
|
|
||||||
|
> You need to enable PlantUML in the settings. Pay attention to the privacy issue if you use online PlantUML server. You may need to prepare Java runtime, PlantUML, and Graphviz if you choose local PlantUML.
|
||||||
|
|
||||||
|
VNote supports [PlantUML](http://plantuml.com/) to draw UML diagrams. You should use `puml` specified as the language of the fenced code block and write the definition of your diagram within it.
|
||||||
|
|
||||||
|
```puml
|
||||||
|
@startuml
|
||||||
|
Bob -> Alice : hello
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
### Math Formulas
|
### Math Formulas
|
||||||
|
|
||||||
|
> You need to enable MathJax in the `Markdown` menu.
|
||||||
|
|
||||||
VNote supports math formulas via [MathJax](https://www.mathjax.org/). The default math delimiters are `$$...$$` and `\[...\]` for **displayed mathematics**, and `$...$` for **inline mathematics**. Sometimes you may need to *escape* some characters via `\`.
|
VNote supports math formulas via [MathJax](https://www.mathjax.org/). The default math delimiters are `$$...$$` and `\[...\]` for **displayed mathematics**, and `$...$` for **inline mathematics**. Sometimes you may need to *escape* some characters via `\`.
|
||||||
|
|
||||||
VNote also supports displayed mathematics via fenced code block with language `mathjax` specified. The benifit of using code block is you do not have to escape most characters.
|
VNote also supports displayed mathematics via fenced code block with language `mathjax` specified. The benifit of using code block is you do not have to escape most characters.
|
||||||
|
@ -109,7 +109,10 @@ As VNote suggests:
|
|||||||
- `lang`用于指定代码块的代码语言,可选;
|
- `lang`用于指定代码块的代码语言,可选;
|
||||||
|
|
||||||
### 图表
|
### 图表
|
||||||
VNote支持 [Flowchart.js](http://flowchart.js.org/) 和 [Mermaid](https://mermaidjs.github.io/) 来实现诸如*流程图*和*序列图*等图表。您需要使用代码块,并标明语言为`flowchart`或`mermaid`,然后在代码块里面定义图表。
|
|
||||||
|
> 需要在`Markdown`菜单中启用Flowchart.js或Mermaid。
|
||||||
|
|
||||||
|
VNote支持 [Flowchart.js](http://flowchart.js.org/) 和 [Mermaid](https://mermaidjs.github.io/) 来实现诸如*流程图*和*序列图*等图表。您需要使用代码块,并标明语言为`flow`或`flowchart`或`mermaid`,然后在代码块里面定义图表。
|
||||||
|
|
||||||
```flowchart
|
```flowchart
|
||||||
st=>start: Start:>http://www.google.com[blank]
|
st=>start: Start:>http://www.google.com[blank]
|
||||||
@ -125,7 +128,22 @@ VNote支持 [Flowchart.js](http://flowchart.js.org/) 和 [Mermaid](https://merma
|
|||||||
cond(no)->sub1(right)->op1
|
cond(no)->sub1(right)->op1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### UML
|
||||||
|
|
||||||
|
> 需要在设置中启用PlantUML。如果使用在线的PlantUML服务器,请注意隐私问题;如果使用本地PlantUML,可能需要安装Java运行时、PlantUML以及Graphviz。
|
||||||
|
|
||||||
|
VNote支持 [PlantUML](http://plantuml.com/) 来实现UML图表。您需要使用代码块,并标明语言为`puml`,然后在代码块里面定义图表。
|
||||||
|
|
||||||
|
```puml
|
||||||
|
@startuml
|
||||||
|
Bob -> Alice : hello
|
||||||
|
@enduml
|
||||||
|
```
|
||||||
|
|
||||||
### 数学公式
|
### 数学公式
|
||||||
|
|
||||||
|
> 需要在`Markdown`菜单中启用MathJax。
|
||||||
|
|
||||||
VNote通过 [MathJax](https://www.mathjax.org/) 来支持数学公式。默认的**块公式**的分隔符是`$$...$$$`和`\[...\]`,**行内公式**的分隔符是`$...$`。有时候,您需要使用`\`来*转义*某些字符。
|
VNote通过 [MathJax](https://www.mathjax.org/) 来支持数学公式。默认的**块公式**的分隔符是`$$...$$$`和`\[...\]`,**行内公式**的分隔符是`$...$`。有时候,您需要使用`\`来*转义*某些字符。
|
||||||
|
|
||||||
VNote也可以使用标明语言`mathjax`的代码块来实现块公式。使用代码块的一个好处是大多数情况下无需转义字符。
|
VNote也可以使用标明语言`mathjax`的代码块来实现块公式。使用代码块的一个好处是大多数情况下无需转义字符。
|
||||||
|
@ -16,12 +16,15 @@ marked.setOptions({
|
|||||||
});
|
});
|
||||||
|
|
||||||
var updateHtml = function(html) {
|
var updateHtml = function(html) {
|
||||||
|
asyncJobsCount = 0;
|
||||||
|
|
||||||
placeholder.innerHTML = html;
|
placeholder.innerHTML = html;
|
||||||
|
|
||||||
insertImageCaption();
|
insertImageCaption();
|
||||||
|
|
||||||
var codes = document.getElementsByTagName('code');
|
var codes = document.getElementsByTagName('code');
|
||||||
mermaidIdx = 0;
|
mermaidIdx = 0;
|
||||||
|
plantUMLIdx = 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.parentElement.tagName.toLowerCase() == 'pre') {
|
if (code.parentElement.tagName.toLowerCase() == 'pre') {
|
||||||
@ -43,6 +46,19 @@ var updateHtml = function(html) {
|
|||||||
}
|
}
|
||||||
} else if (VEnableMathjax && code.classList.contains('language-mathjax')) {
|
} else if (VEnableMathjax && code.classList.contains('language-mathjax')) {
|
||||||
// Mathjax code block.
|
// Mathjax code block.
|
||||||
|
continue;
|
||||||
|
} else if (VPlantUMLMode != 0
|
||||||
|
&& code.classList.contains('language-puml')) {
|
||||||
|
// PlantUML code block.
|
||||||
|
if (VPlantUMLMode == 1) {
|
||||||
|
if (renderPlantUMLOneOnline(code)) {
|
||||||
|
// replaceChild() will decrease codes.length.
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
renderPlantUMLOneLocal(code);
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,8 @@ var updateText = function(text) {
|
|||||||
text = "[TOC]\n\n" + text;
|
text = "[TOC]\n\n" + text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asyncJobsCount = 0;
|
||||||
|
|
||||||
var needToc = mdHasTocSection(text);
|
var needToc = mdHasTocSection(text);
|
||||||
var html = markdownToHtml(text, needToc);
|
var html = markdownToHtml(text, needToc);
|
||||||
placeholder.innerHTML = html;
|
placeholder.innerHTML = html;
|
||||||
@ -113,6 +115,7 @@ var updateText = function(text) {
|
|||||||
insertImageCaption();
|
insertImageCaption();
|
||||||
renderMermaid('lang-mermaid');
|
renderMermaid('lang-mermaid');
|
||||||
renderFlowchart(['lang-flowchart', 'lang-flow']);
|
renderFlowchart(['lang-flowchart', 'lang-flow']);
|
||||||
|
renderPlantUML('lang-puml');
|
||||||
addClassToCodeBlock();
|
addClassToCodeBlock();
|
||||||
renderCodeBlockLineNumber();
|
renderCodeBlockLineNumber();
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ var pendingKeys = [];
|
|||||||
|
|
||||||
var VMermaidDivClass = 'mermaid-diagram';
|
var VMermaidDivClass = 'mermaid-diagram';
|
||||||
var VFlowchartDivClass = 'flowchart-diagram';
|
var VFlowchartDivClass = 'flowchart-diagram';
|
||||||
|
var VPlantUMLDivClass = 'plantuml-diagram';
|
||||||
|
|
||||||
if (typeof VEnableMermaid == 'undefined') {
|
if (typeof VEnableMermaid == 'undefined') {
|
||||||
VEnableMermaid = false;
|
VEnableMermaid = false;
|
||||||
} else if (VEnableMermaid) {
|
} else if (VEnableMermaid) {
|
||||||
@ -32,6 +34,17 @@ if (typeof VStylesToInline == 'undefined') {
|
|||||||
VStylesToInline = '';
|
VStylesToInline = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0 - disable PlantUML;
|
||||||
|
// 1 - Use online PlantUML processor;
|
||||||
|
// 2 - Use local PlantUML processor;
|
||||||
|
if (typeof VPlantUMLMode == 'undefined') {
|
||||||
|
VPlantUMLMode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof VPlantUMLServer == 'undefined') {
|
||||||
|
VPlantUMLServer = 'http://www.plantuml.com/plantuml';
|
||||||
|
}
|
||||||
|
|
||||||
// Add a caption (using alt text) under the image.
|
// Add a caption (using alt text) under the image.
|
||||||
var VImageCenterClass = 'img-center';
|
var VImageCenterClass = 'img-center';
|
||||||
var VImageCaptionClass = 'img-caption';
|
var VImageCaptionClass = 'img-caption';
|
||||||
@ -133,6 +146,8 @@ new QWebChannel(qt.webChannelTransport,
|
|||||||
if (typeof htmlContent == "function") {
|
if (typeof htmlContent == "function") {
|
||||||
content.requestHtmlContent.connect(htmlContent);
|
content.requestHtmlContent.connect(htmlContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content.plantUMLResultReady.connect(handlePlantUMLResult);
|
||||||
});
|
});
|
||||||
|
|
||||||
var VHighlightedAnchorClass = 'highlighted-anchor';
|
var VHighlightedAnchorClass = 'highlighted-anchor';
|
||||||
@ -605,6 +620,72 @@ var renderFlowchartOne = function(code) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var plantUMLIdx = 0;
|
||||||
|
var plantUMLCodeClass = 'plantuml_code_';
|
||||||
|
|
||||||
|
// @className, the class name of the PlantUML code block, such as 'lang-puml'.
|
||||||
|
var renderPlantUML = function(className) {
|
||||||
|
if (VPlantUMLMode == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
plantUMLIdx = 0;
|
||||||
|
|
||||||
|
var codes = document.getElementsByTagName('code');
|
||||||
|
for (var i = 0; i < codes.length; ++i) {
|
||||||
|
var code = codes[i];
|
||||||
|
if (code.classList.contains(className)) {
|
||||||
|
if (VPlantUMLMode == 1) {
|
||||||
|
if (renderPlantUMLOneOnline(code)) {
|
||||||
|
// replaceChild() will decrease codes.length.
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
renderPlantUMLOneLocal(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render @code as PlantUML graph.
|
||||||
|
// Returns true if succeeded.
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
var preNode = code.parentNode;
|
||||||
|
preNode.parentNode.replaceChild(obj, preNode);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var renderPlantUMLOneLocal = function(code) {
|
||||||
|
++asyncJobsCount;
|
||||||
|
code.classList.add(plantUMLCodeClass + plantUMLIdx);
|
||||||
|
content.processPlantUML(plantUMLIdx, VPlantUMLFormat, code.textContent);
|
||||||
|
plantUMLIdx++;
|
||||||
|
};
|
||||||
|
|
||||||
var isImageBlock = function(img) {
|
var isImageBlock = function(img) {
|
||||||
var pn = img.parentNode;
|
var pn = img.parentNode;
|
||||||
return (pn.children.length == 1) && (pn.textContent == '');
|
return (pn.children.length == 1) && (pn.textContent == '');
|
||||||
@ -704,12 +785,20 @@ var insertImageCaption = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var asyncJobsCount = 0;
|
||||||
|
|
||||||
|
var finishOneAsyncJob = function() {
|
||||||
|
--asyncJobsCount;
|
||||||
|
finishLogics();
|
||||||
|
};
|
||||||
|
|
||||||
// The renderer specific code should call this function once thay have finished
|
// The renderer specific code should call this function once thay have finished
|
||||||
// markdown-specifi handle logics, such as Mermaid, MathJax.
|
// markdown-specifi handle logics, such as Mermaid, MathJax.
|
||||||
var finishLogics = function() {
|
var finishLogics = function() {
|
||||||
|
if (asyncJobsCount <= 0) {
|
||||||
content.finishLogics();
|
content.finishLogics();
|
||||||
|
|
||||||
calculateWordCount();
|
calculateWordCount();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Escape @text to Html.
|
// Escape @text to Html.
|
||||||
@ -1170,5 +1259,26 @@ var calculateWordCount = function() {
|
|||||||
var specialCodeBlock = function(lang) {
|
var specialCodeBlock = function(lang) {
|
||||||
return (VEnableMathjax && lang == 'mathjax')
|
return (VEnableMathjax && lang == 'mathjax')
|
||||||
|| (VEnableMermaid && lang == 'mermaid')
|
|| (VEnableMermaid && lang == 'mermaid')
|
||||||
|| (VEnableFlowchart && (lang == 'flowchart' || lang == 'flow'));
|
|| (VEnableFlowchart && (lang == 'flowchart' || lang == 'flow'))
|
||||||
|
|| (VPlantUMLMode != 0 && lang == 'puml');
|
||||||
|
};
|
||||||
|
|
||||||
|
var handlePlantUMLResult = function(id, format, result) {
|
||||||
|
var code = document.getElementsByClassName(plantUMLCodeClass + id)[0];
|
||||||
|
if (code && result.length > 0) {
|
||||||
|
var obj = null;
|
||||||
|
if (format == 'svg') {
|
||||||
|
obj = document.createElement('div');
|
||||||
|
obj.classList.add(VPlantUMLDivClass);
|
||||||
|
obj.innerHTML = result;
|
||||||
|
} else {
|
||||||
|
obj = document.createElement('img');
|
||||||
|
obj.src = "data:image/" + format + ";base64, " + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var preNode = code.parentNode;
|
||||||
|
preNode.parentNode.replaceChild(obj, preNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
finishOneAsyncJob();
|
||||||
};
|
};
|
||||||
|
@ -50,6 +50,8 @@ var updateText = function(text) {
|
|||||||
text = "[TOC]\n\n" + text;
|
text = "[TOC]\n\n" + text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asyncJobsCount = 0;
|
||||||
|
|
||||||
var needToc = mdHasTocSection(text);
|
var needToc = mdHasTocSection(text);
|
||||||
var html = markdownToHtml(text, needToc);
|
var html = markdownToHtml(text, needToc);
|
||||||
placeholder.innerHTML = html;
|
placeholder.innerHTML = html;
|
||||||
@ -57,6 +59,7 @@ var updateText = function(text) {
|
|||||||
insertImageCaption();
|
insertImageCaption();
|
||||||
renderMermaid('lang-mermaid');
|
renderMermaid('lang-mermaid');
|
||||||
renderFlowchart(['lang-flowchart', 'lang-flow']);
|
renderFlowchart(['lang-flowchart', 'lang-flow']);
|
||||||
|
renderPlantUML('lang-puml');
|
||||||
addClassToCodeBlock();
|
addClassToCodeBlock();
|
||||||
renderCodeBlockLineNumber();
|
renderCodeBlockLineNumber();
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ var mdHasTocSection = function(markdown) {
|
|||||||
return n != -1;
|
return n != -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
var highlightCodeBlocks = function(doc, enableMermaid, enableFlowchart, enableMathJax) {
|
var highlightCodeBlocks = function(doc, enableMermaid, enableFlowchart, enableMathJax, enablePlantUML) {
|
||||||
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];
|
||||||
@ -65,6 +65,9 @@ var highlightCodeBlocks = function(doc, enableMermaid, enableFlowchart, enableMa
|
|||||||
} else if (enableMathJax && code.classList.contains('language-mathjax')) {
|
} else if (enableMathJax && code.classList.contains('language-mathjax')) {
|
||||||
// MathJax code block.
|
// MathJax code block.
|
||||||
continue;
|
continue;
|
||||||
|
} else if (enablePlantUML && code.classList.contains('language-puml')) {
|
||||||
|
// PlantUML code block.
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listContainsRegex(code.classList, /language-.*/)) {
|
if (listContainsRegex(code.classList, /language-.*/)) {
|
||||||
@ -79,14 +82,17 @@ var updateText = function(text) {
|
|||||||
text = "[TOC]\n\n" + text;
|
text = "[TOC]\n\n" + text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asyncJobsCount = 0;
|
||||||
|
|
||||||
var needToc = mdHasTocSection(text);
|
var needToc = mdHasTocSection(text);
|
||||||
var html = markdownToHtml(text, needToc);
|
var html = markdownToHtml(text, needToc);
|
||||||
placeholder.innerHTML = html;
|
placeholder.innerHTML = html;
|
||||||
handleToc(needToc);
|
handleToc(needToc);
|
||||||
insertImageCaption();
|
insertImageCaption();
|
||||||
highlightCodeBlocks(document, VEnableMermaid, VEnableFlowchart, VEnableMathjax);
|
highlightCodeBlocks(document, VEnableMermaid, VEnableFlowchart, VEnableMathjax, VPlantUMLMode != 0);
|
||||||
renderMermaid('language-mermaid');
|
renderMermaid('language-mermaid');
|
||||||
renderFlowchart(['language-flowchart', 'language-flow']);
|
renderFlowchart(['language-flowchart', 'language-flow']);
|
||||||
|
renderPlantUML('language-puml');
|
||||||
addClassToCodeBlock();
|
addClassToCodeBlock();
|
||||||
renderCodeBlockLineNumber();
|
renderCodeBlockLineNumber();
|
||||||
|
|
||||||
|
@ -164,13 +164,22 @@ table tr th :last-child, table tr td :last-child {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.mermaid-diagram {
|
div.mermaid-diagram {
|
||||||
overflow-y: hidden;
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
background: #B0BEC5;
|
background: #B0BEC5;
|
||||||
color: #6C6C6C;
|
color: #6C6C6C;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.flowchart-diagram {
|
div.flowchart-diagram {
|
||||||
overflow-y: hidden;
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #B0BEC5;
|
||||||
|
color: #6C6C6C;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.plantuml-diagram {
|
||||||
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
background: #B0BEC5;
|
background: #B0BEC5;
|
||||||
color: #6C6C6C;
|
color: #6C6C6C;
|
||||||
}
|
}
|
||||||
|
@ -169,11 +169,18 @@ table tr th :last-child, table tr td :last-child {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.mermaid-diagram {
|
div.mermaid-diagram {
|
||||||
overflow-y: hidden;
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.flowchart-diagram {
|
div.flowchart-diagram {
|
||||||
overflow-y: hidden;
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.plantuml-diagram {
|
||||||
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-package {
|
.img-package {
|
||||||
|
@ -170,11 +170,18 @@ table tr th :last-child, table tr td :last-child {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.mermaid-diagram {
|
div.mermaid-diagram {
|
||||||
overflow-y: hidden;
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.flowchart-diagram {
|
div.flowchart-diagram {
|
||||||
overflow-y: hidden;
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.plantuml-diagram {
|
||||||
|
width: fit-content;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-package {
|
.img-package {
|
||||||
|
@ -34,13 +34,21 @@ language=System
|
|||||||
; 0 - Hoedown, 1 - Marked, 2 - Markdown-it, 3 - Showdown
|
; 0 - Hoedown, 1 - Marked, 2 - Markdown-it, 3 - Showdown
|
||||||
markdown_converter=2
|
markdown_converter=2
|
||||||
|
|
||||||
|
; Enable Mermaid diagram
|
||||||
enable_mermaid=false
|
enable_mermaid=false
|
||||||
|
|
||||||
|
; Enable MathJax
|
||||||
enable_mathjax=true
|
enable_mathjax=true
|
||||||
|
|
||||||
; Enable flowchart.js
|
; Enable Flowchart.js
|
||||||
enable_flowchart=false
|
enable_flowchart=false
|
||||||
|
|
||||||
|
; Enable PlantUML
|
||||||
|
; 0 - disable PlantUML
|
||||||
|
; 1 - online PlantUML
|
||||||
|
; 2 - local PlantUML
|
||||||
|
plantuml_mode=0
|
||||||
|
|
||||||
; -1 - calculate the factor
|
; -1 - calculate the factor
|
||||||
web_zoom_factor=-1
|
web_zoom_factor=-1
|
||||||
|
|
||||||
@ -263,6 +271,15 @@ copy_targets="Without Background"$s:b(mark):c:i:x,Evernote$e:p:b(mark|pre):c(pre
|
|||||||
|
|
||||||
enable_flash_anchor=true
|
enable_flash_anchor=true
|
||||||
|
|
||||||
|
; PlantUML server to convert UML script online
|
||||||
|
plantuml_server=http://www.plantuml.com/plantuml
|
||||||
|
|
||||||
|
; PlantUML JAR location
|
||||||
|
plantuml_jar=
|
||||||
|
|
||||||
|
; PlantUML Graphviz Dot location
|
||||||
|
plantuml_dot=
|
||||||
|
|
||||||
[shortcuts]
|
[shortcuts]
|
||||||
; Define shortcuts here, with each item in the form "operation=keysequence".
|
; Define shortcuts here, with each item in the form "operation=keysequence".
|
||||||
; Leave keysequence empty to disable the shortcut of an operation.
|
; Leave keysequence empty to disable the shortcut of an operation.
|
||||||
|
@ -125,7 +125,8 @@ SOURCES += main.cpp\
|
|||||||
voutlineue.cpp \
|
voutlineue.cpp \
|
||||||
vhelpue.cpp \
|
vhelpue.cpp \
|
||||||
vlistfolderue.cpp \
|
vlistfolderue.cpp \
|
||||||
dialog/vfixnotebookdialog.cpp
|
dialog/vfixnotebookdialog.cpp \
|
||||||
|
vplantumlhelper.cpp
|
||||||
|
|
||||||
HEADERS += vmainwindow.h \
|
HEADERS += vmainwindow.h \
|
||||||
vdirectorytree.h \
|
vdirectorytree.h \
|
||||||
@ -241,7 +242,8 @@ HEADERS += vmainwindow.h \
|
|||||||
voutlineue.h \
|
voutlineue.h \
|
||||||
vhelpue.h \
|
vhelpue.h \
|
||||||
vlistfolderue.h \
|
vlistfolderue.h \
|
||||||
dialog/vfixnotebookdialog.h
|
dialog/vfixnotebookdialog.h \
|
||||||
|
vplantumlhelper.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
vnote.qrc \
|
vnote.qrc \
|
||||||
|
@ -618,11 +618,12 @@ QString VUtils::generateHtmlTemplate(MarkdownConverterType p_conType,
|
|||||||
g_config->getCodeBlockCssStyleUrl(p_renderCodeBlockStyle),
|
g_config->getCodeBlockCssStyleUrl(p_renderCodeBlockStyle),
|
||||||
p_isPDF);
|
p_isPDF);
|
||||||
|
|
||||||
return generateHtmlTemplate(templ, p_conType, p_wkhtmltopdf, p_addToc);
|
return generateHtmlTemplate(templ, p_conType, p_isPDF, p_wkhtmltopdf, p_addToc);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString VUtils::generateHtmlTemplate(const QString &p_template,
|
QString VUtils::generateHtmlTemplate(const QString &p_template,
|
||||||
MarkdownConverterType p_conType,
|
MarkdownConverterType p_conType,
|
||||||
|
bool p_isPDF,
|
||||||
bool p_wkhtmltopdf,
|
bool p_wkhtmltopdf,
|
||||||
bool p_addToc)
|
bool p_addToc)
|
||||||
{
|
{
|
||||||
@ -721,6 +722,20 @@ QString VUtils::generateHtmlTemplate(const QString &p_template,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int plantUMLMode = g_config->getPlantUMLMode();
|
||||||
|
if (plantUMLMode != PlantUMLMode::DisablePlantUML) {
|
||||||
|
if (plantUMLMode == PlantUMLMode::OnlinePlantUML) {
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
extraFile += QString("<script>var VPlantUMLMode = %1;</script>\n").arg(plantUMLMode);
|
||||||
|
|
||||||
|
QString format = p_isPDF ? "png" : "svg";
|
||||||
|
extraFile += QString("<script>var VPlantUMLFormat = '%1';</script>\n").arg(format);
|
||||||
|
}
|
||||||
|
|
||||||
if (g_config->getEnableImageCaption()) {
|
if (g_config->getEnableImageCaption()) {
|
||||||
extraFile += "<script>var VEnableImageCaption = true;</script>\n";
|
extraFile += "<script>var VEnableImageCaption = true;</script>\n";
|
||||||
}
|
}
|
||||||
|
@ -368,6 +368,7 @@ private:
|
|||||||
|
|
||||||
static QString generateHtmlTemplate(const QString &p_template,
|
static QString generateHtmlTemplate(const QString &p_template,
|
||||||
MarkdownConverterType p_conType,
|
MarkdownConverterType p_conType,
|
||||||
|
bool p_isPDF = false,
|
||||||
bool p_wkhtmltopdf = false,
|
bool p_wkhtmltopdf = false,
|
||||||
bool p_addToc = false);
|
bool p_addToc = false);
|
||||||
|
|
||||||
|
@ -284,6 +284,11 @@ void VConfigManager::initialize()
|
|||||||
|
|
||||||
m_enableFlashAnchor = getConfigFromSettings("web",
|
m_enableFlashAnchor = getConfigFromSettings("web",
|
||||||
"enable_flash_anchor").toBool();
|
"enable_flash_anchor").toBool();
|
||||||
|
|
||||||
|
m_plantUMLMode = getConfigFromSettings("global", "plantuml_mode").toInt();
|
||||||
|
m_plantUMLServer = getConfigFromSettings("web", "plantuml_server").toString();
|
||||||
|
m_plantUMLJar = getConfigFromSettings("web", "plantuml_jar").toString();
|
||||||
|
m_plantUMLDot = getConfigFromSettings("web", "plantuml_dot").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VConfigManager::initSettings()
|
void VConfigManager::initSettings()
|
||||||
|
@ -210,6 +210,9 @@ public:
|
|||||||
bool getEnableMathjax() const;
|
bool getEnableMathjax() const;
|
||||||
void setEnableMathjax(bool p_enabled);
|
void setEnableMathjax(bool p_enabled);
|
||||||
|
|
||||||
|
int getPlantUMLMode() const;
|
||||||
|
void setPlantUMLMode(int p_mode);
|
||||||
|
|
||||||
qreal getWebZoomFactor() const;
|
qreal getWebZoomFactor() const;
|
||||||
void setWebZoomFactor(qreal p_factor);
|
void setWebZoomFactor(qreal p_factor);
|
||||||
bool isCustomWebZoomFactor();
|
bool isCustomWebZoomFactor();
|
||||||
@ -460,6 +463,15 @@ public:
|
|||||||
QStringList getSearchOptions() const;
|
QStringList getSearchOptions() const;
|
||||||
void setSearchOptions(const QStringList &p_opts);
|
void setSearchOptions(const QStringList &p_opts);
|
||||||
|
|
||||||
|
const QString &getPlantUMLServer() const;
|
||||||
|
void setPlantUMLServer(const QString &p_server);
|
||||||
|
|
||||||
|
const QString &getPlantUMLJar() const;
|
||||||
|
void setPlantUMLJar(const QString &p_jarPath);
|
||||||
|
|
||||||
|
const QString &getPlantUMLDot() const;
|
||||||
|
void setPlantUMLDot(const QString &p_dotPath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Look up a config from user and default settings.
|
// Look up a config from user and default settings.
|
||||||
QVariant getConfigFromSettings(const QString §ion, const QString &key) const;
|
QVariant getConfigFromSettings(const QString §ion, const QString &key) const;
|
||||||
@ -852,6 +864,15 @@ private:
|
|||||||
// Whether flash anchor in read mode.
|
// Whether flash anchor in read mode.
|
||||||
bool m_enableFlashAnchor;
|
bool m_enableFlashAnchor;
|
||||||
|
|
||||||
|
// PlantUML mode.
|
||||||
|
int m_plantUMLMode;
|
||||||
|
|
||||||
|
QString m_plantUMLServer;
|
||||||
|
|
||||||
|
QString m_plantUMLJar;
|
||||||
|
|
||||||
|
QString m_plantUMLDot;
|
||||||
|
|
||||||
// The name of the config file in each directory, obsolete.
|
// The name of the config file in each directory, obsolete.
|
||||||
// Use c_dirConfigFile instead.
|
// Use c_dirConfigFile instead.
|
||||||
static const QString c_obsoleteDirConfigFile;
|
static const QString c_obsoleteDirConfigFile;
|
||||||
@ -1325,10 +1346,26 @@ inline void VConfigManager::setEnableMathjax(bool p_enabled)
|
|||||||
if (m_enableMathjax == p_enabled) {
|
if (m_enableMathjax == p_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_enableMathjax = p_enabled;
|
m_enableMathjax = p_enabled;
|
||||||
setConfigToSettings("global", "enable_mathjax", m_enableMathjax);
|
setConfigToSettings("global", "enable_mathjax", m_enableMathjax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int VConfigManager::getPlantUMLMode() const
|
||||||
|
{
|
||||||
|
return m_plantUMLMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VConfigManager::setPlantUMLMode(int p_mode)
|
||||||
|
{
|
||||||
|
if (m_plantUMLMode == p_mode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_plantUMLMode = p_mode;
|
||||||
|
setConfigToSettings("global", "plantuml_mode", p_mode);
|
||||||
|
}
|
||||||
|
|
||||||
inline qreal VConfigManager::getWebZoomFactor() const
|
inline qreal VConfigManager::getWebZoomFactor() const
|
||||||
{
|
{
|
||||||
return m_webZoomFactor;
|
return m_webZoomFactor;
|
||||||
@ -2149,4 +2186,49 @@ inline void VConfigManager::setSearchOptions(const QStringList &p_opts)
|
|||||||
{
|
{
|
||||||
setConfigToSettings("global", "search_options", p_opts);
|
setConfigToSettings("global", "search_options", p_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const QString &VConfigManager::getPlantUMLServer() const
|
||||||
|
{
|
||||||
|
return m_plantUMLServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VConfigManager::setPlantUMLServer(const QString &p_server)
|
||||||
|
{
|
||||||
|
if (m_plantUMLServer == p_server) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_plantUMLServer = p_server;
|
||||||
|
setConfigToSettings("web", "plantuml_server", p_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QString &VConfigManager::getPlantUMLJar() const
|
||||||
|
{
|
||||||
|
return m_plantUMLJar;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VConfigManager::setPlantUMLJar(const QString &p_jarPath)
|
||||||
|
{
|
||||||
|
if (m_plantUMLJar == p_jarPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_plantUMLJar = p_jarPath;
|
||||||
|
setConfigToSettings("web", "plantuml_jar", p_jarPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QString &VConfigManager::getPlantUMLDot() const
|
||||||
|
{
|
||||||
|
return m_plantUMLDot;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VConfigManager::setPlantUMLDot(const QString &p_dotPath)
|
||||||
|
{
|
||||||
|
if (m_plantUMLDot == p_dotPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_plantUMLDot = p_dotPath;
|
||||||
|
setConfigToSettings("web", "plantuml_dot", p_dotPath);
|
||||||
|
}
|
||||||
#endif // VCONFIGMANAGER_H
|
#endif // VCONFIGMANAGER_H
|
||||||
|
@ -152,6 +152,13 @@ enum MarkdownConverterType
|
|||||||
Showdown
|
Showdown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum PlantUMLMode
|
||||||
|
{
|
||||||
|
DisablePlantUML = 0,
|
||||||
|
OnlinePlantUML = 1,
|
||||||
|
LocalPlantUML = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct MarkdownitOption
|
struct MarkdownitOption
|
||||||
{
|
{
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
#include "vdocument.h"
|
#include "vdocument.h"
|
||||||
#include "vfile.h"
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "vfile.h"
|
||||||
|
#include "vplantumlhelper.h"
|
||||||
|
|
||||||
VDocument::VDocument(const VFile *v_file, QObject *p_parent)
|
VDocument::VDocument(const VFile *v_file, QObject *p_parent)
|
||||||
: QObject(p_parent),
|
: QObject(p_parent),
|
||||||
m_file(v_file),
|
m_file(v_file),
|
||||||
m_readyToHighlight(false)
|
m_readyToHighlight(false),
|
||||||
|
m_plantUMLHelper(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,3 +136,16 @@ void VDocument::updateWordCountInfo(int p_wordCount,
|
|||||||
|
|
||||||
emit wordCountInfoUpdated();
|
emit wordCountInfoUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VDocument::processPlantUML(int p_id, const QString &p_format, const QString &p_text)
|
||||||
|
{
|
||||||
|
if (!m_plantUMLHelper) {
|
||||||
|
m_plantUMLHelper = new VPlantUMLHelper(this);
|
||||||
|
connect(m_plantUMLHelper, &VPlantUMLHelper::resultReady,
|
||||||
|
this, [this](int p_id, const QString &p_format, const QString &p_result) {
|
||||||
|
emit plantUMLResultReady(p_id, p_format, p_result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
m_plantUMLHelper->processAsync(p_id, p_format, p_text);
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "vwordcountinfo.h"
|
#include "vwordcountinfo.h"
|
||||||
|
|
||||||
class VFile;
|
class VFile;
|
||||||
|
class VPlantUMLHelper;
|
||||||
|
|
||||||
class VDocument : public QObject
|
class VDocument : public QObject
|
||||||
{
|
{
|
||||||
@ -82,6 +83,9 @@ public slots:
|
|||||||
int p_charWithoutSpacesCount,
|
int p_charWithoutSpacesCount,
|
||||||
int p_charWithSpacesCount);
|
int p_charWithSpacesCount);
|
||||||
|
|
||||||
|
// Web-side call this to process PlantUML locally.
|
||||||
|
void processPlantUML(int p_id, const QString &p_format, const QString &p_text);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void textChanged(const QString &text);
|
void textChanged(const QString &text);
|
||||||
|
|
||||||
@ -118,6 +122,8 @@ signals:
|
|||||||
|
|
||||||
void wordCountInfoUpdated();
|
void wordCountInfoUpdated();
|
||||||
|
|
||||||
|
void plantUMLResultReady(int p_id, const QString &p_format, const QString &p_result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_toc;
|
QString m_toc;
|
||||||
QString m_header;
|
QString m_header;
|
||||||
@ -137,6 +143,8 @@ private:
|
|||||||
bool m_readyToTextToHtml;
|
bool m_readyToTextToHtml;
|
||||||
|
|
||||||
VWordCountInfo m_wordCountInfo;
|
VWordCountInfo m_wordCountInfo;
|
||||||
|
|
||||||
|
VPlantUMLHelper *m_plantUMLHelper;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool VDocument::isReadyToHighlight() const
|
inline bool VDocument::isReadyToHighlight() const
|
||||||
|
@ -67,7 +67,7 @@ bool VHelpUE::initListWidget()
|
|||||||
m_listWidget->addItem(tr("Ctrl+D: Cancel the command"));
|
m_listWidget->addItem(tr("Ctrl+D: Cancel the command"));
|
||||||
m_listWidget->addItem(tr("Ctrl+J: Go to next item"));
|
m_listWidget->addItem(tr("Ctrl+J: Go to next item"));
|
||||||
m_listWidget->addItem(tr("Ctrl+K: Go to previous item"));
|
m_listWidget->addItem(tr("Ctrl+K: Go to previous item"));
|
||||||
m_listWidget->addItem(tr("Ctrl+R: Go to current item's parent item"));
|
m_listWidget->addItem(tr("Ctrl+L: Go to current item's parent item"));
|
||||||
m_listWidget->addItem(tr("Ctrl+T: Expand/Collapse current item"));
|
m_listWidget->addItem(tr("Ctrl+T: Expand/Collapse current item"));
|
||||||
m_listWidget->addItem(tr("Ctrl+S: Sort items"));
|
m_listWidget->addItem(tr("Ctrl+S: Sort items"));
|
||||||
m_listWidget->addItem(tr("Enter: Activate current item"));
|
m_listWidget->addItem(tr("Enter: Activate current item"));
|
||||||
|
@ -50,6 +50,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_flowchartJsFile = ":/utils/flowchart.js/flowchart.min.js";
|
||||||
const QString VNote::c_raphaelJsFile = ":/utils/flowchart.js/raphael.min.js";
|
const QString VNote::c_raphaelJsFile = ":/utils/flowchart.js/raphael.min.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";
|
||||||
|
|
||||||
const QString VNote::c_highlightjsLineNumberExtraFile = ":/utils/highlightjs/highlightjs-line-numbers.min.js";
|
const QString VNote::c_highlightjsLineNumberExtraFile = ":/utils/highlightjs/highlightjs-line-numbers.min.js";
|
||||||
|
|
||||||
const QString VNote::c_docFileFolder = ":/resources/docs";
|
const QString VNote::c_docFileFolder = ":/resources/docs";
|
||||||
@ -128,6 +131,7 @@ QString VNote::generateHtmlTemplate(const QString &p_renderBg,
|
|||||||
"code { word-break: break-all !important; }\n"
|
"code { word-break: break-all !important; }\n"
|
||||||
"div.flowchart-diagram { overflow: hidden !important; }\n"
|
"div.flowchart-diagram { overflow: hidden !important; }\n"
|
||||||
"div.mermaid-diagram { overflow: hidden !important; }\n"
|
"div.mermaid-diagram { overflow: hidden !important; }\n"
|
||||||
|
"div.plantuml-diagram { overflow: hidden !important; }\n"
|
||||||
"a { word-break: break-all !important; }\n"
|
"a { word-break: break-all !important; }\n"
|
||||||
"td.hljs-ln-code { white-space: pre-wrap !important; "
|
"td.hljs-ln-code { white-space: pre-wrap !important; "
|
||||||
"word-break: break-all !important; }\n";
|
"word-break: break-all !important; }\n";
|
||||||
|
@ -64,6 +64,10 @@ public:
|
|||||||
static const QString c_flowchartJsFile;
|
static const QString c_flowchartJsFile;
|
||||||
static const QString c_raphaelJsFile;
|
static const QString c_raphaelJsFile;
|
||||||
|
|
||||||
|
// PlantUML
|
||||||
|
static const QString c_plantUMLJsFile;
|
||||||
|
static const QString c_plantUMLZopfliJsFile;
|
||||||
|
|
||||||
// Highlight.js line number plugin
|
// Highlight.js line number plugin
|
||||||
static const QString c_highlightjsLineNumberExtraFile;
|
static const QString c_highlightjsLineNumberExtraFile;
|
||||||
|
|
||||||
|
90
src/vplantumlhelper.cpp
Normal file
90
src/vplantumlhelper.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "vplantumlhelper.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "vconfigmanager.h"
|
||||||
|
|
||||||
|
extern VConfigManager *g_config;
|
||||||
|
|
||||||
|
#define TaskIdProperty "PlantUMLTaskId"
|
||||||
|
#define TaskFormatProperty "PlantUMLTaskFormat"
|
||||||
|
|
||||||
|
VPlantUMLHelper::VPlantUMLHelper(QObject *p_parent)
|
||||||
|
: QObject(p_parent)
|
||||||
|
{
|
||||||
|
prepareCommand(m_program, m_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VPlantUMLHelper::processAsync(int p_id, const QString &p_format, const QString &p_text)
|
||||||
|
{
|
||||||
|
QProcess *process = new QProcess(this);
|
||||||
|
process->setProperty(TaskIdProperty, p_id);
|
||||||
|
process->setProperty(TaskFormatProperty, p_format);
|
||||||
|
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||||
|
this, SLOT(handleProcessFinished(int, QProcess::ExitStatus)));
|
||||||
|
|
||||||
|
QStringList args(m_args);
|
||||||
|
args << ("-t" + p_format);
|
||||||
|
|
||||||
|
qDebug() << m_program << args;
|
||||||
|
|
||||||
|
process->start(m_program, args);
|
||||||
|
process->write(p_text.toUtf8());
|
||||||
|
process->closeWriteChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VPlantUMLHelper::prepareCommand(QString &p_program, QStringList &p_args) const
|
||||||
|
{
|
||||||
|
p_program = "java";
|
||||||
|
|
||||||
|
p_args << "-jar" << g_config->getPlantUMLJar();
|
||||||
|
p_args << "-charset" << "UTF-8";
|
||||||
|
|
||||||
|
int nbthread = QThread::idealThreadCount();
|
||||||
|
p_args << "-nbthread" << QString::number(nbthread > 0 ? nbthread : 1);
|
||||||
|
|
||||||
|
const QString &dot = g_config->getPlantUMLDot();
|
||||||
|
if (!dot.isEmpty()) {
|
||||||
|
p_args << "-graphvizdot";
|
||||||
|
p_args << dot;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_args << "-pipe";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VPlantUMLHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus)
|
||||||
|
{
|
||||||
|
QProcess *process = static_cast<QProcess *>(sender());
|
||||||
|
int id = process->property(TaskIdProperty).toInt();
|
||||||
|
QString format = process->property(TaskFormatProperty).toString();
|
||||||
|
qDebug() << "process finished" << id << format << p_exitCode << p_exitStatus;
|
||||||
|
bool failed = true;
|
||||||
|
if (p_exitStatus == QProcess::NormalExit) {
|
||||||
|
if (p_exitCode < 0) {
|
||||||
|
qWarning() << "PlantUML fail" << p_exitCode;
|
||||||
|
} else {
|
||||||
|
failed = false;
|
||||||
|
QByteArray outBa = process->readAllStandardOutput();
|
||||||
|
if (format == "svg") {
|
||||||
|
emit resultReady(id, format, QString::fromLocal8Bit(outBa));
|
||||||
|
} else {
|
||||||
|
emit resultReady(id, format, QString::fromLocal8Bit(outBa.toBase64()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "fail to start PlantUML process" << p_exitCode << p_exitStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
QByteArray errBa = process->readAllStandardError();
|
||||||
|
if (!errBa.isEmpty()) {
|
||||||
|
QString errStr(QString::fromLocal8Bit(errBa));
|
||||||
|
qWarning() << "PlantUML stderr:" << errStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit resultReady(id, format, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
process->deleteLater();
|
||||||
|
}
|
30
src/vplantumlhelper.h
Normal file
30
src/vplantumlhelper.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef VPLANTUMLHELPER_H
|
||||||
|
#define VPLANTUMLHELPER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
class VPlantUMLHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit VPlantUMLHelper(QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
void processAsync(int p_id, const QString &p_format, const QString &p_text);
|
||||||
|
|
||||||
|
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultReady(int p_id, const QString &p_format, const QString &p_result);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_program;
|
||||||
|
QStringList m_args;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VPLANTUMLHELPER_H
|
@ -16,14 +16,14 @@ bool VPreviewPage::acceptNavigationRequest(const QUrl &p_url,
|
|||||||
bool p_isMainFrame)
|
bool p_isMainFrame)
|
||||||
{
|
{
|
||||||
Q_UNUSED(p_type);
|
Q_UNUSED(p_type);
|
||||||
Q_UNUSED(p_isMainFrame);
|
|
||||||
|
|
||||||
if (p_url.isLocalFile()) {
|
if (p_url.isLocalFile()) {
|
||||||
QString filePath = p_url.toLocalFile();
|
QString filePath = p_url.toLocalFile();
|
||||||
if (g_mainWin->tryOpenInternalFile(filePath)) {
|
if (g_mainWin->tryOpenInternalFile(filePath)) {
|
||||||
qDebug() << "internal notes jump" << filePath;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (!p_isMainFrame) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDesktopServices::openUrl(p_url);
|
QDesktopServices::openUrl(p_url);
|
||||||
|
@ -352,9 +352,9 @@ void VUniversalEntry::keyPressEvent(QKeyEvent *p_event)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_R:
|
case Qt::Key_L:
|
||||||
if (VUtils::isControlModifierForVim(modifiers)) {
|
if (VUtils::isControlModifierForVim(modifiers)) {
|
||||||
// Ctrl+R to go up a level.
|
// Ctrl+L to go up a level.
|
||||||
if (m_lastEntry) {
|
if (m_lastEntry) {
|
||||||
m_lastEntry->m_entry->selectParentItem(m_lastEntry->m_id);
|
m_lastEntry->m_entry->selectParentItem(m_lastEntry->m_id);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user