markstream-vue

repository·main·Indexed 25 days ago

https://github.com/simon-he95/markstream-vue

A Vue/Nuxt streaming Markdown renderer designed for AI chat and LLM token streams. It supports incomplete Markdown, SSE/WebSocket output, and progressive rendering of Mermaid diagrams, KaTeX math, Shiki highlighting, and Monaco editor blocks to ensure a flicker-free user experience during real-time text generation.

Tokens
166.2K
Snippets
411
Records
877
Agent score
80%

What's inside markstream-vue

  1. Overview of Markstream features

    main

    Markstream provides several specialized features for AI chat streaming interfaces:

    • Progressive Rendering: Mermaid and D2 diagrams render incrementally as they are parsed.
    • Streaming-first Rendering: Designed to handle tokenized and partial markdown chunks.
    • Code Block Optimization:
      • Monaco streaming integration: Efficient updates for large code blocks.
      • Streaming diff code blocks: Displays diffs as they are being generated.
      • Flexible rendering: Choose between Monaco or Shiki.
    • Extensibility: Pluggable parse hooks for pre- and post-transforming tokens.
    • Markdown Support: Full support for tables, math (via KaTeX), task checkboxes, and optional Emoji.
    • Lubu features: Includes math rendering via KaTeX and i18n support.
  2. Handle mid-stream Markdown states with Markstream

    main

    Markstream is designed to manage common failure modes encountered during LLM token streaming:

    • Unclosed code fences: Keeps the content readable instead of treating the entire remaining message as a single code block.
    • Partial tables: Maintains stable syntax until enough rows exist to render a table, preventing paragraph-to-table flickering.
    • Partial math: Defers KaTeX rendering until math expressions are complete enough to parse, showing source text instead of transient errors.
    • Incomplete HTML: Provides security policies to handle untrusted model output.
  3. Implement AI chat and LLM streaming with Markstream

    main

    Markstream is optimized for scenarios where Markdown arrives incrementally via LLM token streams. Key capabilities include:

    • LLM Token Streams: Batch and render chunks from SSE, WebSocket, fetch streams, or custom transports.
    • Incomplete Markdown Stability: Keeps unclosed fences, partial tables, math, and HTML stable while a response is still streaming.
    • Streaming Code Blocks: Supports choosing between Monaco, Shiki, or plain <pre> rendering for code fences that arrive token by token.
    • Progressive Heavy Blocks: Incremental rendering of Mermaid diagrams and KaTeX math during the stream.
  4. Understand the differences between Markstream and traditional Markdown renderers

    main

    Unlike traditional Markdown renderers that convert a complete string into a static HTML tree, Markstream is designed for streaming and interactive AI chat workflows. Key capabilities include:

    • Streaming-first rendering: Renders partial or incrementally-updated content without re-parsing the entire document, ideal for live AI token previews.
    • Streaming-aware code blocks: Supports "code-jump" UX where large code blocks update incrementally while maintaining cursor/selection context.
    • Built-in diff/code-stream components: Displays diffs (line-by-line or token-by-token) with minimal layout reflow.
    • Progressive diagrams and editors: Supports progressive updates for Mermaid diagrams and Monaco-based editors.
    • Flexible code block rendering: Allows choosing between Monaco for interactive editing or Shiki for display-only highlighting.
  5. Understand Markstream's Layered Styling Architecture

    main

    Markstream uses a four-layer CSS architecture to manage styles without hardcoding values:

    1. Layer 1: Base Tokens: Contains Bridge Tokens (--ms-* for host inheritance) and Extension Tokens (project-specific semantic colors).
    2. Layer 2: Semantic Tokens: Component-level variables that reference Layer 1 (e.g., --code-bg: hsl(var(--ms-background));).
    3. Layer 3: Component Styles: Actual component CSS that references Layer 2 variables. Hardcoding is strictly forbidden here.
    4. Layer 4: Dark Theme: Overrides Layer 1 bridge and extension fallback values for dark mode support.
  6. Visual Design Review for Markstream Components

    main
    This document outlines the visual design audit for the Markstream streaming Markdown renderer, based on light and dark mode screenshots from the /example page. It identifies elements requiring redesign (Issue #343) and elements performing well. This serves as a guide for improving the visual hierarchy, contrast, and structural clarity of rendered Markdown elements.
  7. Understand the markstream-vue Theming Architecture

    main

    markstream-vue uses a hybrid theming approach to handle Light and Dark modes. The priority of theme application is as follows:

    1. Props (isDark): The highest priority. Controlled by the host application.
    2. CSS Class: Applying .dark or .is-dark to the root container or component.
    3. Media Query: Fallback to the system preference via prefers-color-scheme: dark.

    This ensures that the renderer can be controlled programmatically by your application while still respecting system settings if no explicit mode is provided.

  8. Key features of Markstream

    main

    Markstream provides streaming-first Markdown rendering optimized for AI chat interfaces. Key capabilities include:

    • Streaming Performance: Minimal re-rendering and efficient DOM updates for frequently updated tokenized Markdown.
    • Enhanced Code Blocks: Support for stream-diffs File/Diff surfaces with syntax highlighting and diff interactions. You can choose between the Monaco editor (CodeBlockNode) or lightweight Shiki highlighting (MarkdownCodeBlockNode).
    • Progressive Mermaid: Charts render instantly as syntax becomes available and improve with subsequent updates.
    • Markdown Support: Full support for tables, formulas (via KaTeX), emoji, checkboxes, and more.
    • Extensibility: Ability to embed custom framework components within Markdown content and use the stream-markdown-parser toolkit for custom math helpers or global plugins.
  9. Understand the Markstream Token System Architecture

    main

    The Markstream design system uses a three-layer token architecture to ensure visual fidelity and themeability:

    1. Base Scale (Scale): Primitive values (spacing, etc.) that represent frequently used increments.
    2. Semantic Tokens: Meaningful abstractions (e.g., --ms-flow-paragraph-y) that map to specific UI roles.
    3. Component Private Constants: Values specific to individual components.

    Critical Implementation Note: To support density themes (like 'Compact Mode'), developers must ensure that values used in JavaScript (e.g., style.transition or height calculations) read from CSS variables instead of being hardcoded. If JS values are hardcoded, theme changes will only affect the CSS layer and not the functional behavior.

  10. Quickstart: Render streamed Markdown in Vue

    main

    To render Markdown arriving via SSE or WebSockets with smooth pacing, use the MarkdownRender component. You can toggle between a virtualized window (for long documents) and an incremental batching mode (for an AI-like 'typing' effect) by adjusting the max-live-nodes prop.

    import MarkdownRender from 'markstream-vue'
    import { ref } from 'vue'
    
    const content = ref('')
    const final = ref(false)
    
    // Example event handling
    eventSource.onmessage = (event) => {
      content.value += event.data
    }
    eventSource.addEventListener('done', () => {
      final.value = true
    })
    
    // Template usage:
    // <MarkdownRender
    //   :content="content"
    //   :final="final"
    //   :max-live-nodes="0"
    //   :batch-rendering="true"
    //   :render-batch-size="16"
    //   :render-batch-delay="8"
    //   :render-batch-budget-ms="4"
    //   :fade="false"
    //   :typewriter="true"
    // />
  11. Implement an incomplete Markdown renderer in Vue

    main

    When building AI chat interfaces, LLM responses are often incomplete (e.g., unclosed code fences, partial tables, or half-written math). Use the MarkdownRender component from markstream-vue to handle these mid-stream states without flickering or rendering errors.

    Key props for streaming:

    • :content: The current accumulated string of Markdown tokens.
    • :final: Set this to true only after the stream has fully completed. This allows the parser to settle incomplete syntax into its final rendered state.
    • mode="chat": Optimized for chat interfaces.
    • :fade="false": Recommended for chat surfaces to prevent opacity animations from restarting on every token update.
    <script setup lang="ts">
    import MarkdownRender from 'markstream-vue'
    import { ref } from 'vue'
    import 'markstream-vue/index.css'
    
    const content = ref('')
    const isDone = ref(false)
    
    async function appendChunk(chunk: string) {
      content.value += chunk
    }
    </script>
    
    <template>
      <MarkdownRender
        mode="chat"
        :content="content"
        :final="isDone"
        :fade="false"
      />
    </template>