ds-markdown 0.0.10-beta.2 → 0.0.10-beta.3

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,40 +1,108 @@
1
1
  # ds-markdown
2
2
 
3
- `ds-markdown`是一个[React](https://react.dev)组件, 类似[deepseek官网](https://chat.deepseek.com/)风格的 `Markdown`
3
+ > 🚀 一个高性能的 React Markdown 打字动画组件,完美复刻 DeepSeek 聊天界面效果
4
4
 
5
- [DEMO](https://onshinpei.github.io/ds-markdown/)
5
+ `ds-markdown` 是一个专为现代 Web 应用设计的 React 组件,提供流畅的打字动画效果和完整的 Markdown 渲染能力。
6
6
 
7
- ## 特性
7
+ [![npm version](https://img.shields.io/npm/v/ds-markdown)](https://www.npmjs.com/package/ds-markdown)
8
+ [![npm downloads](https://img.shields.io/npm/dm/ds-markdown.svg)](https://www.npmjs.com/package/ds-markdown)
9
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/ds-markdown)](https://bundlephobia.com/package/ds-markdown)
10
+ [![React](https://img.shields.io/badge/React-16.8+-blue)](https://react.dev)
8
11
 
9
- - 🦮 对`deepseek`官网的聊天响应效果进行了1:1还原
10
- - 🛠 自带打字效果
11
- - 🦮 内部封装了常用的`markdown`格式的文本显示
12
- - 🔤 对大文档进行了性能优化,进行分批处理,生成打字效果的时候不会对页面造成卡顿现象
12
+ [📖 在线演示](https://onshinpei.github.io/ds-markdown/) | [🔧 StackBlitz 体验](https://stackblitz.com/edit/vitejs-vite-ddfw8avb?file=src%2FApp.tsx)
13
13
 
14
- ## 安装
14
+ ## ✨ 特性
15
+
16
+ - 🎯 **1:1 还原** - 完美复刻 [DeepSeek 官网](https://chat.deepseek.com/) 聊天响应效果
17
+ - ⚡ **高性能** - 智能分批处理,大文档渲染无卡顿
18
+ - 🎬 **流畅动画** - 双模式定时器,支持高频打字效果
19
+ - 🎨 **完整渲染** - 内置常用 Markdown 格式支持
20
+ - 🔧 **灵活配置** - 声明式 + 命令式双重 API 设计
21
+ - 📱 **现代兼容** - 支持 React 16.8+ 和现代浏览器
22
+
23
+ ## 📦 安装
15
24
 
16
25
  ```bash
17
26
  npm install ds-markdown
27
+ # or
28
+ yarn add ds-markdown
29
+ # or
30
+ pnpm add ds-markdown
31
+ ```
32
+
33
+ ## 🚀 快速开始
34
+
35
+ ```tsx
36
+ import DsMarkdown from 'ds-markdown';
37
+ import 'ds-markdown/style.css';
38
+
39
+ function App() {
40
+ return (
41
+ <DsMarkdown timerType="requestAnimationFrame" interval={20} answerType="answer">
42
+ # Hello World 这是一个**打字动画**示例!
43
+ </DsMarkdown>
44
+ );
45
+ }
46
+ ```
47
+
48
+ ## 📚 API 文档
49
+
50
+ ### 默认导出 (声明式 API)
51
+
52
+ | 属性名 | 类型 | 说明 | 默认值 |
53
+ | ------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------- | ------------------------- |
54
+ | `interval` | `number` | 打字间隔时间 (毫秒) | `30` |
55
+ | `timerType` | `'setTimeout'` \| `'requestAnimationFrame'` | 定时器类型,详见下方说明 | `'requestAnimationFrame'` |
56
+ | `answerType` | `'thinking'` \| `'answer'` | 内容类型,影响样式主题 | `'answer'` |
57
+ | `onEnd` | `(data: { str: string; answerType: AnswerType }) => void` | 打字结束回调 **(可能触发多次)** | - |
58
+ | `onStart` | `(data: { currentIndex: number; currentChar: string; answerType: AnswerType; prevStr: string }) => void` | 打字开始回调 **(可能触发多次)** | - |
59
+ | `onTypedChar` | `(data: { currentIndex: number; currentChar: string; answerType: AnswerType; prevStr: string }) => void` | 每个字符打字回调 | - |
60
+
61
+ #### 🎛️ timerType 模式详解
62
+
63
+ ##### `requestAnimationFrame` 模式 (推荐) 🌟
64
+
65
+ ```typescript
66
+ // 特性
67
+ - 🎯 时间驱动:基于真实经过时间计算字符数量
68
+ - 📊 批量处理:单帧内可处理多个字符
69
+ - 🎬 帧同步:与浏览器 60fps 刷新率同步
70
+ - ⚡ 高频优化:完美支持 interval < 16ms 的高速打字
71
+
72
+ // 适用场景
73
+ - 追求流畅动画效果
74
+ - 高频打字 (interval: 5-15ms)
75
+ - 现代 Web 应用的默认选择
18
76
  ```
19
77
 
20
- <a href="https://www.npmjs.com/package/ds-markdown"><img src="https://img.shields.io/npm/v/ds-markdown" alt="npm version"/></a>
21
- <img src="https://img.shields.io/npm/dm/ds-markdown.svg" alt="npm downloads"/> <img src="https://img.shields.io/bundlephobia/minzip/ds-markdown" alt="Min gzipped size"/>
78
+ ##### `setTimeout` 模式 (传统) 📟
22
79
 
23
- ## props
80
+ ```typescript
81
+ // 特性
82
+ - ⚡ 单字符:每次精确处理一个字符
83
+ - 🕐 固定间隔:严格按设定时间执行
84
+ - 🎵 节拍感:经典打字机的节奏感
85
+ - 🎯 精确控制:适合特定时序要求
86
+
87
+ // 适用场景
88
+ - 需要精确时间控制
89
+ - 营造复古打字机效果
90
+ - 兼容性要求较高的场景
91
+ ```
24
92
 
25
- ### 默认导出
93
+ ##### 📊 性能对比
26
94
 
27
- | 属性名 | 类型 | 说明 | 默认值 |
28
- | ------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -------- |
29
- | `interval` | `number` | 打字的速度`ms` | `30` |
30
- | `answerType` | `thinking` \| `answer` | `markdown`类型 | `answer` |
31
- | `onEnd` | `(data: { str: string; answerType: AnswerType }) => void` | 打字结束后回调,**可能会触发多次,因为AI的响应可能是一段一段,间隔可能较久** | - |
32
- | `onStart` | `(data: { currentIndex: number; currentChar: string; answerType: AnswerType; prevStr: string }) => void` | 打字开始回调 **可能会触发多次** | - |
33
- | `onTypedChar` | `(data: { currentIndex: number; currentChar: string; answerType: AnswerType; prevStr: string }) => void` | 当前正在打字的回调 | - |
95
+ | 特性 | requestAnimationFrame | setTimeout |
96
+ | ------------ | ---------------------------- | ---------------- |
97
+ | **字符处理** | 每帧可处理多个字符 | 每次处理一个字符 |
98
+ | **高频间隔** | 优秀 (5ms → 每帧3字符) | 可能卡顿 |
99
+ | **低频间隔** | 正常 (100ms 6帧后1字符) | 精确 |
100
+ | **视觉效果** | 🎬 流畅动画感 | 精确节拍感 |
101
+ | **性能开销** | 🟢 (帧同步) | 🟡 中等 (定时器) |
34
102
 
35
- ## 使用示例 - default export
103
+ ## 💡 使用示例
36
104
 
37
- [在线查看](https://stackblitz.com/edit/vitejs-vite-ddfw8avb?file=src%2FApp.tsx)
105
+ ### 📝 声明式用法 (推荐)
38
106
 
39
107
  ```tsx
40
108
  import { useState } from 'react';
@@ -43,32 +111,33 @@ import 'ds-markdown/style.css';
43
111
 
44
112
  const markdown = `# ds-markdown
45
113
 
46
- \`ds-markdown\`是一个[React](https://react.dev)组件, 类似[deepseek官网](https://chat.deepseek.com/)风格的 \`Markdown\`
114
+ \`ds-markdown\` 是一个高性能的 React Markdown 打字动画组件
47
115
 
48
- ## 特性
116
+ ## 特性
49
117
 
50
- - 🦮 对`deepseek`官网的聊天响应效果进行了1:1还原
51
- - 🛠 自带打字效果
52
- - 🦮 内部封装了常用的\`markdown\`格式的文本显示
53
- - 🔤 对大文档进行了性能优化,进行分批处理,生成打字效果的时候不会对页面造成卡顿现象
118
+ - 🎯 **1:1 还原** - 完美复刻 DeepSeek 聊天界面效果
119
+ - **高性能** - 智能分批处理,大文档渲染无卡顿
120
+ - 🎬 **流畅动画** - 双模式定时器,支持高频打字效果
54
121
  `;
55
122
 
56
123
  function App() {
57
124
  const [thinkingContent, setThinkingContent] = useState('');
58
125
  const [answerContent, setAnswerContent] = useState('');
59
126
 
60
- const onClick = () => {
61
- // 如果重复点击,则会清空之前的效果
62
- setThinkingContent('这是我思考的内容,我已经思考完成,下面是我的答案');
127
+ const handleStart = () => {
128
+ // 清空之前的内容
129
+ setThinkingContent('🤔 正在分析您的问题...\n\n分析完成,准备回答');
63
130
  };
64
131
 
65
- console.log(answerContent);
66
132
  return (
67
133
  <div>
68
- <button onClick={onClick}>点击显示文字效果</button>
134
+ <button onClick={handleStart}>开始演示</button>
135
+
136
+ {/* 思考过程 */}
69
137
  <DsMarkdown
70
138
  answerType="thinking"
71
- interval={5}
139
+ interval={15}
140
+ timerType="requestAnimationFrame"
72
141
  onEnd={() => {
73
142
  console.log('思考完成');
74
143
  setAnswerContent(markdown);
@@ -77,8 +146,9 @@ function App() {
77
146
  {thinkingContent}
78
147
  </DsMarkdown>
79
148
 
80
- {!!answerContent && (
81
- <DsMarkdown answerType="answer" interval={5}>
149
+ {/* 回答内容 */}
150
+ {answerContent && (
151
+ <DsMarkdown answerType="answer" interval={10} timerType="requestAnimationFrame">
82
152
  {answerContent}
83
153
  </DsMarkdown>
84
154
  )}
@@ -89,58 +159,155 @@ function App() {
89
159
  export default App;
90
160
  ```
91
161
 
92
- ## 命令式示例
162
+ [🔗 在线体验](https://stackblitz.com/edit/vitejs-vite-ddfw8avb?file=src%2FApp.tsx)
93
163
 
94
- 上面的示例中使用声明式方式来进行`markdown`的打字效果,当我们用流式拉取到数据时,文字是一个不断变化的过程,我们可以进行命令式的方式来加入文字,这样可以减少`markdown`的`rerender`
95
- 使用方式:
96
- `import { MarkdownCMD } from 'ds-markdown';`
164
+ ### ⚡ 命令式用法 (流式场景)
97
165
 
98
- [在线查看](https://stackblitz.com/edit/vitejs-vite-2ri8kex3?file=src%2FApp.tsx)
166
+ 适用于实时流式数据场景,减少组件重渲染,提升性能。
99
167
 
100
168
  ```tsx
101
- import { useRef, useState } from 'react';
169
+ import { useRef } from 'react';
102
170
  import { MarkdownCMD } from 'ds-markdown';
103
171
  import 'ds-markdown/style.css';
104
172
 
105
- const markdown = `# ds-markdown
106
-
107
- \`ds-markdown\`是一个[React](https://react.dev)组件, 类似[deepseek官网](https://chat.deepseek.com/)风格的 \`Markdown\`
108
-
109
- ## 特性
173
+ function StreamingChat() {
174
+ const markdownRef = useRef<any>();
110
175
 
111
- - 🦮 对`deepseek`官网的聊天响应效果进行了1:1还原
112
- - 🛠 自带打字效果
113
- - 🦮 内部封装了常用的\`markdown\`格式的文本显示
114
- - 🔤 对大文档进行了性能优化,进行分批处理,生成打字效果的时候不会对页面造成卡顿现象
115
- `;
116
-
117
- function App() {
118
- const ref = useRef();
176
+ // 模拟流式数据接收
177
+ const simulateStreaming = async () => {
178
+ markdownRef.current?.clear();
119
179
 
120
- const onClick = () => {
121
- // 如果重复点击,则会清空之前的效果
122
- ref.current.clear();
123
180
  // 显示思考过程
124
- ref.current.push('这是思考过程:我正在思考 ds-markdown是什么\n\n思考完成,准备发送答案', 'thinking');
125
- // 显示结果
126
- ref.current.push(markdown, 'answer');
181
+ markdownRef.current?.push('🤔 正在分析您的问题...\n\n分析完成,准备回答', 'thinking');
182
+
183
+ // 模拟流式回答
184
+ const chunks = [
185
+ '# 关于 ds-markdown\n\n',
186
+ '`ds-markdown` 是一个专为现代 Web 应用设计的组件。\n\n',
187
+ '## 主要特性\n\n',
188
+ '- ⚡ 高性能渲染\n',
189
+ '- 🎬 流畅动画\n',
190
+ '- 🎯 精确控制\n\n',
191
+ '希望这个回答对您有帮助!',
192
+ ];
193
+
194
+ for (const chunk of chunks) {
195
+ await new Promise((resolve) => setTimeout(resolve, 500));
196
+ markdownRef.current?.push(chunk, 'answer');
197
+ }
127
198
  };
128
199
 
129
200
  return (
130
201
  <div>
131
- <button onClick={onClick}>点击显示文字效果</button>
132
- <MarkdownCMD ref={ref} />
202
+ <button onClick={simulateStreaming}>开始流式演示</button>
203
+ <MarkdownCMD
204
+ ref={markdownRef}
205
+ interval={10}
206
+ timerType="requestAnimationFrame"
207
+ onEnd={(data) => {
208
+ console.log('段落完成:', data);
209
+ }}
210
+ />
133
211
  </div>
134
212
  );
135
213
  }
214
+ ```
136
215
 
137
- export default App;
216
+ [🔗 在线体验](https://stackblitz.com/edit/vitejs-vite-2ri8kex3?file=src%2FApp.tsx)
217
+
218
+ ### 命令式 API
219
+
220
+ ```typescript
221
+ interface MarkdownRef {
222
+ push: (content: string, answerType: 'thinking' | 'answer') => void;
223
+ clear: () => void;
224
+ triggerWholeEnd: () => void;
225
+ }
138
226
  ```
139
227
 
140
- ## 兼容性
228
+ | 方法 | 参数 | 说明 |
229
+ | ----------------- | ------------------------------------------- | ------------------ |
230
+ | `push` | `(content: string, answerType: AnswerType)` | 添加内容并开始打字 |
231
+ | `clear` | - | 清空所有内容和状态 |
232
+ | `triggerWholeEnd` | - | 手动触发完成回调 |
233
+
234
+ ## 🎨 样式定制
235
+
236
+ ```css
237
+ /* 自定义思考区域样式 */
238
+ .ds-markdown-thinking {
239
+ background: rgba(255, 193, 7, 0.1);
240
+ border-left: 3px solid #ffc107;
241
+ padding: 12px;
242
+ border-radius: 4px;
243
+ }
244
+
245
+ /* 自定义回答区域样式 */
246
+ .ds-markdown-answer {
247
+ color: #333;
248
+ line-height: 1.6;
249
+ }
250
+
251
+ /* 自定义代码块样式 */
252
+ .ds-markdown pre {
253
+ background: #f8f9fa;
254
+ border-radius: 6px;
255
+ padding: 16px;
256
+ }
257
+ ```
258
+
259
+ ## 🔧 最佳实践
260
+
261
+ ### 1. 性能优化建议
262
+
263
+ ```tsx
264
+ // ✅ 推荐:使用 requestAnimationFrame + 适中的 interval
265
+ <DsMarkdown
266
+ timerType="requestAnimationFrame"
267
+ interval={15} // 15-30ms 为最佳体验
268
+ />
269
+
270
+ // ❌ 避免:过小的 interval 值
271
+ <DsMarkdown interval={1} /> // 可能导致性能问题
272
+ ```
273
+
274
+ ### 2. 流式数据处理
275
+
276
+ ```tsx
277
+ // ✅ 推荐:使用命令式 API
278
+ const ref = useRef();
279
+ useEffect(() => {
280
+ // 实时接收数据时使用 push 方法
281
+ ref.current?.push(newChunk, 'answer');
282
+ }, [newChunk]);
283
+
284
+ // ❌ 避免:频繁更新 children prop
285
+ const [content, setContent] = useState('');
286
+ // 每次更新都会重新解析整个内容
287
+ ```
288
+
289
+ ### 3. 类型安全
290
+
291
+ ```tsx
292
+ import { MarkdownRef } from 'ds-markdown';
293
+
294
+ const ref = useRef<MarkdownRef>(null);
295
+ // 现在具有完整的类型提示
296
+ ```
297
+
298
+ ## 🌐 兼容性
299
+
300
+ - **React**: 16.8.0+
301
+ - **TypeScript**: 4.0+
302
+ - **浏览器**: Chrome 60+, Firefox 55+, Safari 12+
303
+ - **Node.js**: 14.0+
304
+
305
+ ## 📄 License
141
306
 
142
- 由于本组件采用`react hooks`编写,所以`react`版本最低为`v16.8.0`
307
+ MIT © [YourName](https://github.com/yourusername)
143
308
 
144
- ## License
309
+ ---
145
310
 
146
- MIT
311
+ <div align="center">
312
+ <strong>如果这个项目对你有帮助,请给个 ⭐️ Star 支持一下!</strong>
313
+ </div>