Skip to content

Commit 57c91dc

Browse files
committed
Assure TextNodePosition is only used on pasted TextNodes when pasting single-node content; slight reformatting to repo standard line length; learnt about selectionEquivalentTo matcher.
1 parent 8bc6f6c commit 57c91dc

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

super_editor/lib/src/default_editor/common_editor_operations.dart

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2511,7 +2511,7 @@ class PasteEditorCommand extends EditCommand {
25112511
}
25122512

25132513
late DocumentPosition documentPositionAfterPaste;
2514-
if (parsedContent.length > 1) {
2514+
if (parsedContent.length > 1 || parsedContent.first is! TextNode ) {
25152515
// Place the caret at the end of the pasted content.
25162516
final pastedNode = document.getNodeById(previousNode.id)!;
25172517
// ^ re-query the node where we pasted content because nodes are immutable.
@@ -2520,14 +2520,12 @@ class PasteEditorCommand extends EditCommand {
25202520
nodePosition: pastedNode.endPosition,
25212521
);
25222522
} else {
2523-
// The user only pasted content without any newlines in it. Place the
2524-
// caret in the existing node at the end of the pasted text. This is
2525-
// guaranteed to be a TextNode.
2523+
// The user only pasted text content without any newlines in it. Place the
2524+
// caret in the existing text node at the end of the pasted text.
25262525
documentPositionAfterPaste = DocumentPosition(
25272526
nodeId: _pastePosition.nodeId,
25282527
nodePosition: TextNodePosition(
2529-
offset:
2530-
pasteTextOffset + (_parsedContent!.first as TextNode).text.length,
2528+
offset: pasteTextOffset + (_parsedContent!.first as TextNode).text.length,
25312529
),
25322530
);
25332531
}

super_editor/test/super_editor/supereditor_copy_and_paste_test.dart

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:super_editor/super_editor.dart';
77
import 'package:super_editor/super_editor_test.dart';
88

99
import '../test_runners.dart';
10+
import '../test_tools.dart';
1011
import 'supereditor_test_tools.dart';
1112

1213
void main() {
@@ -33,7 +34,8 @@ void main() {
3334

3435
// Ensure that the text was pasted into the paragraph.
3536
final nodeId = doc.first.id;
36-
expect(SuperEditorInspector.findTextInComponent(nodeId).toPlainText(), "Pasted text: This was pasted here");
37+
expect(SuperEditorInspector.findTextInComponent(nodeId).toPlainText(),
38+
"Pasted text: This was pasted here");
3739
});
3840

3941
testAllInputsOnDesktop(
@@ -50,15 +52,15 @@ void main() {
5052

5153
// Place the caret at the empty paragraph.
5254
await tester.placeCaretInParagraph('1', 0);
53-
55+
5456
// Type some text.
5557
switch (inputSource) {
5658
case TextInputSource.keyboard:
5759
await tester.typeKeyboardText('This is a paragraph');
5860
case TextInputSource.ime:
5961
await tester.typeImeText('This is a paragraph');
6062
}
61-
63+
6264
// Place the cursor somewhere in the middle of the text.
6365
await tester.placeCaretInParagraph('1', 8);
6466

@@ -79,12 +81,11 @@ void main() {
7981
expect((doc.getNodeAt(0)! as ParagraphNode).text.toPlainText(),
8082
'This is some content in a paragraph');
8183
final selection = testContext.composer.selection;
82-
expect(selection, isNotNull);
83-
expect(selection!.isCollapsed, isTrue);
84-
expect((selection.base.nodePosition as TextNodePosition).offset, 24);
84+
expect(selection, selectionEquivalentTo(
85+
const DocumentSelection.collapsed(
86+
position: DocumentPosition(nodeId: '1', nodePosition: TextNodePosition(offset: 24)))));
8587
});
8688

87-
8889
testWidgetsOnApple('pastes within a list item', (tester) async {
8990
await tester //
9091
.createDocument()
@@ -96,7 +97,8 @@ void main() {
9697

9798
// Place the caret at the end of the list item.
9899
await tester.placeCaretInParagraph(doc.first.id, 12);
99-
await tester.typeImeText(" "); // <- manually add a space because Markdown strips it
100+
await tester.typeImeText(
101+
" "); // <- manually add a space because Markdown strips it
100102

101103
// Paste text into the paragraph.
102104
tester
@@ -106,7 +108,8 @@ void main() {
106108

107109
// Ensure that the text was pasted into the paragraph.
108110
final nodeId = doc.first.id;
109-
expect(SuperEditorInspector.findTextInComponent(nodeId).toPlainText(), "Pasted text: This was pasted here");
111+
expect(SuperEditorInspector.findTextInComponent(nodeId).toPlainText(),
112+
"Pasted text: This was pasted here");
110113
});
111114

112115
testAllInputsOnDesktop('pastes multiple paragraphs', (
@@ -137,12 +140,16 @@ This is the third paragraph''');
137140
// Ensure three paragraphs were created.
138141
final doc = testContext.document;
139142
expect(doc.nodeCount, 3);
140-
expect((doc.getNodeAt(0)! as ParagraphNode).text.toPlainText(), 'This is a paragraph');
141-
expect((doc.getNodeAt(1)! as ParagraphNode).text.toPlainText(), 'This is a second paragraph');
142-
expect((doc.getNodeAt(2)! as ParagraphNode).text.toPlainText(), 'This is the third paragraph');
143+
expect((doc.getNodeAt(0)! as ParagraphNode).text.toPlainText(),
144+
'This is a paragraph');
145+
expect((doc.getNodeAt(1)! as ParagraphNode).text.toPlainText(),
146+
'This is a second paragraph');
147+
expect((doc.getNodeAt(2)! as ParagraphNode).text.toPlainText(),
148+
'This is the third paragraph');
143149
});
144150

145-
testAllInputsOnAllPlatforms("paste retains node IDs when replayed during undo", (
151+
testAllInputsOnAllPlatforms(
152+
"paste retains node IDs when replayed during undo", (
146153
tester, {
147154
required TextInputSource inputSource,
148155
}) async {
@@ -168,7 +175,8 @@ This is the third paragraph''');
168175
}
169176

170177
// Gather the current node IDs in the document.
171-
final originalNodeIds = testContext.document.toList().map((node) => node.id).toList();
178+
final originalNodeIds =
179+
testContext.document.toList().map((node) => node.id).toList();
172180

173181
// Pump enough time to separate the next text entry from the paste action.
174182
await tester.pump(const Duration(seconds: 2));
@@ -186,11 +194,14 @@ This is the third paragraph''');
186194

187195
// Ensure that the node IDs in the document didn't change after re-running
188196
// the paste command.
189-
final newNodeIds = testContext.document.toList().map((node) => node.id).toList();
197+
final newNodeIds =
198+
testContext.document.toList().map((node) => node.id).toList();
190199
expect(newNodeIds, originalNodeIds);
191200
});
192201

193-
testWidgetsOnMac("paste command content does not mutate when document changes", (tester) async {
202+
testWidgetsOnMac(
203+
"paste command content does not mutate when document changes",
204+
(tester) async {
194205
final testContext = await tester //
195206
.createDocument()
196207
.withSingleEmptyParagraph()

0 commit comments

Comments
 (0)