Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: third_party/Python-Markdown/markdown/extensions/attr_list.py

Issue 1356203004: Check in a simple pure-python based Markdown previewer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@add
Patch Set: fix license file Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # markdown is released under the BSD license
2 # Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
3 # Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
4 # Copyright 2004 Manfred Stienstra (the original version)
5 #
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # * Neither the name of the <organization> nor the
17 # names of its contributors may be used to endorse or promote products
18 # derived from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY
21 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 # DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT
24 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 # POSSIBILITY OF SUCH DAMAGE.
31
32
33 """ 1 """
34 Attribute List Extension for Python-Markdown 2 Attribute List Extension for Python-Markdown
35 ============================================ 3 ============================================
36 4
37 Adds attribute list syntax. Inspired by 5 Adds attribute list syntax. Inspired by
38 [maruku](http://maruku.rubyforge.org/proposal.html#attribute_lists)'s 6 [maruku](http://maruku.rubyforge.org/proposal.html#attribute_lists)'s
39 feature of the same name. 7 feature of the same name.
40 8
41 Copyright 2011 [Waylan Limberg](http://achinghead.com/). 9 See <https://pythonhosted.org/Markdown/extensions/attr_list.html>
10 for documentation.
42 11
43 Contact: markdown@freewisdom.org 12 Original code Copyright 2011 [Waylan Limberg](http://achinghead.com/).
44 13
45 License: BSD (see ../LICENSE.md for details) 14 All changes Copyright 2011-2014 The Python Markdown Project
46 15
47 Dependencies: 16 License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
48 * [Python 2.4+](http://python.org)
49 * [Markdown 2.1+](http://packages.python.org/Markdown/)
50 17
51 """ 18 """
52 19
53 from __future__ import absolute_import 20 from __future__ import absolute_import
54 from __future__ import unicode_literals 21 from __future__ import unicode_literals
55 from . import Extension 22 from . import Extension
56 from ..treeprocessors import Treeprocessor 23 from ..treeprocessors import Treeprocessor
57 from ..util import isBlockLevel 24 from ..util import isBlockLevel
58 import re 25 import re
59 26
60 try: 27 try:
61 Scanner = re.Scanner 28 Scanner = re.Scanner
62 except AttributeError: 29 except AttributeError: # pragma: no cover
63 # must be on Python 2.4 30 # must be on Python 2.4
64 from sre import Scanner 31 from sre import Scanner
65 32
33
66 def _handle_double_quote(s, t): 34 def _handle_double_quote(s, t):
67 k, v = t.split('=') 35 k, v = t.split('=')
68 return k, v.strip('"') 36 return k, v.strip('"')
69 37
38
70 def _handle_single_quote(s, t): 39 def _handle_single_quote(s, t):
71 k, v = t.split('=') 40 k, v = t.split('=')
72 return k, v.strip("'") 41 return k, v.strip("'")
73 42
74 def _handle_key_value(s, t): 43
44 def _handle_key_value(s, t):
75 return t.split('=') 45 return t.split('=')
76 46
47
77 def _handle_word(s, t): 48 def _handle_word(s, t):
78 if t.startswith('.'): 49 if t.startswith('.'):
79 return '.', t[1:] 50 return '.', t[1:]
80 if t.startswith('#'): 51 if t.startswith('#'):
81 return 'id', t[1:] 52 return 'id', t[1:]
82 return t, t 53 return t, t
83 54
84 _scanner = Scanner([ 55 _scanner = Scanner([
85 (r'[^ ]+=".*?"', _handle_double_quote), 56 (r'[^ ]+=".*?"', _handle_double_quote),
86 (r"[^ ]+='.*?'", _handle_single_quote), 57 (r"[^ ]+='.*?'", _handle_single_quote),
87 (r'[^ ]+=[^ ]*', _handle_key_value), 58 (r'[^ ]+=[^ =]+', _handle_key_value),
88 (r'[^ ]+', _handle_word), 59 (r'[^ =]+', _handle_word),
89 (r' ', None) 60 (r' ', None)
90 ]) 61 ])
91 62
63
92 def get_attrs(str): 64 def get_attrs(str):
93 """ Parse attribute list and return a list of attribute tuples. """ 65 """ Parse attribute list and return a list of attribute tuples. """
94 return _scanner.scan(str)[0] 66 return _scanner.scan(str)[0]
95 67
68
96 def isheader(elem): 69 def isheader(elem):
97 return elem.tag in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] 70 return elem.tag in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
98 71
72
99 class AttrListTreeprocessor(Treeprocessor): 73 class AttrListTreeprocessor(Treeprocessor):
100 74
101 BASE_RE = r'\{\:?([^\}]*)\}' 75 BASE_RE = r'\{\:?([^\}]*)\}'
102 HEADER_RE = re.compile(r'[ ]*%s[ ]*$' % BASE_RE) 76 HEADER_RE = re.compile(r'[ ]+%s[ ]*$' % BASE_RE)
103 BLOCK_RE = re.compile(r'\n[ ]*%s[ ]*$' % BASE_RE) 77 BLOCK_RE = re.compile(r'\n[ ]*%s[ ]*$' % BASE_RE)
104 INLINE_RE = re.compile(r'^%s' % BASE_RE) 78 INLINE_RE = re.compile(r'^%s' % BASE_RE)
105 NAME_RE = re.compile(r'[^A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u037 0-\u037d' 79 NAME_RE = re.compile(r'[^A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff'
106 r'\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef' 80 r'\u0370-\u037d\u037f-\u1fff\u200c-\u200d'
107 r'\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd' 81 r'\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff'
82 r'\uf900-\ufdcf\ufdf0-\ufffd'
108 r'\:\-\.0-9\u00b7\u0300-\u036f\u203f-\u2040]+') 83 r'\:\-\.0-9\u00b7\u0300-\u036f\u203f-\u2040]+')
109 84
110 def run(self, doc): 85 def run(self, doc):
111 for elem in doc.getiterator(): 86 for elem in doc.getiterator():
112 if isBlockLevel(elem.tag): 87 if isBlockLevel(elem.tag):
113 # Block level: check for attrs on last line of text 88 # Block level: check for attrs on last line of text
114 RE = self.BLOCK_RE 89 RE = self.BLOCK_RE
115 if isheader(elem): 90 if isheader(elem) or elem.tag == 'dt':
116 # header: check for attrs at end of line 91 # header or def-term: check for attrs at end of line
117 RE = self.HEADER_RE 92 RE = self.HEADER_RE
118 if len(elem) and elem[-1].tail: 93 if len(elem) and elem.tag == 'li':
94 # special case list items. children may include a ul or ol.
95 pos = None
96 # find the ul or ol position
97 for i, child in enumerate(elem):
98 if child.tag in ['ul', 'ol']:
99 pos = i
100 break
101 if pos is None and elem[-1].tail:
102 # use tail of last child. no ul or ol.
103 m = RE.search(elem[-1].tail)
104 if m:
105 self.assign_attrs(elem, m.group(1))
106 elem[-1].tail = elem[-1].tail[:m.start()]
107 elif pos is not None and pos > 0 and elem[pos-1].tail:
108 # use tail of last child before ul or ol
109 m = RE.search(elem[pos-1].tail)
110 if m:
111 self.assign_attrs(elem, m.group(1))
112 elem[pos-1].tail = elem[pos-1].tail[:m.start()]
113 elif elem.text:
114 # use text. ul is first child.
115 m = RE.search(elem.text)
116 if m:
117 self.assign_attrs(elem, m.group(1))
118 elem.text = elem.text[:m.start()]
119 elif len(elem) and elem[-1].tail:
119 # has children. Get from tail of last child 120 # has children. Get from tail of last child
120 m = RE.search(elem[-1].tail) 121 m = RE.search(elem[-1].tail)
121 if m: 122 if m:
122 self.assign_attrs(elem, m.group(1)) 123 self.assign_attrs(elem, m.group(1))
123 elem[-1].tail = elem[-1].tail[:m.start()] 124 elem[-1].tail = elem[-1].tail[:m.start()]
124 if isheader(elem): 125 if isheader(elem):
125 # clean up trailing #s 126 # clean up trailing #s
126 elem[-1].tail = elem[-1].tail.rstrip('#').rstrip() 127 elem[-1].tail = elem[-1].tail.rstrip('#').rstrip()
127 elif elem.text: 128 elif elem.text:
128 # no children. Get from text. 129 # no children. Get from text.
129 m = RE.search(elem.text) 130 m = RE.search(elem.text)
131 if not m and elem.tag == 'td':
132 m = re.search(self.BASE_RE, elem.text)
130 if m: 133 if m:
131 self.assign_attrs(elem, m.group(1)) 134 self.assign_attrs(elem, m.group(1))
132 elem.text = elem.text[:m.start()] 135 elem.text = elem.text[:m.start()]
133 if isheader(elem): 136 if isheader(elem):
134 # clean up trailing #s 137 # clean up trailing #s
135 elem.text = elem.text.rstrip('#').rstrip() 138 elem.text = elem.text.rstrip('#').rstrip()
136 else: 139 else:
137 # inline: check for attrs at start of tail 140 # inline: check for attrs at start of tail
138 if elem.tail: 141 if elem.tail:
139 m = self.INLINE_RE.match(elem.tail) 142 m = self.INLINE_RE.match(elem.tail)
(...skipping 18 matching lines...) Expand all
158 def sanitize_name(self, name): 161 def sanitize_name(self, name):
159 """ 162 """
160 Sanitize name as 'an XML Name, minus the ":"'. 163 Sanitize name as 'an XML Name, minus the ":"'.
161 See http://www.w3.org/TR/REC-xml-names/#NT-NCName 164 See http://www.w3.org/TR/REC-xml-names/#NT-NCName
162 """ 165 """
163 return self.NAME_RE.sub('_', name) 166 return self.NAME_RE.sub('_', name)
164 167
165 168
166 class AttrListExtension(Extension): 169 class AttrListExtension(Extension):
167 def extendMarkdown(self, md, md_globals): 170 def extendMarkdown(self, md, md_globals):
168 md.treeprocessors.add('attr_list', AttrListTreeprocessor(md), '>prettify ') 171 md.treeprocessors.add(
172 'attr_list', AttrListTreeprocessor(md), '>prettify'
173 )
169 174
170 175
171 def makeExtension(configs={}): 176 def makeExtension(*args, **kwargs):
172 return AttrListExtension(configs=configs) 177 return AttrListExtension(*args, **kwargs)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698