Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/mistune/renderers.py: 71%
150 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-03 06:10 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-03 06:10 +0000
1from .util import escape, escape_html
4class BaseRenderer(object):
5 NAME = 'base'
7 def __init__(self):
8 self._methods = {}
10 def register(self, name, method):
11 self._methods[name] = method
13 def _get_method(self, name):
14 try:
15 return object.__getattribute__(self, name)
16 except AttributeError:
17 method = self._methods.get(name)
18 if not method:
19 raise AttributeError('No renderer "{!r}"'.format(name))
20 return method
22 def finalize(self, data):
23 raise NotImplementedError(
24 'The renderer needs to implement the finalize method.')
27class AstRenderer(BaseRenderer):
28 NAME = 'ast'
30 def text(self, text):
31 return {'type': 'text', 'text': text}
33 def link(self, link, children=None, title=None):
34 if isinstance(children, str):
35 children = [{'type': 'text', 'text': children}]
36 return {
37 'type': 'link',
38 'link': link,
39 'children': children,
40 'title': title,
41 }
43 def image(self, src, alt="", title=None):
44 return {'type': 'image', 'src': src, 'alt': alt, 'title': title}
46 def codespan(self, text):
47 return {'type': 'codespan', 'text': text}
49 def linebreak(self):
50 return {'type': 'linebreak'}
52 def inline_html(self, html):
53 return {'type': 'inline_html', 'text': html}
55 def heading(self, children, level):
56 return {'type': 'heading', 'children': children, 'level': level}
58 def newline(self):
59 return {'type': 'newline'}
61 def thematic_break(self):
62 return {'type': 'thematic_break'}
64 def block_code(self, children, info=None):
65 return {
66 'type': 'block_code',
67 'text': children,
68 'info': info
69 }
71 def block_html(self, children):
72 return {'type': 'block_html', 'text': children}
74 def list(self, children, ordered, level, start=None):
75 token = {
76 'type': 'list',
77 'children': children,
78 'ordered': ordered,
79 'level': level,
80 }
81 if start is not None:
82 token['start'] = start
83 return token
85 def list_item(self, children, level):
86 return {'type': 'list_item', 'children': children, 'level': level}
88 def _create_default_method(self, name):
89 def __ast(children):
90 return {'type': name, 'children': children}
91 return __ast
93 def _get_method(self, name):
94 try:
95 return super(AstRenderer, self)._get_method(name)
96 except AttributeError:
97 return self._create_default_method(name)
99 def finalize(self, data):
100 return list(data)
103class HTMLRenderer(BaseRenderer):
104 NAME = 'html'
105 HARMFUL_PROTOCOLS = {
106 'javascript:',
107 'vbscript:',
108 'data:',
109 }
111 def __init__(self, escape=True, allow_harmful_protocols=None):
112 super(HTMLRenderer, self).__init__()
113 self._escape = escape
114 self._allow_harmful_protocols = allow_harmful_protocols
116 def _safe_url(self, url):
117 if self._allow_harmful_protocols is None:
118 schemes = self.HARMFUL_PROTOCOLS
119 elif self._allow_harmful_protocols is True:
120 schemes = None
121 else:
122 allowed = set(self._allow_harmful_protocols)
123 schemes = self.HARMFUL_PROTOCOLS - allowed
125 if schemes:
126 for s in schemes:
127 if url.lower().startswith(s):
128 url = '#harmful-link'
129 break
130 return url
132 def text(self, text):
133 if self._escape:
134 return escape(text)
135 return escape_html(text)
137 def link(self, link, text=None, title=None):
138 if text is None:
139 text = link
141 s = '<a href="' + self._safe_url(link) + '"'
142 if title:
143 s += ' title="' + escape_html(title) + '"'
144 return s + '>' + (text or link) + '</a>'
146 def image(self, src, alt="", title=None):
147 src = self._safe_url(src)
148 alt = escape_html(alt)
149 s = '<img src="' + src + '" alt="' + alt + '"'
150 if title:
151 s += ' title="' + escape_html(title) + '"'
152 return s + ' />'
154 def emphasis(self, text):
155 return '<em>' + text + '</em>'
157 def strong(self, text):
158 return '<strong>' + text + '</strong>'
160 def codespan(self, text):
161 return '<code>' + escape(text) + '</code>'
163 def linebreak(self):
164 return '<br />\n'
166 def inline_html(self, html):
167 if self._escape:
168 return escape(html)
169 return html
171 def paragraph(self, text):
172 return '<p>' + text + '</p>\n'
174 def heading(self, text, level):
175 tag = 'h' + str(level)
176 return '<' + tag + '>' + text + '</' + tag + '>\n'
178 def newline(self):
179 return ''
181 def thematic_break(self):
182 return '<hr />\n'
184 def block_text(self, text):
185 return text
187 def block_code(self, code, info=None):
188 html = '<pre><code'
189 if info is not None:
190 info = info.strip()
191 if info:
192 lang = info.split(None, 1)[0]
193 lang = escape_html(lang)
194 html += ' class="language-' + lang + '"'
195 return html + '>' + escape(code) + '</code></pre>\n'
197 def block_quote(self, text):
198 return '<blockquote>\n' + text + '</blockquote>\n'
200 def block_html(self, html):
201 if not self._escape:
202 return html + '\n'
203 return '<p>' + escape(html) + '</p>\n'
205 def block_error(self, html):
206 return '<div class="error">' + html + '</div>\n'
208 def list(self, text, ordered, level, start=None):
209 if ordered:
210 html = '<ol'
211 if start is not None:
212 html += ' start="' + str(start) + '"'
213 return html + '>\n' + text + '</ol>\n'
214 return '<ul>\n' + text + '</ul>\n'
216 def list_item(self, text, level):
217 return '<li>' + text + '</li>\n'
219 def finalize(self, data):
220 return ''.join(data)