diff --git a/frontend/app_flowy/packages/flowy_editor/lib/infra/html_converter.dart b/frontend/app_flowy/packages/flowy_editor/lib/infra/html_converter.dart index 608020e327..ece4f6b9f4 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/infra/html_converter.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/infra/html_converter.dart @@ -15,12 +15,13 @@ class HTMLConverter { final result = []; final delta = Delta(); - for (final child in _document.body?.nodes.toList() ?? []) { + final childNodes = _document.body?.nodes.toList() ?? []; + 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 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? 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 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? 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 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); + } } } } diff --git a/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/copy_paste_handler.dart b/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/copy_paste_handler.dart index 4eea454605..d7eda6b64a 100644 --- a/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/copy_paste_handler.dart +++ b/frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/copy_paste_handler.dart @@ -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))); }