102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
function pushText(out: string[], value: unknown) {
|
|
const s = typeof value === "string" ? value : null;
|
|
if (!s) return;
|
|
const trimmed = s.replace(/\s+/g, " ").trim();
|
|
if (!trimmed) return;
|
|
out.push(trimmed);
|
|
}
|
|
|
|
export function extractTextFromDocumentContent(content: unknown, maxChars = 60000): string {
|
|
const out: string[] = [];
|
|
|
|
const readPropText = (value: unknown) => {
|
|
if (!value || typeof value !== "object") return null;
|
|
const t = (value as Record<string, unknown>).text;
|
|
return typeof t === "string" ? t : null;
|
|
};
|
|
|
|
const walk = (node: unknown) => {
|
|
if (out.join("\n").length >= maxChars) return;
|
|
|
|
if (node == null) return;
|
|
if (typeof node === "string") {
|
|
pushText(out, node);
|
|
return;
|
|
}
|
|
if (typeof node === "number" || typeof node === "boolean") return;
|
|
|
|
if (Array.isArray(node)) {
|
|
for (const item of node) {
|
|
walk(item);
|
|
if (out.join("\n").length >= maxChars) return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (typeof node === "object") {
|
|
const obj = node as Record<string, unknown>;
|
|
|
|
// 兼容常见 BlockNote 结构:
|
|
// - block.props.text
|
|
// - block.content: [{ text: "..." }, ...]
|
|
// - block.children: [...]
|
|
pushText(out, obj.text);
|
|
pushText(out, readPropText(obj.props));
|
|
|
|
const maybeContent = obj.content;
|
|
if (Array.isArray(maybeContent)) {
|
|
for (const seg of maybeContent) {
|
|
if (typeof seg === "string") pushText(out, seg);
|
|
else if (seg && typeof seg === "object") pushText(out, readPropText(seg));
|
|
if (out.join("\n").length >= maxChars) return;
|
|
}
|
|
}
|
|
|
|
const children = obj.children;
|
|
if (Array.isArray(children)) {
|
|
for (const c of children) {
|
|
walk(c);
|
|
if (out.join("\n").length >= maxChars) return;
|
|
}
|
|
}
|
|
|
|
// 兜底:遍历其它字段(避免遗漏 title/caption 等)
|
|
for (const [k, v] of Object.entries(obj)) {
|
|
if (k === "children" || k === "content" || k === "props" || k === "text") continue;
|
|
if (typeof v === "string") pushText(out, v);
|
|
else if (Array.isArray(v) || (v && typeof v === "object")) walk(v);
|
|
if (out.join("\n").length >= maxChars) return;
|
|
}
|
|
}
|
|
};
|
|
|
|
walk(content);
|
|
|
|
const joined = out.join("\n").trim();
|
|
return joined.length > maxChars ? `${joined.slice(0, maxChars)}…` : joined;
|
|
}
|
|
|
|
type MindmapNode = { data?: { text?: unknown }; children?: unknown[] };
|
|
|
|
export function extractTextFromMindmapData(data: unknown, maxChars = 60000): string {
|
|
const out: string[] = [];
|
|
|
|
const walk = (node: unknown) => {
|
|
if (out.join("\n").length >= maxChars) return;
|
|
if (!node || typeof node !== "object") return;
|
|
const n = node as MindmapNode;
|
|
pushText(out, n.data?.text);
|
|
if (Array.isArray(n.children)) {
|
|
for (const c of n.children) {
|
|
walk(c);
|
|
if (out.join("\n").length >= maxChars) return;
|
|
}
|
|
}
|
|
};
|
|
|
|
walk(data);
|
|
|
|
const joined = out.join("\n").trim();
|
|
return joined.length > maxChars ? `${joined.slice(0, maxChars)}…` : joined;
|
|
}
|