Skip to content

Commit

Permalink
Improve arithmatex patterns
Browse files Browse the repository at this point in the history
Fixes #888
  • Loading branch information
facelessuser committed Apr 11, 2020
1 parent bd6ffd3 commit ad20f65
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 4 deletions.
5 changes: 5 additions & 0 deletions docs/src/markdown/about/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Next

- **FIX**: Better Arithmatex patterns. Fix issue #888 which caused a hang due to a regular expression typo. Also ensure
`#!tex $$..$$` and `#!tex begin{}...end{}` patterns properly don't match if the tail markers are escaped.

## 7.0

Please see [Release Notes](./release.md#upgrading-to-70) for details on upgrading to 7.0.
Expand Down
8 changes: 4 additions & 4 deletions pymdownx/arithmatex.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@
from . import util
import re

RE_SMART_DOLLAR_INLINE = r'(?:(?<!\\)((?:\\{2})+)(?=\$)|(?<!\\)(\$)(?!\s)((?:\\.|[^\$])+?)(?<!\s)(?:\$))'
RE_DOLLAR_INLINE = r'(?:(?<!\\)((?:\\{2})+)(?=\$)|(?<!\\)(\$)((?:\\.|[^\$])+?)(?:\$))'
RE_SMART_DOLLAR_INLINE = r'(?:(?<!\\)((?:\\{2})+)(?=\$)|(?<!\\)(\$)(?!\s)((?:\\.|[^\\$])+?)(?<!\s)(?:\$))'
RE_DOLLAR_INLINE = r'(?:(?<!\\)((?:\\{2})+)(?=\$)|(?<!\\)(\$)((?:\\.|[^\\$])+?)(?:\$))'
RE_BRACKET_INLINE = r'(?:(?<!\\)((?:\\{2})+?)(?=\\\()|(?<!\\)(\\\()((?:\\[^)]|[^\\])+?)(?:\\\)))'

RE_DOLLAR_BLOCK = r'(?P<dollar>[$]{2})(?P<math>.+?)(?P=dollar)'
RE_TEX_BLOCK = r'(?P<math2>\\begin\{(?P<env>[a-z]+\*?)\}.+?\\end\{(?P=env)\})'
RE_DOLLAR_BLOCK = r'(?P<dollar>[$]{2})(?P<math>((?:\\.|[^\\])+?))(?P=dollar)'
RE_TEX_BLOCK = r'(?P<math2>\\begin\{(?P<env>[a-z]+\*?)\}(?:\\.|[^\\])+?\\end\{(?P=env)\})'
RE_BRACKET_BLOCK = r'\\\[(?P<math3>(?:\\[^\]]|[^\\])+?)\\\]'


Expand Down
133 changes: 133 additions & 0 deletions tests/test_extensions/test_arithmatex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"""Test cases for Arithmatex."""
from .. import util


class TestArithmatexBlockEscapes(util.MdCase):
"""Test escaping cases for Arithmatex blocks."""

extension = [
'pymdownx.arithmatex'
]
extension_configs = {}

def test_escaped_dollar_block(self):
"""Test escaping a dollar."""

self.check_markdown(
r'''
$$3+2\$$
''',
r'''
<p>$<span><span class="MathJax_Preview">3+2\$</span><script type="math/tex">3+2\$</script></span></p>
''',
True
)

def test_escaped_dollar_dollar_block(self):
"""Test escaping both dollars."""

self.check_markdown(
r'''
$$3+2\$\$
''',
r'''
<p>$$3+2$$</p>
''',
True
)

def test_double_escaped_dollar_block(self):
"""Test double escaping a dollar."""

self.check_markdown(
r'''
$$3+2\\$$
''',
r'''
<div>
<div class="MathJax_Preview">3+2\\</div>
<script type="math/tex; mode=display">3+2\\</script>
</div>
''',
True
)

def test_escaped_end_block(self):
"""Test escaping an end."""

self.check_markdown(
r'''
\begin{align}3+2\\end{align}
''',
r'''
<p>\begin{align}3+2\end{align}</p>
''',
True
)

def test_double_escaped_end_block(self):
"""Test double escaping an end."""

self.check_markdown(
r'''
\begin{align}3+2\\\end{align}
''',
r'''
<div>
<div class="MathJax_Preview">\begin{align}3+2\\\end{align}</div>
<script type="math/tex; mode=display">\begin{align}3+2\\\end{align}</script>
</div>
''',
True
)

def test_escaped_bracket_block(self):
"""Test escaping a bracket."""

self.check_markdown(
r'''
\[3+2\\]
''',
r'''
<p>[3+2\]</p>
''',
True
)

def test_double_escaped_bracket_block(self):
"""Test double escaping a bracket."""

self.check_markdown(
r'''
\[3+2\\\]
''',
r'''
<div>
<div class="MathJax_Preview">3+2\\</div>
<script type="math/tex; mode=display">3+2\\</script>
</div>
''',
True
)


class TestArithmatexHang(util.MdCase):
"""Test hang cases."""

def test_hang_dollar(self):
"""
We are just making sure this works.
Previously this pattern would hang. It isn't supposed to match due to the space before the last dolloar,
but it definitely shouldn't hang the process.
"""

self.check_markdown(
r'''
$z^{[1]} = \begin{bmatrix}w^{[1]T}_1 \\ w^{[1]T}_2 \\ w^{[1]T}_3 \\ w^{[1]T}_4 \end{bmatrix} \begin{bmatrix}x_1 \\ x_2 \\ x_3 \end{bmatrix} + \begin{bmatrix}b^{[1]}_1 \\ b^{[1]}_2 \\ b^{[1]}_3 \\ b^{[1]}_4 \end{bmatrix}= \begin{bmatrix}w^{[1]T}_1 x + b^{[1]}_1 \\ w^{[1]T}_2 x + b^{[1]}_2\\ w^{[1]T}_3 x + b^{[1]}_3 \\ w^{[1]T}_4 x + b^{[1]}_4 \end{bmatrix} $
''', # noqa: E501
r'''
<p>$z^{[1]} = \begin{bmatrix}w^{[1]T}_1 \ w^{[1]T}_2 \ w^{[1]T}_3 \ w^{[1]T}_4 \end{bmatrix} \begin{bmatrix}x_1 \ x_2 \ x_3 \end{bmatrix} + \begin{bmatrix}b^{[1]}_1 \ b^{[1]}_2 \ b^{[1]}_3 \ b^{[1]}_4 \end{bmatrix}= \begin{bmatrix}w^{[1]T}_1 x + b^{[1]}_1 \ w^{[1]T}_2 x + b^{[1]}_2\ w^{[1]T}_3 x + b^{[1]}_3 \ w^{[1]T}_4 x + b^{[1]}_4 \end{bmatrix} $</p>
''', # noqa: E501
True
)

0 comments on commit ad20f65

Please sign in to comment.