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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final markdownNodes = customMarkdownToDocument(
|
||||||
|
markdownText,
|
||||||
|
tableWidth: 250.0,
|
||||||
|
).root.children;
|
||||||
|
|
||||||
// Get the selected nodes.
|
// Get the selected nodes.
|
||||||
final nodes = editorState.getNodesInSelection(selection);
|
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);
|
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
|
const _sample1 = '''# The Curious Cat
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue