@@ -2764,6 +2764,55 @@ def sub(self, match):
2764
2764
def run (self , text ):
2765
2765
return self .fenced_code_block_re .sub (self .sub , text )
2766
2766
2767
+ class Latex (Extra ):
2768
+ '''
2769
+ Convert $ and $$ to <math> and </math> tags for inline and block math.
2770
+ '''
2771
+ name = 'latex'
2772
+ order = (Stage .CODE_BLOCKS , FencedCodeBlocks ), ()
2773
+
2774
+ _single_dollar_re = re .compile (r'(?<!\$)\$(?!\$)(.*?)\$' )
2775
+ _double_dollar_re = re .compile (r'\$\$(.*?)\$\$' , re .DOTALL )
2776
+
2777
+ # Ways to escape
2778
+ _pre_code_block_re = re .compile (r"<pre>(.*?)</pre>" , re .DOTALL ) # Wraped in <pre>
2779
+ _triple_re = re .compile (r'```(.*?)```' , re .DOTALL ) # Wrapped in a code block ```
2780
+ _single_re = re .compile (r'(?<!`)(`)(.*?)(?<!`)\1(?!`)' ) # Wrapped in a single `
2781
+
2782
+ converter = None
2783
+ code_blocks = {}
2784
+
2785
+ def _convert_single_match (self , match ):
2786
+ return self .converter .convert (match .group (1 ))
2787
+
2788
+ def _convert_double_match (self , match ):
2789
+ return self .converter .convert (match .group (1 ).replace (r"\n" , '' ), display = "block" )
2790
+
2791
+ def code_placeholder (self , match ):
2792
+ placeholder = f"<!--CODE_BLOCK_{ len (self .code_blocks )} -->"
2793
+ self .code_blocks [placeholder ] = match .group (0 )
2794
+ return placeholder
2795
+
2796
+ def run (self , text ):
2797
+ try :
2798
+ import latex2mathml .converter
2799
+ self .converter = latex2mathml .converter
2800
+ except ImportError :
2801
+ raise ImportError ('The "latex" extra requires the "latex2mathml" package to be installed.' )
2802
+
2803
+ # Escape by replacing with a code block
2804
+ text = self ._pre_code_block_re .sub (self .code_placeholder , text )
2805
+ text = self ._single_re .sub (self .code_placeholder , text )
2806
+ text = self ._triple_re .sub (self .code_placeholder , text )
2807
+
2808
+ text = self ._single_dollar_re .sub (self ._convert_single_match , text )
2809
+ text = self ._double_dollar_re .sub (self ._convert_double_match , text )
2810
+
2811
+ # Convert placeholder tag back to original code
2812
+ for placeholder , code_block in self .code_blocks .items ():
2813
+ text = text .replace (placeholder , code_block )
2814
+
2815
+ return text
2767
2816
2768
2817
class LinkPatterns (Extra ):
2769
2818
'''
@@ -3328,6 +3377,7 @@ def test(self, text):
3328
3377
Breaks .register ()
3329
3378
CodeFriendly .register ()
3330
3379
FencedCodeBlocks .register ()
3380
+ Latex .register ()
3331
3381
LinkPatterns .register ()
3332
3382
MarkdownInHTML .register ()
3333
3383
MiddleWordEm .register ()
0 commit comments