0.2.1 onlyoffice修复
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import type { Json } from "@/types/supabase";
|
||||
|
||||
type BlockLike = {
|
||||
id: string;
|
||||
type?: string;
|
||||
props?: Record<string, unknown>;
|
||||
content?: unknown;
|
||||
children?: BlockLike[];
|
||||
};
|
||||
|
||||
const asBlockArray = (value: unknown): BlockLike[] => {
|
||||
if (!Array.isArray(value)) return [];
|
||||
return value.filter((b) => b && typeof b === "object" && typeof (b as { id?: unknown }).id === "string") as BlockLike[];
|
||||
};
|
||||
|
||||
export const findBlockInTree = (
|
||||
blocks: BlockLike[],
|
||||
blockId: string,
|
||||
): { block: BlockLike; parent: BlockLike | null; index: number } | null => {
|
||||
const stack: Array<{ list: BlockLike[]; parent: BlockLike | null }> = [{ list: blocks, parent: null }];
|
||||
while (stack.length) {
|
||||
const item = stack.pop()!;
|
||||
const list = item.list;
|
||||
for (let i = 0; i < list.length; i += 1) {
|
||||
const b = list[i]!;
|
||||
if (b.id === blockId) {
|
||||
return { block: b, parent: item.parent, index: i };
|
||||
}
|
||||
if (Array.isArray(b.children) && b.children.length > 0) {
|
||||
stack.push({ list: b.children, parent: b });
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const cloneBlock = (block: BlockLike): BlockLike => {
|
||||
return {
|
||||
...block,
|
||||
props: block.props ? { ...block.props } : undefined,
|
||||
content: Array.isArray(block.content) ? [...block.content] : block.content,
|
||||
children: Array.isArray(block.children) ? block.children.map(cloneBlock) : block.children,
|
||||
};
|
||||
};
|
||||
|
||||
export const removeBlockSubtree = (
|
||||
blocks: BlockLike[],
|
||||
blockId: string,
|
||||
): { removed: BlockLike | null; nextBlocks: BlockLike[] } => {
|
||||
// 说明:这里不直接修改入参 blocks,返回新的 nextBlocks。
|
||||
const nextTop = blocks.map(cloneBlock);
|
||||
const hit = findBlockInTree(nextTop, blockId);
|
||||
if (!hit) return { removed: null, nextBlocks: nextTop };
|
||||
|
||||
if (hit.parent) {
|
||||
const parent = hit.parent;
|
||||
const nextChildren = asBlockArray(parent.children).map(cloneBlock);
|
||||
const removed = nextChildren.splice(hit.index, 1)[0] ?? null;
|
||||
parent.children = nextChildren;
|
||||
return { removed, nextBlocks: nextTop };
|
||||
}
|
||||
|
||||
const removed = nextTop.splice(hit.index, 1)[0] ?? null;
|
||||
return { removed, nextBlocks: nextTop };
|
||||
};
|
||||
|
||||
export const replaceBlockInTree = (
|
||||
blocks: BlockLike[],
|
||||
blockId: string,
|
||||
nextBlock: BlockLike,
|
||||
): { ok: boolean; nextBlocks: BlockLike[] } => {
|
||||
const nextTop = blocks.map(cloneBlock);
|
||||
const hit = findBlockInTree(nextTop, blockId);
|
||||
if (!hit) return { ok: false, nextBlocks: nextTop };
|
||||
|
||||
const normalized = cloneBlock({ ...nextBlock, id: blockId });
|
||||
if (hit.parent) {
|
||||
const parent = hit.parent;
|
||||
const nextChildren = asBlockArray(parent.children).map(cloneBlock);
|
||||
nextChildren[hit.index] = normalized;
|
||||
parent.children = nextChildren;
|
||||
return { ok: true, nextBlocks: nextTop };
|
||||
}
|
||||
|
||||
nextTop[hit.index] = normalized;
|
||||
return { ok: true, nextBlocks: nextTop };
|
||||
};
|
||||
|
||||
export const extractBlockText = (block: BlockLike): string => {
|
||||
const inline = Array.isArray(block.content) ? (block.content as Array<{ text?: unknown }>) : [];
|
||||
const text = inline.map((n) => (typeof n?.text === "string" ? n.text : "")).join("");
|
||||
return text.trim();
|
||||
};
|
||||
|
||||
export const getBlocksFromDocumentContent = (content: unknown): BlockLike[] => {
|
||||
if (Array.isArray(content)) return asBlockArray(content);
|
||||
if (content && typeof content === "object") {
|
||||
const blocks = (content as { blocks?: unknown }).blocks;
|
||||
return asBlockArray(blocks);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
export const withBlocksWrittenBack = (content: unknown, blocks: BlockLike[]): Json => {
|
||||
// 复用现有结构:数组或 {blocks: []}
|
||||
if (Array.isArray(content)) {
|
||||
return blocks as unknown as Json;
|
||||
}
|
||||
if (content && typeof content === "object") {
|
||||
return { ...(content as Record<string, unknown>), blocks } as Json;
|
||||
}
|
||||
return { blocks } as Json;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user