Passed
Push — master ( ec62d3...86008f )
by Dongxin
42s
created

ReStructuredTextRenderer   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 153
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 153
rs 9
wmc 35

19 Methods

Rating   Name   Duplication   Size   Complexity  
A code() 0 4 1
A indent_lines() 0 8 2
A image() 0 10 2
A __init__() 0 3 1
A softbreak() 0 2 1
A link() 0 5 2
B code_block() 0 17 5
A cr() 0 2 1
A block_quote() 0 5 2
A list() 0 3 2
A document() 0 2 1
B heading() 0 25 3
A linebreak() 0 3 1
A strong() 0 2 1
A paragraph() 0 5 2
A item() 0 7 3
A emph() 0 2 1
A text() 0 2 1
A lit() 0 9 3
1
from __future__ import unicode_literals
2
3
4
from CommonMark.render.renderer import Renderer
5
6
7
class ReStructuredTextRenderer(Renderer):
8
    """
9
    Render reStructuredText from Markdown
10
11
    Example:
12
13
    .. code:: python
14
15
        import CommonMark
16
17
        parser = CommonMark.Parser()
18
        ast = parser.parse('Hello `inline code` example')
19
20
        renderer = CommonMark.ReStructuredTextRenderer()
21
        rst = renderer.render(ast)
22
        print(rst)  # Hello ``inline code`` example
23
    """
24
    def __init__(self, indent_char=' '):
25
        self.indent_char = indent_char
26
        self.indent_length = 0
27
28
    def lit(self, s):
29
        if s == '\n':
30
            indent = ''  # Avoid whitespace if we're just adding a newline
31
        elif self.last_out != '\n':
32
            indent = ''  # Don't indent if we're in the middle of a line
33
        else:
34
            indent = self.indent_char * self.indent_length
35
36
        return super(ReStructuredTextRenderer, self).lit(indent + s)
37
38
    def cr(self):
39
        self.lit('\n')
40
41
    def indent_lines(self, literal, indent_length=4):
42
        indent = self.indent_char * indent_length
43
        new_lines = []
44
45
        for line in literal.splitlines():
46
            new_lines.append(indent + line)
47
48
        return '\n'.join(new_lines)
49
50
    # Nodes
51
52
    def document(self, node, entering):
53
        pass
54
55
    def softbreak(self, node, entering):
56
        self.cr()
57
58
    def linebreak(self, node, entering):
59
        self.cr()
60
        self.cr()
61
62
    def text(self, node, entering):
63
        self.out(node.literal)
64
65
    def emph(self, node, entering):
66
        self.out('*')
67
68
    def strong(self, node, entering):
69
        self.out('**')
70
71
    def paragraph(self, node, entering):
72
        if node.parent.t == 'item':
73
            pass
74
        else:
75
            self.cr()
76
77
    def link(self, node, entering):
78
        if entering:
79
            self.out('`')
80
        else:
81
            self.out(' <%s>`_' % node.destination)
82
83
    def image(self, node, entering):
84
        directive = '.. image:: ' + node.destination
85
86
        if entering:
87
            self.out(directive)
88
            self.cr()
89
            self.indent_length += 4
90
            self.out(':alt: ')
91
        else:
92
            self.indent_length -= 4
93
94
    def code(self, node, entering):
95
        self.out('``')
96
        self.out(node.literal)
97
        self.out('``')
98
99
    def code_block(self, node, entering):
100
        directive = '.. code::'
101
        language_name = None
102
103
        info_words = node.info.split() if node.info else []
104
        if len(info_words) > 0 and len(info_words[0]) > 0:
105
            language_name = info_words[0]
106
107
        if language_name:
108
            directive += ' ' + language_name
109
110
        self.cr()
111
        self.out(directive)
112
        self.cr()
113
        self.cr()
114
        self.out(self.indent_lines(node.literal))
115
        self.cr()
116
117
    def list(self, node, entering):
118
        if entering:
119
            self.cr()
120
121
    def item(self, node, entering):
122
        tagname = '*' if node.list_data['type'] == 'bullet' else '#.'
123
124
        if entering:
125
            self.out(tagname + ' ')
126
        else:
127
            self.cr()
128
129
    def block_quote(self, node, entering):
130
        if entering:
131
            self.indent_length += 4
132
        else:
133
            self.indent_length -= 4
134
135
    def heading(self, node, entering):
136
        heading_chars = [
137
            '#',
138
            '*',
139
            '=',
140
            '-',
141
            '^',
142
            '"'
143
        ]
144
145
        try:
146
            heading_char = heading_chars[node.level-1]
147
        except IndexError:
148
            # Default to the last level if we're in too deep
149
            heading_char = heading_chars[-1]
150
151
        heading_length = len(node.first_child.literal)
152
        banner = heading_char * heading_length
153
154
        if entering:
155
            self.cr()
156
        else:
157
            self.cr()
158
            self.out(banner)
159
            self.cr()
160