aboutsummaryrefslogtreecommitdiffstats
path: root/markdown_extensions/fenced_code.py
diff options
context:
space:
mode:
authorWaylan Limberg <waylan@gmail.com>2008-08-11 20:12:28 -0400
committerWaylan Limberg <waylan@gmail.com>2008-08-11 20:12:28 -0400
commitf9bc5d2b86a94fb98e791966bb26e1abd5ef0ed2 (patch)
tree217d79e69b8972c0c4fb830a36b6b7524e615000 /markdown_extensions/fenced_code.py
parent2783134621439aaa1130a1b73da36b335c6b0361 (diff)
downloadmarkdown-f9bc5d2b86a94fb98e791966bb26e1abd5ef0ed2.tar.gz
markdown-f9bc5d2b86a94fb98e791966bb26e1abd5ef0ed2.tar.bz2
markdown-f9bc5d2b86a94fb98e791966bb26e1abd5ef0ed2.zip
renamed extension module and set import to extension module first, then mdx_filename
Diffstat (limited to 'markdown_extensions/fenced_code.py')
-rw-r--r--markdown_extensions/fenced_code.py105
1 files changed, 105 insertions, 0 deletions
diff --git a/markdown_extensions/fenced_code.py b/markdown_extensions/fenced_code.py
new file mode 100644
index 0000000..c3d9f7f
--- /dev/null
+++ b/markdown_extensions/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'<p>A paragraph before a fenced code block:\\n</p>\\n<pre><code>Fenced code block\\n</code></pre>'
+
+Works with safe_mode also (we check this because we are using the HtmlStash):
+
+ >>> markdown.markdown(text, extensions=['fenced_code'], safe_mode='replace')
+ u'<p>A paragraph before a fenced code block:\\n</p>\\n<pre><code>Fenced code block\\n</code></pre>'
+
+Include tilde's in a code block and wrap with blank lines:
+
+ >>> text = '''
+ ... ~~~~~~~~
+ ...
+ ... ~~~~
+ ...
+ ... ~~~~~~~~'''
+ >>> markdown.markdown(text, extensions=['fenced_code'])
+ u'<pre><code>\\n~~~~\\n\\n</code></pre>'
+
+Multiple blocks and language tags:
+
+ >>> text = '''
+ ... ~~~~
+ ... block one
+ ... ~~~~{.python}
+ ...
+ ... ~~~~
+ ... <p>block two</p>
+ ... ~~~~{.html}'''
+ >>> markdown.markdown(text, extensions=['fenced_code'])
+ u'<pre><code class="python">block one\\n</code></pre>\\n\\n<pre><code class="html">&lt;p&gt;block two&lt;/p&gt;\\n</code></pre>'
+
+"""
+
+import markdown, re
+
+# Global vars
+FENCED_BLOCK_RE = re.compile( \
+ r'(?P<fence>^~{3,})[ ]*\n(?P<code>.*?)(?P=fence)[ ]*(\{\.(?P<lang>[a-zA-Z0-9_-]*)\})?[ ]*$',
+ re.MULTILINE|re.DOTALL
+ )
+CODE_WRAP = '<pre><code%s>%s</code></pre>'
+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('&', '&amp;')
+ txt = txt.replace('<', '&lt;')
+ txt = txt.replace('>', '&gt;')
+ txt = txt.replace('"', '&quot;')
+ return txt
+
+
+def makeExtension(configs=None):
+ return FencedCodeExtension()
+
+
+if __name__ == "__main__":
+ import doctest
+ doctest.testmod()