@will1123/lx-ui-utils 1.0.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 +234 -0
- package/dist/dist/index.esm.js +618 -0
- package/dist/dist/index.esm.min.js +431 -0
- package/dist/dist/index.esm.min.js.map +1 -0
- package/dist/dist/index.umd.js +622 -0
- package/dist/dist/index.umd.min.js +14 -0
- package/dist/dist/index.umd.min.js.map +1 -0
- package/dist/es/index.js +15 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/markdown.js +286 -0
- package/dist/es/markdown.js.map +1 -0
- package/dist/es/sse.js +186 -0
- package/dist/es/sse.js.map +1 -0
- package/dist/es/thinking.js +153 -0
- package/dist/es/thinking.js.map +1 -0
- package/dist/lib/index.js +15 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/markdown.js +286 -0
- package/dist/lib/markdown.js.map +1 -0
- package/dist/lib/sse.js +186 -0
- package/dist/lib/sse.js.map +1 -0
- package/dist/lib/thinking.js +153 -0
- package/dist/lib/thinking.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/markdown.d.ts +115 -0
- package/dist/types/markdown.d.ts.map +1 -0
- package/dist/types/sse.d.ts +70 -0
- package/dist/types/sse.d.ts.map +1 -0
- package/dist/types/thinking.d.ts +64 -0
- package/dist/types/thinking.d.ts.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
var y = Object.defineProperty;
|
|
2
|
+
var b = Object.getOwnPropertySymbols;
|
|
3
|
+
var R = Object.prototype.hasOwnProperty, _ = Object.prototype.propertyIsEnumerable;
|
|
4
|
+
var B = (i, t, e) => t in i ? y(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e, C = (i, t) => {
|
|
5
|
+
for (var e in t || (t = {}))
|
|
6
|
+
R.call(t, e) && B(i, e, t[e]);
|
|
7
|
+
if (b)
|
|
8
|
+
for (var e of b(t))
|
|
9
|
+
_.call(t, e) && B(i, e, t[e]);
|
|
10
|
+
return i;
|
|
11
|
+
};
|
|
12
|
+
var w = (i, t, e) => new Promise((n, s) => {
|
|
13
|
+
var r = (a) => {
|
|
14
|
+
try {
|
|
15
|
+
o(e.next(a));
|
|
16
|
+
} catch (c) {
|
|
17
|
+
s(c);
|
|
18
|
+
}
|
|
19
|
+
}, h = (a) => {
|
|
20
|
+
try {
|
|
21
|
+
o(e.throw(a));
|
|
22
|
+
} catch (c) {
|
|
23
|
+
s(c);
|
|
24
|
+
}
|
|
25
|
+
}, o = (a) => a.done ? n(a.value) : Promise.resolve(a.value).then(r, h);
|
|
26
|
+
o((e = e.apply(i, t)).next());
|
|
27
|
+
});
|
|
28
|
+
class O {
|
|
29
|
+
constructor() {
|
|
30
|
+
this.controller = null, this.eventSource = null, this.timeoutTimer = null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 发起 SSE 请求
|
|
34
|
+
*/
|
|
35
|
+
request(t, e) {
|
|
36
|
+
return w(this, null, function* () {
|
|
37
|
+
var a, c, l, u, p;
|
|
38
|
+
const { url: n, method: s = "GET", headers: r = {}, body: h, timeout: o = 3e4 } = t;
|
|
39
|
+
this.controller = new AbortController();
|
|
40
|
+
try {
|
|
41
|
+
o > 0 && (this.timeoutTimer = setTimeout(() => {
|
|
42
|
+
var m;
|
|
43
|
+
this.close(), (m = e.onError) == null || m.call(e, new Error(`Request timeout after ${o}ms`));
|
|
44
|
+
}, o));
|
|
45
|
+
const f = yield fetch(n, {
|
|
46
|
+
method: s,
|
|
47
|
+
headers: C({
|
|
48
|
+
"Content-Type": "application/json"
|
|
49
|
+
}, r),
|
|
50
|
+
body: s === "POST" ? JSON.stringify(h) : void 0,
|
|
51
|
+
signal: this.controller.signal
|
|
52
|
+
});
|
|
53
|
+
if (this.timeoutTimer && (clearTimeout(this.timeoutTimer), this.timeoutTimer = null), !f.ok)
|
|
54
|
+
throw new Error(`HTTP error! status: ${f.status}`);
|
|
55
|
+
const g = f.headers.get("content-type");
|
|
56
|
+
if (!(g != null && g.includes("text/event-stream")))
|
|
57
|
+
throw new Error("Response is not a Server-Sent Events stream");
|
|
58
|
+
(a = e.onOpen) == null || a.call(e);
|
|
59
|
+
const k = (c = f.body) == null ? void 0 : c.getReader(), S = new TextDecoder();
|
|
60
|
+
let d = "";
|
|
61
|
+
if (!k)
|
|
62
|
+
throw new Error("Response body is null");
|
|
63
|
+
for (; ; ) {
|
|
64
|
+
const { done: m, value: E } = yield k.read();
|
|
65
|
+
if (m) {
|
|
66
|
+
(l = e.onClose) == null || l.call(e);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
d += S.decode(E, { stream: !0 });
|
|
70
|
+
const $ = d.split(`
|
|
71
|
+
|
|
72
|
+
`);
|
|
73
|
+
d = $.pop() || "";
|
|
74
|
+
for (const T of $)
|
|
75
|
+
if (T.trim()) {
|
|
76
|
+
const L = this.parseMessage(T);
|
|
77
|
+
(u = e.onMessage) == null || u.call(e, L);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} catch (f) {
|
|
81
|
+
this.timeoutTimer && (clearTimeout(this.timeoutTimer), this.timeoutTimer = null), this.controller && !this.controller.signal.aborted && ((p = e.onError) == null || p.call(e, f));
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 使用 EventSource 连接(仅支持 GET 请求)
|
|
87
|
+
*/
|
|
88
|
+
connect(t, e) {
|
|
89
|
+
this.eventSource = new EventSource(t), this.eventSource.onopen = () => {
|
|
90
|
+
var n;
|
|
91
|
+
(n = e.onOpen) == null || n.call(e);
|
|
92
|
+
}, this.eventSource.onmessage = (n) => {
|
|
93
|
+
var s;
|
|
94
|
+
(s = e.onMessage) == null || s.call(e, {
|
|
95
|
+
data: n.data,
|
|
96
|
+
event: n.type
|
|
97
|
+
});
|
|
98
|
+
}, this.eventSource.onerror = (n) => {
|
|
99
|
+
var s;
|
|
100
|
+
(s = e.onError) == null || s.call(e, new Error("EventSource error")), this.close();
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 解析 SSE 消息
|
|
105
|
+
*/
|
|
106
|
+
parseMessage(t) {
|
|
107
|
+
const e = {
|
|
108
|
+
data: ""
|
|
109
|
+
}, n = t.split(`
|
|
110
|
+
`);
|
|
111
|
+
for (const s of n)
|
|
112
|
+
s.startsWith("data: ") ? e.data = s.slice(6) : s.startsWith("event: ") ? e.event = s.slice(7) : s.startsWith("id: ") ? e.id = s.slice(4) : s.startsWith("retry: ") && (e.retry = parseInt(s.slice(7)));
|
|
113
|
+
return e;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 关闭连接
|
|
117
|
+
*/
|
|
118
|
+
close() {
|
|
119
|
+
this.controller && (this.controller.abort(), this.controller = null), this.eventSource && (this.eventSource.close(), this.eventSource = null), this.timeoutTimer && (clearTimeout(this.timeoutTimer), this.timeoutTimer = null);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function W(i, t) {
|
|
123
|
+
const e = new O();
|
|
124
|
+
return i.method === "POST" || i.timeout ? e.request(i, t) : e.connect(i.url, t), e;
|
|
125
|
+
}
|
|
126
|
+
function j(i, t = {}) {
|
|
127
|
+
const { tagName: e = "think", includeTags: n = !1, removeRest: s = !1 } = t, r = `<${e}>`, h = `</${e}>`, o = i.indexOf(r), a = i.indexOf(h);
|
|
128
|
+
if (o === -1 || a === -1)
|
|
129
|
+
return {
|
|
130
|
+
thinking: "",
|
|
131
|
+
rest: i,
|
|
132
|
+
hasThinking: !1
|
|
133
|
+
};
|
|
134
|
+
const c = o + r.length, l = a, u = i.slice(c, l), p = i.slice(0, o), f = i.slice(a + h.length), g = p + f;
|
|
135
|
+
return {
|
|
136
|
+
thinking: n ? `${r}${u}${h}` : u,
|
|
137
|
+
rest: s ? "" : g,
|
|
138
|
+
hasThinking: !0
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
class M {
|
|
142
|
+
constructor(t = {}) {
|
|
143
|
+
this.isComplete = !1, this.config = {
|
|
144
|
+
tagName: t.tagName || "think",
|
|
145
|
+
includeTags: t.includeTags || !1,
|
|
146
|
+
removeRest: t.removeRest || !1
|
|
147
|
+
}, this.state = {
|
|
148
|
+
inThinking: !1,
|
|
149
|
+
tagBuffer: "",
|
|
150
|
+
contentBuffer: "",
|
|
151
|
+
beforeContent: "",
|
|
152
|
+
afterContent: ""
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* 追加文本并提取思考内容
|
|
157
|
+
*/
|
|
158
|
+
append(t) {
|
|
159
|
+
if (this.isComplete)
|
|
160
|
+
return {
|
|
161
|
+
thinking: this.getThinking(),
|
|
162
|
+
rest: this.getRest(),
|
|
163
|
+
isComplete: !0
|
|
164
|
+
};
|
|
165
|
+
const { tagName: e } = this.config, n = `<${e}>`, s = `</${e}>`;
|
|
166
|
+
for (let r = 0; r < t.length; r++) {
|
|
167
|
+
const h = t[r];
|
|
168
|
+
if (this.state.inThinking) {
|
|
169
|
+
if (this.state.tagBuffer += h, this.state.tagBuffer.endsWith(s)) {
|
|
170
|
+
const o = this.state.tagBuffer.length - s.length;
|
|
171
|
+
this.state.contentBuffer += this.state.tagBuffer.slice(0, o), this.state.tagBuffer = "", this.state.inThinking = !1, this.isComplete = !0;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
if (this.state.tagBuffer.length > s.length) {
|
|
175
|
+
const o = this.state.tagBuffer.slice(0, 1);
|
|
176
|
+
this.state.contentBuffer += o, this.state.tagBuffer = this.state.tagBuffer.slice(1);
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
if (this.state.tagBuffer += h, this.state.tagBuffer.endsWith(n)) {
|
|
180
|
+
const o = this.state.tagBuffer.length - n.length;
|
|
181
|
+
this.state.beforeContent += this.state.tagBuffer.slice(0, o), this.state.tagBuffer = "", this.state.inThinking = !0;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
this.state.tagBuffer.length > n.length && (this.state.beforeContent += this.state.tagBuffer.slice(0, 1), this.state.tagBuffer = this.state.tagBuffer.slice(1));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return !this.state.inThinking && this.state.tagBuffer && (this.isComplete ? this.state.afterContent += this.state.tagBuffer : this.state.beforeContent += this.state.tagBuffer, this.state.tagBuffer = ""), {
|
|
188
|
+
thinking: this.getThinking(),
|
|
189
|
+
rest: this.getRest(),
|
|
190
|
+
isComplete: this.isComplete
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* 获取当前提取的思考内容
|
|
195
|
+
*/
|
|
196
|
+
getThinking() {
|
|
197
|
+
const { tagName: t, includeTags: e } = this.config, n = `<${t}>`, s = `</${t}>`, r = this.state.contentBuffer;
|
|
198
|
+
return e ? this.state.inThinking ? `${n}${r}` : `${n}${r}${s}` : r;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* 获取剩余内容
|
|
202
|
+
*/
|
|
203
|
+
getRest() {
|
|
204
|
+
const { removeRest: t } = this.config;
|
|
205
|
+
return t ? "" : this.state.beforeContent + this.state.afterContent;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* 是否已完成提取
|
|
209
|
+
*/
|
|
210
|
+
complete() {
|
|
211
|
+
return this.isComplete;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 重置提取器
|
|
215
|
+
*/
|
|
216
|
+
reset() {
|
|
217
|
+
this.state = {
|
|
218
|
+
inThinking: !1,
|
|
219
|
+
tagBuffer: "",
|
|
220
|
+
contentBuffer: "",
|
|
221
|
+
beforeContent: "",
|
|
222
|
+
afterContent: ""
|
|
223
|
+
}, this.isComplete = !1;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function H(i) {
|
|
227
|
+
return new M(i);
|
|
228
|
+
}
|
|
229
|
+
class v {
|
|
230
|
+
constructor(t = {}) {
|
|
231
|
+
this.config = {
|
|
232
|
+
highlight: t.highlight || !1,
|
|
233
|
+
highlightLanguages: t.highlightLanguages || {},
|
|
234
|
+
taskList: t.taskList !== !1,
|
|
235
|
+
table: t.table !== !1,
|
|
236
|
+
link: t.link !== !1,
|
|
237
|
+
image: t.image !== !1
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* 渲染 Markdown 为 HTML
|
|
242
|
+
*/
|
|
243
|
+
render(t) {
|
|
244
|
+
let e = t;
|
|
245
|
+
return e = this.escapeHtml(e), e = this.renderCodeBlocks(e), e = this.renderHeadings(e), e = this.renderEmphasis(e), this.config.taskList && (e = this.renderTaskLists(e)), e = this.renderUnorderedLists(e), e = this.renderOrderedLists(e), this.config.table && (e = this.renderTables(e)), this.config.link && (e = this.renderLinks(e)), this.config.image && (e = this.renderImages(e)), e = this.renderParagraphs(e), e = this.renderLineBreaks(e), e;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* 转义 HTML 特殊字符
|
|
249
|
+
*/
|
|
250
|
+
escapeHtml(t) {
|
|
251
|
+
return t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* 渲染代码块
|
|
255
|
+
*/
|
|
256
|
+
renderCodeBlocks(t) {
|
|
257
|
+
return t.replace(
|
|
258
|
+
/`{3}(\w*)\n([\s\S]*?)`{3}/g,
|
|
259
|
+
(e, n, s) => `<pre><code class="language-${n || "text"}">${s.trim()}</code></pre>`
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* 渲染标题
|
|
264
|
+
*/
|
|
265
|
+
renderHeadings(t) {
|
|
266
|
+
return t.replace(/^#{6}\s+(.+)$/gm, "<h6>$1</h6>").replace(/^#{5}\s+(.+)$/gm, "<h5>$1</h5>").replace(/^#{4}\s+(.+)$/gm, "<h4>$1</h4>").replace(/^#{3}\s+(.+)$/gm, "<h3>$1</h3>").replace(/^#{2}\s+(.+)$/gm, "<h2>$1</h2>").replace(/^#{1}\s+(.+)$/gm, "<h1>$1</h1>");
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* 渲染粗体和斜体
|
|
270
|
+
*/
|
|
271
|
+
renderEmphasis(t) {
|
|
272
|
+
return t = t.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>"), t = t.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>"), t = t.replace(/___(.+?)___/g, "<strong><em>$1</em></strong>"), t = t.replace(/__(.+?)__/g, "<strong>$1</strong>"), t = t.replace(/\*(.+?)\*/g, "<em>$1</em>"), t = t.replace(/_(.+?)_/g, "<em>$1</em>"), t;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* 渲染任务列表
|
|
276
|
+
*/
|
|
277
|
+
renderTaskLists(t) {
|
|
278
|
+
return t.replace(/^\s*-\s*\[x\]\s+(.+)$/gm, '<li class="task-checked"><input type="checkbox" checked disabled> $1</li>').replace(/^\s*-\s*\[\s*\]\s+(.+)$/gm, '<li><input type="checkbox" disabled> $1</li>');
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* 渲染无序列表
|
|
282
|
+
*/
|
|
283
|
+
renderUnorderedLists(t) {
|
|
284
|
+
const e = t.split(`
|
|
285
|
+
`), n = [], s = [];
|
|
286
|
+
for (const r of e) {
|
|
287
|
+
const h = r.match(/^(\s*)-\s+(.+)$/);
|
|
288
|
+
if (!h) {
|
|
289
|
+
for (; s.length > 0; )
|
|
290
|
+
n.push(s.pop() || "");
|
|
291
|
+
n.push(r);
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
const [o, a, c] = h, l = a.length;
|
|
295
|
+
for (; s.length > 0 && s.length < l / 2 + 1; )
|
|
296
|
+
n.push(s.pop() || "");
|
|
297
|
+
for (; s.length < l / 2 + 1; )
|
|
298
|
+
s.push("<ul>"), n.push("<ul>");
|
|
299
|
+
n.push(`<li>${c}</li>`);
|
|
300
|
+
}
|
|
301
|
+
for (; s.length > 0; )
|
|
302
|
+
n.push("</ul>"), s.pop();
|
|
303
|
+
return n.join(`
|
|
304
|
+
`);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* 渲染有序列表
|
|
308
|
+
*/
|
|
309
|
+
renderOrderedLists(t) {
|
|
310
|
+
const e = t.split(`
|
|
311
|
+
`), n = [];
|
|
312
|
+
let s = !1;
|
|
313
|
+
for (const r of e) {
|
|
314
|
+
const h = r.match(/^\s*\d+\.\s+(.+)$/);
|
|
315
|
+
if (!h) {
|
|
316
|
+
s && (n.push("</ol>"), s = !1), n.push(r);
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
const [o, a] = h;
|
|
320
|
+
s || (n.push("<ol>"), s = !0), n.push(`<li>${a}</li>`);
|
|
321
|
+
}
|
|
322
|
+
return s && n.push("</ol>"), n.join(`
|
|
323
|
+
`);
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* 渲染表格
|
|
327
|
+
*/
|
|
328
|
+
renderTables(t) {
|
|
329
|
+
const e = t.split(`
|
|
330
|
+
`), n = [];
|
|
331
|
+
let s = !1, r = !1;
|
|
332
|
+
for (let h = 0; h < e.length; h++) {
|
|
333
|
+
const o = e[h];
|
|
334
|
+
if (o.match(/^\|[\s\-:|]+\|$/))
|
|
335
|
+
continue;
|
|
336
|
+
const a = o.match(/^\|(.+)\|$/);
|
|
337
|
+
if (!a) {
|
|
338
|
+
s && (n.push("</table>"), s = !1, r = !1), n.push(o);
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
const c = a[1].split("|").map((l) => l.trim());
|
|
342
|
+
s || (n.push("<table>"), s = !0), r ? (n.push("<tr>"), c.forEach((l) => {
|
|
343
|
+
n.push(`<td>${l}</td>`);
|
|
344
|
+
}), n.push("</tr>")) : (n.push("<thead><tr>"), c.forEach((l) => {
|
|
345
|
+
n.push(`<th>${l}</th>`);
|
|
346
|
+
}), n.push("</tr></thead><tbody>"), r = !0);
|
|
347
|
+
}
|
|
348
|
+
return s && n.push("</tbody></table>"), n.join(`
|
|
349
|
+
`);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* 渲染链接
|
|
353
|
+
*/
|
|
354
|
+
renderLinks(t) {
|
|
355
|
+
return t.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>');
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* 渲染图片
|
|
359
|
+
*/
|
|
360
|
+
renderImages(t) {
|
|
361
|
+
return t.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" />');
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* 渲染段落
|
|
365
|
+
*/
|
|
366
|
+
renderParagraphs(t) {
|
|
367
|
+
const e = t.split(`
|
|
368
|
+
`), n = [];
|
|
369
|
+
let s = !1;
|
|
370
|
+
for (const r of e) {
|
|
371
|
+
if (!r.trim() || r.match(/^<(h|ul|ol|li|table|pre|div)/)) {
|
|
372
|
+
s && (n.push("</p>"), s = !1), n.push(r);
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
s || (n.push("<p>"), s = !0), n.push(r);
|
|
376
|
+
}
|
|
377
|
+
return s && n.push("</p>"), n.join(`
|
|
378
|
+
`);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* 渲染换行
|
|
382
|
+
*/
|
|
383
|
+
renderLineBreaks(t) {
|
|
384
|
+
return t.replace(/(<p>.*?<\/p>|<li>.*?<\/li>)/g, (e) => e.replace(/\n/g, `<br>
|
|
385
|
+
`));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function I(i, t) {
|
|
389
|
+
return new v(t).render(i);
|
|
390
|
+
}
|
|
391
|
+
class N {
|
|
392
|
+
constructor(t = {}) {
|
|
393
|
+
this.buffer = "", this.config = t, this.renderer = new v(t);
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* 追加文本并渲染
|
|
397
|
+
*/
|
|
398
|
+
append(t) {
|
|
399
|
+
this.buffer += t;
|
|
400
|
+
const e = this.renderer.render(this.buffer);
|
|
401
|
+
return this.config.onUpdate && this.config.onUpdate(e), e;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* 完成渲染
|
|
405
|
+
*/
|
|
406
|
+
complete() {
|
|
407
|
+
const t = this.renderer.render(this.buffer);
|
|
408
|
+
return this.config.onComplete && this.config.onComplete(t), t;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* 重置渲染器
|
|
412
|
+
*/
|
|
413
|
+
reset() {
|
|
414
|
+
this.buffer = "";
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
function U(i) {
|
|
418
|
+
return new N(i);
|
|
419
|
+
}
|
|
420
|
+
export {
|
|
421
|
+
v as MarkdownRenderer,
|
|
422
|
+
N as MarkdownStreamRenderer,
|
|
423
|
+
O as SSEConnection,
|
|
424
|
+
M as ThinkingStreamExtractor,
|
|
425
|
+
U as createMarkdownRenderer,
|
|
426
|
+
H as createThinkingExtractor,
|
|
427
|
+
j as extractThinking,
|
|
428
|
+
I as renderMarkdown,
|
|
429
|
+
W as sse
|
|
430
|
+
};
|
|
431
|
+
//# sourceMappingURL=index.esm.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.min.js","sources":["../../src/sse.ts","../../src/thinking.ts","../../src/markdown.ts"],"sourcesContent":["/**\r\n * SSE (Server-Sent Events) 请求配置\r\n */\r\nexport interface SSEConfig {\r\n /** 请求 URL */\r\n url: string\r\n /** 请求方法 */\r\n method?: 'GET' | 'POST'\r\n /** 请求头 */\r\n headers?: Record<string, string>\r\n /** 请求体(POST 请求时使用) */\r\n body?: any\r\n /** 请求超时时间(毫秒) */\r\n timeout?: number\r\n}\r\n\r\n/**\r\n * SSE 消息\r\n */\r\nexport interface SSEMessage {\r\n /** 数据内容 */\r\n data: string\r\n /** 事件类型 */\r\n event?: string\r\n /** ID */\r\n id?: string\r\n /** 重连时间(毫秒) */\r\n retry?: number\r\n}\r\n\r\n/**\r\n * SSE 事件处理器\r\n */\r\nexport interface SSEHandlers {\r\n /** 接收到消息时触发 */\r\n onMessage?: (message: SSEMessage) => void\r\n /** 连接打开时触发 */\r\n onOpen?: () => void\r\n /** 连接关闭时触发 */\r\n onClose?: () => void\r\n /** 发生错误时触发 */\r\n onError?: (error: Error) => void\r\n}\r\n\r\n/**\r\n * SSE 连接类\r\n */\r\nexport class SSEConnection {\r\n private controller: AbortController | null = null\r\n private eventSource: EventSource | null = null\r\n private timeoutTimer: NodeJS.Timeout | null = null\r\n\r\n /**\r\n * 发起 SSE 请求\r\n */\r\n async request(config: SSEConfig, handlers: SSEHandlers): Promise<void> {\r\n const { url, method = 'GET', headers = {}, body, timeout = 30000 } = config\r\n\r\n // 使用 AbortController 支持取消请求\r\n this.controller = new AbortController()\r\n\r\n try {\r\n // 设置超时\r\n if (timeout > 0) {\r\n this.timeoutTimer = setTimeout(() => {\r\n this.close()\r\n handlers.onError?.(new Error(`Request timeout after ${timeout}ms`))\r\n }, timeout)\r\n }\r\n\r\n // 发起请求\r\n const response = await fetch(url, {\r\n method,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...headers\r\n },\r\n body: method === 'POST' ? JSON.stringify(body) : undefined,\r\n signal: this.controller.signal\r\n })\r\n\r\n // 清除超时定时器\r\n if (this.timeoutTimer) {\r\n clearTimeout(this.timeoutTimer)\r\n this.timeoutTimer = null\r\n }\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`)\r\n }\r\n\r\n // 检查响应是否为 SSE 流\r\n const contentType = response.headers.get('content-type')\r\n if (!contentType?.includes('text/event-stream')) {\r\n throw new Error('Response is not a Server-Sent Events stream')\r\n }\r\n\r\n // 触发打开事件\r\n handlers.onOpen?.()\r\n\r\n // 读取流\r\n const reader = response.body?.getReader()\r\n const decoder = new TextDecoder()\r\n let buffer = ''\r\n\r\n if (!reader) {\r\n throw new Error('Response body is null')\r\n }\r\n\r\n while (true) {\r\n const { done, value } = await reader.read()\r\n\r\n if (done) {\r\n handlers.onClose?.()\r\n break\r\n }\r\n\r\n // 解码数据并添加到缓冲区\r\n buffer += decoder.decode(value, { stream: true })\r\n\r\n // 处理完整的消息\r\n const lines = buffer.split('\\n\\n')\r\n buffer = lines.pop() || ''\r\n\r\n for (const line of lines) {\r\n if (line.trim()) {\r\n const message = this.parseMessage(line)\r\n handlers.onMessage?.(message)\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n // 清除超时定时器\r\n if (this.timeoutTimer) {\r\n clearTimeout(this.timeoutTimer)\r\n this.timeoutTimer = null\r\n }\r\n\r\n // 如果不是主动取消,触发错误事件\r\n if (this.controller && !this.controller.signal.aborted) {\r\n handlers.onError?.(error as Error)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 使用 EventSource 连接(仅支持 GET 请求)\r\n */\r\n connect(url: string, handlers: SSEHandlers): void {\r\n this.eventSource = new EventSource(url)\r\n\r\n this.eventSource.onopen = () => {\r\n handlers.onOpen?.()\r\n }\r\n\r\n this.eventSource.onmessage = event => {\r\n handlers.onMessage?.({\r\n data: event.data,\r\n event: event.type\r\n })\r\n }\r\n\r\n this.eventSource.onerror = error => {\r\n handlers.onError?.(new Error('EventSource error'))\r\n this.close()\r\n }\r\n }\r\n\r\n /**\r\n * 解析 SSE 消息\r\n */\r\n private parseMessage(line: string): SSEMessage {\r\n const message: SSEMessage = {\r\n data: ''\r\n }\r\n\r\n const lines = line.split('\\n')\r\n for (const l of lines) {\r\n if (l.startsWith('data: ')) {\r\n message.data = l.slice(6)\r\n } else if (l.startsWith('event: ')) {\r\n message.event = l.slice(7)\r\n } else if (l.startsWith('id: ')) {\r\n message.id = l.slice(4)\r\n } else if (l.startsWith('retry: ')) {\r\n message.retry = parseInt(l.slice(7))\r\n }\r\n }\r\n\r\n return message\r\n }\r\n\r\n /**\r\n * 关闭连接\r\n */\r\n close(): void {\r\n // 取消 fetch 请求\r\n if (this.controller) {\r\n this.controller.abort()\r\n this.controller = null\r\n }\r\n\r\n // 关闭 EventSource\r\n if (this.eventSource) {\r\n this.eventSource.close()\r\n this.eventSource = null\r\n }\r\n\r\n // 清除超时定时器\r\n if (this.timeoutTimer) {\r\n clearTimeout(this.timeoutTimer)\r\n this.timeoutTimer = null\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 发起 SSE 请求(便捷方法)\r\n */\r\nexport function sse(config: SSEConfig, handlers: SSEHandlers): SSEConnection {\r\n const connection = new SSEConnection()\r\n\r\n // POST 请求或自定义配置使用 fetch\r\n if (config.method === 'POST' || config.timeout) {\r\n connection.request(config, handlers)\r\n } else {\r\n // GET 请求使用 EventSource\r\n connection.connect(config.url, handlers)\r\n }\r\n\r\n return connection\r\n}\r\n","/**\r\n * 思考过程提取配置\r\n */\r\nexport interface ThinkingExtractConfig {\r\n /** 思考标签名称(默认为 'think') */\r\n tagName?: string\r\n /** 是否提取完整标签内容(包含标签本身) */\r\n includeTags?: boolean\r\n /** 是否移除思考内容后的其余文本 */\r\n removeRest?: boolean\r\n}\r\n\r\n/**\r\n * 思考过程结果\r\n */\r\nexport interface ThinkingResult {\r\n /** 提取的思考内容 */\r\n thinking: string\r\n /** 移除思考后的剩余内容 */\r\n rest: string\r\n /** 是否找到思考内容 */\r\n hasThinking: boolean\r\n}\r\n\r\n/**\r\n * 思考标签匹配状态\r\n */\r\ninterface TagMatchState {\r\n /** 是否在思考标签内 */\r\n inThinking: boolean\r\n /** 已找到的标签部分 */\r\n tagBuffer: string\r\n /** 思考内容缓冲区 */\r\n contentBuffer: string\r\n /** 前置内容 */\r\n beforeContent: string\r\n /** 后置内容 */\r\n afterContent: string\r\n}\r\n\r\n/**\r\n * 从 AI 响应中提取思考过程(完整模式)\r\n */\r\nexport function extractThinking(\r\n text: string,\r\n config: ThinkingExtractConfig = {}\r\n): ThinkingResult {\r\n const { tagName = 'think', includeTags = false, removeRest = false } = config\r\n\r\n const openTag = `<${tagName}>`\r\n const closeTag = `</${tagName}>`\r\n\r\n const openIndex = text.indexOf(openTag)\r\n const closeIndex = text.indexOf(closeTag)\r\n\r\n // 没有找到思考标签\r\n if (openIndex === -1 || closeIndex === -1) {\r\n return {\r\n thinking: '',\r\n rest: text,\r\n hasThinking: false\r\n }\r\n }\r\n\r\n // 提取思考内容\r\n const thinkingStart = openIndex + openTag.length\r\n const thinkingEnd = closeIndex\r\n const thinkingContent = text.slice(thinkingStart, thinkingEnd)\r\n\r\n // 提取剩余内容\r\n const beforeContent = text.slice(0, openIndex)\r\n const afterContent = text.slice(closeIndex + closeTag.length)\r\n const restContent = beforeContent + afterContent\r\n\r\n // 返回结果\r\n return {\r\n thinking: includeTags\r\n ? `${openTag}${thinkingContent}${closeTag}`\r\n : thinkingContent,\r\n rest: removeRest ? '' : restContent,\r\n hasThinking: true\r\n }\r\n}\r\n\r\n/**\r\n * 流式提取思考过程(用于 SSE 流式响应)\r\n */\r\nexport class ThinkingStreamExtractor {\r\n private config: ThinkingExtractConfig\r\n private state: TagMatchState\r\n private isComplete: boolean = false\r\n\r\n constructor(config: ThinkingExtractConfig = {}) {\r\n this.config = {\r\n tagName: config.tagName || 'think',\r\n includeTags: config.includeTags || false,\r\n removeRest: config.removeRest || false\r\n }\r\n this.state = {\r\n inThinking: false,\r\n tagBuffer: '',\r\n contentBuffer: '',\r\n beforeContent: '',\r\n afterContent: ''\r\n }\r\n }\r\n\r\n /**\r\n * 追加文本并提取思考内容\r\n */\r\n append(text: string): { thinking: string; rest: string; isComplete: boolean } {\r\n if (this.isComplete) {\r\n return {\r\n thinking: this.getThinking(),\r\n rest: this.getRest(),\r\n isComplete: true\r\n }\r\n }\r\n\r\n const { tagName } = this.config\r\n const openTag = `<${tagName}>`\r\n const closeTag = `</${tagName}>`\r\n\r\n // 逐字符处理\r\n for (let i = 0; i < text.length; i++) {\r\n const char = text[i]\r\n\r\n if (!this.state.inThinking) {\r\n // 查找开始标签\r\n this.state.tagBuffer += char\r\n\r\n // 检查是否匹配到开始标签\r\n if (this.state.tagBuffer.endsWith(openTag)) {\r\n // 移除已匹配的标签部分\r\n const tagStart = this.state.tagBuffer.length - openTag.length\r\n this.state.beforeContent += this.state.tagBuffer.slice(0, tagStart)\r\n this.state.tagBuffer = ''\r\n this.state.inThinking = true\r\n continue\r\n }\r\n\r\n // 如果缓冲区过长,移除不匹配的部分\r\n if (this.state.tagBuffer.length > openTag.length) {\r\n this.state.beforeContent += this.state.tagBuffer.slice(0, 1)\r\n this.state.tagBuffer = this.state.tagBuffer.slice(1)\r\n }\r\n } else {\r\n // 查找结束标签\r\n this.state.tagBuffer += char\r\n\r\n // 检查是否匹配到结束标签\r\n if (this.state.tagBuffer.endsWith(closeTag)) {\r\n // 保存思考内容(不包含结束标签)\r\n const tagEnd = this.state.tagBuffer.length - closeTag.length\r\n this.state.contentBuffer += this.state.tagBuffer.slice(0, tagEnd)\r\n this.state.tagBuffer = ''\r\n this.state.inThinking = false\r\n this.isComplete = true\r\n break\r\n }\r\n\r\n // 如果缓冲区过长,将内容移到思考缓冲区\r\n if (this.state.tagBuffer.length > closeTag.length) {\r\n const overflow = this.state.tagBuffer.slice(0, 1)\r\n this.state.contentBuffer += overflow\r\n this.state.tagBuffer = this.state.tagBuffer.slice(1)\r\n }\r\n }\r\n }\r\n\r\n // 如果不在思考标签内,将缓冲区内容移到前置/后置内容\r\n if (!this.state.inThinking && this.state.tagBuffer) {\r\n if (this.isComplete) {\r\n this.state.afterContent += this.state.tagBuffer\r\n } else {\r\n this.state.beforeContent += this.state.tagBuffer\r\n }\r\n this.state.tagBuffer = ''\r\n }\r\n\r\n return {\r\n thinking: this.getThinking(),\r\n rest: this.getRest(),\r\n isComplete: this.isComplete\r\n }\r\n }\r\n\r\n /**\r\n * 获取当前提取的思考内容\r\n */\r\n getThinking(): string {\r\n const { tagName, includeTags } = this.config\r\n const openTag = `<${tagName}>`\r\n const closeTag = `</${tagName}>`\r\n\r\n const content = this.state.contentBuffer\r\n\r\n if (includeTags) {\r\n // 如果还在标签内,不添加闭合标签\r\n return this.state.inThinking\r\n ? `${openTag}${content}`\r\n : `${openTag}${content}${closeTag}`\r\n }\r\n\r\n return content\r\n }\r\n\r\n /**\r\n * 获取剩余内容\r\n */\r\n getRest(): string {\r\n const { removeRest } = this.config\r\n if (removeRest) {\r\n return ''\r\n }\r\n return this.state.beforeContent + this.state.afterContent\r\n }\r\n\r\n /**\r\n * 是否已完成提取\r\n */\r\n complete(): boolean {\r\n return this.isComplete\r\n }\r\n\r\n /**\r\n * 重置提取器\r\n */\r\n reset(): void {\r\n this.state = {\r\n inThinking: false,\r\n tagBuffer: '',\r\n contentBuffer: '',\r\n beforeContent: '',\r\n afterContent: ''\r\n }\r\n this.isComplete = false\r\n }\r\n}\r\n\r\n/**\r\n * 创建流式提取器实例\r\n */\r\nexport function createThinkingExtractor(\r\n config?: ThinkingExtractConfig\r\n): ThinkingStreamExtractor {\r\n return new ThinkingStreamExtractor(config)\r\n}\r\n","/**\r\n * Markdown 渲染配置\r\n */\r\nexport interface MarkdownRenderConfig {\r\n /** 是否启用代码高亮(默认 false) */\r\n highlight?: boolean\r\n /** 自定义代码高亮语言映射 */\r\n highlightLanguages?: Record<string, string>\r\n /** 是否渲染任务列表(默认 true) */\r\n taskList?: boolean\r\n /** 是否渲染表格(默认 true) */\r\n table?: boolean\r\n /** 是否渲染链接(默认 true) */\r\n link?: boolean\r\n /** 是否渲染图片(默认 true) */\r\n image?: boolean\r\n}\r\n\r\n/**\r\n * Markdown 流式更新配置\r\n */\r\nexport interface MarkdownStreamConfig extends MarkdownRenderConfig {\r\n /** 更新回调函数 */\r\n onUpdate?: (html: string) => void\r\n /** 完成回调函数 */\r\n onComplete?: (html: string) => void\r\n}\r\n\r\n/**\r\n * 简单的 Markdown 渲染器\r\n */\r\nexport class MarkdownRenderer {\r\n private config: MarkdownRenderConfig\r\n\r\n constructor(config: MarkdownRenderConfig = {}) {\r\n this.config = {\r\n highlight: config.highlight || false,\r\n highlightLanguages: config.highlightLanguages || {},\r\n taskList: config.taskList !== false,\r\n table: config.table !== false,\r\n link: config.link !== false,\r\n image: config.image !== false\r\n }\r\n }\r\n\r\n /**\r\n * 渲染 Markdown 为 HTML\r\n */\r\n render(markdown: string): string {\r\n let html = markdown\r\n\r\n // 转义 HTML 特殊字符(除了 Markdown 语法)\r\n html = this.escapeHtml(html)\r\n\r\n // 代码块(需要在其他处理之前)\r\n html = this.renderCodeBlocks(html)\r\n\r\n // 标题\r\n html = this.renderHeadings(html)\r\n\r\n // 粗体和斜体\r\n html = this.renderEmphasis(html)\r\n\r\n // 任务列表\r\n if (this.config.taskList) {\r\n html = this.renderTaskLists(html)\r\n }\r\n\r\n // 无序列表\r\n html = this.renderUnorderedLists(html)\r\n\r\n // 有序列表\r\n html = this.renderOrderedLists(html)\r\n\r\n // 表格\r\n if (this.config.table) {\r\n html = this.renderTables(html)\r\n }\r\n\r\n // 链接\r\n if (this.config.link) {\r\n html = this.renderLinks(html)\r\n }\r\n\r\n // 图片\r\n if (this.config.image) {\r\n html = this.renderImages(html)\r\n }\r\n\r\n // 段落\r\n html = this.renderParagraphs(html)\r\n\r\n // 换行\r\n html = this.renderLineBreaks(html)\r\n\r\n return html\r\n }\r\n\r\n /**\r\n * 转义 HTML 特殊字符\r\n */\r\n private escapeHtml(text: string): string {\r\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')\r\n }\r\n\r\n /**\r\n * 渲染代码块\r\n */\r\n private renderCodeBlocks(text: string): string {\r\n // 代码块(支持语法高亮标记)\r\n return text.replace(\r\n /`{3}(\\w*)\\n([\\s\\S]*?)`{3}/g,\r\n (match, lang, code) => {\r\n const language = lang || 'text'\r\n return `<pre><code class=\"language-${language}\">${code.trim()}</code></pre>`\r\n }\r\n )\r\n }\r\n\r\n /**\r\n * 渲染标题\r\n */\r\n private renderHeadings(text: string): string {\r\n return text\r\n .replace(/^#{6}\\s+(.+)$/gm, '<h6>$1</h6>')\r\n .replace(/^#{5}\\s+(.+)$/gm, '<h5>$1</h5>')\r\n .replace(/^#{4}\\s+(.+)$/gm, '<h4>$1</h4>')\r\n .replace(/^#{3}\\s+(.+)$/gm, '<h3>$1</h3>')\r\n .replace(/^#{2}\\s+(.+)$/gm, '<h2>$1</h2>')\r\n .replace(/^#{1}\\s+(.+)$/gm, '<h1>$1</h1>')\r\n }\r\n\r\n /**\r\n * 渲染粗体和斜体\r\n */\r\n private renderEmphasis(text: string): string {\r\n // 粗体\r\n text = text.replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, '<strong><em>$1</em></strong>')\r\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>')\r\n text = text.replace(/___(.+?)___/g, '<strong><em>$1</em></strong>')\r\n text = text.replace(/__(.+?)__/g, '<strong>$1</strong>')\r\n\r\n // 斜体\r\n text = text.replace(/\\*(.+?)\\*/g, '<em>$1</em>')\r\n text = text.replace(/_(.+?)_/g, '<em>$1</em>')\r\n\r\n return text\r\n }\r\n\r\n /**\r\n * 渲染任务列表\r\n */\r\n private renderTaskLists(text: string): string {\r\n return text.replace(/^\\s*-\\s*\\[x\\]\\s+(.+)$/gm, '<li class=\"task-checked\"><input type=\"checkbox\" checked disabled> $1</li>')\r\n .replace(/^\\s*-\\s*\\[\\s*\\]\\s+(.+)$/gm, '<li><input type=\"checkbox\" disabled> $1</li>')\r\n }\r\n\r\n /**\r\n * 渲染无序列表\r\n */\r\n private renderUnorderedLists(text: string): string {\r\n const lines = text.split('\\n')\r\n const result: string[] = []\r\n const listStack: string[] = []\r\n\r\n for (const line of lines) {\r\n const match = line.match(/^(\\s*)-\\s+(.+)$/)\r\n if (!match) {\r\n // 关闭所有打开的列表\r\n while (listStack.length > 0) {\r\n result.push(listStack.pop() || '')\r\n }\r\n result.push(line)\r\n continue\r\n }\r\n\r\n const [_, indent, content] = match\r\n const indentLevel = indent.length\r\n const listTag = '<ul>'\r\n\r\n // 处理缩进层级\r\n while (listStack.length > 0 && listStack.length < indentLevel / 2 + 1) {\r\n result.push(listStack.pop() || '')\r\n }\r\n\r\n // 打开新的列表\r\n while (listStack.length < indentLevel / 2 + 1) {\r\n listStack.push('<ul>')\r\n result.push('<ul>')\r\n }\r\n\r\n result.push(`<li>${content}</li>`)\r\n }\r\n\r\n // 关闭所有打开的列表\r\n while (listStack.length > 0) {\r\n result.push('</ul>')\r\n listStack.pop()\r\n }\r\n\r\n return result.join('\\n')\r\n }\r\n\r\n /**\r\n * 渲染有序列表\r\n */\r\n private renderOrderedLists(text: string): string {\r\n const lines = text.split('\\n')\r\n const result: string[] = []\r\n let inList = false\r\n\r\n for (const line of lines) {\r\n const match = line.match(/^\\s*\\d+\\.\\s+(.+)$/)\r\n if (!match) {\r\n if (inList) {\r\n result.push('</ol>')\r\n inList = false\r\n }\r\n result.push(line)\r\n continue\r\n }\r\n\r\n const [_, content] = match\r\n if (!inList) {\r\n result.push('<ol>')\r\n inList = true\r\n }\r\n result.push(`<li>${content}</li>`)\r\n }\r\n\r\n if (inList) {\r\n result.push('</ol>')\r\n }\r\n\r\n return result.join('\\n')\r\n }\r\n\r\n /**\r\n * 渲染表格\r\n */\r\n private renderTables(text: string): string {\r\n const lines = text.split('\\n')\r\n const result: string[] = []\r\n let inTable = false\r\n let headerRendered = false\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i]\r\n\r\n // 表格分隔符\r\n if (line.match(/^\\|[\\s\\-:|]+\\|$/)) {\r\n continue\r\n }\r\n\r\n // 表格行\r\n const match = line.match(/^\\|(.+)\\|$/)\r\n if (!match) {\r\n if (inTable) {\r\n result.push('</table>')\r\n inTable = false\r\n headerRendered = false\r\n }\r\n result.push(line)\r\n continue\r\n }\r\n\r\n const cells = match[1].split('|').map((cell: string) => cell.trim())\r\n\r\n if (!inTable) {\r\n result.push('<table>')\r\n inTable = true\r\n }\r\n\r\n if (!headerRendered) {\r\n result.push('<thead><tr>')\r\n cells.forEach((cell: string) => {\r\n result.push(`<th>${cell}</th>`)\r\n })\r\n result.push('</tr></thead><tbody>')\r\n headerRendered = true\r\n } else {\r\n result.push('<tr>')\r\n cells.forEach((cell: string) => {\r\n result.push(`<td>${cell}</td>`)\r\n })\r\n result.push('</tr>')\r\n }\r\n }\r\n\r\n if (inTable) {\r\n result.push('</tbody></table>')\r\n }\r\n\r\n return result.join('\\n')\r\n }\r\n\r\n /**\r\n * 渲染链接\r\n */\r\n private renderLinks(text: string): string {\r\n return text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\">$1</a>')\r\n }\r\n\r\n /**\r\n * 渲染图片\r\n */\r\n private renderImages(text: string): string {\r\n return text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, '<img src=\"$2\" alt=\"$1\" />')\r\n }\r\n\r\n /**\r\n * 渲染段落\r\n */\r\n private renderParagraphs(text: string): string {\r\n const lines = text.split('\\n')\r\n const result: string[] = []\r\n let inParagraph = false\r\n\r\n for (const line of lines) {\r\n // 跳过空行和 HTML 标签\r\n if (!line.trim() || line.match(/^<(h|ul|ol|li|table|pre|div)/)) {\r\n if (inParagraph) {\r\n result.push('</p>')\r\n inParagraph = false\r\n }\r\n result.push(line)\r\n continue\r\n }\r\n\r\n if (!inParagraph) {\r\n result.push('<p>')\r\n inParagraph = true\r\n }\r\n result.push(line)\r\n }\r\n\r\n if (inParagraph) {\r\n result.push('</p>')\r\n }\r\n\r\n return result.join('\\n')\r\n }\r\n\r\n /**\r\n * 渲染换行\r\n */\r\n private renderLineBreaks(text: string): string {\r\n // 在段落内的换行转换为 <br>\r\n return text.replace(/(<p>.*?<\\/p>|<li>.*?<\\/li>)/g, (match) => {\r\n return match.replace(/\\n/g, '<br>\\n')\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * 渲染 Markdown 为 HTML(便捷方法)\r\n */\r\nexport function renderMarkdown(\r\n markdown: string,\r\n config?: MarkdownRenderConfig\r\n): string {\r\n const renderer = new MarkdownRenderer(config)\r\n return renderer.render(markdown)\r\n}\r\n\r\n/**\r\n * 流式渲染 Markdown(用于 SSE 流式响应)\r\n */\r\nexport class MarkdownStreamRenderer {\r\n private renderer: MarkdownRenderer\r\n private buffer: string = ''\r\n private config: MarkdownStreamConfig\r\n\r\n constructor(config: MarkdownStreamConfig = {}) {\r\n this.config = config\r\n this.renderer = new MarkdownRenderer(config)\r\n }\r\n\r\n /**\r\n * 追加文本并渲染\r\n */\r\n append(text: string): string {\r\n this.buffer += text\r\n const html = this.renderer.render(this.buffer)\r\n\r\n if (this.config.onUpdate) {\r\n this.config.onUpdate(html)\r\n }\r\n\r\n return html\r\n }\r\n\r\n /**\r\n * 完成渲染\r\n */\r\n complete(): string {\r\n const html = this.renderer.render(this.buffer)\r\n\r\n if (this.config.onComplete) {\r\n this.config.onComplete(html)\r\n }\r\n\r\n return html\r\n }\r\n\r\n /**\r\n * 重置渲染器\r\n */\r\n reset(): void {\r\n this.buffer = ''\r\n }\r\n}\r\n\r\n/**\r\n * 创建流式渲染器实例\r\n */\r\nexport function createMarkdownRenderer(\r\n config?: MarkdownStreamConfig\r\n): MarkdownStreamRenderer {\r\n return new MarkdownStreamRenderer(config)\r\n}\r\n"],"names":["SSEConnection","config","handlers","__async","_a","_b","_c","_d","_e","url","method","headers","body","timeout","response","__spreadValues","contentType","reader","decoder","buffer","done","value","lines","line","message","error","event","l","sse","connection","extractThinking","text","tagName","includeTags","removeRest","openTag","closeTag","openIndex","closeIndex","thinkingStart","thinkingEnd","thinkingContent","beforeContent","afterContent","restContent","ThinkingStreamExtractor","i","char","tagEnd","overflow","tagStart","content","createThinkingExtractor","MarkdownRenderer","markdown","html","match","lang","code","result","listStack","_","indent","indentLevel","inList","inTable","headerRendered","cells","cell","inParagraph","renderMarkdown","MarkdownStreamRenderer","createMarkdownRenderer"],"mappings":"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"}
|