markdown-it: use markdown-it-texmath to get rid of escape of MathJax

This commit is contained in:
Le Tan 2018-07-05 20:41:16 +08:00
parent 027c8abd17
commit 35be1516ed
11 changed files with 250 additions and 5 deletions

View File

@ -199,6 +199,7 @@ In VNote, almost everything is configurable, such as background color, font, and
- [markdown-it-front-matter](https://github.com/craigdmckenna/markdown-it-front-matter) (MIT License)
- [markdown-it-imsize](https://github.com/tatsy/markdown-it-imsize) (Unknown) (Thanks @Kinka for help)
- [markdown-it-emoji](https://github.com/markdown-it/markdown-it-emoji) (MIT License)
- [markdown-it-texmath](https://github.com/goessner/markdown-it-texmath) (MIT License)
- [mermaid 7.0.0](https://github.com/knsv/mermaid) (MIT License)
- [MathJax](https://www.mathjax.org/) (Apache-2.0)
- [showdown](https://github.com/showdownjs/showdown) (Unknown)

View File

@ -200,6 +200,7 @@ VNote中几乎一切都是可以定制的例如背景颜色、字体以及
- [markdown-it-front-matter](https://github.com/craigdmckenna/markdown-it-front-matter) (MIT License)
- [markdown-it-imsize](https://github.com/tatsy/markdown-it-imsize) (Unknown) (Thanks @Kinka for help)
- [markdown-it-emoji](https://github.com/markdown-it/markdown-it-emoji) (MIT License)
- [markdown-it-texmath](https://github.com/goessner/markdown-it-texmath) (MIT License)
- [mermaid 7.0.0](https://github.com/knsv/mermaid) (MIT License)
- [MathJax](https://www.mathjax.org/) (Apache-2.0)
- [showdown](https://github.com/showdownjs/showdown) (Unknown)

View File

@ -108,6 +108,8 @@ mdit = mdit.use(window.markdownitFootnote);
mdit = mdit.use(window["markdown-it-imsize.js"]);
mdit = mdit.use(texmath, { delimiters: 'dollars' });
var mdHasTocSection = function(markdown) {
var n = markdown.search(/(\n|^)\[toc\]/i);
return n != -1;
@ -150,8 +152,20 @@ var updateText = function(text) {
// If you add new logics after handling MathJax, please pay attention to
// finishLoading logic.
if (VEnableMathjax) {
var texToRender = document.getElementsByClassName('tex-to-render');
var nrTex = texToRender.length;
if (nrTex == 0) {
finishOneAsyncJob();
return;
}
var eles = [];
for (var i = 0; i < nrTex; ++i) {
eles.push(texToRender[i]);
}
try {
MathJax.Hub.Queue(["Typeset", MathJax.Hub, contentDiv, postProcessMathJax]);
MathJax.Hub.Queue(["Typeset", MathJax.Hub, eles, postProcessMathJax]);
} catch (err) {
content.setLog("err: " + err);
finishOneAsyncJob();
@ -196,3 +210,49 @@ var handleMetaData = function() {
pre.appendChild(code);
contentDiv.insertAdjacentElement('afterbegin', pre);
};
var postProcessMathJaxWhenMathjaxReady = function() {
var all = MathJax.Hub.getAllJax();
for (var i = 0; i < all.length; ++i) {
var node = all[i].SourceElement().parentNode;
if (VRemoveMathjaxScript) {
// Remove the SourceElement.
try {
node.removeChild(all[i].SourceElement());
} catch (err) {
content.setLog("err: " + err);
}
}
if (node.tagName.toLowerCase() == 'code') {
var pre = node.parentNode;
var p = document.createElement('p');
p.innerHTML = node.innerHTML;
pre.parentNode.replaceChild(p, pre);
}
}
};
var handleMathjaxReady = function() {
if (!VEnableMathjax) {
return;
}
var texToRender = document.getElementsByClassName('tex-to-render');
var nrTex = texToRender.length;
if (nrTex == 0) {
return;
}
var eles = [];
for (var i = 0; i < nrTex; ++i) {
eles.push(texToRender[i]);
}
try {
MathJax.Hub.Queue(["Typeset", MathJax.Hub, eles, postProcessMathJaxWhenMathjaxReady]);
} catch (err) {
content.setLog("err: " + err);
finishOneAsyncJob();
}
};

View File

@ -92,6 +92,10 @@ if (typeof VOS == 'undefined') {
VOS = 'win';
}
if (typeof handleMathjaxReady == 'undefined') {
var handleMathjaxReady = function() {};
}
// Whether highlight special blocks like puml, flowchart.
var highlightSpecialBlocks = false;
@ -1181,6 +1185,7 @@ var addClassToCodeBlock = function() {
// Add the class to pre.
pare.classList.add("lang-mathjax");
pare.classList.add("language-mathjax");
pare.classList.add("tex-to-render");
}
}
}
@ -1268,7 +1273,11 @@ var postProcessMathJax = function() {
var node = all[i].SourceElement().parentNode;
if (VRemoveMathjaxScript) {
// Remove the SourceElement.
node.removeChild(all[i].SourceElement());
try {
node.removeChild(all[i].SourceElement());
} catch (err) {
content.setLog("err: " + err);
}
}
if (node.tagName.toLowerCase() == 'code') {

View File

@ -43,6 +43,11 @@ var previewMathJax = function(identifier, id, timeStamp, text, isHtml) {
p = htmlToElement(text);
if (isEmptyMathJax(p.textContent)) {
p = null;
} else if (p.tagName.toLowerCase() != 'p') {
// Need to wrap it in a <p>, or domtoimage won't work.
var tp = document.createElement('p');
tp.appendChild(p);
p = tp;
}
} else {
p = document.createElement('p');

View File

@ -35,3 +35,7 @@ Tatsuya Yatagawa
# [markdown-it-emoji](https://github.com/markdown-it/markdown-it-emoji)
v1.4.0
Vitaly Puzrin
# [markdown-it-texmath](https://github.com/goessner/markdown-it-texmath)
v0.0.0
Stefan Goessner

View File

@ -0,0 +1,155 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Stefan Goessner - 2017-18. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* Modified by Le Tan for MathJax support in VNote.
* We mark all the formulas and enclose them with $ in class 'tex-to-render' for
* further processing by MathJax.
*--------------------------------------------------------------------------------------------*/
'use strict';
function texmath(md, options) {
let delimiters = options && options.delimiters || 'dollars';
if (delimiters in texmath.rules) {
for (let rule of texmath.rules[delimiters].inline) {
md.inline.ruler.before('escape', rule.name, texmath.inline(rule)); // ! important
md.renderer.rules[rule.name] = (tokens, idx) => rule.tmpl.replace(/\$1/,texmath.render(tokens[idx].content,false));
}
for (let rule of texmath.rules[delimiters].block) {
md.block.ruler.before('fence', rule.name, texmath.block(rule));
md.renderer.rules[rule.name] = (tokens, idx) => rule.tmpl.replace(/\$1/,texmath.render(tokens[idx].content,true));
}
}
}
texmath.applyRule = function(rule, str, beg) {
let pre, match, post;
rule.rex.lastIndex = beg;
pre = str.startsWith(rule.tag,beg) && (!rule.pre || rule.pre(str,beg));
match = pre && rule.rex.exec(str);
if (match) {
match.lastIndex = rule.rex.lastIndex;
post = !rule.post || rule.post(str, match.lastIndex-1);
}
rule.rex.lastIndex = 0;
return post && match;
}
texmath.inline = (rule) =>
function(state, silent) {
let res = texmath.applyRule(rule, state.src, state.pos);
if (res) {
if (!silent) {
let token = state.push(rule.name, 'math', 0);
token.content = res[1]; // group 1 from regex ..
token.markup = rule.tag;
}
state.pos = res.lastIndex;
}
return !!res;
}
texmath.block = (rule) =>
function(state, begLine, endLine, silent) {
let res = texmath.applyRule(rule, state.src, state.bMarks[begLine] + state.tShift[begLine]);
if (res) {
if (!silent) {
let token = state.push(rule.name, 'math', 0);
token.block = true;
token.content = res[1];
token.markup = rule.tag;
}
for (let line=begLine, endpos=res.lastIndex-1; line < endLine; line++)
if (endpos >= state.bMarks[line] && endpos <= state.eMarks[line]) { // line for end of block math found ...
state.line = line+1;
break;
}
state.pos = res.lastIndex;
}
return !!res;
}
texmath.render = function(tex, isblock) {
let res;
if (isblock) {
res = '$$$$' + tex + '$$$$';
} else {
res = '$$' + tex + '$$';
}
return res;
}
texmath.$_pre = (str,beg) => {
let prv = beg > 0 ? str[beg-1].charCodeAt(0) : false;
return !prv || prv !== 0x5c // no backslash,
&& (prv < 0x30 || prv > 0x39); // no decimal digit .. before opening '$'
}
texmath.$_post = (str,end) => {
let nxt = str[end+1] && str[end+1].charCodeAt(0);
return !nxt || nxt < 0x30 || nxt > 0x39; // no decimal digit .. after closing '$'
}
texmath.rules = {
brackets: {
inline: [
{ name: 'math_inline',
rex: /\\\((.+?)\\\)/gy,
tmpl: '<x-eq class="tex-to-render">$1</x-eq>',
tag: '\\('
}
],
block: [
{ name: 'math_block',
rex: /\\\[(.+?)\\\]/gmy,
tmpl: '<x-eqn class="tex-to-render">$1</x-eqn>',
tag: '\\['
}
]
},
gitlab: {
inline: [
{ name: 'math_inline',
rex: /\$`(.+?)`\$/gy,
tmpl: '<x-eq class="tex-to-render">$1</x-eq>',
tag: '$`'
}
],
block: [
{ name: 'math_block',
rex: /`{3}math\s+?([^`]+?)\s+?`{3}/gmy,
tmpl: '<x-eqn class="tex-to-render">$1</x-eqn>',
tag: '```math'
}
]
},
dollars: {
inline: [
{ name: 'math_inline',
rex: /\$(\S[^$\r\n]*?[^\s\\]{1}?)\$/gy,
tmpl: '<x-eq class="tex-to-render">$1</x-eq>',
tag: '$',
pre: texmath.$_pre,
post: texmath.$_post
},
{ name: 'math_single',
rex: /\$([^$\s\\]{1}?)\$/gy,
tmpl: '<x-eq class="tex-to-render">$1</x-eq>',
tag: '$',
pre: texmath.$_pre,
post: texmath.$_post
}
],
block: [
{ name: 'math_block',
rex: /\${2}([^$]*?)\${2}/gmy,
tmpl: '<x-eqn class="tex-to-render">$1</x-eqn>',
tag: '$$'
}
]
},
};
if (typeof module === "object" && module.exports)
module.exports = texmath;

View File

@ -639,6 +639,8 @@ QString VUtils::generateHtmlTemplate(const QString &p_template,
bool p_wkhtmltopdf,
bool p_addToc)
{
bool mathjaxTypeSetOnLoad = true;
QString jsFile, extraFile;
switch (p_conType) {
case MarkdownConverterType::Marked:
@ -659,7 +661,8 @@ QString VUtils::generateHtmlTemplate(const QString &p_template,
"<script src=\"qrc" + VNote::c_markdownitAnchorExtraFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_markdownitTaskListExtraFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_markdownitImsizeExtraFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_markdownitFootnoteExtraFile + "\"></script>\n";
"<script src=\"qrc" + VNote::c_markdownitFootnoteExtraFile + "\"></script>\n" +
"<script src=\"qrc" + VNote::c_markdownitTexMathExtraFile + "\"></script>\n";
const MarkdownitOption &opt = g_config->getMarkdownitOption();
@ -696,6 +699,8 @@ QString VUtils::generateHtmlTemplate(const QString &p_template,
.arg(opt.m_metadata ? QStringLiteral("true") : QStringLiteral("false"))
.arg(opt.m_emoji ? QStringLiteral("true") : QStringLiteral("false"));
extraFile += optJs;
mathjaxTypeSetOnLoad = false;
break;
}
@ -734,10 +739,12 @@ QString VUtils::generateHtmlTemplate(const QString &p_template,
extraFile += "<script type=\"text/x-mathjax-config\">"
"MathJax.Hub.Config({\n"
" tex2jax: {inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n"
"processEscapes: true,\n"
"processClass: \"tex2jax_process|language-mathjax|lang-mathjax\"},\n"
"processEscapes: true,\n"
"processClass: \"tex2jax_process|language-mathjax|lang-mathjax\"},\n"
" showProcessingMessages: false,\n"
" skipStartupTypeset: " + QString("%1,\n").arg(mathjaxTypeSetOnLoad ? "false" : "true") +
" messageStyle: \"none\"});\n"
"MathJax.Hub.Register.StartupHook(\"End\", function() { handleMathjaxReady(); });\n"
"</script>\n"
"<script type=\"text/javascript\" async src=\"" + mj + "\"></script>\n" +
"<script>var VEnableMathjax = true;</script>\n";

View File

@ -42,6 +42,7 @@ const QString VNote::c_markdownitFootnoteExtraFile = ":/utils/markdown-it/markdo
const QString VNote::c_markdownitFrontMatterExtraFile = ":/utils/markdown-it/markdown-it-front-matter.js";
const QString VNote::c_markdownitImsizeExtraFile = ":/utils/markdown-it/markdown-it-imsize.min.js";
const QString VNote::c_markdownitEmojiExtraFile = ":/utils/markdown-it/markdown-it-emoji.min.js";
const QString VNote::c_markdownitTexMathExtraFile = ":/utils/markdown-it/markdown-it-texmath.js";
const QString VNote::c_showdownJsFile = ":/resources/showdown.js";
const QString VNote::c_showdownExtraFile = ":/utils/showdown/showdown.min.js";

View File

@ -53,6 +53,7 @@ public:
static const QString c_markdownitFrontMatterExtraFile;
static const QString c_markdownitImsizeExtraFile;
static const QString c_markdownitEmojiExtraFile;
static const QString c_markdownitTexMathExtraFile;
// Showdown
static const QString c_showdownJsFile;

View File

@ -265,5 +265,6 @@
<file>resources/view_image.css</file>
<file>resources/icons/decrease_outline_level.svg</file>
<file>resources/icons/increase_outline_level.svg</file>
<file>utils/markdown-it/markdown-it-texmath.js</file>
</qresource>
</RCC>