Created
April 27, 2012 06:30
-
-
Save rctay/2506561 to your computer and use it in GitHub Desktop.
[python] pygments' markdown, revisited
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
The Pygments Markdown Preprocessor | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
This fragment is a Markdown_ preprocessor that renders source code | |
to HTML via Pygments. To use it, invoke Markdown like so:: | |
from markdown import Markdown | |
md = Markdown() | |
CodeBlockProcessors().prepare(md) | |
html = md.convert(someText) | |
markdown is then a callable that can be passed to the context of | |
a template and used in that template, for example. | |
This uses CSS classes by default, so use | |
``pygmentize -S <some style> -f html > pygments.css`` | |
to create a stylesheet to be added to the website. | |
You can then highlight source code in your markdown markup:: | |
[sourcecode:lexer] | |
some code | |
[/sourcecode] | |
.. _Markdown: http://www.freewisdom.org/projects/python-markdown/ | |
:copyright: Copyright 2006-2012 by the Pygments team, see AUTHORS. | |
:license: BSD, see LICENSE for details. | |
""" | |
# Options | |
# ~~~~~~~ | |
# Set to True if you want inline CSS styles instead of classes | |
INLINESTYLES = False | |
import random | |
import re | |
import string | |
from markdown import TextPreprocessor, TextPostprocessor | |
from pygments import highlight | |
from pygments.formatters import HtmlFormatter | |
from pygments.lexers import get_lexer_by_name, TextLexer | |
class CodeBlockProcessors(object): | |
PREFIX_SEED = 'TphNMKSiFB' | |
PATTERN = re.compile(r'\s*\[sourcecode:(.+?)\](.+?)\[/sourcecode\]\s*', re.S) | |
def __init__(self): | |
self.pre = CodeBlockPreprocessor(self) | |
self.post = CodeBlockPostprocessor(self) | |
self.formatter = HtmlFormatter(noclasses=INLINESTYLES) | |
self.stash = [] | |
def prepare(self, md): | |
md.textPreprocessors.insert(0, self.pre) | |
md.textPostprocessors.append(self.post) | |
def choose_prefix(self, lines): | |
p = self.PREFIX_SEED | |
while lines.find(p) != -1: | |
p += random.choice(string.letters) | |
self.code_prefix = p | |
def stash_code_blocks(self, lines): | |
self.choose_prefix(lines) | |
def repl(m): | |
index = len(self.stash) | |
self.stash.append(m) | |
return '\n\n<div class="%s">%s%d</div>\n\n' % ( | |
self.formatter.cssclass, | |
self.code_prefix, | |
index) | |
return self.PATTERN.sub(repl, lines) | |
def unstash_code_blocks(self, lines): | |
def repl(m): | |
index = int(m.group(1)) | |
m = self.stash[index] | |
try: | |
lexer = get_lexer_by_name(m.group(1)) | |
except ValueError: | |
lexer = TextLexer() | |
return highlight(m.group(2), lexer, self.formatter) | |
return re.sub(r'<div class="%s">%s(\d)</div>' % (self.formatter.cssclass, self.code_prefix), | |
repl, lines) | |
class CodeBlockPreprocessor(TextPreprocessor): | |
def __init__(self, processors): | |
self.processors = processors | |
def run(self, lines): | |
return self.processors.stash_code_blocks(lines) | |
class CodeBlockPostprocessor(TextPostprocessor): | |
def __init__(self, processors): | |
self.processors = processors | |
def run(self, lines): | |
return self.processors.unstash_code_blocks(lines) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
The Pygments Markdown Preprocessor | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
This fragment is a Markdown_ preprocessor that renders source code | |
to HTML via Pygments. To use it, invoke Markdown like so:: | |
from markdown import Markdown | |
md = Markdown() | |
md.textPreprocessors.insert(0, CodeBlockPreprocessor()) | |
html = md.convert(someText) | |
markdown is then a callable that can be passed to the context of | |
a template and used in that template, for example. | |
This uses CSS classes by default, so use | |
``pygmentize -S <some style> -f html > pygments.css`` | |
to create a stylesheet to be added to the website. | |
You can then highlight source code in your markdown markup:: | |
[sourcecode:lexer] | |
some code | |
[/sourcecode] | |
.. _Markdown: http://www.freewisdom.org/projects/python-markdown/ | |
:copyright: Copyright 2006-2012 by the Pygments team, see AUTHORS. | |
:license: BSD, see LICENSE for details. | |
""" | |
# Options | |
# ~~~~~~~ | |
# Set to True if you want inline CSS styles instead of classes | |
INLINESTYLES = False | |
import re | |
from markdown import TextPreprocessor | |
from pygments import highlight | |
from pygments.formatters import HtmlFormatter | |
from pygments.lexers import get_lexer_by_name, TextLexer | |
class CodeBlockPreprocessor(TextPreprocessor): | |
pattern = re.compile( | |
r'\s*\[sourcecode:(.+?)\](.+?)\[/sourcecode\]\s*', re.S) | |
formatter = HtmlFormatter(noclasses=INLINESTYLES) | |
def __init__(self, md): | |
self.md = md | |
def run(self, lines): | |
def repl(m): | |
try: | |
lexer = get_lexer_by_name(m.group(1)) | |
except ValueError: | |
lexer = TextLexer() | |
code = highlight(m.group(2), lexer, self.formatter) | |
place_holder = self.md.htmlStash.store(code.strip()) | |
return "\n\n%s\n\n" % place_holder | |
return self.pattern.sub( | |
repl, lines) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment