ds-markdown 0.1.9-beta.7 → 0.1.10-beta.0

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
@@ -43,6 +43,9 @@
43
43
  - **多主题与插件化架构**
44
44
  支持亮/暗主题切换,兼容 remark/rehype 插件,满足个性化和高级扩展需求。
45
45
 
46
+ - **丰富的UI组件系统** 🆕
47
+ 内置按钮、工具提示、分段控制器等UI组件,支持代码块复制、下载等交互功能。
48
+
46
49
  - **适用场景广泛**
47
50
  - AI 聊天机器人/助手
48
51
  - 实时问答/知识库
@@ -61,17 +64,12 @@
61
64
  - [禁用打字动画](#禁用打字动画)
62
65
  - [数学公式支持](#数学公式支持)
63
66
  - [AI 对话场景](#ai-对话场景)
67
+ - [代码块功能](#代码块功能) 🆕
68
+ - [Mermaid图表支持](#mermaid图表支持) 🆕
64
69
  - [📚 完整 API 文档](#-完整-api-文档)
65
- - [🧮 数学公式使用指南](#-数学公式使用指南)
66
70
  - [🔌 插件系统](#-插件系统)
67
- - [🎛️ 定时器模式详解](#️-定时器模式详解)
71
+ - [🎨 UI组件系统](#-ui组件系统) 🆕
68
72
  - [💡 实战示例](#-实战示例)
69
- - [🎯 高级回调控制](#-高级回调控制)
70
- - [🔄 重新开始动画演示](#-重新开始动画演示)
71
- - [▶️ 手动开始动画演示](#️-手动开始动画演示)
72
- - [📝 AI 流式对话](#-ai-流式对话)
73
- - [🧮 数学公式流式渲染](#-数学公式流式渲染)
74
- - [多语言配置](#多语言配置)
75
73
  - [🔧 最佳实践](#-最佳实践)
76
74
 
77
75
  ---
@@ -88,13 +86,21 @@
88
86
 
89
87
  - 完整 Markdown 语法支持,包括代码高亮、表格、列表等
90
88
  - 数学公式渲染 (KaTeX),支持 `$...$` 和 `\[...\]` 语法
89
+ - Mermaid 图表支持,包括流程图、序列图、甘特图、类图等 🆕
91
90
  - 支持亮色/暗色主题,适配不同产品风格
92
91
  - 插件化架构,支持 remark/rehype 插件扩展
93
92
 
93
+ ### 🎨 **UI组件系统** 🆕
94
+
95
+ - 内置丰富的UI组件:Button、IconButton、ToolTip、Segmented等
96
+ - 代码块增强功能:复制、下载、语言标识
97
+ - 完整的交互体验和无障碍支持
98
+
94
99
  ### 🔧 **开发体验**
95
100
 
96
101
  - 支持打字中断 `stop` 和继续 `resume`
97
102
  - 支持打字关闭与开启
103
+ - 完整的TypeScript类型支持
98
104
 
99
105
  ### 🎬 **流畅动画**
100
106
 
@@ -240,6 +246,85 @@ React 19 带来了许多激动人心的新特性:
240
246
  }
241
247
  ```
242
248
 
249
+ ### 代码块功能 🆕
250
+
251
+ ```tsx
252
+ import DsMarkdown from 'ds-markdown';
253
+ import 'ds-markdown/style.css';
254
+
255
+ function CodeBlockDemo() {
256
+ const codeContent = `# Hello World
257
+
258
+ \`\`\`javascript
259
+ function greet(name) {
260
+ console.log(\`Hello, \${name}!\`);
261
+ }
262
+
263
+ greet('ds-markdown');
264
+ \`\`\`
265
+
266
+ 支持代码高亮、复制和下载功能!`;
267
+
268
+ return (
269
+ <DsMarkdown
270
+ interval={20}
271
+ answerType="answer"
272
+ codeBlock={{
273
+ headerActions: true, // 启用代码块头部操作按钮
274
+ }}
275
+ >
276
+ {codeContent}
277
+ </DsMarkdown>
278
+ );
279
+ }
280
+ ```
281
+
282
+ ### Mermaid图表支持 🆕
283
+
284
+ ```tsx
285
+ import DsMarkdown from 'ds-markdown';
286
+ import { ConfigProvider } from 'ds-markdown';
287
+ import mermaidPlugin from 'ds-markdown-mermaid-plugin';
288
+ import 'ds-markdown/style.css';
289
+
290
+ function MermaidDemo() {
291
+ const chartContent = `# 流程图示例
292
+
293
+ \`\`\`mermaid
294
+ flowchart TD
295
+ A[开始] --> B{判断条件}
296
+ B -->|是| C[处理A]
297
+ B -->|否| D[处理B]
298
+ C --> E[结束]
299
+ D --> E
300
+ \`\`\`
301
+
302
+ ## 序列图示例
303
+
304
+ \`\`\`mermaid
305
+ sequenceDiagram
306
+ participant 用户
307
+ participant 系统
308
+ participant 数据库
309
+
310
+ 用户->>系统: 登录请求
311
+ 系统->>数据库: 验证用户
312
+ 数据库-->>系统: 返回结果
313
+ 系统-->>用户: 登录响应
314
+ \`\`\`
315
+
316
+ 支持流程图、序列图、甘特图、类图等多种图表类型!`;
317
+
318
+ return (
319
+ <ConfigProvider>
320
+ <DsMarkdown interval={20} answerType="answer" plugins={[mermaidPlugin]}>
321
+ {chartContent}
322
+ </DsMarkdown>
323
+ </ConfigProvider>
324
+ );
325
+ }
326
+ ```
327
+
243
328
  ---
244
329
 
245
330
  ## 📚 完整 API 文档
@@ -300,14 +385,21 @@ import DsMarkdown, { MarkdownCMD } from 'ds-markdown';
300
385
  - `'dollar'`:使用 `$...$` 和 `$$...$$` 语法
301
386
  - `'bracket'`:使用 `\(...\)` 和 `\[...\]` 语法
302
387
 
388
+ #### IMarkdownCode 🆕
389
+
390
+ | 属性 | 类型 | 说明 | 默认值 |
391
+ | --------------- | --------- | -------------------- | ------ |
392
+ | `headerActions` | `boolean` | 是否显示头部操作按钮 | `true` |
393
+
303
394
  #### IMarkdownPlugin
304
395
 
305
- | 属性 | 类型 | 说明 | 默认值 |
306
- | -------------- | ------------------------- | ------------ | ------ |
307
- | `remarkPlugin` | `unknown` | remark 插件 | - |
308
- | `rehypePlugin` | `unknown` | rehype 插件 | - |
309
- | `type` | `'buildIn'` \| `'custom'` | 插件类型 | - |
310
- | `id` | `any` | 插件唯一标识 | - |
396
+ | 属性 | 类型 | 说明 | 默认值 |
397
+ | -------------- | ---------------------------------------------- | ----------------- | ------ |
398
+ | `remarkPlugin` | `Pluggable` | remark 插件 | - |
399
+ | `rehypePlugin` | `Pluggable` | rehype 插件 | - |
400
+ | `type` | `'buildIn'` \| `'custom'` | 插件类型 | - |
401
+ | `id` | `any` | 插件唯一标识 | - |
402
+ | `components` | `Record<string, React.ComponentType<unknown>>` | 自定义组件映射 🆕 | - |
311
403
 
312
404
  ### 组件暴露的方法
313
405
 
@@ -343,106 +435,95 @@ markdownRef.current?.restart(); // 重新开始动画
343
435
 
344
436
  ---
345
437
 
346
- ## 🧮 数学公式使用指南
347
-
348
- [DEMO1:勾股定理](https://stackblitz.com/edit/vitejs-vite-z94syu8j?file=src%2FApp.tsx)
438
+ ## 🔌 插件系统
349
439
 
350
- [DEMO2:题目解答](https://stackblitz.com/edit/vitejs-vite-xk9lxagc?file=README.md)
440
+ ### 内置插件
351
441
 
352
- ### 基本语法
442
+ #### KaTeX 数学公式插件
353
443
 
354
444
  ```tsx
355
445
  import { katexPlugin } from 'ds-markdown/plugins';
356
446
 
357
- // 1. 启用数学公式支持
358
- <DsMarkdown plugins={[katexPlugin]}>
359
- # 数学公式示例
360
-
361
- // 行内公式
362
- 这是一个行内公式:$E = mc^2$
363
-
364
- // 块级公式
365
- $$\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$$
366
- </DsMarkdown>
447
+ // 启用数学公式支持
448
+ <DsMarkdown plugins={[katexPlugin]}>数学公式:$E = mc^2$</DsMarkdown>;
367
449
  ```
368
450
 
369
- ### 分隔符选择
451
+ #### Mermaid 图表插件 🆕
370
452
 
371
- ```tsx
372
- // 使用美元符号分隔符(默认)
373
- <DsMarkdown
374
- plugins={[katexPlugin]}
375
- math={{ splitSymbol: 'dollar' }}
376
- >
377
- 行内:$a + b = c$
378
- 块级:$$\sum_{i=1}^{n} x_i = x_1 + x_2 + \cdots + x_n$$
379
- </DsMarkdown>
380
-
381
- // 使用括号分隔符
382
- <DsMarkdown
383
- plugins={[katexPlugin]}
384
- math={{ splitSymbol: 'bracket' }}
385
- >
386
- 行内:\(a + b = c\)
387
- 块级:\[\sum_{i=1}^{n} x_i = x_1 + x_2 + \cdots + x_n\]
388
- </DsMarkdown>
389
- ```
390
-
391
- ### 流式数学公式
453
+ **安装 Mermaid 插件:**
392
454
 
393
- ```tsx
394
- // 完美支持流式输出中的数学公式
395
- const mathContent = [
396
- '勾股定理:',
397
- '$a^2 + b^2 = c^2$',
398
- '\n\n',
399
- '其中:',
400
- '- $a$ 和 $b$ 是直角边\n',
401
- '- $c$ 是斜边\n\n',
402
- '对于经典的"勾三股四弦五":\n',
403
- '$c = \\sqrt{3^2 + 4^2} = \\sqrt{25} = 5$\n\n',
404
- '这个定理在几何学中有着广泛的应用!',
405
- ];
406
-
407
- mathContent.forEach((chunk) => {
408
- markdownRef.current?.push(chunk, 'answer');
409
- });
455
+ ```bash
456
+ npm install ds-markdown-mermaid-plugin
410
457
  ```
411
458
 
412
- ### 样式定制
459
+ **基础用法:**
413
460
 
414
- ```css
415
- /* 数学公式样式定制 */
416
- .katex {
417
- font-size: 1.1em;
418
- }
461
+ ```tsx
462
+ import { ConfigProvider, Markdown } from 'ds-markdown';
463
+ import mermaidPlugin from 'ds-markdown-mermaid-plugin';
419
464
 
420
- .katex-display {
421
- margin: 1em 0;
422
- text-align: center;
423
- }
465
+ function App() {
466
+ const content = `
467
+ # 流程图示例
468
+
469
+ \`\`\`mermaid
470
+ flowchart TD
471
+ A[开始] --> B{判断条件}
472
+ B -->|是| C[处理A]
473
+ B -->|否| D[处理B]
474
+ C --> E[结束]
475
+ D --> E
476
+ \`\`\`
477
+ `;
424
478
 
425
- /* 暗色主题适配 */
426
- [data-theme='dark'] .katex {
427
- color: #e1e1e1;
479
+ return (
480
+ <ConfigProvider>
481
+ <Markdown plugins={[mermaidPlugin]}>{content}</Markdown>
482
+ </ConfigProvider>
483
+ );
428
484
  }
429
485
  ```
430
486
 
431
- ---
432
-
433
- ## 🔌 插件系统
487
+ **支持的图表类型:**
434
488
 
435
- ### 内置插件
489
+ - 🔄 **流程图** (Flowchart) - 展示流程和决策路径
490
+ - 📋 **序列图** (Sequence Diagram) - 展示对象间的交互时序
491
+ - 📅 **甘特图** (Gantt Chart) - 项目计划和时间线
492
+ - 🏗️ **类图** (Class Diagram) - 面向对象设计
493
+ - 🥧 **饼图** (Pie Chart) - 数据比例展示
494
+ - 🔀 **状态图** (State Diagram) - 状态转换流程
495
+ - 📊 **Git图** (Git Graph) - 代码分支历史
496
+ - 🗺️ **用户旅程图** (User Journey) - 用户体验流程
436
497
 
437
- #### KaTeX 数学公式插件
498
+ **配置 Mermaid:**
438
499
 
439
500
  ```tsx
440
- import { katexPlugin } from 'ds-markdown/plugins';
501
+ import { ConfigProvider } from 'ds-markdown';
441
502
 
442
- // 启用数学公式支持
443
- <DsMarkdown plugins={[katexPlugin]}>数学公式:$E = mc^2$</DsMarkdown>;
503
+ const mermaidConfig = {
504
+ theme: 'default', // 主题:default, neutral, dark, forest
505
+ flowchart: {
506
+ useMaxWidth: true,
507
+ htmlLabels: true,
508
+ },
509
+ sequence: {
510
+ diagramMarginX: 50,
511
+ diagramMarginY: 10,
512
+ },
513
+ };
514
+
515
+ return (
516
+ <ConfigProvider mermaidConfig={mermaidConfig}>
517
+ <Markdown plugins={[mermaidPlugin]}>{chartContent}</Markdown>
518
+ </ConfigProvider>
519
+ );
444
520
  ```
445
521
 
522
+ **相关链接:**
523
+
524
+ - [ds-markdown-mermaid-plugin GitHub](https://github.com/onshinpei/ds-markdown-mermaid-plugin)
525
+ - [Mermaid 官方文档](https://mermaid.js.org/)
526
+
446
527
  ### 自定义插件
447
528
 
448
529
  ```tsx
@@ -453,6 +534,10 @@ const customPlugin = createBuildInPlugin({
453
534
  remarkPlugin: yourRemarkPlugin,
454
535
  rehypePlugin: yourRehypePlugin,
455
536
  id: Symbol('custom-plugin'),
537
+ components: {
538
+ // 自定义组件映射 🆕
539
+ CustomComponent: MyCustomComponent,
540
+ },
456
541
  });
457
542
 
458
543
  // 使用自定义插件
@@ -461,356 +546,86 @@ const customPlugin = createBuildInPlugin({
461
546
 
462
547
  ---
463
548
 
464
- ## 🎛️ 定时器模式详解
549
+ ## 🎨 UI组件系统 🆕
465
550
 
466
- ### `requestAnimationFrame` 模式 🌟 (推荐)
551
+ ds-markdown 提供了丰富的UI组件,可以单独使用或与markdown组件配合。
467
552
 
468
- ```typescript
469
- // 🎯 特性
470
- - 时间驱动:基于真实经过时间计算字符数量
471
- - 批量处理:单帧内可处理多个字符
472
- - 帧同步:与浏览器 60fps 刷新率同步
473
- - 高频优化:完美支持 interval < 16ms 的高速打字
553
+ ### 核心组件
474
554
 
475
- // 🎯 适用场景
476
- - 现代 Web 应用的默认选择
477
- - 追求流畅动画效果
478
- - 高频打字 (interval > 0 即可)
479
- - AI 实时对话场景
480
- ```
481
-
482
- ### `setTimeout` 模式 📟 (兼容)
483
-
484
- ```typescript
485
- // 🎯 特性
486
- - 单字符:每次精确处理一个字符
487
- - 固定间隔:严格按设定时间执行
488
- - 节拍感:经典打字机的节奏感
489
- - 精确控制:适合特定时序要求
555
+ ```tsx
556
+ import {
557
+ Button,
558
+ IconButton,
559
+ ToolTip,
560
+ Segmented,
561
+ CopyButton,
562
+ DownloadButton
563
+ } from 'ds-markdown';
564
+
565
+ // 按钮组件
566
+ <Button icon={<span>📄</span>} onClick={() => {}}>
567
+ 点击按钮
568
+ </Button>
569
+
570
+ // 工具提示
571
+ <ToolTip title="提示信息">
572
+ <IconButton icon={<span>📋</span>} onClick={() => {}} />
573
+ </ToolTip>
574
+
575
+ // 分段控制器
576
+ <Segmented
577
+ Segmented={[
578
+ { label: '图表', value: 'diagram' },
579
+ { label: '代码', value: 'code' }
580
+ ]}
581
+ value={value}
582
+ onChange={setValue}
583
+ />
490
584
 
491
- // 🎯 适用场景
492
- - 需要精确时间控制
493
- - 营造复古打字机效果
494
- - 兼容性要求较高的场景
585
+ // 代码块操作
586
+ <CopyButton codeContent="console.log('Hello')" />
587
+ <DownloadButton codeContent="console.log('Hello')" language="javascript" />
495
588
  ```
496
589
 
497
- ### 📊 性能对比
590
+ ### 样式定制
498
591
 
499
- | 特性 | requestAnimationFrame | setTimeout |
500
- | ------------ | ---------------------------- | ---------------- |
501
- | **字符处理** | 每帧可处理多个字符 | 每次处理一个字符 |
502
- | **高频间隔** | ✅ 优秀 (5ms → 每帧3字符) | ❌ 可能卡顿 |
503
- | **低频间隔** | 正常 (100ms → 6帧后1字符) | ✅ 精确 |
504
- | **视觉效果** | 🎬 流畅动画感 | ⚡ 精确节拍感 |
505
- | **性能开销** | 🟢 低 (帧同步) | 🟡 中等 (定时器) |
592
+ ```css
593
+ :root {
594
+ --ds-button-bg-color: #f5f5f5;
595
+ --ds-button-hover-color: #e0e0e0;
596
+ --ds-tooltip-bg-color: rgba(0, 0, 0, 0.8);
597
+ }
598
+ ```
506
599
 
507
- 高频推荐`requestAnimationFrame`,低频推荐 `setTimeout`
600
+ ---
508
601
 
509
602
  ## 多语言配置
510
603
 
511
- ConfigProvider 是 ds-markdown 提供的多语言配置组件,用于管理应用中的国际化文本。
512
-
513
- ### 基本用法
514
-
515
604
  ```tsx
516
- import React from 'react';
517
605
  import { ConfigProvider } from 'ds-markdown';
518
606
  import zhCN from 'ds-markdown/i18n/zh';
519
-
520
- const App: React.FC = () => {
521
- return (
522
- <ConfigProvider locale={zhCN}>
523
- <YourApp />
524
- </ConfigProvider>
525
- );
526
- };
527
- ```
528
-
529
- ### 可用的语言包
530
-
531
- #### 中文 (zhCN)
532
-
533
- ```tsx
534
- import zhCN from 'ds-markdown/i18n/zh';
535
- ```
536
-
537
- #### 英文 (enUS)
538
-
539
- ```tsx
540
607
  import enUS from 'ds-markdown/i18n/en';
541
- ```
542
608
 
543
- ### 在组件中使用语言包
609
+ // 中文
610
+ <ConfigProvider locale={zhCN}>
611
+ <DsMarkdown {...props} />
612
+ </ConfigProvider>
544
613
 
545
- 使用 `locale` 属性来切换自己想要的语言包,例如切换到英文
546
-
547
- ```tsx
548
- import React from 'react';
549
- import DsMarkdown from 'ds-markdown';
550
- import { ConfigProvider } from 'ds-markdown';
551
- import en from 'ds-markdown/i18n/en';
552
-
553
- const MyComponent: React.FC = () => {
554
- return (
555
- <ConfigProvider locale={en}>
556
- <DsMarkdown {...props} />
557
- </ConfigProvider>
558
- );
559
- };
614
+ // 英文
615
+ <ConfigProvider locale={enUS}>
616
+ <DsMarkdown {...props} />
617
+ </ConfigProvider>
560
618
  ```
561
619
 
562
- ### 语言包结构
563
-
564
- 当前支持的语言包包含以下字段:
565
-
566
- ```typescript
567
- interface Locale {
568
- codeBlock: {
569
- copy: string;
570
- copied: string;
571
- download: string;
572
- };
573
- [key: string]: string;
574
- }
575
- ```
576
-
577
- ### 注意事项
578
-
579
- 1. `ConfigProvider` 必须包裹在使用 `useLocale` 的组件外层
580
- 2. 语言包对象会被缓存,避免不必要的重新渲染
581
- 3. 支持扩展自定义的语言包字段
582
- 4. 如果没有提供 `ConfigProvider`,会使用默认的中文语言包
583
-
584
620
  ---
585
621
 
586
622
  ## 💡 实战示例
587
623
 
588
- ### 🎯 高级回调控制
589
-
590
- ```tsx
591
- import { useRef, useState } from 'react';
592
- import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
593
-
594
- function AdvancedCallbackDemo() {
595
- const markdownRef = useRef<MarkdownCMDRef>(null);
596
- const [typingStats, setTypingStats] = useState({ progress: 0, currentChar: '', totalChars: 0 });
597
-
598
- const handleBeforeTypedChar = async (data) => {
599
- // 在字符打字前进行异步操作
600
- console.log('即将打字:', data.currentChar);
601
-
602
- // 可以在这里进行网络请求、数据验证等异步操作
603
- if (data.currentChar === '!') {
604
- await new Promise((resolve) => setTimeout(resolve, 500)); // 模拟延迟
605
- }
606
- };
607
-
608
- const handleTypedChar = (data) => {
609
- // 更新打字统计信息
610
- setTypingStats({
611
- progress: Math.round(data.percent),
612
- currentChar: data.currentChar,
613
- totalChars: data.currentIndex + 1,
614
- });
615
-
616
- // 可以在这里添加音效、动画等效果
617
- if (data.currentChar === '.') {
618
- // 播放句号音效
619
- console.log('播放句号音效');
620
- }
621
- };
622
-
623
- const handleStart = (data) => {
624
- console.log('开始打字:', data.currentChar);
625
- };
626
-
627
- const handleEnd = (data) => {
628
- console.log('打字完成:', data.str);
629
- };
630
-
631
- const startDemo = () => {
632
- markdownRef.current?.clear();
633
- markdownRef.current?.push(
634
- '# 高级回调演示\n\n' +
635
- '这个示例展示了如何使用 `onBeforeTypedChar` 和 `onTypedChar` 回调:\n\n' +
636
- '- 🎯 **打字前回调**:可以在字符显示前进行异步操作\n' +
637
- '- 📊 **打字后回调**:可以实时更新进度和添加特效\n' +
638
- '- ⚡ **性能优化**:支持异步操作,不影响打字流畅度\n\n' +
639
- '当前进度:' +
640
- typingStats.progress +
641
- '%\n' +
642
- '已打字数:' +
643
- typingStats.totalChars +
644
- '\n\n' +
645
- '这是一个非常强大的功能!',
646
- 'answer',
647
- );
648
- };
649
-
650
- return (
651
- <div>
652
- <button onClick={startDemo}>🚀 开始高级演示</button>
653
-
654
- <div style={{ margin: '10px 0', padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
655
- <strong>打字统计:</strong> 进度 {typingStats.progress}% | 当前字符: "{typingStats.currentChar}" | 总字符数: {typingStats.totalChars}
656
- </div>
657
-
658
- <MarkdownCMD ref={markdownRef} interval={30} onBeforeTypedChar={handleBeforeTypedChar} onTypedChar={handleTypedChar} onStart={handleStart} onEnd={handleEnd} />
659
- </div>
660
- );
661
- }
662
- ```
663
-
664
- ### 🔄 重新开始动画演示
665
-
666
- ```tsx
667
- import { useRef, useState } from 'react';
668
- import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
669
-
670
- function RestartDemo() {
671
- const markdownRef = useRef<MarkdownCMDRef>(null);
672
- const [isPlaying, setIsPlaying] = useState(false);
673
- const [hasStarted, setHasStarted] = useState(false);
674
-
675
- const startContent = () => {
676
- markdownRef.current?.clear();
677
- markdownRef.current?.push(
678
- '# 重新开始动画演示\n\n' +
679
- '这个示例展示了如何使用 `restart()` 方法:\n\n' +
680
- '- 🔄 **重新开始**:从头开始播放当前内容\n' +
681
- '- ⏸️ **暂停恢复**:可以随时暂停和恢复\n' +
682
- '- 🎯 **精确控制**:完全控制动画播放状态\n\n' +
683
- '当前状态:' +
684
- (isPlaying ? '播放中' : '已暂停') +
685
- '\n\n' +
686
- '这是一个非常实用的功能!',
687
- 'answer',
688
- );
689
- setIsPlaying(true);
690
- };
691
-
692
- const handleStart = () => {
693
- if (hasStarted) {
694
- // 如果已经开始过,则重新开始
695
- markdownRef.current?.restart();
696
- } else {
697
- // 第一次开始
698
- markdownRef.current?.start();
699
- setHasStarted(true);
700
- }
701
- setIsPlaying(true);
702
- };
703
-
704
- const handleStop = () => {
705
- markdownRef.current?.stop();
706
- setIsPlaying(false);
707
- };
708
-
709
- const handleResume = () => {
710
- markdownRef.current?.resume();
711
- setIsPlaying(true);
712
- };
713
-
714
- const handleRestart = () => {
715
- markdownRef.current?.restart();
716
- setIsPlaying(true);
717
- };
718
-
719
- const handleEnd = () => {
720
- setIsPlaying(false);
721
- };
722
-
723
- return (
724
- <div>
725
- <div style={{ marginBottom: '10px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
726
- <button onClick={startContent}>🚀 开始内容</button>
727
- <button onClick={handleStart} disabled={isPlaying}>
728
- {hasStarted ? '🔄 重新开始' : '▶️ 开始'}
729
- </button>
730
- <button onClick={handleStop} disabled={!isPlaying}>
731
- ⏸️ 暂停
732
- </button>
733
- <button onClick={handleResume} disabled={isPlaying}>
734
- ▶️ 恢复
735
- </button>
736
- <button onClick={handleRestart}>🔄 重新开始</button>
737
- </div>
738
-
739
- <div style={{ margin: '10px 0', padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
740
- <strong>动画状态:</strong> {isPlaying ? '🟢 播放中' : '🔴 已暂停'}
741
- </div>
742
-
743
- <MarkdownCMD ref={markdownRef} interval={25} onEnd={handleEnd} />
744
- </div>
745
- );
746
- }
747
- ```
748
-
749
- ### ▶️ 手动开始动画演示
750
-
751
- ```tsx
752
- import { useRef, useState } from 'react';
753
- import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
754
-
755
- function StartDemo() {
756
- const markdownRef = useRef<MarkdownCMDRef>(null);
757
- const [isPlaying, setIsPlaying] = useState(false);
758
- const [hasStarted, setHasStarted] = useState(false);
759
-
760
- const loadContent = () => {
761
- markdownRef.current?.clear();
762
- markdownRef.current?.push(
763
- '# 手动开始动画演示\n\n' +
764
- '这个示例展示了如何使用 `start()` 方法:\n\n' +
765
- '- 🎯 **手动控制**:当 `autoStartTyping=false` 时,需要手动调用 `start()`\n' +
766
- '- ⏱️ **延迟开始**:可以在用户交互后开始动画\n' +
767
- '- 🎮 **游戏化**:适合需要用户主动触发的场景\n\n' +
768
- '点击"开始动画"按钮来手动启动打字效果!',
769
- 'answer',
770
- );
771
- setIsPlaying(false);
772
- };
773
-
774
- const handleStart = () => {
775
- if (hasStarted) {
776
- // 如果已经开始过,则重新开始
777
- markdownRef.current?.restart();
778
- } else {
779
- // 第一次开始
780
- markdownRef.current?.start();
781
- setHasStarted(true);
782
- }
783
- setIsPlaying(true);
784
- };
785
-
786
- const handleEnd = () => {
787
- setIsPlaying(false);
788
- };
789
-
790
- return (
791
- <div>
792
- <div style={{ marginBottom: '10px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
793
- <button onClick={loadContent}>📝 加载内容</button>
794
- <button onClick={handleStart} disabled={isPlaying}>
795
- {hasStarted ? '🔄 重新开始' : '▶️ 开始动画'}
796
- </button>
797
- </div>
798
-
799
- <div style={{ margin: '10px 0', padding: '10px', background: '#f5f5f5', borderRadius: '4px' }}>
800
- <strong>状态:</strong> {isPlaying ? '🟢 动画播放中' : '🔴 等待开始'}
801
- </div>
802
-
803
- <MarkdownCMD ref={markdownRef} interval={30} autoStartTyping={false} onEnd={handleEnd} />
804
- </div>
805
- );
806
- }
807
- ```
808
-
809
624
  ### 📝 AI 流式对话
810
625
 
811
626
  [DEMO: 🔧 StackBlitz 体验](https://stackblitz.com/edit/vitejs-vite-2ri8kex3?file=src%2FApp.tsx)
812
627
 
813
- ````tsx
628
+ ```tsx
814
629
  import { useRef } from 'react';
815
630
  import { MarkdownCMD, MarkdownCMDRef } from 'ds-markdown';
816
631
 
@@ -834,19 +649,6 @@ function StreamingChat() {
834
649
  '- 🎯 **自动优化**:无需手动 memo 和 useMemo\n',
835
650
  '- ⚡ **性能提升**:编译时优化,运行时零开销\n',
836
651
  '- 🔧 **向后兼容**:现有代码无需修改\n\n',
837
- '## 📝 Actions 简化表单\n',
838
- '新的 Actions API 让表单处理变得更简单:\n\n',
839
- '```tsx\n',
840
- 'function ContactForm({ action }) {\n',
841
- ' const [state, formAction] = useActionState(action, null);\n',
842
- ' return (\n',
843
- ' <form action={formAction}>\n',
844
- ' <input name="email" type="email" />\n',
845
- ' <button>提交</button>\n',
846
- ' </form>\n',
847
- ' );\n',
848
- '}\n',
849
- '```\n\n',
850
652
  '希望这个解答对您有帮助!🎉',
851
653
  ];
852
654
 
@@ -856,52 +658,12 @@ function StreamingChat() {
856
658
  }
857
659
  };
858
660
 
661
+ const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
662
+
859
663
  return (
860
664
  <div className="chat-container">
861
665
  <button onClick={simulateAIResponse}>🤖 询问 React 19 新特性</button>
862
-
863
- <MarkdownCMD ref={markdownRef} interval={10} timerType="requestAnimationFrame" onEnd={(data) => console.log('段落完成:', data)} />
864
- </div>
865
- );
866
- }
867
-
868
- const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
869
- ````
870
-
871
- ### 🧮 数学公式流式渲染
872
-
873
- ```tsx
874
- import { katexPlugin } from 'ds-markdown/plugins';
875
-
876
- function MathStreamingDemo() {
877
- const markdownRef = useRef<MarkdownCMDRef>(null);
878
-
879
- const simulateMathResponse = async () => {
880
- markdownRef.current?.clear();
881
-
882
- const mathChunks = [
883
- '# 勾股定理详解\n\n',
884
- '在直角三角形中,斜边的平方等于两条直角边的平方和:\n\n',
885
- '$a^2 + b^2 = c^2$\n\n',
886
- '其中:\n',
887
- '- $a$ 和 $b$ 是直角边\n',
888
- '- $c$ 是斜边\n\n',
889
- '对于经典的"勾三股四弦五":\n',
890
- '$c = \\sqrt{3^2 + 4^2} = \\sqrt{25} = 5$\n\n',
891
- '这个定理在几何学中有着广泛的应用!',
892
- ];
893
-
894
- for (const chunk of mathChunks) {
895
- await delay(150);
896
- markdownRef.current?.push(chunk, 'answer');
897
- }
898
- };
899
-
900
- return (
901
- <div>
902
- <button onClick={simulateMathResponse}>📐 讲解勾股定理</button>
903
-
904
- <MarkdownCMD ref={markdownRef} interval={20} timerType="requestAnimationFrame" plugins={[katexPlugin]} math={{ splitSymbol: 'dollar' }} />
666
+ <MarkdownCMD ref={markdownRef} interval={10} timerType="requestAnimationFrame" />
905
667
  </div>
906
668
  );
907
669
  }
@@ -917,9 +679,6 @@ function MathStreamingDemo() {
917
679
  timerType="requestAnimationFrame"
918
680
  interval={15} // 15-30ms 为最佳体验
919
681
  />
920
-
921
- // ❌ 避免过小间隔
922
- <DsMarkdown interval={1} /> // 可能导致性能问题
923
682
  ```
924
683
 
925
684
  ### 2. 流式数据处理
@@ -930,33 +689,31 @@ const ref = useRef<MarkdownCMDRef>(null);
930
689
  useEffect(() => {
931
690
  ref.current?.push(newChunk, 'answer');
932
691
  }, [newChunk]);
933
-
934
- // ❌ 避免:频繁更新 children
935
- const [content, setContent] = useState('');
936
- // 每次更新都会重新解析整个内容
937
692
  ```
938
693
 
939
694
  ### 3. 数学公式优化
940
695
 
941
696
  ```tsx
942
- // ✅ 推荐:按需加载数学公式样式
943
- import 'ds-markdown/style.css';
697
+ // ✅ 推荐:按需加载
698
+ import { katexPlugin } from 'ds-markdown/plugins';
944
699
  import 'ds-markdown/katex.css'; // 仅在需要时引入
945
700
 
946
- // ✅ 推荐:合理使用分隔符
947
- // 对于简单公式,使用 $...$ 更简洁
948
- // 对于复杂公式,使用 $$...$$ 更清晰
949
-
950
- // ✅ 推荐:插件化配置
951
- import { katexPlugin } from 'ds-markdown/plugins';
952
701
  <DsMarkdown plugins={[katexPlugin]}>数学公式内容</DsMarkdown>;
953
702
  ```
954
703
 
955
- ### 4. 类型安全
704
+ ### 4. Mermaid图表最佳实践 🆕
956
705
 
957
706
  ```tsx
958
- import { MarkdownCMDRef } from 'ds-markdown';
707
+ // 推荐:独立安装插件
708
+ npm install ds-markdown-mermaid-plugin
959
709
 
960
- const ref = useRef<MarkdownCMDRef>(null);
961
- // 完整的 TypeScript 类型提示
710
+ // 推荐:配置适合的主题
711
+ const mermaidConfig = {
712
+ theme: 'default', // 根据应用主题选择
713
+ flowchart: { useMaxWidth: true },
714
+ };
715
+
716
+ <ConfigProvider mermaidConfig={mermaidConfig}>
717
+ <DsMarkdown plugins={[mermaidPlugin]} />
718
+ </ConfigProvider>
962
719
  ```