0
# Text Content Rendering
1
2
Plain text rendering system for converting CommonMark documents back to text format with optional newline stripping and custom formatting. The text renderer extracts textual content from AST nodes while preserving document structure and readability.
3
4
## Capabilities
5
6
### Text Content Renderer
7
8
Main rendering class that converts AST nodes to plain text output.
9
10
```java { .api }
11
/**
12
* Renders a tree of nodes to plain text.
13
* Thread-safe renderer that can be reused across multiple rendering operations.
14
*/
15
public class TextContentRenderer implements Renderer {
16
/**
17
* Create a new builder for configuring a TextContentRenderer
18
* @return a builder instance
19
*/
20
public static Builder builder();
21
22
/**
23
* Render the node to text and return as string
24
* @param node the node to render - must not be null
25
* @return the rendered text as a string
26
*/
27
public String render(Node node);
28
29
/**
30
* Render the node to text and append to the given output
31
* @param node the node to render - must not be null
32
* @param output the appendable to write text 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.text.TextContentRenderer;
43
import org.commonmark.node.Node;
44
45
// Basic text rendering
46
Parser parser = Parser.builder().build();
47
TextContentRenderer renderer = TextContentRenderer.builder().build();
48
49
Node document = parser.parse("# Hello\n\nThis is **bold** text with a [link](url).");
50
String text = renderer.render(document);
51
// Result: "Hello\n\nThis is bold text with a link."
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.txt")) {
59
renderer.render(document, writer);
60
}
61
```
62
63
### Text Content Renderer Builder
64
65
Builder class for configuring text renderer instances with custom options and extensions.
66
67
```java { .api }
68
/**
69
* Builder for configuring a TextContentRenderer
70
*/
71
public static class TextContentRenderer.Builder {
72
/**
73
* Build the configured TextContentRenderer instance
74
* @return the configured TextContentRenderer
75
*/
76
public TextContentRenderer build();
77
78
/**
79
* Whether to strip newlines and render everything on one line, defaults to false
80
* @param stripNewlines true to strip newlines, false to preserve line structure
81
* @return this builder
82
*/
83
public Builder stripNewlines(boolean stripNewlines);
84
85
/**
86
* Add a factory for instantiating a node renderer (done when rendering)
87
* @param nodeRendererFactory the factory for creating a node renderer
88
* @return this builder
89
*/
90
public Builder nodeRendererFactory(TextContentNodeRendererFactory nodeRendererFactory);
91
92
/**
93
* Add extensions to use on this text renderer
94
* @param extensions extensions to use on this text renderer
95
* @return this builder
96
*/
97
public Builder extensions(Iterable<? extends Extension> extensions);
98
}
99
```
100
101
**Usage Examples:**
102
103
```java
104
import org.commonmark.renderer.text.TextContentRenderer;
105
106
// Strip newlines for single-line output
107
TextContentRenderer singleLineRenderer = TextContentRenderer.builder()
108
.stripNewlines(true)
109
.build();
110
111
Node document = parser.parse("# Title\n\nParagraph one.\n\nParagraph two.");
112
String singleLine = singleLineRenderer.render(document);
113
// Result: "Title Paragraph one. Paragraph two."
114
115
// Preserve line structure (default)
116
TextContentRenderer structuredRenderer = TextContentRenderer.builder()
117
.stripNewlines(false)
118
.build();
119
120
String structured = structuredRenderer.render(document);
121
// Result: "Title\n\nParagraph one.\n\nParagraph two."
122
```
123
124
### Text Content Renderer Extension System
125
126
Extension interfaces and classes for customizing text rendering behavior.
127
128
```java { .api }
129
/**
130
* Extension interface for text content renderer
131
*/
132
public interface TextContentRenderer.TextContentRendererExtension extends Extension {
133
/**
134
* Extend the text content renderer builder with custom functionality
135
* @param rendererBuilder the builder to extend
136
*/
137
void extend(TextContentRenderer.Builder rendererBuilder);
138
}
139
140
/**
141
* Factory for text content node renderers
142
*/
143
public interface TextContentNodeRendererFactory {
144
/**
145
* Create a node renderer with the given context
146
* @param context the rendering context
147
* @return a node renderer instance
148
*/
149
NodeRenderer create(TextContentNodeRendererContext context);
150
}
151
152
/**
153
* Context for text content node rendering
154
*/
155
public interface TextContentNodeRendererContext {
156
/**
157
* Whether newlines should be stripped
158
* @return true if newlines should be stripped
159
*/
160
boolean stripNewlines();
161
162
/**
163
* Get the text content writer
164
* @return the text content writer
165
*/
166
TextContentWriter getWriter();
167
168
/**
169
* Render a child node
170
* @param node the node to render
171
*/
172
void render(Node node);
173
}
174
```
175
176
### Text Content Writer
177
178
Low-level text writing utility used by node renderers.
179
180
```java { .api }
181
/**
182
* Helper for writing text content
183
*/
184
public class TextContentWriter {
185
/**
186
* Create a text content writer that writes to the given appendable
187
* @param out the appendable to write to
188
*/
189
public TextContentWriter(Appendable out);
190
191
/**
192
* Write whitespace (space character)
193
*/
194
public void whitespace();
195
196
/**
197
* Write a colon character
198
*/
199
public void colon();
200
201
/**
202
* Write a line break
203
*/
204
public void line();
205
206
/**
207
* Write text content, stripping newlines if configured
208
* @param s the text to write
209
*/
210
public void writeStripped(String s);
211
212
/**
213
* Write text content as-is
214
* @param s the text to write
215
*/
216
public void write(String s);
217
218
/**
219
* Write a single character
220
* @param c the character to write
221
*/
222
public void write(char c);
223
}
224
```
225
226
**Usage Examples:**
227
228
```java
229
import org.commonmark.renderer.text.TextContentWriter;
230
231
// Custom text writer usage
232
StringBuilder output = new StringBuilder();
233
TextContentWriter writer = new TextContentWriter(output);
234
235
writer.write("Hello");
236
writer.whitespace();
237
writer.write("world");
238
writer.line();
239
writer.writeStripped("Text with\nnewlines"); // May strip newlines based on configuration
240
```
241
242
### Core Text Content Node Renderer
243
244
The built-in renderer that handles all core CommonMark nodes for text output.
245
246
```java { .api }
247
/**
248
* Core text content renderer for built-in nodes
249
*/
250
public class CoreTextContentNodeRenderer extends AbstractVisitor implements NodeRenderer {
251
/**
252
* Create a core text content node renderer with the given context
253
* @param context the rendering context
254
*/
255
public CoreTextContentNodeRenderer(TextContentNodeRendererContext context);
256
257
/**
258
* Get the node types this renderer handles
259
* @return set of node types
260
*/
261
public Set<Class<? extends Node>> getNodeTypes();
262
263
/**
264
* Render the specified node
265
* @param node the node to render
266
*/
267
public void render(Node node);
268
269
// Visit methods for all core node types (inherited from AbstractVisitor)
270
}
271
```
272
273
## Text Rendering Behavior
274
275
The text content renderer handles different node types with specific text extraction logic:
276
277
### Block Elements
278
- **Document**: Renders all child blocks with appropriate spacing
279
- **Heading**: Renders heading text followed by double newline
280
- **Paragraph**: Renders paragraph text followed by double newline
281
- **BlockQuote**: Renders quoted text with standard spacing
282
- **Code Blocks**: Renders code content with appropriate line breaks
283
- **Lists**: Renders list items with appropriate spacing and structure
284
- **Thematic Break**: Renders as empty (no text content)
285
- **HTML Blocks**: Renders as empty (HTML content stripped)
286
287
### Inline Elements
288
- **Text**: Renders literal text content
289
- **Code**: Renders code content without backticks
290
- **Emphasis/Strong**: Renders emphasized text without formatting markers
291
- **Link**: Renders link text content (URL is ignored)
292
- **Image**: Renders alt text content
293
- **Line Breaks**: Renders as space or newline depending on type
294
- **HTML Inline**: Renders as empty (HTML content stripped)
295
296
**Usage Examples:**
297
298
```java
299
import org.commonmark.renderer.text.TextContentRenderer;
300
import org.commonmark.renderer.text.TextContentNodeRendererFactory;
301
import org.commonmark.renderer.text.TextContentNodeRendererContext;
302
import org.commonmark.renderer.NodeRenderer;
303
import org.commonmark.node.CustomNode;
304
305
// Custom text node renderer
306
public class CustomTextRenderer implements NodeRenderer {
307
private final TextContentNodeRendererContext context;
308
private final TextContentWriter writer;
309
310
public CustomTextRenderer(TextContentNodeRendererContext context) {
311
this.context = context;
312
this.writer = context.getWriter();
313
}
314
315
@Override
316
public Set<Class<? extends Node>> getNodeTypes() {
317
return Collections.singleton(CustomNode.class);
318
}
319
320
@Override
321
public void render(Node node) {
322
CustomNode customNode = (CustomNode) node;
323
324
writer.write("[CUSTOM: ");
325
renderChildren(customNode);
326
writer.write("]");
327
}
328
329
private void renderChildren(Node parent) {
330
Node child = parent.getFirstChild();
331
while (child != null) {
332
context.render(child);
333
child = child.getNext();
334
}
335
}
336
}
337
338
// Register custom text renderer
339
TextContentRenderer renderer = TextContentRenderer.builder()
340
.nodeRendererFactory(context -> new CustomTextRenderer(context))
341
.build();
342
343
// Demonstrate different rendering modes
344
Parser parser = Parser.builder().build();
345
Node document = parser.parse(
346
"# Title\n\n" +
347
"This is a paragraph with **bold** text and a [link](url).\n\n" +
348
"- List item 1\n" +
349
"- List item 2\n\n" +
350
"```java\n" +
351
"System.out.println(\"code\");\n" +
352
"```"
353
);
354
355
// Default text rendering (preserves structure)
356
TextContentRenderer defaultRenderer = TextContentRenderer.builder().build();
357
String structured = defaultRenderer.render(document);
358
System.out.println("Structured:\n" + structured);
359
360
// Single-line text rendering
361
TextContentRenderer singleLineRenderer = TextContentRenderer.builder()
362
.stripNewlines(true)
363
.build();
364
String singleLine = singleLineRenderer.render(document);
365
System.out.println("Single line: " + singleLine);
366
```
367
368
## Common Use Cases
369
370
### Extract Plain Text from Markdown
371
```java
372
// Convert Markdown to plain text for search indexing
373
String markdown = "# Article Title\n\nThis **article** discusses [CommonMark](url).";
374
Node document = parser.parse(markdown);
375
String plainText = textRenderer.render(document);
376
// Use plainText for full-text search, previews, etc.
377
```
378
379
### Generate Text Summaries
380
```java
381
// Generate single-line summary
382
TextContentRenderer summaryRenderer = TextContentRenderer.builder()
383
.stripNewlines(true)
384
.build();
385
String summary = summaryRenderer.render(document);
386
// Use summary for meta descriptions, previews, etc.
387
```
388
389
### Extract Headings for Table of Contents
390
```java
391
// Custom renderer to extract only headings
392
public class HeadingExtractor implements NodeRenderer {
393
// Implementation that only renders heading text
394
}
395
```