From 4e7d92f8d8d58039f84c4677a9d69be3c20a16ef Mon Sep 17 00:00:00 2001 From: Lucas van Dijk Date: Sun, 24 Jan 2010 23:46:38 +0100 Subject: Added pygments support to fenced_code --- markdown/extensions/fenced_code.py | 77 +++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/markdown/extensions/fenced_code.py b/markdown/extensions/fenced_code.py index 307b1dc..f16f94c 100644 --- a/markdown/extensions/fenced_code.py +++ b/markdown/extensions/fenced_code.py @@ -9,7 +9,7 @@ This extension adds Fenced Code Blocks to Python-Markdown. >>> import markdown >>> text = ''' ... A paragraph before a fenced code block: - ... + ... ... ~~~ ... Fenced code block ... ~~~ @@ -22,14 +22,14 @@ 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
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
' @@ -40,7 +40,7 @@ Multiple blocks and language tags: ... ~~~~{.python} ... block one ... ~~~~ - ... + ... ... ~~~~.html ...

block two

... ~~~~''' @@ -52,19 +52,29 @@ Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/). Project website: Contact: markdown@freewisdom.org -License: BSD (see ../docs/LICENSE for details) +License: BSD (see ../docs/LICENSE for details) Dependencies: -* [Python 2.3+](http://python.org) +* [Python 2.4+](http://python.org) * [Markdown 2.0+](http://www.freewisdom.org/projects/python-markdown/) +* [Pygments (optional)](http://pygments.org) """ import markdown, re +try: + from pygments import highlight + from pygments.lexers import get_lexer_by_name + from pygments.formatters import HtmlFormatter +except ImportError: + HAS_PYGMENTS = False +else: + HAS_PYGMENTS = True + # Global vars FENCED_BLOCK_RE = re.compile( \ - r'(?P^~{3,})[ ]*(\{?\.(?P[a-zA-Z0-9_-]*)\}?)?[ ]*\n(?P.*?)(?P=fence)[ ]*$', + r'(?P^~{3,})[ ]*(\{?\.(?P[a-zA-Z0-9_-]*)\}?)?[ ]*\n(?P.*?)(?P=fence)[ ]*$', re.MULTILINE|re.DOTALL ) CODE_WRAP = '
%s
' @@ -73,26 +83,67 @@ LANG_TAG = ' class="%s"' class FencedCodeExtension(markdown.Extension): + def __init__(self, configs): + self.config = { + 'HIGHLIGHT_STYLE': ['tango', 'The pygments HTML Formatter style to use'], + 'NO_CSS_CLASSES': [True, 'Do not use any CSS classes, use inline styles instead'], + 'LINENOS': [True, 'Display line numbers'] + } + + for key, value in configs: + self.config[key][0] = value + def extendMarkdown(self, md, md_globals): """ Add FencedBlockPreprocessor to the Markdown instance. """ - md.preprocessors.add('fenced_code_block', - FencedBlockPreprocessor(md), + md.preprocessors.add('fenced_code_block', + FencedBlockPreprocessor(md, self.config), "_begin") class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor): - + + def __init__(self, md, config): + markdown.preprocessors.Preprocessor.__init__(self, md) + self.config = config + + def getConfig(self, key): + if key in self.config: + return self.config[key][0] + else: + return None + def run(self, lines): """ Match and store Fenced Code Blocks in the HtmlStash. """ text = "\n".join(lines) while 1: m = FENCED_BLOCK_RE.search(text) if m: + highlighted = False + lang = '' if m.group('lang'): lang = LANG_TAG % m.group('lang') - code = CODE_WRAP % (lang, self._escape(m.group('code'))) + + # If pygments installed, highlight code + if HAS_PYGMENTS and m.group('lang'): + formatter = HtmlFormatter( + linenos=self.getConfig('LINENOS'), + style=self.getConfig('HIGHLIGHT_STYLE'), + noclasses=self.getConfig('NO_CSS_CLASSES') + ) + + try: + lexer = get_lexer_by_name(m.group('lang')) + except: + highlighted = False + else: + highlighted = True + code = highlight(m.group('code'), lexer, formatter) + + if not highlighted: + code = CODE_WRAP % (lang, self._escape(m.group('code'))) + placeholder = self.markdown.htmlStash.store(code, safe=True) text = '%s\n%s\n%s'% (text[:m.start()], placeholder, text[m.end():]) else: @@ -109,7 +160,7 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor): def makeExtension(configs=None): - return FencedCodeExtension() + return FencedCodeExtension(configs=configs) if __name__ == "__main__": -- cgit v1.2.3