markstream-vue 0.0.14-beta.6 → 0.0.14-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,7 +16,12 @@ Use this skill when the host app is Angular and the task is to adopt the Angular
16
16
  4. Prefer standalone Angular integration.
17
17
  - Use `MarkstreamAngularComponent` in `imports` and keep examples signal-friendly.
18
18
  5. Start with `[content]`.
19
- - Use `[final]`, `[codeBlockStream]`, and other streaming inputs only when the UI actually streams.
19
+ - For streaming AI chat, keep `[content]` and use built-in smooth streaming first.
20
+ - `[smoothStreaming]="'auto'"` is the default and activates when `[typewriter]="true"` or `[maxLiveNodes]="0"`.
21
+ - `[typewriter]` only controls the blinking cursor and defaults to `false`.
22
+ - `[fade]` controls node enter and streamed-text fade animations and defaults to `true`.
23
+ - Use `[final]` for end-of-stream state; final parsing is gated until visible content catches up when smooth streaming is active.
24
+ - Move to `nodes` + `final` only for worker-preparsed content, shared AST stores, or custom AST control.
20
25
  - Remember that `[htmlPolicy]` now defaults to `'safe'`, and Mermaid strict mode is on by default through `[mermaidProps]`.
21
26
  6. Use `[customHtmlTags]` and `[customComponents]` for trusted tag workflows.
22
27
  7. Validate with the smallest useful Angular dev or build command.
@@ -24,7 +29,7 @@ Use this skill when the host app is Angular and the task is to adopt the Angular
24
29
  ## Default Decisions
25
30
 
26
31
  - Standalone Angular first, NgModule-era patterns only when the repo still depends on them.
27
- - Treat streaming flags as opt-in.
32
+ - Treat the cursor as opt-in (`typewriter=false` by default), but keep fade animations enabled by default (`fade=true`).
28
33
  - Keep optional peers minimal and explicit.
29
34
  - Keep `[htmlPolicy]="'safe'"` and Mermaid strict mode unless the task is preserving trusted legacy rendering.
30
35
  - If a trusted surface needs broader old behavior, opt out locally with `[htmlPolicy]="'trusted'"` and `[mermaidProps]="{ isStrict: false }"`, and document that trust boundary.
@@ -24,6 +24,7 @@ Read [references/patterns.md](references/patterns.md) before choosing an overrid
24
24
  4. Preserve nested Markdown when needed.
25
25
  - For trusted custom tags with inner Markdown, render `node.content` with a nested renderer.
26
26
  - Pass the same custom-tag allowlist to nested renderers.
27
+ - Nested renderers inside a smooth-streaming parent are automatically suppressed from double pacing — do not add `smooth-streaming` to child renderers.
27
28
  5. Keep props and cleanup intact.
28
29
  - Preserve `node`, `loading`, `indexKey`, `customId`, and `isDark`.
29
30
  - For `mermaid` and `infographic` overrides, preserve `estimatedPreviewHeightPx` so async preview shells keep stable height during remounts.
@@ -21,11 +21,18 @@ Read [references/scenarios.md](references/scenarios.md) before making dependency
21
21
  - For Vue 3 Monaco preloading, use `preloadCodeBlockRuntime` from `markstream-vue` so the renderer runtime knows Monaco is warm. Existing `getUseMonaco()` calls are still compatible.
22
22
  3. Fix CSS order.
23
23
  - Put reset styles before Markstream styles.
24
- - In Tailwind or UnoCSS projects, place `markstream-*/index.css` inside `@layer components`.
24
+ - In Tailwind or UnoCSS projects, use `@import 'markstream-*/index.css' layer(components);`.
25
25
  - Import `katex/dist/katex.min.css` when math is enabled.
26
26
  4. Add the smallest working render example.
27
27
  - Use `content` for static or low-frequency rendering.
28
- - Use `nodes` plus `final` when the app receives streaming updates.
28
+ - For streaming AI chat, start with `content` and built-in smooth streaming.
29
+ - Auto mode is the default: `smoothStreaming="auto"` / `smooth-streaming="auto"`.
30
+ - Auto pacing activates when `typewriter=true` or `maxLiveNodes <= 0` / `max-live-nodes <= 0`.
31
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
32
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
33
+ - For high-frequency smooth streams, consider `fade=false` / `:fade="false"` / `[fade]="false"` to avoid fade stacking.
34
+ - Use `nodes` + `final` only for worker preparsing, shared AST stores, or custom AST control.
35
+ - For manual pacing with `nodes`, use `useSmoothMarkdownStream`: `enqueue()` chunks, `finish()` when done, render from `visible`, wait for `caughtUp` before final parsing.
29
36
  - Preserve the default hardening: HTML policies now default to `safe`, and Mermaid runs in strict mode by default.
30
37
  5. Keep customization scoped.
31
38
  - If the task requires overrides, prefer `customId` / `custom-id` plus scoped `setCustomComponents(...)`.
@@ -36,7 +43,9 @@ Read [references/scenarios.md](references/scenarios.md) before making dependency
36
43
  ## Default Decisions
37
44
 
38
45
  - Prefer the minimal peer set over "install everything".
39
- - Prefer `content` unless the app is clearly SSE, chat, token-streaming, or worker-preparsed.
46
+ - Prefer `content` for most streaming chat now that built-in smooth streaming is available across Vue 3, Vue 2, React, Svelte, and Angular.
47
+ - Move to `nodes` only when another layer owns parsing or AST transforms.
48
+ - When using `content` for streaming, smooth streaming (`smooth-streaming="auto"`) is on by default for `typewriter` or `max-live-nodes <= 0`. Set `:smooth-streaming="false"` to preserve raw chunk cadence.
40
49
  - Treat CSS order as a first-class part of installation, not a later cleanup.
41
50
  - When the request includes SSR, explicitly gate browser-only peers behind client-only boundaries.
42
51
  - Do not widen HTML or Mermaid security defaults unless the user explicitly needs trusted legacy compatibility.
@@ -24,11 +24,16 @@
24
24
 
25
25
  - reset first
26
26
  - Markstream CSS after reset
27
- - in Tailwind or UnoCSS projects, keep Markstream CSS inside `@layer components`
27
+ - in Tailwind or UnoCSS projects, use `@import '...' layer(components)`
28
28
  - import KaTeX CSS when math is used
29
29
  - when standalone node components are rendered directly, wrap them with the package root class such as `.markstream-vue`, `.markstream-react`, or `.markstream-svelte`
30
30
 
31
31
  ## Input choice
32
32
 
33
- - `content`: docs pages, static articles, low-frequency updates
34
- - `nodes` + `final`: SSE, token streaming, AI chat, worker-preparsed content
33
+ - `content`: docs pages, static articles, low-frequency updates, and most SSE / token streaming / AI chat surfaces.
34
+ - `content` + built-in smooth streaming: jittery AI streams where visible output should be paced independently from raw chunk cadence.
35
+ - `smoothStreaming="auto"` / `smooth-streaming="auto"` is the default.
36
+ - Auto mode enables pacing when `typewriter=true` or `maxLiveNodes <= 0` / `max-live-nodes <= 0`.
37
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
38
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
39
+ - `nodes` + `final`: worker-preparsed content, shared AST stores, custom AST transforms, or cases where another layer already owns parsing.
@@ -29,8 +29,10 @@ Read [references/adoption-checklist.md](references/adoption-checklist.md) before
29
29
  5. Review gaps honestly.
30
30
  - Do not claim 1:1 parity where none exists.
31
31
  - Call out parser, plugin, security, or HTML behavior that still needs manual review.
32
- 6. Treat streaming as a second pass unless clearly required now.
33
- - Move to `nodes` only when the app receives streaming or high-frequency updates.
32
+ 6. Consider smooth streaming before jumping to `nodes`.
33
+ - If the app streams `content` and only needs pacing, `smooth-streaming="auto"` (the default) handles it without requiring `nodes`.
34
+ - Move to `nodes` only when the app needs custom AST control, worker preparsing, or high-frequency structural updates.
35
+ - When smooth streaming is on, pair it with `:fade="false"`.
34
36
  7. Validate and summarize.
35
37
  - Run the smallest relevant tests or build.
36
38
  - Report direct mappings, TODOs, and remaining verification work.
@@ -38,6 +40,7 @@ Read [references/adoption-checklist.md](references/adoption-checklist.md) before
38
40
  ## Default Decisions
39
41
 
40
42
  - Renderer swap first, streaming optimization second.
43
+ - Smooth streaming is an intermediate option between "just content" and "full nodes migration": it paces visible output without requiring AST control.
41
44
  - Preserve safety over feature parity when HTML or security rules are involved.
42
45
  - Prefer explicit TODOs over vague claims.
43
46
  - Recommend against migration when the current stack depends heavily on transforms that Markstream does not mirror directly.
@@ -47,6 +50,7 @@ Read [references/adoption-checklist.md](references/adoption-checklist.md) before
47
50
 
48
51
  - `docs/guide/react-markdown-migration.md`
49
52
  - `docs/guide/react-markdown-migration-cookbook.md`
53
+ - `docs/guide/ai-chat-streaming.md`
50
54
  - `docs/guide/installation.md`
51
55
  - `docs/guide/component-overrides.md`
52
56
  - `docs/guide/advanced.md`
@@ -14,13 +14,19 @@ Use this skill when the host app is Nuxt and SSR boundaries matter.
14
14
  3. Keep browser-only peers behind client-only boundaries.
15
15
  - Prefer `<client-only>` wrappers, `.client` plugins, or guarded setup paths.
16
16
  4. Import `markstream-vue/index.css` from a client-safe app shell or plugin.
17
- 5. Start with `content`, and move to `nodes` plus `final` only when the UI is streaming.
17
+ 5. Start with `content`, and move to `nodes` plus `final` only when the UI needs custom AST control.
18
+ - For streaming AI chat, use `typewriter` or `:max-live-nodes="0"` — smooth streaming (`smooth-streaming="auto"`) paces visible output automatically.
19
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
20
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
21
+ - When smooth streaming is on, pair it with `:fade="false"` to avoid delta fade stacking with high-commit pacing.
22
+ - In SSR, avoid `smooth-streaming="true"` on first-screen content; the mounted gate inside `auto` prevents hydration mismatch.
18
23
  - Remember that `html-policy` now defaults to `safe`, and Mermaid strict mode is on by default through `mermaid-props`.
19
24
  6. Validate with the smallest relevant Nuxt dev, build, or typecheck command.
20
25
 
21
26
  ## Default Decisions
22
27
 
23
28
  - SSR safety comes before feature completeness.
29
+ - Smooth streaming is SSR-safe in `auto` mode (the default) because it gates on mount. Do not use `smooth-streaming="true"` for first-screen SSR content — it bypasses the mounted gate and can cause hydration mismatch or blank flash.
24
30
  - Avoid import-time access to browser globals from server code paths.
25
31
  - Treat Monaco, Mermaid workers, and similar heavy peers as client-only unless the repo already has a proven SSR pattern.
26
32
  - Keep `html-policy="safe"` and Mermaid strict mode unless the task is preserving trusted legacy rendering.
@@ -13,7 +13,11 @@ Use this skill when the host app is React or Next and the task is to wire Markst
13
13
  2. Install `markstream-react` plus only the requested optional peers.
14
14
  3. Import `markstream-react/index.css` from the app shell or client entry.
15
15
  4. Start with `content`.
16
- - Move to `nodes` plus `final` only when the UI receives streaming or high-frequency updates.
16
+ - For streaming or high-frequency AI output, keep `content` and use built-in smooth streaming first.
17
+ - `smoothStreaming="auto"` is the default and activates when `typewriter={true}` or `maxLiveNodes <= 0`.
18
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
19
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
20
+ - Move to `nodes` + `final` only for worker-preparsed content, shared AST stores, or custom AST control.
17
21
  - Remember that `htmlPolicy` now defaults to `safe`, and Mermaid strict mode is on by default through `mermaidProps`.
18
22
  5. Respect SSR boundaries in Next.
19
23
  - Prefer `use client`, dynamic imports with `ssr: false`, or other client-only boundaries when browser-only peers are involved.
@@ -24,7 +28,10 @@ Use this skill when the host app is React or Next and the task is to wire Markst
24
28
 
25
29
  - Renderer wiring first, migration cleanup second.
26
30
  - If the repo already uses `react-markdown`, pair this skill with `markstream-migration`.
31
+ - Prefer `content` with built-in smooth streaming for most AI chat / token streaming surfaces.
32
+ - Move to `nodes` only when another layer owns parsing or AST transforms.
27
33
  - Prefer the smallest client-only boundary that solves the SSR issue.
34
+ - Avoid `smoothStreaming={true}` for first-screen SSR content unless intentionally starting from blank; auto mode uses the mounted gate.
28
35
  - Keep `htmlPolicy="safe"` and Mermaid strict mode unless the request is preserving trusted legacy rendering.
29
36
  - If a trusted surface needs older behavior, use `htmlPolicy="trusted"` and `mermaidProps={{ isStrict: false }}` only on that surface and explain why.
30
37
 
@@ -8,7 +8,12 @@ description: Integrate markstream-svelte in Svelte 5 apps. Svelte 4 unsupported.
8
8
  - Confirm Svelte 5; ask Svelte 4 users to upgrade.
9
9
  - Add package and only requested peers.
10
10
  - Import CSS after resets; KaTeX CSS for math.
11
- - Default to `<MarkdownRender {content} />`; use `nodes`+`final` for streaming/workers.
11
+ - Default to `<MarkdownRender {content} />`.
12
+ - For streaming AI chat, keep `content` and use built-in smooth streaming first.
13
+ - `smoothStreaming="auto"` is the default and activates when `typewriter={true}` or `maxLiveNodes <= 0`.
14
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
15
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
16
+ - Use `nodes` + `final` for worker-preparsed content, shared AST stores, or custom AST control.
12
17
  - Use `$props()` and callbacks.
13
18
  - Workers: `setKaTeXWorker`, `setMermaidWorker`, `workers/*?worker`.
14
19
  - Custom UI: scoped `setCustomComponents`, `customId`, `customHtmlTags`.
@@ -12,9 +12,14 @@ Use this skill when the host app is plain Vue 3, typically Vite-based, and not N
12
12
  1. Confirm the repo is Vue 3 and not Nuxt.
13
13
  2. Install `markstream-vue` plus only the optional peers required by the requested features.
14
14
  3. Import `markstream-vue/index.css` after resets.
15
- - In Tailwind or UnoCSS projects, keep Markstream styles inside `@layer components`.
15
+ - In Tailwind or UnoCSS projects, use `@import 'markstream-vue/index.css' layer(components);`.
16
16
  4. Start with `<MarkdownRender :content="markdown" />`.
17
- - Switch to `nodes` plus `final` only for streaming, SSE, or high-frequency updates.
17
+ - For AI chat or streaming UIs, use `typewriter` or `:max-live-nodes="0"` smooth streaming is auto-enabled (`smooth-streaming="auto"`, the default) and paces visible output so bursty chunks appear steadily.
18
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
19
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
20
+ - Set `:smooth-streaming="false"` to preserve raw chunk cadence; set `:smooth-streaming="true"` to force smooth pacing even on first-screen content (may cause hydration mismatch in SSR).
21
+ - When smooth streaming is on, pair it with `:fade="false"` to avoid delta fade (280 ms) stacking with high-commit pacing.
22
+ - Switch to `nodes` plus `final` only when the app needs custom AST control, worker preparsing, or structural updates beyond pacing.
18
23
  - Remember that `html-policy` now defaults to `safe`, and Mermaid strict mode is on by default through `mermaid-props`.
19
24
  5. Use `custom-id` plus scoped `setCustomComponents(...)` for overrides.
20
25
  6. Validate with the smallest useful dev, build, or typecheck command.
@@ -22,6 +27,8 @@ Use this skill when the host app is plain Vue 3, typically Vite-based, and not N
22
27
  ## Default Decisions
23
28
 
24
29
  - Vue 3 apps default to `content`.
30
+ - Smooth streaming (`smooth-streaming="auto"`) is on by default when `typewriter` or `max-live-nodes <= 0`. It only paces the `content` path; `nodes` mode is never affected.
31
+ - For manual pacing with `nodes`, use `useSmoothMarkdownStream` directly: `enqueue()` chunks, `finish()` when done, render from `visible`, and wait for `caughtUp` before final parsing.
25
32
  - Prefer local component registration unless the repo already uses a shared plugin entry.
26
33
  - When Monaco code blocks need app-level preloading, import `preloadCodeBlockRuntime` from `markstream-vue`. Existing `getUseMonaco()` preloads remain valid; do not import `stream-monaco` directly just to warm workers.
27
34
  - Keep `html-policy="safe"` and Mermaid strict mode unless the task is explicitly preserving trusted legacy behavior.
@@ -33,4 +40,5 @@ Use this skill when the host app is plain Vue 3, typically Vite-based, and not N
33
40
  - `docs/guide/quick-start.md`
34
41
  - `docs/guide/installation.md`
35
42
  - `docs/guide/usage.md`
43
+ - `docs/guide/ai-chat-streaming.md`
36
44
  - `docs/guide/component-overrides.md`
@@ -14,6 +14,11 @@ Use this skill when the host app is Vue 2 and not specifically a Vue CLI / Webpa
14
14
  - Add `@vue/composition-api` only when the repo is Vue 2.6 and uses Composition API patterns.
15
15
  3. Import `markstream-vue2/index.css` after resets.
16
16
  4. Start with `<MarkdownRender :content="markdown" />`.
17
+ - For AI chat or streaming UIs, keep `content` and use built-in smooth streaming first.
18
+ - `smooth-streaming="auto"` is the default and activates when `typewriter=true` or `max-live-nodes <= 0`.
19
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
20
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
21
+ - Move to `nodes` + `final` only for worker-preparsed content, shared AST stores, or custom AST control.
17
22
  - Remember that `html-policy` now defaults to `safe`, and Mermaid strict mode is on by default through `mermaid-props`.
18
23
  5. Use scoped custom component mappings when the task needs overrides or trusted tags.
19
24
  6. Validate with the smallest useful dev or build command.
@@ -16,6 +16,11 @@ Use this skill when the host app is Vue 2 on Vue CLI or another Webpack 4-style
16
16
  - Use `createKaTeXWorkerFromCDN(...)` and `createMermaidWorkerFromCDN(...)` when workers are needed.
17
17
  5. Prefer stable code block defaults over brittle Monaco wiring.
18
18
  - `MarkdownCodeBlockNode` plus `stream-markdown` is safer than Monaco in Webpack 4-era repos.
19
+ - For AI chat or streaming UIs, keep `content` and use built-in smooth streaming first.
20
+ - `smooth-streaming="auto"` is the default and activates when `typewriter=true` or `max-live-nodes <= 0`.
21
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
22
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
23
+ - Move to `nodes` + `final` only for worker-preparsed content, shared AST stores, or custom AST control.
19
24
  - Remember that `html-policy` now defaults to `safe`, and Mermaid strict mode is on by default through `mermaid-props`.
20
25
  6. Validate with the smallest useful local dev or build command.
21
26
 
@@ -15,6 +15,11 @@ Use this skill when the host app is Vue 2 and the bundler is Vite.
15
15
  4. Use Vite worker imports when the repo needs bundled workers.
16
16
  - `markstream-vue2/workers/... ?worker` or `?worker&inline` patterns are allowed here.
17
17
  5. Keep Composition API decisions explicit for Vue 2.6 repos.
18
+ - For AI chat or streaming UIs, keep `content` and use built-in smooth streaming first.
19
+ - `smooth-streaming="auto"` is the default and activates when `typewriter=true` or `max-live-nodes <= 0`.
20
+ - `typewriter` only controls the blinking cursor and defaults to `false`.
21
+ - `fade` controls node enter and streamed-text fade animations and defaults to `true`.
22
+ - Move to `nodes` + `final` only for worker-preparsed content, shared AST stores, or custom AST control.
18
23
  - Remember that `html-policy` now defaults to `safe`, and Mermaid strict mode is on by default through `mermaid-props`.
19
24
  6. Validate with the smallest useful Vite dev or build command.
20
25
 
package/README.md CHANGED
@@ -151,7 +151,7 @@ createApp({
151
151
  }).mount('#app')
152
152
  ```
153
153
 
154
- Import `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`, `stream-markdown`, `mermaid`, and `katex` only when you need Monaco code blocks, Shiki highlighting, diagrams, or math.
154
+ Import `markstream-vue/index.css` after your reset (e.g., use `@import 'markstream-vue/index.css' layer(components);` for Tailwind) 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.
155
155
  If your app intentionally scales root font size on mobile, use `markstream-vue/index.px.css` to avoid `rem`-based global scaling side effects.
156
156
 
157
157
  Renderer 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`.
@@ -258,36 +258,38 @@ Then use `<MarkdownRender :content="md" />` in your pages.
258
258
 
259
259
  ## ⏱️ Streaming in 30 seconds
260
260
 
261
- Render streamed Markdown (SSE/websocket) with incremental updates:
261
+ Render streamed Markdown (SSE/websocket) with built-in smooth pacing:
262
262
 
263
263
  ```ts
264
- import type { ParsedNode } from 'markstream-vue'
265
- import MarkdownRender, { getMarkdown, parseMarkdownToStructure } from 'markstream-vue'
264
+ import MarkdownRender from 'markstream-vue'
266
265
  import { ref } from 'vue'
267
266
 
268
- const nodes = ref<ParsedNode[]>([])
269
- const buffer = ref('')
270
- const md = getMarkdown()
267
+ const content = ref('')
268
+ const final = ref(false)
271
269
 
272
- function addChunk(chunk: string) {
273
- buffer.value += chunk
274
- nodes.value = parseMarkdownToStructure(buffer.value, md)
270
+ eventSource.onmessage = (event) => {
271
+ content.value += event.data
275
272
  }
276
-
277
- // e.g., inside your SSE/onmessage handler
278
- eventSource.onmessage = event => addChunk(event.data)
273
+ eventSource.addEventListener('done', () => {
274
+ final.value = true
275
+ })
279
276
 
280
277
  // template
281
278
  // <MarkdownRender
282
- // :nodes="nodes"
279
+ // :content="content"
280
+ // :final="final"
283
281
  // :max-live-nodes="0"
284
- // :batch-rendering="{
285
- // renderBatchSize: 16,
286
- // renderBatchDelay: 8,
287
- // }"
282
+ // :batch-rendering="true"
283
+ // :render-batch-size="16"
284
+ // :render-batch-delay="8"
285
+ // :render-batch-budget-ms="4"
286
+ // :fade="false"
287
+ // :typewriter="true"
288
288
  // />
289
289
  ```
290
290
 
291
+ `smooth-streaming` is enabled by default in typewriter/incremental mode (`typewriter` or `max-live-nodes <= 0`). Disable per surface with `:smooth-streaming="false"` if you want raw chunk cadence.
292
+
291
293
  Switch rendering style per surface:
292
294
 
293
295
  - Virtualized window (default): steady scrolling and memory usage for long docs.
@@ -332,7 +334,7 @@ const md = getMarkdown() // match server setup
332
334
 
333
335
  function addChunk(chunk: string) {
334
336
  buffer.value += chunk
335
- nodes.value = parseMarkdownToStructure(buffer.value, md)
337
+ nodes.value = parseMarkdownToStructure(buffer.value, md, { final: false })
336
338
  }
337
339
  ```
338
340
 
package/README.zh-CN.md CHANGED
@@ -152,7 +152,7 @@ createApp({
152
152
  }).mount('#app')
153
153
  ```
154
154
 
155
- 确保在 CSS reset(如 `@tailwind base` 或 `@unocss/reset`)之后导入 `markstream-vue/index.css`,最好放在 `@layer components` 中以避免 Tailwind/UnoCSS 覆盖组件样式。根据需求再按需安装可选 peer 依赖:`stream-monaco`(Monaco 代码块)、`shiki` + `stream-markdown`(Shiki 高亮)、`mermaid`(Mermaid 图表)、`katex`(数学公式)。
155
+ 确保在 CSS reset(如 `@tailwind base` 或 `@unocss/reset`)之后导入 `markstream-vue/index.css`,推荐使用 `@import 'markstream-vue/index.css' layer(components);` 以避免 Tailwind/UnoCSS 覆盖组件样式。根据需求再按需安装可选 peer 依赖:`stream-monaco`(Monaco 代码块)、`shiki` + `stream-markdown`(Shiki 高亮)、`mermaid`(Mermaid 图表)、`katex`(数学公式)。
156
156
  如果你的移动端会主动调大根字号(`html`/`body`),建议改用 `markstream-vue/index.px.css`,避免 `rem` 跟随根字号导致整体放大。
157
157
 
158
158
  渲染器的 CSS 会作用于内部 `.markstream-vue` 容器下,以尽量降低对全局的影响;如果你脱离 `MarkdownRender` 单独使用导出的节点组件,请在外层包一层带 `markstream-vue` 类名的容器。
@@ -259,36 +259,38 @@ export default defineNuxtPlugin((nuxtApp) => {
259
259
 
260
260
  ## ⏱️ 30 秒流式接入
261
261
 
262
- 用 SSE / WebSocket 增量渲染 Markdown:
262
+ 用 SSE / WebSocket 结合内置平滑节奏渲染 Markdown:
263
263
 
264
264
  ```ts
265
- import type { ParsedNode } from 'markstream-vue'
266
- import MarkdownRender, { getMarkdown, parseMarkdownToStructure } from 'markstream-vue'
265
+ import MarkdownRender from 'markstream-vue'
267
266
  import { ref } from 'vue'
268
267
 
269
- const nodes = ref<ParsedNode[]>([])
270
- const buffer = ref('')
271
- const md = getMarkdown()
268
+ const content = ref('')
269
+ const final = ref(false)
272
270
 
273
- function addChunk(chunk: string) {
274
- buffer.value += chunk
275
- nodes.value = parseMarkdownToStructure(buffer.value, md)
271
+ eventSource.onmessage = (event) => {
272
+ content.value += event.data
276
273
  }
277
-
278
- // 例如在 SSE / onmessage 处理器中
279
- eventSource.onmessage = event => addChunk(event.data)
274
+ eventSource.addEventListener('done', () => {
275
+ final.value = true
276
+ })
280
277
 
281
278
  // template
282
279
  // <MarkdownRender
283
- // :nodes="nodes"
280
+ // :content="content"
281
+ // :final="final"
284
282
  // :max-live-nodes="0"
285
- // :batch-rendering="{
286
- // renderBatchSize: 16,
287
- // renderBatchDelay: 8,
288
- // }"
283
+ // :batch-rendering="true"
284
+ // :render-batch-size="16"
285
+ // :render-batch-delay="8"
286
+ // :render-batch-budget-ms="4"
287
+ // :fade="false"
288
+ // :typewriter="true"
289
289
  // />
290
290
  ```
291
291
 
292
+ `smooth-streaming` 在打字机/增量模式(`typewriter` 或 `max-live-nodes <= 0`)默认开启;如果希望严格按原始 chunk 节奏显示,可按实例设置 `:smooth-streaming="false"`。
293
+
292
294
  按页面需要切换渲染风格:
293
295
 
294
296
  - 虚拟化窗口(默认):长文档滚动平稳、内存稳定。