|
1
|
|
|
""" |
|
2
|
|
|
Definition List Extension for Python-Markdown |
|
3
|
|
|
============================================= |
|
4
|
|
|
|
|
5
|
|
|
Adds parsing of Definition Lists to Python-Markdown. |
|
6
|
|
|
|
|
7
|
|
|
See <https://pythonhosted.org/Markdown/extensions/definition_lists.html> |
|
8
|
|
|
for documentation. |
|
9
|
|
|
|
|
10
|
|
|
Original code Copyright 2008 [Waylan Limberg](http://achinghead.com) |
|
11
|
|
|
|
|
12
|
|
|
All changes Copyright 2008-2014 The Python Markdown Project |
|
13
|
|
|
|
|
14
|
|
|
License: [BSD](http://www.opensource.org/licenses/bsd-license.php) |
|
15
|
|
|
|
|
16
|
|
|
""" |
|
17
|
|
|
|
|
18
|
|
|
from __future__ import absolute_import |
|
19
|
|
|
from __future__ import unicode_literals |
|
20
|
|
|
from . import Extension |
|
21
|
|
|
from ..blockprocessors import BlockProcessor, ListIndentProcessor |
|
22
|
|
|
from ..util import etree |
|
23
|
|
|
import re |
|
24
|
|
|
|
|
25
|
|
|
|
|
26
|
|
|
class DefListProcessor(BlockProcessor): |
|
27
|
|
|
""" Process Definition Lists. """ |
|
28
|
|
|
|
|
29
|
|
|
RE = re.compile(r'(^|\n)[ ]{0,3}:[ ]{1,3}(.*?)(\n|$)') |
|
30
|
|
|
NO_INDENT_RE = re.compile(r'^[ ]{0,3}[^ :]') |
|
31
|
|
|
|
|
32
|
|
|
def test(self, parent, block): |
|
33
|
|
|
return bool(self.RE.search(block)) |
|
34
|
|
|
|
|
35
|
|
|
def run(self, parent, blocks): |
|
36
|
|
|
|
|
37
|
|
|
raw_block = blocks.pop(0) |
|
38
|
|
|
m = self.RE.search(raw_block) |
|
39
|
|
|
terms = [l.strip() for l in |
|
40
|
|
|
raw_block[:m.start()].split('\n') if l.strip()] |
|
41
|
|
|
block = raw_block[m.end():] |
|
42
|
|
|
no_indent = self.NO_INDENT_RE.match(block) |
|
43
|
|
|
if no_indent: |
|
44
|
|
|
d, theRest = (block, None) |
|
45
|
|
|
else: |
|
46
|
|
|
d, theRest = self.detab(block) |
|
47
|
|
|
if d: |
|
48
|
|
|
d = '%s\n%s' % (m.group(2), d) |
|
49
|
|
|
else: |
|
50
|
|
|
d = m.group(2) |
|
51
|
|
|
sibling = self.lastChild(parent) |
|
52
|
|
|
if not terms and sibling is None: |
|
53
|
|
|
# This is not a definition item. Most likely a paragraph that |
|
54
|
|
|
# starts with a colon at the begining of a document or list. |
|
55
|
|
|
blocks.insert(0, raw_block) |
|
56
|
|
|
return False |
|
57
|
|
|
if not terms and sibling.tag == 'p': |
|
58
|
|
|
# The previous paragraph contains the terms |
|
59
|
|
|
state = 'looselist' |
|
60
|
|
|
terms = sibling.text.split('\n') |
|
61
|
|
|
parent.remove(sibling) |
|
62
|
|
|
# Aquire new sibling |
|
63
|
|
|
sibling = self.lastChild(parent) |
|
64
|
|
|
else: |
|
65
|
|
|
state = 'list' |
|
66
|
|
|
|
|
67
|
|
|
if sibling is not None and sibling.tag == 'dl': |
|
68
|
|
|
# This is another item on an existing list |
|
69
|
|
|
dl = sibling |
|
70
|
|
|
if not terms and len(dl) and dl[-1].tag == 'dd' and len(dl[-1]): |
|
71
|
|
|
state = 'looselist' |
|
72
|
|
|
else: |
|
73
|
|
|
# This is a new list |
|
74
|
|
|
dl = etree.SubElement(parent, 'dl') |
|
75
|
|
|
# Add terms |
|
76
|
|
|
for term in terms: |
|
77
|
|
|
dt = etree.SubElement(dl, 'dt') |
|
78
|
|
|
dt.text = term |
|
79
|
|
|
# Add definition |
|
80
|
|
|
self.parser.state.set(state) |
|
81
|
|
|
dd = etree.SubElement(dl, 'dd') |
|
82
|
|
|
self.parser.parseBlocks(dd, [d]) |
|
83
|
|
|
self.parser.state.reset() |
|
84
|
|
|
|
|
85
|
|
|
if theRest: |
|
86
|
|
|
blocks.insert(0, theRest) |
|
87
|
|
|
|
|
88
|
|
|
|
|
89
|
|
|
class DefListIndentProcessor(ListIndentProcessor): |
|
90
|
|
|
""" Process indented children of definition list items. """ |
|
91
|
|
|
|
|
92
|
|
|
ITEM_TYPES = ['dd'] |
|
93
|
|
|
LIST_TYPES = ['dl'] |
|
94
|
|
|
|
|
95
|
|
|
def create_item(self, parent, block): |
|
96
|
|
|
""" Create a new dd and parse the block with it as the parent. """ |
|
97
|
|
|
dd = etree.SubElement(parent, 'dd') |
|
98
|
|
|
self.parser.parseBlocks(dd, [block]) |
|
99
|
|
|
|
|
100
|
|
|
|
|
101
|
|
|
class DefListExtension(Extension): |
|
102
|
|
|
""" Add definition lists to Markdown. """ |
|
103
|
|
|
|
|
104
|
|
|
def extendMarkdown(self, md, md_globals): |
|
105
|
|
|
""" Add an instance of DefListProcessor to BlockParser. """ |
|
106
|
|
|
md.parser.blockprocessors.add('defindent', |
|
107
|
|
|
DefListIndentProcessor(md.parser), |
|
108
|
|
|
'>indent') |
|
109
|
|
|
md.parser.blockprocessors.add('deflist', |
|
110
|
|
|
DefListProcessor(md.parser), |
|
111
|
|
|
'>ulist') |
|
112
|
|
|
|
|
113
|
|
|
|
|
114
|
|
|
def makeExtension(*args, **kwargs): |
|
115
|
|
|
return DefListExtension(*args, **kwargs) |
|
116
|
|
|
|