From 67fd06366e8830cfb59d7787761f49ae39cb69e5 Mon Sep 17 00:00:00 2001 From: Vincent Chan Date: Tue, 2 Aug 2022 15:19:17 +0800 Subject: [PATCH] feat: handle HTMLElement --- .../example/lib/plugin/image_node_widget.dart | 3 +- .../lib/infra/html_converter.dart | 94 +++++++++++++++++-- 2 files changed, 89 insertions(+), 8 deletions(-) diff --git a/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/image_node_widget.dart b/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/image_node_widget.dart index 6a01fb6430..417d1ce11c 100644 --- a/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/image_node_widget.dart +++ b/frontend/app_flowy/packages/flowy_editor/example/lib/plugin/image_node_widget.dart @@ -90,8 +90,7 @@ class _ImageNodeWidgetState extends State with Selectable { @override Position getPositionInOffset(Offset start) { - // TODO: implement getPositionInOffset - throw UnimplementedError(); + return Position(path: node.path, offset: 0); } @override 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 40687ca160..e39d082607 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 @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:flowy_editor/document/node.dart'; import 'package:flowy_editor/document/text_delta.dart'; import 'package:html/parser.dart' show parse; @@ -10,17 +12,97 @@ class HTMLConverter { List toNodes() { final result = []; - final delta = Delta(); final bodyChildren = _document.body?.children ?? []; for (final child in bodyChildren) { - delta.insert(child.text); - } - - if (delta.operations.isNotEmpty) { - result.add(TextNode(type: "text", delta: delta)); + _handleElement(result, child); } return result; } + + _handleElement(List nodes, html.Element element) { + if (element.localName == "h1") { + _handleHeadingElement(nodes, element, "h1"); + } else if (element.localName == "h2") { + _handleHeadingElement(nodes, element, "h2"); + } else if (element.localName == "h3") { + _handleHeadingElement(nodes, element, "h3"); + } else if (element.localName == "ul") { + _handleUnorderedList(nodes, element); + } else if (element.localName == "li") { + _handleListElement(nodes, element); + } else if (element.localName == "p") { + _handleParagraph(nodes, element); + } else { + final delta = Delta(); + delta.insert(element.text); + if (delta.operations.isNotEmpty) { + nodes.add(TextNode(type: "text", delta: delta)); + } + } + } + + _handleParagraph(List nodes, html.Element element) { + for (final child in element.children) { + if (child.localName == "a") { + _handleAnchorLink(nodes, child); + } + } + + final delta = Delta(); + delta.insert(element.text); + if (delta.operations.isNotEmpty) { + nodes.add(TextNode(type: "text", delta: delta)); + } + } + + _handleAnchorLink(List nodes, html.Element element) { + for (final child in element.children) { + if (child.localName == "img") { + _handleImage(nodes, child); + return; + } + } + } + + _handleImage(List nodes, html.Element element) { + final src = element.attributes["src"]; + final attributes = {}; + if (src != null) { + attributes["image_src"] = src; + } + nodes.add( + Node(type: "image", attributes: attributes, children: LinkedList())); + } + + _handleUnorderedList(List nodes, html.Element element) { + element.children.forEach((child) { + _handleListElement(nodes, child); + }); + } + + _handleHeadingElement( + List nodes, + html.Element element, + String headingStyle, + ) { + final delta = Delta(); + delta.insert(element.text); + if (delta.operations.isNotEmpty) { + nodes.add(TextNode( + type: "text", + attributes: {"subtype": "heading", "heading": headingStyle}, + delta: delta)); + } + } + + _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)); + } + } }