StreamMarkdown class
A widget that renders Markdown content from a stream in real-time.
StreamMarkdown is designed specifically for streaming scenarios where markdown content arrives incrementally, such as AI chat responses, live documentation updates, or collaborative editing. It efficiently accumulates and renders text chunks as they arrive from a stream.
Basic Usage
StreamController<String> controller = StreamController<String>();
// Display the streaming widget
StreamMarkdown(
stream: controller.stream,
styleSheet: MarkdownStyleSheet.light(),
)
// Later, send chunks to the stream
controller.add('# Hello\n\n');
await Future.delayed(Duration(milliseconds: 100));
controller.add('This is **streaming** ');
await Future.delayed(Duration(milliseconds: 100));
controller.add('markdown!');
Use Cases
AI Chat Applications: Perfect for displaying streaming LLM responses
StreamMarkdown(
stream: openAI.streamCompletion(prompt),
styleSheet: MarkdownStyleSheet.github(),
useEnhancedComponents: true,
)
Live Collaboration: Show real-time updates from multiple users
StreamMarkdown(
stream: firestore
.collection('documents')
.doc(docId)
.snapshots()
.map((doc) => doc.data()['content'] as String),
styleSheet: MarkdownStyleSheet.light(),
)
Progressive Loading: Display content as it loads from network
StreamMarkdown(
stream: fetchLargeDocument(),
loadingWidget: Center(child: CircularProgressIndicator()),
)
How It Works
- The widget listens to the provided stream
- Each chunk received is appended to an internal buffer
- The accumulated text is parsed and rendered on each update
- The UI updates smoothly as new content arrives
Performance Considerations
- The widget re-parses and re-renders the entire accumulated content on each chunk
- For very large documents with frequent updates, consider batching chunks
- The parsing is fast (AST-based), but very large documents may cause frame drops
- Consider using SmoothMarkdown for static content instead
Error Handling
Currently, stream errors are silently ignored. The errorBuilder parameter is
available but not yet fully implemented. To handle errors:
final stream = sourceStream.handleError((error) {
print('Stream error: $error');
// You can transform errors or rethrow
});
StreamMarkdown(stream: stream)
See also:
- SmoothMarkdown, for static markdown content
- MarkdownStyleSheet, for customizing the visual appearance
- MarkdownConfig, for configuring parsing behavior
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- StreamMarkdown
Constructors
-
StreamMarkdown({required Stream<
String> stream, Key? key, MarkdownStyleSheet? styleSheet, MarkdownConfig? config, void onTapLink(String url)?, Widget imageBuilder(String url, String? alt, String? title)?, Widget codeBuilder(String code, String? language)?, bool useEnhancedComponents = false, Widget? loadingWidget, Widget errorBuilder(Object error)?, ParserPluginRegistry? plugins, BuilderRegistry? builderRegistry}) -
Creates a widget that renders streaming Markdown content.
const
Properties
- builderRegistry → BuilderRegistry?
-
Custom widget builder registry for rendering plugin nodes.
final
- codeBuilder → Widget Function(String code, String? language)?
-
Custom widget builder for rendering code blocks.
final
- config → MarkdownConfig?
-
Configuration options for Markdown parsing behavior.
final
- errorBuilder → Widget Function(Object error)?
-
Custom widget builder for displaying stream errors.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- imageBuilder → Widget Function(String url, String? alt, String? title)?
-
Custom widget builder for rendering images.
final
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- loadingWidget → Widget?
-
Widget to display while waiting for the first chunk from the stream.
final
- onTapLink → void Function(String url)?
-
Callback function invoked when a user taps on a link.
final
- plugins → ParserPluginRegistry?
-
Parser plugins for extending markdown syntax.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
stream
→ Stream<
String> -
The stream of Markdown text chunks to render.
final
- styleSheet → MarkdownStyleSheet?
-
The style sheet used to control the visual appearance of rendered markdown.
final
- useEnhancedComponents → bool
-
Whether to use enhanced UI components with additional visual effects.
final
Methods
-
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< StreamMarkdown> -
Creates the mutable state for this widget at a given location in the tree.
override
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited