diff --git a/lib/src/editor/editor_component/service/shortcuts/command/copy_paste_extension.dart b/lib/src/editor/editor_component/service/shortcuts/command/copy_paste_extension.dart index d566478ea..9d54b610c 100644 --- a/lib/src/editor/editor_component/service/shortcuts/command/copy_paste_extension.dart +++ b/lib/src/editor/editor_component/service/shortcuts/command/copy_paste_extension.dart @@ -56,20 +56,36 @@ extension EditorCopyPaste on EditorState { if (node == null || delta == null) { return; } + final transaction = this.transaction; + // check if the first node is a non-delta node, + // if so, insert the nodes after the current selection. + final startWithNonDeltaBlock = nodes.first.delta == null; + if (startWithNonDeltaBlock) { + transaction.insertNodes(node.path.next, nodes); + await apply(transaction); + return; + } + final lastNodeLength = calculateLength(nodes); // merge the current selected node delta into the nodes. if (delta.isNotEmpty) { - nodes.first.insertDelta( - delta.slice(0, selection.startIndex), - insertAfter: false, - ); + final firstNode = nodes.first; + if (firstNode.delta != null) { + nodes.first.insertDelta( + delta.slice(0, selection.startIndex), + insertAfter: false, + ); + } - nodes.last.insertDelta( - delta.slice(selection.endIndex), - insertAfter: true, - ); + final lastNode = nodes.last; + if (lastNode.delta != null) { + nodes.last.insertDelta( + delta.slice(selection.endIndex), + insertAfter: true, + ); + } } if (delta.isEmpty && node.type != ParagraphBlockKeys.type) { diff --git a/test/new/editor_component/service/shortcuts/command_shortcuts/paste_command_test.dart b/test/new/editor_component/service/shortcuts/command_shortcuts/paste_command_test.dart index 10a1a9ce9..8fdb533ec 100644 --- a/test/new/editor_component/service/shortcuts/command_shortcuts/paste_command_test.dart +++ b/test/new/editor_component/service/shortcuts/command_shortcuts/paste_command_test.dart @@ -23,5 +23,48 @@ void main() async { await editor.dispose(); }); + + testWidgets('paste multiple nodes that start with non-delta node', + (tester) async { + const text = 'Hello World'; + final editor = tester.editor..addParagraph(initialText: text); + await editor.startTesting(); + + // paste the context after the text + await editor.updateSelection( + Selection.collapsed(Position(path: [0], offset: text.length)), + ); + const pastedText = 'pasted text'; + editor.editorState.pasteMultiLineNodes([ + imageNode(url: ''), + paragraphNode(text: pastedText), + ]); + await tester.pumpAndSettle(); + + expect(editor.nodeAtPath([0])!.delta!.toPlainText(), text); + expect(editor.nodeAtPath([1])!.type, ImageBlockKeys.type); + expect(editor.nodeAtPath([2])!.delta!.toPlainText(), pastedText); + }); + }); + + testWidgets('paste multiple nodes that start with delta node', + (tester) async { + const text = 'Hello World'; + final editor = tester.editor..addParagraph(initialText: text); + await editor.startTesting(); + + // paste the context after the text + await editor.updateSelection( + Selection.collapsed(Position(path: [0], offset: text.length)), + ); + const pastedText = 'pasted text'; + editor.editorState.pasteMultiLineNodes([ + paragraphNode(text: pastedText), + imageNode(url: ''), + ]); + await tester.pumpAndSettle(); + + expect(editor.nodeAtPath([0])!.delta!.toPlainText(), text + pastedText); + expect(editor.nodeAtPath([1])!.type, ImageBlockKeys.type); }); }