remons-render-markdown 1.0.28-beta.9 → 1.0.28

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
@@ -1,422 +1,422 @@
1
- # render-markdown
2
-
3
- 一个基于 React 的 Markdown 渲染组件,支持 GFM(GitHub Flavored Markdown)Tabs 标签、代码高亮、Mermaid 图表等功能。
4
-
5
- 渲染效果
6
- ![整体渲染效果](https://remons.cn:3008/upload/md_assets/%E6%95%B4%E4%BD%93%E6%B8%B2%E6%9F%93%E6%95%88%E6%9E%9C.png)
7
-
8
- ## 技术方案
9
-
10
- ### 技术栈
11
-
12
- | 类别 | 技术选型 | 说明 |
13
- |------|---------|------|
14
- | 框架 | React 18 | 组件库基础框架 |
15
- | 构建工具 | Vite | 基于 Rollup 的极速构建器 |
16
- | 语言 | TypeScript | 提供类型定义 |
17
- | 样式方案 | CSS Modules / 内联样式 | 轻量无外部依赖 |
18
- | 代码规范 | ESLint + Prettier | 统一代码风格 |
19
- | 发布工具 | changesets | 语义化版本管理与 changelog 生成 |
20
-
21
- ### 核心功能
22
-
23
- - **GFM 支持**: 完整的 GitHub Flavored Markdown 渲染
24
- - **增量渲染**: 基于 morphdom 的 DOM 差异化更新,适用于流式输出场景
25
- - **代码高亮**: 基于 highlight.js 的代码语法高亮
26
- - **Mermaid 图表**: 支持 Mermaid 语法渲染流程图、时序图等
27
- - **Tab 标签页**: 支持 Tab 标签页语法
28
- - **Alert 提示框**: 支持警告、提示等信息框
29
- - **目录锚点**: 自动生成文档目录和锚点链接(自行实现目录渲染)
30
- - **代码复制**: 一键复制代码块
31
- - **代码折叠**: 支持代码块折叠展开
32
- - **深色模式**: 自动适配深色/浅色主题
33
-
34
- ## API
35
-
36
- ### 安装
37
-
38
- ```bash
39
- npm install remons-render-markdown
40
- ```
41
-
42
- ### 导出内容
43
-
44
- ```typescript
45
- import RenderMarkdown, { markdownFormat, languagesCommon, initHighlighter, useIncrementalRender } from 'remons-render-markdown';
46
- ```
47
-
48
- #### 默认导出
49
-
50
- - **RenderMarkdown**: React 组件,用于渲染 Markdown 内容
51
-
52
- #### 命名导出
53
-
54
- - **markdownFormat**: Markdown 解析函数,返回 `{ anchor: AnchorItem[], info: string }`
55
- - **languagesCommon**: 默认支持的语言包配置(javascript, typescript, css, json, bash, xml, plaintext)
56
- - **initHighlighter**: 初始化高亮语言包的函数
57
- - **useIncrementalRender**: 增量渲染 hook,使用 morphdom 进行 DOM 差异化更新,适用于流式输出场景
58
- - **renderMermaid**: 独立的 Mermaid 图表渲染组件
59
-
60
- ### RenderMarkdown 组件 Props
61
-
62
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
63
- |------|------|------|--------|------|
64
- | content | string | ✅ | - | Markdown 内容 |
65
- | createTime | string | ❌ | - | 创建时间,用于显示文档更新时间 |
66
- | isSlotMermaid | boolean | ❌ | true | 是否使用 Mermaid 插件渲染图表 |
67
- | isShowCollapsed | boolean | ❌ | true | 是否显示代码折叠按钮 |
68
- | codeType | string | ❌ | - | 指定代码类型(如 'javascript' 等),不传则按 Markdown 渲染 |
69
- | editButton | React.ReactNode | ❌ | - | 自定义编辑按钮 |
70
- | backTopTarget | HTMLElement | ❌ | body | 返回顶部按钮监听的容器 |
71
- | showDriverGuide | boolean | ❌ | false | 是否显示新手引导 |
72
- | showToc | boolean | ❌ | false | 是否显示目录(TOC)按钮和侧边栏 |
73
-
74
- ### markdownFormat 函数
75
-
76
- 解析 Markdown 内容并返回结构化数据。
77
-
78
- **参数:**
79
-
80
- - `content: string` - Markdown 文本内容
81
-
82
- **返回值:**
83
-
84
- ```typescript
85
- {
86
- anchor: Array<{
87
- title: string; // 标题文本
88
- href: string; // 锚点链接
89
- nodeName: string; // 节点名称,如 "H1", "H2"
90
- nodeTitle: string; // 完整节点 HTML
91
- children: Array<...>; // 子标题
92
- }>;
93
- info: string; // 渲染后的 HTML 字符串
94
- }
95
- ```
96
-
97
- ### initHighlighter 函数
98
-
99
- 注册自定义的代码高亮语言。
100
-
101
- **参数:**
102
-
103
- - `languages: Record<string, any>` - 语言包对象,格式为 `{ languageName: languageModule }`
104
-
105
- **示例:**
106
-
107
- ```typescript
108
- import javascript from 'highlight.js/lib/languages/javascript';
109
- import python from 'highlight.js/lib/languages/python';
110
-
111
- initHighlighter({
112
- javascript,
113
- python,
114
- });
115
- ```
116
-
117
- ## 使用方式
118
-
119
- ### 基础用法
120
-
121
- ```tsx
122
- import RenderMarkdown from 'remons-render-markdown';
123
- import 'render-markdown/dist/index.css';
124
-
125
- function App() {
126
- const markdownContent = `
127
- # Hello World
128
-
129
- This is a **Markdown** renderer.
130
-
131
- \`\`\`javascript
132
- console.log('Hello');
133
- \`\`\`
134
- `;
135
-
136
- return <RenderMarkdown content={markdownContent} />;
137
- }
138
- ```
139
-
140
- ### 完整示例
141
-
142
- ```tsx
143
- import RenderMarkdown from 'remons-render-markdown';
144
- import 'render-markdown/dist/index.css';
145
-
146
- function ArticlePage() {
147
- const content = `
148
- # 文章标题
149
-
150
- 这是一篇示例文章。
151
-
152
- ## 代码示例
153
-
154
- \`\`\`javascript
155
- const greeting = 'Hello World';
156
- console.log(greeting);
157
- \`\`\`
158
-
159
- ## Mermaid 图表
160
-
161
- \`\`\`mermaid
162
- graph TD
163
- A[开始] --> B[处理]
164
- B --> C[结束]
165
- \`\`\`
166
- `;
167
-
168
- return (
169
- <RenderMarkdown
170
- content={content}
171
- createTime="2026-07-23T12:00:00Z"
172
- isSlotMermaid={true}
173
- isShowCollapsed={true}
174
- editButton={<button>编辑</button>}
175
- />
176
- );
177
- }
178
- ```
179
-
180
- ### 使用 markdownFormat 获取目录结构
181
-
182
- ```tsx
183
- import { markdownFormat } from 'remons-render-markdown';
184
-
185
- async function TableOfContents() {
186
- const content = '# 标题1\n## 标题1.1\n## 标题1.2\n# 标题2';
187
- const { anchor, info } = await markdownFormat(content);
188
-
189
- console.log(anchor);
190
- // [
191
- // { title: '标题1', href: '标题1', nodeName: 'H1', children: [...] },
192
- // { title: '标题2', href: '标题2', nodeName: 'H1', children: [] }
193
- // ]
194
-
195
- return <div dangerouslySetInnerHTML={{ __html: info }} />;
196
- }
197
- ```
198
-
199
- ### 自定义代码高亮语言
200
-
201
- ```tsx
202
- import RenderMarkdown, { initHighlighter, languagesCommon } from 'remons-render-markdown';
203
- import 'render-markdown/dist/index.css';
204
- import python from 'highlight.js/lib/languages/python';
205
- import go from 'highlight.js/lib/languages/go';
206
-
207
- // 注册额外的语言
208
- initHighlighter({
209
- ...languagesCommon, // 包含默认语言
210
- python,
211
- go,
212
- });
213
-
214
- function App() {
215
- return (
216
- <RenderMarkdown
217
- content={`
218
- \`\`\`python
219
- def hello():
220
- print('Hello')
221
- \`\`\`
222
-
223
- \`\`\`go
224
- package main
225
- import "fmt"
226
- func main() {
227
- fmt.Println("Hello")
228
- }
229
- \`\`\`
230
- `}
231
- />
232
- );
233
- }
234
- ```
235
-
236
- ### 仅渲染特定代码类型
237
-
238
- ```tsx
239
- import RenderMarkdown from 'remons-render-markdown';
240
- import 'render-markdown/dist/index.css';
241
-
242
- function CodeViewer() {
243
- const code = `
244
- const x = 1;
245
- const y = 2;
246
- console.log(x + y);
247
- `;
248
-
249
- return (
250
- <RenderMarkdown
251
- content={code}
252
- codeType="javascript"
253
- isSlotMermaid={false}
254
- />
255
- );
256
- }
257
- ```
258
-
259
- ### 使用 useIncrementalRender 实现增量渲染
260
-
261
- `useIncrementalRender` 适用于流式输出场景(如 AI 对话),通过 morphdom 实现高效的 DOM 差异化更新。
262
-
263
- ```tsx
264
- import { useIncrementalRender } from 'remons-render-markdown';
265
-
266
- function StreamingContent({ content }) {
267
- const { anchors, hasContent, setInnerRef } = useIncrementalRender({
268
- content,
269
- // 可选:节流时间,默认 16ms
270
- throttleMs: 16,
271
- });
272
-
273
- return (
274
- <div>
275
- {hasContent && <div ref={setInnerRef} />}
276
- {anchors.length > 0 && (
277
- <ul>
278
- {anchors.map((item) => (
279
- <li key={item.href}>
280
- <a href={`#${item.href}`}>{item.title}</a>
281
- </li>
282
- ))}
283
- </ul>
284
- )}
285
- </div>
286
- );
287
- }
288
- ```
289
-
290
- **参数:**
291
-
292
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
293
- |------|------|------|--------|------|
294
- | content | string | ✅ | - | Markdown 内容 |
295
- | codeType | string | ❌ | - | 代码类型,不传则按 Markdown 渲染 |
296
- | customRenderers | MarkdownPlugin[] | ❌ | - | 自定义 markdown-it 插件 |
297
- | throttleMs | number | ❌ | 16 | 节流时间(ms) |
298
- | onNodeDiscarded | (el: HTMLElement) => void | ❌ | - | 节点被 diff 移除后触发(含被移除子树的子节点),用于清理 React Root 等挂载状态 |
299
-
300
- **返回值:**
301
-
302
- | 属性 | 类型 | 说明 |
303
- |------|------|------|
304
- | anchors | AnchorItem[] | 文档锚点列表 |
305
- | hasContent | boolean | 是否有内容 |
306
- | setInnerRef | (node: HTMLDivElement) => void | 内容容器的 ref 回调 |
307
-
308
- **增量渲染与自定义插件(customRenderers)的配合约定:**
309
-
310
- 1. 插件产出的容器节点(如 `:::badge` / `:::linkCard` / `<plugin-container>`)按"标签 + className"语义匹配,内容位移时不同类型的块不会被错配到旧节点上。
311
- 2. 元素上 JS 后加的 `data-*` 属性(如初始化守卫位 `data-xxx-inited`)在 diff 后会被保留,"只初始化一次"的守卫逻辑不会在增量渲染中被重复触发。
312
- 3. JS 动态插入的额外子节点(如 React 挂载点、收起按钮)默认会被 diff 移除;若需跨增量渲染保留,请给节点设置 `data-md-persist` 属性(见导出常量 `MD_PERSIST_ATTR`)。
313
- 4. 被 diff 移除的节点会触发 `onNodeDiscarded`,请在此卸载挂载在其上的 React Root,避免内存泄漏。
314
-
315
- ### 关于语法
316
-
317
- #### mermaid 图表
318
-
319
- ```code
320
- ---
321
- title: 图表标题
322
- ---
323
- ......... 图表内容
324
- ```
325
-
326
- - 折叠图
327
- ![mermaid 渲染图](https://remons.cn:3008/upload/md_assets/mermaid%20%E7%BC%A9%E7%95%A5%E5%9B%BE.png)
328
-
329
- - 缩略图
330
- ![mermaid 渲染图](https://remons.cn:3008/upload/md_assets/mermaid%20%E5%B1%95%E5%BC%80%E5%9B%BE.png)
331
- #### Tabs 标签页
332
-
333
- 依赖于 `@mdit/plugin-tab` 插件,参考 [mdit-plugin-tab](https://mdit-plugins.github.io/zh/tab.html) 的文档。
334
- *暂不支持 tabs 嵌套*
335
-
336
- 语法示例:
337
-
338
- ```markdown
339
- :::markdown-tabs
340
-
341
- @tab:active tab1
342
- ```javascript
343
- console.log('Hello');
344
- ```
345
-
346
- @tab tab2
347
- ```typescript
348
- console.log('World');
349
- ```
350
- :::
351
- ```
352
- ![tabs 渲染图](https://remons.cn:3008/upload/md_assets/tabs.png)
353
-
354
- #### Alert 提示框
355
-
356
- 语法示例:
357
-
358
- ```markdown
359
- > [!warning]
360
- > 我是一个警告信息
361
- ```
362
-
363
- ![alert 渲染图](https://remons.cn:3008/upload/md_assets/alert.png)
364
-
365
- #### renderMermaid 方法
366
-
367
- 支持渲染独立的 Mermaid 图表渲染组件,支持缩放、全屏、下载、源码查看等功能。
368
-
369
- ```tsx
370
- import { renderMermaid } from 'remons-render-markdown';
371
- import 'remons-render-markdown/dist/index.css';
372
-
373
- function MermaidComponent() {
374
- const mermaidCode = `
375
- ---
376
- title: 流程图示例
377
- ---
378
- graph TD
379
- A[开始] --> B[处理]
380
- B --> C[结束]
381
- `;
382
-
383
- return (
384
- <div>
385
- {
386
- renderMermaid({ source: mermaidCode })
387
- }
388
- </div>
389
- );
390
- }
391
- ```
392
-
393
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
394
- |------|------|------|--------|------|
395
- | source | string | ✅ | - | Mermaid 代码字符串,支持设置标题 |
396
- | debounceMs | number | ❌ | 300 | 图表渲染时的 debounce 时间(毫秒) |
397
- | enablePanzoom | boolean | ❌ | true | 是否启用缩放和平移功能 |
398
- | showDownload | boolean | ❌ | true | 是否显示下载按钮(支持 SVG/PNG 格式) |
399
- | showSourceView | boolean | ❌ | false | 是否显示源码查看按钮和工具栏 |
400
- | showCollapse | boolean | ❌ | false | 是否显示折叠/展开按钮 |
401
- | defaultCollapsed | boolean | ❌ | true | 默认折叠状态 |
402
- | className | string | ❌ | "" | 自定义样式类名 |
403
- | minHeight | number | ❌ | 200 | 最小高度(像素) |
404
-
405
- **功能特性:**
406
- - 缩放:支持放大、缩小、重置视图
407
- - 全屏:支持浏览器原生全屏模式
408
- - 下载:支持下载 SVG 和 PNG 格式
409
- - 源码查看:点击按钮可查看 Mermaid 源码
410
- - 折叠/展开:支持图表的折叠和展开
411
- - 缩略图模式:最小化时显示缩略图
412
- - 深色模式:自动适配主题
413
-
414
-
415
- ## 注意事项
416
-
417
- 1. **样式引入**:务必引入 `remons-render-markdown/dist/index.css` 以确保正确的样式渲染
418
- 2. **Mermaid 支持**:当 `isSlotMermaid` 为 `true` 时,会自动渲染 mermaid 代码块为图表
419
- 3. **代码高亮**:请使用 `initHighlighter` 注册(必须)
420
- 4. **安全性**:外部链接会自动添加 `target="_blank"` 和 `rel="noopener"` 属性
421
- 5. **性能优化**:Mermaid 渲染会延迟执行,以优化首屏加载速度
422
-
1
+ # render-markdown
2
+
3
+ 一个基于 React 的 Markdown 渲染组件,支持 GFM(GitHub Flavored Markdown)Tabs 标签、代码高亮、Mermaid 图表等功能。
4
+
5
+ 渲染效果
6
+ ![整体渲染效果](https://remons.cn:3008/upload/md_assets/%E6%95%B4%E4%BD%93%E6%B8%B2%E6%9F%93%E6%95%88%E6%9E%9C.png)
7
+
8
+ ## 技术方案
9
+
10
+ ### 技术栈
11
+
12
+ | 类别 | 技术选型 | 说明 |
13
+ |------|---------|------|
14
+ | 框架 | React 18 | 组件库基础框架 |
15
+ | 构建工具 | Vite | 基于 Rollup 的极速构建器 |
16
+ | 语言 | TypeScript | 提供类型定义 |
17
+ | 样式方案 | CSS Modules / 内联样式 | 轻量无外部依赖 |
18
+ | 代码规范 | ESLint + Prettier | 统一代码风格 |
19
+ | 发布工具 | changesets | 语义化版本管理与 changelog 生成 |
20
+
21
+ ### 核心功能
22
+
23
+ - **GFM 支持**: 完整的 GitHub Flavored Markdown 渲染
24
+ - **增量渲染**: 基于 morphdom 的 DOM 差异化更新,适用于流式输出场景
25
+ - **代码高亮**: 基于 highlight.js 的代码语法高亮
26
+ - **Mermaid 图表**: 支持 Mermaid 语法渲染流程图、时序图等
27
+ - **Tab 标签页**: 支持 Tab 标签页语法
28
+ - **Alert 提示框**: 支持警告、提示等信息框
29
+ - **目录锚点**: 自动生成文档目录和锚点链接(自行实现目录渲染)
30
+ - **代码复制**: 一键复制代码块
31
+ - **代码折叠**: 支持代码块折叠展开
32
+ - **深色模式**: 自动适配深色/浅色主题
33
+
34
+ ## API
35
+
36
+ ### 安装
37
+
38
+ ```bash
39
+ npm install remons-render-markdown
40
+ ```
41
+
42
+ ### 导出内容
43
+
44
+ ```typescript
45
+ import RenderMarkdown, { markdownFormat, languagesCommon, initHighlighter, useIncrementalRender } from 'remons-render-markdown';
46
+ ```
47
+
48
+ #### 默认导出
49
+
50
+ - **RenderMarkdown**: React 组件,用于渲染 Markdown 内容
51
+
52
+ #### 命名导出
53
+
54
+ - **markdownFormat**: Markdown 解析函数,返回 `{ anchor: AnchorItem[], info: string }`
55
+ - **languagesCommon**: 默认支持的语言包配置(javascript, typescript, css, json, bash, xml, plaintext)
56
+ - **initHighlighter**: 初始化高亮语言包的函数
57
+ - **useIncrementalRender**: 增量渲染 hook,使用 morphdom 进行 DOM 差异化更新,适用于流式输出场景
58
+ - **renderMermaid**: 独立的 Mermaid 图表渲染组件
59
+
60
+ ### RenderMarkdown 组件 Props
61
+
62
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
63
+ |------|------|------|--------|------|
64
+ | content | string | ✅ | - | Markdown 内容 |
65
+ | createTime | string | ❌ | - | 创建时间,用于显示文档更新时间 |
66
+ | isSlotMermaid | boolean | ❌ | true | 是否使用 Mermaid 插件渲染图表 |
67
+ | isShowCollapsed | boolean | ❌ | true | 是否显示代码折叠按钮 |
68
+ | codeType | string | ❌ | - | 指定代码类型(如 'javascript' 等),不传则按 Markdown 渲染 |
69
+ | editButton | React.ReactNode | ❌ | - | 自定义编辑按钮 |
70
+ | backTopTarget | HTMLElement | ❌ | body | 返回顶部按钮监听的容器 |
71
+ | showDriverGuide | boolean | ❌ | false | 是否显示新手引导 |
72
+ | showToc | boolean | ❌ | false | 是否显示目录(TOC)按钮和侧边栏 |
73
+
74
+ ### markdownFormat 函数
75
+
76
+ 解析 Markdown 内容并返回结构化数据。
77
+
78
+ **参数:**
79
+
80
+ - `content: string` - Markdown 文本内容
81
+
82
+ **返回值:**
83
+
84
+ ```typescript
85
+ {
86
+ anchor: Array<{
87
+ title: string; // 标题文本
88
+ href: string; // 锚点链接
89
+ nodeName: string; // 节点名称,如 "H1", "H2"
90
+ nodeTitle: string; // 完整节点 HTML
91
+ children: Array<...>; // 子标题
92
+ }>;
93
+ info: string; // 渲染后的 HTML 字符串
94
+ }
95
+ ```
96
+
97
+ ### initHighlighter 函数
98
+
99
+ 注册自定义的代码高亮语言。
100
+
101
+ **参数:**
102
+
103
+ - `languages: Record<string, any>` - 语言包对象,格式为 `{ languageName: languageModule }`
104
+
105
+ **示例:**
106
+
107
+ ```typescript
108
+ import javascript from 'highlight.js/lib/languages/javascript';
109
+ import python from 'highlight.js/lib/languages/python';
110
+
111
+ initHighlighter({
112
+ javascript,
113
+ python,
114
+ });
115
+ ```
116
+
117
+ ## 使用方式
118
+
119
+ ### 基础用法
120
+
121
+ ```tsx
122
+ import RenderMarkdown from 'remons-render-markdown';
123
+ import 'render-markdown/dist/index.css';
124
+
125
+ function App() {
126
+ const markdownContent = `
127
+ # Hello World
128
+
129
+ This is a **Markdown** renderer.
130
+
131
+ \`\`\`javascript
132
+ console.log('Hello');
133
+ \`\`\`
134
+ `;
135
+
136
+ return <RenderMarkdown content={markdownContent} />;
137
+ }
138
+ ```
139
+
140
+ ### 完整示例
141
+
142
+ ```tsx
143
+ import RenderMarkdown from 'remons-render-markdown';
144
+ import 'render-markdown/dist/index.css';
145
+
146
+ function ArticlePage() {
147
+ const content = `
148
+ # 文章标题
149
+
150
+ 这是一篇示例文章。
151
+
152
+ ## 代码示例
153
+
154
+ \`\`\`javascript
155
+ const greeting = 'Hello World';
156
+ console.log(greeting);
157
+ \`\`\`
158
+
159
+ ## Mermaid 图表
160
+
161
+ \`\`\`mermaid
162
+ graph TD
163
+ A[开始] --> B[处理]
164
+ B --> C[结束]
165
+ \`\`\`
166
+ `;
167
+
168
+ return (
169
+ <RenderMarkdown
170
+ content={content}
171
+ createTime="2026-07-23T12:00:00Z"
172
+ isSlotMermaid={true}
173
+ isShowCollapsed={true}
174
+ editButton={<button>编辑</button>}
175
+ />
176
+ );
177
+ }
178
+ ```
179
+
180
+ ### 使用 markdownFormat 获取目录结构
181
+
182
+ ```tsx
183
+ import { markdownFormat } from 'remons-render-markdown';
184
+
185
+ async function TableOfContents() {
186
+ const content = '# 标题1\n## 标题1.1\n## 标题1.2\n# 标题2';
187
+ const { anchor, info } = await markdownFormat(content);
188
+
189
+ console.log(anchor);
190
+ // [
191
+ // { title: '标题1', href: '标题1', nodeName: 'H1', children: [...] },
192
+ // { title: '标题2', href: '标题2', nodeName: 'H1', children: [] }
193
+ // ]
194
+
195
+ return <div dangerouslySetInnerHTML={{ __html: info }} />;
196
+ }
197
+ ```
198
+
199
+ ### 自定义代码高亮语言
200
+
201
+ ```tsx
202
+ import RenderMarkdown, { initHighlighter, languagesCommon } from 'remons-render-markdown';
203
+ import 'render-markdown/dist/index.css';
204
+ import python from 'highlight.js/lib/languages/python';
205
+ import go from 'highlight.js/lib/languages/go';
206
+
207
+ // 注册额外的语言
208
+ initHighlighter({
209
+ ...languagesCommon, // 包含默认语言
210
+ python,
211
+ go,
212
+ });
213
+
214
+ function App() {
215
+ return (
216
+ <RenderMarkdown
217
+ content={`
218
+ \`\`\`python
219
+ def hello():
220
+ print('Hello')
221
+ \`\`\`
222
+
223
+ \`\`\`go
224
+ package main
225
+ import "fmt"
226
+ func main() {
227
+ fmt.Println("Hello")
228
+ }
229
+ \`\`\`
230
+ `}
231
+ />
232
+ );
233
+ }
234
+ ```
235
+
236
+ ### 仅渲染特定代码类型
237
+
238
+ ```tsx
239
+ import RenderMarkdown from 'remons-render-markdown';
240
+ import 'render-markdown/dist/index.css';
241
+
242
+ function CodeViewer() {
243
+ const code = `
244
+ const x = 1;
245
+ const y = 2;
246
+ console.log(x + y);
247
+ `;
248
+
249
+ return (
250
+ <RenderMarkdown
251
+ content={code}
252
+ codeType="javascript"
253
+ isSlotMermaid={false}
254
+ />
255
+ );
256
+ }
257
+ ```
258
+
259
+ ### 使用 useIncrementalRender 实现增量渲染
260
+
261
+ `useIncrementalRender` 适用于流式输出场景(如 AI 对话),通过 morphdom 实现高效的 DOM 差异化更新。
262
+
263
+ ```tsx
264
+ import { useIncrementalRender } from 'remons-render-markdown';
265
+
266
+ function StreamingContent({ content }) {
267
+ const { anchors, hasContent, setInnerRef } = useIncrementalRender({
268
+ content,
269
+ // 可选:节流时间,默认 16ms
270
+ throttleMs: 16,
271
+ });
272
+
273
+ return (
274
+ <div>
275
+ {hasContent && <div ref={setInnerRef} />}
276
+ {anchors.length > 0 && (
277
+ <ul>
278
+ {anchors.map((item) => (
279
+ <li key={item.href}>
280
+ <a href={`#${item.href}`}>{item.title}</a>
281
+ </li>
282
+ ))}
283
+ </ul>
284
+ )}
285
+ </div>
286
+ );
287
+ }
288
+ ```
289
+
290
+ **参数:**
291
+
292
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
293
+ |------|------|------|--------|------|
294
+ | content | string | ✅ | - | Markdown 内容 |
295
+ | codeType | string | ❌ | - | 代码类型,不传则按 Markdown 渲染 |
296
+ | customRenderers | MarkdownPlugin[] | ❌ | - | 自定义 markdown-it 插件 |
297
+ | throttleMs | number | ❌ | 16 | 节流时间(ms) |
298
+ | onNodeDiscarded | (el: HTMLElement) => void | ❌ | - | 节点被 diff 移除后触发(含被移除子树的子节点),用于清理 React Root 等挂载状态 |
299
+
300
+ **返回值:**
301
+
302
+ | 属性 | 类型 | 说明 |
303
+ |------|------|------|
304
+ | anchors | AnchorItem[] | 文档锚点列表 |
305
+ | hasContent | boolean | 是否有内容 |
306
+ | setInnerRef | (node: HTMLDivElement) => void | 内容容器的 ref 回调 |
307
+
308
+ **增量渲染与自定义插件(customRenderers)的配合约定:**
309
+
310
+ 1. 插件产出的容器节点(如 `:::badge` / `:::linkCard` / `<plugin-container>`)按"标签 + className"语义匹配,内容位移时不同类型的块不会被错配到旧节点上。
311
+ 2. 元素上 JS 后加的 `data-*` 属性(如初始化守卫位 `data-xxx-inited`)在 diff 后会被保留,"只初始化一次"的守卫逻辑不会在增量渲染中被重复触发。
312
+ 3. JS 动态插入的额外子节点(如 React 挂载点、收起按钮)默认会被 diff 移除;若需跨增量渲染保留,请给节点设置 `data-md-persist` 属性(见导出常量 `MD_PERSIST_ATTR`)。
313
+ 4. 被 diff 移除的节点会触发 `onNodeDiscarded`,请在此卸载挂载在其上的 React Root,避免内存泄漏。
314
+
315
+ ### 关于语法
316
+
317
+ #### mermaid 图表
318
+
319
+ ```code
320
+ ---
321
+ title: 图表标题
322
+ ---
323
+ ......... 图表内容
324
+ ```
325
+
326
+ - 折叠图
327
+ ![mermaid 渲染图](https://remons.cn:3008/upload/md_assets/mermaid%20%E7%BC%A9%E7%95%A5%E5%9B%BE.png)
328
+
329
+ - 缩略图
330
+ ![mermaid 渲染图](https://remons.cn:3008/upload/md_assets/mermaid%20%E5%B1%95%E5%BC%80%E5%9B%BE.png)
331
+ #### Tabs 标签页
332
+
333
+ 依赖于 `@mdit/plugin-tab` 插件,参考 [mdit-plugin-tab](https://mdit-plugins.github.io/zh/tab.html) 的文档。
334
+ *暂不支持 tabs 嵌套*
335
+
336
+ 语法示例:
337
+
338
+ ```markdown
339
+ :::markdown-tabs
340
+
341
+ @tab:active tab1
342
+ ```javascript
343
+ console.log('Hello');
344
+ ```
345
+
346
+ @tab tab2
347
+ ```typescript
348
+ console.log('World');
349
+ ```
350
+ :::
351
+ ```
352
+ ![tabs 渲染图](https://remons.cn:3008/upload/md_assets/tabs.png)
353
+
354
+ #### Alert 提示框
355
+
356
+ 语法示例:
357
+
358
+ ```markdown
359
+ > [!warning]
360
+ > 我是一个警告信息
361
+ ```
362
+
363
+ ![alert 渲染图](https://remons.cn:3008/upload/md_assets/alert.png)
364
+
365
+ #### renderMermaid 方法
366
+
367
+ 支持渲染独立的 Mermaid 图表渲染组件,支持缩放、全屏、下载、源码查看等功能。
368
+
369
+ ```tsx
370
+ import { renderMermaid } from 'remons-render-markdown';
371
+ import 'remons-render-markdown/dist/index.css';
372
+
373
+ function MermaidComponent() {
374
+ const mermaidCode = `
375
+ ---
376
+ title: 流程图示例
377
+ ---
378
+ graph TD
379
+ A[开始] --> B[处理]
380
+ B --> C[结束]
381
+ `;
382
+
383
+ return (
384
+ <div>
385
+ {
386
+ renderMermaid({ source: mermaidCode })
387
+ }
388
+ </div>
389
+ );
390
+ }
391
+ ```
392
+
393
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
394
+ |------|------|------|--------|------|
395
+ | source | string | ✅ | - | Mermaid 代码字符串,支持设置标题 |
396
+ | debounceMs | number | ❌ | 300 | 图表渲染时的 debounce 时间(毫秒) |
397
+ | enablePanzoom | boolean | ❌ | true | 是否启用缩放和平移功能 |
398
+ | showDownload | boolean | ❌ | true | 是否显示下载按钮(支持 SVG/PNG 格式) |
399
+ | showSourceView | boolean | ❌ | false | 是否显示源码查看按钮和工具栏 |
400
+ | showCollapse | boolean | ❌ | false | 是否显示折叠/展开按钮 |
401
+ | defaultCollapsed | boolean | ❌ | true | 默认折叠状态 |
402
+ | className | string | ❌ | "" | 自定义样式类名 |
403
+ | minHeight | number | ❌ | 200 | 最小高度(像素) |
404
+
405
+ **功能特性:**
406
+ - 缩放:支持放大、缩小、重置视图
407
+ - 全屏:支持浏览器原生全屏模式
408
+ - 下载:支持下载 SVG 和 PNG 格式
409
+ - 源码查看:点击按钮可查看 Mermaid 源码
410
+ - 折叠/展开:支持图表的折叠和展开
411
+ - 缩略图模式:最小化时显示缩略图
412
+ - 深色模式:自动适配主题
413
+
414
+
415
+ ## 注意事项
416
+
417
+ 1. **样式引入**:务必引入 `remons-render-markdown/dist/index.css` 以确保正确的样式渲染
418
+ 2. **Mermaid 支持**:当 `isSlotMermaid` 为 `true` 时,会自动渲染 mermaid 代码块为图表
419
+ 3. **代码高亮**:请使用 `initHighlighter` 注册(必须)
420
+ 4. **安全性**:外部链接会自动添加 `target="_blank"` 和 `rel="noopener"` 属性
421
+ 5. **性能优化**:Mermaid 渲染会延迟执行,以优化首屏加载速度
422
+