##// END OF EJS Templates
adding inline-block math
Nicholas Bollweg -
Show More
@@ -1,118 +1,122 b''
1 """Markdown filters with mistune
1 """Markdown filters with mistune
2
2
3 Used from markdown.py
3 Used from markdown.py
4 """
4 """
5 # Copyright (c) IPython Development Team.
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7
7
8 from __future__ import print_function
8 from __future__ import print_function
9
9
10 import re
10 import re
11
11
12 import mistune
12 import mistune
13
13
14 from pygments import highlight
14 from pygments import highlight
15 from pygments.lexers import get_lexer_by_name
15 from pygments.lexers import get_lexer_by_name
16 from pygments.formatters import HtmlFormatter
16 from pygments.formatters import HtmlFormatter
17 from pygments.util import ClassNotFound
17 from pygments.util import ClassNotFound
18
18
19 from IPython.nbconvert.filters.strings import add_anchor
19 from IPython.nbconvert.filters.strings import add_anchor
20 from IPython.nbconvert.utils.exceptions import ConversionException
20 from IPython.nbconvert.utils.exceptions import ConversionException
21 from IPython.utils.decorators import undoc
21 from IPython.utils.decorators import undoc
22
22
23
23
24 @undoc
24 @undoc
25 class MathBlockGrammar(mistune.BlockGrammar):
25 class MathBlockGrammar(mistune.BlockGrammar):
26 block_math = re.compile("^\$\$([^\$]*?)\$\$", re.DOTALL)
26 block_math = re.compile(r"^\$\$(.*?)\$\$", re.DOTALL)
27 latex_environment = re.compile(r"^\\begin\{([a-z]*\*?)\}(.*?)\\end\{\1\}",
27 latex_environment = re.compile(r"^\\begin\{([a-z]*\*?)\}(.*?)\\end\{\1\}",
28 re.DOTALL)
28 re.DOTALL)
29
29
30 @undoc
30 @undoc
31 class MathBlockLexer(mistune.BlockLexer):
31 class MathBlockLexer(mistune.BlockLexer):
32 default_rules = ['block_math', 'latex_environment'] + mistune.BlockLexer.default_rules
32 default_rules = ['block_math', 'latex_environment'] + mistune.BlockLexer.default_rules
33
33
34 def __init__(self, rules=None, **kwargs):
34 def __init__(self, rules=None, **kwargs):
35 if rules is None:
35 if rules is None:
36 rules = MathBlockGrammar()
36 rules = MathBlockGrammar()
37 super(MathBlockLexer, self).__init__(rules, **kwargs)
37 super(MathBlockLexer, self).__init__(rules, **kwargs)
38
38
39 def parse_block_math(self, m):
39 def parse_block_math(self, m):
40 """Parse a $$math$$ block"""
40 """Parse a $$math$$ block"""
41 self.tokens.append({
41 self.tokens.append({
42 'type': 'block_math',
42 'type': 'block_math',
43 'text': m.group(1)
43 'text': m.group(1)
44 })
44 })
45
45
46 def parse_latex_environment(self, m):
46 def parse_latex_environment(self, m):
47 self.tokens.append({
47 self.tokens.append({
48 'type': 'latex_environment',
48 'type': 'latex_environment',
49 'name': m.group(1),
49 'name': m.group(1),
50 'text': m.group(2)
50 'text': m.group(2)
51 })
51 })
52
52
53 @undoc
53 @undoc
54 class MathInlineGrammar(mistune.InlineGrammar):
54 class MathInlineGrammar(mistune.InlineGrammar):
55 math = re.compile("^\$([^\$]+?)\$")
55 math = re.compile(r"^\$(.+?)\$")
56 block_math = re.compile(r"^\$\$(.+?)\$\$", re.DOTALL)
56 text = re.compile(r'^[\s\S]+?(?=[\\<!\[_*`~$]|https?://| {2,}\n|$)')
57 text = re.compile(r'^[\s\S]+?(?=[\\<!\[_*`~$]|https?://| {2,}\n|$)')
57
58
58 @undoc
59 @undoc
59 class MathInlineLexer(mistune.InlineLexer):
60 class MathInlineLexer(mistune.InlineLexer):
60 default_rules = ['math'] + mistune.InlineLexer.default_rules
61 default_rules = ['math', 'block_math'] + mistune.InlineLexer.default_rules
61
62
62 def __init__(self, renderer, rules=None, **kwargs):
63 def __init__(self, renderer, rules=None, **kwargs):
63 if rules is None:
64 if rules is None:
64 rules = MathInlineGrammar()
65 rules = MathInlineGrammar()
65 super(MathInlineLexer, self).__init__(renderer, rules, **kwargs)
66 super(MathInlineLexer, self).__init__(renderer, rules, **kwargs)
66
67
67 def output_math(self, m):
68 def output_math(self, m):
68 return self.renderer.inline_math(m.group(1))
69 return self.renderer.inline_math(m.group(1))
69
70
71 def output_block_math(self, m):
72 return self.renderer.block_math(m.group(1))
73
70 @undoc
74 @undoc
71 class MarkdownWithMath(mistune.Markdown):
75 class MarkdownWithMath(mistune.Markdown):
72 def __init__(self, renderer, **kwargs):
76 def __init__(self, renderer, **kwargs):
73 if 'inline' not in kwargs:
77 if 'inline' not in kwargs:
74 kwargs['inline'] = MathInlineLexer
78 kwargs['inline'] = MathInlineLexer
75 if 'block' not in kwargs:
79 if 'block' not in kwargs:
76 kwargs['block'] = MathBlockLexer
80 kwargs['block'] = MathBlockLexer
77 super(MarkdownWithMath, self).__init__(renderer, **kwargs)
81 super(MarkdownWithMath, self).__init__(renderer, **kwargs)
78
82
79 def output_block_math(self):
83 def output_block_math(self):
80 return self.renderer.block_math(self.token['text'])
84 return self.renderer.block_math(self.token['text'])
81
85
82 def output_latex_environment(self):
86 def output_latex_environment(self):
83 return self.renderer.latex_environment(self.token['name'], self.token['text'])
87 return self.renderer.latex_environment(self.token['name'], self.token['text'])
84
88
85 @undoc
89 @undoc
86 class IPythonRenderer(mistune.Renderer):
90 class IPythonRenderer(mistune.Renderer):
87 def block_code(self, code, lang):
91 def block_code(self, code, lang):
88 if lang:
92 if lang:
89 try:
93 try:
90 lexer = get_lexer_by_name(lang, stripall=True)
94 lexer = get_lexer_by_name(lang, stripall=True)
91 except ClassNotFound:
95 except ClassNotFound:
92 code = lang + '\n' + code
96 code = lang + '\n' + code
93 lang = None
97 lang = None
94
98
95 if not lang:
99 if not lang:
96 return '\n<pre><code>%s</code></pre>\n' % \
100 return '\n<pre><code>%s</code></pre>\n' % \
97 mistune.escape(code)
101 mistune.escape(code)
98
102
99 formatter = HtmlFormatter()
103 formatter = HtmlFormatter()
100 return highlight(code, lexer, formatter)
104 return highlight(code, lexer, formatter)
101
105
102 def header(self, text, level, raw=None):
106 def header(self, text, level, raw=None):
103 html = super(IPythonRenderer, self).header(text, level, raw=raw)
107 html = super(IPythonRenderer, self).header(text, level, raw=raw)
104 return add_anchor(html)
108 return add_anchor(html)
105
109
106 # Pass math through unaltered - mathjax does the rendering in the browser
110 # Pass math through unaltered - mathjax does the rendering in the browser
107 def block_math(self, text):
111 def block_math(self, text):
108 return '$$%s$$' % text
112 return '$$%s$$' % text
109
113
110 def latex_environment(self, name, text):
114 def latex_environment(self, name, text):
111 return r'\begin{%s}%s\end{%s}' % (name, text, name)
115 return r'\begin{%s}%s\end{%s}' % (name, text, name)
112
116
113 def inline_math(self, text):
117 def inline_math(self, text):
114 return '$%s$' % text
118 return '$%s$' % text
115
119
116 def markdown2html_mistune(source):
120 def markdown2html_mistune(source):
117 """Convert a markdown string to HTML using mistune"""
121 """Convert a markdown string to HTML using mistune"""
118 return MarkdownWithMath(renderer=IPythonRenderer()).render(source)
122 return MarkdownWithMath(renderer=IPythonRenderer()).render(source)
General Comments 0
You need to be logged in to leave comments. Login now