diff options
Diffstat (limited to 'markdown/extensions')
-rw-r--r-- | markdown/extensions/__init__.py | 33 | ||||
-rw-r--r-- | markdown/extensions/abbr.py | 26 | ||||
-rw-r--r-- | markdown/extensions/admonition.py | 14 | ||||
-rw-r--r-- | markdown/extensions/attr_list.py | 30 | ||||
-rw-r--r-- | markdown/extensions/codehilite.py | 77 | ||||
-rw-r--r-- | markdown/extensions/def_list.py | 14 | ||||
-rw-r--r-- | markdown/extensions/extra.py | 6 | ||||
-rw-r--r-- | markdown/extensions/fenced_code.py | 34 | ||||
-rw-r--r-- | markdown/extensions/footnotes.py | 102 | ||||
-rw-r--r-- | markdown/extensions/headerid.py | 28 | ||||
-rw-r--r-- | markdown/extensions/meta.py | 16 | ||||
-rw-r--r-- | markdown/extensions/nl2br.py | 6 | ||||
-rw-r--r-- | markdown/extensions/sane_lists.py | 9 | ||||
-rw-r--r-- | markdown/extensions/smart_strong.py | 12 | ||||
-rw-r--r-- | markdown/extensions/smarty.py | 76 | ||||
-rw-r--r-- | markdown/extensions/tables.py | 14 | ||||
-rw-r--r-- | markdown/extensions/toc.py | 93 | ||||
-rw-r--r-- | markdown/extensions/wikilinks.py | 31 |
18 files changed, 346 insertions, 275 deletions
diff --git a/markdown/extensions/__init__.py b/markdown/extensions/__init__.py index 03b2a4c..a823fef 100644 --- a/markdown/extensions/__init__.py +++ b/markdown/extensions/__init__.py @@ -7,9 +7,10 @@ from __future__ import unicode_literals from ..util import parseBoolValue import warnings + class Extension(object): """ Base class for extensions to subclass. """ - + # Default config -- to be overriden by a subclass # Must be of the following format: # { @@ -18,7 +19,7 @@ class Extension(object): # Note that Extension.setConfig will raise a KeyError # if a default is not set here. config = {} - + def __init__(self, *args, **kwargs): """ Initiate Extension and set up configs. """ @@ -26,23 +27,26 @@ class Extension(object): # (there only ever used to be one so we use arg[0]) if len(args): self.setConfigs(args[0]) - warnings.warn('Extension classes accepting positional args is pending Deprecation. ' - 'Each setting should be passed into the Class as a keyword. Positional ' - 'args will be deprecated in version 2.6 and raise an error in version ' - '2.7. See the Release Notes for Python-Markdown version 2.5 for more info.', + warnings.warn('Extension classes accepting positional args is ' + 'pending Deprecation. Each setting should be ' + 'passed into the Class as a keyword. Positional ' + 'args will be deprecated in version 2.6 and raise ' + 'an error in version 2.7. See the Release Notes for ' + 'Python-Markdown version 2.5 for more info.', PendingDeprecationWarning) # check for configs kwarg for backward compat. if 'configs' in kwargs.keys(): self.setConfigs(kwargs.pop('configs', {})) - warnings.warn('Extension classes accepting a dict on the single keyword "config" is ' - 'pending Deprecation. Each setting should be passed into the Class as ' - 'a keyword directly. The "config" keyword will be deprecated in version ' - '2.6 and raise an error in version 2.7. See the Release Notes for ' + warnings.warn('Extension classes accepting a dict on the single ' + 'keyword "config" is pending Deprecation. Each ' + 'setting should be passed into the Class as a ' + 'keyword directly. The "config" keyword will be ' + 'deprecated in version 2.6 and raise an error in ' + 'version 2.7. See the Release Notes for ' 'Python-Markdown version 2.5 for more info.', PendingDeprecationWarning) # finally, use kwargs self.setConfigs(kwargs) - def getConfig(self, key, default=''): """ Return a setting for the given key or an empty string. """ @@ -88,6 +92,7 @@ class Extension(object): * md_globals: Global variables in the markdown module namespace. """ - raise NotImplementedError('Extension "%s.%s" must define an "extendMarkdown"' \ - 'method.' % (self.__class__.__module__, self.__class__.__name__)) - + raise NotImplementedError( + 'Extension "%s.%s" must define an "extendMarkdown"' + 'method.' % (self.__class__.__module__, self.__class__.__name__) + ) diff --git a/markdown/extensions/abbr.py b/markdown/extensions/abbr.py index 58dd0aa..353d126 100644 --- a/markdown/extensions/abbr.py +++ b/markdown/extensions/abbr.py @@ -4,7 +4,7 @@ Abbreviation Extension for Python-Markdown This extension adds abbreviation handling to Python-Markdown. -See <https://pythonhosted.org/Markdown/extensions/abbreviations.html> +See <https://pythonhosted.org/Markdown/extensions/abbreviations.html> for documentation. Oringinal code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/) and @@ -12,7 +12,7 @@ Oringinal code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/) and All changes Copyright 2008-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) ''' @@ -27,14 +27,15 @@ import re # Global Vars ABBR_REF_RE = re.compile(r'[*]\[(?P<abbr>[^\]]*)\][ ]?:\s*(?P<title>.*)') + class AbbrExtension(Extension): """ Abbreviation Extension for Python-Markdown. """ def extendMarkdown(self, md, md_globals): """ Insert AbbrPreprocessor before ReferencePreprocessor. """ md.preprocessors.add('abbr', AbbrPreprocessor(md), '<reference') - - + + class AbbrPreprocessor(Preprocessor): """ Abbreviation Preprocessor - parse text for abbr references. """ @@ -42,7 +43,7 @@ class AbbrPreprocessor(Preprocessor): ''' Find and remove all Abbreviation references from the text. Each reference is set as a new AbbrPattern in the markdown instance. - + ''' new_text = [] for line in lines: @@ -50,19 +51,19 @@ class AbbrPreprocessor(Preprocessor): if m: abbr = m.group('abbr').strip() title = m.group('title').strip() - self.markdown.inlinePatterns['abbr-%s'%abbr] = \ + self.markdown.inlinePatterns['abbr-%s' % abbr] = \ AbbrPattern(self._generate_pattern(abbr), title) else: new_text.append(line) return new_text - + def _generate_pattern(self, text): ''' - Given a string, returns an regex pattern to match that string. - - 'HTML' -> r'(?P<abbr>[H][T][M][L])' - - Note: we force each char as a literal match (in brackets) as we don't + Given a string, returns an regex pattern to match that string. + + 'HTML' -> r'(?P<abbr>[H][T][M][L])' + + Note: we force each char as a literal match (in brackets) as we don't know what they will be beforehand. ''' @@ -85,5 +86,6 @@ class AbbrPattern(Pattern): abbr.set('title', self.title) return abbr + def makeExtension(*args, **kwargs): return AbbrExtension(*args, **kwargs) diff --git a/markdown/extensions/admonition.py b/markdown/extensions/admonition.py index 189f2c2..8fe3aee 100644 --- a/markdown/extensions/admonition.py +++ b/markdown/extensions/admonition.py @@ -4,16 +4,16 @@ Admonition extension for Python-Markdown Adds rST-style admonitions. Inspired by [rST][] feature with the same name. -[rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions +[rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions # flake8: noqa -See <https://pythonhosted.org/Markdown/extensions/admonition.html> +See <https://pythonhosted.org/Markdown/extensions/admonition.html> for documentation. Original code Copyright [Tiago Serafim](http://www.tiagoserafim.com/). All changes Copyright The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -46,8 +46,8 @@ class AdmonitionProcessor(BlockProcessor): def test(self, parent, block): sibling = self.lastChild(parent) return self.RE.search(block) or \ - (block.startswith(' ' * self.tab_length) and sibling and \ - sibling.get('class', '').find(self.CLASSNAME) != -1) + (block.startswith(' ' * self.tab_length) and sibling and + sibling.get('class', '').find(self.CLASSNAME) != -1) def run(self, parent, blocks): sibling = self.lastChild(parent) @@ -82,7 +82,8 @@ class AdmonitionProcessor(BlockProcessor): klass, title = match.group(1).lower(), match.group(2) if title is None: # no title was provided, use the capitalized classname as title - # e.g.: `!!! note` will render `<p class="admonition-title">Note</p>` + # e.g.: `!!! note` will render + # `<p class="admonition-title">Note</p>` title = klass.capitalize() elif title == '': # an explicit blank title should not be rendered @@ -93,4 +94,3 @@ class AdmonitionProcessor(BlockProcessor): def makeExtension(*args, **kwargs): return AdmonitionExtension(*args, **kwargs) - diff --git a/markdown/extensions/attr_list.py b/markdown/extensions/attr_list.py index 59da3b4..395259a 100644 --- a/markdown/extensions/attr_list.py +++ b/markdown/extensions/attr_list.py @@ -2,18 +2,18 @@ Attribute List Extension for Python-Markdown ============================================ -Adds attribute list syntax. Inspired by +Adds attribute list syntax. Inspired by [maruku](http://maruku.rubyforge.org/proposal.html#attribute_lists)'s feature of the same name. -See <https://pythonhosted.org/Markdown/extensions/attr_list.html> +See <https://pythonhosted.org/Markdown/extensions/attr_list.html> for documentation. Original code Copyright 2011 [Waylan Limberg](http://achinghead.com/). All changes Copyright 2011-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -26,21 +26,25 @@ import re try: Scanner = re.Scanner -except AttributeError: #pragma: no cover +except AttributeError: # pragma: no cover # must be on Python 2.4 from sre import Scanner + def _handle_double_quote(s, t): k, v = t.split('=') return k, v.strip('"') + def _handle_single_quote(s, t): k, v = t.split('=') return k, v.strip("'") -def _handle_key_value(s, t): + +def _handle_key_value(s, t): return t.split('=') + def _handle_word(s, t): if t.startswith('.'): return '.', t[1:] @@ -56,22 +60,26 @@ _scanner = Scanner([ (r' ', None) ]) + def get_attrs(str): """ Parse attribute list and return a list of attribute tuples. """ return _scanner.scan(str)[0] + def isheader(elem): return elem.tag in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] + class AttrListTreeprocessor(Treeprocessor): - + BASE_RE = r'\{\:?([^\}]*)\}' HEADER_RE = re.compile(r'[ ]+%s[ ]*$' % BASE_RE) BLOCK_RE = re.compile(r'\n[ ]*%s[ ]*$' % BASE_RE) INLINE_RE = re.compile(r'^%s' % BASE_RE) - NAME_RE = re.compile(r'[^A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u0370-\u037d' - r'\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef' - r'\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd' + NAME_RE = re.compile(r'[^A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff' + r'\u0370-\u037d\u037f-\u1fff\u200c-\u200d' + r'\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff' + r'\uf900-\ufdcf\ufdf0-\ufffd' r'\:\-\.0-9\u00b7\u0300-\u036f\u203f-\u2040]+') def run(self, doc): @@ -160,7 +168,9 @@ class AttrListTreeprocessor(Treeprocessor): class AttrListExtension(Extension): def extendMarkdown(self, md, md_globals): - md.treeprocessors.add('attr_list', AttrListTreeprocessor(md), '>prettify') + md.treeprocessors.add( + 'attr_list', AttrListTreeprocessor(md), '>prettify' + ) def makeExtension(*args, **kwargs): diff --git a/markdown/extensions/codehilite.py b/markdown/extensions/codehilite.py index 0c3df7e..211db21 100644 --- a/markdown/extensions/codehilite.py +++ b/markdown/extensions/codehilite.py @@ -4,7 +4,7 @@ CodeHilite Extension for Python-Markdown Adds code/syntax highlighting to standard Python-Markdown code blocks. -See <https://pythonhosted.org/Markdown/extensions/code_hilite.html> +See <https://pythonhosted.org/Markdown/extensions/code_hilite.html> for documentation. Original code Copyright 2006-2008 [Waylan Limberg](http://achinghead.com/). @@ -19,7 +19,7 @@ from __future__ import absolute_import from __future__ import unicode_literals from . import Extension from ..treeprocessors import Treeprocessor -import warnings + try: from pygments import highlight from pygments.lexers import get_lexer_by_name, guess_lexer @@ -47,7 +47,7 @@ def parse_hl_lines(expr): # ------------------ The Main CodeHilite Class ---------------------- class CodeHilite(object): """ - Determine language of source code, and pass it into the pygments hilighter. + Determine language of source code, and pass it into pygments hilighter. Basic Usage: >>> code = CodeHilite(src = 'some text') @@ -55,10 +55,11 @@ class CodeHilite(object): * src: Source string or any object with a .readline attribute. - * linenums: (Boolean) Set line numbering to 'on' (True), 'off' (False) or 'auto'(None). - Set to 'auto' by default. + * linenums: (Boolean) Set line numbering to 'on' (True), + 'off' (False) or 'auto'(None). Set to 'auto' by default. - * guess_lang: (Boolean) Turn language auto-detection 'on' or 'off' (on by default). + * guess_lang: (Boolean) Turn language auto-detection + 'on' or 'off' (on by default). * css_class: Set class name of wrapper div ('codehilite' by default). @@ -67,14 +68,14 @@ class CodeHilite(object): 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. + >>> code.linenos = True # Turns line numbering on or of. >>> html = code.hilite() """ def __init__(self, src=None, linenums=None, guess_lang=True, - css_class="codehilite", lang=None, style='default', - noclasses=False, tab_length=4, hl_lines=None): + css_class="codehilite", lang=None, style='default', + noclasses=False, tab_length=4, hl_lines=None): self.src = src self.lang = lang self.linenums = linenums @@ -132,9 +133,9 @@ class CodeHilite(object): classes.append('linenums') class_str = '' if classes: - class_str = ' class="%s"' % ' '.join(classes) - return '<pre class="%s"><code%s>%s</code></pre>\n'% \ - (self.css_class, class_str, txt) + class_str = ' class="%s"' % ' '.join(classes) + return '<pre class="%s"><code%s>%s</code></pre>\n' % \ + (self.css_class, class_str, txt) def _parseHeader(self): """ @@ -142,8 +143,8 @@ class CodeHilite(object): 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 line and 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 + 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 @@ -156,9 +157,9 @@ class CodeHilite(object): import re - #split text into lines + # split text into lines lines = self.src.split("\n") - #pull first line to examine + # pull first line to examine fl = lines.pop(0) c = re.compile(r''' @@ -192,8 +193,9 @@ class CodeHilite(object): self.src = "\n".join(lines).strip("\n") - # ------------------ The Markdown Extension ------------------------------- + + class HiliteTreeprocessor(Treeprocessor): """ Hilight source code in code blocks. """ @@ -203,13 +205,15 @@ class HiliteTreeprocessor(Treeprocessor): for block in blocks: children = block.getchildren() if len(children) == 1 and children[0].tag == 'code': - code = CodeHilite(children[0].text, - linenums=self.config['linenums'], - guess_lang=self.config['guess_lang'], - css_class=self.config['css_class'], - style=self.config['pygments_style'], - noclasses=self.config['noclasses'], - tab_length=self.markdown.tab_length) + code = CodeHilite( + children[0].text, + linenums=self.config['linenums'], + guess_lang=self.config['guess_lang'], + css_class=self.config['css_class'], + style=self.config['pygments_style'], + noclasses=self.config['noclasses'], + tab_length=self.markdown.tab_length + ) placeholder = self.markdown.htmlStash.store(code.hilite(), safe=True) # Clear codeblock in etree instance @@ -226,13 +230,22 @@ class CodeHiliteExtension(Extension): def __init__(self, *args, **kwargs): # define default configs self.config = { - 'linenums': [None, "Use lines numbers. True=yes, False=no, None=auto"], - 'force_linenos' : [False, "Depreciated! Use 'linenums' instead. Force line numbers - Default: False"], - 'guess_lang' : [True, "Automatic language detection - Default: True"], - 'css_class' : ["codehilite", - "Set class name for wrapper <div> - Default: codehilite"], - 'pygments_style' : ['default', 'Pygments HTML Formatter Style (Colorscheme) - Default: default'], - 'noclasses': [False, 'Use inline styles instead of CSS classes - Default false'] + 'linenums': [None, + "Use lines numbers. True=yes, False=no, None=auto"], + 'force_linenos': [False, + "Depreciated! Use 'linenums' instead. Force " + "line numbers - Default: False"], + 'guess_lang': [True, + "Automatic language detection - Default: True"], + 'css_class': ["codehilite", + "Set class name for wrapper <div> - " + "Default: codehilite"], + 'pygments_style': ['default', + 'Pygments HTML Formatter Style ' + '(Colorscheme) - Default: default'], + 'noclasses': [False, + 'Use inline styles instead of CSS classes - ' + 'Default false'] } super(CodeHiliteExtension, self).__init__(*args, **kwargs) @@ -247,4 +260,4 @@ class CodeHiliteExtension(Extension): def makeExtension(*args, **kwargs): - return CodeHiliteExtension(*args, **kwargs) + return CodeHiliteExtension(*args, **kwargs) diff --git a/markdown/extensions/def_list.py b/markdown/extensions/def_list.py index 22e2491..118b739 100644 --- a/markdown/extensions/def_list.py +++ b/markdown/extensions/def_list.py @@ -4,14 +4,14 @@ Definition List Extension for Python-Markdown Adds parsing of Definition Lists to Python-Markdown. -See <https://pythonhosted.org/Markdown/extensions/definition_lists.html> +See <https://pythonhosted.org/Markdown/extensions/definition_lists.html> for documentation. Original code Copyright 2008 [Waylan Limberg](http://achinghead.com) All changes Copyright 2008-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -36,7 +36,8 @@ class DefListProcessor(BlockProcessor): raw_block = blocks.pop(0) m = self.RE.search(raw_block) - terms = [l.strip() for l in raw_block[:m.start()].split('\n') if l.strip()] + terms = [l.strip() for l in + raw_block[:m.start()].split('\n') if l.strip()] block = raw_block[m.end():] no_indent = self.NO_INDENT_RE.match(block) if no_indent: @@ -49,7 +50,7 @@ class DefListProcessor(BlockProcessor): d = m.group(2) sibling = self.lastChild(parent) if not terms and sibling is None: - # This is not a definition item. Most likely a paragraph that + # This is not a definition item. Most likely a paragraph that # starts with a colon at the begining of a document or list. blocks.insert(0, raw_block) return False @@ -84,6 +85,7 @@ class DefListProcessor(BlockProcessor): if theRest: blocks.insert(0, theRest) + class DefListIndentProcessor(ListIndentProcessor): """ Process indented children of definition list items. """ @@ -94,7 +96,6 @@ class DefListIndentProcessor(ListIndentProcessor): """ Create a new dd and parse the block with it as the parent. """ dd = etree.SubElement(parent, 'dd') self.parser.parseBlocks(dd, [block]) - class DefListExtension(Extension): @@ -105,11 +106,10 @@ class DefListExtension(Extension): md.parser.blockprocessors.add('defindent', DefListIndentProcessor(md.parser), '>indent') - md.parser.blockprocessors.add('deflist', + md.parser.blockprocessors.add('deflist', DefListProcessor(md.parser), '>ulist') def makeExtension(*args, **kwargs): return DefListExtension(*args, **kwargs) - diff --git a/markdown/extensions/extra.py b/markdown/extensions/extra.py index 4044a87..de5db03 100644 --- a/markdown/extensions/extra.py +++ b/markdown/extensions/extra.py @@ -20,12 +20,12 @@ under a differant name. You could also edit the `extensions` global variable defined below, but be aware that such changes may be lost when you upgrade to any future version of Python-Markdown. -See <https://pythonhosted.org/Markdown/extensions/extra.html> +See <https://pythonhosted.org/Markdown/extensions/extra.html> for documentation. Copyright The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -51,7 +51,7 @@ class ExtraExtension(Extension): """ Add various extensions to Markdown class.""" def __init__(self, *args, **kwargs): - """ config is just a dumb holder which gets passed to actual ext later. """ + """ config is a dumb holder which gets passed to actual ext later. """ self.config = kwargs.pop('configs', {}) self.config.update(kwargs) diff --git a/markdown/extensions/fenced_code.py b/markdown/extensions/fenced_code.py index 2aacca6..4af8891 100644 --- a/markdown/extensions/fenced_code.py +++ b/markdown/extensions/fenced_code.py @@ -4,7 +4,7 @@ Fenced Code Extension for Python Markdown This extension adds Fenced Code Blocks to Python-Markdown. -See <https://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html> +See <https://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html> for documentation. Original code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/). @@ -12,7 +12,7 @@ Original code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/). All changes Copyright 2008-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ from __future__ import absolute_import @@ -30,8 +30,8 @@ class FencedCodeExtension(Extension): md.registerExtension(self) md.preprocessors.add('fenced_code_block', - FencedBlockPreprocessor(md), - ">normalize_whitespace") + FencedBlockPreprocessor(md), + ">normalize_whitespace") class FencedBlockPreprocessor(Preprocessor): @@ -75,21 +75,26 @@ class FencedBlockPreprocessor(Preprocessor): # If config is not empty, then the codehighlite extension # is enabled, so we call it to highlight the code if self.codehilite_conf: - highliter = CodeHilite(m.group('code'), - linenums=self.codehilite_conf['linenums'][0], - guess_lang=self.codehilite_conf['guess_lang'][0], - css_class=self.codehilite_conf['css_class'][0], - style=self.codehilite_conf['pygments_style'][0], - lang=(m.group('lang') or None), - noclasses=self.codehilite_conf['noclasses'][0], - hl_lines=parse_hl_lines(m.group('hl_lines'))) + highliter = CodeHilite( + m.group('code'), + linenums=self.codehilite_conf['linenums'][0], + guess_lang=self.codehilite_conf['guess_lang'][0], + css_class=self.codehilite_conf['css_class'][0], + style=self.codehilite_conf['pygments_style'][0], + lang=(m.group('lang') or None), + noclasses=self.codehilite_conf['noclasses'][0], + hl_lines=parse_hl_lines(m.group('hl_lines')) + ) code = highliter.hilite() else: - code = self.CODE_WRAP % (lang, self._escape(m.group('code'))) + code = self.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():]) + text = '%s\n%s\n%s' % (text[:m.start()], + placeholder, + text[m.end():]) else: break return text.split("\n") @@ -105,4 +110,3 @@ class FencedBlockPreprocessor(Preprocessor): def makeExtension(*args, **kwargs): return FencedCodeExtension(*args, **kwargs) - diff --git a/markdown/extensions/footnotes.py b/markdown/extensions/footnotes.py index a59de97..4779f0c 100644 --- a/markdown/extensions/footnotes.py +++ b/markdown/extensions/footnotes.py @@ -4,12 +4,12 @@ Footnotes Extension for Python-Markdown Adds footnote handling to Python-Markdown. -See <https://pythonhosted.org/Markdown/extensions/footnotes.html> +See <https://pythonhosted.org/Markdown/extensions/footnotes.html> for documentation. Copyright The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -25,30 +25,32 @@ from ..odict import OrderedDict import re FN_BACKLINK_TEXT = "zz1337820767766393qq" -NBSP_PLACEHOLDER = "qq3936677670287331zz" +NBSP_PLACEHOLDER = "qq3936677670287331zz" DEF_RE = re.compile(r'[ ]{0,3}\[\^([^\]]*)\]:\s*(.*)') TABBED_RE = re.compile(r'((\t)|( ))(.*)') + class FootnoteExtension(Extension): """ Footnote Extension. """ - def __init__ (self, *args, **kwargs): + def __init__(self, *args, **kwargs): """ Setup configs. """ self.config = { 'PLACE_MARKER': - ["///Footnotes Go Here///", - "The text string that marks where the footnotes go"], + ["///Footnotes Go Here///", + "The text string that marks where the footnotes go"], 'UNIQUE_IDS': - [False, - "Avoid name collisions across " - "multiple calls to reset()."], + [False, + "Avoid name collisions across " + "multiple calls to reset()."], "BACKLINK_TEXT": - ["↩", - "The text string that links from the footnote to the reader's place."] + ["↩", + "The text string that links from the footnote " + "to the reader's place."] } super(FootnoteExtension, self).__init__(*args, **kwargs) - + # In multiple invocations, emit links that don't get tangled. self.unique_prefix = 0 @@ -60,23 +62,27 @@ class FootnoteExtension(Extension): self.parser = md.parser self.md = md # Insert a preprocessor before ReferencePreprocessor - md.preprocessors.add("footnote", FootnotePreprocessor(self), - "<reference") + md.preprocessors.add( + "footnote", FootnotePreprocessor(self), "<reference" + ) # Insert an inline pattern before ImageReferencePattern - FOOTNOTE_RE = r'\[\^([^\]]*)\]' # blah blah [^1] blah - md.inlinePatterns.add("footnote", FootnotePattern(FOOTNOTE_RE, self), - "<reference") + FOOTNOTE_RE = r'\[\^([^\]]*)\]' # blah blah [^1] blah + md.inlinePatterns.add( + "footnote", FootnotePattern(FOOTNOTE_RE, self), "<reference" + ) # Insert a tree-processor that would actually add the footnote div - # This must be before all other treeprocessors (i.e., inline and + # This must be before all other treeprocessors (i.e., inline and # codehilite) so they can run on the the contents of the div. - md.treeprocessors.add("footnote", FootnoteTreeprocessor(self), - "_begin") + md.treeprocessors.add( + "footnote", FootnoteTreeprocessor(self), "_begin" + ) # Insert a postprocessor after amp_substitute oricessor - md.postprocessors.add("footnote", FootnotePostprocessor(self), - ">amp_substitute") + md.postprocessors.add( + "footnote", FootnotePostprocessor(self), ">amp_substitute" + ) def reset(self): - """ Clear the footnotes on reset, and prepare for a distinct document. """ + """ Clear footnotes on reset, and prepare for distinct document. """ self.footnotes = OrderedDict() self.unique_prefix += 1 @@ -92,7 +98,7 @@ class FootnoteExtension(Extension): return child, element, False finder(child) return None - + res = finder(root) return res @@ -115,7 +121,8 @@ class FootnoteExtension(Extension): def makeFootnoteRefId(self, id): """ Return footnote back-link id. """ if self.getConfig("UNIQUE_IDS"): - return 'fnref%s%d-%s' % (self.get_separator(), self.unique_prefix, id) + return 'fnref%s%d-%s' % (self.get_separator(), + self.unique_prefix, id) else: return 'fnref%s%s' % (self.get_separator(), id) @@ -137,10 +144,13 @@ class FootnoteExtension(Extension): backlink = etree.Element("a") backlink.set("href", "#" + self.makeFootnoteRefId(id)) if self.md.output_format not in ['html5', 'xhtml5']: - backlink.set("rev", "footnote") # Invalid in HTML5 + backlink.set("rev", "footnote") # Invalid in HTML5 backlink.set("class", "footnote-backref") - backlink.set("title", "Jump back to footnote %d in the text" % \ - (self.footnotes.index(id)+1)) + backlink.set( + "title", + "Jump back to footnote %d in the text" % + (self.footnotes.index(id)+1) + ) backlink.text = FN_BACKLINK_TEXT if li.getchildren(): @@ -157,7 +167,7 @@ class FootnoteExtension(Extension): class FootnotePreprocessor(Preprocessor): """ Find all footnote references and store for later use. """ - def __init__ (self, footnotes): + def __init__(self, footnotes): self.footnotes = footnotes def run(self, lines): @@ -178,7 +188,7 @@ class FootnotePreprocessor(Preprocessor): if m: fn, _i = self.detectTabbed(lines[i+1:]) fn.insert(0, m.group(2)) - i += _i-1 # skip past footnote + i += _i-1 # skip past footnote self.footnotes.setFootnote(m.group(1), "\n".join(fn)) else: newlines.append(lines[i]) @@ -199,16 +209,16 @@ class FootnotePreprocessor(Preprocessor): """ items = [] - blank_line = False # have we encountered a blank line yet? - i = 0 # to keep track of where we are + blank_line = False # have we encountered a blank line yet? + i = 0 # to keep track of where we are def detab(line): match = TABBED_RE.match(line) if match: - return match.group(4) + return match.group(4) for line in lines: - if line.strip(): # Non-blank line + if line.strip(): # Non-blank line detabbed_line = detab(line) if detabbed_line: items.append(detabbed_line) @@ -222,23 +232,24 @@ class FootnotePreprocessor(Preprocessor): else: return items, i+1 - else: # Blank line: _maybe_ we are done. + else: # Blank line: _maybe_ we are done. blank_line = True - i += 1 # advance + i += 1 # advance # Find the next non-blank line for j in range(i, len(lines)): if lines[j].strip(): - next_line = lines[j]; break + next_line = lines[j] + break else: - break # There is no more text; we are done. + break # There is no more text; we are done. # Check if the next non-blank line is tabbed - if detab(next_line): # Yes, more work to do. + if detab(next_line): # Yes, more work to do. items.append("") continue else: - break # No, we are done. + break # No, we are done. else: i += 1 @@ -260,7 +271,7 @@ class FootnotePattern(Pattern): sup.set('id', self.footnotes.makeFootnoteRefId(id)) a.set('href', '#' + self.footnotes.makeFootnoteId(id)) if self.footnotes.md.output_format not in ['html5', 'xhtml5']: - a.set('rel', 'footnote') # invalid in HTML5 + a.set('rel', 'footnote') # invalid in HTML5 a.set('class', 'footnote-ref') a.text = text_type(self.footnotes.footnotes.index(id) + 1) return sup @@ -271,7 +282,7 @@ class FootnotePattern(Pattern): class FootnoteTreeprocessor(Treeprocessor): """ Build and append footnote div to end of document. """ - def __init__ (self, footnotes): + def __init__(self, footnotes): self.footnotes = footnotes def run(self, root): @@ -290,16 +301,19 @@ class FootnoteTreeprocessor(Treeprocessor): else: root.append(footnotesDiv) + class FootnotePostprocessor(Postprocessor): """ Replace placeholders with html entities. """ def __init__(self, footnotes): self.footnotes = footnotes def run(self, text): - text = text.replace(FN_BACKLINK_TEXT, self.footnotes.getConfig("BACKLINK_TEXT")) + text = text.replace( + FN_BACKLINK_TEXT, self.footnotes.getConfig("BACKLINK_TEXT") + ) return text.replace(NBSP_PLACEHOLDER, " ") + def makeExtension(*args, **kwargs): """ Return an instance of the FootnoteExtension """ return FootnoteExtension(*args, **kwargs) - diff --git a/markdown/extensions/headerid.py b/markdown/extensions/headerid.py index f7b7805..c9f2a21 100644 --- a/markdown/extensions/headerid.py +++ b/markdown/extensions/headerid.py @@ -4,14 +4,14 @@ HeaderID Extension for Python-Markdown Auto-generate id attributes for HTML headers. -See <https://pythonhosted.org/Markdown/extensions/header_id.html> +See <https://pythonhosted.org/Markdown/extensions/header_id.html> for documentation. Original code Copyright 2007-2011 [Waylan Limberg](http://achinghead.com/). All changes Copyright 2011-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -41,18 +41,18 @@ def unique(id, ids): while id in ids or not id: m = IDCOUNT_RE.match(id) if m: - id = '%s_%d'% (m.group(1), int(m.group(2))+1) + id = '%s_%d' % (m.group(1), int(m.group(2))+1) else: - id = '%s_%d'% (id, 1) + id = '%s_%d' % (id, 1) ids.add(id) return id def itertext(elem): - """ Loop through all children and return text only. - + """ Loop through all children and return text only. + Reimplements method of same name added to ElementTree in Python 2.7 - + """ if elem.text: yield elem.text @@ -103,7 +103,6 @@ class HeaderIdTreeprocessor(Treeprocessor): level = 6 elem.tag = 'h%d' % level - def _get_meta(self): """ Return meta data suported by this ext as a tuple """ level = int(self.config['level']) - 1 @@ -111,7 +110,7 @@ class HeaderIdTreeprocessor(Treeprocessor): if hasattr(self.md, 'Meta'): if 'header_level' in self.md.Meta: level = int(self.md.Meta['header_level'][0]) - 1 - if 'header_forceid' in self.md.Meta: + if 'header_forceid' in self.md.Meta: force = parseBoolValue(self.md.Meta['header_forceid'][0]) return level, force @@ -120,11 +119,11 @@ class HeaderIdExtension(Extension): def __init__(self, *args, **kwargs): # set defaults self.config = { - 'level' : ['1', 'Base level for headers.'], - 'forceid' : ['True', 'Force all headers to have an id.'], - 'separator' : ['-', 'Word separator.'], - 'slugify' : [slugify, 'Callable to generate anchors'], - } + 'level': ['1', 'Base level for headers.'], + 'forceid': ['True', 'Force all headers to have an id.'], + 'separator': ['-', 'Word separator.'], + 'slugify': [slugify, 'Callable to generate anchors'] + } super(HeaderIdExtension, self).__init__(*args, **kwargs) @@ -146,4 +145,3 @@ class HeaderIdExtension(Extension): def makeExtension(*args, **kwargs): return HeaderIdExtension(*args, **kwargs) - diff --git a/markdown/extensions/meta.py b/markdown/extensions/meta.py index bcc25a0..a733a8a 100644 --- a/markdown/extensions/meta.py +++ b/markdown/extensions/meta.py @@ -4,14 +4,14 @@ Meta Data Extension for Python-Markdown This extension adds Meta Data handling to markdown. -See <https://pythonhosted.org/Markdown/extensions/meta_data.html> +See <https://pythonhosted.org/Markdown/extensions/meta_data.html> for documentation. Original code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com). All changes Copyright 2008-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -25,13 +25,16 @@ import re META_RE = re.compile(r'^[ ]{0,3}(?P<key>[A-Za-z0-9_-]+):\s*(?P<value>.*)') META_MORE_RE = re.compile(r'^[ ]{4,}(?P<value>.*)') + class MetaExtension (Extension): """ Meta-Data extension for Python-Markdown. """ def extendMarkdown(self, md, md_globals): """ Add MetaPreprocessor to Markdown instance. """ - md.preprocessors.add("meta", MetaPreprocessor(md), ">normalize_whitespace") + md.preprocessors.add( + "meta", MetaPreprocessor(md), ">normalize_whitespace" + ) class MetaPreprocessor(Preprocessor): @@ -44,7 +47,7 @@ class MetaPreprocessor(Preprocessor): while lines: line = lines.pop(0) if line.strip() == '': - break # blank line - done + break # blank line - done m1 = META_RE.match(line) if m1: key = m1.group('key').lower().strip() @@ -60,11 +63,10 @@ class MetaPreprocessor(Preprocessor): meta[key].append(m2.group('value').strip()) else: lines.insert(0, line) - break # no meta data - done + break # no meta data - done self.markdown.Meta = meta return lines - + def makeExtension(*args, **kwargs): return MetaExtension(*args, **kwargs) - diff --git a/markdown/extensions/nl2br.py b/markdown/extensions/nl2br.py index 062a7e6..8acd60c 100644 --- a/markdown/extensions/nl2br.py +++ b/markdown/extensions/nl2br.py @@ -5,14 +5,14 @@ NL2BR Extension A Python-Markdown extension to treat newlines as hard breaks; like GitHub-flavored Markdown does. -See <https://pythonhosted.org/Markdown/extensions/nl2br.html> +See <https://pythonhosted.org/Markdown/extensions/nl2br.html> for documentation. Oringinal code Copyright 2011 [Brian Neal](http://deathofagremmie.com/) All changes Copyright 2011-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -23,6 +23,7 @@ from ..inlinepatterns import SubstituteTagPattern BR_RE = r'\n' + class Nl2BrExtension(Extension): def extendMarkdown(self, md, md_globals): @@ -32,4 +33,3 @@ class Nl2BrExtension(Extension): def makeExtension(*args, **kwargs): return Nl2BrExtension(*args, **kwargs) - diff --git a/markdown/extensions/sane_lists.py b/markdown/extensions/sane_lists.py index 9eb3a11..213c8a6 100644 --- a/markdown/extensions/sane_lists.py +++ b/markdown/extensions/sane_lists.py @@ -4,14 +4,14 @@ Sane List Extension for Python-Markdown Modify the behavior of Lists in Python-Markdown to act in a sane manor. -See <https://pythonhosted.org/Markdown/extensions/sane_lists.html> +See <https://pythonhosted.org/Markdown/extensions/sane_lists.html> for documentation. Original code Copyright 2011 [Waylan Limberg](http://achinghead.com) All changes Copyright 2011-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -23,13 +23,13 @@ import re class SaneOListProcessor(OListProcessor): - + CHILD_RE = re.compile(r'^[ ]{0,3}((\d+\.))[ ]+(.*)') SIBLING_TAGS = ['ol'] class SaneUListProcessor(UListProcessor): - + CHILD_RE = re.compile(r'^[ ]{0,3}(([*+-]))[ ]+(.*)') SIBLING_TAGS = ['ul'] @@ -45,4 +45,3 @@ class SaneListExtension(Extension): def makeExtension(*args, **kwargs): return SaneListExtension(*args, **kwargs) - diff --git a/markdown/extensions/smart_strong.py b/markdown/extensions/smart_strong.py index 331dae8..58570bb 100644 --- a/markdown/extensions/smart_strong.py +++ b/markdown/extensions/smart_strong.py @@ -4,14 +4,14 @@ Smart_Strong Extension for Python-Markdown This extention adds smarter handling of double underscores within words. -See <https://pythonhosted.org/Markdown/extensions/smart_strong.html> +See <https://pythonhosted.org/Markdown/extensions/smart_strong.html> for documentation. Original code Copyright 2011 [Waylan Limberg](http://achinghead.com) All changes Copyright 2011-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) ''' @@ -23,13 +23,19 @@ from ..inlinepatterns import SimpleTagPattern SMART_STRONG_RE = r'(?<!\w)(_{2})(?!_)(.+?)(?<!_)\2(?!\w)' STRONG_RE = r'(\*{2})(.+?)\2' + class SmartEmphasisExtension(Extension): """ Add smart_emphasis extension to Markdown class.""" def extendMarkdown(self, md, md_globals): """ Modify inline patterns. """ md.inlinePatterns['strong'] = SimpleTagPattern(STRONG_RE, 'strong') - md.inlinePatterns.add('strong2', SimpleTagPattern(SMART_STRONG_RE, 'strong'), '>emphasis2') + md.inlinePatterns.add( + 'strong2', + SimpleTagPattern(SMART_STRONG_RE, 'strong'), + '>emphasis2' + ) + def makeExtension(*args, **kwargs): return SmartEmphasisExtension(*args, **kwargs) diff --git a/markdown/extensions/smarty.py b/markdown/extensions/smarty.py index 00c330f..3d79061 100644 --- a/markdown/extensions/smarty.py +++ b/markdown/extensions/smarty.py @@ -3,17 +3,17 @@ Smarty extension for Python-Markdown ==================================== -Adds conversion of ASCII dashes, quotes and ellipses to their HTML +Adds conversion of ASCII dashes, quotes and ellipses to their HTML entity equivalents. -See <https://pythonhosted.org/Markdown/extensions/smarty.html> +See <https://pythonhosted.org/Markdown/extensions/smarty.html> for documentation. Author: 2013, Dmitry Shachnev <mitya57@gmail.com> All changes Copyright 2013-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) SmartyPants license: @@ -32,7 +32,7 @@ SmartyPants license: the documentation and/or other materials provided with the distribution. - * Neither the name "SmartyPants" nor the names of its contributors + * Neither the name "SmartyPants" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -86,7 +86,7 @@ from . import Extension from ..inlinepatterns import HtmlPattern from ..odict import OrderedDict from ..treeprocessors import InlineProcessor -from ..util import parseBoolValue + # Constants for quote education. punctClass = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]""" @@ -94,14 +94,14 @@ endOfWordClass = r"[\s.,;:!?)]" closeClass = "[^\ \t\r\n\[\{\(\-\u0002\u0003]" openingQuotesBase = ( - '(\s' # a whitespace char - '| ' # or a non-breaking space entity - '|--' # or dashes - '|–|—' # or unicode - '|&[mn]dash;' # or named dash entities - '|–|—' # or decimal entities - ')' -) + '(\s' # a whitespace char + '| ' # or a non-breaking space entity + '|--' # or dashes + '|–|—' # or unicode + '|&[mn]dash;' # or named dash entities + '|–|—' # or decimal entities + ')' +) substitutions = { 'mdash': '—', @@ -137,13 +137,14 @@ closingDoubleQuotesRegex2 = '(?<=%s)"' % closeClass openingSingleQuotesRegex = r"%s'(?=\w)" % openingQuotesBase # Single closing quotes: -closingSingleQuotesRegex = r"(?<=%s)'(?!\s|s\b|\d)" % closeClass +closingSingleQuotesRegex = r"(?<=%s)'(?!\s|s\b|\d)" % closeClass closingSingleQuotesRegex2 = r"(?<=%s)'(\s|s\b)" % closeClass # All remaining quotes should be opening ones remainingSingleQuotesRegex = "'" remainingDoubleQuotesRegex = '"' + class SubstituteTextPattern(HtmlPattern): def __init__(self, pattern, replace, markdown_instance): """ Replaces matches with some text. """ @@ -160,6 +161,7 @@ class SubstituteTextPattern(HtmlPattern): result += self.markdown.htmlStash.store(part, safe=True) return result + class SmartyExtension(Extension): def __init__(self, *args, **kwargs): self.config = { @@ -167,7 +169,7 @@ class SmartyExtension(Extension): 'smart_angled_quotes': [False, 'Educate angled quotes'], 'smart_dashes': [True, 'Educate dashes'], 'smart_ellipses': [True, 'Educate ellipses'], - 'substitutions' : [{}, 'Overwrite default substitutions'], + 'substitutions': [{}, 'Overwrite default substitutions'], } super(SmartyExtension, self).__init__(*args, **kwargs) self.substitutions = dict(substitutions) @@ -182,31 +184,40 @@ class SmartyExtension(Extension): self.inlinePatterns.add(name, pattern, after) def educateDashes(self, md): - emDashesPattern = SubstituteTextPattern(r'(?<!-)---(?!-)', - (self.substitutions['mdash'],), md) - enDashesPattern = SubstituteTextPattern(r'(?<!-)--(?!-)', - (self.substitutions['ndash'],), md) + emDashesPattern = SubstituteTextPattern( + r'(?<!-)---(?!-)', (self.substitutions['mdash'],), md + ) + enDashesPattern = SubstituteTextPattern( + r'(?<!-)--(?!-)', (self.substitutions['ndash'],), md + ) self.inlinePatterns.add('smarty-em-dashes', emDashesPattern, '_begin') - self.inlinePatterns.add('smarty-en-dashes', enDashesPattern, - '>smarty-em-dashes') + self.inlinePatterns.add( + 'smarty-en-dashes', enDashesPattern, '>smarty-em-dashes' + ) def educateEllipses(self, md): - ellipsesPattern = SubstituteTextPattern(r'(?<!\.)\.{3}(?!\.)', - (self.substitutions['ellipsis'],), md) + ellipsesPattern = SubstituteTextPattern( + r'(?<!\.)\.{3}(?!\.)', (self.substitutions['ellipsis'],), md + ) self.inlinePatterns.add('smarty-ellipses', ellipsesPattern, '_begin') def educateAngledQuotes(self, md): - leftAngledQuotePattern = SubstituteTextPattern(r'\<\<', - (self.substitutions['left-angle-quote'],), md) - rightAngledQuotePattern = SubstituteTextPattern(r'\>\>', - (self.substitutions['right-angle-quote'],), md) - self.inlinePatterns.add('smarty-left-angle-quotes', - leftAngledQuotePattern, '_begin') - self.inlinePatterns.add('smarty-right-angle-quotes', - rightAngledQuotePattern, '>smarty-left-angle-quotes') + leftAngledQuotePattern = SubstituteTextPattern( + r'\<\<', (self.substitutions['left-angle-quote'],), md + ) + rightAngledQuotePattern = SubstituteTextPattern( + r'\>\>', (self.substitutions['right-angle-quote'],), md + ) + self.inlinePatterns.add( + 'smarty-left-angle-quotes', leftAngledQuotePattern, '_begin' + ) + self.inlinePatterns.add( + 'smarty-right-angle-quotes', + rightAngledQuotePattern, + '>smarty-left-angle-quotes' + ) def educateQuotes(self, md): - configs = self.getConfigs() lsquo = self.substitutions['left-single-quote'] rsquo = self.substitutions['right-single-quote'] ldquo = self.substitutions['left-double-quote'] @@ -243,5 +254,6 @@ class SmartyExtension(Extension): md.treeprocessors.add('smarty', inlineProcessor, '_end') md.ESCAPED_CHARS.extend(['"', "'"]) + def makeExtension(*args, **kwargs): return SmartyExtension(*args, **kwargs) diff --git a/markdown/extensions/tables.py b/markdown/extensions/tables.py index 57507e9..cbf711a 100644 --- a/markdown/extensions/tables.py +++ b/markdown/extensions/tables.py @@ -4,7 +4,7 @@ Tables Extension for Python-Markdown Added parsing of tables to Python-Markdown. -See <https://pythonhosted.org/Markdown/extensions/tables.html> +See <https://pythonhosted.org/Markdown/extensions/tables.html> for documentation. Original code Copyright 2009 [Waylan Limberg](http://achinghead.com) @@ -21,13 +21,14 @@ from . import Extension from ..blockprocessors import BlockProcessor from ..util import etree + class TableProcessor(BlockProcessor): """ Process Tables. """ def test(self, parent, block): rows = block.split('\n') - return (len(rows) > 2 and '|' in rows[0] and - '|' in rows[1] and '-' in rows[1] and + return (len(rows) > 2 and '|' in rows[0] and + '|' in rows[1] and '-' in rows[1] and rows[1].strip()[0] in ['|', ':', '-']) def run(self, parent, blocks): @@ -66,13 +67,13 @@ class TableProcessor(BlockProcessor): if parent.tag == 'thead': tag = 'th' cells = self._split_row(row, border) - # We use align here rather than cells to ensure every row + # We use align here rather than cells to ensure every row # contains the same number of columns. for i, a in enumerate(align): c = etree.SubElement(tr, tag) try: c.text = cells[i].strip() - except IndexError: #pragma: no cover + except IndexError: # pragma: no cover c.text = "" if a: c.set('align', a) @@ -92,11 +93,10 @@ class TableExtension(Extension): def extendMarkdown(self, md, md_globals): """ Add an instance of TableProcessor to BlockParser. """ - md.parser.blockprocessors.add('table', + md.parser.blockprocessors.add('table', TableProcessor(md.parser), '<hashheader') def makeExtension(*args, **kwargs): return TableExtension(*args, **kwargs) - diff --git a/markdown/extensions/toc.py b/markdown/extensions/toc.py index f7fb675..99542ed 100644 --- a/markdown/extensions/toc.py +++ b/markdown/extensions/toc.py @@ -2,14 +2,14 @@ Table of Contents Extension for Python-Markdown =============================================== -See <https://pythonhosted.org/Markdown/extensions/toc.html> +See <https://pythonhosted.org/Markdown/extensions/toc.html> for documentation. Oringinal code Copyright 2008 [Jack Miller](http://codezen.org) All changes Copyright 2008-2014 The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) """ @@ -68,9 +68,11 @@ def order_toc_list(toc_list): # Note current level as last levels.append(current_level) - # Level is the same, so append to the current parent (if available) + # Level is the same, so append to + # the current parent (if available) if current_level == levels[-1]: - (parents[-1]['children'] if parents else ordered_list).append(t) + (parents[-1]['children'] if parents + else ordered_list).append(t) # Current level is > last item's level, # So make last item a parent and append current as child @@ -84,14 +86,14 @@ def order_toc_list(toc_list): class TocTreeprocessor(Treeprocessor): - + # Iterator wrapper to get parent and child all at once def iterparent(self, root): for parent in root.getiterator(): for child in parent: yield parent, child - - def add_anchor(self, c, elem_id): #@ReservedAssignment + + def add_anchor(self, c, elem_id): # @ReservedAssignment anchor = etree.Element("a") anchor.text = c.text anchor.attrib["href"] = "#" + elem_id @@ -105,12 +107,13 @@ class TocTreeprocessor(Treeprocessor): def add_permalink(self, c, elem_id): permalink = etree.Element("a") permalink.text = ("%spara;" % AMP_SUBSTITUTE - if self.use_permalinks is True else self.use_permalinks) + if self.use_permalinks is True + else self.use_permalinks) permalink.attrib["href"] = "#" + elem_id permalink.attrib["class"] = "headerlink" permalink.attrib["title"] = "Permanent link" c.append(permalink) - + def build_toc_etree(self, div, toc_list): # Add title to the div if self.config["title"]: @@ -129,20 +132,20 @@ class TocTreeprocessor(Treeprocessor): if item['children']: build_etree_ul(item['children'], li) return ul - + return build_etree_ul(toc_list, div) - + def run(self, doc): div = etree.Element("div") div.attrib["class"] = "toc" header_rgx = re.compile("[Hh][123456]") - + self.use_anchors = parseBoolValue(self.config["anchorlink"]) self.use_permalinks = parseBoolValue(self.config["permalink"], False) if self.use_permalinks is None: self.use_permalinks = self.config["permalink"] - + # Get a list of id attributes used_ids = set() for c in doc.getiterator(): @@ -160,7 +163,7 @@ class TocTreeprocessor(Treeprocessor): # validation by putting a <div> inside of a <p> # we actually replace the <p> in its entirety. # We do not allow the marker inside a header as that - # would causes an enless loop of placing a new TOC + # would causes an enless loop of placing a new TOC # inside previously generated TOC. if c.text and c.text.strip() == self.config["marker"] and \ not header_rgx.match(c.tag) and c.tag not in ['pre', 'code']: @@ -169,32 +172,34 @@ class TocTreeprocessor(Treeprocessor): p[i] = div break marker_found = True - + if header_rgx.match(c.tag): - - # Do not override pre-existing ids - if not "id" in c.attrib: + + # Do not override pre-existing ids + if "id" not in c.attrib: elem_id = stashedHTML2text(text, self.markdown) - elem_id = unique(self.config["slugify"](elem_id, '-'), used_ids) + elem_id = unique(self.config["slugify"](elem_id, '-'), + used_ids) c.attrib["id"] = elem_id else: elem_id = c.attrib["id"] tag_level = int(c.tag[-1]) - + toc_list.append({'level': tag_level, - 'id': elem_id, - 'name': text}) + 'id': elem_id, + 'name': text}) if self.use_anchors: self.add_anchor(c, elem_id) if self.use_permalinks: self.add_permalink(c, elem_id) - + toc_list_nested = order_toc_list(toc_list) self.build_toc_etree(div, toc_list_nested) prettify = self.markdown.treeprocessors.get('prettify') - if prettify: prettify.run(div) + if prettify: + prettify.run(div) if not marker_found: # serialize and attach to markdown instance. toc = self.markdown.serializer(div) @@ -204,26 +209,26 @@ class TocTreeprocessor(Treeprocessor): class TocExtension(Extension): - + TreeProcessorClass = TocTreeprocessor - + def __init__(self, *args, **kwargs): - self.config = { - "marker" : ["[TOC]", - "Text to find and replace with Table of Contents - " - "Defaults to \"[TOC]\""], - "slugify" : [slugify, - "Function to generate anchors based on header text - " - "Defaults to the headerid ext's slugify function."], - "title" : ["", - "Title to insert into TOC <div> - " - "Defaults to an empty string"], - "anchorlink" : [0, - "1 if header should be a self link - " - "Defaults to 0"], - "permalink" : [0, - "1 or link text if a Sphinx-style permalink should be added - " - "Defaults to 0"] + self.config = { + "marker": ["[TOC]", + "Text to find and replace with Table of Contents - " + "Defaults to \"[TOC]\""], + "slugify": [slugify, + "Function to generate anchors based on header text - " + "Defaults to the headerid ext's slugify function."], + "title": ["", + "Title to insert into TOC <div> - " + "Defaults to an empty string"], + "anchorlink": [0, + "1 if header should be a self link - " + "Defaults to 0"], + "permalink": [0, + "1 or link text if a Sphinx-style permalink should " + "be added - Defaults to 0"] } super(TocExtension, self).__init__(*args, **kwargs) @@ -232,8 +237,8 @@ class TocExtension(Extension): tocext = self.TreeProcessorClass(md) tocext.config = self.getConfigs() # Headerid ext is set to '>prettify'. With this set to '_end', - # it should always come after headerid ext (and honor ids assinged - # by the header id extension) if both are used. Same goes for + # it should always come after headerid ext (and honor ids assinged + # by the header id extension) if both are used. Same goes for # attr_list extension. This must come last because we don't want # to redefine ids after toc is created. But we do want toc prettified. md.treeprocessors.add("toc", tocext, "_end") diff --git a/markdown/extensions/wikilinks.py b/markdown/extensions/wikilinks.py index 64377cf..94e1b67 100644 --- a/markdown/extensions/wikilinks.py +++ b/markdown/extensions/wikilinks.py @@ -4,14 +4,14 @@ WikiLinks Extension for Python-Markdown Converts [[WikiLinks]] to relative links. -See <https://pythonhosted.org/Markdown/extensions/wikilinks.html> +See <https://pythonhosted.org/Markdown/extensions/wikilinks.html> for documentation. Original code Copyright [Waylan Limberg](http://achinghead.com/). All changes Copyright The Python Markdown Project -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) +License: [BSD](http://www.opensource.org/licenses/bsd-license.php) ''' @@ -22,27 +22,28 @@ from ..inlinepatterns import Pattern from ..util import etree import re + def build_url(label, base, end): """ Build a url from the label, a base, and an end. """ clean_label = re.sub(r'([ ]+_)|(_[ ]+)|([ ]+)', '_', label) - return '%s%s%s'% (base, clean_label, end) + return '%s%s%s' % (base, clean_label, end) class WikiLinkExtension(Extension): - def __init__ (self, *args, **kwargs): + def __init__(self, *args, **kwargs): self.config = { - 'base_url' : ['/', 'String to append to beginning or URL.'], - 'end_url' : ['/', 'String to append to end of URL.'], - 'html_class' : ['wikilink', 'CSS hook. Leave blank for none.'], - 'build_url' : [build_url, 'Callable formats URL from label.'], + 'base_url': ['/', 'String to append to beginning or URL.'], + 'end_url': ['/', 'String to append to end of URL.'], + 'html_class': ['wikilink', 'CSS hook. Leave blank for none.'], + 'build_url': [build_url, 'Callable formats URL from label.'], } - + super(WikiLinkExtension, self).__init__(*args, **kwargs) - + def extendMarkdown(self, md, md_globals): self.md = md - + # append to end of inline patterns WIKILINK_RE = r'\[\[([\w0-9_ -]+)\]\]' wikilinkPattern = WikiLinks(WIKILINK_RE, self.getConfigs()) @@ -54,14 +55,14 @@ class WikiLinks(Pattern): def __init__(self, pattern, config): super(WikiLinks, self).__init__(pattern) self.config = config - + def handleMatch(self, m): if m.group(2).strip(): base_url, end_url, html_class = self._getMeta() label = m.group(2).strip() url = self.config['build_url'](label, base_url, end_url) a = etree.Element('a') - a.text = label + a.text = label a.set('href', url) if html_class: a.set('class', html_class) @@ -82,7 +83,7 @@ class WikiLinks(Pattern): if 'wiki_html_class' in self.md.Meta: html_class = self.md.Meta['wiki_html_class'][0] return base_url, end_url, html_class - -def makeExtension(*args, **kwargs) : + +def makeExtension(*args, **kwargs): return WikiLinkExtension(*args, **kwargs) |