summaryrefslogtreecommitdiffstats
path: root/mdit_py_plugins/texmath
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mdit_py_plugins/texmath/LICENSE21
-rw-r--r--mdit_py_plugins/texmath/README.md137
-rw-r--r--mdit_py_plugins/texmath/__init__.py1
-rw-r--r--mdit_py_plugins/texmath/index.py307
-rw-r--r--mdit_py_plugins/texmath/port.yaml7
5 files changed, 473 insertions, 0 deletions
diff --git a/mdit_py_plugins/texmath/LICENSE b/mdit_py_plugins/texmath/LICENSE
new file mode 100644
index 0000000..b88387c
--- /dev/null
+++ b/mdit_py_plugins/texmath/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2013-17 Stefan Goessner
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/mdit_py_plugins/texmath/README.md b/mdit_py_plugins/texmath/README.md
new file mode 100644
index 0000000..f79f335
--- /dev/null
+++ b/mdit_py_plugins/texmath/README.md
@@ -0,0 +1,137 @@
+[![License](https://img.shields.io/github/license/goessner/markdown-it-texmath.svg)](https://github.com/goessner/markdown-it-texmath/blob/master/licence.txt)
+[![npm](https://img.shields.io/npm/v/markdown-it-texmath.svg)](https://www.npmjs.com/package/markdown-it-texmath)
+[![npm](https://img.shields.io/npm/dt/markdown-it-texmath.svg)](https://www.npmjs.com/package/markdown-it-texmath)
+
+# markdown-it-texmath
+
+Add TeX math equations to your Markdown documents rendered by [markdown-it](https://github.com/markdown-it/markdown-it) parser. [KaTeX](https://github.com/Khan/KaTeX) is used as a fast math renderer.
+
+## Features
+Simplify the process of authoring markdown documents containing math formulas.
+This extension is a comfortable tool for scientists, engineers and students with markdown as their first choice document format.
+
+* Macro support
+* Simple formula numbering
+* Inline math with tables, lists and blockquote.
+* User setting delimiters:
+ * `'dollars'` (default)
+ * inline: `$...$`
+ * display: `$$...$$`
+ * display + equation number: `$$...$$ (1)`
+ * `'brackets'`
+ * inline: `\(...\)`
+ * display: `\[...\]`
+ * display + equation number: `\[...\] (1)`
+ * `'gitlab'`
+ * inline: ``$`...`$``
+ * display: `` ```math ... ``` ``
+ * display + equation number: `` ```math ... ``` (1)``
+ * `'julia'`
+ * inline: `$...$` or ``` ``...`` ```
+ * display: `` ```math ... ``` ``
+ * display + equation number: `` ```math ... ``` (1)``
+ * `'kramdown'`
+ * inline: ``$$...$$``
+ * display: `$$...$$`
+ * display + equation number: `$$...$$ (1)`
+
+## Show me
+
+View a [test table](https://goessner.github.io/markdown-it-texmath/index.html).
+
+[try it out ...](https://goessner.github.io/markdown-it-texmath/markdown-it-texmath-demo.html)
+
+## Use with `node.js`
+
+Install the extension. Verify having `markdown-it` and `katex` already installed .
+```
+npm install markdown-it-texmath
+```
+Use it with JavaScript.
+```js
+let kt = require('katex'),
+ tm = require('markdown-it-texmath').use(kt),
+ md = require('markdown-it')().use(tm,{delimiters:'dollars',macros:{"\\RR": "\\mathbb{R}"}});
+
+md.render('Euler\'s identity \(e^{i\pi}+1=0\) is a beautiful formula in $\\RR 2$.')
+```
+
+## Use in Browser
+```html
+<html>
+<head>
+ <meta charset='utf-8'>
+ <link rel="stylesheet" href="katex.min.css">
+ <link rel="stylesheet" href="texmath.css">
+ <script src="markdown-it.min.js"></script>
+ <script src="katex.min.js"></script>
+ <script src="texmath.js"></script>
+</head>
+<body>
+ <div id="out"></div>
+ <script>
+ let md;
+ document.addEventListener("DOMContentLoaded", () => {
+ const tm = texmath.use(katex);
+ md = markdownit().use(tm,{delimiters:'dollars',macros:{"\\RR": "\\mathbb{R}"}});
+ out.innerHTML = md.render('Euler\'s identity $e^{i\pi}+1=0$ is a beautiful formula in //RR 2.');
+ })
+ </script>
+</body>
+</html>
+```
+## CDN
+
+Use following links for `texmath.js` and `texmath.css`
+* `https://gitcdn.xyz/cdn/goessner/markdown-it-texmath/master/texmath.js`
+* `https://gitcdn.xyz/cdn/goessner/markdown-it-texmath/master/texmath.css`
+
+## Dependencies
+
+* [`markdown-it`](https://github.com/markdown-it/markdown-it): Markdown parser done right. Fast and easy to extend.
+* [`katex`](https://github.com/Khan/KaTeX): This is where credits for fast rendering TeX math in HTML go to.
+
+## ToDo
+
+ nothing yet
+
+## FAQ
+
+* __`markdown-it-texmath` with React Native does not work, why ?__
+ * `markdown-it-texmath` is using regular expressions with `y` [(sticky) property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky) and cannot avoid this. The use of the `y` flag in regular expressions means the plugin is not compatible with React Native (which as of now doesn't support it and throws an error `Invalid flags supplied to RegExp constructor`).
+
+## CHANGELOG
+
+### [0.6.0] on October 04, 2019
+* Add support for [Julia Markdown](https://docs.julialang.org/en/v1/stdlib/Markdown/) on [request](https://github.com/goessner/markdown-it-texmath/issues/15).
+
+### [0.5.5] on February 07, 2019
+* Remove [rendering bug with brackets delimiters](https://github.com/goessner/markdown-it-texmath/issues/9).
+
+### [0.5.4] on January 20, 2019
+* Remove pathological [bug within blockquotes](https://github.com/goessner/mdmath/issues/50).
+
+### [0.5.3] on November 11, 2018
+* Add support for Tex macros (https://katex.org/docs/supported.html#macros) .
+* Bug with [brackets delimiters](https://github.com/goessner/markdown-it-texmath/issues/9) .
+
+### [0.5.2] on September 07, 2018
+* Add support for [Kramdown](https://kramdown.gettalong.org/) .
+
+### [0.5.0] on August 15, 2018
+* Fatal blockquote bug investigated. Implemented workaround to vscode bug, which has finally gone with vscode 1.26.0 .
+
+### [0.4.6] on January 05, 2018
+* Escaped underscore bug removed.
+
+### [0.4.5] on November 06, 2017
+* Backslash bug removed.
+
+### [0.4.4] on September 27, 2017
+* Modifying the `block` mode regular expression with `gitlab` delimiters, so removing the `newline` bug.
+
+## License
+
+`markdown-it-texmath` is licensed under the [MIT License](./license.txt)
+
+ © [Stefan Gössner](https://github.com/goessner)
diff --git a/mdit_py_plugins/texmath/__init__.py b/mdit_py_plugins/texmath/__init__.py
new file mode 100644
index 0000000..f0c2588
--- /dev/null
+++ b/mdit_py_plugins/texmath/__init__.py
@@ -0,0 +1 @@
+from .index import texmath_plugin # noqa F401
diff --git a/mdit_py_plugins/texmath/index.py b/mdit_py_plugins/texmath/index.py
new file mode 100644
index 0000000..ecf178c
--- /dev/null
+++ b/mdit_py_plugins/texmath/index.py
@@ -0,0 +1,307 @@
+import re
+from typing import Optional
+
+from markdown_it import MarkdownIt
+from markdown_it.common.utils import charCodeAt
+
+
+def texmath_plugin(md: MarkdownIt, delimiters="dollars", macros: Optional[dict] = None):
+ """Plugin ported from
+ `markdown-it-texmath <https://github.com/goessner/markdown-it-texmath>`__.
+
+ It parses TeX math equations set inside opening and closing delimiters:
+
+ .. code-block:: md
+
+ $\\alpha = \\frac{1}{2}$
+
+ :param delimiters: one of: brackets, dollars, gitlab, julia, kramdown
+
+ """
+ macros = macros or {}
+
+ if delimiters in rules:
+ for rule_inline in rules[delimiters]["inline"]:
+ md.inline.ruler.before(
+ "escape", rule_inline["name"], make_inline_func(rule_inline)
+ )
+
+ def render_math_inline(self, tokens, idx, options, env):
+ return rule_inline["tmpl"].format(
+ render(tokens[idx].content, False, macros)
+ )
+
+ md.add_render_rule(rule_inline["name"], render_math_inline)
+
+ for rule_block in rules[delimiters]["block"]:
+ md.block.ruler.before(
+ "fence", rule_block["name"], make_block_func(rule_block)
+ )
+
+ def render_math_block(self, tokens, idx, options, env):
+ return rule_block["tmpl"].format(
+ render(tokens[idx].content, True, macros), tokens[idx].info
+ )
+
+ md.add_render_rule(rule_block["name"], render_math_block)
+
+
+def applyRule(rule, string: str, begin, inBlockquote):
+
+ if not (
+ string.startswith(rule["tag"], begin)
+ and (rule["pre"](string, begin) if "pre" in rule else True)
+ ):
+ return False
+
+ match = rule["rex"].match(string[begin:]) # type: re.Match
+
+ if not match or match.start() != 0:
+ return False
+
+ lastIndex = match.end() + begin - 1
+ if "post" in rule:
+ if not (
+ rule["post"](string, lastIndex) # valid post-condition
+ # remove evil blockquote bug (https:#github.com/goessner/mdmath/issues/50)
+ and (not inBlockquote or "\n" not in match.group(1))
+ ):
+ return False
+ return match
+
+
+def make_inline_func(rule):
+ def _func(state, silent):
+ res = applyRule(rule, state.src, state.pos, False)
+ if res:
+ if not silent:
+ token = state.push(rule["name"], "math", 0)
+ token.content = res[1] # group 1 from regex ..
+ token.markup = rule["tag"]
+
+ state.pos += res.end()
+
+ return bool(res)
+
+ return _func
+
+
+def make_block_func(rule):
+ def _func(state, begLine, endLine, silent):
+ begin = state.bMarks[begLine] + state.tShift[begLine]
+ res = applyRule(rule, state.src, begin, state.parentType == "blockquote")
+ if res:
+ if not silent:
+ token = state.push(rule["name"], "math", 0)
+ token.block = True
+ token.content = res[1]
+ token.info = res[len(res.groups())]
+ token.markup = rule["tag"]
+
+ line = begLine
+ endpos = begin + res.end() - 1
+
+ while line < endLine:
+ if endpos >= state.bMarks[line] and endpos <= state.eMarks[line]:
+ # line for end of block math found ...
+ state.line = line + 1
+ break
+ line += 1
+
+ state.pos = begin + res.end()
+
+ return bool(res)
+
+ return _func
+
+
+def dollar_pre(str, beg):
+ prv = charCodeAt(str[beg - 1], 0) if beg > 0 else False
+ return (
+ (not prv) or prv != 0x5C and (prv < 0x30 or prv > 0x39) # no backslash,
+ ) # no decimal digit .. before opening '$'
+
+
+def dollar_post(string, end):
+ try:
+ nxt = string[end + 1] and charCodeAt(string[end + 1], 0)
+ except IndexError:
+ return True
+ return (
+ (not nxt) or (nxt < 0x30) or (nxt > 0x39)
+ ) # no decimal digit .. after closing '$'
+
+
+def render(tex, displayMode, macros):
+ return tex
+ # TODO better HTML renderer port for math
+ # try:
+ # res = katex.renderToString(tex,{throwOnError:False,displayMode,macros})
+ # except:
+ # res = tex+": "+err.message.replace("<","&lt;")
+ # return res
+
+
+# def use(katex): # math renderer used ...
+# texmath.katex = katex; # ... katex solely at current ...
+# return texmath;
+# }
+
+
+# All regexes areg global (g) and sticky (y), see:
+# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky
+
+rules: dict = {
+ "brackets": {
+ "inline": [
+ {
+ "name": "math_inline",
+ "rex": re.compile(r"^\\\((.+?)\\\)", re.DOTALL),
+ "tmpl": "<eq>{0}</eq>",
+ "tag": "\\(",
+ }
+ ],
+ "block": [
+ {
+ "name": "math_block_eqno",
+ "rex": re.compile(
+ r"^\\\[(((?!\\\]|\\\[)[\s\S])+?)\\\]\s*?\(([^)$\r\n]+?)\)", re.M
+ ),
+ "tmpl": '<section class="eqno"><eqn>{0}</eqn><span>({1})</span></section>',
+ "tag": "\\[",
+ },
+ {
+ "name": "math_block",
+ "rex": re.compile(r"^\\\[([\s\S]+?)\\\]", re.M),
+ "tmpl": "<section>\n<eqn>{0}</eqn>\n</section>\n",
+ "tag": "\\[",
+ },
+ ],
+ },
+ "gitlab": {
+ "inline": [
+ {
+ "name": "math_inline",
+ "rex": re.compile(r"^\$`(.+?)`\$"),
+ "tmpl": "<eq>{0}</eq>",
+ "tag": "$`",
+ }
+ ],
+ "block": [
+ {
+ "name": "math_block_eqno",
+ "rex": re.compile(
+ r"^`{3}math\s+?([^`]+?)\s+?`{3}\s*?\(([^)$\r\n]+?)\)", re.M
+ ),
+ "tmpl": '<section class="eqno">\n<eqn>{0}</eqn><span>({1})</span>\n</section>\n', # noqa: E501
+ "tag": "```math",
+ },
+ {
+ "name": "math_block",
+ "rex": re.compile(r"^`{3}math\s+?([^`]+?)\s+?`{3}", re.M),
+ "tmpl": "<section>\n<eqn>{0}</eqn>\n</section>\n",
+ "tag": "```math",
+ },
+ ],
+ },
+ "julia": {
+ "inline": [
+ {
+ "name": "math_inline",
+ "rex": re.compile(r"^`{2}([^`]+?)`{2}"),
+ "tmpl": "<eq>{0}</eq>",
+ "tag": "``",
+ },
+ {
+ "name": "math_inline",
+ "rex": re.compile(r"^\$(\S[^$\r\n]*?[^\s\\]{1}?)\$"),
+ "tmpl": "<eq>{0}</eq>",
+ "tag": "$",
+ "pre": dollar_pre,
+ "post": dollar_post,
+ },
+ {
+ "name": "math_single",
+ "rex": re.compile(r"^\$([^$\s\\]{1}?)\$"),
+ "tmpl": "<eq>{0}</eq>",
+ "tag": "$",
+ "pre": dollar_pre,
+ "post": dollar_post,
+ },
+ ],
+ "block": [
+ {
+ "name": "math_block_eqno",
+ "rex": re.compile(
+ r"^`{3}math\s+?([^`]+?)\s+?`{3}\s*?\(([^)$\r\n]+?)\)", re.M
+ ),
+ "tmpl": '<section class="eqno"><eqn>{0}</eqn><span>({1})</span></section>',
+ "tag": "```math",
+ },
+ {
+ "name": "math_block",
+ "rex": re.compile(r"^`{3}math\s+?([^`]+?)\s+?`{3}", re.M),
+ "tmpl": "<section><eqn>{0}</eqn></section>",
+ "tag": "```math",
+ },
+ ],
+ },
+ "kramdown": {
+ "inline": [
+ {
+ "name": "math_inline",
+ "rex": re.compile(r"^\${2}([^$\r\n]*?)\${2}"),
+ "tmpl": "<eq>{0}</eq>",
+ "tag": "$$",
+ }
+ ],
+ "block": [
+ {
+ "name": "math_block_eqno",
+ "rex": re.compile(r"^\${2}([^$]*?)\${2}\s*?\(([^)$\r\n]+?)\)", re.M),
+ "tmpl": '<section class="eqno"><eqn>{0}</eqn><span>({1})</span></section>',
+ "tag": "$$",
+ },
+ {
+ "name": "math_block",
+ "rex": re.compile(r"^\${2}([^$]*?)\${2}", re.M),
+ "tmpl": "<section><eqn>{0}</eqn></section>",
+ "tag": "$$",
+ },
+ ],
+ },
+ "dollars": {
+ "inline": [
+ {
+ "name": "math_inline",
+ "rex": re.compile(r"^\$(\S[^$]*?[^\s\\]{1}?)\$"),
+ "tmpl": "<eq>{0}</eq>",
+ "tag": "$",
+ "pre": dollar_pre,
+ "post": dollar_post,
+ },
+ {
+ "name": "math_single",
+ "rex": re.compile(r"^\$([^$\s\\]{1}?)\$"),
+ "tmpl": "<eq>{0}</eq>",
+ "tag": "$",
+ "pre": dollar_pre,
+ "post": dollar_post,
+ },
+ ],
+ "block": [
+ {
+ "name": "math_block_eqno",
+ "rex": re.compile(r"^\${2}([^$]*?)\${2}\s*?\(([^)$\r\n]+?)\)", re.M),
+ "tmpl": '<section class="eqno">\n<eqn>{0}</eqn><span>({1})</span>\n</section>\n', # noqa: E501
+ "tag": "$$",
+ },
+ {
+ "name": "math_block",
+ "rex": re.compile(r"^\${2}([^$]*?)\${2}", re.M),
+ "tmpl": "<section>\n<eqn>{0}</eqn>\n</section>\n",
+ "tag": "$$",
+ },
+ ],
+ },
+}
diff --git a/mdit_py_plugins/texmath/port.yaml b/mdit_py_plugins/texmath/port.yaml
new file mode 100644
index 0000000..ba47ac8
--- /dev/null
+++ b/mdit_py_plugins/texmath/port.yaml
@@ -0,0 +1,7 @@
+- package: markdown-it-texmath
+ commit: 78c548829ce2ef85c73dc71e680d01e5ae41ffbf
+ date: Oct 4, 2019
+ version: 0.6
+ changes: |
+ both dollars/math_inline and brackets/math_inline regexes have been changed,
+ to allow (single) line breaks