Przeglądaj źródła

refactor: move node to core/document

Lucas.Xu 2 lat temu
rodzic
commit
11eca2b3d9
58 zmienionych plików z 281 dodań i 282 usunięć
  1. 2 3
      frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/code_block_node_widget.dart
  2. 2 3
      frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/horizontal_rule_node_widget.dart
  3. 1 1
      frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/tex_block_node_widget.dart
  4. 1 1
      frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/underscore_to_italic.dart
  5. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/appflowy_editor.dart
  6. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/commands/edit_text.dart
  7. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/commands/format_built_in_text.dart
  8. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/commands/format_text.dart
  9. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/commands/text_command_infra.dart
  10. 80 83
      frontend/app_flowy/packages/appflowy_editor/lib/src/core/document/node.dart
  11. 34 31
      frontend/app_flowy/packages/appflowy_editor/lib/src/document/attributes.dart
  12. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/document/node_iterator.dart
  13. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/document/state_tree.dart
  14. 18 7
      frontend/app_flowy/packages/appflowy_editor/lib/src/document/text_delta.dart
  15. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/extensions/node_extensions.dart
  16. 4 4
      frontend/app_flowy/packages/appflowy_editor/lib/src/extensions/text_node_extensions.dart
  17. 4 6
      frontend/app_flowy/packages/appflowy_editor/lib/src/infra/html_converter.dart
  18. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/infra/infra.dart
  19. 2 3
      frontend/app_flowy/packages/appflowy_editor/lib/src/operation/transaction_builder.dart
  20. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/editor/editor_entry.dart
  21. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/image/image_node_builder.dart
  22. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/image/image_node_widget.dart
  23. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/image/image_upload_widget.dart
  24. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/bulleted_list_text.dart
  25. 2 2
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/flowy_rich_text.dart
  26. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/heading_text.dart
  27. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/number_list_text.dart
  28. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/quoted_text.dart
  29. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/rich_text.dart
  30. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_widget.dart
  31. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/render/style/editor_style.dart
  32. 4 4
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/default_text_operations/format_rich_text_style.dart
  33. 2 2
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/input_service.dart
  34. 2 2
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/backspace_handler.dart
  35. 5 6
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/copy_paste_handler.dart
  36. 3 3
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart
  37. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/format_style_handler.dart
  38. 4 4
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/markdown_syntax_to_styled_text.dart
  39. 2 2
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/markdown_syntax_to_styled_text_handler.dart
  40. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/select_all_handler.dart
  41. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/slash_handler.dart
  42. 5 5
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/whitespace_handler.dart
  43. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/render_plugin_service.dart
  44. 1 1
      frontend/app_flowy/packages/appflowy_editor/lib/src/service/selection_service.dart
  45. 3 5
      frontend/app_flowy/packages/appflowy_editor/test/document/node_test.dart
  46. 0 1
      frontend/app_flowy/packages/appflowy_editor/test/infra/infra_test.dart
  47. 1 2
      frontend/app_flowy/packages/appflowy_editor/test/infra/test_editor.dart
  48. 5 5
      frontend/app_flowy/packages/appflowy_editor/test/legacy/delta_test.dart
  49. 1 1
      frontend/app_flowy/packages/appflowy_editor/test/legacy/operation_test.dart
  50. 9 9
      frontend/app_flowy/packages/appflowy_editor/test/legacy/undo_manager_test.dart
  51. 1 1
      frontend/app_flowy/packages/appflowy_editor/test/render/selection_menu/selection_menu_widget_test.dart
  52. 12 14
      frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/backspace_handler_test.dart
  53. 6 6
      frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler_test.dart
  54. 18 18
      frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/markdown_syntax_to_styled_text_handler_test.dart
  55. 18 18
      frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/markdown_syntax_to_styled_text_test.dart
  56. 1 1
      frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/redo_undo_handler_test.dart
  57. 2 2
      frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/space_on_web_handler_test.dart
  58. 2 2
      frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/white_space_handler_test.dart

+ 2 - 3
frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/code_block_node_widget.dart

@@ -60,7 +60,7 @@ SelectionMenuItem codeBlockMenuItem = SelectionMenuItem(
     if (selection == null || textNodes.isEmpty) {
       return;
     }
-    if (textNodes.first.toRawString().isEmpty) {
+    if (textNodes.first.toPlainText().isEmpty) {
       TransactionBuilder(editorState)
         ..updateNode(textNodes.first, {
           'subtype': 'code_block',
@@ -74,7 +74,6 @@ SelectionMenuItem codeBlockMenuItem = SelectionMenuItem(
         ..insertNode(
           selection.end.path.next,
           TextNode(
-            type: 'text',
             children: LinkedList(),
             attributes: {
               'subtype': 'code_block',
@@ -149,7 +148,7 @@ class __CodeBlockNodeWidgeState extends State<_CodeBlockNodeWidge>
 
   Widget _buildCodeBlock(BuildContext context) {
     final result = highlight.highlight.parse(
-      widget.textNode.toRawString(),
+      widget.textNode.toPlainText(),
       language: _language,
       autoDetection: _language == null,
     );

+ 2 - 3
frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/horizontal_rule_node_widget.dart

@@ -17,7 +17,7 @@ ShortcutEventHandler _insertHorzaontalRule = (editorState, event) {
     return KeyEventResult.ignored;
   }
   final textNode = textNodes.first;
-  if (textNode.toRawString() == '--') {
+  if (textNode.toPlainText() == '--') {
     TransactionBuilder(editorState)
       ..deleteText(textNode, 0, 2)
       ..insertNode(
@@ -53,7 +53,7 @@ SelectionMenuItem horizontalRuleMenuItem = SelectionMenuItem(
       return;
     }
     final textNode = textNodes.first;
-    if (textNode.toRawString().isEmpty) {
+    if (textNode.toPlainText().isEmpty) {
       TransactionBuilder(editorState)
         ..insertNode(
           textNode.path,
@@ -71,7 +71,6 @@ SelectionMenuItem horizontalRuleMenuItem = SelectionMenuItem(
         ..insertNode(
           selection.end.path.next,
           TextNode(
-            type: 'text',
             children: LinkedList(),
             attributes: {
               'subtype': 'horizontal_rule',

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/tex_block_node_widget.dart

@@ -21,7 +21,7 @@ SelectionMenuItem teXBlockMenuItem = SelectionMenuItem(
       return;
     }
     final Path texNodePath;
-    if (textNodes.first.toRawString().isEmpty) {
+    if (textNodes.first.toPlainText().isEmpty) {
       texNodePath = selection.end.path;
       TransactionBuilder(editorState)
         ..insertNode(

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/underscore_to_italic.dart

@@ -18,7 +18,7 @@ ShortcutEventHandler _underscoreToItalicHandler = (editorState, event) {
   }
 
   final textNode = textNodes.first;
-  final text = textNode.toRawString();
+  final text = textNode.toPlainText();
   // Determine if an 'underscore' already exists in the text node and only once.
   final firstUnderscore = text.indexOf('_');
   final lastUnderscore = text.lastIndexOf('_');

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/appflowy_editor.dart

@@ -3,7 +3,7 @@ library appflowy_editor;
 
 export 'src/infra/log.dart';
 export 'src/render/style/editor_style.dart';
-export 'src/document/node.dart';
+export 'src/core/document/node.dart';
 export 'src/document/path.dart';
 export 'src/document/position.dart';
 export 'src/document/selection.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/commands/edit_text.dart

@@ -1,7 +1,7 @@
 import 'dart:async';
 
 import 'package:appflowy_editor/src/commands/text_command_infra.dart';
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/operation/transaction_builder.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/commands/format_built_in_text.dart

@@ -2,7 +2,7 @@ import 'package:appflowy_editor/src/commands/format_text.dart';
 import 'package:appflowy_editor/src/commands/text_command_infra.dart';
 import 'package:appflowy_editor/src/document/attributes.dart';
 import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/editor_state.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/commands/format_text.dart

@@ -2,7 +2,7 @@ import 'dart:async';
 
 import 'package:appflowy_editor/src/commands/text_command_infra.dart';
 import 'package:appflowy_editor/src/document/attributes.dart';
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/editor_state.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/commands/text_command_infra.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/editor_state.dart';

+ 80 - 83
frontend/app_flowy/packages/appflowy_editor/lib/src/document/node.dart → frontend/app_flowy/packages/appflowy_editor/lib/src/core/document/node.dart

@@ -1,47 +1,21 @@
 import 'dart:collection';
+
+import 'package:flutter/material.dart';
+
+import 'package:appflowy_editor/src/document/attributes.dart';
+import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/document/text_delta.dart';
-import 'package:flutter/material.dart';
-import './attributes.dart';
 
 class Node extends ChangeNotifier with LinkedListEntry<Node> {
-  Node? parent;
-  final String type;
-  final LinkedList<Node> children;
-  Attributes _attributes;
-
-  GlobalKey? key;
-  // TODO: abstract a selectable node??
-  final layerLink = LayerLink();
-
-  String? get subtype {
-    // TODO: make 'subtype' as a const value.
-    if (_attributes.containsKey('subtype')) {
-      assert(_attributes['subtype'] is String?,
-          'subtype must be a [String] or [null]');
-      return _attributes['subtype'] as String?;
-    }
-    return null;
-  }
-
-  String get id {
-    if (subtype != null) {
-      return '$type/$subtype';
-    }
-    return type;
-  }
-
-  Path get path => _path();
-
-  Attributes get attributes => _attributes;
-
   Node({
     required this.type,
-    required this.children,
-    required Attributes attributes,
+    Attributes? attributes,
     this.parent,
-  }) : _attributes = attributes {
-    for (final child in children) {
+    LinkedList<Node>? children,
+  })  : children = children ?? LinkedList<Node>(),
+        _attributes = attributes ?? {} {
+    for (final child in this.children) {
       child.parent = this;
     }
   }
@@ -49,14 +23,13 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
   factory Node.fromJson(Map<String, Object> json) {
     assert(json['type'] is String);
 
-    // TODO: check the type that not exist on plugins.
     final jType = json['type'] as String;
     final jChildren = json['children'] as List?;
     final jAttributes = json['attributes'] != null
         ? Attributes.from(json['attributes'] as Map)
         : Attributes.from({});
 
-    final LinkedList<Node> children = LinkedList();
+    final children = LinkedList<Node>();
     if (jChildren != null) {
       children.addAll(
         jChildren.map(
@@ -69,14 +42,14 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
 
     Node node;
 
-    if (jType == "text") {
+    if (jType == 'text') {
       final jDelta = json['delta'] as List<dynamic>?;
       final delta = jDelta == null ? Delta() : Delta.fromJson(jDelta);
       node = TextNode(
-          type: jType,
-          children: children,
-          attributes: jAttributes,
-          delta: delta);
+        children: children,
+        attributes: jAttributes,
+        delta: delta,
+      );
     } else {
       node = Node(
         type: jType,
@@ -92,20 +65,48 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
     return node;
   }
 
+  final String type;
+  final LinkedList<Node> children;
+  Node? parent;
+  Attributes _attributes;
+
+  // Renderable
+  GlobalKey? key;
+  final layerLink = LayerLink();
+
+  Attributes get attributes => {..._attributes};
+
+  String get id {
+    if (subtype != null) {
+      return '$type/$subtype';
+    }
+    return type;
+  }
+
+  String? get subtype {
+    if (attributes[BuiltInAttributeKey.subtype] is String) {
+      return attributes[BuiltInAttributeKey.subtype] as String;
+    }
+    return null;
+  }
+
+  Path get path => _computePath();
+
   void updateAttributes(Attributes attributes) {
-    final oldAttributes = {..._attributes};
-    _attributes = composeAttributes(_attributes, attributes) ?? {};
+    final oldAttributes = this.attributes;
+
+    _attributes = composeAttributes(this.attributes, attributes) ?? {};
 
     // Notifies the new attributes
     // if attributes contains 'subtype', should notify parent to rebuild node
     // else, just notify current node.
     bool shouldNotifyParent =
-        _attributes['subtype'] != oldAttributes['subtype'];
+        this.attributes['subtype'] != oldAttributes['subtype'];
     shouldNotifyParent ? parent?.notifyListeners() : notifyListeners();
   }
 
   Node? childAtIndex(int index) {
-    if (children.length <= index) {
+    if (children.length <= index || index < 0) {
       return null;
     }
 
@@ -121,7 +122,8 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
   }
 
   void insert(Node entry, {int? index}) {
-    index ??= children.length;
+    final length = children.length;
+    index ??= length;
 
     if (children.isEmpty) {
       entry.parent = this;
@@ -130,8 +132,9 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
       return;
     }
 
-    final length = children.length;
-
+    // If index is out of range, insert at the end.
+    // If index is negative, insert at the beginning.
+    // If index is positive, insert at the index.
     if (index >= length) {
       children.last.insertAfter(entry);
     } else if (index <= 0) {
@@ -173,28 +176,14 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
     };
     if (children.isNotEmpty) {
       map['children'] =
-          (children.map((node) => node.toJson())).toList(growable: false);
+          children.map((node) => node.toJson()).toList(growable: false);
     }
-    if (_attributes.isNotEmpty) {
-      map['attributes'] = _attributes;
+    if (attributes.isNotEmpty) {
+      map['attributes'] = attributes;
     }
     return map;
   }
 
-  Path _path([Path previous = const []]) {
-    if (parent == null) {
-      return previous;
-    }
-    var index = 0;
-    for (var child in parent!.children) {
-      if (child == this) {
-        break;
-      }
-      index += 1;
-    }
-    return parent!._path([index, ...previous]);
-  }
-
   Node copyWith({
     String? type,
     LinkedList<Node>? children,
@@ -202,8 +191,8 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
   }) {
     final node = Node(
       type: type ?? this.type,
-      attributes: attributes ?? {..._attributes},
-      children: children ?? LinkedList(),
+      attributes: attributes ?? {...this.attributes},
+      children: children,
     );
     if (children == null && this.children.isNotEmpty) {
       for (final child in this.children) {
@@ -214,19 +203,31 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
     }
     return node;
   }
+
+  Path _computePath([Path previous = const []]) {
+    if (parent == null) {
+      return previous;
+    }
+    var index = 0;
+    for (final child in parent!.children) {
+      if (child == this) {
+        break;
+      }
+      index += 1;
+    }
+    return parent!._computePath([index, ...previous]);
+  }
 }
 
 class TextNode extends Node {
-  Delta _delta;
-
   TextNode({
-    required super.type,
     required Delta delta,
     LinkedList<Node>? children,
     Attributes? attributes,
   })  : _delta = delta,
         super(
-          children: children ?? LinkedList(),
+          type: 'text',
+          children: children,
           attributes: attributes ?? {},
         );
 
@@ -234,14 +235,11 @@ class TextNode extends Node {
       : _delta = Delta([TextInsert('')]),
         super(
           type: 'text',
-          children: LinkedList(),
           attributes: attributes ?? {},
         );
 
-  Delta get delta {
-    return _delta;
-  }
-
+  Delta _delta;
+  Delta get delta => _delta;
   set delta(Delta v) {
     _delta = v;
     notifyListeners();
@@ -250,21 +248,20 @@ class TextNode extends Node {
   @override
   Map<String, Object> toJson() {
     final map = super.toJson();
-    map['delta'] = _delta.toJson();
+    map['delta'] = delta.toJson();
     return map;
   }
 
   @override
   TextNode copyWith({
-    String? type,
+    String? type = 'text',
     LinkedList<Node>? children,
     Attributes? attributes,
     Delta? delta,
   }) {
     final textNode = TextNode(
-      type: type ?? this.type,
       children: children,
-      attributes: attributes ?? _attributes,
+      attributes: attributes ?? this.attributes,
       delta: delta ?? this.delta,
     );
     if (children == null && this.children.isNotEmpty) {
@@ -277,5 +274,5 @@ class TextNode extends Node {
     return textNode;
   }
 
-  String toRawString() => _delta.toRawString();
+  String toPlainText() => _delta.toPlainText();
 }

+ 34 - 31
frontend/app_flowy/packages/appflowy_editor/lib/src/document/attributes.dart

@@ -1,42 +1,45 @@
+/// Attributes is used to describe the Node's information.
+///
+/// Please note: The keywords in [BuiltInAttributeKey] are reserved.
 typedef Attributes = Map<String, dynamic>;
 
-int hashAttributes(Attributes attributes) {
-  return Object.hashAllUnordered(
-      attributes.entries.map((e) => Object.hash(e.key, e.value)));
+Attributes? composeAttributes(
+  Attributes? base,
+  Attributes? other, {
+  keepNull = false,
+}) {
+  base ??= {};
+  other ??= {};
+  Attributes attributes = {
+    ...base,
+    ...other,
+  };
+
+  if (!keepNull) {
+    attributes = Attributes.from(attributes)
+      ..removeWhere((_, value) => value == null);
+  }
+
+  return attributes.isNotEmpty ? attributes : null;
 }
 
-Attributes invertAttributes(Attributes? attr, Attributes? base) {
-  attr ??= {};
+Attributes invertAttributes(Attributes? base, Attributes? other) {
   base ??= {};
-  final Attributes baseInverted = base.keys.fold({}, (memo, key) {
-    if (base![key] != attr![key] && attr.containsKey(key)) {
-      memo[key] = base[key];
+  other ??= {};
+  final Attributes attributes = base.keys.fold({}, (previousValue, key) {
+    if (other!.containsKey(key) && other[key] != base![key]) {
+      previousValue[key] = base[key];
     }
-    return memo;
+    return previousValue;
   });
-  return attr.keys.fold(baseInverted, (memo, key) {
-    if (attr![key] != base![key] && !base.containsKey(key)) {
-      memo[key] = null;
+  return other.keys.fold(attributes, (previousValue, key) {
+    if (!base!.containsKey(key) && other![key] != base[key]) {
+      previousValue[key] = null;
     }
-    return memo;
+    return previousValue;
   });
 }
 
-Attributes? composeAttributes(Attributes? a, Attributes? b,
-    [bool keepNull = false]) {
-  a ??= {};
-  b ??= {};
-  Attributes attributes = {...b};
-
-  if (!keepNull) {
-    attributes = Map.from(attributes)..removeWhere((_, value) => value == null);
-  }
-
-  for (final entry in a.entries) {
-    if (!b.containsKey(entry.key)) {
-      attributes[entry.key] = entry.value;
-    }
-  }
-
-  return attributes.isNotEmpty ? attributes : null;
-}
+int hashAttributes(Attributes base) => Object.hashAllUnordered(
+      base.entries.map((e) => Object.hash(e.key, e.value)),
+    );

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/document/node_iterator.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 
 import './state_tree.dart';
 

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/document/state_tree.dart

@@ -1,6 +1,6 @@
 import 'dart:math';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/document/text_delta.dart';
 import './attributes.dart';

+ 18 - 7
frontend/app_flowy/packages/appflowy_editor/lib/src/document/text_delta.dart

@@ -47,7 +47,9 @@ class TextInsert extends TextOperation {
     final contentHash = content.hashCode;
     final attrs = _attributes;
     return Object.hash(
-        contentHash, attrs == null ? null : hashAttributes(attrs));
+      contentHash,
+      attrs != null ? hashAttributes(attrs) : null,
+    );
   }
 
   @override
@@ -101,7 +103,10 @@ class TextRetain extends TextOperation {
   @override
   int get hashCode {
     final attrs = _attributes;
-    return Object.hash(_length, attrs == null ? null : hashAttributes(attrs));
+    return Object.hash(
+      _length,
+      attrs != null ? hashAttributes(attrs) : null,
+    );
   }
 
   @override
@@ -401,7 +406,11 @@ class Delta extends Iterable<TextOperation> {
         final thisOp = thisIter._next(length);
         final otherOp = otherIter._next(length);
         final attributes = composeAttributes(
-            thisOp.attributes, otherOp.attributes, thisOp is TextRetain);
+          thisOp.attributes,
+          otherOp.attributes,
+          keepNull: thisOp is TextRetain,
+        );
+
         if (otherOp is TextRetain && otherOp.length > 0) {
           TextOperation? newOp;
           if (thisOp is TextRetain) {
@@ -480,8 +489,10 @@ class Delta extends Iterable<TextOperation> {
           if (op is TextDelete) {
             inverted.add(baseOp);
           } else if (op is TextRetain && op.attributes != null) {
-            inverted.retain(baseOp.length,
-                invertAttributes(op.attributes, baseOp.attributes));
+            inverted.retain(
+              baseOp.length,
+              invertAttributes(baseOp.attributes, op.attributes),
+            );
           }
         }
         return previousValue + length;
@@ -520,7 +531,7 @@ class Delta extends Iterable<TextOperation> {
   ///
   /// This method can help you to compute the position of the next character.
   int nextRunePosition(int pos) {
-    final stringContent = toRawString();
+    final stringContent = toPlainText();
     if (pos >= stringContent.length - 1) {
       return stringContent.length;
     }
@@ -535,7 +546,7 @@ class Delta extends Iterable<TextOperation> {
     return stringContent.length;
   }
 
-  String toRawString() {
+  String toPlainText() {
     _rawString ??=
         _operations.whereType<TextInsert>().map((op) => op.content).join();
     return _rawString!;

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/extensions/node_extensions.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/extensions/object_extensions.dart';
 import 'package:appflowy_editor/src/extensions/path_extensions.dart';

+ 4 - 4
frontend/app_flowy/packages/appflowy_editor/lib/src/extensions/text_node_extensions.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/document/position.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
@@ -171,7 +171,7 @@ extension TextNodesExtension on List<TextNode> {
         if (i == 0 && pathEquals(node.path, selection.start.path)) {
           if (selection.isBackward) {
             newSelection = selection.copyWith(
-              end: Position(path: node.path, offset: node.toRawString().length),
+              end: Position(path: node.path, offset: node.toPlainText().length),
             );
           } else {
             newSelection = selection.copyWith(
@@ -187,13 +187,13 @@ extension TextNodesExtension on List<TextNode> {
           } else {
             newSelection = selection.copyWith(
               start:
-                  Position(path: node.path, offset: node.toRawString().length),
+                  Position(path: node.path, offset: node.toPlainText().length),
             );
           }
         } else {
           newSelection = Selection(
             start: Position(path: node.path, offset: 0),
-            end: Position(path: node.path, offset: node.toRawString().length),
+            end: Position(path: node.path, offset: node.toPlainText().length),
           );
         }
         if (!node.allSatisfyInSelection(newSelection, styleKey, test)) {

+ 4 - 6
frontend/app_flowy/packages/appflowy_editor/lib/src/infra/html_converter.dart

@@ -2,7 +2,7 @@ import 'dart:collection';
 import 'dart:ui';
 
 import 'package:appflowy_editor/src/document/attributes.dart';
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/text_delta.dart';
 import 'package:appflowy_editor/src/extensions/color_extension.dart';
 import 'package:flutter/material.dart';
@@ -89,7 +89,7 @@ class HTMLToNodesConverter {
       }
     }
     if (delta.isNotEmpty) {
-      result.add(TextNode(type: "text", delta: delta));
+      result.add(TextNode(delta: delta));
     }
     return result;
   }
@@ -134,7 +134,7 @@ class HTMLToNodesConverter {
       final delta = Delta();
       delta.insert(element.text);
       if (delta.isNotEmpty) {
-        return [TextNode(type: "text", delta: delta)];
+        return [TextNode(delta: delta)];
       }
     }
     return [];
@@ -271,8 +271,7 @@ class HTMLToNodesConverter {
       }
     }
 
-    final textNode =
-        TextNode(type: "text", delta: delta, attributes: attributes);
+    final textNode = TextNode(delta: delta, attributes: attributes);
     if (isCheckbox) {
       textNode.attributes["subtype"] = BuiltInAttributeKey.checkbox;
       textNode.attributes["checkbox"] = checked;
@@ -315,7 +314,6 @@ class HTMLToNodesConverter {
     final delta = Delta();
     delta.insert(element.text);
     return TextNode(
-        type: "text",
         attributes: {"subtype": "heading", "heading": headingStyle},
         delta: delta);
   }

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/infra/infra.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 
 class Infra {
 // find the forward nearest text node

+ 2 - 3
frontend/app_flowy/packages/appflowy_editor/lib/src/operation/transaction_builder.dart

@@ -2,7 +2,7 @@ import 'dart:collection';
 import 'dart:math';
 
 import 'package:appflowy_editor/src/document/attributes.dart';
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/document/position.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
@@ -42,8 +42,7 @@ class TransactionBuilder {
   /// Updates the attributes of nodes.
   updateNode(Node node, Attributes attributes) {
     beforeSelection = state.cursorSelection;
-
-    final inverted = invertAttributes(attributes, node.attributes);
+    final inverted = invertAttributes(node.attributes, attributes);
     add(UpdateOperation(
       node.path,
       {...attributes},

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/editor/editor_entry.dart

@@ -1,6 +1,6 @@
 import 'package:flutter/material.dart';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/service/render_plugin_service.dart';
 

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/image/image_node_builder.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/operation/transaction_builder.dart';
 import 'package:appflowy_editor/src/service/render_plugin_service.dart';
 import 'package:flutter/material.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/image/image_node_widget.dart

@@ -1,5 +1,5 @@
 import 'package:appflowy_editor/src/extensions/object_extensions.dart';
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/position.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/infra/flowy_svg.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/image/image_upload_widget.dart

@@ -1,6 +1,6 @@
 import 'dart:collection';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/infra/flowy_svg.dart';
 import 'package:appflowy_editor/src/operation/transaction_builder.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/bulleted_list_text.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/infra/flowy_svg.dart';
 import 'package:appflowy_editor/src/render/rich_text/built_in_text_widget.dart';

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/flowy_rich_text.dart

@@ -5,7 +5,7 @@ import 'package:flutter/gestures.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/path.dart';
 import 'package:appflowy_editor/src/document/position.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
@@ -163,7 +163,7 @@ class _FlowyRichTextState extends State<FlowyRichText> with SelectableMixin {
   Widget _buildRichText(BuildContext context) {
     return MouseRegion(
       cursor: SystemMouseCursors.text,
-      child: widget.textNode.toRawString().isEmpty
+      child: widget.textNode.toPlainText().isEmpty
           ? Stack(
               children: [
                 _buildPlaceholderText(context),

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/heading_text.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/render/rich_text/built_in_text_widget.dart';
 import 'package:appflowy_editor/src/render/rich_text/default_selectable.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/number_list_text.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/render/rich_text/built_in_text_widget.dart';
 import 'package:appflowy_editor/src/render/rich_text/default_selectable.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/quoted_text.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/infra/flowy_svg.dart';
 import 'package:appflowy_editor/src/render/rich_text/built_in_text_widget.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/rich_text.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/render/rich_text/built_in_text_widget.dart';
 import 'package:appflowy_editor/src/render/rich_text/default_selectable.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_widget.dart

@@ -44,7 +44,7 @@ class SelectionMenuItem {
     if (selection != null && nodes.length == 1) {
       final node = nodes.first as TextNode;
       final end = selection.start.offset;
-      final start = node.toRawString().substring(0, end).lastIndexOf('/');
+      final start = node.toPlainText().substring(0, end).lastIndexOf('/');
       TransactionBuilder(editorState)
         ..deleteText(
           node,

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/render/style/editor_style.dart

@@ -1,6 +1,6 @@
 import 'package:flutter/material.dart';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/extensions/attributes_extension.dart';
 

+ 4 - 4
frontend/app_flowy/packages/appflowy_editor/lib/src/service/default_text_operations/format_rich_text_style.dart

@@ -1,5 +1,5 @@
 import 'package:appflowy_editor/src/document/attributes.dart';
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/position.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
@@ -125,7 +125,7 @@ bool formatTextNodes(EditorState editorState, Attributes attributes) {
       ..afterSelection = Selection.collapsed(
         Position(
           path: textNode.path,
-          offset: textNode.toRawString().length,
+          offset: textNode.toPlainText().length,
         ),
       );
   }
@@ -232,10 +232,10 @@ bool formatRichTextStyle(EditorState editorState, Attributes attributes) {
     for (var i = 0; i < textNodes.length; i++) {
       final textNode = textNodes[i];
       var index = 0;
-      var length = textNode.toRawString().length;
+      var length = textNode.toPlainText().length;
       if (i == 0 && textNode == nodes.first) {
         index = selection.start.offset;
-        length = textNode.toRawString().length - selection.start.offset;
+        length = textNode.toPlainText().length - selection.start.offset;
       } else if (i == textNodes.length - 1 && textNode == nodes.last) {
         length = selection.end.offset;
       }

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/service/input_service.dart

@@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/extensions/node_extensions.dart';
@@ -282,7 +282,7 @@ class _AppFlowyInputState extends State<AppFlowyInput>
     // FIXME: upward and selection update.
     if (textNodes.isNotEmpty && selection != null) {
       final text = textNodes.fold<String>(
-          '', (sum, textNode) => '$sum${textNode.toRawString()}\n');
+          '', (sum, textNode) => '$sum${textNode.toPlainText()}\n');
       attach(
         TextEditingValue(
           text: text,

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/backspace_handler.dart

@@ -163,7 +163,7 @@ KeyEventResult _backDeleteToPreviousTextNode(
     transactionBuilder.afterSelection = Selection.collapsed(
       Position(
         path: previousTextNode.path,
-        offset: previousTextNode.toRawString().length,
+        offset: previousTextNode.toPlainText().length,
       ),
     );
   }
@@ -267,7 +267,7 @@ void _deleteTextNodes(TransactionBuilder transactionBuilder,
     List<TextNode> textNodes, Selection selection) {
   final first = textNodes.first;
   final last = textNodes.last;
-  var content = textNodes.last.toRawString();
+  var content = textNodes.last.toPlainText();
   content = content.substring(selection.end.offset, content.length);
   // Merge the fist and the last text node content,
   //  and delete the all nodes expect for the first.

+ 5 - 6
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/copy_paste_handler.dart

@@ -136,10 +136,10 @@ void _pasteMultipleLinesInText(
         final tailTextNode = tailNodes.last as TextNode;
         tailTextNode.delta = tailTextNode.delta + remain;
       } else if (remain.isNotEmpty) {
-        tailNodes.add(TextNode(type: "text", delta: remain));
+        tailNodes.add(TextNode(delta: remain));
       }
     } else {
-      tailNodes.add(TextNode(type: "text", delta: remain));
+      tailNodes.add(TextNode(delta: remain));
     }
 
     tb.setAfterSelection(afterSelection);
@@ -261,9 +261,8 @@ void _handlePastePlainText(EditorState editorState, String plainText) {
 
     path[path.length - 1]++;
     final tb = TransactionBuilder(editorState);
-    final List<TextNode> nodes = remains
-        .map((e) => TextNode(type: "text", delta: _lineContentToDelta(e)))
-        .toList();
+    final List<TextNode> nodes =
+        remains.map((e) => TextNode(delta: _lineContentToDelta(e))).toList();
 
     final afterSelection =
         _computeSelectionAfterPasteMultipleNodes(editorState, nodes);
@@ -272,7 +271,7 @@ void _handlePastePlainText(EditorState editorState, String plainText) {
     if (nodes.isNotEmpty) {
       final last = nodes.last;
       nodes[nodes.length - 1] =
-          TextNode(type: "text", delta: last.delta..addAll(insertedLineSuffix));
+          TextNode(delta: last.delta..addAll(insertedLineSuffix));
     }
 
     // insert first line

+ 3 - 3
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler.dart

@@ -43,7 +43,7 @@ ShortcutEventHandler enterWithoutShiftInTextNodesHandler =
       ..deleteText(
         textNodes.first,
         selection.start.offset,
-        textNodes.first.toRawString().length,
+        textNodes.first.toPlainText().length,
       )
       ..deleteNodes(subTextNodes)
       ..deleteText(
@@ -73,7 +73,7 @@ ShortcutEventHandler enterWithoutShiftInTextNodesHandler =
   // If selection is collapsed and position.start.offset == 0,
   //  insert a empty text node before.
   if (selection.isCollapsed && selection.start.offset == 0) {
-    if (textNode.toRawString().isEmpty && textNode.subtype != null) {
+    if (textNode.toPlainText().isEmpty && textNode.subtype != null) {
       final afterSelection = Selection.collapsed(
         Position(path: textNode.path, offset: 0),
       );
@@ -156,7 +156,7 @@ ShortcutEventHandler enterWithoutShiftInTextNodesHandler =
   transactionBuilder.deleteText(
     textNode,
     selection.start.offset,
-    textNode.toRawString().length - selection.start.offset,
+    textNode.toPlainText().length - selection.start.offset,
   );
   if (textNode.children.isNotEmpty) {
     final children = textNode.children.toList(growable: false);

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/format_style_handler.dart

@@ -2,7 +2,7 @@ import 'package:appflowy_editor/src/service/default_text_operations/format_rich_
 import 'package:appflowy_editor/src/service/shortcut_event/shortcut_event_handler.dart';
 import 'package:flutter/material.dart';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 
 ShortcutEventHandler formatBoldEventHandler = (editorState, event) {
   final selection = editorState.service.selectionService.currentSelection.value;

+ 4 - 4
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/markdown_syntax_to_styled_text.dart

@@ -44,7 +44,7 @@ ShortcutEventHandler backquoteToCodeHandler = (editorState, event) {
 
   final textNode = textNodes.first;
   final selectionText = textNode
-      .toRawString()
+      .toPlainText()
       .substring(selection.start.offset, selection.end.offset);
 
   // toggle code style when selected some text
@@ -53,7 +53,7 @@ ShortcutEventHandler backquoteToCodeHandler = (editorState, event) {
     return KeyEventResult.handled;
   }
 
-  final text = textNode.toRawString().substring(0, selection.end.offset);
+  final text = textNode.toPlainText().substring(0, selection.end.offset);
   final backquoteIndexes = _findBackquoteIndexes(text, textNode);
   if (backquoteIndexes.isEmpty) {
     return KeyEventResult.ignored;
@@ -134,7 +134,7 @@ ShortcutEventHandler doubleTildeToStrikethrough = (editorState, event) {
   }
 
   final textNode = textNodes.first;
-  final text = textNode.toRawString().substring(0, selection.end.offset);
+  final text = textNode.toPlainText().substring(0, selection.end.offset);
 
   // make sure the last two characters are ~~.
   if (text.length < 2 || text[selection.end.offset - 1] != '~') {
@@ -199,7 +199,7 @@ ShortcutEventHandler markdownLinkToLinkHandler = (editorState, event) {
 
   // find all of the indexs for important characters
   final textNode = textNodes.first;
-  final text = textNode.toRawString();
+  final text = textNode.toPlainText();
   final firstOpeningBracket = text.indexOf('[');
   final firstClosingBracket = text.indexOf(']');
 

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/markdown_syntax_to_styled_text_handler.dart

@@ -11,7 +11,7 @@ ShortcutEventHandler doubleAsterisksToBold = (editorState, event) {
   }
 
   final textNode = textNodes.first;
-  final text = textNode.toRawString().substring(0, selection.end.offset);
+  final text = textNode.toPlainText().substring(0, selection.end.offset);
 
   // make sure the last two characters are **.
   if (text.length < 2 || text[selection.end.offset - 1] != '*') {
@@ -75,7 +75,7 @@ ShortcutEventHandler doubleUnderscoresToBold = (editorState, event) {
   }
 
   final textNode = textNodes.first;
-  final text = textNode.toRawString().substring(0, selection.end.offset);
+  final text = textNode.toPlainText().substring(0, selection.end.offset);
 
   // make sure the last two characters are __.
   if (text.length < 2 || text[selection.end.offset - 1] != '_') {

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/select_all_handler.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/position.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/service/shortcut_event/shortcut_event_handler.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/slash_handler.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/operation/transaction_builder.dart';
 import 'package:appflowy_editor/src/render/selection_menu/selection_menu_service.dart';
 import 'package:appflowy_editor/src/extensions/node_extensions.dart';

+ 5 - 5
frontend/app_flowy/packages/appflowy_editor/lib/src/service/internal_key_event_handlers/whitespace_handler.dart

@@ -2,7 +2,7 @@ import 'package:appflowy_editor/src/service/shortcut_event/shortcut_event_handle
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:appflowy_editor/src/document/built_in_attribute_keys.dart';
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/position.dart';
 import 'package:appflowy_editor/src/document/selection.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
@@ -44,7 +44,7 @@ ShortcutEventHandler whiteSpaceHandler = (editorState, event) {
   }
 
   final textNode = textNodes.first;
-  final text = textNode.toRawString().substring(0, selection.end.offset);
+  final text = textNode.toPlainText().substring(0, selection.end.offset);
 
   final numberMatch = _numberRegex.firstMatch(text);
 
@@ -140,13 +140,13 @@ KeyEventResult _toCheckboxList(EditorState editorState, TextNode textNode) {
   final String symbol;
   bool check = false;
   final symbols = List<String>.from(_checkboxListSymbols)
-    ..retainWhere(textNode.toRawString().startsWith);
+    ..retainWhere(textNode.toPlainText().startsWith);
   if (symbols.isNotEmpty) {
     symbol = symbols.first;
     check = true;
   } else {
     symbol = (List<String>.from(_unCheckboxListSymbols)
-          ..retainWhere(textNode.toRawString().startsWith))
+          ..retainWhere(textNode.toPlainText().startsWith))
         .first;
     check = false;
   }
@@ -170,7 +170,7 @@ KeyEventResult _toCheckboxList(EditorState editorState, TextNode textNode) {
 KeyEventResult _toHeadingStyle(
     EditorState editorState, TextNode textNode, Selection selection) {
   final x = _countOfSign(
-    textNode.toRawString(),
+    textNode.toPlainText(),
     selection,
   );
   final hX = 'h$x';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/service/render_plugin_service.dart

@@ -1,4 +1,4 @@
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/editor_state.dart';
 import 'package:appflowy_editor/src/infra/log.dart';
 import 'package:flutter/material.dart';

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/lib/src/service/selection_service.dart

@@ -1,7 +1,7 @@
 import 'package:appflowy_editor/src/infra/log.dart';
 import 'package:flutter/material.dart';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:appflowy_editor/src/document/node_iterator.dart';
 import 'package:appflowy_editor/src/document/position.dart';
 import 'package:appflowy_editor/src/document/selection.dart';

+ 3 - 5
frontend/app_flowy/packages/appflowy_editor/test/document/node_test.dart

@@ -57,7 +57,6 @@ void main() async {
 
     test('test textNode copyWith', () {
       final textNode = TextNode(
-        type: 'example',
         children: LinkedList(),
         attributes: {
           'example': 'example',
@@ -65,7 +64,7 @@ void main() async {
         delta: Delta()..insert('AppFlowy'),
       );
       expect(textNode.toJson(), {
-        'type': 'example',
+        'type': 'text',
         'attributes': {
           'example': 'example',
         },
@@ -79,7 +78,6 @@ void main() async {
       );
 
       final textNodeWithChildren = TextNode(
-        type: 'example',
         children: LinkedList()..add(textNode),
         attributes: {
           'example': 'example',
@@ -87,7 +85,7 @@ void main() async {
         delta: Delta()..insert('AppFlowy'),
       );
       expect(textNodeWithChildren.toJson(), {
-        'type': 'example',
+        'type': 'text',
         'attributes': {
           'example': 'example',
         },
@@ -96,7 +94,7 @@ void main() async {
         ],
         'children': [
           {
-            'type': 'example',
+            'type': 'text',
             'attributes': {
               'example': 'example',
             },

+ 0 - 1
frontend/app_flowy/packages/appflowy_editor/test/infra/infra_test.dart

@@ -15,7 +15,6 @@ void main() async {
       const text = 'Welcome to Appflowy 😁';
       TextNode textNode() {
         return TextNode(
-          type: 'text',
           delta: Delta()..insert(text),
         );
       }

+ 1 - 2
frontend/app_flowy/packages/appflowy_editor/test/infra/test_editor.dart

@@ -63,7 +63,6 @@ class EditorWidgetTester {
   void insertTextNode(String? text, {Attributes? attributes, Delta? delta}) {
     insert(
       TextNode(
-        type: 'text',
         delta: delta ?? Delta([TextInsert(text ?? 'Test')]),
         attributes: attributes,
       ),
@@ -103,7 +102,7 @@ class EditorWidgetTester {
       {Selection? selection}) async {
     await apply([
       TextEditingDeltaInsertion(
-        oldText: textNode.toRawString(),
+        oldText: textNode.toPlainText(),
         textInserted: text,
         insertionOffset: offset,
         selection: selection != null

+ 5 - 5
frontend/app_flowy/packages/appflowy_editor/test/legacy/delta_test.dart

@@ -318,12 +318,12 @@ void main() {
   });
   group("attributes", () {
     test("compose", () {
-      final attrs = composeAttributes({"a": null}, {"b": null}, true);
+      final attrs = composeAttributes({'a': null}, {'b': null}, keepNull: true);
       expect(attrs != null, true);
-      expect(attrs!.containsKey("a"), true);
-      expect(attrs.containsKey("b"), true);
-      expect(attrs["a"], null);
-      expect(attrs["b"], null);
+      expect(attrs?.containsKey("a"), true);
+      expect(attrs?.containsKey("b"), true);
+      expect(attrs?["a"], null);
+      expect(attrs?["b"], null);
     });
   });
 }

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/test/legacy/operation_test.dart

@@ -1,6 +1,6 @@
 import 'dart:collection';
 
-import 'package:appflowy_editor/src/document/node.dart';
+import 'package:appflowy_editor/src/core/document/node.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:appflowy_editor/src/operation/operation.dart';
 import 'package:appflowy_editor/src/operation/transaction_builder.dart';

+ 9 - 9
frontend/app_flowy/packages/appflowy_editor/test/legacy/undo_manager_test.dart

@@ -21,12 +21,12 @@ void main() async {
     final editorState = EditorState(document: document);
 
     final historyItem = HistoryItem();
-    historyItem.add(DeleteOperation(
-        [0], [TextNode(type: 'text', delta: Delta()..insert('0'))]));
-    historyItem.add(DeleteOperation(
-        [0], [TextNode(type: 'text', delta: Delta()..insert('1'))]));
-    historyItem.add(DeleteOperation(
-        [0], [TextNode(type: 'text', delta: Delta()..insert('2'))]));
+    historyItem
+        .add(DeleteOperation([0], [TextNode(delta: Delta()..insert('0'))]));
+    historyItem
+        .add(DeleteOperation([0], [TextNode(delta: Delta()..insert('1'))]));
+    historyItem
+        .add(DeleteOperation([0], [TextNode(delta: Delta()..insert('2'))]));
 
     final transaction = historyItem.toTransaction(editorState);
     assert(isInsertAndPathEqual(transaction.operations[0], [0], '2'));
@@ -39,8 +39,8 @@ void main() async {
     final editorState = EditorState(document: document);
 
     final historyItem = HistoryItem();
-    historyItem.add(DeleteOperation(
-        [0], [TextNode(type: 'text', delta: Delta()..insert('0'))]));
+    historyItem
+        .add(DeleteOperation([0], [TextNode(delta: Delta()..insert('0'))]));
     historyItem
         .add(UpdateOperation([0], {"subType": "number"}, {"subType": null}));
     historyItem.add(DeleteOperation([0], [TextNode.empty(), TextNode.empty()]));
@@ -72,5 +72,5 @@ bool isInsertAndPathEqual(Operation operation, Path path, [String? content]) {
     return true;
   }
 
-  return firstNode.delta.toRawString() == content;
+  return firstNode.delta.toPlainText() == content;
 }

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/test/render/selection_menu/selection_menu_widget_test.dart

@@ -147,7 +147,7 @@ Future<void> _testDefaultSelectionMenuItems(
     int index, EditorWidgetTester editor) async {
   expect(editor.documentLength, 4);
   expect(editor.documentSelection, Selection.single(path: [2], startOffset: 0));
-  expect((editor.nodeAtPath([1]) as TextNode).toRawString(),
+  expect((editor.nodeAtPath([1]) as TextNode).toPlainText(),
       'Welcome to Appflowy 😁');
   final node = editor.nodeAtPath([2]);
   final item = defaultSelectionMenuItems[index];

+ 12 - 14
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/backspace_handler_test.dart

@@ -117,7 +117,7 @@ void main() async {
     expect(editor.documentLength, 1);
     expect(editor.documentSelection,
         Selection.single(path: [0], startOffset: text.length));
-    expect((editor.nodeAtPath([0]) as TextNode).toRawString(), text * 2);
+    expect((editor.nodeAtPath([0]) as TextNode).toPlainText(), text * 2);
   });
 
   // Before
@@ -275,7 +275,6 @@ void main() async {
     //    * Welcome to Appflowy 😁
     const text = 'Welcome to Appflowy 😁';
     final node = TextNode(
-      type: 'text',
       delta: Delta()..insert(text),
       attributes: {
         BuiltInAttributeKey.subtype: BuiltInAttributeKey.bulletedList,
@@ -320,7 +319,7 @@ void main() async {
       editor.documentSelection,
       Selection.single(path: [0, 0], startOffset: text.length),
     );
-    expect((editor.nodeAtPath([0, 0]) as TextNode).toRawString(), text * 2);
+    expect((editor.nodeAtPath([0, 0]) as TextNode).toPlainText(), text * 2);
   });
 
   testWidgets('Delete the complicated nested bulleted list', (tester) async {
@@ -331,7 +330,6 @@ void main() async {
     //    * Welcome to Appflowy 😁
     const text = 'Welcome to Appflowy 😁';
     final node = TextNode(
-      type: 'text',
       delta: Delta()..insert(text),
       attributes: {
         BuiltInAttributeKey.subtype: BuiltInAttributeKey.bulletedList,
@@ -390,7 +388,7 @@ void main() async {
       true,
     );
     expect(
-      (editor.nodeAtPath([0, 0]) as TextNode).toRawString() == text * 2,
+      (editor.nodeAtPath([0, 0]) as TextNode).toPlainText() == text * 2,
       true,
     );
     expect(
@@ -496,7 +494,7 @@ Future<void> _deleteStyledTextByBackspace(
   expect(editor.documentSelection,
       Selection.single(path: [1], startOffset: text.length));
   expect(editor.nodeAtPath([1])?.subtype, style);
-  expect((editor.nodeAtPath([1]) as TextNode).toRawString(), text * 2);
+  expect((editor.nodeAtPath([1]) as TextNode).toPlainText(), text * 2);
 
   await editor.updateSelection(
     Selection.single(path: [1], startOffset: 0),
@@ -538,7 +536,7 @@ Future<void> _deleteStyledTextByDelete(
     expect(
         editor.documentSelection, Selection.single(path: [1], startOffset: 0));
     expect(editor.nodeAtPath([1])?.subtype, style);
-    expect((editor.nodeAtPath([1]) as TextNode).toRawString(),
+    expect((editor.nodeAtPath([1]) as TextNode).toPlainText(),
         text.safeSubString(i));
   }
 
@@ -548,7 +546,7 @@ Future<void> _deleteStyledTextByDelete(
   expect(editor.documentLength, 2);
   expect(editor.documentSelection, Selection.single(path: [1], startOffset: 0));
   expect(editor.nodeAtPath([1])?.subtype, style);
-  expect((editor.nodeAtPath([1]) as TextNode).toRawString(), text);
+  expect((editor.nodeAtPath([1]) as TextNode).toPlainText(), text);
 }
 
 Future<void> _deleteTextByBackspace(
@@ -568,7 +566,7 @@ Future<void> _deleteTextByBackspace(
 
   expect(editor.documentLength, 3);
   expect(editor.documentSelection, Selection.single(path: [1], startOffset: 9));
-  expect((editor.nodeAtPath([1]) as TextNode).toRawString(),
+  expect((editor.nodeAtPath([1]) as TextNode).toPlainText(),
       'Welcome t Appflowy 😁');
 
   // delete 'to '
@@ -578,7 +576,7 @@ Future<void> _deleteTextByBackspace(
   await editor.pressLogicKey(LogicalKeyboardKey.backspace);
   expect(editor.documentLength, 3);
   expect(editor.documentSelection, Selection.single(path: [2], startOffset: 8));
-  expect((editor.nodeAtPath([2]) as TextNode).toRawString(),
+  expect((editor.nodeAtPath([2]) as TextNode).toPlainText(),
       'Welcome Appflowy 😁');
 
   // delete 'Appflowy 😁
@@ -593,7 +591,7 @@ Future<void> _deleteTextByBackspace(
   expect(editor.documentLength, 1);
   expect(
       editor.documentSelection, Selection.single(path: [0], startOffset: 11));
-  expect((editor.nodeAtPath([0]) as TextNode).toRawString(),
+  expect((editor.nodeAtPath([0]) as TextNode).toPlainText(),
       'Welcome to Appflowy 😁');
 }
 
@@ -614,7 +612,7 @@ Future<void> _deleteTextByDelete(
 
   expect(editor.documentLength, 3);
   expect(editor.documentSelection, Selection.single(path: [1], startOffset: 9));
-  expect((editor.nodeAtPath([1]) as TextNode).toRawString(),
+  expect((editor.nodeAtPath([1]) as TextNode).toPlainText(),
       'Welcome t Appflowy 😁');
 
   // delete 'to '
@@ -624,7 +622,7 @@ Future<void> _deleteTextByDelete(
   await editor.pressLogicKey(LogicalKeyboardKey.delete);
   expect(editor.documentLength, 3);
   expect(editor.documentSelection, Selection.single(path: [2], startOffset: 8));
-  expect((editor.nodeAtPath([2]) as TextNode).toRawString(),
+  expect((editor.nodeAtPath([2]) as TextNode).toPlainText(),
       'Welcome Appflowy 😁');
 
   // delete 'Appflowy 😁
@@ -639,6 +637,6 @@ Future<void> _deleteTextByDelete(
   expect(editor.documentLength, 1);
   expect(
       editor.documentSelection, Selection.single(path: [0], startOffset: 11));
-  expect((editor.nodeAtPath([0]) as TextNode).toRawString(),
+  expect((editor.nodeAtPath([0]) as TextNode).toPlainText(),
       'Welcome to Appflowy 😁');
 }

+ 6 - 6
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/enter_without_shift_in_text_node_handler_test.dart

@@ -74,10 +74,10 @@ void main() async {
       expect(lastNode != null, true);
       expect(lastNode is TextNode, true);
       lastNode = lastNode as TextNode;
-      expect(lastNode.delta.toRawString(), text);
-      expect((lastNode.previous as TextNode).delta.toRawString(), '');
+      expect(lastNode.delta.toPlainText(), text);
+      expect((lastNode.previous as TextNode).delta.toPlainText(), '');
       expect(
-          (lastNode.previous!.previous as TextNode).delta.toRawString(), text);
+          (lastNode.previous!.previous as TextNode).delta.toPlainText(), text);
     });
 
     // Before
@@ -134,7 +134,7 @@ void main() async {
       );
       await editor.pressLogicKey(LogicalKeyboardKey.enter);
       expect(editor.documentLength, 2);
-      expect((editor.nodeAtPath([1]) as TextNode).toRawString(), text);
+      expect((editor.nodeAtPath([1]) as TextNode).toPlainText(), text);
     });
   });
 }
@@ -227,6 +227,6 @@ Future<void> _testMultipleSelection(
   );
 
   expect(editor.documentLength, 2);
-  expect((editor.nodeAtPath([0]) as TextNode).toRawString(), 'Welcome');
-  expect((editor.nodeAtPath([1]) as TextNode).toRawString(), 'to Appflowy 😁');
+  expect((editor.nodeAtPath([0]) as TextNode).toPlainText(), 'Welcome');
+  expect((editor.nodeAtPath([1]) as TextNode).toPlainText(), 'to Appflowy 😁');
 }

+ 18 - 18
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/markdown_syntax_to_styled_text_handler_test.dart

@@ -39,11 +39,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allBold, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('App**Flowy** to bold AppFlowy', (tester) async {
@@ -62,11 +62,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 3,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allBold, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('***AppFlowy** to bold *AppFlowy', (tester) async {
@@ -85,11 +85,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 1,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allBold, true);
-        expect(textNode.toRawString(), '*AppFlowy');
+        expect(textNode.toPlainText(), '*AppFlowy');
       });
 
       testWidgets('**AppFlowy** application to bold AppFlowy only',
@@ -115,7 +115,7 @@ void main() async {
           ),
         );
         expect(appFlowyBold, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('**** nothing changes', (tester) async {
@@ -134,11 +134,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allBold, false);
-        expect(textNode.toRawString(), text);
+        expect(textNode.toPlainText(), text);
       });
     });
 
@@ -171,11 +171,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allBold, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('App__Flowy__ to bold AppFlowy', (tester) async {
@@ -194,11 +194,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 3,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allBold, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('___AppFlowy__ to bold _AppFlowy', (tester) async {
@@ -217,11 +217,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 1,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allBold, true);
-        expect(textNode.toRawString(), '_AppFlowy');
+        expect(textNode.toPlainText(), '_AppFlowy');
       });
 
       testWidgets('__AppFlowy__ application to bold AppFlowy only',
@@ -247,7 +247,7 @@ void main() async {
           ),
         );
         expect(appFlowyBold, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('____ nothing changes', (tester) async {
@@ -266,11 +266,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allBold, false);
-        expect(textNode.toRawString(), text);
+        expect(textNode.toPlainText(), text);
       });
     });
   });

+ 18 - 18
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/markdown_syntax_to_styled_text_test.dart

@@ -38,11 +38,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allCode, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('App`Flowy` to code AppFlowy', (tester) async {
@@ -61,11 +61,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 3,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allCode, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('`` nothing changes', (tester) async {
@@ -84,11 +84,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allCode, false);
-        expect(textNode.toRawString(), text);
+        expect(textNode.toPlainText(), text);
       });
     });
 
@@ -120,11 +120,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 1,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allCode, true);
-        expect(textNode.toRawString(), '`AppFlowy');
+        expect(textNode.toPlainText(), '`AppFlowy');
       });
 
       testWidgets('```` nothing changes', (tester) async {
@@ -143,11 +143,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allCode, false);
-        expect(textNode.toRawString(), text);
+        expect(textNode.toPlainText(), text);
       });
     });
 
@@ -180,11 +180,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allStrikethrough, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('App~~Flowy~~ to strikethrough AppFlowy', (tester) async {
@@ -203,11 +203,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 3,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allStrikethrough, true);
-        expect(textNode.toRawString(), 'AppFlowy');
+        expect(textNode.toPlainText(), 'AppFlowy');
       });
 
       testWidgets('~~~AppFlowy~~ to bold ~AppFlowy', (tester) async {
@@ -226,11 +226,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 1,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allStrikethrough, true);
-        expect(textNode.toRawString(), '~AppFlowy');
+        expect(textNode.toPlainText(), '~AppFlowy');
       });
 
       testWidgets('~~~~ nothing changes', (tester) async {
@@ -249,11 +249,11 @@ void main() async {
           Selection.single(
             path: [0],
             startOffset: 0,
-            endOffset: textNode.toRawString().length,
+            endOffset: textNode.toPlainText().length,
           ),
         );
         expect(allStrikethrough, false);
-        expect(textNode.toRawString(), text);
+        expect(textNode.toPlainText(), text);
       });
     });
   });

+ 1 - 1
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/redo_undo_handler_test.dart

@@ -56,7 +56,7 @@ Future<void> _testBackspaceUndoRedo(
   }
 
   expect(editor.documentLength, 3);
-  expect((editor.nodeAtPath([1]) as TextNode).toRawString(), text);
+  expect((editor.nodeAtPath([1]) as TextNode).toPlainText(), text);
   expect(editor.documentSelection, selection);
 
   if (Platform.isWindows || Platform.isLinux) {

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/space_on_web_handler_test.dart

@@ -26,7 +26,7 @@ void main() async {
         );
         await editor.pressLogicKey(LogicalKeyboardKey.space);
         expect(
-          (editor.nodeAtPath([i]) as TextNode).toRawString(),
+          (editor.nodeAtPath([i]) as TextNode).toPlainText(),
           'W elcome to Appflowy 😁',
         );
       }
@@ -36,7 +36,7 @@ void main() async {
         );
         await editor.pressLogicKey(LogicalKeyboardKey.space);
         expect(
-          (editor.nodeAtPath([i]) as TextNode).toRawString(),
+          (editor.nodeAtPath([i]) as TextNode).toPlainText(),
           'W elcome to Appflowy 😁 ',
         );
       }

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/white_space_handler_test.dart

@@ -87,7 +87,7 @@ void main() async {
         expect(textNode.subtype, BuiltInAttributeKey.heading);
         // BuiltInAttributeKey.h1 ~ BuiltInAttributeKey.h6
         expect(textNode.attributes.heading, 'h$i');
-        expect(textNode.toRawString().startsWith('##'), true);
+        expect(textNode.toPlainText().startsWith('##'), true);
       }
     });
 
@@ -211,7 +211,7 @@ void main() async {
       await editor.pressLogicKey(LogicalKeyboardKey.space);
       expect(textNode.subtype, BuiltInAttributeKey.checkbox);
       expect(textNode.attributes.check, true);
-      expect(textNode.toRawString(), insertedText);
+      expect(textNode.toPlainText(), insertedText);
     });
   });
 }