mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-24 14:47:13 -04:00
fix: replace the selected text with ai response in the multiple lines
This commit is contained in:
parent
18da4f5d2f
commit
d471d54252
2 changed files with 303 additions and 1 deletions
|
@ -358,10 +358,67 @@ class MarkdownTextRobot {
|
|||
return;
|
||||
}
|
||||
|
||||
final markdownNodes = customMarkdownToDocument(
|
||||
markdownText,
|
||||
tableWidth: 250.0,
|
||||
).root.children;
|
||||
|
||||
// Get the selected nodes.
|
||||
final nodes = editorState.getNodesInSelection(selection);
|
||||
|
||||
// Replace the delta of the selected nodes.
|
||||
// step 1. merge the first selected node and the first node from the ai response
|
||||
// step 2. merge the last selected node and the last node from the ai response
|
||||
// step 3. insert the middle nodes from the ai response
|
||||
// step 4. delete the middle nodes
|
||||
final transaction = editorState.transaction;
|
||||
|
||||
// step 1
|
||||
final firstNode = nodes.firstOrNull;
|
||||
final delta = firstNode?.delta;
|
||||
final firstMarkdownNode = markdownNodes.firstOrNull;
|
||||
final firstMarkdownDelta = firstMarkdownNode?.delta;
|
||||
if (firstNode != null &&
|
||||
delta != null &&
|
||||
firstMarkdownNode != null &&
|
||||
firstMarkdownDelta != null) {
|
||||
final startIndex = selection.startIndex;
|
||||
final length = delta.length - startIndex;
|
||||
transaction
|
||||
..deleteText(firstNode, startIndex, length)
|
||||
..insertTextDelta(firstNode, startIndex, firstMarkdownDelta);
|
||||
}
|
||||
|
||||
// step 2
|
||||
final lastNode = nodes.lastOrNull;
|
||||
final lastDelta = lastNode?.delta;
|
||||
final lastMarkdownNode = markdownNodes.lastOrNull;
|
||||
final lastMarkdownDelta = lastMarkdownNode?.delta;
|
||||
if (lastNode != null &&
|
||||
lastDelta != null &&
|
||||
lastMarkdownNode != null &&
|
||||
lastMarkdownDelta != null) {
|
||||
final endIndex = selection.endIndex;
|
||||
transaction
|
||||
..deleteText(lastNode, 0, endIndex)
|
||||
..insertTextDelta(lastNode, 0, lastMarkdownDelta);
|
||||
}
|
||||
|
||||
// step 3
|
||||
final insertedPath = selection.start.path.nextNPath(1);
|
||||
if (markdownNodes.length > 2) {
|
||||
transaction.insertNodes(
|
||||
insertedPath,
|
||||
markdownNodes.skip(1).take(markdownNodes.length - 2).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
// step 4
|
||||
if (nodes.length > 2) {
|
||||
final middleNodes = nodes.skip(1).take(nodes.length - 2).toList();
|
||||
transaction.deleteNodes(middleNodes);
|
||||
}
|
||||
|
||||
await editorState.apply(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -488,6 +488,251 @@ void main() {
|
|||
expect(d7.attributes, null);
|
||||
});
|
||||
});
|
||||
|
||||
group('markdown text robot - replace in multiple lines:', () {
|
||||
final text1 =
|
||||
'''The introduction of the World Wide Web in the early 1990s marked a turning point. ''';
|
||||
final text2 =
|
||||
'''Tim Berners-Lee's invention made the internet accessible to non-technical users, opening the floodgates for mass adoption. ''';
|
||||
final text3 =
|
||||
'''Email became widespread, and instant messaging services like ICQ and AOL Instant Messenger gained popularity, allowing for real-time text communication.''';
|
||||
|
||||
Document buildTestDocument() {
|
||||
return Document(
|
||||
root: pageNode(
|
||||
children: [
|
||||
paragraphNode(delta: Delta()..insert(text1)),
|
||||
paragraphNode(delta: Delta()..insert(text2)),
|
||||
paragraphNode(delta: Delta()..insert(text3)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 1. create a document with 3 paragraph nodes
|
||||
// 2. use the text robot to replace the selected content in the multiple lines
|
||||
// 3. check the document
|
||||
test(
|
||||
'the selection starts with the first paragraph and ends with the middle of second paragraph',
|
||||
() async {
|
||||
final document = buildTestDocument();
|
||||
final editorState = EditorState(document: document);
|
||||
|
||||
editorState.selection = Selection(
|
||||
start: Position(
|
||||
path: [0],
|
||||
),
|
||||
end: Position(
|
||||
path: [1],
|
||||
offset: text2.length -
|
||||
', opening the floodgates for mass adoption. '.length,
|
||||
),
|
||||
);
|
||||
|
||||
final markdownText =
|
||||
'''The **introduction** of the World Wide Web in the *early 1990s* marked a significant turning point.
|
||||
|
||||
Tim Berners-Lee's **revolutionary invention** made the internet accessible to non-technical users''';
|
||||
final markdownTextRobot = MarkdownTextRobot(
|
||||
editorState: editorState,
|
||||
);
|
||||
await markdownTextRobot.replace(
|
||||
selection: editorState.selection!,
|
||||
markdownText: markdownText,
|
||||
);
|
||||
|
||||
final afterNodes = editorState.document.root.children;
|
||||
expect(afterNodes.length, 3);
|
||||
|
||||
{
|
||||
// first paragraph
|
||||
final delta1 = afterNodes[0].delta!.toList();
|
||||
expect(delta1.length, 5);
|
||||
|
||||
final d1 = delta1[0] as TextInsert;
|
||||
expect(d1.text, 'The ');
|
||||
expect(d1.attributes, null);
|
||||
|
||||
final d2 = delta1[1] as TextInsert;
|
||||
expect(d2.text, 'introduction');
|
||||
expect(d2.attributes, {AppFlowyRichTextKeys.bold: true});
|
||||
|
||||
final d3 = delta1[2] as TextInsert;
|
||||
expect(d3.text, ' of the World Wide Web in the ');
|
||||
expect(d3.attributes, null);
|
||||
|
||||
final d4 = delta1[3] as TextInsert;
|
||||
expect(d4.text, 'early 1990s');
|
||||
expect(d4.attributes, {AppFlowyRichTextKeys.italic: true});
|
||||
|
||||
final d5 = delta1[4] as TextInsert;
|
||||
expect(d5.text, ' marked a significant turning point.');
|
||||
expect(d5.attributes, null);
|
||||
}
|
||||
|
||||
{
|
||||
// second paragraph
|
||||
final delta2 = afterNodes[1].delta!.toList();
|
||||
expect(delta2.length, 3);
|
||||
|
||||
final d1 = delta2[0] as TextInsert;
|
||||
expect(d1.text, "Tim Berners-Lee's ");
|
||||
expect(d1.attributes, null);
|
||||
|
||||
final d2 = delta2[1] as TextInsert;
|
||||
expect(d2.text, "revolutionary invention");
|
||||
expect(d2.attributes, {AppFlowyRichTextKeys.bold: true});
|
||||
|
||||
final d3 = delta2[2] as TextInsert;
|
||||
expect(
|
||||
d3.text,
|
||||
" made the internet accessible to non-technical users, opening the floodgates for mass adoption. ",
|
||||
);
|
||||
expect(d3.attributes, null);
|
||||
}
|
||||
|
||||
{
|
||||
// third paragraph
|
||||
final delta3 = afterNodes[2].delta!.toList();
|
||||
expect(delta3.length, 1);
|
||||
|
||||
final d1 = delta3[0] as TextInsert;
|
||||
expect(d1.text, text3);
|
||||
expect(d1.attributes, null);
|
||||
}
|
||||
});
|
||||
|
||||
test(
|
||||
'the selection starts with the middle of the first paragraph and ends with the middle of last paragraph',
|
||||
() async {
|
||||
final document = buildTestDocument();
|
||||
final editorState = EditorState(document: document);
|
||||
|
||||
editorState.selection = Selection(
|
||||
start: Position(
|
||||
path: [0],
|
||||
offset: 'The introduction of the World Wide Web'.length,
|
||||
),
|
||||
end: Position(
|
||||
path: [2],
|
||||
offset:
|
||||
'Email became widespread, and instant messaging services like ICQ and AOL Instant Messenger gained popularity'
|
||||
.length,
|
||||
),
|
||||
);
|
||||
|
||||
final markdownText =
|
||||
''' in the **early 1990s** marked a *significant turning point* in technological history.
|
||||
|
||||
Tim Berners-Lee's **revolutionary invention** made the internet accessible to non-technical users, opening the floodgates for *unprecedented mass adoption*.
|
||||
|
||||
Email became **widely prevalent**, and instant messaging services like *ICQ* and *AOL Instant Messenger* gained tremendous popularity
|
||||
''';
|
||||
final markdownTextRobot = MarkdownTextRobot(
|
||||
editorState: editorState,
|
||||
);
|
||||
await markdownTextRobot.replace(
|
||||
selection: editorState.selection!,
|
||||
markdownText: markdownText,
|
||||
);
|
||||
|
||||
final afterNodes = editorState.document.root.children;
|
||||
expect(afterNodes.length, 3);
|
||||
|
||||
{
|
||||
// first paragraph
|
||||
final delta1 = afterNodes[0].delta!.toList();
|
||||
expect(delta1.length, 5);
|
||||
|
||||
final d1 = delta1[0] as TextInsert;
|
||||
expect(d1.text, 'The introduction of the World Wide Web in the ');
|
||||
expect(d1.attributes, null);
|
||||
|
||||
final d2 = delta1[1] as TextInsert;
|
||||
expect(d2.text, 'early 1990s');
|
||||
expect(d2.attributes, {AppFlowyRichTextKeys.bold: true});
|
||||
|
||||
final d3 = delta1[2] as TextInsert;
|
||||
expect(d3.text, ' marked a ');
|
||||
expect(d3.attributes, null);
|
||||
|
||||
final d4 = delta1[3] as TextInsert;
|
||||
expect(d4.text, 'significant turning point');
|
||||
expect(d4.attributes, {AppFlowyRichTextKeys.italic: true});
|
||||
|
||||
final d5 = delta1[4] as TextInsert;
|
||||
expect(d5.text, ' in technological history.');
|
||||
expect(d5.attributes, null);
|
||||
}
|
||||
|
||||
{
|
||||
// second paragraph
|
||||
final delta2 = afterNodes[1].delta!.toList();
|
||||
expect(delta2.length, 5);
|
||||
|
||||
final d1 = delta2[0] as TextInsert;
|
||||
expect(d1.text, "Tim Berners-Lee's ");
|
||||
expect(d1.attributes, null);
|
||||
|
||||
final d2 = delta2[1] as TextInsert;
|
||||
expect(d2.text, "revolutionary invention");
|
||||
expect(d2.attributes, {AppFlowyRichTextKeys.bold: true});
|
||||
|
||||
final d3 = delta2[2] as TextInsert;
|
||||
expect(
|
||||
d3.text,
|
||||
" made the internet accessible to non-technical users, opening the floodgates for ",
|
||||
);
|
||||
expect(d3.attributes, null);
|
||||
|
||||
final d4 = delta2[3] as TextInsert;
|
||||
expect(d4.text, "unprecedented mass adoption");
|
||||
expect(d4.attributes, {AppFlowyRichTextKeys.italic: true});
|
||||
|
||||
final d5 = delta2[4] as TextInsert;
|
||||
expect(d5.text, ".");
|
||||
expect(d5.attributes, null);
|
||||
}
|
||||
|
||||
{
|
||||
// third paragraph
|
||||
// third paragraph
|
||||
final delta3 = afterNodes[2].delta!.toList();
|
||||
expect(delta3.length, 7);
|
||||
|
||||
final d1 = delta3[0] as TextInsert;
|
||||
expect(d1.text, "Email became ");
|
||||
expect(d1.attributes, null);
|
||||
|
||||
final d2 = delta3[1] as TextInsert;
|
||||
expect(d2.text, "widely prevalent");
|
||||
expect(d2.attributes, {AppFlowyRichTextKeys.bold: true});
|
||||
|
||||
final d3 = delta3[2] as TextInsert;
|
||||
expect(d3.text, ", and instant messaging services like ");
|
||||
expect(d3.attributes, null);
|
||||
|
||||
final d4 = delta3[3] as TextInsert;
|
||||
expect(d4.text, "ICQ");
|
||||
expect(d4.attributes, {AppFlowyRichTextKeys.italic: true});
|
||||
|
||||
final d5 = delta3[4] as TextInsert;
|
||||
expect(d5.text, " and ");
|
||||
expect(d5.attributes, null);
|
||||
|
||||
final d6 = delta3[5] as TextInsert;
|
||||
expect(d6.text, "AOL Instant Messenger");
|
||||
expect(d6.attributes, {AppFlowyRichTextKeys.italic: true});
|
||||
|
||||
final d7 = delta3[6] as TextInsert;
|
||||
expect(
|
||||
d7.text,
|
||||
" gained tremendous popularity, allowing for real-time text communication.",
|
||||
);
|
||||
expect(d7.attributes, null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const _sample1 = '''# The Curious Cat
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue