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

1from .util import escape, escape_html 

2 

3 

4class BaseRenderer(object): 

5 NAME = 'base' 

6 

7 def __init__(self): 

8 self._methods = {} 

9 

10 def register(self, name, method): 

11 self._methods[name] = method 

12 

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 

21 

22 def finalize(self, data): 

23 raise NotImplementedError( 

24 'The renderer needs to implement the finalize method.') 

25 

26 

27class AstRenderer(BaseRenderer): 

28 NAME = 'ast' 

29 

30 def text(self, text): 

31 return {'type': 'text', 'text': text} 

32 

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 } 

42 

43 def image(self, src, alt="", title=None): 

44 return {'type': 'image', 'src': src, 'alt': alt, 'title': title} 

45 

46 def codespan(self, text): 

47 return {'type': 'codespan', 'text': text} 

48 

49 def linebreak(self): 

50 return {'type': 'linebreak'} 

51 

52 def inline_html(self, html): 

53 return {'type': 'inline_html', 'text': html} 

54 

55 def heading(self, children, level): 

56 return {'type': 'heading', 'children': children, 'level': level} 

57 

58 def newline(self): 

59 return {'type': 'newline'} 

60 

61 def thematic_break(self): 

62 return {'type': 'thematic_break'} 

63 

64 def block_code(self, children, info=None): 

65 return { 

66 'type': 'block_code', 

67 'text': children, 

68 'info': info 

69 } 

70 

71 def block_html(self, children): 

72 return {'type': 'block_html', 'text': children} 

73 

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 

84 

85 def list_item(self, children, level): 

86 return {'type': 'list_item', 'children': children, 'level': level} 

87 

88 def _create_default_method(self, name): 

89 def __ast(children): 

90 return {'type': name, 'children': children} 

91 return __ast 

92 

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) 

98 

99 def finalize(self, data): 

100 return list(data) 

101 

102 

103class HTMLRenderer(BaseRenderer): 

104 NAME = 'html' 

105 HARMFUL_PROTOCOLS = { 

106 'javascript:', 

107 'vbscript:', 

108 'data:', 

109 } 

110 

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 

115 

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 

124 

125 if schemes: 

126 for s in schemes: 

127 if url.lower().startswith(s): 

128 url = '#harmful-link' 

129 break 

130 return url 

131 

132 def text(self, text): 

133 if self._escape: 

134 return escape(text) 

135 return escape_html(text) 

136 

137 def link(self, link, text=None, title=None): 

138 if text is None: 

139 text = link 

140 

141 s = '<a href="' + self._safe_url(link) + '"' 

142 if title: 

143 s += ' title="' + escape_html(title) + '"' 

144 return s + '>' + (text or link) + '</a>' 

145 

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 + ' />' 

153 

154 def emphasis(self, text): 

155 return '<em>' + text + '</em>' 

156 

157 def strong(self, text): 

158 return '<strong>' + text + '</strong>' 

159 

160 def codespan(self, text): 

161 return '<code>' + escape(text) + '</code>' 

162 

163 def linebreak(self): 

164 return '<br />\n' 

165 

166 def inline_html(self, html): 

167 if self._escape: 

168 return escape(html) 

169 return html 

170 

171 def paragraph(self, text): 

172 return '<p>' + text + '</p>\n' 

173 

174 def heading(self, text, level): 

175 tag = 'h' + str(level) 

176 return '<' + tag + '>' + text + '</' + tag + '>\n' 

177 

178 def newline(self): 

179 return '' 

180 

181 def thematic_break(self): 

182 return '<hr />\n' 

183 

184 def block_text(self, text): 

185 return text 

186 

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' 

196 

197 def block_quote(self, text): 

198 return '<blockquote>\n' + text + '</blockquote>\n' 

199 

200 def block_html(self, html): 

201 if not self._escape: 

202 return html + '\n' 

203 return '<p>' + escape(html) + '</p>\n' 

204 

205 def block_error(self, html): 

206 return '<div class="error">' + html + '</div>\n' 

207 

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' 

215 

216 def list_item(self, text, level): 

217 return '<li>' + text + '</li>\n' 

218 

219 def finalize(self, data): 

220 return ''.join(data)