feat: paste html rich text inside text

This commit is contained in:
Vincent Chan 2022-08-03 15:30:00 +08:00
parent aba84a3ccd
commit e73465170a
2 changed files with 58 additions and 20 deletions

View File

@ -15,12 +15,13 @@ class HTMLConverter {
final result = <Node>[];
final delta = Delta();
for (final child in _document.body?.nodes.toList() ?? <html.Node>[]) {
final childNodes = _document.body?.nodes.toList() ?? <html.Node>[];
for (final child in childNodes) {
if (child is html.Element) {
if (child.localName == "span") {
delta.insert(child.text);
} else if (child.localName == "strong") {
delta.insert(child.text, {"bold": true});
if (child.localName == "a" ||
child.localName == "span" ||
child.localName == "strong") {
_handleRichTextElement(delta, child);
} else {
_handleElement(result, child);
}
@ -59,6 +60,25 @@ class HTMLConverter {
}
_handleParagraph(List<Node> nodes, html.Element element) {
_handleRichText(nodes, element);
}
_handleRichTextElement(Delta delta, html.Element element) {
if (element.localName == "span") {
delta.insert(element.text);
} else if (element.localName == "a") {
final hyperLink = element.attributes["href"];
Map<String, dynamic>? attributes;
if (hyperLink != null) {
attributes = {"href": hyperLink};
}
delta.insert(element.text, attributes);
} else if (element.localName == "strong") {
delta.insert(element.text, {"bold": true});
}
}
_handleRichText(List<Node> nodes, html.Element element) {
final image = element.querySelector("img");
if (image != null) {
_handleImage(nodes, image);
@ -69,13 +89,10 @@ class HTMLConverter {
for (final child in element.nodes.toList()) {
if (child is html.Element) {
if (child.localName == "a") {
final hyperLink = child.attributes["href"];
Map<String, dynamic>? attributes;
if (hyperLink != null) {
attributes = {"href": hyperLink};
}
delta.insert(child.text, attributes);
if (child.localName == "a" ||
child.localName == "span" ||
child.localName == "strong") {
_handleRichTextElement(delta, element);
} else {
delta.insert(child.text);
}
@ -122,11 +139,11 @@ class HTMLConverter {
}
_handleListElement(List<Node> nodes, html.Element element) {
final delta = Delta();
delta.insert(element.text);
if (delta.operations.isNotEmpty) {
nodes.add(TextNode(
type: "text", attributes: {"subtype": "bullet-list"}, delta: delta));
final childNodes = element.nodes.toList();
for (final child in childNodes) {
if (child is html.Element) {
_handleRichText(nodes, child);
}
}
}
}

View File

@ -10,8 +10,6 @@ _handleCopy() async {
}
_pasteHTML(EditorState editorState, String html) {
final converter = HTMLConverter(html);
final nodes = converter.toNodes();
final selection = editorState.cursorSelection;
if (selection == null) {
return;
@ -21,9 +19,31 @@ _pasteHTML(EditorState editorState, String html) {
if (path.isEmpty) {
return;
}
path[path.length - 1]++;
final converter = HTMLConverter(html);
final nodes = converter.toNodes();
if (nodes.isEmpty) {
return;
} else if (nodes.length == 1) {
final firstNode = nodes[0];
final nodeAtPath = editorState.document.nodeAtPath(path)!;
final tb = TransactionBuilder(editorState);
final startOffset = selection.start.offset;
if (nodeAtPath.type == "text" && firstNode.type == "text") {
final textNodeAtPath = nodeAtPath as TextNode;
final firstTextNode = firstNode as TextNode;
tb.textEdit(textNodeAtPath,
() => Delta().retain(startOffset).concat(firstTextNode.delta));
tb.setAfterSelection(Selection.collapsed(Position(
path: path, offset: startOffset + firstTextNode.delta.length)));
}
tb.commit();
return;
}
final tb = TransactionBuilder(editorState);
path[path.length - 1]++;
tb.insertNodes(path, nodes);
tb.commit();
}
@ -98,6 +118,7 @@ _handlePastePlainText(EditorState editorState, String plainText) {
tb.insertNodes(path, nodes);
tb.commit();
// fixme: don't set the cursor manually
editorState.updateCursorSelection(Selection.collapsed(
Position(path: nodes.last.path, offset: lines.last.length)));
}