From 2b7e391fcd51d3468133f628f2e013574cf16536 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Sat, 9 Aug 2008 22:55:44 -0400 Subject: reorganized the extensions into a seperate dir. Much cleaner looking file system IMO. --- mdx/mdx_fenced_code.py | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 mdx/mdx_fenced_code.py (limited to 'mdx/mdx_fenced_code.py') diff --git a/mdx/mdx_fenced_code.py b/mdx/mdx_fenced_code.py new file mode 100644 index 0000000..c3d9f7f --- /dev/null +++ b/mdx/mdx_fenced_code.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +""" +Fenced Code Extension for Python Markdown +========================================= + +This extension adds Fenced Code Blocks to Python-Markdown. + + >>> import markdown + >>> text = ''' + ... A paragraph before a fenced code block: + ... + ... ~~~ + ... Fenced code block + ... ~~~ + ... ''' + >>> html = markdown.markdown(text, extensions=['fenced_code']) + >>> html + u'

A paragraph before a fenced code block:\\n

\\n
Fenced code block\\n
' + +Works with safe_mode also (we check this because we are using the HtmlStash): + + >>> markdown.markdown(text, extensions=['fenced_code'], safe_mode='replace') + u'

A paragraph before a fenced code block:\\n

\\n
Fenced code block\\n
' + +Include tilde's in a code block and wrap with blank lines: + + >>> text = ''' + ... ~~~~~~~~ + ... + ... ~~~~ + ... + ... ~~~~~~~~''' + >>> markdown.markdown(text, extensions=['fenced_code']) + u'
\\n~~~~\\n\\n
' + +Multiple blocks and language tags: + + >>> text = ''' + ... ~~~~ + ... block one + ... ~~~~{.python} + ... + ... ~~~~ + ...

block two

+ ... ~~~~{.html}''' + >>> markdown.markdown(text, extensions=['fenced_code']) + u'
block one\\n
\\n\\n
<p>block two</p>\\n
' + +""" + +import markdown, re + +# Global vars +FENCED_BLOCK_RE = re.compile( \ + r'(?P^~{3,})[ ]*\n(?P.*?)(?P=fence)[ ]*(\{\.(?P[a-zA-Z0-9_-]*)\})?[ ]*$', + re.MULTILINE|re.DOTALL + ) +CODE_WRAP = '
%s
' +LANG_TAG = ' class="%s"' + + +class FencedCodeExtension(markdown.Extension): + + def extendMarkdown(self, md, md_globals): + """ Add FencedBlockPreprocessor to the Markdown instance. """ + + FENCED_BLOCK_PREPROCESSOR = FencedBlockPreprocessor() + FENCED_BLOCK_PREPROCESSOR.md = md + md.textPreprocessors.insert(0, FENCED_BLOCK_PREPROCESSOR) + + +class FencedBlockPreprocessor(markdown.TextPreprocessor): + + def run(self, text): + """ Match and store Fenced Code Blocks in the HtmlStash. """ + 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.md.htmlStash.store(code, safe=True) + text = '%s\n%s\n%s'% (text[:m.start()], placeholder, text[m.end():]) + else: + break + return text + + def _escape(self, txt): + """ basic html escaping """ + txt = txt.replace('&', '&') + txt = txt.replace('<', '<') + txt = txt.replace('>', '>') + txt = txt.replace('"', '"') + return txt + + +def makeExtension(configs=None): + return FencedCodeExtension() + + +if __name__ == "__main__": + import doctest + doctest.testmod() -- cgit v1.2.3