Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/mistune/renderers/html.py: 88%
103 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1from ..core import BaseRenderer
2from ..util import escape as escape_text, striptags, safe_entity
5class HTMLRenderer(BaseRenderer):
6 """A renderer for converting Markdown to HTML."""
7 NAME = 'html'
8 HARMFUL_PROTOCOLS = (
9 'javascript:',
10 'vbscript:',
11 'file:',
12 'data:',
13 )
14 GOOD_DATA_PROTOCOLS = (
15 'data:image/gif;',
16 'data:image/png;',
17 'data:image/jpeg;',
18 'data:image/webp;',
19 )
21 def __init__(self, escape=True, allow_harmful_protocols=None):
22 super(HTMLRenderer, self).__init__()
23 self._allow_harmful_protocols = allow_harmful_protocols
24 self._escape = escape
26 def render_token(self, token, state):
27 # backward compitable with v2
28 func = self._get_method(token['type'])
29 attrs = token.get('attrs')
31 if 'raw' in token:
32 text = token['raw']
33 elif 'children' in token:
34 text = self.render_tokens(token['children'], state)
35 else:
36 if attrs:
37 return func(**attrs)
38 else:
39 return func()
40 if attrs:
41 return func(text, **attrs)
42 else:
43 return func(text)
45 def safe_url(self, url: str) -> str:
46 """Ensure the given URL is safe. This method is used for rendering
47 links, images, and etc.
48 """
49 if self._allow_harmful_protocols is True:
50 return url
52 _url = url.lower()
53 if self._allow_harmful_protocols and \
54 _url.startswith(tuple(self._allow_harmful_protocols)):
55 return url
57 if _url.startswith(self.HARMFUL_PROTOCOLS) and \
58 not _url.startswith(self.GOOD_DATA_PROTOCOLS):
59 return '#harmful-link'
60 return url
62 def text(self, text: str) -> str:
63 if self._escape:
64 return escape_text(text)
65 return safe_entity(text)
67 def emphasis(self, text: str) -> str:
68 return '<em>' + text + '</em>'
70 def strong(self, text: str) -> str:
71 return '<strong>' + text + '</strong>'
73 def link(self, text: str, url: str, title=None) -> str:
74 s = '<a href="' + self.safe_url(url) + '"'
75 if title:
76 s += ' title="' + safe_entity(title) + '"'
77 return s + '>' + text + '</a>'
79 def image(self, text: str, url: str, title=None) -> str:
80 src = self.safe_url(url)
81 alt = escape_text(striptags(text))
82 s = '<img src="' + src + '" alt="' + alt + '"'
83 if title:
84 s += ' title="' + safe_entity(title) + '"'
85 return s + ' />'
87 def codespan(self, text: str) -> str:
88 return '<code>' + text + '</code>'
90 def linebreak(self) -> str:
91 return '<br />\n'
93 def softbreak(self) -> str:
94 return '\n'
96 def inline_html(self, html: str) -> str:
97 if self._escape:
98 return escape_text(html)
99 return html
101 def paragraph(self, text: str) -> str:
102 return '<p>' + text + '</p>\n'
104 def heading(self, text: str, level: int, **attrs) -> str:
105 tag = 'h' + str(level)
106 html = '<' + tag
107 _id = attrs.get('id')
108 if _id:
109 html += ' id="' + _id + '"'
110 return html + '>' + text + '</' + tag + '>\n'
112 def blank_line(self) -> str:
113 return ''
115 def thematic_break(self) -> str:
116 return '<hr />\n'
118 def block_text(self, text: str) -> str:
119 return text
121 def block_code(self, code: str, info=None) -> str:
122 html = '<pre><code'
123 if info is not None:
124 info = safe_entity(info.strip())
125 if info:
126 lang = info.split(None, 1)[0]
127 html += ' class="language-' + lang + '"'
128 return html + '>' + escape_text(code) + '</code></pre>\n'
130 def block_quote(self, text: str) -> str:
131 return '<blockquote>\n' + text + '</blockquote>\n'
133 def block_html(self, html: str) -> str:
134 if self._escape:
135 return '<p>' + escape_text(html.strip()) + '</p>\n'
136 return html + '\n'
138 def block_error(self, text: str) -> str:
139 return '<div class="error"><pre>' + text + '</pre></div>\n'
141 def list(self, text: str, ordered: bool, **attrs) -> str:
142 if ordered:
143 html = '<ol'
144 start = attrs.get('start')
145 if start is not None:
146 html += ' start="' + str(start) + '"'
147 return html + '>\n' + text + '</ol>\n'
148 return '<ul>\n' + text + '</ul>\n'
150 def list_item(self, text: str) -> str:
151 return '<li>' + text + '</li>\n'