Browse Source

Monkeypatched MD parser to correctly handle fenced code in quotes.

Ralfp 12 years ago
parent
commit
96f57e5544
1 changed files with 59 additions and 0 deletions
  1. 59 0
      misago/markdown/__init__.py

+ 59 - 0
misago/markdown/__init__.py

@@ -1 +1,60 @@
 from misago.markdown.factory import *
+
+# Monkeypatch blockquote parser to handle codes
+from markdown import util
+import markdown.blockprocessors
+from markdown.extensions.fenced_code import FENCED_BLOCK_RE, CODE_WRAP, LANG_TAG
+
+class MisagoBlockQuoteProcessor(markdown.blockprocessors.BlockQuoteProcessor):
+    def run(self, parent, blocks):
+        block = blocks.pop(0)
+        m = self.RE.search(block)
+        if m:
+            before = block[:m.start()] # Lines before blockquote
+            # Pass lines before blockquote in recursively for parsing forst.
+            self.parser.parseBlocks(parent, [before])
+            # Remove ``> `` from begining of each line.
+            block = '\n'.join([self.clean(line) for line in 
+                            block[m.start():].split('\n')])
+
+        sibling = self.lastChild(parent)
+        if sibling and sibling.tag == "blockquote":
+            # Previous block was a blockquote so set that as this blocks parent
+            quote = sibling
+        else:
+            # This is a new blockquote. Create a new parent element.
+            quote = util.etree.SubElement(parent, 'blockquote')
+        # Recursively parse block with blockquote as parent.
+        # change parser state so blockquotes embedded in lists use p tags
+        self.parser.state.set('blockquote')
+        # MONKEYPATCH START
+        block = self.clear_codes(block)
+        # MONKEYPATCH END
+        self.parser.parseChunk(quote, block)
+        self.parser.state.reset()
+
+    # MONKEYPATCH START
+    def clear_codes(self, text):
+        while 1:
+            m = FENCED_BLOCK_RE.search(text)
+            if m:
+                lang = ''
+                if m.group('lang'):
+                    lang = LANG_TAG % m.group('lang')
+                code = CODE_WRAP % (lang, self._escape(m.group('code')))
+                placeholder = self.parser.markdown.htmlStash.store(code, safe=True)
+                text = '%s\n\n%s\n\n%s' % (text[:m.start()].strip(), placeholder.strip(), text[m.end():].strip())
+            else:
+                break
+        return text.strip()
+
+    def _escape(self, txt):
+        """ basic html escaping """
+        txt = txt.replace('&', '&')
+        txt = txt.replace('<', '&lt;')
+        txt = txt.replace('>', '&gt;')
+        txt = txt.replace('"', '&quot;')
+        return txt.strip()
+    # MONKEYPATCH END
+
+markdown.blockprocessors.BlockQuoteProcessor = MisagoBlockQuoteProcessor