SwiftStreamingMarkdown

repository·main·Indexed 43 days ago

https://github.com/microsoft/swiftstreamingmarkdown

A high-performance iOS and macOS Markdown renderer designed for smooth, animated streaming of LLM-generated content. Features include MarkdownView for static strings, StreamedMarkdownView for growing content via AsyncStream, and support for CommonMark and GitHub-flavored Markdown, including LaTeX math and tables.

Tokens
1.3K
Snippets
5
Records
6
Agent score
7%

What's inside SwiftStreamingMarkdown

  1. How to use StreamedMarkdownView for streaming content

    main

    For chat-style UIs where the Markdown source grows over time, use StreamedMarkdownView. It requires a StreamedMarkdownSource object. The text property of the source must yield progressively larger snapshots of the full Markdown source (not deltas) via an AsyncStream<String>.

    import SwiftUI
    import SwiftStreamingMarkdown
    
    class ChatResponseSource: ObservableObject, StreamedMarkdownSource {
      var text: AsyncStream<String> { /* yields full source snapshots */ }
    }
    
    struct ChatBubble: View {
      @EnvironmentObject var source: ChatResponseSource
    
      var body: some View {
        StreamedMarkdownView(source: source)
      }
    }
  2. Install SwiftStreamingMarkdown via Swift Package Manager

    main

    SwiftStreamingMarkdown is distributed exclusively as a Swift Package. You can add it to your project using Xcode or by modifying your Package.swift file.

    // In Package.swift
    .package(url: "https://github.com/microsoft/SwiftStreamingMarkdown", from: "0.1.0"),
    
    .target(
      name: "MyApp",
      dependencies: [
        .product(name: "SwiftStreamingMarkdown", package: "SwiftStreamingMarkdown")
      ]
    )
  3. Quick start with MarkdownView

    main

    The simplest way to render Markdown is using MarkdownView. It parses and renders a static string of Markdown using the default theme.

    import SwiftUI
    import SwiftStreamingMarkdown
    
    struct ContentView: View {
      var body: some View {
        ScrollView {
          MarkdownView(text: """
          # Hello, **world!**
    
          SwiftStreamingMarkdown supports tables, lists, code blocks, and
          inline `code`.
    
          ```swift
          print("Hello, world!")
          ```
          ")
          .padding()
        }
      }
    }
  4. Listen for rendering and interaction events with MarkdownListener

    main

    Conform to the MarkdownListener protocol to receive notifications for rendering lifecycle events and user interactions (like table copies or context menu usage). The listener is propagated through the SwiftUI environment.

    final class AnalyticsListener: MarkdownListener {
      func onRender(markdown: RenderableDocument) async { /* ... */ }
      func onTableCopyTap(content: String) async { /* ... */ }
      func onTableDownloadTap(content: String) async { /* ... */ }
      func onContextMenuAppear(id: String, selectedContent: String) async { /* ... */ }
      func onContextMenuTap(id: String, selectedContent: String) async { /* ... */ }
    }
    
    // Usage
    MarkdownView(text: source, listener: AnalyticsListener())
  5. Customize the Markdown theme with MarkdownRenderConfig

    main

    Styling is controlled by MarkdownRenderConfig. You can create a custom configuration by composing withXxx helper methods on the .default instance.

    let config = MarkdownRenderConfig.default
      .withShouldAnimateText(value: true)
      .withHeadingStyle(value: MarkdownRenderConfig.defaultHeadingStyle)
      .withParagraphStyle(value: MarkdownRenderConfig.defaultParagraphStyle)
  6. Supported Markdown syntax

    main

    The renderer supports a subset of CommonMark and GitHub-flavored Markdown optimized for LLM responses:

    • Headings (# to ######)
    • Paragraphs (soft and hard line breaks)
    • Images (![alt](url)) — block-level (requires opt-in via ImageConfig)
    • Text styling: Bold, italic, bold-italic, strikethrough
    • Inline code and Inline links
    • Fenced code blocks with language tags
    • Block quotes (supports nested inlines, lists, and citations)
    • Ordered and Unordered lists (with nesting)
    • Task lists (- [ ] / - [x]) — display-only
    • Thematic breaks (---)
    • Tables with alignment (:---, :---:, ---:)
    • LaTeX math: Inline \( … \) and Display $$ … $$
    • Inline citation pills