Index: third_party/Python-Markdown/markdown/extensions/attr_list.py |
diff --git a/third_party/markdown/extensions/attr_list.py b/third_party/Python-Markdown/markdown/extensions/attr_list.py |
similarity index 57% |
copy from third_party/markdown/extensions/attr_list.py |
copy to third_party/Python-Markdown/markdown/extensions/attr_list.py |
index 43482a1d9d79573580b5be5ddefad10b4d1acb50..683bdf831c0d55b3740a4bd8f89d1cbdf9c51caa 100644 |
--- a/third_party/markdown/extensions/attr_list.py |
+++ b/third_party/Python-Markdown/markdown/extensions/attr_list.py |
@@ -1,52 +1,19 @@ |
-# markdown is released under the BSD license |
-# Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later) |
-# Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) |
-# Copyright 2004 Manfred Stienstra (the original version) |
-# |
-# All rights reserved. |
-# |
-# Redistribution and use in source and binary forms, with or without |
-# modification, are permitted provided that the following conditions are met: |
-# |
-# * Redistributions of source code must retain the above copyright |
-# notice, this list of conditions and the following disclaimer. |
-# * Redistributions in binary form must reproduce the above copyright |
-# notice, this list of conditions and the following disclaimer in the |
-# documentation and/or other materials provided with the distribution. |
-# * Neither the name of the <organization> nor the |
-# names of its contributors may be used to endorse or promote products |
-# derived from this software without specific prior written permission. |
-# |
-# THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY |
-# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
-# DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT |
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-# POSSIBILITY OF SUCH DAMAGE. |
- |
- |
""" |
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. |
-Copyright 2011 [Waylan Limberg](http://achinghead.com/). |
+See <https://pythonhosted.org/Markdown/extensions/attr_list.html> |
+for documentation. |
-Contact: markdown@freewisdom.org |
+Original code Copyright 2011 [Waylan Limberg](http://achinghead.com/). |
-License: BSD (see ../LICENSE.md for details) |
+All changes Copyright 2011-2014 The Python Markdown Project |
-Dependencies: |
-* [Python 2.4+](http://python.org) |
-* [Markdown 2.1+](http://packages.python.org/Markdown/) |
+License: [BSD](http://www.opensource.org/licenses/bsd-license.php) |
""" |
@@ -59,21 +26,25 @@ import re |
try: |
Scanner = re.Scanner |
-except AttributeError: |
+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:] |
@@ -84,27 +55,31 @@ def _handle_word(s, t): |
_scanner = Scanner([ |
(r'[^ ]+=".*?"', _handle_double_quote), |
(r"[^ ]+='.*?'", _handle_single_quote), |
- (r'[^ ]+=[^ ]*', _handle_key_value), |
- (r'[^ ]+', _handle_word), |
+ (r'[^ ]+=[^ =]+', _handle_key_value), |
+ (r'[^ =]+', _handle_word), |
(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) |
+ 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): |
@@ -112,10 +87,36 @@ class AttrListTreeprocessor(Treeprocessor): |
if isBlockLevel(elem.tag): |
# Block level: check for attrs on last line of text |
RE = self.BLOCK_RE |
- if isheader(elem): |
- # header: check for attrs at end of line |
+ if isheader(elem) or elem.tag == 'dt': |
+ # header or def-term: check for attrs at end of line |
RE = self.HEADER_RE |
- if len(elem) and elem[-1].tail: |
+ if len(elem) and elem.tag == 'li': |
+ # special case list items. children may include a ul or ol. |
+ pos = None |
+ # find the ul or ol position |
+ for i, child in enumerate(elem): |
+ if child.tag in ['ul', 'ol']: |
+ pos = i |
+ break |
+ if pos is None and elem[-1].tail: |
+ # use tail of last child. no ul or ol. |
+ m = RE.search(elem[-1].tail) |
+ if m: |
+ self.assign_attrs(elem, m.group(1)) |
+ elem[-1].tail = elem[-1].tail[:m.start()] |
+ elif pos is not None and pos > 0 and elem[pos-1].tail: |
+ # use tail of last child before ul or ol |
+ m = RE.search(elem[pos-1].tail) |
+ if m: |
+ self.assign_attrs(elem, m.group(1)) |
+ elem[pos-1].tail = elem[pos-1].tail[:m.start()] |
+ elif elem.text: |
+ # use text. ul is first child. |
+ m = RE.search(elem.text) |
+ if m: |
+ self.assign_attrs(elem, m.group(1)) |
+ elem.text = elem.text[:m.start()] |
+ elif len(elem) and elem[-1].tail: |
# has children. Get from tail of last child |
m = RE.search(elem[-1].tail) |
if m: |
@@ -127,6 +128,8 @@ class AttrListTreeprocessor(Treeprocessor): |
elif elem.text: |
# no children. Get from text. |
m = RE.search(elem.text) |
+ if not m and elem.tag == 'td': |
+ m = re.search(self.BASE_RE, elem.text) |
if m: |
self.assign_attrs(elem, m.group(1)) |
elem.text = elem.text[:m.start()] |
@@ -165,8 +168,10 @@ 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(configs={}): |
- return AttrListExtension(configs=configs) |
+def makeExtension(*args, **kwargs): |
+ return AttrListExtension(*args, **kwargs) |