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