* MarkdownViewWindow: add switch for code block line number
* MarkodwnViewWindow: fix Turndown <style> issue
* MarkdownViewWindow: add config for overridding MathJax script
* SortDialog: fix sorting issue of date
* FramelessMainWindow: fix StayOnTop issue
This commit is contained in:
Le Tan 2022-01-10 20:06:45 +08:00
parent 09dba18994
commit a4a5dea3d7
27 changed files with 209 additions and 67 deletions

View File

@ -139,6 +139,15 @@ namespace vnotex
CRLF, CRLF,
CR CR
}; };
enum Role
{
// Qt::UserRole = 0x0100
UserRole2 = 0x0101,
HighlightsRole = 0x0102,
// Used for comparison.
ComparisonRole = 0x0103
};
} // ns vnotex } // ns vnotex
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions); Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions);

View File

@ -21,6 +21,7 @@ QString WebGlobalOptions::toJavascriptObject() const
return QStringLiteral("window.vxOptions = {\n") return QStringLiteral("window.vxOptions = {\n")
+ QString("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml)) + QString("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml))
+ QString("webGraphviz: %1,\n").arg(Utils::boolToString(m_webGraphviz)) + QString("webGraphviz: %1,\n").arg(Utils::boolToString(m_webGraphviz))
+ QString("mathJaxScript: '%1',\n").arg(m_mathJaxScript)
+ QString("constrainImageWidthEnabled: %1,\n").arg(Utils::boolToString(m_constrainImageWidthEnabled)) + QString("constrainImageWidthEnabled: %1,\n").arg(Utils::boolToString(m_constrainImageWidthEnabled))
+ QString("imageAlignCenterEnabled: %1,\n").arg(Utils::boolToString(m_imageAlignCenterEnabled)) + QString("imageAlignCenterEnabled: %1,\n").arg(Utils::boolToString(m_imageAlignCenterEnabled))
+ QString("protectFromXss: %1,\n").arg(Utils::boolToString(m_protectFromXss)) + QString("protectFromXss: %1,\n").arg(Utils::boolToString(m_protectFromXss))
@ -28,6 +29,7 @@ QString WebGlobalOptions::toJavascriptObject() const
+ QString("autoBreakEnabled: %1,\n").arg(Utils::boolToString(m_autoBreakEnabled)) + QString("autoBreakEnabled: %1,\n").arg(Utils::boolToString(m_autoBreakEnabled))
+ QString("linkifyEnabled: %1,\n").arg(Utils::boolToString(m_linkifyEnabled)) + QString("linkifyEnabled: %1,\n").arg(Utils::boolToString(m_linkifyEnabled))
+ QString("indentFirstLineEnabled: %1,\n").arg(Utils::boolToString(m_indentFirstLineEnabled)) + QString("indentFirstLineEnabled: %1,\n").arg(Utils::boolToString(m_indentFirstLineEnabled))
+ QString("codeBlockLineNumberEnabled: %1,\n").arg(Utils::boolToString(m_codeBlockLineNumberEnabled))
+ QString("sectionNumberEnabled: %1,\n").arg(Utils::boolToString(m_sectionNumberEnabled)) + QString("sectionNumberEnabled: %1,\n").arg(Utils::boolToString(m_sectionNumberEnabled))
+ QString("transparentBackgroundEnabled: %1,\n").arg(Utils::boolToString(m_transparentBackgroundEnabled)) + QString("transparentBackgroundEnabled: %1,\n").arg(Utils::boolToString(m_transparentBackgroundEnabled))
+ QString("scrollable: %1,\n").arg(Utils::boolToString(m_scrollable)) + QString("scrollable: %1,\n").arg(Utils::boolToString(m_scrollable))
@ -212,6 +214,7 @@ QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorC
WebGlobalOptions opts; WebGlobalOptions opts;
opts.m_webPlantUml = p_config.getWebPlantUml(); opts.m_webPlantUml = p_config.getWebPlantUml();
opts.m_webGraphviz = p_config.getWebGraphviz(); opts.m_webGraphviz = p_config.getWebGraphviz();
opts.m_mathJaxScript = p_config.getMathJaxScript();
opts.m_sectionNumberEnabled = p_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Read; opts.m_sectionNumberEnabled = p_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Read;
opts.m_sectionNumberBaseLevel = p_config.getSectionNumberBaseLevel(); opts.m_sectionNumberBaseLevel = p_config.getSectionNumberBaseLevel();
opts.m_constrainImageWidthEnabled = p_config.getConstrainImageWidthEnabled(); opts.m_constrainImageWidthEnabled = p_config.getConstrainImageWidthEnabled();
@ -221,6 +224,7 @@ QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorC
opts.m_autoBreakEnabled = p_config.getAutoBreakEnabled(); opts.m_autoBreakEnabled = p_config.getAutoBreakEnabled();
opts.m_linkifyEnabled = p_config.getLinkifyEnabled(); opts.m_linkifyEnabled = p_config.getLinkifyEnabled();
opts.m_indentFirstLineEnabled = p_config.getIndentFirstLineEnabled(); opts.m_indentFirstLineEnabled = p_config.getIndentFirstLineEnabled();
opts.m_codeBlockLineNumberEnabled = p_config.getCodeBlockLineNumberEnabled();
opts.m_transparentBackgroundEnabled = p_paras.m_transparentBackgroundEnabled; opts.m_transparentBackgroundEnabled = p_paras.m_transparentBackgroundEnabled;
opts.m_scrollable = p_paras.m_scrollable; opts.m_scrollable = p_paras.m_scrollable;
opts.m_bodyWidth = p_paras.m_bodyWidth; opts.m_bodyWidth = p_paras.m_bodyWidth;

View File

@ -15,6 +15,8 @@ namespace vnotex
bool m_webGraphviz = true; bool m_webGraphviz = true;
QString m_mathJaxScript;
bool m_sectionNumberEnabled = true; bool m_sectionNumberEnabled = true;
int m_sectionNumberBaseLevel = 2; int m_sectionNumberBaseLevel = 2;
@ -33,6 +35,8 @@ namespace vnotex
bool m_indentFirstLineEnabled = false; bool m_indentFirstLineEnabled = false;
bool m_codeBlockLineNumberEnabled = true;
// Force to use transparent background. // Force to use transparent background.
bool m_transparentBackgroundEnabled = false; bool m_transparentBackgroundEnabled = false;

View File

@ -39,6 +39,8 @@ void MarkdownEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_u
m_graphvizExe = READSTR(QStringLiteral("graphviz_exe")); m_graphvizExe = READSTR(QStringLiteral("graphviz_exe"));
m_mathJaxScript = READSTR(QStringLiteral("mathjax_script"));
m_prependDotInRelativeLink = READBOOL(QStringLiteral("prepend_dot_in_relative_link")); m_prependDotInRelativeLink = READBOOL(QStringLiteral("prepend_dot_in_relative_link"));
m_confirmBeforeClearObsoleteImages = READBOOL(QStringLiteral("confirm_before_clear_obsolete_images")); m_confirmBeforeClearObsoleteImages = READBOOL(QStringLiteral("confirm_before_clear_obsolete_images"));
m_insertFileNameAsTitle = READBOOL(QStringLiteral("insert_file_name_as_title")); m_insertFileNameAsTitle = READBOOL(QStringLiteral("insert_file_name_as_title"));
@ -58,6 +60,7 @@ void MarkdownEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_u
m_autoBreakEnabled = READBOOL(QStringLiteral("auto_break")); m_autoBreakEnabled = READBOOL(QStringLiteral("auto_break"));
m_linkifyEnabled = READBOOL(QStringLiteral("linkify")); m_linkifyEnabled = READBOOL(QStringLiteral("linkify"));
m_indentFirstLineEnabled = READBOOL(QStringLiteral("indent_first_line")); m_indentFirstLineEnabled = READBOOL(QStringLiteral("indent_first_line"));
m_codeBlockLineNumberEnabled = READBOOL(QStringLiteral("code_block_line_number"));
m_smartTableEnabled = READBOOL(QStringLiteral("smart_table")); m_smartTableEnabled = READBOOL(QStringLiteral("smart_table"));
m_smartTableInterval = READINT(QStringLiteral("smart_table_interval")); m_smartTableInterval = READINT(QStringLiteral("smart_table_interval"));
@ -87,6 +90,7 @@ QJsonObject MarkdownEditorConfig::toJson() const
obj[QStringLiteral("plantuml_command")] = m_plantUmlCommand; obj[QStringLiteral("plantuml_command")] = m_plantUmlCommand;
obj[QStringLiteral("web_graphviz")] = m_webGraphviz; obj[QStringLiteral("web_graphviz")] = m_webGraphviz;
obj[QStringLiteral("graphviz_exe")] = m_graphvizExe; obj[QStringLiteral("graphviz_exe")] = m_graphvizExe;
obj[QStringLiteral("mathjax_script")] = m_mathJaxScript;
obj[QStringLiteral("prepend_dot_in_relative_link")] = m_prependDotInRelativeLink; obj[QStringLiteral("prepend_dot_in_relative_link")] = m_prependDotInRelativeLink;
obj[QStringLiteral("confirm_before_clear_obsolete_images")] = m_confirmBeforeClearObsoleteImages; obj[QStringLiteral("confirm_before_clear_obsolete_images")] = m_confirmBeforeClearObsoleteImages;
obj[QStringLiteral("insert_file_name_as_title")] = m_insertFileNameAsTitle; obj[QStringLiteral("insert_file_name_as_title")] = m_insertFileNameAsTitle;
@ -105,6 +109,7 @@ QJsonObject MarkdownEditorConfig::toJson() const
obj[QStringLiteral("auto_break")] = m_autoBreakEnabled; obj[QStringLiteral("auto_break")] = m_autoBreakEnabled;
obj[QStringLiteral("linkify")] = m_linkifyEnabled; obj[QStringLiteral("linkify")] = m_linkifyEnabled;
obj[QStringLiteral("indent_first_line")] = m_indentFirstLineEnabled; obj[QStringLiteral("indent_first_line")] = m_indentFirstLineEnabled;
obj[QStringLiteral("code_block_line_number")] = m_codeBlockLineNumberEnabled;
obj[QStringLiteral("smart_table")] = m_smartTableEnabled; obj[QStringLiteral("smart_table")] = m_smartTableEnabled;
obj[QStringLiteral("smart_table_interval")] = m_smartTableInterval; obj[QStringLiteral("smart_table_interval")] = m_smartTableInterval;
obj[QStringLiteral("spell_check")] = m_spellCheckEnabled; obj[QStringLiteral("spell_check")] = m_spellCheckEnabled;
@ -249,6 +254,16 @@ void MarkdownEditorConfig::setGraphvizExe(const QString &p_exe)
updateConfig(m_graphvizExe, p_exe, this); updateConfig(m_graphvizExe, p_exe, this);
} }
const QString &MarkdownEditorConfig::getMathJaxScript() const
{
return m_mathJaxScript;
}
void MarkdownEditorConfig::setMathJaxScript(const QString &p_script)
{
updateConfig(m_mathJaxScript, p_script, this);
}
bool MarkdownEditorConfig::getPrependDotInRelativeLink() const bool MarkdownEditorConfig::getPrependDotInRelativeLink() const
{ {
return m_prependDotInRelativeLink; return m_prependDotInRelativeLink;
@ -371,6 +386,16 @@ void MarkdownEditorConfig::setIndentFirstLineEnabled(bool p_enabled)
updateConfig(m_indentFirstLineEnabled, p_enabled, this); updateConfig(m_indentFirstLineEnabled, p_enabled, this);
} }
bool MarkdownEditorConfig::getCodeBlockLineNumberEnabled() const
{
return m_codeBlockLineNumberEnabled;
}
void MarkdownEditorConfig::setCodeBlockLineNumberEnabled(bool p_enabled)
{
updateConfig(m_codeBlockLineNumberEnabled, p_enabled, this);
}
QString MarkdownEditorConfig::sectionNumberModeToString(SectionNumberMode p_mode) const QString MarkdownEditorConfig::sectionNumberModeToString(SectionNumberMode p_mode) const
{ {
switch (p_mode) { switch (p_mode) {

View File

@ -76,6 +76,9 @@ namespace vnotex
const QString &getGraphvizExe() const; const QString &getGraphvizExe() const;
void setGraphvizExe(const QString &p_exe); void setGraphvizExe(const QString &p_exe);
const QString &getMathJaxScript() const;
void setMathJaxScript(const QString &p_script);
bool getPrependDotInRelativeLink() const; bool getPrependDotInRelativeLink() const;
bool getConfirmBeforeClearObsoleteImages() const; bool getConfirmBeforeClearObsoleteImages() const;
@ -122,6 +125,9 @@ namespace vnotex
bool getIndentFirstLineEnabled() const; bool getIndentFirstLineEnabled() const;
void setIndentFirstLineEnabled(bool p_enabled); void setIndentFirstLineEnabled(bool p_enabled);
bool getCodeBlockLineNumberEnabled() const;
void setCodeBlockLineNumberEnabled(bool p_enabled);
bool getSmartTableEnabled() const; bool getSmartTableEnabled() const;
void setSmartTableEnabled(bool p_enabled); void setSmartTableEnabled(bool p_enabled);
@ -181,6 +187,9 @@ namespace vnotex
// Graphviz executable file. // Graphviz executable file.
QString m_graphvizExe; QString m_graphvizExe;
// MathJax script to override that in mathjax.js file.
QString m_mathJaxScript;
// Whether prepend a dot in front of the relative link, like images. // Whether prepend a dot in front of the relative link, like images.
bool m_prependDotInRelativeLink = false; bool m_prependDotInRelativeLink = false;
@ -227,6 +236,9 @@ namespace vnotex
// Whether indent the first line of a paragraph. // Whether indent the first line of a paragraph.
bool m_indentFirstLineEnabled = false; bool m_indentFirstLineEnabled = false;
// Whether enable code block line number in read mode.
bool m_codeBlockLineNumberEnabled = true;
bool m_smartTableEnabled = true; bool m_smartTableEnabled = true;
// Interval time to do smart table format. // Interval time to do smart table format.

View File

@ -318,6 +318,8 @@
"web_graphviz" : true, "web_graphviz" : true,
"//commnet" : "Local Graphviz executable file to render Graphviz", "//commnet" : "Local Graphviz executable file to render Graphviz",
"graphviz_exe" : "", "graphviz_exe" : "",
"//commnet" : "MathJax script to use",
"mathjax_script" : "",
"//comment" : "Whether prepend a dot at front in relative link like images", "//comment" : "Whether prepend a dot at front in relative link like images",
"prepend_dot_in_relative_link" : false, "prepend_dot_in_relative_link" : false,
"//comment" : "Whether ask for user confirmation before clearing obsolete images", "//comment" : "Whether ask for user confirmation before clearing obsolete images",
@ -350,6 +352,8 @@
"linkify" : true, "linkify" : true,
"//comment" : "Whether add indentation to the first line of paragraph", "//comment" : "Whether add indentation to the first line of paragraph",
"indent_first_line" : false, "indent_first_line" : false,
"//comment" : "Whether add line number to fenced code block in read mode",
"code_block_line_number" : true,
"//comment" : "Whether enable smart table (formatting)", "//comment" : "Whether enable smart table (formatting)",
"smart_table" : true, "smart_table" : true,
"//comment" : "Time interval (milliseconds) to do smart table formatting", "//comment" : "Time interval (milliseconds) to do smart table formatting",

View File

@ -21,8 +21,8 @@ Here is an overview of Markdown syntax supported by VNote.
**Notes**: **Notes**:
* At least one space is needed after the `#`; * At least one space is needed after the `#`
* A header should occupy one entire line; * A header should occupy one entire line
### Emphasis ### Emphasis
```md ```md
@ -35,8 +35,8 @@ __This text will be bold__
**Notes**: **Notes**:
* `*` is recommended in VNote; * `*` is recommended in VNote
* If the render failed, try to add an additional space before the first `*` and after the last `*`. The space is necessary if the surrounded text begins or ends with full width punctuation; * If the render failed, try to add an additional space before the first `*` and after the last `*`. The space is necessary if the surrounded text begins or ends with full width punctuation
### Lists ### Lists
#### Unordered #### Unordered
@ -107,8 +107,8 @@ Here is another sentence within the quote.
**Notes**: **Notes**:
* Space is needed after the marker `>`; * Space is needed after the marker `>`
* You could just add only one `>` at the first line; * You could just add only one `>` at the first line
### Fenced Code Block ### Fenced Code Block
```lang ```lang
@ -121,15 +121,16 @@ Here is another sentence within the quote.
**Notes**: **Notes**:
* `lang` is optional to specify the language of the code; if not specified, VNote won't highlight the code; * `lang` is optional to specify the language of the code; if not specified, VNote won't highlight the code
* It is always a good practice to add one empty line before the whole fenced code block; * For a detailed supported languages list, please visit [Prism](https://prismjs.com/#supported-languages)
* It is always a good practice to add one empty line before the whole fenced code block
### Diagrams ### Diagrams
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. 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`; * [Flowchart.js](http://flowchart.js.org/) for *flowchart* with language `flow` or `flowchart`
* [Mermaid](https://mermaidjs.github.io/) with language `mermaid`; * [Mermaid](https://mermaidjs.github.io/) with language `mermaid`
* [WaveDrom](https://wavedrom.com/) for *digital timing diagram* with language `wavedrom`; * [WaveDrom](https://wavedrom.com/) for *digital timing diagram* with language `wavedrom`
For example, For example,
@ -162,11 +163,11 @@ VNote supports [Graphviz](http://www.graphviz.org/) to draw diagrams. You should
### Math Formulas ### Math Formulas
VNote supports math formulas via [MathJax](https://www.mathjax.org/). The default math delimiters are `$$...$$` for **displayed mathematics**, and `$...$` for **inline mathematics**. VNote supports math formulas via [MathJax](https://www.mathjax.org/). The default math delimiters are `$$...$$` for **displayed mathematics**, and `$...$` for **inline mathematics**.
* Inline mathematics should not cross multiple lines; * Inline mathematics should not cross multiple lines
* Forms like `3$abc$`, `$abc$4`, `$ abc$`, and `$abc $` will not be treated as mathematics; * Forms like `3$abc$`, `$abc$4`, `$ abc$`, and `$abc $` will not be treated as mathematics
* Use `\` to escape `$`; * Use `\` to escape `$`
* There should be only space chars before opening `$$` and after closing `$$`; * There should be only space chars before opening `$$` and after closing `$$`
* Use `\\` to new a line within a displayed mathematics; * Use `\\` to new a line within a displayed mathematics
VNote also supports displayed mathematics via fenced code block with language `mathjax` specified. VNote also supports displayed mathematics via fenced code block with language `mathjax` specified.

View File

@ -1,8 +1,8 @@
# Shortcuts # Shortcuts
1. All the keys without special notice are **case insensitive**; 1. All the keys without special notice are **case insensitive**
2. On macOS, `Ctrl` corresponds to `Command` except in Vi mode; 2. On macOS, `Ctrl` corresponds to `Command` except in Vi mode
3. The key sequence `Ctrl+G, I` means that first press both `Ctrl` and `G` simultaneously, release them, then press `I` and release; 3. The key sequence `Ctrl+G, I` means that first press both `Ctrl` and `G` simultaneously, release them, then press `I` and release
4. For a **complete latest shortcuts list** or modifying default shortcuts, please view the `vnotex.json` configuration file. 4. For a **complete latest shortcuts list** or modifying default shortcuts, please view the `vnotex.json` configuration file
## General ## General
- `Ctrl+G, E` - `Ctrl+G, E`
@ -77,12 +77,12 @@ Zoom in/out the page through the mouse scroll.
- `Ctrl+0` - `Ctrl+0`
Recover the page zoom factor to 100%. Recover the page zoom factor to 100%.
- Jump between titles - Jump between titles
- `<N>[[`: jump to previous `N` title; - `<N>[[`: jump to previous `N` title
- `<N>]]`: jump to next `N` title; - `<N>]]`: jump to next `N` title
- `<N>[]`: jump to previous `N` title at the same level; - `<N>[]`: jump to previous `N` title at the same level
- `<N>][`: jump to next `N` title at the same level; - `<N>][`: jump to next `N` title at the same level
- `<N>[{`: jump to previous `N` title at a higher level; - `<N>[{`: jump to previous `N` title at a higher level
- `<N>]}`: jump to next `N` title at a higher level; - `<N>]}`: jump to next `N` title at a higher level
### Edit Mode ### Edit Mode
Shares the same shortcuts with Text Editor. Shares the same shortcuts with Text Editor.

View File

@ -21,8 +21,8 @@ Markdown是一种通过少量简单的标记字符来格式化文本的方法。
**注意** **注意**
* `#`之后需要至少一个空格 * `#`之后需要至少一个空格
* 一个标题应该占一整行 * 一个标题应该占一整行
### 强调 ### 强调
```md ```md
@ -35,8 +35,8 @@ __This text will be bold__
**注意** **注意**
* VNote推荐使用`*` * VNote推荐使用`*`
* 如果渲染错误,请尝试在第一个`*`之前以及最后一个`*`之后添加一个空格。如果被标记的文本是以全角符号开始或结尾,一般都需要前后添加一个空格 * 如果渲染错误,请尝试在第一个`*`之前以及最后一个`*`之后添加一个空格。如果被标记的文本是以全角符号开始或结尾,一般都需要前后添加一个空格
### 列表 ### 列表
#### 无序列表 #### 无序列表
@ -107,8 +107,8 @@ Here is another sentence within the quote.
**注意** **注意**
* `>`标记后面需要至少一个空格 * `>`标记后面需要至少一个空格
* 多行连续的引用可以只在第一行添加标记 * 多行连续的引用可以只在第一行添加标记
### 代码块 ### 代码块
```lang ```lang
@ -121,15 +121,16 @@ Here is another sentence within the quote.
**注意** **注意**
* `lang`用于指定代码块的代码语言可选如果不指定VNote不会尝试高亮代码 * `lang`用于指定代码块的代码语言可选如果不指定VNote不会尝试高亮代码
* 总是在一个代码块前面添加一个空行是一个不错的实践; * 请访问[Prism](https://prismjs.com/#supported-languages)获取一个完整的支持语言列表
* 总是在一个代码块前面添加一个空行是一个不错的实践
### 图表 ### 图表
VNote支持使用以下引擎来绘制图表。您需要使用代码块并标明特定语言然后在代码块里面定义图表。 VNote支持使用以下引擎来绘制图表。您需要使用代码块并标明特定语言然后在代码块里面定义图表。
* [Flowchart.js](http://flowchart.js.org/),语言为`flow``flowchart` * [Flowchart.js](http://flowchart.js.org/),语言为`flow``flowchart`
* [Mermaid](https://mermaidjs.github.io/),语言为`mermaid` * [Mermaid](https://mermaidjs.github.io/),语言为`mermaid`
* [WaveDrom](https://wavedrom.com/),数字时序图,语言为`wavedrom` * [WaveDrom](https://wavedrom.com/),数字时序图,语言为`wavedrom`
例如, 例如,
@ -162,11 +163,11 @@ VNote支持[Graphviz](http://www.graphviz.org/)来绘制图表。您需要使用
### 数学公式 ### 数学公式
VNote通过[MathJax](https://www.mathjax.org/)来支持数学公式。默认的**公式块**的分隔符是`$$...$$`**行内公式**的分隔符是`$...$` VNote通过[MathJax](https://www.mathjax.org/)来支持数学公式。默认的**公式块**的分隔符是`$$...$$`**行内公式**的分隔符是`$...$`
* 行内公式不能跨多行 * 行内公式不能跨多行
* 形如`3$abc$`/`$abc$4`/`$ abc$``$abc $`的不会被解析为公式 * 形如`3$abc$`/`$abc$4`/`$ abc$``$abc $`的不会被解析为公式
* 使用`\`转义`$` * 使用`\`转义`$`
* 开始的`$$`之前以及结束的`$$`之后都只允许出现空格字符 * 开始的`$$`之前以及结束的`$$`之后都只允许出现空格字符
* 在公式块中,使用`\\`来换行 * 在公式块中,使用`\\`来换行
VNote也可以使用标明语言`mathjax`的代码块来实现公式块。 VNote也可以使用标明语言`mathjax`的代码块来实现公式块。

View File

@ -1,8 +1,8 @@
# 快捷键 # 快捷键
1. 以下按键除特别说明外,都不区分大小写 1. 以下按键除特别说明外,都不区分大小写
2. 在macOS下`Ctrl`对应于`Command`在Vi模式下除外 2. 在macOS下`Ctrl`对应于`Command`在Vi模式下除外
3. 按键序列`Ctrl+G, I`表示先同时按下`Ctrl``G`,释放,然后按下`I`并释放 3. 按键序列`Ctrl+G, I`表示先同时按下`Ctrl``G`,释放,然后按下`I`并释放
4. 可以通过查看配置文件`vnotex.json`来获取一个**完整的最新的快捷键列表**或者修改默认快捷键 4. 可以通过查看配置文件`vnotex.json`来获取一个**完整的最新的快捷键列表**或者修改默认快捷键
## 通用 ## 通用
- `Ctrl+G, E` - `Ctrl+G, E`
@ -77,12 +77,12 @@ VNote的很多部件均支持`Ctrl+J`和`Ctrl+K`导航。
- `Ctrl+0` - `Ctrl+0`
恢复页面大小为100%。 恢复页面大小为100%。
- 标题跳转 - 标题跳转
- `<N>[[`:跳转到上`N`个标题 - `<N>[[`:跳转到上`N`个标题
- `<N>]]`:跳转到下`N`个标题 - `<N>]]`:跳转到下`N`个标题
- `<N>[]`:跳转到上`N`个同层级的标题 - `<N>[]`:跳转到上`N`个同层级的标题
- `<N>][`:跳转到下`N`个同层级的标题 - `<N>][`:跳转到下`N`个同层级的标题
- `<N>[{`:跳转到上`N`个高一层级的标题 - `<N>[{`:跳转到上`N`个高一层级的标题
- `<N>]}`:跳转到下`N`个高一层级的标题 - `<N>]}`:跳转到下`N`个高一层级的标题
### 编辑模式 ### 编辑模式
和文本编辑器共享一样的快捷键。 和文本编辑器共享一样的快捷键。

View File

@ -56,6 +56,10 @@ class MathJaxRenderer extends VxWorker {
this.initialized = true; this.initialized = true;
this.readyCallback = p_callback; this.readyCallback = p_callback;
if (!!window.vxOptions.mathJaxScript) {
this.mathJaxScript = window.vxOptions.mathJaxScript;
console.log('override MathJax script', this.mathJaxScript);
}
Utils.loadScript(this.mathJaxScript, null); Utils.loadScript(this.mathJaxScript, null);
return false; return false;
} }

View File

@ -83,8 +83,6 @@ class PrismRenderer extends VxWorker {
} }
} }
p_containerNode.classList.add('line-numbers');
Prism.highlightAllUnder(p_containerNode, false /* async or not */); Prism.highlightAllUnder(p_containerNode, false /* async or not */);
// Remove the toolbar. // Remove the toolbar.

View File

@ -20,6 +20,9 @@ class TurndownConverter {
this.ts.use(turndownPluginGfm.gfm); this.ts.use(turndownPluginGfm.gfm);
// TODO: verify and copy several rules from VNote 2.0. // TODO: verify and copy several rules from VNote 2.0.
// No <head> and <style> parse.
this.ts.remove(['head', 'style']);
this.fixMark(); this.fixMark();
this.fixParagraph(); this.fixParagraph();

View File

@ -69,6 +69,8 @@ class VNoteX extends EventEmitter {
window.vxOptions.imageAlignCenterEnabled); window.vxOptions.imageAlignCenterEnabled);
this.setContentContainerOption('vx-indent-first-line', this.setContentContainerOption('vx-indent-first-line',
window.vxOptions.indentFirstLineEnabled); window.vxOptions.indentFirstLineEnabled);
this.setContentContainerOption('line-numbers',
window.vxOptions.codeBlockLineNumberEnabled);
this.setBodyOption('vx-transparent-background', this.setBodyOption('vx-transparent-background',
window.vxOptions.transparentBackgroundEnabled); window.vxOptions.transparentBackgroundEnabled);
this.setContentContainerOption('vx-nonscrollable', this.setContentContainerOption('vx-nonscrollable',

View File

@ -24,6 +24,7 @@
#include <widgets/messageboxhelper.h> #include <widgets/messageboxhelper.h>
#include <widgets/editors/plantumlhelper.h> #include <widgets/editors/plantumlhelper.h>
#include <widgets/editors/graphvizhelper.h> #include <widgets/editors/graphvizhelper.h>
#include <widgets/lineedit.h>
using namespace vnotex; using namespace vnotex;
@ -90,6 +91,8 @@ void MarkdownEditorPage::loadInternal()
m_indentFirstLineCheckBox->setChecked(markdownConfig.getIndentFirstLineEnabled()); m_indentFirstLineCheckBox->setChecked(markdownConfig.getIndentFirstLineEnabled());
m_codeBlockLineNumberCheckBox->setChecked(markdownConfig.getCodeBlockLineNumberEnabled());
m_smartTableCheckBox->setChecked(markdownConfig.getSmartTableEnabled()); m_smartTableCheckBox->setChecked(markdownConfig.getSmartTableEnabled());
m_spellCheckCheckBox->setChecked(markdownConfig.isSpellCheckEnabled()); m_spellCheckCheckBox->setChecked(markdownConfig.isSpellCheckEnabled());
@ -108,6 +111,8 @@ void MarkdownEditorPage::loadInternal()
m_graphvizFileInput->setText(markdownConfig.getGraphvizExe()); m_graphvizFileInput->setText(markdownConfig.getGraphvizExe());
m_mathJaxScriptLineEdit->setText(markdownConfig.getMathJaxScript());
{ {
const auto &fontFamily = markdownConfig.getEditorOverriddenFontFamily(); const auto &fontFamily = markdownConfig.getEditorOverriddenFontFamily();
m_editorOverriddenFontFamilyCheckBox->setChecked(!fontFamily.isEmpty()); m_editorOverriddenFontFamilyCheckBox->setChecked(!fontFamily.isEmpty());
@ -172,6 +177,8 @@ bool MarkdownEditorPage::saveInternal()
markdownConfig.setIndentFirstLineEnabled(m_indentFirstLineCheckBox->isChecked()); markdownConfig.setIndentFirstLineEnabled(m_indentFirstLineCheckBox->isChecked());
markdownConfig.setCodeBlockLineNumberEnabled(m_codeBlockLineNumberCheckBox->isChecked());
markdownConfig.setSmartTableEnabled(m_smartTableCheckBox->isChecked()); markdownConfig.setSmartTableEnabled(m_smartTableCheckBox->isChecked());
markdownConfig.setSpellCheckEnabled(m_spellCheckCheckBox->isChecked()); markdownConfig.setSpellCheckEnabled(m_spellCheckCheckBox->isChecked());
@ -184,6 +191,8 @@ bool MarkdownEditorPage::saveInternal()
markdownConfig.setGraphvizExe(m_graphvizFileInput->text()); markdownConfig.setGraphvizExe(m_graphvizFileInput->text());
markdownConfig.setMathJaxScript(m_mathJaxScriptLineEdit->text());
{ {
bool checked = m_editorOverriddenFontFamilyCheckBox->isChecked(); bool checked = m_editorOverriddenFontFamilyCheckBox->isChecked();
markdownConfig.setEditorOverriddenFontFamily(checked ? m_editorOverriddenFontFamilyComboBox->currentFont().family() : QString()); markdownConfig.setEditorOverriddenFontFamily(checked ? m_editorOverriddenFontFamilyComboBox->currentFont().family() : QString());
@ -278,6 +287,16 @@ QGroupBox *MarkdownEditorPage::setupReadGroup()
this, &MarkdownEditorPage::pageIsChanged); this, &MarkdownEditorPage::pageIsChanged);
} }
{
const QString label(tr("Code block line number"));
m_codeBlockLineNumberCheckBox = WidgetsFactory::createCheckBox(label, box);
m_codeBlockLineNumberCheckBox->setToolTip(tr("Add line number to code block"));
layout->addRow(m_codeBlockLineNumberCheckBox);
addSearchItem(label, m_codeBlockLineNumberCheckBox->toolTip(), m_codeBlockLineNumberCheckBox);
connect(m_codeBlockLineNumberCheckBox, &QCheckBox::stateChanged,
this, &MarkdownEditorPage::pageIsChanged);
}
return box; return box;
} }
@ -552,5 +571,16 @@ QGroupBox *MarkdownEditorPage::setupGeneralGroup()
this, &MarkdownEditorPage::pageIsChanged); this, &MarkdownEditorPage::pageIsChanged);
} }
{
m_mathJaxScriptLineEdit = WidgetsFactory::createLineEdit(box);
m_mathJaxScriptLineEdit->setToolTip(tr("Override the MathJax script used to render math formulas"));
const QString label(tr("MathJax script:"));
layout->addRow(label, m_mathJaxScriptLineEdit);
addSearchItem(label, m_mathJaxScriptLineEdit->toolTip(), m_mathJaxScriptLineEdit);
connect(m_mathJaxScriptLineEdit, &QLineEdit::textChanged,
this, &MarkdownEditorPage::pageIsChanged);
}
return box; return box;
} }

View File

@ -9,6 +9,7 @@ class QDoubleSpinBox;
class QSpinBox; class QSpinBox;
class QComboBox; class QComboBox;
class QFontComboBox; class QFontComboBox;
class QLineEdit;
namespace vnotex namespace vnotex
{ {
@ -60,6 +61,8 @@ namespace vnotex
QCheckBox *m_indentFirstLineCheckBox = nullptr; QCheckBox *m_indentFirstLineCheckBox = nullptr;
QCheckBox *m_codeBlockLineNumberCheckBox = nullptr;
QDoubleSpinBox *m_zoomFactorSpinBox = nullptr; QDoubleSpinBox *m_zoomFactorSpinBox = nullptr;
QComboBox *m_sectionNumberComboBox = nullptr; QComboBox *m_sectionNumberComboBox = nullptr;
@ -80,6 +83,8 @@ namespace vnotex
LocationInputWithBrowseButton *m_graphvizFileInput = nullptr; LocationInputWithBrowseButton *m_graphvizFileInput = nullptr;
QLineEdit *m_mathJaxScriptLineEdit = nullptr;
QCheckBox *m_editorOverriddenFontFamilyCheckBox = nullptr; QCheckBox *m_editorOverriddenFontFamilyCheckBox = nullptr;
QFontComboBox *m_editorOverriddenFontFamilyComboBox = nullptr; QFontComboBox *m_editorOverriddenFontFamilyComboBox = nullptr;

View File

@ -9,6 +9,7 @@
#include <widgets/treewidget.h> #include <widgets/treewidget.h>
#include <widgets/widgetsfactory.h> #include <widgets/widgetsfactory.h>
#include <widgets/treewidgetitem.h> #include <widgets/treewidgetitem.h>
#include <core/global.h>
using namespace vnotex; using namespace vnotex;
@ -248,3 +249,15 @@ QTreeWidgetItem *SortDialog::addItem(const QStringList &p_cols)
auto item = new TreeWidgetItem(m_treeWidget, p_cols); auto item = new TreeWidgetItem(m_treeWidget, p_cols);
return item; return item;
} }
QTreeWidgetItem *SortDialog::addItem(const QStringList &p_cols, const QStringList &p_comparisonCols)
{
Q_ASSERT(p_cols.size() == p_comparisonCols.size());
auto item = new TreeWidgetItem(m_treeWidget, p_cols);
for (int i = 0; i < p_cols.size(); ++i) {
if (!p_comparisonCols[i].isNull()) {
item->setData(i, Role::ComparisonRole, p_comparisonCols[i]);
}
}
return item;
}

View File

@ -26,6 +26,10 @@ namespace vnotex
// Add one item to the tree. // Add one item to the tree.
QTreeWidgetItem *addItem(const QStringList &p_cols); QTreeWidgetItem *addItem(const QStringList &p_cols);
// Add one item to the tree.
// @p_comparisonCols: for column i, if it is not null, use it for comparison.
QTreeWidgetItem *addItem(const QStringList &p_cols, const QStringList &p_comparisonCols);
private: private:
enum MoveOperation enum MoveOperation
{ {

View File

@ -1069,7 +1069,6 @@ void MarkdownEditor::handleHtmlToMarkdownData(quint64 p_id, TimeStamp p_timeStam
} }
} }
static QString purifyImageTitle(QString p_title) static QString purifyImageTitle(QString p_title)
{ {
return p_title.remove(QRegExp("[\\r\\n\\[\\]]")); return p_title.remove(QRegExp("[\\r\\n\\[\\]]"));

View File

@ -43,3 +43,8 @@ bool FramelessMainWindow::isMaximized() const
{ {
return (m_windowStates & Qt::WindowMaximized) && !(m_windowStates & Qt::WindowFullScreen); return (m_windowStates & Qt::WindowMaximized) && !(m_windowStates & Qt::WindowFullScreen);
} }
void FramelessMainWindow::setWindowFlagsOnUpdate()
{
// Do nothing by default.
}

View File

@ -28,6 +28,8 @@ namespace vnotex
protected: protected:
bool isMaximized() const; bool isMaximized() const;
virtual void setWindowFlagsOnUpdate();
const bool m_frameless = true; const bool m_frameless = true;
bool m_movable = true; bool m_movable = true;

View File

@ -3,7 +3,6 @@
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <QTimer> #include <QTimer>
#include <QDebug>
#include <QEvent> #include <QEvent>
#include <windows.h> #include <windows.h>
@ -221,4 +220,14 @@ void FramelessMainWindowWin::forceRedraw()
} }
} }
void FramelessMainWindowWin::setWindowFlagsOnUpdate()
{
if (m_frameless) {
// We need to re-set the window flags again in some cases, such as after StayOnTop.
HWND hwnd = reinterpret_cast<HWND>(winId());
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
}
}
#endif #endif

View File

@ -21,6 +21,8 @@ namespace vnotex
void moveEvent(QMoveEvent *p_event) Q_DECL_OVERRIDE; void moveEvent(QMoveEvent *p_event) Q_DECL_OVERRIDE;
void setWindowFlagsOnUpdate() Q_DECL_OVERRIDE;
private: private:
// To fix some unkonwn bugs of the interface. // To fix some unkonwn bugs of the interface.
void forceRedraw(); void forceRedraw();

View File

@ -595,6 +595,8 @@ void MainWindow::setStayOnTop(bool p_enabled)
setWindowFlags(flags ^ magicFlag); setWindowFlags(flags ^ magicFlag);
} }
setWindowFlagsOnUpdate();
if (shown) { if (shown) {
show(); show();
} }

View File

@ -1561,7 +1561,10 @@ void NotebookNodeExplorer::manualSort()
QStringList cols {child->getName(), QStringList cols {child->getName(),
Utils::dateTimeString(child->getCreatedTimeUtc().toLocalTime()), Utils::dateTimeString(child->getCreatedTimeUtc().toLocalTime()),
Utils::dateTimeString(child->getModifiedTimeUtc().toLocalTime())}; Utils::dateTimeString(child->getModifiedTimeUtc().toLocalTime())};
auto item = sortDlg.addItem(cols); QStringList comparisonCols {QString(),
Utils::dateTimeStringUniform(child->getCreatedTimeUtc().toLocalTime()),
Utils::dateTimeStringUniform(child->getModifiedTimeUtc().toLocalTime())};
auto item = sortDlg.addItem(cols, comparisonCols);
item->setData(0, Qt::UserRole, i); item->setData(0, Qt::UserRole, i);
} }
} }

View File

@ -16,14 +16,6 @@ namespace vnotex
class TreeWidget; class TreeWidget;
class SimpleSegmentHighlighter; class SimpleSegmentHighlighter;
enum
{
// Qt::UserRole = 0x0100
UserRole2 = 0x0101,
HighlightsRole = 0x0102
};
class StyledItemDelegateInterface class StyledItemDelegateInterface
{ {
public: public:

View File

@ -3,6 +3,8 @@
#include <QTreeWidget> #include <QTreeWidget>
#include <QVariant> #include <QVariant>
#include <core/global.h>
using namespace vnotex; using namespace vnotex;
TreeWidgetItem::TreeWidgetItem(QTreeWidget *p_parent, const QStringList &p_strings, int p_type) TreeWidgetItem::TreeWidgetItem(QTreeWidget *p_parent, const QStringList &p_strings, int p_type)
@ -13,8 +15,15 @@ TreeWidgetItem::TreeWidgetItem(QTreeWidget *p_parent, const QStringList &p_strin
bool TreeWidgetItem::operator<(const QTreeWidgetItem &p_other) const bool TreeWidgetItem::operator<(const QTreeWidgetItem &p_other) const
{ {
int column = treeWidget() ? treeWidget()->sortColumn() : 0; int column = treeWidget() ? treeWidget()->sortColumn() : 0;
const QVariant v1 = data(column, Qt::DisplayRole);
const QVariant v2 = p_other.data(column, Qt::DisplayRole); // Check ComparisonRole first.
QVariant v1 = data(column, Role::ComparisonRole);
QVariant v2 = p_other.data(column, Role::ComparisonRole);
if (v1.isNull() || v2.isNull()) {
v1 = data(column, Qt::DisplayRole);
v2 = p_other.data(column, Qt::DisplayRole);
}
if (v1.canConvert<QString>() && v2.canConvert<QString>()) { if (v1.canConvert<QString>() && v2.canConvert<QString>()) {
const auto s1 = v1.toString().toLower(); const auto s1 = v1.toString().toLower();
const auto s2 = v2.toString().toLower(); const auto s2 = v2.toString().toLower();