77Adds support for displaying math formulas using
88[MathJax](http://www.mathjax.org/).
99
10- Author: 2015-2017 , Dmitry Shachnev <mitya57@gmail.com>.
10+ Author: 2015-2020 , Dmitry Shachnev <mitya57@gmail.com>.
1111'''
1212
13- from markdown .inlinepatterns import Pattern
13+ from markdown .inlinepatterns import InlineProcessor
1414from markdown .extensions import Extension
1515from markdown .util import AtomicString , etree
1616
1717
18+ def _wrap_node (node , preview_text , wrapper_tag ):
19+ preview = etree .Element ('span' , {'class' : 'MathJax_Preview' })
20+ preview .text = AtomicString (preview_text )
21+ wrapper = etree .Element (wrapper_tag )
22+ wrapper .extend ([preview , node ])
23+ return wrapper
24+
25+
26+ class InlineMathPattern (InlineProcessor ):
27+ def handleMatch (self , m , data ):
28+ node = etree .Element ('script' )
29+ node .set ('type' , self ._content_type )
30+ node .text = AtomicString (m .group (2 ))
31+ if self ._add_preview :
32+ node = _wrap_node (node , m .group (0 ), 'span' )
33+ return node , m .start (0 ), m .end (0 )
34+
35+
36+ class DisplayMathPattern (InlineProcessor ):
37+ def handleMatch (self , m , data ):
38+ node = etree .Element ('script' )
39+ node .set ('type' , '%s; mode=display' % self ._content_type )
40+ if '\\ begin' in m .group (1 ):
41+ node .text = AtomicString (m .group (0 ))
42+ else :
43+ node .text = AtomicString (m .group (2 ))
44+ if self ._add_preview :
45+ node = _wrap_node (node , m .group (0 ), 'div' )
46+ return node , m .start (0 ), m .end (0 )
47+
48+
1849class MathExtension (Extension ):
1950 def __init__ (self , * args , ** kwargs ):
2051 self .config = {
@@ -26,56 +57,33 @@ def __init__(self, *args, **kwargs):
2657 }
2758 super (MathExtension , self ).__init__ (* args , ** kwargs )
2859
29- def _get_content_type (self ):
30- if self .getConfig ('use_asciimath' ):
31- return 'math/asciimath'
32- return 'math/tex'
33-
3460 def extendMarkdown (self , md ):
35- def _wrap_node (node , preview_text , wrapper_tag ):
36- if not self .getConfig ('add_preview' ):
37- return node
38- preview = etree .Element ('span' , {'class' : 'MathJax_Preview' })
39- preview .text = AtomicString (preview_text )
40- wrapper = etree .Element (wrapper_tag )
41- wrapper .extend ([preview , node ])
42- return wrapper
43-
44- def handle_match_inline (m ):
45- node = etree .Element ('script' )
46- node .set ('type' , self ._get_content_type ())
47- node .text = AtomicString (m .group (3 ))
48- return _wrap_node (node , '' .join (m .group (2 , 3 , 4 )), 'span' )
49-
50- def handle_match (m ):
51- node = etree .Element ('script' )
52- node .set ('type' , '%s; mode=display' % self ._get_content_type ())
53- if '\\ begin' in m .group (2 ):
54- node .text = AtomicString ('' .join (m .group (2 , 4 , 5 )))
55- return _wrap_node (node , '' .join (m .group (1 , 2 , 4 , 5 , 6 )), 'div' )
56- else :
57- node .text = AtomicString (m .group (3 ))
58- return _wrap_node (node , '' .join (m .group (2 , 3 , 4 )), 'div' )
59-
6061 inlinemathpatterns = (
61- Pattern (r'(?<!\\|\$)(\$)([^\$]+)(\$)' ), # $...$
62- Pattern (r'(?<!\\)(\\\()(.+?)(\\\))' ) # \(...\)
62+ InlineMathPattern (r'(?<!\\|\$)(\$)([^\$]+)(\$)' ), # $...$
63+ InlineMathPattern (r'(?<!\\)(\\\()(.+?)(\\\))' ) # \(...\)
6364 )
6465 mathpatterns = (
65- Pattern (r'(?<!\\)(\$\$)([^\$]+)(\$\$)' ), # $$...$$
66- Pattern (r'(?<!\\)(\\\[)(.+?)(\\\])' ), # \[...\]
67- Pattern (r'(?<!\\)(\\begin{([a-z]+?\*?)})(.+?)(\\end{\3})' )
66+ DisplayMathPattern (r'(?<!\\)(\$\$)([^\$]+)(\$\$)' ), # $$...$$
67+ DisplayMathPattern (r'(?<!\\)(\\\[)(.+?)(\\\])' ), # \[...\]
68+ DisplayMathPattern ( # \begin...\end
69+ r'(?<!\\)(\\begin{([a-z]+?\*?)})(.+?)(\\end{\2})' )
6870 )
6971 if not self .getConfig ('enable_dollar_delimiter' ):
7072 inlinemathpatterns = inlinemathpatterns [1 :]
7173 if self .getConfig ('use_asciimath' ):
7274 mathpatterns = mathpatterns [:- 1 ] # \begin...\end is TeX only
75+
76+ add_preview = self .getConfig ('add_preview' )
77+ use_asciimath = self .getConfig ('use_asciimath' )
78+ content_type = 'math/asciimath' if use_asciimath else 'math/tex'
7379 for i , pattern in enumerate (mathpatterns ):
74- pattern .handleMatch = handle_match
80+ pattern ._add_preview = add_preview
81+ pattern ._content_type = content_type
7582 # we should have higher priority than 'escape' which has 180
7683 md .inlinePatterns .register (pattern , 'math-%d' % i , 185 )
7784 for i , pattern in enumerate (inlinemathpatterns ):
78- pattern .handleMatch = handle_match_inline
85+ pattern ._add_preview = add_preview
86+ pattern ._content_type = content_type
7987 md .inlinePatterns .register (pattern , 'math-inline-%d' % i , 185 )
8088 if self .getConfig ('enable_dollar_delimiter' ):
8189 md .ESCAPED_CHARS .append ('$' )
0 commit comments