Skip to content

Commit

Permalink
Merge pull request #573 from navanchauhan/latex-extra
Browse files Browse the repository at this point in the history
Add new LaTeX Extra
  • Loading branch information
nicholasserra authored Apr 7, 2024
2 parents 4722442 + d171ac9 commit f017595
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 2 deletions.
50 changes: 50 additions & 0 deletions lib/markdown2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2764,6 +2764,55 @@ def sub(self, match):
def run(self, text):
return self.fenced_code_block_re.sub(self.sub, text)

class Latex(Extra):
'''
Convert $ and $$ to <math> and </math> tags for inline and block math.
'''
name = 'latex'
order = (Stage.CODE_BLOCKS, FencedCodeBlocks), ()

_single_dollar_re = re.compile(r'(?<!\$)\$(?!\$)(.*?)\$')
_double_dollar_re = re.compile(r'\$\$(.*?)\$\$', re.DOTALL)

# Ways to escape
_pre_code_block_re = re.compile(r"<pre>(.*?)</pre>", re.DOTALL) # Wraped in <pre>
_triple_re = re.compile(r'```(.*?)```', re.DOTALL) # Wrapped in a code block ```
_single_re = re.compile(r'(?<!`)(`)(.*?)(?<!`)\1(?!`)') # Wrapped in a single `

converter = None
code_blocks = {}

def _convert_single_match(self, match):
return self.converter.convert(match.group(1))

def _convert_double_match(self, match):
return self.converter.convert(match.group(1).replace(r"\n", ''), display="block")

def code_placeholder(self, match):
placeholder = f"<!--CODE_BLOCK_{len(self.code_blocks)}-->"
self.code_blocks[placeholder] = match.group(0)
return placeholder

def run(self, text):
try:
import latex2mathml.converter
self.converter = latex2mathml.converter
except ImportError:
raise ImportError('The "latex" extra requires the "latex2mathml" package to be installed.')

# Escape by replacing with a code block
text = self._pre_code_block_re.sub(self.code_placeholder, text)
text = self._single_re.sub(self.code_placeholder, text)
text = self._triple_re.sub(self.code_placeholder, text)

text = self._single_dollar_re.sub(self._convert_single_match, text)
text = self._double_dollar_re.sub(self._convert_double_match, text)

# Convert placeholder tag back to original code
for placeholder, code_block in self.code_blocks.items():
text = text.replace(placeholder, code_block)

return text

class LinkPatterns(Extra):
'''
Expand Down Expand Up @@ -3328,6 +3377,7 @@ def test(self, text):
Breaks.register()
CodeFriendly.register()
FencedCodeBlocks.register()
Latex.register()
LinkPatterns.register()
MarkdownInHTML.register()
MiddleWordEm.register()
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@

extras_require = {
"code_syntax_highlighting": ["pygments>=2.7.3"],
"wavedrom": ["wavedrom; python_version>='3.7'"]
"wavedrom": ["wavedrom; python_version>='3.7'"],
"latex": ['latex2mathml; python_version>="3.8.1"'],
}
# nested listcomp to combine all optional extras into convenient "all" option
extras_require["all"] = [i for v in tuple(extras_require.values()) for i in v]
Expand Down
2 changes: 1 addition & 1 deletion test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def setup():
setup()
default_tags = []
warnings = []
for extra_lib in ('pygments', 'wavedrom'):
for extra_lib in ('pygments', 'wavedrom', 'latex2mathml'):
try:
mod = importlib.import_module(extra_lib)
except ImportError:
Expand Down
18 changes: 18 additions & 0 deletions test/tm-cases/latex.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<h2>Simple Test</h2>

<p>Inline Equations can be written as <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mrow><mi>y</mi><mo>&#x0003D;</mo><mi>m</mi><mi>x</mi><mo>&#x0002B;</mo><mi>b</mi></mrow></math>.
Block equations are wrapped using</p>

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mrow><mi>x</mi><mo>&#x0003D;</mo><mfrac><mrow><mo>&#x02212;</mo><mi>b</mi><mi>&#x000B1;</mi><msqrt><mrow><msup><mi>b</mi><mn>2</mn></msup><mo>&#x02212;</mo><mn>4</mn><mi>a</mi><mi>c</mi></mrow></msqrt></mrow><mrow><mn>2</mn><mi>a</mi></mrow></mfrac></mrow></math>

<p>This code block will not have the math rendered.
<code>
some random code, describing $a and $b will not be rendered, $y=mx$
</code>
This will not work either <code>$\sqrt{2}</code> or</p>

<p><code>
$$
f = 12
$$
</code></p>
1 change: 1 addition & 0 deletions test/tm-cases/latex.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"extras": ["latex","latex2mathml"]}
1 change: 1 addition & 0 deletions test/tm-cases/latex.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extra latex latex2mathml
17 changes: 17 additions & 0 deletions test/tm-cases/latex.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## Simple Test
Inline Equations can be written as $y=mx+b$.
Block equations are wrapped using
$$
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
$$
This code block will not have the math rendered.
```
some random code, describing $a and $b will not be rendered, $y=mx$
```
This will not work either `$\sqrt{2}` or

```
$$
f = 12
$$
```

0 comments on commit f017595

Please sign in to comment.