ds-markdown 0.0.10-beta.2 → 0.0.10-beta.4
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 +305 -67
- package/dist/cjs/MarkdownCMD/index.d.ts +1 -0
- package/dist/cjs/MarkdownCMD/index.js +297 -309
- package/dist/cjs/MarkdownCMD/index.js.map +1 -1
- package/dist/cjs/defined.d.ts +14 -0
- package/dist/cjs/hooks/useTypingTask.d.ts +31 -0
- package/dist/cjs/hooks/useTypingTask.js +226 -0
- package/dist/cjs/hooks/useTypingTask.js.map +1 -0
- package/dist/cjs/utils/rule.js +0 -1
- package/dist/cjs/utils/rule.js.map +1 -1
- package/dist/esm/MarkdownCMD/index.d.ts +1 -0
- package/dist/esm/MarkdownCMD/index.js +298 -310
- package/dist/esm/MarkdownCMD/index.js.map +1 -1
- package/dist/esm/defined.d.ts +14 -0
- package/dist/esm/hooks/useTypingTask.d.ts +31 -0
- package/dist/esm/hooks/useTypingTask.js +222 -0
- package/dist/esm/hooks/useTypingTask.js.map +1 -0
- package/dist/esm/utils/rule.js +0 -1
- package/dist/esm/utils/rule.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,40 +1,108 @@
|
|
|
1
1
|
# ds-markdown
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> 🚀 一个高性能的 React Markdown 打字动画组件,完美复刻 DeepSeek 聊天界面效果
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`ds-markdown` 是一个专为现代 Web 应用设计的 React 组件,提供流畅的打字动画效果和完整的 Markdown 渲染能力。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[](https://www.npmjs.com/package/ds-markdown)
|
|
8
|
+
[](https://www.npmjs.com/package/ds-markdown)
|
|
9
|
+
[](https://bundlephobia.com/package/ds-markdown)
|
|
10
|
+
[](https://react.dev)
|
|
8
11
|
|
|
9
|
-
-
|
|
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
|
+
}
|
|
18
46
|
```
|
|
19
47
|
|
|
20
|
-
|
|
21
|
-
|
|
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` | 每个字符打字回调 | - |
|
|
22
60
|
|
|
23
|
-
|
|
61
|
+
#### 🎛️ timerType 模式详解
|
|
24
62
|
|
|
25
|
-
|
|
63
|
+
##### `requestAnimationFrame` 模式 (推荐) 🌟
|
|
26
64
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
| `onTypedChar` | `(data: { currentIndex: number; currentChar: string; answerType: AnswerType; prevStr: string }) => void` | 当前正在打字的回调 | - |
|
|
65
|
+
```typescript
|
|
66
|
+
// 特性
|
|
67
|
+
- 🎯 时间驱动:基于真实经过时间计算字符数量
|
|
68
|
+
- 📊 批量处理:单帧内可处理多个字符
|
|
69
|
+
- 🎬 帧同步:与浏览器 60fps 刷新率同步
|
|
70
|
+
- ⚡ 高频优化:完美支持 interval < 16ms 的高速打字
|
|
34
71
|
|
|
35
|
-
|
|
72
|
+
// 适用场景
|
|
73
|
+
- 追求流畅动画效果
|
|
74
|
+
- 高频打字 (interval: 5-15ms)
|
|
75
|
+
- 现代 Web 应用的默认选择
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
##### `setTimeout` 模式 (传统) 📟
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// 特性
|
|
82
|
+
- ⚡ 单字符:每次精确处理一个字符
|
|
83
|
+
- 🕐 固定间隔:严格按设定时间执行
|
|
84
|
+
- 🎵 节拍感:经典打字机的节奏感
|
|
85
|
+
- 🎯 精确控制:适合特定时序要求
|
|
86
|
+
|
|
87
|
+
// 适用场景
|
|
88
|
+
- 需要精确时间控制
|
|
89
|
+
- 营造复古打字机效果
|
|
90
|
+
- 兼容性要求较高的场景
|
|
91
|
+
```
|
|
36
92
|
|
|
37
|
-
|
|
93
|
+
##### 📊 性能对比
|
|
94
|
+
|
|
95
|
+
| 特性 | requestAnimationFrame | setTimeout |
|
|
96
|
+
| ------------ | ---------------------------- | ---------------- |
|
|
97
|
+
| **字符处理** | 每帧可处理多个字符 | 每次处理一个字符 |
|
|
98
|
+
| **高频间隔** | ✅ 优秀 (5ms → 每帧3字符) | ❌ 可能卡顿 |
|
|
99
|
+
| **低频间隔** | ✅ 正常 (100ms → 6帧后1字符) | ✅ 精确 |
|
|
100
|
+
| **视觉效果** | 🎬 流畅动画感 | ⚡ 精确节拍感 |
|
|
101
|
+
| **性能开销** | 🟢 低 (帧同步) | 🟡 中等 (定时器) |
|
|
102
|
+
|
|
103
|
+
## 💡 使用示例
|
|
104
|
+
|
|
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
|
|
114
|
+
\`ds-markdown\` 是一个高性能的 React Markdown 打字动画组件
|
|
47
115
|
|
|
48
|
-
## 特性
|
|
116
|
+
## ✨ 特性
|
|
49
117
|
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
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
|
|
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={
|
|
134
|
+
<button onClick={handleStart}>开始演示</button>
|
|
135
|
+
|
|
136
|
+
{/* 思考过程 */}
|
|
69
137
|
<DsMarkdown
|
|
70
138
|
answerType="thinking"
|
|
71
|
-
interval={
|
|
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
|
-
{
|
|
81
|
-
|
|
149
|
+
{/* 回答内容 */}
|
|
150
|
+
{answerContent && (
|
|
151
|
+
<DsMarkdown answerType="answer" interval={10} timerType="requestAnimationFrame">
|
|
82
152
|
{answerContent}
|
|
83
153
|
</DsMarkdown>
|
|
84
154
|
)}
|
|
@@ -89,58 +159,226 @@ 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
|
-
|
|
95
|
-
使用方式:
|
|
96
|
-
`import { MarkdownCMD } from 'ds-markdown';`
|
|
164
|
+
### ⚡ 命令式用法 (流式场景)
|
|
97
165
|
|
|
98
|
-
|
|
166
|
+
适用于实时流式数据场景,减少组件重渲染,提升性能。
|
|
99
167
|
|
|
100
168
|
```tsx
|
|
101
|
-
import { useRef
|
|
169
|
+
import { useRef } from 'react';
|
|
102
170
|
import { MarkdownCMD } from 'ds-markdown';
|
|
103
171
|
import 'ds-markdown/style.css';
|
|
104
172
|
|
|
105
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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={
|
|
132
|
-
<MarkdownCMD
|
|
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
|
-
|
|
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
|
+
flushBuffer: (answerType?: AnswerType) => void;
|
|
226
|
+
}
|
|
138
227
|
```
|
|
139
228
|
|
|
140
|
-
|
|
229
|
+
| 方法 | 参数 | 说明 |
|
|
230
|
+
| ----------------- | ------------------------------------------- | ------------------------- |
|
|
231
|
+
| `push` | `(content: string, answerType: AnswerType)` | 添加内容并开始打字 |
|
|
232
|
+
| `clear` | - | 清空所有内容和状态 |
|
|
233
|
+
| `triggerWholeEnd` | - | 手动触发完成回调 |
|
|
234
|
+
| `flushBuffer` | `answerType?: AnswerType` | 强制刷新缓冲区内容 (新增) |
|
|
235
|
+
|
|
236
|
+
### 4. 类型安全
|
|
237
|
+
|
|
238
|
+
```tsx
|
|
239
|
+
import { MarkdownRef } from 'ds-markdown';
|
|
240
|
+
|
|
241
|
+
const ref = useRef<MarkdownRef>(null);
|
|
242
|
+
// 现在具有完整的类型提示和新增的 flushBuffer 方法
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 🎨 样式定制
|
|
246
|
+
|
|
247
|
+
```css
|
|
248
|
+
/* 自定义思考区域样式 */
|
|
249
|
+
.ds-markdown-thinking {
|
|
250
|
+
background: rgba(255, 193, 7, 0.1);
|
|
251
|
+
border-left: 3px solid #ffc107;
|
|
252
|
+
padding: 12px;
|
|
253
|
+
border-radius: 4px;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/* 自定义回答区域样式 */
|
|
257
|
+
.ds-markdown-answer {
|
|
258
|
+
color: #333;
|
|
259
|
+
line-height: 1.6;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* 自定义代码块样式 */
|
|
263
|
+
.ds-markdown pre {
|
|
264
|
+
background: #f8f9fa;
|
|
265
|
+
border-radius: 6px;
|
|
266
|
+
padding: 16px;
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## 🔧 最佳实践
|
|
271
|
+
|
|
272
|
+
### 1. 性能优化建议
|
|
273
|
+
|
|
274
|
+
```tsx
|
|
275
|
+
// ✅ 推荐:使用 requestAnimationFrame + 适中的 interval
|
|
276
|
+
<DsMarkdown
|
|
277
|
+
timerType="requestAnimationFrame"
|
|
278
|
+
interval={15} // 15-30ms 为最佳体验
|
|
279
|
+
/>
|
|
280
|
+
|
|
281
|
+
// ❌ 避免:过小的 interval 值
|
|
282
|
+
<DsMarkdown interval={1} /> // 可能导致性能问题
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 2. 流式数据处理
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
// ✅ 推荐:使用命令式 API
|
|
289
|
+
const ref = useRef();
|
|
290
|
+
useEffect(() => {
|
|
291
|
+
// 实时接收数据时使用 push 方法
|
|
292
|
+
ref.current?.push(newChunk, 'answer');
|
|
293
|
+
}, [newChunk]);
|
|
294
|
+
|
|
295
|
+
// ❌ 避免:频繁更新 children prop
|
|
296
|
+
const [content, setContent] = useState('');
|
|
297
|
+
// 每次更新都会重新解析整个内容
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 3. 流式 Markdown 语法处理
|
|
301
|
+
|
|
302
|
+
**问题场景**: 流式输出时,不完整的 Markdown 语法会导致渲染错误
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
// 🚨 问题示例:逐字符推送导致的解析错误
|
|
306
|
+
push('#'); // "# "
|
|
307
|
+
push(' '); // "# "
|
|
308
|
+
push('标题'); // "# 标题"
|
|
309
|
+
push('\n'); // "# 标题\n"
|
|
310
|
+
push('1'); // "# 标题\n1" ← 这里会被误解析
|
|
311
|
+
push('.'); // "# 标题\n1." ← 形成正确的列表
|
|
312
|
+
push(' 列表项'); // "# 标题\n1. 列表项"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
**✅ 解决方案**: 组件内置**同步智能缓冲机制**
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
// 组件会实时检测并缓冲不完整的语法
|
|
319
|
+
const streamingDemo = async () => {
|
|
320
|
+
const chunks = ['#', ' ', '使用', '技能', '\n', '1', '.', ' ', '技能1', '\n', '2', '.', ' 技能2'];
|
|
321
|
+
|
|
322
|
+
for (const chunk of chunks) {
|
|
323
|
+
markdownRef.current?.push(chunk, 'answer');
|
|
324
|
+
// 无需延迟,组件内部智能处理
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// 手动刷新剩余缓冲内容 (可选)
|
|
328
|
+
markdownRef.current?.flushBuffer();
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// 组件会同步智能处理:
|
|
332
|
+
// 1. 实时检测 "# 使用技能\n1" 语法不完整
|
|
333
|
+
// 2. 智能缓冲,等待更多字符
|
|
334
|
+
// 3. 收到 "." 形成 "1." 后立即处理
|
|
335
|
+
// 4. 零延迟,纯同步处理
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**同步缓冲机制特性**:
|
|
339
|
+
|
|
340
|
+
- ⚡ **零延迟**: 无 setTimeout,纯同步实时处理
|
|
341
|
+
- 🧠 **智能边界**: 基于 Markdown 语法规则的边界检测
|
|
342
|
+
- 🔄 **实时分割**: 遇到完整语法立即处理,不完整时智能缓冲
|
|
343
|
+
- 🛡️ **安全保障**: 提供 `flushBuffer()` 方法处理剩余内容
|
|
344
|
+
|
|
345
|
+
**支持的语法检测**:
|
|
346
|
+
|
|
347
|
+
````typescript
|
|
348
|
+
// 完整语法模式 (立即处理)
|
|
349
|
+
'## 标题'; // 完整标题
|
|
350
|
+
'1. 列表项'; // 完整列表项
|
|
351
|
+
'- 项目'; // 完整无序列表
|
|
352
|
+
'> 引用内容'; // 完整引用
|
|
353
|
+
'```javascript'; // 代码块开始
|
|
354
|
+
'```'; // 代码块结束
|
|
355
|
+
'内容以换行结尾\n'; // 换行边界
|
|
356
|
+
|
|
357
|
+
// 不完整语法 (智能缓冲)
|
|
358
|
+
'##'; // 只有标题符号
|
|
359
|
+
'1'; // 只有数字
|
|
360
|
+
'```java'; // 可能的代码块开始
|
|
361
|
+
````
|
|
362
|
+
|
|
363
|
+
**新增 API**:
|
|
364
|
+
|
|
365
|
+
| 方法 | 参数 | 说明 |
|
|
366
|
+
| ------------- | ------------------------- | ------------------ |
|
|
367
|
+
| `flushBuffer` | `answerType?: AnswerType` | 强制刷新缓冲区内容 |
|
|
368
|
+
|
|
369
|
+
## 🌐 兼容性
|
|
370
|
+
|
|
371
|
+
- **React**: 16.8.0+
|
|
372
|
+
- **TypeScript**: 4.0+
|
|
373
|
+
- **浏览器**: Chrome 60+, Firefox 55+, Safari 12+
|
|
374
|
+
- **Node.js**: 14.0+
|
|
375
|
+
|
|
376
|
+
## 📄 License
|
|
141
377
|
|
|
142
|
-
|
|
378
|
+
MIT © [onshinpei](https://github.com/onshinpei)
|
|
143
379
|
|
|
144
|
-
|
|
380
|
+
---
|
|
145
381
|
|
|
146
|
-
|
|
382
|
+
<div align="center">
|
|
383
|
+
<strong>如果这个项目对你有帮助,请给个 ⭐️ Star 支持一下!</strong>
|
|
384
|
+
</div>
|
|
@@ -3,6 +3,7 @@ export interface MarkdownRef {
|
|
|
3
3
|
push: (content: string, answerType: AnswerType) => void;
|
|
4
4
|
clear: () => void;
|
|
5
5
|
triggerWholeEnd: () => void;
|
|
6
|
+
flushBuffer: (answerType?: AnswerType) => void;
|
|
6
7
|
}
|
|
7
8
|
declare const MarkdownCMD: import("react").ForwardRefExoticComponent<MarkdownProps & import("react").RefAttributes<MarkdownRef>>;
|
|
8
9
|
export default MarkdownCMD;
|