Completed
Push — master ( 32cfa8...ec62d3 )
by Dongxin
48s
created

DefListExtension   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 11
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
rs 10
wmc 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A extendMarkdown() 0 8 1
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