0
# HTML Rendering
1
2
High-performance HTML rendering system with extensive customization options including URL sanitization, attribute providers, custom node renderers, and output formatting controls. The HTML renderer converts CommonMark AST nodes into clean, standards-compliant HTML output.
3
4
## Capabilities
5
6
### HTML Renderer
7
8
Main rendering class that converts AST nodes to HTML output.
9
10
```java { .api }
11
/**
12
* Renders a tree of nodes to HTML.
13
* Thread-safe renderer that can be reused across multiple rendering operations.
14
*/
15
public class HtmlRenderer implements Renderer {
16
/**
17
* Create a new builder for configuring an HtmlRenderer
18
* @return a builder instance
19
*/
20
public static Builder builder();
21
22
/**
23
* Render the node to HTML and return as string
24
* @param node the node to render - must not be null
25
* @return the rendered HTML as a string
26
*/
27
public String render(Node node);
28
29
/**
30
* Render the node to HTML and append to the given output
31
* @param node the node to render - must not be null
32
* @param output the appendable to write HTML to
33
*/
34
public void render(Node node, Appendable output);
35
}
36
```
37
38
**Usage Examples:**
39
40
```java
41
import org.commonmark.parser.Parser;
42
import org.commonmark.renderer.html.HtmlRenderer;
43
import org.commonmark.node.Node;
44
45
// Basic HTML rendering
46
Parser parser = Parser.builder().build();
47
HtmlRenderer renderer = HtmlRenderer.builder().build();
48
49
Node document = parser.parse("# Hello\n\nThis is **bold** text.");
50
String html = renderer.render(document);
51
// Result: <h1>Hello</h1>\n<p>This is <strong>bold</strong> text.</p>\n
52
53
// Render to StringBuilder
54
StringBuilder sb = new StringBuilder();
55
renderer.render(document, sb);
56
57
// Render to file
58
try (FileWriter writer = new FileWriter("output.html")) {
59
renderer.render(document, writer);
60
}
61
```
62
63
### HTML Renderer Builder
64
65
Builder class for configuring HTML renderer instances with custom options and extensions.
66
67
```java { .api }
68
/**
69
* Builder for configuring an HtmlRenderer
70
*/
71
public static class HtmlRenderer.Builder {
72
/**
73
* Build the configured HtmlRenderer instance
74
* @return the configured HtmlRenderer
75
*/
76
public HtmlRenderer build();
77
78
/**
79
* The HTML to use for rendering a softbreak, defaults to "\n"
80
* Set it to "<br>" to make them hard breaks
81
* Set it to " " to ignore line wrapping in the source
82
* @param softbreak HTML for softbreak
83
* @return this builder
84
*/
85
public Builder softbreak(String softbreak);
86
87
/**
88
* Whether HtmlInline and HtmlBlock should be escaped, defaults to false
89
* @param escapeHtml true for escaping, false for preserving raw HTML
90
* @return this builder
91
*/
92
public Builder escapeHtml(boolean escapeHtml);
93
94
/**
95
* Whether Image src and Link href should be sanitized, defaults to false
96
* @param sanitizeUrls true for sanitization, false for preserving raw attribute
97
* @return this builder
98
*/
99
public Builder sanitizeUrls(boolean sanitizeUrls);
100
101
/**
102
* UrlSanitizer used to filter URLs if sanitizeUrls is true
103
* @param urlSanitizer Filterer used to filter Image src and Link href
104
* @return this builder
105
*/
106
public Builder urlSanitizer(UrlSanitizer urlSanitizer);
107
108
/**
109
* Whether URLs of link or images should be percent-encoded, defaults to false
110
* @param percentEncodeUrls true to percent-encode, false for leaving as-is
111
* @return this builder
112
*/
113
public Builder percentEncodeUrls(boolean percentEncodeUrls);
114
115
/**
116
* Add a factory for an attribute provider for adding/changing HTML attributes to the rendered tags
117
* @param attributeProviderFactory the attribute provider factory to add
118
* @return this builder
119
*/
120
public Builder attributeProviderFactory(AttributeProviderFactory attributeProviderFactory);
121
122
/**
123
* Add a factory for instantiating a node renderer (done when rendering)
124
* @param nodeRendererFactory the factory for creating a node renderer
125
* @return this builder
126
*/
127
public Builder nodeRendererFactory(HtmlNodeRendererFactory nodeRendererFactory);
128
129
/**
130
* Add extensions to use on this HTML renderer
131
* @param extensions extensions to use on this HTML renderer
132
* @return this builder
133
*/
134
public Builder extensions(Iterable<? extends Extension> extensions);
135
}
136
```
137
138
**Usage Examples:**
139
140
```java
141
import org.commonmark.renderer.html.HtmlRenderer;
142
import org.commonmark.renderer.html.AttributeProvider;
143
144
// Custom softbreak handling
145
HtmlRenderer brRenderer = HtmlRenderer.builder()
146
.softbreak("<br>\n")
147
.build();
148
149
// Escape HTML content
150
HtmlRenderer safeRenderer = HtmlRenderer.builder()
151
.escapeHtml(true)
152
.build();
153
154
// URL sanitization
155
HtmlRenderer sanitizedRenderer = HtmlRenderer.builder()
156
.sanitizeUrls(true)
157
.percentEncodeUrls(true)
158
.build();
159
160
// Custom attribute provider
161
HtmlRenderer customRenderer = HtmlRenderer.builder()
162
.attributeProviderFactory(context -> new AttributeProvider() {
163
@Override
164
public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
165
if (node instanceof Heading) {
166
attributes.put("class", "heading-" + ((Heading) node).getLevel());
167
}
168
}
169
})
170
.build();
171
```
172
173
### HTML Renderer Extension System
174
175
Extension interfaces and classes for customizing HTML rendering behavior.
176
177
```java { .api }
178
/**
179
* Extension interface for HTML renderer
180
*/
181
public interface HtmlRenderer.HtmlRendererExtension extends Extension {
182
/**
183
* Extend the HTML renderer builder with custom functionality
184
* @param rendererBuilder the builder to extend
185
*/
186
void extend(HtmlRenderer.Builder rendererBuilder);
187
}
188
189
/**
190
* Factory for HTML node renderers
191
*/
192
public interface HtmlNodeRendererFactory {
193
/**
194
* Create a node renderer with the given context
195
* @param context the rendering context
196
* @return a node renderer instance
197
*/
198
NodeRenderer create(HtmlNodeRendererContext context);
199
}
200
201
/**
202
* Context for HTML node rendering
203
*/
204
public interface HtmlNodeRendererContext {
205
/**
206
* Whether HTML should be escaped
207
* @return true if HTML should be escaped
208
*/
209
boolean shouldEscapeHtml();
210
211
/**
212
* Whether URLs should be sanitized
213
* @return true if URLs should be sanitized
214
*/
215
boolean shouldSanitizeUrls();
216
217
/**
218
* Get the URL sanitizer
219
* @return the URL sanitizer
220
*/
221
UrlSanitizer urlSanitizer();
222
223
/**
224
* Encode a URL if percent encoding is enabled
225
* @param url the URL to encode
226
* @return the encoded URL
227
*/
228
String encodeUrl(String url);
229
230
/**
231
* Extend attributes for a node and tag
232
* @param node the node being rendered
233
* @param tagName the HTML tag name
234
* @param attributes the current attributes
235
* @return the extended attributes
236
*/
237
Map<String, String> extendAttributes(Node node, String tagName, Map<String, String> attributes);
238
239
/**
240
* Get the HTML writer
241
* @return the HTML writer
242
*/
243
HtmlWriter getWriter();
244
245
/**
246
* Get the softbreak string
247
* @return the softbreak HTML
248
*/
249
String getSoftbreak();
250
251
/**
252
* Render a child node
253
* @param node the node to render
254
*/
255
void render(Node node);
256
}
257
```
258
259
### Attribute Provider System
260
261
System for adding custom HTML attributes to rendered elements.
262
263
```java { .api }
264
/**
265
* Provides attributes for HTML elements
266
*/
267
public interface AttributeProvider {
268
/**
269
* Set attributes for the specified node and tag
270
* @param node the node being rendered
271
* @param tagName the HTML tag name
272
* @param attributes the attributes map to modify
273
*/
274
void setAttributes(Node node, String tagName, Map<String, String> attributes);
275
}
276
277
/**
278
* Factory for attribute providers
279
*/
280
public interface AttributeProviderFactory {
281
/**
282
* Create an attribute provider with the given context
283
* @param context the attribute provider context
284
* @return an attribute provider instance
285
*/
286
AttributeProvider create(AttributeProviderContext context);
287
}
288
289
/**
290
* Context for attribute providers
291
*/
292
public interface AttributeProviderContext {
293
// Context methods for attribute provision
294
}
295
```
296
297
**Usage Examples:**
298
299
```java
300
import org.commonmark.renderer.html.AttributeProvider;
301
import org.commonmark.node.*;
302
303
// Add CSS classes to headings
304
AttributeProvider headingClassProvider = new AttributeProvider() {
305
@Override
306
public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
307
if (node instanceof Heading) {
308
Heading heading = (Heading) node;
309
attributes.put("class", "heading heading-" + heading.getLevel());
310
}
311
}
312
};
313
314
// Add target="_blank" to external links
315
AttributeProvider externalLinkProvider = new AttributeProvider() {
316
@Override
317
public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
318
if (node instanceof Link && tagName.equals("a")) {
319
Link link = (Link) node;
320
if (link.getDestination().startsWith("http")) {
321
attributes.put("target", "_blank");
322
attributes.put("rel", "noopener");
323
}
324
}
325
}
326
};
327
328
// Use providers
329
HtmlRenderer renderer = HtmlRenderer.builder()
330
.attributeProviderFactory(context -> headingClassProvider)
331
.attributeProviderFactory(context -> externalLinkProvider)
332
.build();
333
```
334
335
### URL Sanitization
336
337
System for sanitizing URLs in links and images for security.
338
339
```java { .api }
340
/**
341
* Sanitizes URLs in links and images
342
*/
343
public interface UrlSanitizer {
344
/**
345
* Sanitize a link URL
346
* @param url the URL to sanitize
347
* @return the sanitized URL, or null to remove the URL
348
*/
349
String sanitizeLinkUrl(String url);
350
351
/**
352
* Sanitize an image URL
353
* @param url the URL to sanitize
354
* @return the sanitized URL, or null to remove the URL
355
*/
356
String sanitizeImageUrl(String url);
357
}
358
359
/**
360
* Default URL sanitizer implementation
361
*/
362
public class DefaultUrlSanitizer implements UrlSanitizer {
363
/**
364
* Sanitize a link URL - allows http, https, ftp, mailto
365
* @param url the URL to sanitize
366
* @return the sanitized URL, or null if not allowed
367
*/
368
public String sanitizeLinkUrl(String url);
369
370
/**
371
* Sanitize an image URL - allows http, https, data
372
* @param url the URL to sanitize
373
* @return the sanitized URL, or null if not allowed
374
*/
375
public String sanitizeImageUrl(String url);
376
}
377
```
378
379
**Usage Examples:**
380
381
```java
382
import org.commonmark.renderer.html.UrlSanitizer;
383
import org.commonmark.renderer.html.DefaultUrlSanitizer;
384
385
// Custom URL sanitizer
386
UrlSanitizer strictSanitizer = new UrlSanitizer() {
387
@Override
388
public String sanitizeLinkUrl(String url) {
389
// Only allow https URLs
390
if (url.startsWith("https://")) {
391
return url;
392
}
393
return null; // Remove unsafe URLs
394
}
395
396
@Override
397
public String sanitizeImageUrl(String url) {
398
// Only allow https images or data URLs
399
if (url.startsWith("https://") || url.startsWith("data:image/")) {
400
return url;
401
}
402
return null;
403
}
404
};
405
406
HtmlRenderer renderer = HtmlRenderer.builder()
407
.sanitizeUrls(true)
408
.urlSanitizer(strictSanitizer)
409
.build();
410
```
411
412
### HTML Writer
413
414
Low-level HTML writing utility used by node renderers.
415
416
```java { .api }
417
/**
418
* Helper for writing HTML output
419
*/
420
public class HtmlWriter {
421
/**
422
* Create an HTML writer that writes to the given appendable
423
* @param out the appendable to write to
424
*/
425
public HtmlWriter(Appendable out);
426
427
/**
428
* Write raw HTML content (not escaped)
429
* @param s the raw HTML to write
430
*/
431
public void raw(String s);
432
433
/**
434
* Write text content (HTML-escaped)
435
* @param text the text to write
436
*/
437
public void text(String text);
438
439
/**
440
* Write an HTML tag with no attributes
441
* @param name the tag name
442
*/
443
public void tag(String name);
444
445
/**
446
* Write an HTML tag with attributes
447
* @param name the tag name
448
* @param attrs the attributes map
449
*/
450
public void tag(String name, Map<String, String> attrs);
451
452
/**
453
* Write an HTML tag with attributes, specifying if it's a void element
454
* @param name the tag name
455
* @param attrs the attributes map
456
* @param voidElement true if this is a void element (like <br>)
457
*/
458
public void tag(String name, Map<String, String> attrs, boolean voidElement);
459
460
/**
461
* Write a line break
462
*/
463
public void line();
464
}
465
```
466
467
### Core HTML Node Renderer
468
469
The built-in renderer that handles all core CommonMark nodes.
470
471
```java { .api }
472
/**
473
* Core HTML renderer for built-in nodes
474
*/
475
public class CoreHtmlNodeRenderer extends AbstractVisitor implements NodeRenderer {
476
/**
477
* Create a core HTML node renderer with the given context
478
* @param context the rendering context
479
*/
480
public CoreHtmlNodeRenderer(HtmlNodeRendererContext context);
481
482
/**
483
* Get the node types this renderer handles
484
* @return set of node types
485
*/
486
public Set<Class<? extends Node>> getNodeTypes();
487
488
/**
489
* Render the specified node
490
* @param node the node to render
491
*/
492
public void render(Node node);
493
494
// Visit methods for all core node types (inherited from AbstractVisitor)
495
}
496
```
497
498
**Usage Examples:**
499
500
```java
501
import org.commonmark.renderer.html.HtmlWriter;
502
import org.commonmark.renderer.html.HtmlNodeRendererContext;
503
import org.commonmark.renderer.NodeRenderer;
504
import org.commonmark.node.CustomBlock;
505
506
// Custom node renderer example
507
public class CustomBlockRenderer implements NodeRenderer {
508
private final HtmlNodeRendererContext context;
509
private final HtmlWriter html;
510
511
public CustomBlockRenderer(HtmlNodeRendererContext context) {
512
this.context = context;
513
this.html = context.getWriter();
514
}
515
516
@Override
517
public Set<Class<? extends Node>> getNodeTypes() {
518
return Collections.singleton(CustomBlock.class);
519
}
520
521
@Override
522
public void render(Node node) {
523
CustomBlock customBlock = (CustomBlock) node;
524
525
Map<String, String> attrs = new HashMap<>();
526
attrs.put("class", "custom-block");
527
528
html.tag("div", context.extendAttributes(node, "div", attrs));
529
renderChildren(customBlock);
530
html.tag("/div");
531
}
532
533
private void renderChildren(Node parent) {
534
Node child = parent.getFirstChild();
535
while (child != null) {
536
context.render(child);
537
child = child.getNext();
538
}
539
}
540
}
541
542
// Register custom renderer
543
HtmlRenderer renderer = HtmlRenderer.builder()
544
.nodeRendererFactory(context -> new CustomBlockRenderer(context))
545
.build();
546
```