Skip to content

Instantly share code, notes, and snippets.

@rctay
Created April 27, 2012 06:30
Show Gist options
  • Save rctay/2506561 to your computer and use it in GitHub Desktop.
Save rctay/2506561 to your computer and use it in GitHub Desktop.
[python] pygments' markdown, revisited
# -*- 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)
# -*- 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