-
Notifications
You must be signed in to change notification settings - Fork 30
/
mdrenderer.py
286 lines (222 loc) · 8.83 KB
/
mdrenderer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
import re
from mistune import Renderer, escape, escape_link
class MdStyleInstruction(object):
softnewline = False
def __init__(self, mdname):
self.mdname = mdname
def __repr__(self):
params = ['{}={}'.format(a, getattr(self,a)) for a in dir(self) if not a.startswith('__') and not callable(getattr(self,a))]
return '<{} {}>'.format(type(self), ", ".join(params))
class MdStyleInstructionCell(MdStyleInstruction):
pass
class MdStyleInstructionText(MdStyleInstruction):
pass
class MdStyleInstructionLink(MdStyleInstruction):
softnewline = True
def __init__(self, link):
super(MdStyleInstructionLink, self).__init__('link')
self.link = link
class MdStyleInstructionListStart(MdStyleInstruction):
softnewline = True
ordered = True
def __init__(self, ordered):
super(MdStyleInstructionListStart, self).__init__('link')
self.ordered = ordered
class MdStyleInstructionListEnd(MdStyleInstruction):
softnewline = False
def __init__(self):
super(MdStyleInstructionListEnd, self).__init__('link')
class MdStyleInstructionListItem(MdStyleInstruction):
softnewline = True
def __init__(self):
super(MdStyleInstructionListItem, self).__init__('list_item')
class MdStyleInstructionLineBreak(MdStyleInstruction):
softnewline = True
def __init__(self):
super(MdStyleInstructionLineBreak, self).__init__('linebreak')
class Md2XLSRenderer(Renderer):
def placeholder(self):
"""Returns the default, empty output value for the renderer.
All renderer methods use the '+=' operator to append to this value.
Default is a string so rendering HTML can build up a result string with
the rendered Markdown.
Can be overridden by Renderer subclasses to be types like an empty
list, allowing the renderer to create a tree-like structure to
represent the document (which can then be reprocessed later into a
separate format like docx or pdf).
"""
return []
### Block-level functions
def block_code(self, code, lang=None):
"""Rendering block level code. ``pre > code``.
:param code: text content of the code block.
:param lang: language of the given code.
"""
code = code.rstrip('\n')
return ["<code>"] + code
def block_quote(self, text):
"""Rendering <blockquote> with the given text.
:param text: text content of the blockquote.
"""
return ["<blockquote>"] + text
def block_html(self, html):
"""Rendering block level pure html content.
:param html: text content of the html snippet.
"""
if self.options.get('skip_style') and \
html.lower().startswith('<style'):
return ['']
if self.options.get('escape'):
return [escape(html)]
return [html]
def header(self, text, level, raw=None):
"""Rendering header/heading tags like ``<h1>`` ``<h2>``.
:param text: rendered text content for the header.
:param level: a number for the header level, for example: 1.
:param raw: raw text content of the header.
"""
return [[MdStyleInstructionCell('h{}'.format(level))] + text]
def hrule(self):
"""Rendering method for ``<hr>`` tag."""
return [MdStyleInstructionCell('hrule')]
def list(self, body, ordered=True):
"""Rendering list tags like ``<ul>`` and ``<ol>``.
:param body: body contents of the list.
:param ordered: whether this list is ordered or not.
"""
return [[MdStyleInstructionListStart(ordered)]] + body + [[MdStyleInstructionListEnd()]]
def list_item(self, text):
"""Rendering list item snippet. Like ``<li>``."""
#return [[MdStyleInstructionList(), *text]]
return [[MdStyleInstructionListItem()] + text]
def paragraph(self, text):
"""Rendering paragraph tags. Like ``<p>``."""
return [text]
def table(self, header, body):
"""Rendering table element. Wrap header and body in it.
:param header: header part of the table.
:param body: body part of the table.
"""
return header + body
def table_row(self, content):
"""Rendering a table row. Like ``<tr>``.
:param content: content of current table row.
"""
return ['<tr>\n%s</tr>\n'] + content
def table_cell(self, content, **flags):
"""Rendering a table cell. Like ``<th>`` ``<td>``.
:param content: content of current table cell.
:param header: whether this is header or not.
:param align: align of current table cell.
"""
return content
### Span-level functions
def double_emphasis(self, text):
"""Rendering **strong** text.
:param text: text content for emphasis.
"""
return [MdStyleInstructionText('double_emphasis')] + text
def emphasis(self, text):
"""Rendering *emphasis* text.
:param text: text content for emphasis.
"""
return [MdStyleInstructionText('emphasis')] + text
def codespan(self, text):
"""Rendering inline `code` text.
:param text: text content for inline code.
"""
if isinstance(text, str):
text = [' {} '.format(text)]
return [MdStyleInstructionText('codespan')] + text
def linebreak(self):
"""Rendering line break like ``<br>``."""
return [MdStyleInstructionLineBreak()]
def strikethrough(self, text):
"""Rendering ~~strikethrough~~ text.
:param text: text content for strikethrough.
"""
return [MdStyleInstructionText('strikethrough')] + text
def text(self, text):
"""Rendering unformatted text.
:param text: text content.
"""
return [text]
def escape(self, text):
"""Rendering escape sequence.
:param text: text content.
"""
return [escape(text)]
def autolink(self, link, is_email=False):
"""Rendering a given link or email address.
:param link: link content or email address.
:param is_email: whether this is an email or not.
"""
text = link = escape_link(link)
if is_email:
link = 'mailto:%s' % link
return [MdStyleInstructionLink(link)] + text
def link(self, link, title, text):
"""Rendering a given link with content and title.
:param link: href link for ``<a>`` tag.
:param title: title content for `title` attribute.
:param text: text content for description.
"""
link = escape_link(link)
return [MdStyleInstructionLink(link)] + text
def image(self, src, title, text):
"""Rendering a image with title and text.
:param src: source link of the image.
:param title: title text of the image.
:param text: alt text of the image.
"""
src = escape_link(src)
text = escape(text, quote=True)
if title:
title = escape(title, quote=True)
html = '<img src="%s" alt="%s" title="%s"' % (src, text, title)
else:
html = '<img src="%s" alt="%s"' % (src, text)
if self.options.get('use_xhtml'):
return '%s />' % html
return '%s>' % html
def inline_html(self, html):
"""Rendering span level pure html content.
:param html: text content of the html snippet.
"""
if self.options.get('escape'):
return [escape(html)]
return [html]
def newline(self):
"""Rendering newline element."""
return ['<new line>']
def footnote_ref(self, key, index):
"""Rendering the ref anchor of a footnote.
:param key: identity key for the footnote.
:param index: the index count of current footnote.
"""
html = (
'<sup class="footnote-ref" id="fnref-%s">'
'<a href="#fn-%s">%d</a></sup>'
) % (escape(key), escape(key), index)
return html
def footnote_item(self, key, text):
"""Rendering a footnote item.
:param key: identity key for the footnote.
:param text: text content of the footnote.
"""
back = (
'<a href="#fnref-%s" class="footnote">↩</a>'
) % escape(key)
text = text.rstrip()
if text.endswith('</p>'):
text = re.sub(r'<\/p>$', r'%s</p>' % back, text)
else:
text = '%s<p>%s</p>' % (text, back)
html = '<li id="fn-%s">%s</li>\n' % (escape(key), text)
return html
def footnotes(self, text):
"""Wrapper for all footnotes.
:param text: contents of all footnotes.
"""
html = '<div class="footnotes">\n%s<ol>%s</ol>\n</div>\n'
return html % (self.hrule(), text)