markstream-vue2 0.0.19-beta.9 → 0.0.20

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.
package/README.md CHANGED
@@ -139,6 +139,55 @@ new Vue({
139
139
  }).$mount('#app')
140
140
  ```
141
141
 
142
+ ## Streaming best practices
143
+
144
+ - For high-frequency SSE / token streaming, prefer parsing outside the renderer and pass `nodes` instead of reparsing the whole `content` string every chunk.
145
+ - Keep `viewport-priority` enabled unless you explicitly want eager rendering. Mermaid / Monaco / D2 blocks now stay idle while offscreen and resume when they approach the viewport.
146
+
147
+ ```vue
148
+ <template>
149
+ <MarkdownRender
150
+ :nodes="nodes"
151
+ :final="final"
152
+ :viewport-priority="true"
153
+ :defer-nodes-until-visible="true"
154
+ />
155
+ </template>
156
+ ```
157
+
158
+ ## Heavy-node prop forwarding
159
+
160
+ `MarkdownRender` can forward framework-level props directly into specialized heavy renderers:
161
+
162
+ ```vue
163
+ <template>
164
+ <MarkdownRender
165
+ :content="markdown"
166
+ :mermaid-props="{
167
+ showHeader: false,
168
+ renderDebounceMs: 180,
169
+ previewPollDelayMs: 500
170
+ }"
171
+ :d2-props="{ progressiveIntervalMs: 500 }"
172
+ :infographic-props="{ showHeader: false }"
173
+ />
174
+ </template>
175
+ ```
176
+
177
+ Notes:
178
+ - Use kebab-case in templates: `mermaid-props`, `d2-props`, `infographic-props`.
179
+ - These props are forwarded to the built-in Mermaid / D2 / Infographic blocks and to custom `mermaid` / `d2` / `infographic` overrides registered with `setCustomComponents(...)`.
180
+
181
+ ## Mermaid tuning
182
+
183
+ Common `mermaid-props` keys for streaming scenarios:
184
+
185
+ - `renderDebounceMs`: delay partial/full progressive work during rapid token bursts.
186
+ - `contentStableDelayMs`: how long source mode waits before auto-switching back to preview when content stabilizes.
187
+ - `previewPollDelayMs`: initial delay before preview polling tries to upgrade a partial preview into a full render.
188
+ - `previewPollMaxDelayMs`: cap for preview polling backoff.
189
+ - `previewPollMaxAttempts`: maximum retry count while the Mermaid source is still incomplete.
190
+
142
191
  ## Build and size checks
143
192
 
144
193
  ```bash
@@ -174,6 +223,64 @@ Fix: align both to the same version (e.g. `2.6.14` or `2.7.16`).
174
223
  Cause: Vue 2.6 + Composition API missing `_setupProxy` patch, or plugin not installed.
175
224
  Fix: ensure `@vue/composition-api` is installed + `Vue.use(...)`, and update to the latest markstream-vue2 build.
176
225
 
226
+ ### Custom node renders trigger `infinite update loop`
227
+ Cause: in Vue 2.6 / Vue CLI 4, recursively mounting another `MarkdownRender` inside a custom node component can create a render loop when the parent renderer is still streaming.
228
+ Fix: prefer `NestedRenderer` for nested streaming content. If you only need static HTML output, `renderNestedMarkdownToHtml(...)` is still available.
229
+
230
+ ```ts
231
+ import { NestedRenderer } from 'markstream-vue2'
232
+
233
+ export default {
234
+ components: { NestedRenderer },
235
+ props: {
236
+ node: { type: Object, required: true },
237
+ },
238
+ }
239
+ ```
240
+
241
+ ```vue
242
+ <template>
243
+ <NestedRenderer
244
+ :node="node"
245
+ custom-id="chat-demo"
246
+ :custom-html-tags="['thinking']"
247
+ :typewriter="false"
248
+ :batch-rendering="false"
249
+ :viewport-priority="false"
250
+ :defer-nodes-until-visible="false"
251
+ />
252
+ </template>
253
+ ```
254
+
255
+ `NestedRenderer` keeps the inner content streamable, but switches the nested renderer to the `nodes` path so Vue 2.6 does not recurse through a second `content`-driven renderer.
256
+
257
+ If you cannot mount another renderer and just need a static nested body, use `renderNestedMarkdownToHtml(...)`:
258
+
259
+ ```ts
260
+ import { renderNestedMarkdownToHtml } from 'markstream-vue2'
261
+
262
+ export default {
263
+ props: {
264
+ node: { type: Object, required: true },
265
+ },
266
+ computed: {
267
+ renderedHtml() {
268
+ return renderNestedMarkdownToHtml(
269
+ { node: this.node },
270
+ {
271
+ customHtmlTags: ['thinking'],
272
+ customNodeClass(node) {
273
+ return node.type === 'thinking' ? 'thinking-node__nested' : ''
274
+ },
275
+ },
276
+ )
277
+ },
278
+ },
279
+ }
280
+ ```
281
+
282
+ This keeps deeply nested custom content streamable without recursively mounting a second `content`-driven `MarkdownRender` / `NodeRenderer`.
283
+
177
284
  ## Tailwind
178
285
 
179
286
  If your app uses Tailwind and you want to avoid shipping duplicated utility CSS, import the Tailwind-ready output instead: