Browse Source

refactor: rename highlightColor to backgroundColor

Vincent Chan 2 years ago
parent
commit
20fb714550

+ 1 - 1
frontend/app_flowy/packages/flowy_editor/example/assets/example.json

@@ -73,7 +73,7 @@
           },
           {
             "insert": "  /  ",
-            "attributes": { "highlightColor": "0xFFFFFF00" }
+            "attributes": { "backgroundColor": "0xFFFFFF00" }
           },
           {
             "insert": "to see all the types of content you can add - entity, headers, videos, sub pages, etc."

+ 56 - 4
frontend/app_flowy/packages/flowy_editor/lib/infra/html_converter.dart

@@ -4,6 +4,7 @@ import 'package:flowy_editor/document/attributes.dart';
 import 'package:flowy_editor/document/node.dart';
 import 'package:flowy_editor/document/text_delta.dart';
 import 'package:flowy_editor/render/rich_text/rich_text_style.dart';
+import 'package:flowy_editor/service/internal_key_event_handlers/delete_text_handler.dart';
 import 'package:html/parser.dart' show parse;
 import 'package:html/dom.dart' as html;
 
@@ -239,7 +240,28 @@ class NodesToHTMLConverter {
   final List<html.Node> _result = [];
   html.Element? _stashListContainer;
 
-  NodesToHTMLConverter({required this.nodes, this.startOffset, this.endOffset});
+  NodesToHTMLConverter(
+      {required this.nodes, this.startOffset, this.endOffset}) {
+    if (nodes.isEmpty) {
+      return;
+    } else if (nodes.length == 1) {
+      final first = nodes.first;
+      if (first is TextNode) {
+        nodes[0] = first.copyWith(
+            delta: first.delta.slice(startOffset ?? 0, endOffset));
+      }
+    } else {
+      final first = nodes.first;
+      final last = nodes.last;
+      if (first is TextNode) {
+        nodes[0] = first.copyWith(delta: first.delta.slice(startOffset ?? 0));
+      }
+      if (last is TextNode) {
+        nodes[nodes.length - 1] =
+            last.copyWith(delta: last.delta.slice(0, endOffset));
+      }
+    }
+  }
 
   List<html.Node> toHTMLNodes() {
     for (final node in nodes) {
@@ -296,6 +318,26 @@ class NodesToHTMLConverter {
         checked: textNode.attributes["checkbox"] == true);
   }
 
+  String _attributesToCssStyle(Map<String, dynamic> attributes) {
+    final cssMap = <String, String>{};
+    if (attributes[StyleKey.backgroundColor] != null) {
+      cssMap["background-color"] = attributes[StyleKey.backgroundColor];
+    } else if (attributes[StyleKey.color] != null) {
+      cssMap["color"] = attributes[StyleKey.color];
+    }
+    return _cssMapToCssStyle(cssMap);
+  }
+
+  String _cssMapToCssStyle(Map<String, String> cssMap) {
+    return cssMap.entries.fold("", (previousValue, element) {
+      final kv = '${element.key}: ${element.value}';
+      if (previousValue.isEmpty) {
+        return kv;
+      }
+      return '$previousValue; $kv"';
+    });
+  }
+
   html.Element _deltaToHtml(Delta delta,
       {String? subType, int? end, bool? checked}) {
     if (end != null) {
@@ -319,9 +361,19 @@ class NodesToHTMLConverter {
       if (op is TextInsert) {
         final attributes = op.attributes;
         if (attributes != null && attributes[StyleKey.bold] == true) {
-          final strong = html.Element.tag("strong");
-          strong.append(html.Text(op.content));
-          childNodes.add(strong);
+          if (attributes.length == 1 && attributes[StyleKey.bold] == true) {
+            final strong = html.Element.tag(tagStrong);
+            strong.append(html.Text(op.content));
+            childNodes.add(strong);
+          } else {
+            final span = html.Element.tag(tagSpan);
+            final cssString = _attributesToCssStyle(attributes);
+            if (cssString.isNotEmpty) {
+              span.attributes["style"] = cssString;
+            }
+            span.append(html.Text(op.content));
+            childNodes.add(span);
+          }
         } else {
           childNodes.add(html.Text(op.content));
         }

+ 7 - 7
frontend/app_flowy/packages/flowy_editor/lib/render/rich_text/rich_text_style.dart

@@ -22,7 +22,7 @@ class StyleKey {
   static String underline = 'underline';
   static String strikethrough = 'strikethrough';
   static String color = 'color';
-  static String highlightColor = 'highlightColor';
+  static String backgroundColor = 'backgroundColor';
   static String font = 'font';
   static String href = 'href';
 
@@ -151,11 +151,11 @@ extension DeltaAttributesExtensions on Attributes {
     return null;
   }
 
-  Color? get highlightColor {
-    if (containsKey(StyleKey.highlightColor) &&
-        this[StyleKey.highlightColor] is String) {
+  Color? get backgroundColor {
+    if (containsKey(StyleKey.backgroundColor) &&
+        this[StyleKey.backgroundColor] is String) {
       return Color(
-        int.parse(this[StyleKey.highlightColor]),
+        int.parse(this[StyleKey.backgroundColor]),
       );
     }
     return null;
@@ -266,8 +266,8 @@ class RichTextStyle {
   }
 
   Color? get _backgroundColor {
-    if (attributes.highlightColor != null) {
-      return attributes.highlightColor!;
+    if (attributes.backgroundColor != null) {
+      return attributes.backgroundColor!;
     } else if (attributes.code) {
       return Colors.grey.withOpacity(0.4);
     }

+ 10 - 2
frontend/app_flowy/packages/flowy_editor/lib/service/internal_key_event_handlers/copy_paste_handler.dart

@@ -15,7 +15,11 @@ _handleCopy(EditorState editorState) async {
     final nodeAtPath = editorState.document.nodeAtPath(selection.end.path)!;
     if (nodeAtPath.type == "text") {
       final textNode = nodeAtPath as TextNode;
-      final htmlString = NodesToHTMLConverter(nodes: [textNode]).toHTMLString();
+      final htmlString = NodesToHTMLConverter(
+              nodes: [textNode],
+              startOffset: selection.start.offset,
+              endOffset: selection.end.offset)
+          .toHTMLString();
       debugPrint('copy html: $htmlString');
       RichClipboard.setData(RichClipboardData(html: htmlString));
     } else {
@@ -29,7 +33,11 @@ _handleCopy(EditorState editorState) async {
 
   final nodes = NodeIterator(editorState.document, beginNode, endNode).toList();
 
-  final copyString = NodesToHTMLConverter(nodes: nodes).toHTMLString();
+  final copyString = NodesToHTMLConverter(
+          nodes: nodes,
+          startOffset: selection.start.offset,
+          endOffset: selection.end.offset)
+      .toHTMLString();
   debugPrint('copy html: $copyString');
   RichClipboard.setData(RichClipboardData(html: copyString));
 }