markstream-react 0.0.50-beta.1 → 0.0.52

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.
Files changed (65) hide show
  1. package/README.md +134 -104
  2. package/dist/Tooltip-Ux2h3oiV.js +207 -0
  3. package/dist/{codeBlockExtraProps-B9FyDF6H.js → codeBlockExtraProps-NhTjbA1T.js} +1 -1
  4. package/dist/{index-Dkx6ncr8.js → index-DdaK6qko.js} +14 -14
  5. package/dist/index.css +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.px.css +1 -1
  8. package/dist/index.tailwind.css +1 -1
  9. package/dist/markstream-react.css +1 -1
  10. package/dist/next.d.ts +6 -3
  11. package/dist/next.js +1 -1
  12. package/dist/server.d.ts +46 -43
  13. package/dist/server.js +1 -1
  14. package/dist/tailwind.cjs +4 -0
  15. package/dist/tailwind.d.ts +2 -0
  16. package/dist/tailwind.js +2 -0
  17. package/dist/types/components/AdmonitionNode/AdmonitionNode.d.ts +2 -1
  18. package/dist/types/components/BlockquoteNode/BlockquoteNode.d.ts +2 -1
  19. package/dist/types/components/CheckboxNode/CheckboxNode.d.ts +2 -1
  20. package/dist/types/components/CodeBlockNode/CodeBlockNode.d.ts +2 -1
  21. package/dist/types/components/CodeBlockNode/PreCodeNode.d.ts +2 -1
  22. package/dist/types/components/D2BlockNode/D2BlockNode.d.ts +2 -1
  23. package/dist/types/components/DefinitionListNode/DefinitionListNode.d.ts +2 -1
  24. package/dist/types/components/EmojiNode/EmojiNode.d.ts +2 -1
  25. package/dist/types/components/EmphasisNode/EmphasisNode.d.ts +2 -1
  26. package/dist/types/components/FootnoteAnchorNode/FootnoteAnchorNode.d.ts +2 -1
  27. package/dist/types/components/FootnoteNode/FootnoteNode.d.ts +2 -1
  28. package/dist/types/components/FootnoteReferenceNode/FootnoteReferenceNode.d.ts +2 -1
  29. package/dist/types/components/HardBreakNode/HardBreakNode.d.ts +2 -1
  30. package/dist/types/components/HeadingNode/HeadingNode.d.ts +2 -1
  31. package/dist/types/components/HighlightNode/HighlightNode.d.ts +2 -1
  32. package/dist/types/components/HtmlBlockNode/HtmlBlockNode.d.ts +1 -1
  33. package/dist/types/components/HtmlInlineNode/HtmlInlineNode.d.ts +2 -1
  34. package/dist/types/components/ImageNode/ImageNode.d.ts +1 -1
  35. package/dist/types/components/InfographicBlockNode/InfographicBlockNode.d.ts +2 -1
  36. package/dist/types/components/InlineCodeNode/InlineCodeNode.d.ts +2 -1
  37. package/dist/types/components/InsertNode/InsertNode.d.ts +2 -1
  38. package/dist/types/components/LinkNode/LinkNode.d.ts +2 -1
  39. package/dist/types/components/ListItemNode/ListItemNode.d.ts +2 -1
  40. package/dist/types/components/ListNode/ListNode.d.ts +2 -1
  41. package/dist/types/components/MarkdownCodeBlockNode/MarkdownCodeBlockNode.d.ts +2 -1
  42. package/dist/types/components/Math/MathBlockNode.d.ts +1 -1
  43. package/dist/types/components/Math/MathInlineNode.d.ts +1 -1
  44. package/dist/types/components/MermaidBlockNode/MermaidBlockNode.d.ts +2 -1
  45. package/dist/types/components/NodeRenderer/FallbackComponent.d.ts +2 -1
  46. package/dist/types/components/ParagraphNode/ParagraphNode.d.ts +2 -1
  47. package/dist/types/components/ReferenceNode/ReferenceNode.d.ts +1 -1
  48. package/dist/types/components/StrikethroughNode/StrikethroughNode.d.ts +2 -1
  49. package/dist/types/components/StrongNode/StrongNode.d.ts +2 -1
  50. package/dist/types/components/SubscriptNode/SubscriptNode.d.ts +2 -1
  51. package/dist/types/components/SuperscriptNode/SuperscriptNode.d.ts +2 -1
  52. package/dist/types/components/TableNode/TableNode.d.ts +2 -1
  53. package/dist/types/components/TextNode/TextNode.d.ts +2 -1
  54. package/dist/types/components/ThematicBreakNode/ThematicBreakNode.d.ts +2 -1
  55. package/dist/types/components/VmrContainerNode/VmrContainerNode.d.ts +2 -1
  56. package/dist/types/context/viewportPriority.d.ts +1 -1
  57. package/dist/types/renderers/codeBlockExtraProps.d.ts +4 -1
  58. package/dist/types/renderers/renderChildren.d.ts +1 -1
  59. package/dist/types/renderers/renderNode.d.ts +1 -1
  60. package/dist/types/server-renderer/index.d.ts +41 -41
  61. package/dist/types/styles.d.ts +1 -0
  62. package/dist/types/types/component-props.d.ts +5 -0
  63. package/package.json +39 -40
  64. package/dist/Tooltip-CGyQXyg8.js +0 -204
  65. package/dist/tailwind.ts +0 -3
package/README.md CHANGED
@@ -1,166 +1,196 @@
1
1
  # markstream-react
2
2
 
3
- React renderer that consumes the structured AST output from `stream-markdown-parser` and renders it with lightweight semantic HTML components. This is the React counter-part to the Vue renderer that powers `markstream-vue`.
3
+ React/Next.js streaming Markdown renderer for AI chat, SSE/WebSocket output, long AI responses, Mermaid, KaTeX, and code blocks.
4
4
 
5
- ## Development
5
+ `markstream-react` is the React renderer in the Markstream family. It renders raw Markdown strings with `content`, and it can also accept pre-parsed `nodes` when a worker or store already owns parsing.
6
+
7
+ ## Install
6
8
 
7
9
  ```bash
8
- pnpm --filter markstream-react dev
10
+ pnpm add markstream-react
9
11
  ```
10
12
 
11
- ## Build
13
+ Optional features are peer dependencies. Install only what your Markdown output needs.
12
14
 
13
- ```bash
14
- pnpm --filter markstream-react build
15
- pnpm --filter markstream-react build:analyze
16
- pnpm --filter markstream-react size:check
17
- ```
15
+ ## Quick Start
18
16
 
19
- ## Usage
17
+ Import one Markstream CSS file explicitly. The JavaScript entry does not inject styles automatically.
20
18
 
21
19
  ```tsx
22
- import NodeRenderer from 'markstream-react'
20
+ import MarkdownRender from 'markstream-react'
23
21
  import 'markstream-react/index.css'
24
22
 
25
- export default function Article({ markdown }: { markdown: string }) {
26
- return (
27
- <NodeRenderer content={markdown} />
28
- )
23
+ export default function ChatMessage({
24
+ content,
25
+ isDone,
26
+ }: {
27
+ content: string
28
+ isDone: boolean
29
+ }) {
30
+ return <MarkdownRender content={content} final={isDone} fade={false} />
29
31
  }
30
32
  ```
31
33
 
32
- If your app scales root font size on mobile (`html` / `body`), use `markstream-react/index.px.css` to prevent `rem`-based global scaling side effects.
34
+ Use `markstream-react/index.px.css` instead when your app scales the root font size on mobile and you want renderer sizing to stay pixel-based.
35
+
36
+ ## Streaming Example
37
+
38
+ For most SSE/WebSocket chat surfaces, accumulate the Markdown string and pass `content` plus `final`:
39
+
40
+ ```tsx
41
+ import MarkdownRender from 'markstream-react'
42
+ import { useEffect, useState } from 'react'
43
+ import 'markstream-react/index.css'
44
+
45
+ export function ChatView() {
46
+ const [content, setContent] = useState('')
47
+ const [isDone, setIsDone] = useState(false)
48
+
49
+ useEffect(() => {
50
+ const eventSource = new EventSource('/api/chat/stream')
51
+ eventSource.onmessage = (event) => {
52
+ if (event.data === '[DONE]') {
53
+ setIsDone(true)
54
+ eventSource.close()
55
+ return
56
+ }
33
57
 
34
- You can also pass a pre-parsed `nodes` array if you already have AST data.
58
+ const data = JSON.parse(event.data) as { content?: string }
59
+ setContent(prev => prev + (data.content ?? ''))
60
+ }
35
61
 
36
- ## Streaming best practices
62
+ return () => eventSource.close()
63
+ }, [])
64
+
65
+ return <MarkdownRender content={content} final={isDone} fade={false} />
66
+ }
67
+ ```
37
68
 
38
- - For high-frequency SSE / token streaming, prefer parsing outside the component and pass `nodes` instead of reparsing the full `content` string every chunk.
39
- - Keep `viewportPriority` enabled unless you explicitly want eager rendering. Mermaid / Monaco / D2 blocks now stay idle while offscreen and resume when they approach the viewport.
69
+ If parsing is already external, pass `nodes`. Use a per-message parser id so generated code-block DOM ids stay unique across chat lists.
40
70
 
41
71
  ```tsx
42
- import NodeRenderer from 'markstream-react'
43
-
44
- export default function StreamView({ nodes, final }: { nodes: any[], final: boolean }) {
45
- return (
46
- <NodeRenderer
47
- nodes={nodes}
48
- final={final}
49
- viewportPriority
50
- deferNodesUntilVisible
51
- />
72
+ import MarkdownRender from 'markstream-react'
73
+ import { useMemo } from 'react'
74
+ import { getMarkdown, parseMarkdownToStructure } from 'stream-markdown-parser'
75
+
76
+ export function ParsedChatMessage({
77
+ messageId,
78
+ content,
79
+ isDone,
80
+ }: {
81
+ messageId: string
82
+ content: string
83
+ isDone: boolean
84
+ }) {
85
+ const md = useMemo(() => getMarkdown(`chat-${messageId}`), [messageId])
86
+ const nodes = useMemo(
87
+ () => parseMarkdownToStructure(content, md, { final: isDone }),
88
+ [content, isDone, md],
52
89
  )
90
+
91
+ return <MarkdownRender nodes={nodes} final={isDone} fade={false} />
53
92
  }
54
93
  ```
55
94
 
56
- ## Heavy-node prop forwarding
95
+ ## Next.js SSR
57
96
 
58
- `NodeRenderer` can forward renderer-level props directly into Mermaid / D2 / Infographic blocks:
97
+ Import styles once from your app shell:
59
98
 
60
99
  ```tsx
61
- <NodeRenderer
62
- content={markdown}
63
- mermaidProps={{
64
- showHeader: false,
65
- renderDebounceMs: 180,
66
- previewPollDelayMs: 500,
67
- }}
68
- d2Props={{ progressiveIntervalMs: 500 }}
69
- infographicProps={{ showHeader: false }}
70
- />
100
+ // app/layout.tsx or pages/_app.tsx
101
+ import 'markstream-react/index.css'
71
102
  ```
72
103
 
73
- Notes:
74
- - These props are forwarded to the built-in Mermaid / D2 / Infographic blocks and to custom `mermaid` / `d2` / `infographic` overrides registered with `setCustomComponents(...)`.
75
- - `viewportPriority` applies to those heavy nodes too, so offscreen graphs will not keep doing background work while the text stream is still updating.
104
+ Use the root package in client components for live SSE/WebSocket streams:
105
+
106
+ ```tsx
107
+ 'use client'
108
+
109
+ import MarkdownRender from 'markstream-react'
76
110
 
77
- ## Language-specific code block overrides
111
+ export function LiveMessage({ content, isDone }: { content: string, isDone: boolean }) {
112
+ return <MarkdownRender content={content} final={isDone} fade={false} />
113
+ }
114
+ ```
78
115
 
79
- You can register a custom component under a fenced language key without wrapping the generic `code_block` renderer:
116
+ Use `markstream-react/next` for SSR-first Markdown with client enhancement, or `markstream-react/server` for server-only rendering:
80
117
 
81
118
  ```tsx
82
- import type { NodeComponentProps } from 'markstream-react'
83
- import { setCustomComponents } from 'markstream-react'
119
+ import MarkdownRender from 'markstream-react/next'
84
120
 
85
- function EChartsBlockNode(props: NodeComponentProps<any>) {
86
- return <div data-language={String(props.node?.language)}>{String(props.node?.code || '')}</div>
121
+ export default function Page() {
122
+ return <MarkdownRender content="# Server HTML first" final />
87
123
  }
88
-
89
- setCustomComponents('docs', {
90
- echarts: EChartsBlockNode,
91
- })
92
124
  ```
93
125
 
94
- Notes:
95
- - `echarts` only catches fences whose language is `echarts`.
96
- - Code block routing priority is exact language key -> built-in `mermaid` / `d2` / `infographic` routes -> `code_block`.
97
- - Custom `mermaid` / `d2` / `infographic` overrides keep their specialized top-level props; other custom language keys use the normal custom component contract (`node`, `ctx`, `renderNode`, and friends).
126
+ ## Optional Peers
98
127
 
99
- ## Mermaid tuning
128
+ | Feature | Package |
129
+ | --- | --- |
130
+ | Shiki code blocks | `stream-markdown` |
131
+ | Monaco editor code blocks | `stream-monaco` |
132
+ | Mermaid diagrams | `mermaid` |
133
+ | KaTeX math | `katex` |
134
+ | D2 diagrams | `@terrastruct/d2` |
135
+ | Infographic blocks | `@antv/infographic` |
100
136
 
101
- Common `mermaidProps` keys for streaming scenarios:
137
+ KaTeX still needs its CSS in your app when math rendering is enabled:
102
138
 
103
- - `renderDebounceMs`: delay progressive work during rapid token bursts.
104
- - `contentStableDelayMs`: how long source mode waits before auto-switching back to preview when content stabilizes.
105
- - `previewPollDelayMs`: initial delay before preview polling tries to upgrade a partial preview into a full render.
106
- - `previewPollMaxDelayMs`: cap for preview polling backoff.
107
- - `previewPollMaxAttempts`: maximum retry count while the Mermaid source is still incomplete.
139
+ ```tsx
140
+ import 'katex/dist/katex.min.css'
141
+ ```
108
142
 
109
- ## Bundle size notes
143
+ ## Tailwind
110
144
 
111
- - Optional peers are not bundled; install only what you use (`stream-monaco`, `stream-markdown`, `mermaid`, `katex`, etc.).
112
- - Infrequent language icons are split into an async chunk and loaded on demand.
113
- - To avoid first-hit fallback icons, preload once when the app is idle:
145
+ Non-Tailwind projects should import the precompiled CSS:
114
146
 
115
147
  ```tsx
116
- import { preloadExtendedLanguageIcons } from 'markstream-react'
117
-
118
- if (typeof window !== 'undefined')
119
- void preloadExtendedLanguageIcons()
148
+ import 'markstream-react/index.css'
120
149
  ```
121
150
 
122
- ## Tailwind
151
+ Tailwind projects can import the Tailwind-ready CSS and include the extracted class list in `tailwind.config.js`:
152
+
153
+ ```tsx
154
+ import 'markstream-react/index.tailwind.css'
155
+ ```
123
156
 
124
- - Non-Tailwind projects: keep importing `markstream-react/index.css` (includes precompiled utilities for the renderer).
125
- - Tailwind projects (avoid duplicate utilities): import `markstream-react/index.tailwind.css` and add `require('markstream-react/tailwind')` to your `tailwind.config.js` `content`.
157
+ ```js
158
+ module.exports = {
159
+ content: [
160
+ './src/**/*.{js,ts,jsx,tsx}',
161
+ require('markstream-react/tailwind'),
162
+ ],
163
+ }
164
+ ```
126
165
 
127
- ## Custom components (e.g. `<thinking>`)
166
+ ## Custom Components
128
167
 
129
- Custom tag-like blocks are exposed as nodes with `type: 'thinking'` (the tag name, no angle brackets) when you register the tag in `customHtmlTags` or register a custom component mapping for it.
168
+ Register custom renderers with `setCustomComponents`. Custom tag-like blocks are exposed as nodes with `type` equal to the tag name when the parser is configured for that tag.
130
169
 
131
170
  ```tsx
132
171
  import type { NodeComponentProps } from 'markstream-react'
133
- import NodeRenderer, { setCustomComponents } from 'markstream-react'
172
+ import MarkdownRender, { setCustomComponents } from 'markstream-react'
134
173
 
135
174
  function ThinkingNode(props: NodeComponentProps<{ type: 'thinking', content: string }>) {
136
- const { node, ctx } = props
137
- return (
138
- <div className="thinking-node">
139
- <div className="thinking-title">Thinking</div>
140
- <NodeRenderer
141
- content={node.content}
142
- customId={ctx?.customId}
143
- isDark={ctx?.isDark}
144
- typewriter={false}
145
- batchRendering={false}
146
- deferNodesUntilVisible={false}
147
- viewportPriority={false}
148
- maxLiveNodes={0}
149
- />
150
- </div>
151
- )
175
+ return <MarkdownRender content={props.node.content} fade={false} />
152
176
  }
153
177
 
154
178
  setCustomComponents('chat', { thinking: ThinkingNode })
155
179
  ```
156
180
 
157
- ## Type exports
181
+ ## When Not to Use It
182
+
183
+ Use `react-markdown`, `marked`, or `markdown-it` when you only render short static Markdown, need the smallest possible Markdown stack, or already have a complete remark/rehype pipeline and do not need streaming mid-state handling.
184
+
185
+ ## Type Exports
186
+
187
+ The package root exports the public component and renderer types, including `NodeRendererProps`, `NodeComponentProps`, `RenderContext`, `RenderNodeFn`, `CustomComponentMap`, and code-block option types.
158
188
 
159
- `markstream-react` now exposes the core public types directly from the package root, including:
189
+ ## Development
160
190
 
161
- - `NodeRendererProps`
162
- - `NodeComponentProps`
163
- - `RenderContext`
164
- - `RenderNodeFn`
165
- - `CustomComponentMap`
166
- - `CodeBlockMonacoOptions`
191
+ ```bash
192
+ pnpm --filter markstream-react dev
193
+ pnpm --filter markstream-react build
194
+ pnpm --filter markstream-react check:exports
195
+ pnpm --filter markstream-react size:check
196
+ ```