[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-8788":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":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":25,"hasPages":25,"topics":26,"createdAt":10,"pushedAt":10,"updatedAt":36,"readmeContent":37,"aiSummary":38,"trendingCount":16,"starSnapshotCount":16,"syncStatus":39,"lastSyncTime":40,"discoverSource":41},8788,"markstream-vue","Simon-He95\u002Fmarkstream-vue","Simon-He95","A Vue 3 renderer specifically built for AI-powered streaming Markdown: Monaco incremental, Mermaid progressive, and KaTeX formula speed, with real-time updates and no jitter, ready to use out of the box.","https:\u002F\u002Fmarkstream-vue.simonhe.me\u002F",null,"Vue",2562,162,7,3,0,11,39,261,45,108.14,"MIT License",false,"main",true,[27,28,29,30,5,31,32,33,34,35],"ai","infographic","katex","markdown","mermaid","monaco-editor","shiki","stream-render","vue3","2026-06-12 04:00:41","# markstream-vue\n\n> Fast, streaming-friendly Markdown rendering for Vue 3 — progressive Mermaid, streaming diff code blocks, and real-time previews optimized for large documents.\n\n[![NPM version](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Fmarkstream-vue?color=a1b858&label=)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fmarkstream-vue)\n[![中文版](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fdocs-中文文档-blue)](README.zh-CN.md)\n[![Docs](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fdocs-vitepress-blue)](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002F)\n[![Playground](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplayground-live-34c759)](https:\u002F\u002Fmarkstream-vue.simonhe.me\u002F)\n[![Test page](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Ftest-shareable%20repro-0A84FF)](https:\u002F\u002Fmarkstream-vue.simonhe.me\u002Ftest)\n[![NPM downloads](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdm\u002Fmarkstream-vue)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fmarkstream-vue)\n[![Bundle size](https:\u002F\u002Fimg.shields.io\u002Fbundlephobia\u002Fminzip\u002Fmarkstream-vue)](https:\u002F\u002Fbundlephobia.com\u002Fpackage\u002Fmarkstream-vue)\n[![Release](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002FSimon-He95\u002Fmarkstream-vue?display_name=release&logo=github)](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Freleases)\n[![Discussions](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fdiscussions\u002FSimon-He95\u002Fmarkstream-vue?logo=github)](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Fdiscussions)\n[![Discord](https:\u002F\u002Fimg.shields.io\u002Fdiscord\u002F986352439269560380?label=discord&logo=discord&logoColor=fff&color=5865F2)](https:\u002F\u002Fdiscord.gg\u002FvkzdkjeRCW)\n[![Support](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fsupport-guide-ff6f61)](.\u002FSUPPORT.md)\n[![Security](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fsecurity-policy-8A2BE2)](.\u002FSECURITY.md)\n[![CI](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Factions\u002Fworkflows\u002Fci.yml)\n[![License](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fl\u002Fmarkstream-vue)](.\u002Flicense)\n\nLooking for other frameworks?\n\n- Vue 2.6: use [`markstream-vue2`](.\u002Fpackages\u002Fmarkstream-vue2\u002FREADME.md) (a baseline port with fewer advanced features)\n- React: see `packages\u002Fmarkstream-react` at [`packages\u002Fmarkstream-react\u002FREADME.md`](.\u002Fpackages\u002Fmarkstream-react\u002FREADME.md) (first-pass port)\n\n## Contents\n\n- [TL;DR Highlights](#tldr-highlights)\n- [Choose Your Path](#choose-your-path)\n- [Try It Now](#-try-it-now)\n- [Community & support](#-community--support)\n- [Quick Start](#-quick-start)\n- [Common commands](#-common-commands)\n- [Streaming in 30 seconds](#-streaming-in-30-seconds)\n- [Performance presets](#-performance-presets)\n- [Key props & options](#-key-props--options-cheatsheet)\n- [Where it shines](#-where-it-shines)\n- [FAQ](#-faq-quick-answers)\n- [Why markstream-vue](#-why-markstream-vue-over-a-typical-markdown-renderer)\n- [Roadmap](#-roadmap-snapshot)\n- [Releases](#-releases)\n- [Showcase](#-showcase--examples)\n- [Introduction Video](#-introduction-video)\n- [Features](#features)\n- [Contributing & community](#-contributing--community)\n- [Troubleshooting](#troubleshooting--common-issues)\n- [Thanks](#thanks)\n- [Star History](#star-history)\n- [License](#license)\n\n> 📖 Detailed docs, API, and advanced usage: https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002F\n\n## TL;DR Highlights\n\n- Purpose-built for **streaming Markdown** (AI\u002Fchat\u002FSSE) with zero flicker and predictable memory.\n- **Two render modes**: virtual window for long docs, incremental batching for “typing” effects.\n- **Progressive diagrams** (Mermaid) and **streaming code blocks** (Monaco\u002FShiki) that keep up with diffs.\n- Works with **raw Markdown strings or pre-parsed nodes**, supports **custom Vue components** inline.\n- TypeScript-first, ship-ready defaults — import CSS and render.\n\n## Choose Your Path\n\n| If you want to... | Start here | Then go to |\n| --- | --- | --- |\n| get the first render on screen | [Quick Start](#-quick-start) | [Installation guide](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Finstallation) |\n| integrate it into a docs site or VitePress theme | [Docs Site & VitePress](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Fvitepress-docs-integration) | [Custom Tags & Advanced Components](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Fcustom-components) |\n| build an AI chat UI or SSE stream | [AI Chat & Streaming](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Fai-chat-streaming) | [Performance](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Fperformance) |\n| replace one built-in renderer | [Override Built-in Components](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Fcomponent-overrides) | [Renderer & Node Components](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Fcomponents) |\n| add trusted tags such as `thinking` | [Custom Tags & Advanced Components](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Fcustom-components) | [API Reference](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Fapi) |\n| debug a broken integration but do not know why yet | [Troubleshooting by Symptom](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Ftroubleshooting-path) | [Troubleshooting](https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Ftroubleshooting) |\n\n## 🚀 Try It Now\n\n- Playground (interactive demo): https:\u002F\u002Fmarkstream-vue.simonhe.me\u002F\n- Interactive test page (shareable links, easy reproduction): https:\u002F\u002Fmarkstream-vue.simonhe.me\u002Ftest\n- Docs: https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002F\n- AI\u002FLLM context (project map): https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fllms\n- AI\u002FLLM context (中文): https:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fllms.zh-CN\n- One-click StackBlitz demo: https:\u002F\u002Fstackblitz.com\u002Fgithub\u002FSimon-He95\u002Fmarkstream-vue?file=playground\u002Fsrc\u002FApp.vue\n- Changelog: [CHANGELOG.md](.\u002FCHANGELOG.md)\n- Nuxt playground: `pnpm play:nuxt`\n- Discord: https:\u002F\u002Fdiscord.gg\u002FvkzdkjeRCW\n\n## CLI helpers for skills and prompts\n\nIf you want the packaged AI assets without cloning the repo:\n\n```bash\nnpx skills add Simon-He95\u002Fmarkstream-vue\nnpx markstream-vue skills list\nnpx markstream-vue skills install\nnpx markstream-vue prompts list\nnpx markstream-vue prompts show install-markstream\n```\n\nRecommended usage:\n\n- `npx skills add Simon-He95\u002Fmarkstream-vue` is the primary path for Codex-compatible skill discovery because it reads `.agents\u002Fskills` directly from the GitHub repository\n- `skills install` installs the bundled skills into your agent skill directory (default: `~\u002F.agents\u002Fskills`)\n- `prompts list` and `prompts show` to discover and copy maintained prompt templates\n\nOther `npx skills add` forms also work:\n\n```bash\n# Full GitHub URL\nnpx skills add https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\n\n# Direct path to one skill in this repo\nnpx skills add https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Ftree\u002Fmain\u002F.agents\u002Fskills\u002Fmarkstream-install\n\n# Any git URL\nnpx skills add git@github.com:Simon-He95\u002Fmarkstream-vue.git\n```\n\n## 💬 Community & support\n\n- Discussions: https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Fdiscussions\n- Discord: https:\u002F\u002Fdiscord.gg\u002FvkzdkjeRCW\n- Issues: please use templates and attach a repro link (https:\u002F\u002Fmarkstream-vue.simonhe.me\u002Ftest)\n\nThe test page gives you an editor + live preview plus “generate share link” that encodes the input in the URL (with a fallback to open directly or pre-fill a GitHub Issue for long payloads).\n\n## Support the project\n\nIf markstream-vue helps your work, you can support ongoing maintenance with one of these QR codes.\n\n| Alipay | WeChat Pay |\n| --- | --- |\n| \u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002FSimon-He95\u002Fmarkstream-vue\u002Fmain\u002Fdocs\u002Fpublic\u002Fsponsor\u002Fzhifubao.jpg\" alt=\"Alipay QR code\" width=\"240\" \u002F> | \u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002FSimon-He95\u002Fmarkstream-vue\u002Fmain\u002Fdocs\u002Fpublic\u002Fsponsor\u002Fweixin.jpg\" alt=\"WeChat Pay QR code\" width=\"240\" \u002F> |\n\n## ⚡ Quick Start\n\n```bash\npnpm add markstream-vue\n# npm install markstream-vue\n# yarn add markstream-vue\n```\n\n```ts\nimport MarkdownRender from 'markstream-vue'\n\u002F\u002F main.ts\nimport { createApp } from 'vue'\nimport 'markstream-vue\u002Findex.css'\n\ncreateApp({\n  components: { MarkdownRender },\n  template: '\u003CMarkdownRender custom-id=\"docs\" :content=\"doc\" \u002F>',\n  setup() {\n    const doc = '# Hello from markstream-vue\\\\n\\\\nSupports **streaming** nodes.'\n    return { doc }\n  },\n}).mount('#app')\n```\n\nImport `markstream-vue\u002Findex.css` after your reset (e.g., Tailwind `@layer components`) so renderer styles win over utility classes. Install optional peers such as `stream-monaco`, `shiki`, `stream-markdown`, `mermaid`, and `katex` only when you need Monaco code blocks, Shiki highlighting, diagrams, or math.\nIf your app intentionally scales root font size on mobile, use `markstream-vue\u002Findex.px.css` to avoid `rem`-based global scaling side effects.\n\nRenderer CSS is scoped under an internal `.markstream-vue` container to minimize global style conflicts. If you render exported node components outside of `MarkdownRender`, wrap them in an element with class `markstream-vue`.\n\nFor dark theme variables, either add a `.dark` class on an ancestor, or pass `:is-dark=\"true\"` to `MarkdownRender` to scope dark mode to the renderer.\n\nPrefer the unified code-block `theme` prop for new integrations. When you render through `MarkdownRender`, pass it via `code-block-props`:\n\n```vue\n\u003CMarkdownRender\n  :is-dark=\"isDark\"\n  :code-block-props=\"{ theme: { light: 'vitesse-light', dark: 'vitesse-dark' } }\"\n  :content=\"doc\"\n\u002F>\n```\n\nLanguage icons use the built-in `material` theme by default. Advanced integrations can inspect or switch icon themes with the exported helpers, or set an initial theme with `app.use(VueRendererMarkdown, { iconTheme })`:\n\n```ts\nimport { getRegisteredThemes, setIconTheme } from 'markstream-vue'\n\nconsole.log(getRegisteredThemes()) \u002F\u002F ['material']\nsetIconTheme('material')\n```\n\nUse `registerIconTheme()` if you want to add your own icon pack.\n\nEnable heavy peers only when needed:\n\n```ts\nimport { enableKatex, enableMermaid } from 'markstream-vue'\nimport 'markstream-vue\u002Findex.css'\nimport 'katex\u002Fdist\u002Fkatex.min.css'\n\n\u002F\u002F after you install `mermaid` \u002F `katex` peers\nenableMermaid()\nenableKatex()\n```\n\n\u003Cdetails>\n\u003Csummary>Optional: CDN-backed workers (KaTeX \u002F Mermaid)\u003C\u002Fsummary>\n\nIf you load KaTeX via CDN and want KaTeX rendering in a Web Worker (no bundler \u002F optional peer not installed), inject a CDN-backed worker:\n\n```ts\nimport { createKaTeXWorkerFromCDN, setKaTeXWorker } from 'markstream-vue'\n\nconst { worker } = createKaTeXWorkerFromCDN({\n  mode: 'classic',\n  \u002F\u002F UMD builds used by importScripts() inside the worker\n  katexUrl: 'https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fkatex@0.16.22\u002Fdist\u002Fkatex.min.js',\n  mhchemUrl: 'https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fkatex@0.16.22\u002Fdist\u002Fcontrib\u002Fmhchem.min.js',\n})\n\nif (worker)\n  setKaTeXWorker(worker)\n```\n\nIf you load Mermaid via CDN and want off-main-thread parsing (used by progressive Mermaid rendering), inject a Mermaid parser worker:\n\n```ts\nimport { createMermaidWorkerFromCDN, setMermaidWorker } from 'markstream-vue'\n\nconst { worker } = createMermaidWorkerFromCDN({\n  \u002F\u002F Mermaid CDN builds are commonly ESM; module worker is recommended.\n  mode: 'module',\n  workerOptions: { type: 'module' },\n  mermaidUrl: 'https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fmermaid@11\u002Fdist\u002Fmermaid.esm.min.mjs',\n})\n\nif (worker)\n  setMermaidWorker(worker)\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Nuxt quick drop-in\u003C\u002Fsummary>\n\n```ts\n\u002F\u002F plugins\u002Fmarkstream-vue.client.ts\nimport { defineNuxtPlugin } from '#app'\nimport MarkdownRender from 'markstream-vue'\nimport 'markstream-vue\u002Findex.css'\n\nexport default defineNuxtPlugin((nuxtApp) => {\n  nuxtApp.vueApp.component('MarkdownRender', MarkdownRender)\n})\n```\n\nThen use `\u003CMarkdownRender :content=\"md\" \u002F>` in your pages.\n\n\u003C\u002Fdetails>\n\n## 🛠️ Common commands\n\n- `pnpm dev` — playground dev server\n- `pnpm play:nuxt` — Nuxt playground dev\n- `pnpm build` — library + CSS build\n- `pnpm build:analyze` — build with bundle visualizer reports (`bundle-visualizer.html`, `bundle-visualizer-tailwind.html`)\n- `pnpm size:check` — run dist + npm package size budget checks (same guard used in CI)\n- `pnpm test` — Vitest suite (`pnpm test:update` for snapshots)\n- `pnpm typecheck` \u002F `pnpm lint` — type and lint checks\n\n## ⏱️ Streaming in 30 seconds\n\nRender streamed Markdown (SSE\u002Fwebsocket) with incremental updates:\n\n```ts\nimport type { ParsedNode } from 'markstream-vue'\nimport MarkdownRender, { getMarkdown, parseMarkdownToStructure } from 'markstream-vue'\nimport { ref } from 'vue'\n\nconst nodes = ref\u003CParsedNode[]>([])\nconst buffer = ref('')\nconst md = getMarkdown()\n\nfunction addChunk(chunk: string) {\n  buffer.value += chunk\n  nodes.value = parseMarkdownToStructure(buffer.value, md)\n}\n\n\u002F\u002F e.g., inside your SSE\u002Fonmessage handler\neventSource.onmessage = event => addChunk(event.data)\n\n\u002F\u002F template\n\u002F\u002F \u003CMarkdownRender\n\u002F\u002F   :nodes=\"nodes\"\n\u002F\u002F   :max-live-nodes=\"0\"\n\u002F\u002F   :batch-rendering=\"{\n\u002F\u002F     renderBatchSize: 16,\n\u002F\u002F     renderBatchDelay: 8,\n\u002F\u002F   }\"\n\u002F\u002F \u002F>\n```\n\nSwitch rendering style per surface:\n\n- Virtualized window (default): steady scrolling and memory usage for long docs.\n- Incremental batches: set `:max-live-nodes=\"0\"` for AI-like “typing” with lightweight placeholders.\n\n\u003Cdetails>\n\u003Csummary>Advanced: SSR \u002F worker \u002F streaming handoff\u003C\u002Fsummary>\n\n### SSR \u002F Worker usage (deterministic output)\n\nPre-parse Markdown on the server or in a worker and render typed nodes on the client:\n\n```ts\n\u002F\u002F server or worker\nimport { getMarkdown, parseMarkdownToStructure } from 'markstream-vue'\n\nconst md = getMarkdown()\nconst nodes = parseMarkdownToStructure('# Hello\\n\\nThis is parsed once', md)\n\u002F\u002F send `nodes` JSON to the client\n```\n\n```vue\n\u003C!-- client -->\n\u003CMarkdownRender :nodes=\"nodesFromServer\" \u002F>\n```\n\nThis avoids client-side parsing and keeps SSR\u002Fhydration deterministic.\n\n### Hybrid: SSR + streaming handoff\n\n- Server: parse the first Markdown batch to nodes and serialize `initialNodes` (and the raw `initialMarkdown` if you also stream later chunks).\n- Client: hydrate with the same parser options, then keep streaming:\n\n```ts\nimport type { ParsedNode } from 'markstream-vue'\nimport { getMarkdown, parseMarkdownToStructure } from 'markstream-vue'\nimport { ref } from 'vue'\n\nconst nodes = ref\u003CParsedNode[]>(initialNodes)\nconst buffer = ref(initialMarkdown)\nconst md = getMarkdown() \u002F\u002F match server setup\n\nfunction addChunk(chunk: string) {\n  buffer.value += chunk\n  nodes.value = parseMarkdownToStructure(buffer.value, md)\n}\n```\n\nThis avoids re-parsing SSR content while letting later SSE\u002FWebSocket chunks continue the stream.\n\n> Tip: when you know the stream has ended (the message is complete), use `parseMarkdownToStructure(buffer.value, md, { final: true })` or pass `:final=\"true\"` to the component. This disables mid-state (`loading`) parsing so trailing delimiters (like `$$` or an unclosed code fence) won’t get stuck showing perpetual loading.\n\n\u003C\u002Fdetails>\n\n## ⚙️ Performance presets\n\n- **Virtual window (default)** – keep `max-live-nodes` at its default `320` to enable virtualization. Nodes render immediately and the renderer keeps a sliding window of elements mounted so long docs remain responsive without showing skeleton placeholders.\n- **Incremental stream** – set `:max-live-nodes=\"0\"` when you want a true typewriter effect. This disables virtualization and turns on incremental batching governed by `batchRendering`, `initialRenderBatchSize`, `renderBatchSize`, `renderBatchDelay`, and `renderBatchBudgetMs`, so new content flows in small slices with lightweight placeholders.\n\nPick one mode per surface: virtualization for best scrollback and steady memory usage, or incremental batching for AI-style “typing” previews.\n\n> Tip: In chats, combine `max-live-nodes=\"0\"` with small `renderBatchSize` (e.g., `16`) and a tiny `renderBatchDelay` (e.g., `8ms`) to keep the “typing” feel smooth without jumping large chunks. Tune `renderBatchBudgetMs` down if you need to cap CPU per frame.\n\n## 🧰 Key props & options (cheatsheet)\n\n- `content` vs `nodes`: pass raw Markdown or pre-parsed nodes (from `parseMarkdownToStructure`).\n- `max-live-nodes`: `320` (default virtualization) or `0` (incremental batches).\n- `batchRendering`: fine-tune batches with `initialRenderBatchSize`, `renderBatchSize`, `renderBatchDelay`, `renderBatchBudgetMs`.\n- `enableMermaid` \u002F `enableKatex`: (re)enable heavy peers or custom loaders when needed (pairs with `disableMermaid` \u002F `disableKatex`).\n- `parse-options`: reuse parser hooks (e.g., `preTransformTokens`, `requireClosingStrong`) on the component.\n- `final`: marks end-of-stream; disables mid-state loading parsing and forces unfinished constructs to settle.\n- `custom-html-tags`: extend streaming HTML allowlist for custom tags and emit them as custom nodes for `setCustomComponents` (e.g., `['thinking']`).\n- `setCustomComponents(customId?, mapping)`: register inline Vue components for custom tags\u002Fmarkers (scoped by `custom-id` when provided).\n\nExample: map Markdown placeholders to Vue components (scoped)\n\n```ts\nimport { setCustomComponents } from 'markstream-vue'\n\nsetCustomComponents('docs', {\n  CALLOUT: () => import('.\u002Fcomponents\u002FCallout.vue'),\n})\n\n\u002F\u002F Markdown: [[CALLOUT:warning title=\"Heads up\" body=\"Details here\"]]\n```\n\nUse the same `custom-id` on the renderer:\n\n```vue\n\u003CMarkdownRender\n  :content=\"doc\"\n  custom-id=\"docs\"\n\u002F>\n```\n\nParse hooks example (match server + client):\n\n```vue\n\u003CMarkdownRender\n  :content=\"doc\"\n  :parse-options=\"{\n    requireClosingStrong: true,\n    preTransformTokens: (tokens) => tokens,\n  }\"\n\u002F>\n```\n\n## 🔥 Where it shines\n\n- AI\u002Fchat UIs with long-form answers and Markdown tokens arriving over SSE\u002Fwebsocket.\n- Docs, changelogs, and knowledge bases that need instant load but stay responsive as they grow.\n- Streaming diffs and code review panes that benefit from Monaco live updates.\n- Diagram-heavy content that should render progressively (Mermaid) without blocking.\n- Embedding Vue components in Markdown-driven surfaces (callouts, widgets, CTA buttons).\n\n## ❓ FAQ (quick answers)\n\n- Mermaid\u002FKaTeX not rendering? Install the peer (`mermaid` \u002F `katex`) and pass `:enable-mermaid=\"true\"` \u002F `:enable-katex=\"true\"` or call the loader setters. If you load them via CDN script tags, the library will also pick up `window.mermaid` \u002F `window.katex`.\n- CDN + KaTeX worker: if you don't bundle `katex` but still want off-main-thread rendering, create and inject a worker that loads KaTeX via CDN (UMD) using `createKaTeXWorkerFromCDN()` + `setKaTeXWorker()`.\n- Bundle size: peers are optional and not bundled; import only `markstream-vue\u002Findex.css` once; use Shiki (`MarkdownCodeBlockNode`) when Monaco is too heavy. Infrequent language icons are split into an async chunk and load on demand; call `preloadExtendedLanguageIcons()` during app idle if you want to avoid first-hit icon fallback.\n- Custom UI: register components via `setCustomComponents` (global or scoped), then emit markers\u002Fplaceholders in Markdown and map them to Vue components.\n\n## 🆚 Why markstream-vue over a typical Markdown renderer?\n\n| Needs | Typical Markdown preview | markstream-vue |\n| --- | --- | --- |\n| Streaming input | Re-renders whole tree, flashes | Incremental batches with virtual windowing |\n| Large code blocks | Slow re-highlight | Monaco streaming updates + Shiki option |\n| Diagrams | Blocks while parsing | Progressive Mermaid with graceful fallback |\n| Custom UI | Limited slots | Inline Vue components & typed nodes |\n| Long docs | Memory spikes | Configurable live-node cap for steady usage |\n\n## 🗺️ Roadmap (snapshot)\n\n- More “instant start” templates (Vite + Nuxt + Tailwind) and updated StackBlitz.\n- Additional codeblock presets (diff-friendly Shiki themes, Monaco decoration helpers).\n- Cookbook docs for AI\u002Fchat patterns (SSE\u002FWebSocket, retry\u002Fresume, markdown mid-states).\n- More showcase examples for embedding Vue components inside Markdown surfaces.\n\n## 📦 Releases\n\n- Latest: [Releases](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Freleases) — see highlights and upgrade notes.\n- Full history: [CHANGELOG.md](.\u002FCHANGELOG.md)\n- Recent highlights (0.0.3-beta.1\u002Fbeta.0):\n  - Parser bumped to `stream-markdown-parser@0.0.36` for parsing fixes.\n  - Monaco upgrades with more languages\u002Fthemes + diff-friendly code block tweaks.\n  - HTML\u002FSVG preview dialog and AST debug view in the playground.\n\n## 🧭 Showcase & examples\n\nBuild something with markstream-vue? Open a PR to add it here (include a link + 1 screenshot\u002FGIF). Ideal fits: AI\u002Fchat UIs, streaming docs, diff\u002Fcode-review panes, or Markdown-driven pages with embedded Vue components.\n\n- **FlowNote** — streaming Markdown note app demo (SSE + virtual window) — https:\u002F\u002Fmarkstream-vue.simonhe.me\u002F\n- **AI Chat surface** — playground “test” page showing incremental batches + share links — https:\u002F\u002Fmarkstream-vue.simonhe.me\u002Ftest\n\n## 📺 Introduction Video\n\nA short video introduces the key features and usage of markstream-vue:\n\n[![Watch on Bilibili](https:\u002F\u002Fi1.hdslb.com\u002Fbfs\u002Farchive\u002Ff073718bd0e51acaea436d7197880478213113c6.jpg)](https:\u002F\u002Fwww.bilibili.com\u002Fvideo\u002FBV17Z4qzpE9c\u002F)\n\nWatch on Bilibili: [Open in Bilibili](https:\u002F\u002Fwww.bilibili.com\u002Fvideo\u002FBV17Z4qzpE9c\u002F)\n\n## Features\n\n- ⚡ Extreme performance: minimal re-rendering and efficient DOM updates for streaming scenarios\n- 🌊 Streaming-first: native support for incomplete or frequently updated tokenized Markdown\n- 🧠 Monaco streaming updates: high-performance Monaco integration for smooth incremental updates of large code blocks\n- 🪄 Progressive Mermaid: charts render instantly when syntax is available, and improve with later updates\n- 🧩 Custom components: embed custom Vue components in Markdown content\n- 📝 Full Markdown support: tables, formulas, emoji, checkboxes, code blocks, etc.\n- 🔄 Real-time updates: supports incremental content without breaking formatting\n- 📦 TypeScript-first: complete type definitions and IntelliSense\n- 🔌 Zero config: works out of the box in Vue 3 projects\n- 🎨 Flexible code block rendering: choose Monaco editor (`CodeBlockNode`) or lightweight Shiki highlighting (`MarkdownCodeBlockNode`)\n- 🧰 Parser toolkit: [`stream-markdown-parser`](.\u002Fpackages\u002Fmarkdown-parser) now documents how to reuse the parser in workers\u002FSSE streams and feed `\u003CMarkdownRender :nodes>` directly, plus APIs for registering global plugins and custom math helpers.\n\n## 🙌 Contributing & community\n\n- Read the contributor guide: [CONTRIBUTING.md](.\u002FCONTRIBUTING.md) and follow the PR template.\n- Be kind and follow the [Code of Conduct](.\u002FCODE_OF_CONDUCT.md).\n- Issues: use templates for bugs\u002Frequests; attach a repro from https:\u002F\u002Fmarkstream-vue.simonhe.me\u002Ftest when possible.\n- Questions? Start a discussion: https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Fdiscussions\n- Chat live: Discord https:\u002F\u002Fdiscord.gg\u002FvkzdkjeRCW\n- Looking to contribute? Start with [good first issues](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Flabels\u002Fgood%20first%20issue).\n- Support guide: [SUPPORT.md](.\u002FSUPPORT.md)\n- PRs: follow Conventional Commits, add tests for parser\u002Frender changes, and include screenshots\u002FGIFs for UI tweaks.\n- If the project helps you, consider starring and sharing the repo — it keeps the work sustainable.\n- Security: see [SECURITY.md](.\u002FSECURITY.md) to report vulnerabilities privately.\n\n### Quick ways to help\n\n- Add repro links\u002Fscreenshots to existing issues.\n- Improve docs\u002Fexamples (especially streaming + SSR\u002Fworker patterns).\n- Share playground\u002Ftest links that showcase performance edge cases.\n\n## Troubleshooting & Common Issues\n\nTroubleshooting has moved into the docs:\nhttps:\u002F\u002Fmarkstream-vue-docs.simonhe.me\u002Fguide\u002Ftroubleshooting\n\nIf you can't find a solution there, open a GitHub issue:\nhttps:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Fissues\n\n### Report an issue quickly\n\n1. Reproduce in the test page and click “generate share link”: https:\u002F\u002Fmarkstream-vue.simonhe.me\u002Ftest\n2. Open a bug report with the link and a screenshot: https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Fissues\u002Fnew?template=bug_report.yml\n\n## Thanks\n\n### Contributors\n\nThanks to all the people who have contributed to this project!\n\n[![Contributors](https:\u002F\u002Fcontrib.rocks\u002Fimage?repo=Simon-He95\u002Fmarkstream-vue)](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkstream-vue\u002Fgraphs\u002Fcontributors)\n\n### Dependencies\n\nThis project uses and benefits from:\n- [stream-monaco](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fstream-monaco)\n- [stream-markdown](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fstream-markdown)\n- [mermaid](https:\u002F\u002Fmermaid-js.github.io\u002Fmermaid)\n- [katex](https:\u002F\u002Fkatex.org\u002F)\n- [shiki](https:\u002F\u002Fgithub.com\u002Fshikijs\u002Fshiki)\n- [markdown-it-ts](https:\u002F\u002Fgithub.com\u002FSimon-He95\u002Fmarkdown-it-ts)\n\nThanks to the authors and contributors of these projects!\n\n## Star History\n\n[![Star History Chart](https:\u002F\u002Fapi.star-history.com\u002Fsvg?repos=Simon-He95\u002Fmarkstream-vue&type=Date)](https:\u002F\u002Fwww.star-history.com\u002F#Simon-He95\u002Fmarkstream-vue&Date)\n\n## License\n\n[MIT](.\u002Flicense) © [Simon He](https:\u002F\u002Fgithub.com\u002FSimon-He95)\n","markstream-vue 是一个专为 Vue 3 设计的 Markdown 渲染器，特别适用于 AI 驱动的流式文档处理。它支持 Monaco 编辑器的增量渲染、Mermaid 图表的渐进显示以及 KaTeX 公式的快速解析，并且能够在实时更新时保持无抖动。该项目的核心功能包括高效的流式渲染和对大文档的优化，确保了在处理复杂或大型 Markdown 文件时的流畅体验。适合用于需要高性能 Markdown 渲染的应用场景，如技术文档编写平台、在线代码编辑器或者任何需要展示动态内容的网站。",2,"2026-06-11 03:19:47","top_language"]