##// END OF EJS Templates
Integrate pass-through of mathematical expressions with markdown rendering
Thomas Kluyver -
Show More
@@ -19,6 +19,7 b' from __future__ import print_function'
19 import os
19 import os
20 import subprocess
20 import subprocess
21 from io import TextIOWrapper, BytesIO
21 from io import TextIOWrapper, BytesIO
22 import re
22
23
23 import mistune
24 import mistune
24 from pygments import highlight
25 from pygments import highlight
@@ -69,6 +70,48 b' def markdown2latex(source):'
69 """
70 """
70 return pandoc(source, 'markdown', 'latex')
71 return pandoc(source, 'markdown', 'latex')
71
72
73 class MathBlockGrammar(mistune.BlockGrammar):
74 block_math = re.compile("^\$\$(.*?)\$\$")
75
76 class MathBlockLexer(mistune.BlockLexer):
77 default_features = ['block_math'] + mistune.BlockLexer.default_features
78
79 def __init__(self, rules=None, **kwargs):
80 if rules is None:
81 rules = MathBlockGrammar()
82 super(MathBlockLexer, self).__init__(rules, **kwargs)
83
84 def parse_block_math(self, m):
85 """Parse a $$math$$ block"""
86 self.tokens.append({
87 'type': 'block_math',
88 'text': m.group(1)
89 })
90
91 class MathInlineGrammar(mistune.InlineGrammar):
92 math = re.compile("^\$(.+?)\$")
93
94 class MathInlineLexer(mistune.InlineLexer):
95 default_features = ['math'] + mistune.InlineLexer.default_features
96
97 def __init__(self, renderer, rules=None, **kwargs):
98 if rules is None:
99 rules = MathInlineGrammar()
100 super(MathInlineLexer, self).__init__(renderer, rules, **kwargs)
101
102 def output_math(self, m):
103 self.renderer.inline_math(m.group(1))
104
105 class MarkdownWithMath(mistune.Markdown):
106 def __init__(self, renderer, **kwargs):
107 if 'inline' not in kwargs:
108 kwargs['inline'] = MathInlineLexer(renderer, **kwargs)
109 if 'block' not in kwargs:
110 kwargs['block'] = MathBlockLexer(**kwargs)
111 super(MarkdownWithMath, self).__init__(renderer, **kwargs)
112
113 def parse_block_math(self):
114 return self.renderer.block_math(self.token['text'])
72
115
73 class MyRenderer(mistune.Renderer):
116 class MyRenderer(mistune.Renderer):
74 def block_code(self, code, lang):
117 def block_code(self, code, lang):
@@ -79,9 +122,16 b' class MyRenderer(mistune.Renderer):'
79 formatter = HtmlFormatter()
122 formatter = HtmlFormatter()
80 return highlight(code, lexer, formatter)
123 return highlight(code, lexer, formatter)
81
124
125 # Pass math through unaltered - mathjax does the rendering in the browser
126 def block_math(self, text):
127 return '$$%s$$' % text
128
129 def inline_math(self, text):
130 return '$%s$' % text
131
82 def markdown2html_mistune(source):
132 def markdown2html_mistune(source):
83 """Convert a markdown string to HTML using mistune"""
133 """Convert a markdown string to HTML using mistune"""
84 return mistune.Markdown(renderer=MyRenderer()).render(source)
134 return MarkdownWithMath(renderer=MyRenderer()).render(source)
85
135
86 def markdown2html_pandoc(source):
136 def markdown2html_pandoc(source):
87 """Convert a markdown string to HTML via pandoc"""
137 """Convert a markdown string to HTML via pandoc"""
@@ -114,7 +164,7 b" def markdown2html_marked(source, encoding='utf-8'):"
114 return out.rstrip('\n')
164 return out.rstrip('\n')
115
165
116 # The mistune renderer is the default, because it's simple to depend on it
166 # The mistune renderer is the default, because it's simple to depend on it
117 markdown2html = markdown2html_mistune
167 markdown2html = markdown2html_marked
118
168
119 def markdown2rst(source):
169 def markdown2rst(source):
120 """Convert a markdown string to ReST via pandoc.
170 """Convert a markdown string to ReST via pandoc.
General Comments 0
You need to be logged in to leave comments. Login now