{"id":34759356,"url":"https://github.com/Simon-He95/markstream-vue","last_synced_at":"2025-12-30T09:01:51.583Z","repository":{"id":294823050,"uuid":"988222683","full_name":"Simon-He95/markstream-vue","owner":"Simon-He95","description":"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.","archived":false,"fork":false,"pushed_at":"2025-12-21T11:24:26.000Z","size":21944,"stargazers_count":1737,"open_issues_count":3,"forks_count":103,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-12-23T03:06:25.289Z","etag":null,"topics":["ai","katex","markdown","markstream-vue","mermaid","monaco-editor","shiki","stream-render","vue3"],"latest_commit_sha":null,"homepage":"https://markstream-vue.simonhe.me/","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Simon-He95.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"Simon-He95","custom":["https://github.com/Simon-He95/sponsor"]}},"created_at":"2025-05-22T08:28:26.000Z","updated_at":"2025-12-23T02:27:08.000Z","dependencies_parsed_at":"2025-05-22T08:41:55.742Z","dependency_job_id":"39e27c76-e92e-4629-9591-28295d608ea2","html_url":"https://github.com/Simon-He95/markstream-vue","commit_stats":null,"previous_names":["simon-he95/vue-markdown-render","simon-he95/vue-markdown-renderer","simon-he95/markstream-vue"],"tags_count":135,"template":false,"template_full_name":null,"purl":"pkg:github/Simon-He95/markstream-vue","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Simon-He95%2Fmarkstream-vue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Simon-He95%2Fmarkstream-vue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Simon-He95%2Fmarkstream-vue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Simon-He95%2Fmarkstream-vue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Simon-He95","download_url":"https://codeload.github.com/Simon-He95/markstream-vue/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Simon-He95%2Fmarkstream-vue/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28077947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-27T02:00:05.897Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","katex","markdown","markstream-vue","mermaid","monaco-editor","shiki","stream-render","vue3"],"created_at":"2025-12-25T06:00:31.486Z","updated_at":"2025-12-30T09:01:51.573Z","avatar_url":"https://github.com/Simon-He95.png","language":"Vue","funding_links":["https://github.com/sponsors/Simon-He95","https://github.com/Simon-He95/sponsor"],"categories":["Vue"],"sub_categories":[],"readme":"# markstream-vue\n\n\u003e 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://img.shields.io/npm/v/markstream-vue?color=a1b858\u0026label=)](https://www.npmjs.com/package/markstream-vue)\n[![中文版](https://img.shields.io/badge/docs-中文文档-blue)](README.zh-CN.md)\n[![Docs](https://img.shields.io/badge/docs-vitepress-blue)](https://markstream-vue-docs.simonhe.me/)\n[![Playground](https://img.shields.io/badge/playground-live-34c759)](https://markstream-vue.simonhe.me/)\n[![Test page](https://img.shields.io/badge/test-shareable%20repro-0A84FF)](https://markstream-vue.simonhe.me/test)\n[![NPM downloads](https://img.shields.io/npm/dm/markstream-vue)](https://www.npmjs.com/package/markstream-vue)\n[![Bundle size](https://img.shields.io/bundlephobia/minzip/markstream-vue)](https://bundlephobia.com/package/markstream-vue)\n[![Release](https://img.shields.io/github/v/release/Simon-He95/markstream-vue?display_name=release\u0026logo=github)](https://github.com/Simon-He95/markstream-vue/releases)\n[![Discussions](https://img.shields.io/github/discussions/Simon-He95/markstream-vue?logo=github)](https://github.com/Simon-He95/markstream-vue/discussions)\n[![Discord](https://img.shields.io/discord/986352439269560380?label=discord\u0026logo=discord\u0026logoColor=fff\u0026color=5865F2)](https://discord.gg/vkzdkjeRCW)\n[![Support](https://img.shields.io/badge/support-guide-ff6f61)](./SUPPORT.md)\n[![Security](https://img.shields.io/badge/security-policy-8A2BE2)](./SECURITY.md)\n[![CI](https://github.com/Simon-He95/markstream-vue/actions/workflows/ci.yml/badge.svg)](https://github.com/Simon-He95/markstream-vue/actions/workflows/ci.yml)\n[![License](https://img.shields.io/npm/l/markstream-vue)](./license)\n\nLooking for Vue 2.6? Use [`markstream-vue2`](./packages/markstream-vue2/README.md) (a baseline port with fewer advanced features).\n\n## Contents\n\n- [TL;DR Highlights](#tldr-highlights)\n- [Try It Now](#-try-it-now)\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 \u0026 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- [Releases](#-releases)\n- [Showcase](#-showcase--examples)\n- [Contributing \u0026 community](#-contributing--community)\n- [Community \u0026 support](#-community--support)\n- [Troubleshooting](#troubleshooting--common-issues)\n\u003e 📖 All detailed documentation, API, examples, and advanced usage have been migrated to the VitePress documentation site:\n\u003e https://markstream-vue-docs.simonhe.me/guide/\n\n## TL;DR Highlights\n\n- Purpose-built for **streaming Markdown** (AI/chat/SSE) 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/Shiki) 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## 🚀 Try It Now\n\n- Playground (interactive demo): https://markstream-vue.simonhe.me/\n- Interactive test page (shareable links, easy reproduction): https://markstream-vue.simonhe.me/test\n- Docs: https://markstream-vue-docs.simonhe.me/guide/\n- AI/LLM context (project map): https://markstream-vue-docs.simonhe.me/llms\n- AI/LLM context (中文): https://markstream-vue-docs.simonhe.me/llms.zh-CN\n- One-click StackBlitz demo: https://stackblitz.com/github/Simon-He95/markstream-vue?file=playground/src/App.vue\n- Changelog: [CHANGELOG.md](./CHANGELOG.md)\n- Nuxt playground: `pnpm play:nuxt`\n- Discord: https://discord.gg/vkzdkjeRCW\n\n## 💬 Community \u0026 support\n\n- Discussions: https://github.com/Simon-He95/markstream-vue/discussions\n- Discord: https://discord.gg/vkzdkjeRCW\n- Issues: please use templates and attach a repro link (https://markstream-vue.simonhe.me/test)\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## ⚡ 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// main.ts\nimport { createApp } from 'vue'\nimport 'markstream-vue/index.css'\n\ncreateApp({\n  components: { MarkdownRender },\n  template: '\u003cMarkdownRender custom-id=\"docs\" :content=\"doc\" /\u003e',\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/index.css` after your reset (e.g., Tailwind `@layer components`) so renderer styles win over utility classes. Install optional peers such as `stream-monaco`, `shiki`, `mermaid`, and `katex` only when you need Monaco code blocks, Shiki highlighting, diagrams, or math.\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\nEnable heavy peers only when needed:\n\n```ts\nimport { enableKatex, enableMermaid } from 'markstream-vue'\nimport 'markstream-vue/index.css'\n\n// after you install `mermaid` / `katex` peers\nenableMermaid()\nenableKatex()\n```\n\nIf you load KaTeX via CDN and want KaTeX rendering in a Web Worker (no bundler / 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  // UMD builds used by importScripts() inside the worker\n  katexUrl: 'https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.js',\n  mhchemUrl: 'https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/mhchem.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  // Mermaid CDN builds are commonly ESM; module worker is recommended.\n  mode: 'module',\n  workerOptions: { type: 'module' },\n  mermaidUrl: 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs',\n})\n\nif (worker)\n  setMermaidWorker(worker)\n```\n\n### Nuxt quick drop-in\n\n```ts\n// plugins/markstream-vue.client.ts\nimport { defineNuxtPlugin } from '#app'\nimport MarkdownRender from 'markstream-vue'\nimport 'markstream-vue/index.css'\n\nexport default defineNuxtPlugin((nuxtApp) =\u003e {\n  nuxtApp.vueApp.component('MarkdownRender', MarkdownRender)\n})\n```\n\nThen use `\u003cMarkdownRender :content=\"md\" /\u003e` in your pages.\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 test` — Vitest suite (`pnpm test:update` for snapshots)\n- `pnpm typecheck` / `pnpm lint` — type and lint checks\n\n## ⏱️ Streaming in 30 seconds\n\nRender streamed Markdown (SSE/websocket) with incremental updates:\n\n```ts\nimport type { ParsedNode } from 'markstream-vue'\nimport MarkdownRender, {\n  getMarkdown,\n\n  parseMarkdownToStructure\n} from 'markstream-vue'\nimport { ref } from 'vue'\n\nconst nodes = ref\u003cParsedNode[]\u003e([])\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// e.g., inside your SSE/onmessage handler\neventSource.onmessage = event =\u003e addChunk(event.data)\n\n// template\n// \u003cMarkdownRender\n//   :nodes=\"nodes\"\n//   :max-live-nodes=\"0\"\n//   :batch-rendering=\"{\n//     renderBatchSize: 16,\n//     renderBatchDelay: 8,\n//   }\"\n// /\u003e\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### SSR / 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// server or worker\nimport { getMarkdown, parseMarkdownToStructure } from 'markstream-vue'\n\nconst md = getMarkdown()\nconst nodes = parseMarkdownToStructure('# Hello\\n\\nThis is parsed once', md)\n// send `nodes` JSON to the client\n```\n\n```vue\n\u003c!-- client --\u003e\n\u003cMarkdownRender :nodes=\"nodesFromServer\" /\u003e\n```\n\nThis avoids client-side parsing and keeps SSR/hydration 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[]\u003e(initialNodes)\nconst buffer = ref(initialMarkdown)\nconst md = getMarkdown() // 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/WebSocket chunks continue the stream.\n\n\u003e 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## ⚙️ 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\u003e 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 \u0026 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` / `enableKatex` / `enableMonaco`: opt-in heavy deps when needed.\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- `custom-components`: register inline Vue components for custom tags/markers.\n\nExample: map Markdown placeholders to Vue components\n\n```ts\nimport { setCustomComponents } from 'markstream-vue'\n\nsetCustomComponents({\n  CALLOUT: () =\u003e import('./components/Callout.vue'),\n})\n\n// Markdown: [[CALLOUT:warning title=\"Heads up\" body=\"Details here\"]]\n```\n\nOr pass per-renderer:\n\n```vue\n\u003cMarkdownRender\n  :content=\"doc\"\n  :custom-components=\"{\n    CALLOUT: () =\u003e import('./components/Callout.vue'),\n  }\"\n/\u003e\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) =\u003e tokens,\n  }\"\n/\u003e\n```\n\n## 🔥 Where it shines\n\n- AI/chat UIs with long-form answers and Markdown tokens arriving over SSE/websocket.\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/KaTeX not rendering? Install the peer (`mermaid` / `katex`) and pass `:enable-mermaid=\"true\"` / `:enable-katex=\"true\"` or call the loader setters. If you load them via CDN script tags, the library will also pick up `window.mermaid` / `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/index.css` once. Use Shiki (`MarkdownCodeBlockNode`) when Monaco is too heavy.\n- Custom UI: register components via `setCustomComponents` (global) or `custom-components` prop, then emit markers/placeholders 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 \u0026 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/chat patterns (SSE/WebSocket, retry/resume, markdown mid-states).\n- More showcase examples for embedding Vue components inside Markdown surfaces.\n\n## 📦 Releases\n\n- Latest: [Releases](https://github.com/Simon-He95/markstream-vue/releases) — see highlights and upgrade notes.\n- Full history: [CHANGELOG.md](./CHANGELOG.md)\n- Recent highlights (0.0.3-beta.1/beta.0):\n  - Parser bumped to `stream-markdown-parser@0.0.36` for parsing fixes.\n  - Monaco upgrades with more languages/themes + diff-friendly code block tweaks.\n  - HTML/SVG preview dialog and AST debug view in the playground.\n\n## 🧭 Showcase \u0026 examples\n\nBuild something with markstream-vue? Open a PR to add it here (include a link + 1 screenshot/GIF). Ideal fits: AI/chat UIs, streaming docs, diff/code-review panes, or Markdown-driven pages with embedded Vue components.\n\n- **FlowNote** — streaming Markdown note app demo (SSE + virtual window) — https://markstream-vue.simonhe.me/\n- **AI Chat surface** — playground “test” page showing incremental batches + share links — https://markstream-vue.simonhe.me/test\n\n## 📺 Introduction Video\n\nA short video introduces the key features and usage of markstream-vue:\n\n[![Watch on Bilibili](https://i1.hdslb.com/bfs/archive/f073718bd0e51acaea436d7197880478213113c6.jpg)](https://www.bilibili.com/video/BV17Z4qzpE9c/)\n\nWatch on Bilibili: [Open in Bilibili](https://www.bilibili.com/video/BV17Z4qzpE9c/)\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`](./packages/markdown-parser) now documents how to reuse the parser in workers/SSE streams and feed `\u003cMarkdownRender :nodes\u003e` directly, plus APIs for registering global plugins and custom math helpers.\n\n## 🙌 Contributing \u0026 community\n\n- Read the contributor guide: [CONTRIBUTING.md](./CONTRIBUTING.md) and follow the PR template.\n- Be kind and follow the [Code of Conduct](./CODE_OF_CONDUCT.md).\n- Issues: use templates for bugs/requests; attach a repro from https://markstream-vue.simonhe.me/test when possible.\n- Questions? Start a discussion: https://github.com/Simon-He95/markstream-vue/discussions\n- Chat live: Discord https://discord.gg/vkzdkjeRCW\n- Looking to contribute? Start with [good first issues](https://github.com/Simon-He95/markstream-vue/labels/good%20first%20issue).\n- Support guide: [SUPPORT.md](./SUPPORT.md)\n- PRs: follow Conventional Commits, add tests for parser/render changes, and include screenshots/GIFs 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](./SECURITY.md) to report vulnerabilities privately.\n\n### Quick ways to help\n\n- Add repro links/screenshots to existing issues.\n- Improve docs/examples (especially streaming + SSR/worker patterns).\n- Share playground/test links that showcase performance edge cases.\n\n## Troubleshooting \u0026 Common Issues\n\nTroubleshooting has moved into the docs:\nhttps://markstream-vue-docs.simonhe.me/guide/troubleshooting\n\nIf you can't find a solution there, open a GitHub issue:\nhttps://github.com/Simon-He95/markstream-vue/issues\n\n### Report an issue quickly\n\n1. Reproduce in the test page and click “generate share link”: https://markstream-vue.simonhe.me/test\n2. Open a bug report with the link and a screenshot: https://github.com/Simon-He95/markstream-vue/issues/new?template=bug_report.yml\n\n## Thanks\n\nThis project uses and benefits from:\n- [stream-monaco](https://github.com/Simon-He95/stream-monaco)\n- [stream-markdown](https://github.com/Simon-He95/stream-markdown)\n- [mermaid](https://mermaid-js.github.io/mermaid)\n- [katex](https://katex.org/)\n- [shiki](https://github.com/shikijs/shiki)\n- [markdown-it-ts](https://github.com/Simon-He95/markdown-it-ts)\n\nThanks to the authors and contributors of these projects!\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=Simon-He95/markstream-vue\u0026type=Date)](https://www.star-history.com/#Simon-He95/markstream-vue\u0026Date)\n\n## License\n\n[MIT](./license) © [Simon He](https://github.com/Simon-He95)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSimon-He95%2Fmarkstream-vue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSimon-He95%2Fmarkstream-vue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSimon-He95%2Fmarkstream-vue/lists"}