[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-85112":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":15,"stars30d":15,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":16,"rankGlobal":10,"rankLanguage":10,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":18,"hasPages":18,"topics":20,"createdAt":10,"pushedAt":10,"updatedAt":30,"readmeContent":31,"aiSummary":10,"trendingCount":15,"starSnapshotCount":15,"syncStatus":32,"lastSyncTime":33,"discoverSource":34},85112,"SwiftStreamingMarkdown","microsoft\u002FSwiftStreamingMarkdown","microsoft","A performant markdown library for iOS that supports streaming","",null,"Swift",134,6,1,0,38.33,"MIT License",false,"main",[21,22,23,24,25,26,27,28,29],"ai","ai-agent","ios","llm","markdown","streaming","swift","swift-package-manager","swiftui","2026-06-15 10:04:25","# SwiftStreamingMarkdown\n\n[![CI](https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FSwiftStreamingMarkdown\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg?branch=main)](https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FSwiftStreamingMarkdown\u002Factions\u002Fworkflows\u002Fci.yml)\n[![Swift 5.9](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FSwift-5.9-orange.svg)](https:\u002F\u002Fswift.org)\n[![iOS 16+](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FiOS-16%2B-blue.svg)](https:\u002F\u002Fdeveloper.apple.com\u002Fios\u002F)\n[![SwiftPM](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FSwiftPM-compatible-brightgreen.svg)](https:\u002F\u002Fswift.org\u002Fpackage-manager\u002F)\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-yellow.svg)](LICENSE)\n\nAn iOS Markdown renderer that offers smooth streaming experiences.\n\n- ⚡ Smooth, high-performance streaming transitions for newly received text\n- 🧮 Native inline and block LaTeX math rendering\n- 🔗 Inline citation UI for source-grounded LLM responses\n- 🎨 Highly configurable typography, theming, and iOS context menus\n- 📊 Built-in hooks for analytics and interaction tracking\n\n## Catalog\n\n- [Demos](#demos)\n- [Markdown support](#markdown-support)\n  - [Supported](#supported)\n  - [Not yet supported](#not-yet-supported)\n  - [Streaming Performance](#streaming-performance)\n- [Installation](#installation)\n  - [Xcode](#xcode)\n  - [`Package.swift`](#packageswift)\n  - [Binary Size](#binary-size)\n- [Quick start](#quick-start)\n- [Streaming usage](#streaming-usage)\n- [Customizing the theme](#customizing-the-theme)\n- [Listening for events](#listening-for-events)\n- [Sample app](#sample-app)\n- [Development](#development)\n- [Contributing](#contributing)\n- [Security](#security)\n- [License](#license)\n\n## Demos\n\nHere are a few demos to help you quickly understand this library's capabilities. More can be found in the sample app.\n\n\u003Ctable>\n  \u003Ctr>\n    \u003Ctd>\n      \u003Ch3>Table\u003C\u002Fh3>\n    \u003C\u002Ftd>\n    \u003Ctd>\n      \u003Cvideo src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fbdfc448f-069a-413f-a9d8-221fe1a1e303\" width=\"400\" controls>\u003C\u002Fvideo>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Ctd>\n      \u003Ch3>LaTeX\u003C\u002Fh3>\n    \u003C\u002Ftd>\n    \u003Ctd>\n      \u003Cvideo src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F590d7757-4ad6-46e1-9e59-9b2a13355087\" width=\"400\" controls>\u003C\u002Fvideo>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Ctd>\n      \u003Ch3>Customization\u003C\u002Fh3>\n    \u003C\u002Ftd>\n    \u003Ctd>\n      \u003Cvideo src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fbec02fc2-8b8d-4bc3-9145-0a6f2012ffc6\" width=\"400\" controls>\u003C\u002Fvideo>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Ctd>\n      \u003Ch3>Inline citation\u003C\u002Fh3>\n    \u003C\u002Ftd>\n    \u003Ctd>\n      \u003Cimg width=\"361\" height=\"156\" alt=\"Inline Citation\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Ff35fa1af-0d9a-48b2-81f2-b3228d1b7322\" \u002F>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Ctd>\n      \u003Ch3>Code block\u003C\u002Fh3>\n    \u003C\u002Ftd>\n    \u003Ctd>\n      \u003Cimg width=\"375\" height=\"453\" alt=\"code-block\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fd6e3a266-e00b-442b-82f4-f9f395629547\" \u002F>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n\u003C\u002Ftable>\n\n## Markdown support\n\nThe renderer targets the subset of CommonMark + GitHub-flavored Markdown that LLM responses actually emit. Unsupported syntax degrades to readable text so streamed responses never break.\n\n### Supported\n\n- [x] Headings (`#` … `######`)\n- [x] Paragraphs with soft and hard line breaks\n- [x] **Bold**, *italic*, ***bold-italic***, ~~strikethrough~~\n- [x] `Inline code`\n- [x] Inline links\n- [x] Fenced code blocks with language tag\n- [x] Block quotes (with nested inlines, lists, and citations)\n- [x] Ordered lists\n- [x] Unordered lists (with nesting)\n- [x] Thematic breaks (`---`)\n- [x] Tables with `:---`, `:---:`, `---:` column alignment\n- [x] Inline LaTeX math via `\\( … \\)`\n- [x] Display LaTeX math via `$$ … $$`\n- [x] Inline citation pills\n\n### Not yet supported\n\n- [ ] Images (`![alt](url)`) — alt text only\n- [ ] Task lists (`- [ ]` \u002F `- [x]`)\n- [ ] Footnotes (`[^1]`)\n- [ ] Highlight (`==text==`), superscript (`^x^`), subscript (`~x~`)\n- [ ] Raw HTML (`\u003Cdetails>`, `\u003Ckbd>`, `\u003Caside>`, …) — kept inline as text\n- [ ] GitHub alerts (`> [!NOTE]`) — rendered as plain block quotes\n- [ ] Container directives (`::: warning … :::`) and admonitions (`!!! note`)\n- [ ] Mermaid \u002F PlantUML diagrams — rendered as fenced code\n\nThe bundled `Kitchen Sink` demonstration in the sample app exercises every item above so you can verify the fallback behavior on-device.\n\n### Streaming Performance\n\n`SwiftStreamingMarkdown` includes built-in animations for streaming content as new text arrives. It is designed to keep rendering smooth while minimizing main-thread work. The chart below compares its performance against popular Markdown libraries that do not provide built-in streaming support.\n\nProfiling was performed on an iPhone XS using the sample app while continuously streaming content and scrolling. Even under this demanding workload on older hardware, `SwiftStreamingMarkdown` maintains smooth rendering without noticeable UI stalls.\n\n\u003Ctable>\n  \u003Ctr>\n    \u003Ctd>\n      \u003Ch3>SwiftStreamingMarkdown\u003C\u002Fh3>\n    \u003C\u002Ftd>\n    \u003Ctd>\n      \u003Cimg width=\"891\" height=\"110\" alt=\"profiling-streaming\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fd8eb9ee6-7b61-4bbb-b70d-e1862a6b1176\" \u002F>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n    \u003Ctd>\n      \u003Ch3>Markdown library without streaming support\u003C\u002Fh3>\n    \u003C\u002Ftd>\n    \u003Ctd>\n      \u003Cimg width=\"940\" height=\"156\" alt=\"profiling-streaming-comparison\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F739d00d3-5067-409a-96d4-9c3c8b6c0675\" \u002F>\n    \u003C\u002Ftd>\n  \u003C\u002Ftr>\n\u003C\u002Ftable>\n\n\n\n\n## Installation\n\nSwiftStreamingMarkdown is distributed exclusively as a Swift Package.\n\n### Xcode\n\n1. Choose **File ▸ Add Package Dependencies…**\n2. Enter `https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FSwiftStreamingMarkdown`\n3. Select the version rule you want (e.g. *Up to next minor*) and add the\n   `SwiftStreamingMarkdown` product to your app target.\n\n### `Package.swift`\n\n```swift\n.package(url: \"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FSwiftStreamingMarkdown\", from: \"0.1.0\"),\n```\n\n```swift\n.target(\n  name: \"MyApp\",\n  dependencies: [\n    .product(name: \"SwiftStreamingMarkdown\", package: \"SwiftStreamingMarkdown\")\n  ]\n)\n```\n\n### Binary Size\n\nIntegrating `SwiftStreamingMarkdown` adds roughly **3 MB** to your app's App Store download size. The increase comes from the rendering engine and its dependencies (e.g. `swift-markdown`, `cmark-gfm`, `iosMath` for LaTeX, `HighlightSwift` for code syntax highlighting) and bundled resources such as math fonts and the syntax-highlighting runtime. Actual size depends on your app's architecture slices and App Store compression.\n\n## Quick start\n\nThe simplest entry point is `MarkdownView`, which parses and renders a static\nstring of Markdown using the default theme:\n\n```swift\nimport SwiftUI\nimport SwiftStreamingMarkdown\n\nstruct ContentView: View {\n  var body: some View {\n    ScrollView {\n      MarkdownView(text: \"\"\"\n      # Hello, **world!**\n\n      SwiftStreamingMarkdown supports tables, lists, code blocks, and\n      inline `code`.\n\n      ```swift\n      print(\"Hello, world!\")\n      ```\n      \"\"\")\n      .padding()\n    }\n  }\n}\n```\n\n## Streaming usage\n\nFor chat-style UIs that grow the Markdown source over time, use\n`StreamedMarkdownView`. It takes a `StreamedMarkdownSource` whose `text`\nproperty yields progressively larger snapshots of the Markdown source (each\nemission is the full source so far, not a delta) and incrementally parses\nand renders them as they arrive.\n\n```swift\nimport SwiftUI\nimport SwiftStreamingMarkdown\n\nclass ChatResponseSource: ObservableObject, StreamedMarkdownSource {\n  var text: AsyncStream\u003CString> { ... }\n}\n\nstruct ChatBubble: View {\n  @EnvironmentObject var source: ChatResponseSource\n\n  var body: some View {\n    StreamedMarkdownView(source: source)\n  }\n}\n```\n\nIf you'd rather drive `DocumentView` directly, parse each snapshot with\n`MarkdownParser.parse(text:config:)` and feed the resulting\n`RenderableDocument` into your view yourself.\n\nThe bundled [sample app](Examples\u002FSwiftStreamingMarkdownSample) demonstrates\nchunked streaming end-to-end with adjustable chunk size and interval, plus\nauto-scroll wired through a `MarkdownListener`.\n\n## Customizing the theme\n\n`MarkdownRenderConfig` is the single source of truth for styling. Build one\nby composing the `withXxx` helpers on `.default`:\n\n```swift\nlet config = MarkdownRenderConfig.default\n  .withShouldAnimateText(value: true)\n  .withHeadingStyle(value: MarkdownRenderConfig.defaultHeadingStyle)\n  .withParagraphStyle(value: MarkdownRenderConfig.defaultParagraphStyle)\n```\n\nFor finer control, construct `MarkdownRenderConfig` directly to override the\ninline, paragraph, heading, list, table, and citation styles in one place.\n\n## Listening for events\n\nConform to `MarkdownListener` to receive notifications whenever the renderer\ndraws or the user interacts with rendered content (table copy\u002Fdownload taps,\ncontext-menu lifecycle, etc.):\n\n```swift\nfinal class AnalyticsListener: MarkdownListener {\n  func onRender(markdown: RenderableDocument) async { \u002F* ... *\u002F }\n  func onTableCopyTap(content: String) async { \u002F* ... *\u002F }\n  func onTableDownloadTap(content: String) async { \u002F* ... *\u002F }\n  func onContextMenuAppear(id: String, selectedContent: String) async { \u002F* ... *\u002F }\n  func onContextMenuTap(id: String, selectedContent: String) async { \u002F* ... *\u002F }\n}\n\nMarkdownView(text: source, listener: AnalyticsListener())\n```\n\nThe listener is propagated through the SwiftUI environment, so deeply nested\nrendered subviews observe the same hooks.\n\n## Sample app\n\nA SwiftUI sample app lives in\n[`Examples\u002FSwiftStreamingMarkdownSample`](Examples\u002FSwiftStreamingMarkdownSample).\nIt includes a streaming demonstration with adjustable chunk size and interval,\na settings screen, and a logging `MarkdownListener` implementation. The sample\nXcode project is generated from `Examples\u002FSwiftStreamingMarkdownSample\u002Fproject.yml`;\nrun `make sample-project` to generate and open it in Xcode.\n\n## Development\n\nRun `make help` to see the repo's common development commands. The most useful\ntargets are:\n\n| Command | Purpose |\n| --- | --- |\n| `make dev-setup` | Verify local tools such as Xcode, SwiftLint, XcodeGen, `cloc`, ImageMagick, and `diff-image`. |\n| `make project` | Resolve Swift package dependencies and open the package in Xcode. |\n| `make generate-sample-project` | Generate the sample app project with XcodeGen. |\n| `make sample-project` | Generate and open the sample app project in Xcode. |\n| `make lint` | Run `swiftlint --strict`. |\n| `make test` | Run the package unit tests with `xcodebuild`. |\n| `make build-sample` | Generate and build the sample app. |\n| `make ci` | Run lint, tests, and the sample-app build. |\n| `make cloc` | Count code with `cloc --vcs=git`. |\n\n## Contributing\n\nContributions are welcome! Bug reports and feature requests go through the\n[issue templates](.github\u002FISSUE_TEMPLATE). See [CONTRIBUTING.md](CONTRIBUTING.md)\nfor local setup, code style, and the pull-request process.\n\nThis project follows the\n[Microsoft Open Source Code of Conduct](https:\u002F\u002Fopensource.microsoft.com\u002Fcodeofconduct\u002F).\n\n## Security\n\nPlease follow the responsible-disclosure process described in\n[SECURITY.md](SECURITY.md). Do not file security issues publicly.\n\n## License\n\nSwiftStreamingMarkdown is released under the [MIT License](LICENSE). Dependencies\nare declared in [`Package.swift`](Package.swift); each upstream ships its own\nlicense terms via Swift Package Manager.\n",2,"2026-06-15 02:30:02","CREATED_QUERY"]