diff --git a/packages/blocks/src/_common/adapters/markdown.ts b/packages/blocks/src/_common/adapters/markdown.ts index 0ca0c55c239c..1560449b8e65 100644 --- a/packages/blocks/src/_common/adapters/markdown.ts +++ b/packages/blocks/src/_common/adapters/markdown.ts @@ -1313,10 +1313,10 @@ export class MarkdownAdapter extends BaseAdapter { displayMode: NoteDisplayMode.DocAndEdgeless, }, children: [], - }; + } as BlockSnapshot; const contentSlice = (await this._traverseMarkdown( markdownAst, - blockSnapshotRoot as BlockSnapshot, + blockSnapshotRoot, payload.assets )) as BlockSnapshot; if (contentSlice.children.length === 0) { diff --git a/packages/blocks/src/_common/adapters/mix-text.ts b/packages/blocks/src/_common/adapters/mix-text.ts index 39981b9498e7..be4857fb0557 100644 --- a/packages/blocks/src/_common/adapters/mix-text.ts +++ b/packages/blocks/src/_common/adapters/mix-text.ts @@ -46,6 +46,30 @@ export class MixTextAdapter extends BaseAdapter { this._markdownAdapter = new MarkdownAdapter(job); } + private _splitDeltas(deltas: DeltaInsert[]): DeltaInsert[][] { + const result: DeltaInsert[][] = [[]]; + const pending: DeltaInsert[] = deltas; + while (pending.length > 0) { + const delta = pending.shift(); + if (!delta) { + break; + } + if (delta.insert.includes('\n')) { + const splitIndex = delta.insert.indexOf('\n'); + const line = delta.insert.slice(0, splitIndex); + const rest = delta.insert.slice(splitIndex + 1); + result[result.length - 1].push({ ...delta, insert: line }); + result.push([]); + if (rest) { + pending.unshift({ ...delta, insert: rest }); + } + } else { + result[result.length - 1].push(delta); + } + } + return result; + } + private async _traverseSnapshot( snapshot: BlockSnapshot ): Promise<{ mixtext: string }> { @@ -245,13 +269,6 @@ export class MixTextAdapter extends BaseAdapter { return null; } payload.file = payload.file.replaceAll('\r', ''); - const lines = payload.file.split('\n'); - for (let i = 0; i < lines.length - 1; i++) { - if (lines[i].length !== 0 && lines[i + 1].length !== 0) { - lines[i] += '\n'; - } - } - payload.file = lines.join('\n'); const sliceSnapshot = await this._markdownAdapter.toSliceSnapshot({ file: payload.file, assets: payload.assets, @@ -260,6 +277,79 @@ export class MixTextAdapter extends BaseAdapter { workspaceId: payload.workspaceId, pageId: payload.pageId, }); + if (!sliceSnapshot) { + return null; + } + for (const contentSlice of sliceSnapshot.content) { + const blockSnapshotRoot = { + type: 'block', + id: nanoid(), + flavour: 'affine:note', + props: { + xywh: '[0,0,800,95]', + background: DEFAULT_NOTE_BACKGROUND_COLOR, + index: 'a0', + hidden: false, + displayMode: NoteDisplayMode.DocAndEdgeless, + }, + children: [], + } as BlockSnapshot; + const walker = new ASTWalker(); + walker.setONodeTypeGuard( + (node): node is BlockSnapshot => + BlockSnapshotSchema.safeParse(node).success + ); + walker.setEnter((o, context) => { + switch (o.node.flavour) { + case 'affine:note': { + break; + } + case 'affine:paragraph': { + if (o.parent?.node.flavour !== 'affine:note') { + context.openNode({ ...o.node, children: [] }); + break; + } + const text = (o.node.props.text ?? { delta: [] }) as { + delta: DeltaInsert[]; + }; + const newDeltas = this._splitDeltas(text.delta); + for (const [i, delta] of newDeltas.entries()) { + context.openNode({ + ...o.node, + id: i === 0 ? o.node.id : nanoid(), + props: { + ...o.node.props, + text: { + '$blocksuite:internal:text$': true, + delta, + }, + }, + children: [], + }); + if (i < newDeltas.length - 1) { + context.closeNode(); + } + } + break; + } + default: { + context.openNode({ ...o.node, children: [] }); + } + } + }); + walker.setLeave((o, context) => { + switch (o.node.flavour) { + case 'affine:note': { + break; + } + default: { + context.closeNode(); + } + } + }); + await walker.walk(contentSlice, blockSnapshotRoot); + contentSlice.children = blockSnapshotRoot.children; + } return sliceSnapshot; } }