markstream-vue
Simon-He95/markstream-vue — AI / SSE 向けストリーミング Markdown レンダラ(Vue 3 中心のパッケージ群)
markstream-vue は、AI チャットや LLM トークンストリーム向けの ストリーミング Markdown レンダラ。未完成の Markdown、長い回答、Mermaid / KaTeX、ストリーミング中のコードブロックを、ちらつきを抑えつつ描画する。完成済み文書向けの marked / markdown-it / react-markdown とは用途が分かれる。
リポジトリ名は markstream-vue だが、Markstream として Vue / React / Svelte / Angular / Vue 2 向けのレンダラ群と、フレームワーク非依存の stream-markdown-parser・markstream-core を同梱する。
公式ドキュメントの framework overview が選択ガイド。Vue / Nuxt / VitePress なら markstream-vue、パースだけなら stream-markdown-parser。
| パッケージ | 対象 | インストール |
|---|---|---|
markstream-vue | Vue 3 / Nuxt / VitePress | pnpm add markstream-vue |
markstream-react | React / Next.js / Remix | pnpm add markstream-react |
markstream-svelte | Svelte 5 | pnpm add markstream-svelte svelte@^5 |
markstream-angular | Angular standalone | pnpm add markstream-angular |
markstream-vue2 | Vue 2.6 / 2.7 | pnpm add markstream-vue2 |
stream-markdown-parser | 任意 JS/TS(パース) | pnpm add stream-markdown-parser |
markstream-core | ストリーム制御ユーティリティ | pnpm add markstream-core |
flowchart TD
parser["stream-markdown-parser"]
core["markstream-core"]
vue["markstream-vue"]
react["markstream-react"]
svelte["markstream-svelte"]
angular["markstream-angular"]
vue2["markstream-vue2"]
parser --> vue
parser --> react
parser --> svelte
parser --> angular
parser --> vue2
core --> vue
core --> react
CSS を一度 import し、MarkdownRender に content とストリーム完了フラグ final を渡す。
pnpm add markstream-vue
<script setup lang="ts">
import MarkdownRender from 'markstream-vue'
import 'markstream-vue/index.css'
defineProps<{ content: string; isDone: boolean }>()
</script>
<template>
<MarkdownRender mode="chat" :content="content" :final="isDone" />
</template>
Tailwind 利用時は @import 'markstream-vue/index.css' layer(components); のようにレイヤを指定し、レンダラ側スタイルがユーティリティに負けないようにする。モバイルでルート rem をスケールしている場合は markstream-vue/index.px.css を検討する。
const content = ref('')
const final = ref(false)
eventSource.onmessage = (event) => {
content.value += event.data
}
eventSource.addEventListener('done', () => {
final.value = true
})
// <MarkdownRender :content="content" :final="final" :fade="false" />
mode="chat"
AI / SSE 向け。ペースを安定させ、不透明度アニメによるちらつきを避ける。典型では fade={false} と smooth-streaming="auto"。
mode="docs"
リッチなドキュメント向け。大きめの描画バッチ、ツールチップ、fade が既定で有効。コードレンダラとレイアウト戦略が chat と異なる。
mode="minimal"
chat と同系統の軽量既定を、非チャット面で中立名として使いたいとき。
final が立ったからといって chat → docs に変えない。ペースは smooth-streaming / typewriter / fade で調整する。smooth-streaming の高頻度更新と fade の併用は、opacity 再スタートの連続になりやすい。
| プリセット | 設定 | 用途 |
|---|---|---|
| Virtual window | max-live-nodes 既定 220 |
長文のスクロールバックとメモリを安定。ノードはすぐ描画し、マウント窓をスライド。 |
| Incremental | :max-live-nodes="0" |
タイプライタ風。バッチ系 props(renderBatchSize など)でスライス描画。 |
チャットでは例として renderBatchSize={16}、renderBatchDelay={8}、renderBatchBudgetMs を下げて CPU を抑える組み合わせが README に示されている。
content(生 Markdown)または nodes(事前パース結果)のどちらかを受け取り、NodeRenderer 経由でブロック/インラインを描画する。サーバーや Worker で parseMarkdownToStructure した結果をクライアントに渡すと、SSR / hydration を決定的にしやすい。
flowchart TD
src["SSE / WebSocket / string"]
md["content または nodes"]
parse["parseMarkdownToStructure\nstreamParse auto / true"]
batch["virtual window または\nincremental batches"]
nodes["NodeRenderer"]
peers["optional: Mermaid / KaTeX\nMonaco / Shiki / D2"]
dom[".markstream-vue DOM"]
src --> md
md --> parse
parse --> batch
batch --> nodes
nodes --> peers
peers --> dom
nodes --> dom
parseMarkdownToStructureの既定はstreamParse: 'auto'。非 final のトップレベルではmd.stream.parseとキャッシュを使う。MarkdownRenderが自分でパースする場合、ストリーム向けにstreamParse: trueが既定。finalが変わるとキャッシュを無効化し、完了セマンティクスで再パースする。- 無関係な one-shot 文書で同一
mdインスタンスを再利用するときは{ final: true }または{ streamParse: false }を渡す。
| prop / API | 要点 |
|---|---|
content / nodes | 生 Markdown か、事前パース済みノード。 |
final | ストリーム終端。途中状態の loading パースを止め、未閉じ構文を確定させる。 |
max-live-nodes | 220(仮想化)または 0(増分バッチ)。 |
batchRendering 系 | initialRenderBatchSize / renderBatchSize / renderBatchDelay / renderBatchBudgetMs。 |
smooth-streaming | typewriter / max-live-nodes <= 0 では既定オン。生チャンク間隔にしたい面では false。 |
parse-options | preTransformTokens や requireClosingStrong などパーサフック。 |
custom-html-tags | 例: ['thinking']。カスタムタグをストリーム許可し、カスタムノードとして出す。 |
setCustomComponents | custom-id スコープで Vue コンポーネントを登録。 |
code-block-props | 例: theme: { light, dark }。構造キー(node, ctx 等)は無視される。 |
htmlPolicy | 信頼できない UGC では "escape" を推奨(生 HTML をテキスト扱い)。 |
is-dark / .dark | 祖先に .dark、または prop でレンダラ内ダークを指定。 |
mermaid / katex / stream-diffs / shiki などは任意 peer。使わない限りバンドルに乗らない。強化コードブロック(File / Diff)が要るなら stream-diffs。無い場合は意図的に <pre> へフォールバックする。
import { enableKatex, enableMermaid } from 'markstream-vue'
import 'markstream-vue/index.css'
import 'katex/dist/katex.min.css'
enableMermaid()
enableKatex()
CDN 経由で KaTeX / Mermaid を載せる場合は、createKaTeXWorkerFromCDN + setKaTeXWorker、createMermaidWorkerFromCDN + setMermaidWorker で Worker を注入できる(オフメインスレッド描画・パース向け)。
レンダラ CSS は内部コンテナ .markstream-vue にスコープされる。デザイン方針は「既定スタイル付き + CSS 変数で換装可能(非 headless)」。shadcn 互換のため --ms-* bridge token で宿主変数を継承し、未定義時は内蔵デフォルトへフォールバックする(design/architecture.md)。
MarkdownRender 外でノードコンポーネント単体を使うときは、親に class="markstream-vue" を付ける。
| 症状 / 状況 | 対応 |
|---|---|
| Mermaid / KaTeX が出ない | peer を入れ、enableMermaid / enableKatex、または prop の enable 系。CDN なら window.mermaid / window.katex も拾う。 |
| リッチコードブロックが出ない | stream-diffs を入れるか、:render-code-blocks-as-pre="true" で明示的に軽量にする。 |
末尾の $$ やフェンスがずっと loading |
ストリーム終了時に :final="true"、または parseMarkdownToStructure(..., { final: true })。 |
| 信頼できない HTML | htmlPolicy="escape"。 |
| 1.0 の安定面 | MarkdownRender、ストリーミング / 事前ノード、安全 HTML 方針、任意統合、virtual-scroll 連携、CSS / worker / SSR エントリが契約。npm タグは beta のままの期間があり得る。 |
| ニーズ | 一般的な Markdown プレビュー | markstream-vue |
|---|---|---|
| ストリーム入力 | 全体再描画・フラッシュ | 増分バッチ + virtual window |
| 大きなコード | 再ハイライトが重い | stream-diffs / Shiki オプション |
| 図 | パース完了までブロックしやすい | プログレッシブ Mermaid |
| カスタム UI | スロットが限られがち | インライン Vue コンポーネント + 型付きノード |
| 長文 | メモリが跳ねやすい | live-node 上限で定常化 |
- GitHub: Simon-He95/markstream-vue
- Framework overview / docs
- Vue 3 playground
- Shareable test / repro page
- npm: markstream-vue
- llms.txt(LLM 向け要約)
- エージェント向けスキル:
npx skills add Simon-He95/markstream-vue(リポジトリの.agents/skills)
出典: Simon-He95/markstream-vue の README.md / design/architecture.md(解説時点の upstream)