aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas van Dijk <luckyluke56@gmail.com>2010-01-25 21:11:26 +0100
committerLucas van Dijk <luckyluke56@gmail.com>2010-01-25 21:11:26 +0100
commitee6fb73b160721e666e72a0921135d6abae19fa4 (patch)
tree29a40435c5c2df41ce7d935b32217c5c0996025f
parent4e7d92f8d8d58039f84c4677a9d69be3c20a16ef (diff)
downloadmarkdown-ee6fb73b160721e666e72a0921135d6abae19fa4.tar.gz
markdown-ee6fb73b160721e666e72a0921135d6abae19fa4.tar.bz2
markdown-ee6fb73b160721e666e72a0921135d6abae19fa4.zip
Refactored codehilite and fenced code, so now fenced code will also be highlited when codehilite extension is enabled
-rw-r--r--markdown/__init__.py27
-rw-r--r--markdown/extensions/codehilite.py90
-rw-r--r--markdown/extensions/fenced_code.py71
3 files changed, 94 insertions, 94 deletions
diff --git a/markdown/__init__.py b/markdown/__init__.py
index 211e3d5..26314f6 100644
--- a/markdown/__init__.py
+++ b/markdown/__init__.py
@@ -182,7 +182,7 @@ class Markdown:
def __init__(self,
extensions=[],
extension_configs={},
- safe_mode = False,
+ safe_mode = False,
output_format=DEFAULT_OUTPUT_FORMAT):
"""
Creates a new Markdown instance.
@@ -200,12 +200,12 @@ class Markdown:
* "xhtml": Outputs latest supported version of XHTML (currently XHTML 1.1).
* "html4": Outputs HTML 4
* "html": Outputs latest supported version of HTML (currently HTML 4).
- Note that it is suggested that the more specific formats ("xhtml1"
+ Note that it is suggested that the more specific formats ("xhtml1"
and "html4") be used as "xhtml" or "html" may change in the future
- if it makes sense at that time.
+ if it makes sense at that time.
"""
-
+
self.safeMode = safe_mode
self.registeredExtensions = []
self.docType = ""
@@ -300,9 +300,9 @@ class Markdown:
# Map format keys to serializers
self.output_formats = {
- 'html' : html4.to_html_string,
+ 'html' : html4.to_html_string,
'html4' : html4.to_html_string,
- 'xhtml' : etree.tostring,
+ 'xhtml' : etree.tostring,
'xhtml1': etree.tostring,
}
@@ -348,7 +348,8 @@ class Markdown:
self.references.clear()
for extension in self.registeredExtensions:
- extension.reset()
+ if hasattr(extension, 'reset'):
+ extension.reset()
def set_output_format(self, format):
""" Set the output format for the class instance. """
@@ -546,8 +547,8 @@ def load_extension(ext_name, configs = []):
# function called makeExtension()
try:
return module.makeExtension(configs.items())
- except AttributeError:
- message(CRITICAL, "Failed to initiate extension '%s'" % ext_name)
+ except AttributeError, e:
+ message(CRITICAL, "Failed to initiate extension '%s': %s" % (ext_name, e))
def load_extensions(ext_names):
@@ -588,15 +589,15 @@ def markdown(text,
* "xhtml": Outputs latest supported version of XHTML (currently XHTML 1.1).
* "html4": Outputs HTML 4
* "html": Outputs latest supported version of HTML (currently HTML 4).
- Note that it is suggested that the more specific formats ("xhtml1"
+ Note that it is suggested that the more specific formats ("xhtml1"
and "html4") be used as "xhtml" or "html" may change in the future
- if it makes sense at that time.
+ if it makes sense at that time.
Returns: An HTML document as a string.
"""
md = Markdown(extensions=load_extensions(extensions),
- safe_mode=safe_mode,
+ safe_mode=safe_mode,
output_format=output_format)
return md.convert(text)
@@ -608,7 +609,7 @@ def markdownFromFile(input = None,
safe_mode = False,
output_format = DEFAULT_OUTPUT_FORMAT):
"""Read markdown code from a file and write it to a file or a stream."""
- md = Markdown(extensions=load_extensions(extensions),
+ md = Markdown(extensions=load_extensions(extensions),
safe_mode=safe_mode,
output_format=output_format)
md.convertFile(input, output, encoding)
diff --git a/markdown/extensions/codehilite.py b/markdown/extensions/codehilite.py
index c5d496b..b9e1760 100644
--- a/markdown/extensions/codehilite.py
+++ b/markdown/extensions/codehilite.py
@@ -10,9 +10,9 @@ Copyright 2006-2008 [Waylan Limberg](http://achinghead.com/).
Project website: <http://www.freewisdom.org/project/python-markdown/CodeHilite>
Contact: markdown@freewisdom.org
-
+
License: BSD (see ../docs/LICENSE for details)
-
+
Dependencies:
* [Python 2.3+](http://python.org/)
* [Markdown 2.0+](http://www.freewisdom.org/projects/python-markdown/)
@@ -38,41 +38,45 @@ class CodeHilite:
Basic Usage:
>>> code = CodeHilite(src = 'some text')
>>> html = code.hilite()
-
+
* src: Source string or any object with a .readline attribute.
-
+
* linenos: (Boolen) Turn line numbering 'on' or 'off' (off by default).
* css_class: Set class name of wrapper div ('codehilite' by default).
-
+
Low Level Usage:
>>> code = CodeHilite()
>>> code.src = 'some text' # String or anything with a .readline attr.
>>> code.linenos = True # True or False; Turns line numbering on or of.
>>> html = code.hilite()
-
+
"""
- def __init__(self, src=None, linenos=False, css_class="codehilite"):
+ def __init__(self, src=None, linenos=False, css_class="codehilite",
+ lang=None, style='default', noclasses=False):
self.src = src
- self.lang = None
+ self.lang = lang
self.linenos = linenos
self.css_class = css_class
+ self.style = style
+ self.noclasses = noclasses
def hilite(self):
"""
- Pass code to the [Pygments](http://pygments.pocoo.org/) highliter with
- optional line numbers. The output should then be styled with css to
- your liking. No styles are applied by default - only styling hooks
- (i.e.: <span class="k">).
+ Pass code to the [Pygments](http://pygments.pocoo.org/) highliter with
+ optional line numbers. The output should then be styled with css to
+ your liking. No styles are applied by default - only styling hooks
+ (i.e.: <span class="k">).
returns : A string of html.
-
+
"""
self.src = self.src.strip('\n')
-
- self._getLang()
+
+ if self.lang == None:
+ self._getLang()
try:
from pygments import highlight
@@ -96,8 +100,10 @@ class CodeHilite:
lexer = guess_lexer(self.src)
except ValueError:
lexer = TextLexer()
- formatter = HtmlFormatter(linenos=self.linenos,
- cssclass=self.css_class)
+ formatter = HtmlFormatter(linenos=self.linenos,
+ cssclass=self.css_class,
+ style=self.style,
+ noclasses=self.noclasses)
return highlight(self.src, lexer, formatter)
def _escape(self, txt):
@@ -114,8 +120,8 @@ class CodeHilite:
txt = txt.replace('\t', ' '*TAB_LENGTH)
txt = txt.replace(" "*4, "&nbsp; &nbsp; ")
txt = txt.replace(" "*3, "&nbsp; &nbsp;")
- txt = txt.replace(" "*2, "&nbsp; ")
-
+ txt = txt.replace(" "*2, "&nbsp; ")
+
# Add line numbers
lines = txt.splitlines()
txt = '<div class="codehilite"><pre><ol>\n'
@@ -126,31 +132,31 @@ class CodeHilite:
def _getLang(self):
- """
+ """
Determines language of a code block from shebang lines and whether said
line should be removed or left in place. If the sheband line contains a
path (even a single /) then it is assumed to be a real shebang lines and
- left alone. However, if no path is given (e.i.: #!python or :::python)
+ left alone. However, if no path is given (e.i.: #!python or :::python)
then it is assumed to be a mock shebang for language identifitation of a
- code fragment and removed from the code block prior to processing for
- code highlighting. When a mock shebang (e.i: #!python) is found, line
- numbering is turned on. When colons are found in place of a shebang
- (e.i.: :::python), line numbering is left in the current state - off
+ code fragment and removed from the code block prior to processing for
+ code highlighting. When a mock shebang (e.i: #!python) is found, line
+ numbering is turned on. When colons are found in place of a shebang
+ (e.i.: :::python), line numbering is left in the current state - off
by default.
-
+
"""
import re
-
+
#split text into lines
lines = self.src.split("\n")
#pull first line to examine
fl = lines.pop(0)
-
+
c = re.compile(r'''
(?:(?:::+)|(?P<shebang>[#]!)) # Shebang or 2 or more colons.
- (?P<path>(?:/\w+)*[/ ])? # Zero or 1 path
- (?P<lang>[\w+-]*) # The language
+ (?P<path>(?:/\w+)*[/ ])? # Zero or 1 path
+ (?P<lang>[\w+-]*) # The language
''', re.VERBOSE)
# search first line for shebang
m = c.search(fl)
@@ -169,7 +175,7 @@ class CodeHilite:
else:
# No match
lines.insert(0, fl)
-
+
self.src = "\n".join(lines).strip("\n")
@@ -184,14 +190,16 @@ class HiliteTreeprocessor(markdown.treeprocessors.Treeprocessor):
for block in blocks:
children = block.getchildren()
if len(children) == 1 and children[0].tag == 'code':
- code = CodeHilite(children[0].text,
+ code = CodeHilite(children[0].text,
linenos=self.config['force_linenos'][0],
- css_class=self.config['css_class'][0])
- placeholder = self.markdown.htmlStash.store(code.hilite(),
+ css_class=self.config['css_class'][0],
+ style=self.config['pygments_style'][0],
+ noclasses=self.config['noclasses'][0])
+ placeholder = self.markdown.htmlStash.store(code.hilite(),
safe=True)
# Clear codeblock in etree instance
block.clear()
- # Change to p element which will later
+ # Change to p element which will later
# be removed when inserting raw html
block.tag = 'p'
block.text = placeholder
@@ -204,19 +212,23 @@ class CodeHiliteExtension(markdown.Extension):
# define default configs
self.config = {
'force_linenos' : [False, "Force line numbers - Default: False"],
- 'css_class' : ["codehilite",
+ 'css_class' : ["codehilite",
"Set class name for wrapper <div> - Default: codehilite"],
+ 'pygments_style' : ['tango', 'Pygments HTML Formatter Style (Colorscheme) - Default: tango'],
+ 'noclasses': [False, 'Use inline styles instead of CSS classes - Default false']
}
-
+
# Override defaults with user settings
for key, value in configs:
- self.setConfig(key, value)
+ self.setConfig(key, value)
def extendMarkdown(self, md, md_globals):
""" Add HilitePostprocessor to Markdown instance. """
hiliter = HiliteTreeprocessor(md)
hiliter.config = self.config
- md.treeprocessors.add("hilite", hiliter, "_begin")
+ md.treeprocessors.add("hilite", hiliter, "_begin")
+
+ md.registerExtension(self)
def makeExtension(configs={}):
diff --git a/markdown/extensions/fenced_code.py b/markdown/extensions/fenced_code.py
index f16f94c..2b03bbc 100644
--- a/markdown/extensions/fenced_code.py
+++ b/markdown/extensions/fenced_code.py
@@ -62,15 +62,7 @@ Dependencies:
"""
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
+from markdown.extensions.codehilite import CodeHilite, CodeHiliteExtension
# Global vars
FENCED_BLOCK_RE = re.compile( \
@@ -80,32 +72,24 @@ FENCED_BLOCK_RE = re.compile( \
CODE_WRAP = '<pre><code%s>%s</code></pre>'
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.registerExtension(self)
md.preprocessors.add('fenced_code_block',
- FencedBlockPreprocessor(md, self.config),
+ FencedBlockPreprocessor(md),
"_begin")
class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
- def __init__(self, md, config):
+ def __init__(self, md):
markdown.preprocessors.Preprocessor.__init__(self, md)
- self.config = config
+
+ self.checked_for_codehilite = False
+ self.codehilite_conf = {}
def getConfig(self, key):
if key in self.config:
@@ -115,33 +99,36 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
def run(self, lines):
""" Match and store Fenced Code Blocks in the HtmlStash. """
+
+ # Check for code hilite extension
+ if not self.checked_for_codehilite:
+ for ext in self.markdown.registeredExtensions:
+ if isinstance(ext, CodeHiliteExtension):
+ self.codehilite_conf = ext.config
+ break
+
+ self.checked_for_codehilite = True
+
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')
- # 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:
+ # If config is not empty, then the codehighlite extension
+ # is enabled, so we call it to highlite the code
+ if self.codehilite_conf:
+ highliter = CodeHilite(m.group('code'),
+ linenos=self.codehilite_conf['force_linenos'][0],
+ css_class=self.codehilite_conf['css_class'][0],
+ style=self.codehilite_conf['pygments_style'][0],
+ lang=(m.group('lang') if m.group('lang') else None),
+ noclasses=self.codehilite_conf['noclasses'][0])
+
+ code = highliter.hilite()
+ else:
code = CODE_WRAP % (lang, self._escape(m.group('code')))
placeholder = self.markdown.htmlStash.store(code, safe=True)