0
# Renderers
1
2
Output format renderers that convert parsed Markdown tokens into various formats including HTML, reStructuredText, and normalized Markdown. Renderers provide the final output stage of the parsing pipeline and can be customized or extended for specific output requirements.
3
4
## Capabilities
5
6
### HTML Renderer
7
8
Converts parsed Markdown tokens to HTML output with security features, customizable escaping, and protocol filtering.
9
10
```python { .api }
11
class HTMLRenderer(BaseRenderer):
12
"""
13
A renderer for converting Markdown to HTML.
14
15
Attributes:
16
- NAME: ClassVar[Literal["html"]] = "html"
17
- HARMFUL_PROTOCOLS: ClassVar[Tuple[str, ...]] - Blocked URL protocols
18
- GOOD_DATA_PROTOCOLS: ClassVar[Tuple[str, ...]] - Allowed data URLs
19
"""
20
21
def __init__(
22
self,
23
escape: bool = True,
24
allow_harmful_protocols: Optional[bool] = None
25
):
26
"""
27
Initialize HTML renderer.
28
29
Parameters:
30
- escape: Whether to escape HTML in rendered output
31
- allow_harmful_protocols: Whether to allow potentially harmful URL protocols
32
"""
33
34
def safe_url(self, url: str) -> str:
35
"""
36
Ensure the given URL is safe by filtering harmful protocols.
37
38
Parameters:
39
- url: URL to validate
40
41
Returns:
42
Safe URL or empty string if harmful
43
"""
44
```
45
46
Usage example:
47
48
```python
49
from mistune import HTMLRenderer, Markdown
50
51
# Default HTML renderer with escaping
52
renderer = HTMLRenderer(escape=True)
53
md = Markdown(renderer=renderer)
54
html = md('**Bold** and <script>alert("xss")</script>')
55
# Output: '<p><strong>Bold</strong> and <script>alert("xss")</script></p>\n'
56
57
# HTML renderer without escaping
58
renderer = HTMLRenderer(escape=False)
59
md = Markdown(renderer=renderer)
60
html = md('**Bold** and <em>italic</em>')
61
# Output: '<p><strong>Bold</strong> and <em>italic</em></p>\n'
62
```
63
64
### reStructuredText Renderer
65
66
Converts Markdown tokens to reStructuredText format for documentation systems and Sphinx integration.
67
68
```python { .api }
69
class RSTRenderer(BaseRenderer):
70
"""
71
A renderer for converting Markdown to reStructuredText format.
72
73
Attributes:
74
- NAME: ClassVar[Literal["rst"]] = "rst"
75
"""
76
77
def __init__(self):
78
"""Initialize reStructuredText renderer."""
79
```
80
81
Usage example:
82
83
```python
84
from mistune import RSTRenderer, Markdown
85
86
renderer = RSTRenderer()
87
md = Markdown(renderer=renderer)
88
rst = md('''
89
# Main Heading
90
91
This is a paragraph with **bold** and *italic* text.
92
93
- List item 1
94
- List item 2
95
96
``inline code``
97
''')
98
99
print(rst)
100
# Output:
101
# Main Heading
102
# ============
103
#
104
# This is a paragraph with **bold** and *italic* text.
105
#
106
# - List item 1
107
# - List item 2
108
#
109
# ``inline code``
110
```
111
112
### Markdown Renderer
113
114
Normalizes and reformats Markdown input, useful for Markdown formatting and standardization.
115
116
```python { .api }
117
class MarkdownRenderer(BaseRenderer):
118
"""
119
A renderer for converting parsed tokens back to normalized Markdown.
120
121
Attributes:
122
- NAME: ClassVar[Literal["markdown"]] = "markdown"
123
"""
124
125
def __init__(self):
126
"""Initialize Markdown renderer."""
127
```
128
129
Usage example:
130
131
```python
132
from mistune import MarkdownRenderer, Markdown
133
134
renderer = MarkdownRenderer()
135
md = Markdown(renderer=renderer)
136
137
# Normalize inconsistent Markdown formatting
138
normalized = md('''
139
# Inconsistent Heading
140
This is a paragraph with multiple spaces.
141
142
* List item 1
143
* List item 2
144
''')
145
146
print(normalized)
147
# Output: Clean, normalized Markdown
148
```
149
150
### Base Renderer
151
152
Abstract base class for creating custom renderers with common rendering functionality.
153
154
```python { .api }
155
class BaseRenderer:
156
"""
157
Base class for all renderers providing common rendering functionality.
158
159
Attributes:
160
- NAME: ClassVar[str] - Unique identifier for the renderer
161
"""
162
163
def render_tokens(
164
self,
165
tokens: List[Dict[str, Any]],
166
state: BlockState
167
) -> str:
168
"""
169
Render a list of tokens to string output.
170
171
Parameters:
172
- tokens: List of parsed tokens to render
173
- state: Current block parsing state
174
175
Returns:
176
Rendered string output
177
"""
178
179
def render_token(
180
self,
181
token: Dict[str, Any],
182
state: BlockState
183
) -> str:
184
"""
185
Render a single token to string output.
186
187
Parameters:
188
- token: Token to render
189
- state: Current block parsing state
190
191
Returns:
192
Rendered string representation of token
193
"""
194
195
def finalize_data(self, data: str) -> str:
196
"""
197
Finalize rendered data before returning.
198
199
Parameters:
200
- data: Rendered data string
201
202
Returns:
203
Finalized output string
204
"""
205
```
206
207
### Custom Renderer Creation
208
209
Pattern for creating custom renderers by extending BaseRenderer:
210
211
```python
212
from mistune import BaseRenderer, BlockState
213
214
class CustomRenderer(BaseRenderer):
215
NAME = "custom"
216
217
def render_heading(self, text: str, level: int) -> str:
218
# Custom heading rendering
219
return f"{'#' * level} {text}\n\n"
220
221
def render_paragraph(self, text: str) -> str:
222
# Custom paragraph rendering
223
return f"<p class='custom'>{text}</p>\n"
224
225
def render_strong(self, text: str) -> str:
226
# Custom bold rendering
227
return f"<b class='strong'>{text}</b>"
228
229
# Use custom renderer
230
from mistune import Markdown
231
md = Markdown(renderer=CustomRenderer())
232
output = md('# Heading\n\nThis is **bold** text.')
233
```
234
235
## Renderer Integration
236
237
Renderers integrate with the parser through the renderer parameter:
238
239
```python
240
# String shortcuts
241
md = mistune.create_markdown(renderer='html') # HTMLRenderer
242
md = mistune.create_markdown(renderer='ast') # No renderer (AST output)
243
244
# Renderer instances
245
from mistune import HTMLRenderer, RSTRenderer
246
md = mistune.create_markdown(renderer=HTMLRenderer(escape=False))
247
md = mistune.create_markdown(renderer=RSTRenderer())
248
249
# Custom renderer
250
md = mistune.create_markdown(renderer=CustomRenderer())
251
```
252
253
## AST Output
254
255
When no renderer is specified or renderer='ast', mistune returns the parsed Abstract Syntax Tree:
256
257
```python
258
import mistune
259
260
# Get AST tokens instead of rendered output
261
tokens = mistune.markdown('**bold** text', renderer='ast')
262
# Returns: [{'type': 'paragraph', 'children': [
263
# {'type': 'strong', 'children': [{'type': 'text', 'raw': 'bold'}]},
264
# {'type': 'text', 'raw': ' text'}
265
# ]}]
266
267
# AST is useful for analysis and custom processing
268
def analyze_tokens(tokens):
269
for token in tokens:
270
print(f"Token type: {token['type']}")
271
if 'children' in token:
272
analyze_tokens(token['children'])
273
274
analyze_tokens(tokens)
275
```