animated_streaming_markdown chatbot demo with render-backed selection

Contributors Forks Stargazers Issues License Pub Version


animated_streaming_markdown logo

animated_streaming_markdown

Streaming Markdown parser + renderer for Flutter, optimized for incremental append flows. Native targets and Flutter web are supported, including zero-config Tree-sitter WASM assets for published builds.
Explore the docs »

View Demo · Report Bug · Request Feature

Latest Update

  • 0.3.6 selection architecture: selection is now projected from stable source ranges through render-backed selectable text, including partial cell selection and cross-block table drags.
  • Selection auto-scroll: dragging at viewport edges scrolls vertically, while wide tables also scroll horizontally near their left and right edges.
  • Animation without layout jolts: settled word tokens compact into lighter static spans while preserving token geometry; the example defaults to the original Fade preset and also includes Gravity.
  • Flutter web is first-class: published builds include the generated Tree-sitter WASM parser asset, so app developers do not need to edit web/index.html or copy files manually.
  • KaTeX-style LaTeX rendering: inline $...$ / \(...\) and display $$...$$ / \[...\] math now render through flutter_math_fork, a pure Dart/Flutter KaTeX parser and renderer.
  • Real chatbot example: the example app can connect to local Ollama plus ChatGPT/OpenAI, Claude, Gemini, and Grok-compatible cloud APIs.
Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Documentation
  5. Roadmap
  6. Contributing
  7. License
  8. Contact
  9. Acknowledgments

About The Project

animated_streaming_markdown provides 2 main layers:

  • Parser: MarkdownStreamParser for typed replace/append requests
  • Renderer: AnimatedStreamingMarkdown for block rendering, token reveal animations, inline images, links, selection, and KaTeX-compatible LaTeX math
  • Tables: stable shared-width Markdown tables with left-aligned viewport framing and row-by-row reveal during streaming

It is designed for chat-like or streaming text interfaces where markdown arrives progressively and needs stable UI updates.

(back to top)

Built With

  • Flutter
  • Dart
  • Tree-sitter

(back to top)

Getting Started

Prerequisites

  • Flutter >=3.0.0
  • Dart SDK >=3.0.0 <4.0.0
  • Native toolchain for your target platform (Android/iOS/macOS/Linux/Windows)
  • No extra setup is required for Flutter web consumers; the package ships the generated WASM parser asset and falls back safely when needed.

Installation

  1. Add dependency:
    dependencies:
     animated_streaming_markdown: ^0.3.6
    
  2. Install packages:
    flutter pub get
    

(back to top)

Usage

1) Start parser worker and stream markdown

final parser = MarkdownStreamParser();
await parser.start();

final setResult = await parser.replace('# Hello');

final appendResult = await parser.append('\n\nStreaming **markdown** chunk...');

2) Render blocks with AnimatedStreamingMarkdown

AnimatedStreamingMarkdown(
  blocks: appendResult.blocks,
  asSliver: true,
  tokenStaggerDelay: const Duration(milliseconds: 180),
  tokenAnimationDuration: const Duration(milliseconds: 240),
  enableSelection: true,
);

The built-in animation is a Fade reveal. Supply tokenAnimationBuilder only when opting into a custom effect such as Gravity or Rotate in.

3) Render LaTeX math with KaTeX-compatible syntax

LaTeX is supported in both inline and display forms:

AnimatedStreamingMarkdown.fromMarkdown(
  markdown: r'''
Inline math: $x^2 + y^2 = z^2$

Display math:

$$
\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
$$
''',
);

Use latexBuilder to wrap or replace the default flutter_math_fork widget:

AnimatedStreamingMarkdown(
  blocks: appendResult.blocks,
  latexBuilder: (context, latex) {
    return latex.defaultWidget;
  },
);

4) Important APIs

  • MarkdownStreamParser.start()
  • MarkdownStreamParser.replace(markdown)
  • MarkdownStreamParser.append(chunk)
  • MarkdownStreamParser.parse(operation, text)
  • MarkdownStreamParser.dispose()
  • MarkdownSyncParser.parseMarkdown(markdown)
  • warmUpStreamingMarkdownParser(includeWorker: true)
  • AnimatedStreamingMarkdown(...)
  • AnimatedStreamingMarkdown.fromMarkdown(...)
    • blocks
    • asSliver
    • tokenStaggerDelay
    • tokenAnimationDuration / tokenAnimationDurationFactor
    • tokenAnimationBuilder
    • tokenCompaction
    • onTokenDelay
    • showCodeBlockCopyButton
    • enableSelection
    • selectionStrategy
    • blockBuilder
    • imageBuilder
    • latexBuilder

For a complete integration sample, check example/lib/src/demos/markdown_cases_demo.dart. For the full chatbot sample with Ollama, ChatGPT/OpenAI, Claude, Gemini, and Grok providers, check example/lib/main.dart.

Documentation

The documentation site is built with Docusaurus from docs/ and deployed to GitHub Pages by Deploy Documentation.

Run the docs site locally:

cd website
npm ci
npm run start

Build the static site:

cd website
npm run build

Migration notes for 0.3.0

0.3.0 keeps the 0.2.x API available, but the preferred names now describe the package behavior more directly:

0.2.x name 0.3.x preferred name
StreamingMarkdownParseWorker MarkdownStreamParser
request(op: 'set', ...) replace(markdown)
request(op: 'append', ...) append(chunk)
StreamingMarkdownParseResult.renderNodes MarkdownParseResult.blocks
StreamingMarkdownRenderView AnimatedStreamingMarkdown
nodes blocks
sliver asSliver
tokenArrivalDelay tokenStaggerDelay
tokenFadeInDuration tokenAnimationDuration
tokenFadeInRelativeToDelay tokenAnimationDurationFactor
allowUnclosedInlineDelimiters allowIncompleteInlineSyntax
enableTextSelection enableSelection
customBlockBuilder blockBuilder
markdownTheme theme

(back to top)

Roadmap

  • Done: Incremental parser worker (replace / append)
  • Done: Streaming renderer for markdown block nodes
  • Done: Per-token custom animation builder API
  • Done: Example with multiple animation presets
  • Done: Docusaurus documentation site for samnn.dev
  • Done: Convenience constructors and sync parser helpers
  • Done: Opt-in code block copy button
  • Done: KaTeX-compatible LaTeX math rendering
  • Done: Render-backed selection with stable ranges, table traversal, and edge auto-scroll
  • Next: Performance optimization across parser, rendering, token compaction, and benchmarks
  • Next: Feature development guided by real application requirements and user requests

See the open issues for proposed features and known issues.

(back to top)

Contributing

Contributions are welcome.

  1. Fork the project
  2. Create your branch (git checkout -b feature/your-feature)
  3. Commit your changes (git commit -m "Add your feature")
  4. Push branch (git push origin feature/your-feature)
  5. Open a Pull Request

See CONTRIBUTING.md for local setup, repository layout, and quality gates.

(back to top)

License

Distributed under the Apache-2.0 License. See LICENSE for details.

(back to top)

Contact

(back to top)

Acknowledgments

(back to top)

Libraries

animated_streaming_markdown
Animated streaming Markdown public API.