ds-markdown 0.0.10-beta.1 → 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 +234 -67
- package/dist/cjs/MarkdownCMD/index.js +183 -225
- package/dist/cjs/MarkdownCMD/index.js.map +1 -1
- package/dist/cjs/defined.d.ts +20 -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/Tokenizer.d.ts +11 -0
- package/dist/cjs/utils/Tokenizer.js +26 -4
- package/dist/cjs/utils/Tokenizer.js.map +1 -1
- package/dist/cjs/utils/compiler.js +5 -1
- package/dist/cjs/utils/compiler.js.map +1 -1
- package/dist/cjs/utils/methods/deepClone.d.ts +1 -0
- package/dist/cjs/utils/methods/deepClone.js +7 -0
- package/dist/cjs/utils/methods/deepClone.js.map +1 -0
- package/dist/cjs/utils/rule.js +2 -1
- package/dist/cjs/utils/rule.js.map +1 -1
- package/dist/esm/MarkdownCMD/index.js +184 -226
- package/dist/esm/MarkdownCMD/index.js.map +1 -1
- package/dist/esm/defined.d.ts +20 -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/Tokenizer.d.ts +11 -0
- package/dist/esm/utils/Tokenizer.js +24 -3
- package/dist/esm/utils/Tokenizer.js.map +1 -1
- package/dist/esm/utils/compiler.js +6 -2
- package/dist/esm/utils/compiler.js.map +1 -1
- package/dist/esm/utils/methods/deepClone.d.ts +1 -0
- package/dist/esm/utils/methods/deepClone.js +4 -0
- package/dist/esm/utils/methods/deepClone.js.map +1 -0
- package/dist/esm/utils/rule.js +2 -1
- package/dist/esm/utils/rule.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef,
|
|
2
|
+
import { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import HighReactMarkdown from '../components/HighReactMarkdown/index.js';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
import { compiler } from '../utils/compiler.js';
|
|
6
6
|
import { __DEV__ } from '../constant.js';
|
|
7
|
-
|
|
7
|
+
import deepClone from '../utils/methods/deepClone.js';
|
|
8
|
+
import { useTypingTask } from '../hooks/useTypingTask.js';
|
|
9
|
+
const MarkdownCMD = forwardRef(({ interval = 30, onEnd, onStart, onTypedChar, timerType = 'requestAnimationFrame' }, ref) => {
|
|
8
10
|
/** 当前需要打字的内容 */
|
|
9
11
|
const charsRef = useRef([]);
|
|
10
12
|
/**
|
|
@@ -12,23 +14,6 @@ const MarkdownCMD = forwardRef(({ interval = 30, isClosePrettyTyped = false, onE
|
|
|
12
14
|
* 如果打字已经完全结束,则不会再触发打字效果
|
|
13
15
|
*/
|
|
14
16
|
const isWholeTypedEndRef = useRef(false);
|
|
15
|
-
/** 已经打过的字 */
|
|
16
|
-
const typedCharsRef = useRef(undefined);
|
|
17
|
-
/** 是否卸载 */
|
|
18
|
-
const isUnmountRef = useRef(false);
|
|
19
|
-
/** 是否正在打字 */
|
|
20
|
-
const isTypedRef = useRef(false);
|
|
21
|
-
/** 打字结束回调, */
|
|
22
|
-
const onEndRef = useRef(onEnd);
|
|
23
|
-
onEndRef.current = onEnd;
|
|
24
|
-
/** 打字开始回调 */
|
|
25
|
-
const onStartRef = useRef(onStart);
|
|
26
|
-
onStartRef.current = onStart;
|
|
27
|
-
/** 打字过程中回调 */
|
|
28
|
-
const onTypedCharRef = useRef(onTypedChar);
|
|
29
|
-
onTypedCharRef.current = onTypedChar;
|
|
30
|
-
/** 打字定时器 */
|
|
31
|
-
const timerRef = useRef(null);
|
|
32
17
|
/**
|
|
33
18
|
* 稳定段落
|
|
34
19
|
* 稳定段落是已经打过字,并且不会再变化的段落
|
|
@@ -38,211 +23,122 @@ const MarkdownCMD = forwardRef(({ interval = 30, isClosePrettyTyped = false, onE
|
|
|
38
23
|
const [currentSegment, setCurrentSegment] = useState(undefined);
|
|
39
24
|
/** 当前段落引用 */
|
|
40
25
|
const currentParagraphRef = useRef(undefined);
|
|
41
|
-
currentParagraphRef.current = currentSegment;
|
|
42
|
-
/** 清除打字定时器 */
|
|
43
|
-
const clearTimer = () => {
|
|
44
|
-
if (timerRef.current) {
|
|
45
|
-
clearTimeout(timerRef.current);
|
|
46
|
-
timerRef.current = null;
|
|
47
|
-
}
|
|
48
|
-
isTypedRef.current = false;
|
|
49
|
-
};
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
isUnmountRef.current = false;
|
|
52
|
-
return () => {
|
|
53
|
-
isUnmountRef.current = true;
|
|
54
|
-
};
|
|
55
|
-
}, []);
|
|
56
|
-
/** 思考段落 */
|
|
57
|
-
const thinkingParagraphs = useMemo(() => stableSegments.filter((paragraph) => paragraph.answerType === 'thinking'), [stableSegments]);
|
|
58
|
-
/** 回答段落 */
|
|
59
|
-
const answerParagraphs = useMemo(() => stableSegments.filter((paragraph) => paragraph.answerType === 'answer'), [stableSegments]);
|
|
60
|
-
/**
|
|
61
|
-
* 记录打过的字
|
|
62
|
-
* @param char 当前字符
|
|
63
|
-
* @returns
|
|
64
|
-
*/
|
|
65
|
-
const recordTypedChars = (char) => {
|
|
66
|
-
let prevStr = '';
|
|
67
|
-
if (!typedCharsRef.current || typedCharsRef.current.answerType !== char.answerType) {
|
|
68
|
-
typedCharsRef.current = {
|
|
69
|
-
typedContent: char.content,
|
|
70
|
-
answerType: char.answerType,
|
|
71
|
-
prevStr: '',
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
prevStr = typedCharsRef.current.typedContent;
|
|
76
|
-
typedCharsRef.current.typedContent += char.content;
|
|
77
|
-
typedCharsRef.current.prevStr = prevStr;
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
prevStr,
|
|
81
|
-
nextStr: typedCharsRef.current?.typedContent || '',
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* 触发打字开始回调
|
|
86
|
-
* @param char 当前字符
|
|
87
|
-
*/
|
|
88
|
-
const triggerOnStart = (char) => {
|
|
89
|
-
const onStartFn = onStartRef.current;
|
|
90
|
-
if (!onStartFn) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const { prevStr } = recordTypedChars(char);
|
|
94
|
-
onStartRef.current?.({
|
|
95
|
-
currentIndex: prevStr.length,
|
|
96
|
-
currentChar: char.content,
|
|
97
|
-
answerType: char.answerType,
|
|
98
|
-
prevStr,
|
|
99
|
-
});
|
|
100
|
-
};
|
|
101
|
-
/**
|
|
102
|
-
* 触发打字结束回调
|
|
103
|
-
*/
|
|
104
|
-
const triggerOnEnd = () => {
|
|
105
|
-
const onEndFn = onEndRef.current;
|
|
106
|
-
if (!onEndFn) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
onEndFn({
|
|
110
|
-
str: typedCharsRef.current?.typedContent,
|
|
111
|
-
answerType: typedCharsRef.current?.answerType,
|
|
112
|
-
});
|
|
113
|
-
};
|
|
26
|
+
// currentParagraphRef.current = currentSegment;
|
|
114
27
|
/**
|
|
115
|
-
*
|
|
116
|
-
* @param char 当前字符
|
|
117
|
-
* @param isStartPoint 是否是开始打字(第一个字)
|
|
28
|
+
* 处理字符显示逻辑
|
|
118
29
|
*/
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
prevStr: typedCharsRef.current?.prevStr || '',
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
/** 开始打字任务 */
|
|
135
|
-
const startTypedTask = () => {
|
|
136
|
-
if (isTypedRef.current) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const chars = charsRef.current;
|
|
140
|
-
/** 停止打字 */
|
|
141
|
-
const stopTyped = () => {
|
|
142
|
-
isTypedRef.current = false;
|
|
143
|
-
if (timerRef.current) {
|
|
144
|
-
clearTimeout(timerRef.current);
|
|
145
|
-
timerRef.current = null;
|
|
146
|
-
}
|
|
147
|
-
triggerOnEnd();
|
|
148
|
-
};
|
|
149
|
-
/** 打下一个字 */
|
|
150
|
-
const nextTyped = () => {
|
|
151
|
-
if (chars.length === 0) {
|
|
152
|
-
stopTyped();
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
timerRef.current = setTimeout(startTyped, interval);
|
|
156
|
-
};
|
|
157
|
-
/**
|
|
158
|
-
* 开始打字
|
|
159
|
-
* @param isStartPoint 是否是开始打字
|
|
160
|
-
*/
|
|
161
|
-
function startTyped(isStartPoint = false) {
|
|
162
|
-
if (isUnmountRef.current) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
isTypedRef.current = true;
|
|
166
|
-
const char = chars.shift();
|
|
167
|
-
if (char === undefined) {
|
|
168
|
-
stopTyped();
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
if (isStartPoint) {
|
|
172
|
-
triggerOnStart(char);
|
|
173
|
-
triggerOnTypedChar(char, isStartPoint);
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
triggerOnTypedChar(char);
|
|
177
|
-
}
|
|
178
|
-
const currentSegment = currentParagraphRef.current;
|
|
179
|
-
/** 如果碰到 space 则需要处理成两个段落 */
|
|
180
|
-
if (char.contentType === 'space') {
|
|
181
|
-
if (currentSegment) {
|
|
182
|
-
setStableSegments((prev) => {
|
|
183
|
-
const newParagraphs = [...prev];
|
|
184
|
-
if (currentSegment) {
|
|
185
|
-
newParagraphs.push({ ...currentSegment, isTyped: false });
|
|
186
|
-
}
|
|
187
|
-
newParagraphs.push({
|
|
188
|
-
content: '',
|
|
189
|
-
isTyped: false,
|
|
190
|
-
type: 'br',
|
|
191
|
-
answerType: char.answerType,
|
|
192
|
-
});
|
|
193
|
-
return newParagraphs;
|
|
194
|
-
});
|
|
195
|
-
setCurrentSegment(undefined);
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
setStableSegments((prev) => {
|
|
199
|
-
const newParagraphs = [...prev];
|
|
30
|
+
const processCharDisplay = (char) => {
|
|
31
|
+
const currentSegment = currentParagraphRef.current;
|
|
32
|
+
/** 如果碰到 space,和split_segment 则需要处理成两个段落 */
|
|
33
|
+
if (char.contentType === 'space' || char.contentType === 'split_segment') {
|
|
34
|
+
if (currentSegment) {
|
|
35
|
+
setStableSegments((prev) => {
|
|
36
|
+
const newParagraphs = [...prev];
|
|
37
|
+
// 放入到稳定队列
|
|
38
|
+
if (currentSegment) {
|
|
39
|
+
newParagraphs.push({ ...currentSegment, isTyped: false });
|
|
40
|
+
}
|
|
41
|
+
if (char.contentType === 'space') {
|
|
200
42
|
newParagraphs.push({
|
|
201
43
|
content: '',
|
|
202
44
|
isTyped: false,
|
|
203
45
|
type: 'br',
|
|
204
46
|
answerType: char.answerType,
|
|
47
|
+
tokensReference: {
|
|
48
|
+
[char.tokenId]: {
|
|
49
|
+
startIndex: 0,
|
|
50
|
+
raw: char.content,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
205
53
|
});
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
// 处理当前段落
|
|
213
|
-
let _currentParagraph = currentSegment;
|
|
214
|
-
const newCurrentParagraph = {
|
|
215
|
-
content: '',
|
|
216
|
-
isTyped: false,
|
|
217
|
-
type: 'text',
|
|
218
|
-
answerType: char.answerType,
|
|
219
|
-
};
|
|
220
|
-
if (!_currentParagraph) {
|
|
221
|
-
// 如果当前没有段落,则直接设置为当前段落
|
|
222
|
-
_currentParagraph = newCurrentParagraph;
|
|
54
|
+
}
|
|
55
|
+
return newParagraphs;
|
|
56
|
+
});
|
|
57
|
+
setCurrentSegment(() => undefined);
|
|
58
|
+
currentParagraphRef.current = undefined;
|
|
223
59
|
}
|
|
224
|
-
else
|
|
225
|
-
// 如果当前段落和当前字符的回答类型不一致,则需要处理成两个段落
|
|
60
|
+
else {
|
|
226
61
|
setStableSegments((prev) => {
|
|
227
62
|
const newParagraphs = [...prev];
|
|
228
|
-
newParagraphs.push({
|
|
63
|
+
newParagraphs.push({
|
|
64
|
+
content: '',
|
|
65
|
+
isTyped: false,
|
|
66
|
+
type: 'br',
|
|
67
|
+
answerType: char.answerType,
|
|
68
|
+
tokensReference: {
|
|
69
|
+
[char.tokenId]: {
|
|
70
|
+
startIndex: 0,
|
|
71
|
+
raw: char.content,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
});
|
|
229
75
|
return newParagraphs;
|
|
230
76
|
});
|
|
231
|
-
_currentParagraph = newCurrentParagraph;
|
|
232
|
-
setCurrentSegment(_currentParagraph);
|
|
233
77
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// 处理当前段落
|
|
81
|
+
const newCurrentParagraph = {
|
|
82
|
+
content: '',
|
|
83
|
+
isTyped: false,
|
|
84
|
+
type: 'text',
|
|
85
|
+
answerType: char.answerType,
|
|
86
|
+
tokensReference: {},
|
|
87
|
+
};
|
|
88
|
+
let _currentParagraph = currentSegment;
|
|
89
|
+
if (!_currentParagraph) {
|
|
90
|
+
// 如果当前没有段落,则直接设置为新当前段落
|
|
91
|
+
_currentParagraph = newCurrentParagraph;
|
|
92
|
+
}
|
|
93
|
+
else if (currentSegment && currentSegment?.answerType !== char.answerType) {
|
|
94
|
+
// 如果当前段落和当前字符的回答类型不一致,则需要处理成两个段落
|
|
95
|
+
setStableSegments((prev) => {
|
|
96
|
+
const newParagraphs = [...prev];
|
|
97
|
+
newParagraphs.push({ ...currentSegment, isTyped: false });
|
|
98
|
+
return newParagraphs;
|
|
240
99
|
});
|
|
241
|
-
|
|
100
|
+
_currentParagraph = newCurrentParagraph;
|
|
242
101
|
}
|
|
243
|
-
|
|
102
|
+
const tokensReference = deepClone(_currentParagraph.tokensReference);
|
|
103
|
+
if (tokensReference[char.tokenId]) {
|
|
104
|
+
tokensReference[char.tokenId].raw += char.content;
|
|
105
|
+
tokensReference[char.tokenId].startIndex = currentSegment?.content?.length || 0;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
tokensReference[char.tokenId] = {
|
|
109
|
+
startIndex: currentSegment?.content?.length || 0,
|
|
110
|
+
raw: char.content,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const newCurrentSegment = {
|
|
114
|
+
..._currentParagraph,
|
|
115
|
+
tokensReference,
|
|
116
|
+
content: (currentSegment?.content || '') + char.content,
|
|
117
|
+
isTyped: true,
|
|
118
|
+
};
|
|
119
|
+
currentParagraphRef.current = newCurrentSegment;
|
|
120
|
+
setCurrentSegment(() => newCurrentSegment);
|
|
244
121
|
};
|
|
245
|
-
|
|
122
|
+
/** 思考段落 */
|
|
123
|
+
const thinkingParagraphs = useMemo(() => stableSegments.filter((paragraph) => paragraph.answerType === 'thinking'), [stableSegments]);
|
|
124
|
+
/** 回答段落 */
|
|
125
|
+
const answerParagraphs = useMemo(() => stableSegments.filter((paragraph) => paragraph.answerType === 'answer'), [stableSegments]);
|
|
126
|
+
// 使用新的打字任务 hook
|
|
127
|
+
const typingTask = useTypingTask({
|
|
128
|
+
timerType,
|
|
129
|
+
interval,
|
|
130
|
+
charsRef,
|
|
131
|
+
onEnd,
|
|
132
|
+
onStart,
|
|
133
|
+
onTypedChar,
|
|
134
|
+
processCharDisplay,
|
|
135
|
+
});
|
|
136
|
+
const lastSegmentRawRef = useRef({
|
|
137
|
+
thinking: '',
|
|
138
|
+
answer: '',
|
|
139
|
+
thinkingReference: null,
|
|
140
|
+
answerReference: null,
|
|
141
|
+
});
|
|
246
142
|
useImperativeHandle(ref, () => ({
|
|
247
143
|
/**
|
|
248
144
|
* 添加内容
|
|
@@ -250,55 +146,117 @@ const MarkdownCMD = forwardRef(({ interval = 30, isClosePrettyTyped = false, onE
|
|
|
250
146
|
* @param answerType 回答类型 {AnswerType}
|
|
251
147
|
*/
|
|
252
148
|
push: (content, answerType) => {
|
|
149
|
+
if (content.length === 0) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const lastSegmentReference = lastSegmentRawRef.current[`${answerType}Reference`];
|
|
253
153
|
if (isWholeTypedEndRef.current) {
|
|
254
154
|
if (__DEV__) {
|
|
255
155
|
console.warn('打字已经完全结束,不能再添加新的内容');
|
|
256
156
|
}
|
|
257
157
|
return;
|
|
258
158
|
}
|
|
259
|
-
|
|
260
|
-
|
|
159
|
+
let currentLastSegmentReference = null;
|
|
160
|
+
let currentLastSegmentRaw = '';
|
|
161
|
+
let lastSegmentRaw = '';
|
|
162
|
+
if (lastSegmentReference) {
|
|
163
|
+
lastSegmentRaw = lastSegmentReference.noTrimEndRaw || lastSegmentReference.raw;
|
|
164
|
+
currentLastSegmentRaw = lastSegmentRaw + content;
|
|
261
165
|
}
|
|
262
166
|
else {
|
|
263
|
-
|
|
167
|
+
currentLastSegmentRaw = content;
|
|
264
168
|
}
|
|
265
|
-
const tokens = compiler(
|
|
266
|
-
// 如果最后一个token是
|
|
267
|
-
if (tokens[tokens.length - 1].type === '
|
|
268
|
-
|
|
169
|
+
const tokens = compiler(currentLastSegmentRaw);
|
|
170
|
+
// 如果最后一个token是space,则把lastSegmentRaw设置为空
|
|
171
|
+
if (tokens[tokens.length - 1].type === 'space') {
|
|
172
|
+
currentLastSegmentReference = null;
|
|
269
173
|
}
|
|
270
174
|
else {
|
|
271
|
-
|
|
175
|
+
currentLastSegmentReference = tokens[tokens.length - 1];
|
|
272
176
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
177
|
+
const pushAndSplitSegment = (raw, currenIndex) => {
|
|
178
|
+
const currentToken = tokens[currenIndex];
|
|
179
|
+
if (currenIndex > 0) {
|
|
180
|
+
const prevToken = tokens[currenIndex - 1];
|
|
181
|
+
if (prevToken.type !== 'space' && currentToken.type !== 'space') {
|
|
182
|
+
charsRef.current.push({ content: '', answerType, contentType: 'split_segment', tokenId: currentToken.id });
|
|
183
|
+
}
|
|
276
184
|
}
|
|
277
|
-
|
|
278
|
-
|
|
185
|
+
charsRef.current.push(...raw.split('').map((char) => ({ content: char, answerType, contentType: 'segment', tokenId: currentToken.id })));
|
|
186
|
+
};
|
|
187
|
+
if (!lastSegmentReference) {
|
|
188
|
+
tokens.forEach((token, i) => {
|
|
189
|
+
if (token.type === 'space') {
|
|
190
|
+
charsRef.current.push({ content: token.raw, answerType, contentType: 'space', tokenId: token.id });
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
pushAndSplitSegment(token.raw, i);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
let str = '';
|
|
199
|
+
let firstSpaceIndex = -1;
|
|
200
|
+
let nextTokenIndex = lastSegmentRaw.length;
|
|
201
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
202
|
+
const token = tokens[i];
|
|
203
|
+
if (token.type === 'space') {
|
|
204
|
+
if (firstSpaceIndex === -1) {
|
|
205
|
+
firstSpaceIndex = str.length;
|
|
206
|
+
}
|
|
207
|
+
str += token.raw;
|
|
208
|
+
if (lastSegmentRaw.length > firstSpaceIndex) {
|
|
209
|
+
// 如果lastSegmentRaw的长度大于firstSpaceIndex,则需要将当前设置为 segment
|
|
210
|
+
charsRef.current.push(...token.raw.split('').map((char) => ({ content: char, answerType, contentType: 'segment', tokenId: token.id })));
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
charsRef.current.push({ content: token.raw, answerType, contentType: 'space', tokenId: token.id });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
str += token.noTrimEndRaw || token.raw;
|
|
218
|
+
const realRaw = str.slice(nextTokenIndex);
|
|
219
|
+
if (realRaw.length > 0) {
|
|
220
|
+
pushAndSplitSegment(realRaw, i);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
nextTokenIndex = str.length;
|
|
279
224
|
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
225
|
+
}
|
|
226
|
+
lastSegmentRawRef.current[`${answerType}Reference`] = currentLastSegmentReference;
|
|
227
|
+
if (!typingTask.isTyping()) {
|
|
228
|
+
typingTask.start();
|
|
283
229
|
}
|
|
284
230
|
},
|
|
285
231
|
/**
|
|
286
232
|
* 清除打字任务
|
|
287
233
|
*/
|
|
288
234
|
clear: () => {
|
|
289
|
-
|
|
235
|
+
typingTask.stop();
|
|
290
236
|
charsRef.current = [];
|
|
291
237
|
setStableSegments([]);
|
|
292
238
|
setCurrentSegment(undefined);
|
|
293
239
|
isWholeTypedEndRef.current = false;
|
|
240
|
+
currentParagraphRef.current = undefined;
|
|
241
|
+
typingTask.clear();
|
|
242
|
+
lastSegmentRawRef.current = {
|
|
243
|
+
thinking: '',
|
|
244
|
+
answer: '',
|
|
245
|
+
thinkingReference: null,
|
|
246
|
+
answerReference: null,
|
|
247
|
+
};
|
|
294
248
|
},
|
|
295
249
|
/**
|
|
296
250
|
* 主动触发打字结束
|
|
297
251
|
*/
|
|
298
252
|
triggerWholeEnd: () => {
|
|
299
253
|
isWholeTypedEndRef.current = true;
|
|
300
|
-
if (!
|
|
301
|
-
triggerOnEnd
|
|
254
|
+
if (!typingTask.isTyping()) {
|
|
255
|
+
// 这里需要手动触发结束回调,因为 hook 中的 triggerOnEnd 不能直接调用
|
|
256
|
+
onEnd?.({
|
|
257
|
+
str: undefined,
|
|
258
|
+
answerType: undefined,
|
|
259
|
+
});
|
|
302
260
|
}
|
|
303
261
|
},
|
|
304
262
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/MarkdownCMD/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/MarkdownCMD/index.tsx"],"names":[],"mappings":"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"}
|
package/dist/esm/defined.d.ts
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
* 回答类型,思考和回答
|
|
3
3
|
*/
|
|
4
4
|
export type AnswerType = 'answer' | 'thinking';
|
|
5
|
+
/**
|
|
6
|
+
* 字符接口
|
|
7
|
+
*/
|
|
8
|
+
export interface IChar {
|
|
9
|
+
content: string;
|
|
10
|
+
answerType: AnswerType;
|
|
11
|
+
/**
|
|
12
|
+
* split_segment 两个连续的段落,需要做分割
|
|
13
|
+
*/
|
|
14
|
+
contentType: 'space' | 'segment' | 'split_segment';
|
|
15
|
+
tokenId: number;
|
|
16
|
+
}
|
|
5
17
|
/**
|
|
6
18
|
* 段落类型
|
|
7
19
|
* 段落类型为br时,表示换行
|
|
@@ -16,8 +28,16 @@ export interface IParagraph {
|
|
|
16
28
|
type: 'br' | 'text';
|
|
17
29
|
/** 回答类型 */
|
|
18
30
|
answerType: AnswerType;
|
|
31
|
+
/** token 参考 */
|
|
32
|
+
tokensReference: Record<string, ITokensReference>;
|
|
33
|
+
}
|
|
34
|
+
export interface ITokensReference {
|
|
35
|
+
startIndex: number;
|
|
36
|
+
raw: string;
|
|
19
37
|
}
|
|
20
38
|
export interface MarkdownProps {
|
|
39
|
+
/** 计时类型: 支持setTimeout和requestAnimationFrame */
|
|
40
|
+
timerType?: 'setTimeout' | 'requestAnimationFrame';
|
|
21
41
|
/** 打字机效果间隔时间 */
|
|
22
42
|
interval: number;
|
|
23
43
|
/** 是否关闭匀速打字机效果 */
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AnswerType, IChar, MarkdownProps } from '../defined.js';
|
|
2
|
+
interface UseTypingTaskOptions {
|
|
3
|
+
timerType: MarkdownProps['timerType'];
|
|
4
|
+
interval: number;
|
|
5
|
+
charsRef: React.MutableRefObject<IChar[]>;
|
|
6
|
+
onEnd?: (data?: {
|
|
7
|
+
str?: string;
|
|
8
|
+
answerType?: AnswerType;
|
|
9
|
+
}) => void;
|
|
10
|
+
onStart?: (data?: {
|
|
11
|
+
currentIndex: number;
|
|
12
|
+
currentChar: string;
|
|
13
|
+
answerType: AnswerType;
|
|
14
|
+
prevStr: string;
|
|
15
|
+
}) => void;
|
|
16
|
+
onTypedChar?: (data?: {
|
|
17
|
+
currentIndex: number;
|
|
18
|
+
currentChar: string;
|
|
19
|
+
answerType: AnswerType;
|
|
20
|
+
prevStr: string;
|
|
21
|
+
}) => void;
|
|
22
|
+
processCharDisplay: (char: IChar) => void;
|
|
23
|
+
}
|
|
24
|
+
export interface TypingTaskController {
|
|
25
|
+
start: () => void;
|
|
26
|
+
stop: () => void;
|
|
27
|
+
clear: () => void;
|
|
28
|
+
isTyping: () => boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare const useTypingTask: (options: UseTypingTaskOptions) => TypingTaskController;
|
|
31
|
+
export {};
|