MarkdownViewer
The MarkdownViewer component renders markdown text as HTML. It supports standard markdown syntax including headers, lists, code blocks, links, images, and emoji rendering. The component also provides progressive rendering, which displays content character-by-character for a typewriter effect.
Setting content
Create a MarkdownViewer with or without initial content, then update it using setContent():
MarkdownViewer viewer = new MarkdownViewer("# Hello World");
// Replace content entirely
viewer.setContent("""
## New Content
- Item 1
- Item 2
""");
// Get current content
String content = viewer.getContent();
The component implements HasText, so setText() and getText() work as aliases for the content methods.
Mostrar Código
- Java
Appending content
The append() method adds content incrementally without replacing what's already there:
viewer.append("## New Section\n\n");
viewer.append("More content here...");
By default, appended content appears immediately. When progressive rendering is enabled, appended content goes into a buffer and displays character-by-character instead.
Auto-scroll
Enable auto-scroll to keep the viewport at the bottom as content grows. This works with any method of adding content, whether setContent(), append(), or progressive rendering. If a user manually scrolls up to review earlier content, auto-scroll pauses and resumes when they scroll back to the bottom.
viewer.setAutoScroll(true);
Progressive rendering
Progressive rendering displays content character-by-character rather than all at once, creating a typewriter effect. AI chat interfaces commonly use this to show responses appearing gradually:
MarkdownViewer viewer = new MarkdownViewer();
viewer.setProgressiveRender(true);
When enabled, content added via setContent() or append() goes into a buffer and displays incrementally. When disabled, content appears immediately.
Mostrar Código
- Java
Render speed
The setRenderSpeed() method controls how many characters render per animation frame. Higher values mean faster rendering. At 60fps, the default speed of 4 translates to approximately 240 characters per second:
| Speed | Characters/Second |
|---|---|
| 4 (default) | ~240 |
| 6 | ~360 |
| 10 | ~600 |
viewer.setRenderSpeed(6);
If your server sends content faster than the viewer renders, the buffer grows and displayed content lags behind. Increase renderSpeed to keep pace, or call flush() when all content has been received to display remaining content immediately.
Render state
When progressive rendering is enabled, the isRendering() method returns true while the component is actively displaying buffered content. Chat interfaces often use this to show or hide a stop button:
if (viewer.isRendering()) {
stopButton.setVisible(true);
}
This method always returns false when progressive rendering is disabled.
Controlling rendering
Two methods control how progressive rendering stops:
stop()halts rendering and discards any buffered content not yet displayed. Call this when the user cancels.flush()halts rendering but immediately displays all remaining buffered content. Call this when all content has been received and you want to show it without waiting.
// User clicked "Stop generating"
viewer.stop();
// All content received, show everything now
viewer.flush();
These methods have no effect when progressive rendering is disabled.
Waiting for completion
The whenRenderComplete() method returns a PendingResult that completes when progressive rendering finishes displaying all buffered content:
viewer.whenRenderComplete().thenAccept(v -> {
inputField.setEnabled(true);
inputField.focus();
});
If progressive rendering isn't enabled or no content is being rendered, the PendingResult completes immediately.
When using progressive rendering, don't re-enable input fields based solely on when you finish calling append(). The renderer may still be displaying buffered content. Wait for whenRenderComplete() so all content appears before users can interact again.
The following demo simulates an AI chat interface using append() with progressive rendering enabled:
Mostrar Código
- Java
Clearing content
Remove all content with clear():
viewer.clear();
If progressive rendering is active, clear() also stops rendering and completes any pending whenRenderComplete() results.
Syntax highlighting
The MarkdownViewer supports syntax highlighting for code blocks when Prism.js is available. Add Prism.js to your app using the @JavaScript and @StyleSheet annotations:
@StyleSheet("https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-tomorrow.min.css")
@JavaScript(
value = "https://cdn.jsdelivr.net/combine/npm/prismjs@1/prism.min.js,npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js",
top = true
)
public class Application extends App {
// ...
}
The autoloader plugin loads language definitions as needed, so code blocks with language hints like ```java or ```python get highlighted automatically.