1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-11-24 08:12:24 +02:00

All: Also support $ as delimiter for Katex expressoins

This commit is contained in:
Laurent Cozic 2018-02-06 17:58:54 +00:00
parent d25d9b3f44
commit 727ba7300e
8 changed files with 85 additions and 32 deletions

View File

@ -2852,6 +2852,24 @@
"uc.micro": "1.0.3"
}
},
"markdown-it-katex": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/markdown-it-katex/-/markdown-it-katex-2.0.3.tgz",
"integrity": "sha1-17hqGuoLnWSW+rTnkZoY/e9YnDk=",
"requires": {
"katex": "0.6.0"
},
"dependencies": {
"katex": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.6.0.tgz",
"integrity": "sha1-EkGOCRIcBckgQbazuftrqyE8tvM=",
"requires": {
"match-at": "0.1.1"
}
}
}
},
"match-at": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/match-at/-/match-at-0.1.1.tgz",

View File

@ -70,6 +70,7 @@
"levenshtein": "^1.0.5",
"lodash": "^4.17.4",
"markdown-it": "^8.4.0",
"markdown-it-katex": "^2.0.3",
"md5": "^2.2.1",
"mime": "^2.0.3",
"moment": "^2.19.1",

View File

@ -150,19 +150,19 @@ Joplin uses and renders [Github-flavoured Markdown](https://github.com/adam-p/ma
## Math notation
Math expressions can be added using the [Katex notation](https://khan.github.io/KaTeX/). To add an inline equation, wrap the expression in `` `{.katex}EXPRESSION` ``, eg. `` `{.katex}\sqrt{3x-1}+(1+x)^2` ``. To create an expression block, wrap it as follow:
Math expressions can be added using the [Katex notation](https://khan.github.io/KaTeX/). To add an inline equation, wrap the expression in `$EXPRESSION$`, eg. `$\sqrt{3x-1}+(1+x)^2$`. To create an expression block, wrap it as follow:
```katex
$$
EXPRESSION
```
$$
For example:
```katex
$$
f(x) = \int_{-\infty}^\infty
\hat f(\xi)\,e^{2 \pi i \xi x}
\,d\xi
```
$$
Here is an example with the Markdown and rendered result side by side:

View File

@ -157,7 +157,7 @@ class MdToHtml {
}
}
customCodeHandler_(language) {
rendererPlugin_(language) {
if (!language) return null;
const handlers = {};
@ -196,9 +196,10 @@ class MdToHtml {
const isCodeBlock = tag === 'code' && t.block;
const isInlineCode = t.type === 'code_inline';
const codeBlockLanguage = t && t.info ? t.info : null;
let codeBlockHandler = null;
let rendererPlugin = null;
let rendererPluginOptions = { tagType: 'inline' };
if (isCodeBlock) codeBlockHandler = this.customCodeHandler_(codeBlockLanguage);
if (isCodeBlock) rendererPlugin = this.rendererPlugin_(codeBlockLanguage);
if (previousToken && previousToken.tag === 'li' && tag === 'p') {
// Markdown-it render list items as <li><p>Text<p></li> which makes it
@ -216,7 +217,7 @@ class MdToHtml {
} else if (t.type === 'link_open') {
openTag = 'a';
} else if (isCodeBlock) {
if (codeBlockHandler) {
if (rendererPlugin) {
openTag = null;
} else {
openTag = 'pre';
@ -235,25 +236,30 @@ class MdToHtml {
if (isCodeBlock) {
const codeAttrs = ['code'];
if (!codeBlockHandler) {
if (!rendererPlugin) {
if (codeBlockLanguage) codeAttrs.push(t.info); // t.info contains the language when the token is a codeblock
output.push('<code class="' + codeAttrs.join(' ') + '">');
}
} else if (isInlineCode) {
const result = this.parseInlineCodeLanguage_(tokenContent);
if (result) {
codeBlockHandler = this.customCodeHandler_(result.language);
rendererPlugin = this.rendererPlugin_(result.language);
tokenContent = result.newContent;
}
if (!codeBlockHandler) {
if (!rendererPlugin) {
output.push('<code>');
}
}
if (codeBlockHandler) {
codeBlockHandler.loadAssets().catch((error) => {
console.warn('MdToHtml: Error loading assets for ' + codeBlockHandler.name() + ': ', error.message);
if (t.type === 'math_inline' || t.type === 'math_block') {
rendererPlugin = this.rendererPlugin_('katex');
rendererPluginOptions = { tagType: t.type === 'math_block' ? 'block' : 'inline' };
}
if (rendererPlugin) {
rendererPlugin.loadAssets().catch((error) => {
console.warn('MdToHtml: Error loading assets for ' + rendererPlugin.name() + ': ', error.message);
});
}
@ -270,8 +276,10 @@ class MdToHtml {
output = output.concat(parsedChildren);
} else {
if (tokenContent) {
if ((isCodeBlock || isInlineCode) && codeBlockHandler) {
output = codeBlockHandler.processContent(output, tokenContent, isCodeBlock ? 'block' : 'inline');
if ((isCodeBlock || isInlineCode) && rendererPlugin) {
output = rendererPlugin.processContent(output, tokenContent, isCodeBlock ? 'block' : 'inline');
} else if (rendererPlugin) {
output = rendererPlugin.processContent(output, tokenContent, rendererPluginOptions.tagType);
} else {
output.push(htmlentities(tokenContent));
}
@ -286,15 +294,15 @@ class MdToHtml {
} else if (tag && t.type.indexOf('inline') >= 0) {
closeTag = openTag;
} else if (isCodeBlock) {
if (!codeBlockHandler) closeTag = openTag;
if (!rendererPlugin) closeTag = openTag;
}
if (isCodeBlock) {
if (!codeBlockHandler) {
if (!rendererPlugin) {
output.push('</code>');
}
} else if (isInlineCode) {
if (!codeBlockHandler) {
if (!rendererPlugin) {
output.push('</code>');
}
}
@ -307,9 +315,9 @@ class MdToHtml {
}
}
if (codeBlockHandler) {
const extraCss = codeBlockHandler.extraCss();
const name = codeBlockHandler.name();
if (rendererPlugin) {
const extraCss = rendererPlugin.extraCss();
const name = rendererPlugin.name();
if (extraCss && !(name in extraCssBlocks)) {
extraCssBlocks[name] = extraCss;
}
@ -345,6 +353,13 @@ class MdToHtml {
linkify: true,
});
// This is currently used only so that the $expression$ and $$\nexpression\n$$ blocks are translated
// to math_inline and math_block blocks. These blocks are then processed directly with the Katex
// library. It is better this way as then it is possible to conditionally load the CSS required by
// Katex and use an up-to-date version of Katex (as of 2018, the plugin is still using 0.6, which is
// buggy instead of 0.9).
md.use(require('markdown-it-katex'));
// Hack to make checkboxes clickable. Ideally, checkboxes should be parsed properly in
// renderTokens_(), but for now this hack works. Marking it with HORRIBLE_HACK so
// that it can be removed and replaced later on.

View File

@ -3666,6 +3666,24 @@
"uc.micro": "1.0.3"
}
},
"markdown-it-katex": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/markdown-it-katex/-/markdown-it-katex-2.0.3.tgz",
"integrity": "sha1-17hqGuoLnWSW+rTnkZoY/e9YnDk=",
"requires": {
"katex": "0.6.0"
},
"dependencies": {
"katex": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.6.0.tgz",
"integrity": "sha1-EkGOCRIcBckgQbazuftrqyE8tvM=",
"requires": {
"match-at": "0.1.1"
}
}
}
},
"match-at": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/match-at/-/match-at-0.1.1.tgz",

View File

@ -17,6 +17,7 @@
"html-entities": "^1.2.1",
"katex": "^0.9.0-beta1",
"markdown-it": "^8.4.0",
"markdown-it-katex": "^2.0.3",
"md5": "^2.2.1",
"moment": "^2.18.1",
"prop-types": "^15.6.0",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -331,16 +331,16 @@ sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin
<h1 id="markdown">Markdown</h1>
<p>Joplin uses and renders <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet">Github-flavoured Markdown</a> with a few variations and additions. In particular:</p>
<h2 id="math-notation">Math notation</h2>
<p>Math expressions can be added using the <a href="https://khan.github.io/KaTeX/">Katex notation</a>. To add an inline equation, wrap the expression in <code>`{.katex}EXPRESSION` </code>, eg. <code>`{.katex}\sqrt{3x-1}+(1+x)^2` </code>. To create an expression block, wrap it as follow:</p>
<pre><code>```katex
<p>Math expressions can be added using the <a href="https://khan.github.io/KaTeX/">Katex notation</a>. To add an inline equation, wrap the expression in <code>$EXPRESSION$</code>, eg. <code>$\sqrt{3x-1}+(1+x)^2$</code>. To create an expression block, wrap it as follow:</p>
<pre><code>$$
EXPRESSION
```
$$
</code></pre><p>For example:</p>
<pre><code>```katex
<pre><code>$$
f(x) = \int_{-\infty}^\infty
\hat f(\xi)\,e^{2 \pi i \xi x}
\,d\xi
```
$$
</code></pre><p>Here is an example with the Markdown and rendered result side by side:</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/Katex.png" style="max-width: 100%; max-height: 35em;"></p>
<h2 id="checkboxes">Checkboxes</h2>
@ -378,14 +378,14 @@ f(x) = \int_{-\infty}^\infty
<td><img src="https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/hr.png" alt=""></td>
<td>Croatian</td>
<td>hr_HR</td>
<td>Hrvoje Mandić <a href="&#109;&#97;&#x69;&#x6c;&#116;&#111;&#x3a;&#x74;&#114;&#98;&#117;&#104;&#x6f;&#x6d;&#x40;&#110;&#101;&#x74;&#46;&#104;&#114;">&#x74;&#114;&#98;&#117;&#104;&#x6f;&#x6d;&#x40;&#110;&#101;&#x74;&#46;&#104;&#114;</a></td>
<td>Hrvoje Mandić <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#x3a;&#116;&#114;&#98;&#117;&#x68;&#111;&#109;&#64;&#110;&#101;&#116;&#46;&#104;&#114;">&#116;&#114;&#98;&#117;&#x68;&#111;&#109;&#64;&#110;&#101;&#116;&#46;&#104;&#114;</a></td>
<td>72%</td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/de.png" alt=""></td>
<td>Deutsch</td>
<td>de_DE</td>
<td>Tobias Strobel <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#58;&#x67;&#x69;&#x74;&#64;&#x73;&#x74;&#x72;&#x6f;&#x62;&#x65;&#108;&#x74;&#111;&#98;&#x69;&#97;&#x73;&#x2e;&#x64;&#x65;">&#x67;&#x69;&#x74;&#64;&#x73;&#x74;&#x72;&#x6f;&#x62;&#x65;&#108;&#x74;&#111;&#98;&#x69;&#97;&#x73;&#x2e;&#x64;&#x65;</a></td>
<td>Tobias Strobel <a href="&#x6d;&#97;&#105;&#108;&#116;&#111;&#58;&#x67;&#x69;&#116;&#x40;&#115;&#x74;&#114;&#111;&#98;&#101;&#108;&#x74;&#111;&#98;&#x69;&#x61;&#x73;&#46;&#x64;&#x65;">&#x67;&#x69;&#116;&#x40;&#115;&#x74;&#114;&#111;&#98;&#101;&#108;&#x74;&#111;&#98;&#x69;&#x61;&#x73;&#46;&#x64;&#x65;</a></td>
<td>92%</td>
</tr>
<tr>
@ -441,14 +441,14 @@ f(x) = \int_{-\infty}^\infty
<td><img src="https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/ru.png" alt=""></td>
<td>Русский</td>
<td>ru_RU</td>
<td>Artyom Karlov <a href="&#x6d;&#97;&#105;&#x6c;&#116;&#x6f;&#58;&#x61;&#114;&#116;&#x79;&#111;&#109;&#46;&#107;&#x61;&#114;&#x6c;&#x6f;&#118;&#64;&#x67;&#109;&#x61;&#105;&#x6c;&#x2e;&#x63;&#x6f;&#x6d;">&#x61;&#114;&#116;&#x79;&#111;&#109;&#46;&#107;&#x61;&#114;&#x6c;&#x6f;&#118;&#64;&#x67;&#109;&#x61;&#105;&#x6c;&#x2e;&#x63;&#x6f;&#x6d;</a></td>
<td>Artyom Karlov <a href="&#x6d;&#x61;&#105;&#x6c;&#116;&#111;&#58;&#x61;&#114;&#x74;&#121;&#111;&#109;&#46;&#x6b;&#97;&#114;&#108;&#x6f;&#118;&#64;&#x67;&#109;&#x61;&#105;&#x6c;&#x2e;&#99;&#x6f;&#x6d;">&#x61;&#114;&#x74;&#121;&#111;&#109;&#46;&#x6b;&#97;&#114;&#108;&#x6f;&#118;&#64;&#x67;&#109;&#x61;&#105;&#x6c;&#x2e;&#99;&#x6f;&#x6d;</a></td>
<td>96%</td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/cn.png" alt=""></td>
<td>中文 (简体)</td>
<td>zh_CN</td>
<td>RCJacH <a href="&#x6d;&#97;&#x69;&#108;&#116;&#111;&#58;&#x52;&#67;&#x4a;&#97;&#x63;&#72;&#x40;&#x6f;&#x75;&#116;&#108;&#111;&#x6f;&#107;&#x2e;&#x63;&#111;&#109;">&#x52;&#67;&#x4a;&#97;&#x63;&#72;&#x40;&#x6f;&#x75;&#116;&#108;&#111;&#x6f;&#107;&#x2e;&#x63;&#111;&#109;</a></td>
<td>RCJacH <a href="&#x6d;&#x61;&#x69;&#108;&#x74;&#111;&#58;&#x52;&#x43;&#74;&#x61;&#99;&#x48;&#x40;&#x6f;&#117;&#x74;&#108;&#111;&#111;&#107;&#x2e;&#x63;&#x6f;&#109;">&#x52;&#x43;&#74;&#x61;&#99;&#x48;&#x40;&#x6f;&#117;&#x74;&#108;&#111;&#111;&#107;&#x2e;&#x63;&#x6f;&#109;</a></td>
<td>76%</td>
</tr>
<tr>