0
# Writers and Output Generation
1
2
Writer system for generating HTML and Markdown output from internal document representations. The writer system provides a flexible interface for creating different output formats and custom rendering logic.
3
4
## Capabilities
5
6
### Writer Factory
7
8
Create writer instances for different output formats.
9
10
```python { .api }
11
def writer(output_format=None):
12
"""
13
Create writer instance for specified output format.
14
15
Parameters:
16
- output_format: str, "html" or "markdown" (default: "html")
17
18
Returns:
19
HtmlWriter or MarkdownWriter instance
20
"""
21
22
def formats():
23
"""
24
Get available output format keys.
25
26
Returns:
27
List of supported format strings
28
"""
29
```
30
31
Usage example:
32
33
```python
34
from mammoth.writers import writer, formats
35
36
# Get available formats
37
print(formats()) # ['html', 'markdown']
38
39
# Create HTML writer
40
html_writer = writer("html")
41
42
# Create Markdown writer
43
md_writer = writer("markdown")
44
```
45
46
### HTML Writer
47
48
Writer class for generating HTML output with full control over element creation and attributes.
49
50
```python { .api }
51
class HtmlWriter:
52
"""HTML writer for generating HTML output."""
53
54
def text(self, text):
55
"""
56
Write text content with proper escaping.
57
58
Parameters:
59
- text: str, text content to write
60
"""
61
62
def start(self, name, attributes=None):
63
"""
64
Write opening HTML tag.
65
66
Parameters:
67
- name: str, HTML element name
68
- attributes: dict, HTML attributes (optional)
69
"""
70
71
def end(self, name):
72
"""
73
Write closing HTML tag.
74
75
Parameters:
76
- name: str, HTML element name
77
"""
78
79
def self_closing(self, name, attributes=None):
80
"""
81
Write self-closing HTML tag.
82
83
Parameters:
84
- name: str, HTML element name
85
- attributes: dict, HTML attributes (optional)
86
"""
87
88
def append(self, html):
89
"""
90
Append raw HTML content.
91
92
Parameters:
93
- html: str, HTML content to append
94
"""
95
96
def as_string(self):
97
"""
98
Get final HTML output.
99
100
Returns:
101
str, complete HTML content
102
"""
103
```
104
105
Usage example:
106
107
```python
108
from mammoth.writers import writer
109
110
html_writer = writer("html")
111
112
# Create HTML structure
113
html_writer.start("div", {"class": "container"})
114
html_writer.start("h1")
115
html_writer.text("Hello World")
116
html_writer.end("h1")
117
html_writer.start("p")
118
html_writer.text("This is a paragraph.")
119
html_writer.end("p")
120
html_writer.self_closing("img", {"src": "image.jpg", "alt": "Image"})
121
html_writer.end("div")
122
123
# Get final HTML
124
output = html_writer.as_string()
125
print(output) # <div class="container"><h1>Hello World</h1><p>This is a paragraph.</p><img src="image.jpg" alt="Image" /></div>
126
```
127
128
### Markdown Writer
129
130
Writer class for generating Markdown output with the same interface as HtmlWriter.
131
132
```python { .api }
133
class MarkdownWriter:
134
"""Markdown writer for generating Markdown output."""
135
136
def text(self, text):
137
"""Write text content with Markdown escaping."""
138
139
def start(self, name, attributes=None):
140
"""Convert HTML opening tag to Markdown equivalent."""
141
142
def end(self, name):
143
"""Convert HTML closing tag to Markdown equivalent."""
144
145
def self_closing(self, name, attributes=None):
146
"""Convert self-closing HTML tag to Markdown equivalent."""
147
148
def append(self, html):
149
"""Append content, converting HTML to Markdown."""
150
151
def as_string(self):
152
"""Get final Markdown output."""
153
```
154
155
Usage example:
156
157
```python
158
from mammoth.writers import writer
159
160
md_writer = writer("markdown")
161
162
# Create Markdown structure
163
md_writer.start("h1")
164
md_writer.text("Hello World")
165
md_writer.end("h1")
166
md_writer.start("p")
167
md_writer.text("This is a paragraph.")
168
md_writer.end("p")
169
170
# Get final Markdown
171
output = md_writer.as_string()
172
print(output) # # Hello World\n\nThis is a paragraph.
173
```
174
175
### Writer Interface
176
177
Abstract base class defining the writer interface.
178
179
```python { .api }
180
class Writer:
181
"""Abstract base class for all writers."""
182
183
def text(self, text):
184
"""Write text content."""
185
raise NotImplementedError()
186
187
def start(self, name, attributes=None):
188
"""Write opening tag."""
189
raise NotImplementedError()
190
191
def end(self, name):
192
"""Write closing tag."""
193
raise NotImplementedError()
194
195
def self_closing(self, name, attributes=None):
196
"""Write self-closing tag."""
197
raise NotImplementedError()
198
199
def append(self, html):
200
"""Append raw content."""
201
raise NotImplementedError()
202
203
def as_string(self):
204
"""Get final output."""
205
raise NotImplementedError()
206
```
207
208
## HTML Generation Functions
209
210
Low-level HTML generation utilities for creating HTML node trees.
211
212
```python { .api }
213
def text(value):
214
"""
215
Create text node.
216
217
Parameters:
218
- value: str, text content
219
220
Returns:
221
TextNode instance
222
"""
223
224
def element(tag_names, attributes=None, children=None,
225
collapsible=None, separator=None):
226
"""
227
Create HTML element nodes.
228
229
Parameters:
230
- tag_names: str or list, HTML element name(s)
231
- attributes: dict, HTML attributes
232
- children: list, child nodes
233
- collapsible: bool, whether element can be collapsed
234
- separator: str, separator for multiple elements
235
236
Returns:
237
Element instance
238
"""
239
240
def collapsible_element(tag_names, attributes=None, children=None):
241
"""
242
Create collapsible HTML elements.
243
244
Parameters:
245
- tag_names: str or list, HTML element name(s)
246
- attributes: dict, HTML attributes
247
- children: list, child nodes
248
249
Returns:
250
Element instance that can be collapsed if empty
251
"""
252
253
def strip_empty(nodes):
254
"""
255
Remove empty elements from node tree.
256
257
Parameters:
258
- nodes: list, HTML nodes
259
260
Returns:
261
List of nodes with empty elements removed
262
"""
263
264
def collapse(nodes):
265
"""
266
Collapse adjacent matching elements.
267
268
Parameters:
269
- nodes: list, HTML nodes
270
271
Returns:
272
List of nodes with adjacent elements collapsed
273
"""
274
275
def write(writer, nodes):
276
"""
277
Write HTML nodes using a writer.
278
279
Parameters:
280
- writer: Writer instance
281
- nodes: list, HTML nodes to write
282
"""
283
```
284
285
### Force Write Constant
286
287
Special constant for forcing elements to be written even if empty.
288
289
```python { .api }
290
force_write = ForceWrite() # Forces element to be written even if empty
291
```
292
293
Usage example:
294
295
```python
296
from mammoth.html import element, text, force_write, write
297
from mammoth.writers import writer
298
299
# Create HTML node tree
300
nodes = [
301
element("div", {"class": "container"}, [
302
element("h1", None, [text("Title")]),
303
element("p", None, [text("Content")]),
304
element("div", {"class": "empty"}, [], force_write) # Force empty div
305
])
306
]
307
308
# Write to HTML
309
html_writer = writer("html")
310
write(html_writer, nodes)
311
output = html_writer.as_string()
312
```
313
314
## Custom Writer Examples
315
316
### Custom XML Writer
317
318
```python
319
from mammoth.writers.abc import Writer
320
321
class XmlWriter(Writer):
322
def __init__(self):
323
self._content = []
324
325
def text(self, text):
326
# Escape XML special characters
327
escaped = text.replace("&", "&").replace("<", "<").replace(">", ">")
328
self._content.append(escaped)
329
330
def start(self, name, attributes=None):
331
tag = f"<{name}"
332
if attributes:
333
for key, value in attributes.items():
334
tag += f' {key}="{value}"'
335
tag += ">"
336
self._content.append(tag)
337
338
def end(self, name):
339
self._content.append(f"</{name}>")
340
341
def self_closing(self, name, attributes=None):
342
tag = f"<{name}"
343
if attributes:
344
for key, value in attributes.items():
345
tag += f' {key}="{value}"'
346
tag += "/>"
347
self._content.append(tag)
348
349
def append(self, content):
350
self._content.append(content)
351
352
def as_string(self):
353
return "".join(self._content)
354
355
# Use custom writer
356
xml_writer = XmlWriter()
357
xml_writer.start("document")
358
xml_writer.start("title")
359
xml_writer.text("My Document")
360
xml_writer.end("title")
361
xml_writer.end("document")
362
363
print(xml_writer.as_string()) # <document><title>My Document</title></document>
364
```