123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- """
- Pelican Mathjax Markdown Extension
- ==================================
- An extension for the Python Markdown module that enables
- the Pelican python blog to process mathjax. This extension
- gives Pelican the ability to use Mathjax as a "first class
- citizen" of the blog
- """
- import markdown
- from markdown.util import etree
- from markdown.util import AtomicString
- class PelicanMathJaxPattern(markdown.inlinepatterns.Pattern):
- """Inline markdown processing that matches mathjax"""
- def __init__(self, pelican_mathjax_extension, tag, pattern):
- super(PelicanMathJaxPattern,self).__init__(pattern)
- self.math_tag_class = pelican_mathjax_extension.getConfig('math_tag_class')
- self.pelican_mathjax_extension = pelican_mathjax_extension
- self.tag = tag
- def handleMatch(self, m):
- node = markdown.util.etree.Element(self.tag)
- node.set('class', self.math_tag_class)
- prefix = '\\(' if m.group('prefix') == '$' else m.group('prefix')
- suffix = '\\)' if m.group('suffix') == '$' else m.group('suffix')
- node.text = markdown.util.AtomicString(prefix + m.group('math') + suffix)
-
-
- self.pelican_mathjax_extension.mathjax_needed = True
- return node
- class PelicanMathJaxCorrectDisplayMath(markdown.treeprocessors.Treeprocessor):
- """Corrects invalid html that results from a <div> being put inside
- a <p> for displayed math"""
- def __init__(self, pelican_mathjax_extension):
- self.pelican_mathjax_extension = pelican_mathjax_extension
- def correct_html(self, root, children, div_math, insert_idx, text):
- """Separates out <div class="math"> from the parent tag <p>. Anything
- in between is put into its own parent tag of <p>"""
- current_idx = 0
- for idx in div_math:
- el = markdown.util.etree.Element('p')
- el.text = text
- el.extend(children[current_idx:idx])
-
- if len(el) != 0 or (el.text and not el.text.isspace()):
- root.insert(insert_idx, el)
- insert_idx += 1
- text = children[idx].tail
- children[idx].tail = None
- root.insert(insert_idx, children[idx])
- insert_idx += 1
- current_idx = idx+1
- el = markdown.util.etree.Element('p')
- el.text = text
- el.extend(children[current_idx:])
- if len(el) != 0 or (el.text and not el.text.isspace()):
- root.insert(insert_idx, el)
- def run(self, root):
- """Searches for <div class="math"> that are children in <p> tags and corrects
- the invalid HTML that results"""
- math_tag_class = self.pelican_mathjax_extension.getConfig('math_tag_class')
- for parent in root:
- div_math = []
- children = list(parent)
- for div in parent.findall('div'):
- if div.get('class') == math_tag_class:
- div_math.append(children.index(div))
-
- if not div_math:
- continue
- insert_idx = list(root).index(parent)
- self.correct_html(root, children, div_math, insert_idx, parent.text)
- root.remove(parent)
- return root
- class PelicanMathJaxAddJavaScript(markdown.treeprocessors.Treeprocessor):
- """Tree Processor for adding Mathjax JavaScript to the blog"""
- def __init__(self, pelican_mathjax_extension):
- self.pelican_mathjax_extension = pelican_mathjax_extension
- def run(self, root):
-
- if (not self.pelican_mathjax_extension.mathjax_needed):
- return root
-
- mathjax_script = etree.Element('script')
- mathjax_script.set('type','text/javascript')
- mathjax_script.text = AtomicString(self.pelican_mathjax_extension.getConfig('mathjax_script'))
- root.append(mathjax_script)
-
-
- self.pelican_mathjax_extension.mathjax_needed = False
- return root
- class PelicanMathJaxExtension(markdown.Extension):
- """A markdown extension enabling mathjax processing in Markdown for Pelican"""
- def __init__(self, config):
- try:
-
- self.config['mathjax_script'] = ['', 'Mathjax JavaScript script']
- self.config['math_tag_class'] = ['math', 'The class of the tag in which mathematics is wrapped']
- self.config['auto_insert'] = [True, 'Determines if mathjax script is automatically inserted into content']
- super(PelicanMathJaxExtension,self).__init__(**config)
- except AttributeError:
-
- config['mathjax_script'] = [config['mathjax_script'], 'Mathjax JavaScript script']
- config['math_tag_class'] = [config['math_tag_class'], 'The class of the tag in which mathematic is wrapped']
- config['auto_insert'] = [config['auto_insert'], 'Determines if mathjax script is automatically inserted into content']
- super(PelicanMathJaxExtension,self).__init__(config)
-
-
- self.mathjax_needed = False
- def extendMarkdown(self, md, md_globals):
-
- mathjax_inline_regex = r'(?P<prefix>\$)(?P<math>.+?)(?P<suffix>(?<!\s)\2)'
- mathjax_display_regex = r'(?P<prefix>\$\$|\\begin\{(.+?)\})(?P<math>.+?)(?P<suffix>\2|\\end\{\3\})'
-
-
-
- md.inlinePatterns.add('mathjax_displayed', PelicanMathJaxPattern(self, 'div', mathjax_display_regex), '<escape')
- md.inlinePatterns.add('mathjax_inlined', PelicanMathJaxPattern(self, 'span', mathjax_inline_regex), '<escape')
-
- md.treeprocessors.add('mathjax_correctdisplayedmath', PelicanMathJaxCorrectDisplayMath(self), '>inline')
-
-
- if self.getConfig('auto_insert'):
- md.treeprocessors.add('mathjax_addjavascript', PelicanMathJaxAddJavaScript(self), '_end')
|