返回 DeepSeek-Reasonix
sessionExportBlocks.ts
根目录 / desktop / frontend / src / lib / sessionExportBlocks.ts
1 import { unified } from "unified";
2 import remarkParse from "remark-parse";
3 import remarkGfm from "remark-gfm";
4 import remarkMath from "remark-math";
5
6 const blockBudget = 32 << 10;
7 function chunks(text: string): string[] {
8 const out: string[] = [];
9 while (text.length > blockBudget) {
10 let end = text.lastIndexOf("\n", blockBudget);
11 if (end < blockBudget / 2) end = text.lastIndexOf(" ", blockBudget);
12 if (end < blockBudget / 2) end = blockBudget;
13 else end++;
14 const code = text.charCodeAt(end - 1); if (code >= 0xd800 && code <= 0xdbff) end--;
15 out.push(text.slice(0, end)); text = text.slice(end);
16 }
17 if (text) out.push(text);
18 return out;
19 }
20 /** Keep definitions available when a message's top-level blocks are paged. */
21 export function splitExportMarkdown(source: string): string[] {
22 if (source.length <= blockBudget) return [source];
23 const tree = unified().use(remarkParse).use(remarkGfm).use(remarkMath).parse(source);
24 const definitions = tree.children.filter(node => node.type === "definition" || node.type === "footnoteDefinition")
25 .map(node => source.slice(node.position?.start.offset, node.position?.end.offset)).join("\n");
26 const out: string[] = [];
27 for (const node of tree.children) {
28 if (node.type === "definition" || node.type === "footnoteDefinition") continue;
29 const text = source.slice(node.position?.start.offset, node.position?.end.offset);
30 if (node.type === "code" && text.length > blockBudget) {
31 const fence = "`".repeat(Math.max(2, ...Array.from(node.value.matchAll(/`+/g), match => match[0].length)) + 1);
32 for (const part of chunks(node.value)) out.push(`${fence}${node.lang ?? ""}\n${part}\n${fence}`);
33 } else if (node.type === "table" && text.length > blockBudget) {
34 const lines = text.split("\n"); const header = lines.slice(0, 2).join("\n");
35 let group = header;
36 for (const line of lines.slice(2)) { if (group.length + line.length > blockBudget && group !== header) { out.push(group + "\n" + definitions); group = header; } group += "\n" + line; }
37 out.push(group + "\n" + definitions);
38 } else {
39 for (const part of chunks(text)) out.push(part + (definitions ? "\n\n" + definitions : ""));
40 }
41 }
42 return out;
43 }
44
44 lines TYPESCRIPT