refactor: move node to core/document
This commit is contained in:
parent
b96d5d5d51
commit
85207cb14c
58 changed files with 281 additions and 282 deletions
|
|
@ -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,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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('_');
|
||||
|
|
|
|||
|
|
@ -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,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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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,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';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,278 @@
|
|||
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';
|
||||
|
||||
class Node extends ChangeNotifier with LinkedListEntry<Node> {
|
||||
Node({
|
||||
required this.type,
|
||||
Attributes? attributes,
|
||||
this.parent,
|
||||
LinkedList<Node>? children,
|
||||
}) : children = children ?? LinkedList<Node>(),
|
||||
_attributes = attributes ?? {} {
|
||||
for (final child in this.children) {
|
||||
child.parent = this;
|
||||
}
|
||||
}
|
||||
|
||||
factory Node.fromJson(Map<String, Object> json) {
|
||||
assert(json['type'] is String);
|
||||
|
||||
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 children = LinkedList<Node>();
|
||||
if (jChildren != null) {
|
||||
children.addAll(
|
||||
jChildren.map(
|
||||
(jChild) => Node.fromJson(
|
||||
Map<String, Object>.from(jChild),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Node node;
|
||||
|
||||
if (jType == 'text') {
|
||||
final jDelta = json['delta'] as List<dynamic>?;
|
||||
final delta = jDelta == null ? Delta() : Delta.fromJson(jDelta);
|
||||
node = TextNode(
|
||||
children: children,
|
||||
attributes: jAttributes,
|
||||
delta: delta,
|
||||
);
|
||||
} else {
|
||||
node = Node(
|
||||
type: jType,
|
||||
children: children,
|
||||
attributes: jAttributes,
|
||||
);
|
||||
}
|
||||
|
||||
for (final child in children) {
|
||||
child.parent = 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 = 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 =
|
||||
this.attributes['subtype'] != oldAttributes['subtype'];
|
||||
shouldNotifyParent ? parent?.notifyListeners() : notifyListeners();
|
||||
}
|
||||
|
||||
Node? childAtIndex(int index) {
|
||||
if (children.length <= index || index < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return children.elementAt(index);
|
||||
}
|
||||
|
||||
Node? childAtPath(Path path) {
|
||||
if (path.isEmpty) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return childAtIndex(path.first)?.childAtPath(path.sublist(1));
|
||||
}
|
||||
|
||||
void insert(Node entry, {int? index}) {
|
||||
final length = children.length;
|
||||
index ??= length;
|
||||
|
||||
if (children.isEmpty) {
|
||||
entry.parent = this;
|
||||
children.add(entry);
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
children.first.insertBefore(entry);
|
||||
} else {
|
||||
childAtIndex(index)?.insertBefore(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void insertAfter(Node entry) {
|
||||
entry.parent = parent;
|
||||
super.insertAfter(entry);
|
||||
|
||||
// Notifies the new node.
|
||||
parent?.notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void insertBefore(Node entry) {
|
||||
entry.parent = parent;
|
||||
super.insertBefore(entry);
|
||||
|
||||
// Notifies the new node.
|
||||
parent?.notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void unlink() {
|
||||
super.unlink();
|
||||
|
||||
parent?.notifyListeners();
|
||||
parent = null;
|
||||
}
|
||||
|
||||
Map<String, Object> toJson() {
|
||||
var map = <String, Object>{
|
||||
'type': type,
|
||||
};
|
||||
if (children.isNotEmpty) {
|
||||
map['children'] =
|
||||
children.map((node) => node.toJson()).toList(growable: false);
|
||||
}
|
||||
if (attributes.isNotEmpty) {
|
||||
map['attributes'] = attributes;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
Node copyWith({
|
||||
String? type,
|
||||
LinkedList<Node>? children,
|
||||
Attributes? attributes,
|
||||
}) {
|
||||
final node = Node(
|
||||
type: type ?? this.type,
|
||||
attributes: attributes ?? {...this.attributes},
|
||||
children: children,
|
||||
);
|
||||
if (children == null && this.children.isNotEmpty) {
|
||||
for (final child in this.children) {
|
||||
node.children.add(
|
||||
child.copyWith()..parent = 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 {
|
||||
TextNode({
|
||||
required Delta delta,
|
||||
LinkedList<Node>? children,
|
||||
Attributes? attributes,
|
||||
}) : _delta = delta,
|
||||
super(
|
||||
type: 'text',
|
||||
children: children,
|
||||
attributes: attributes ?? {},
|
||||
);
|
||||
|
||||
TextNode.empty({Attributes? attributes})
|
||||
: _delta = Delta([TextInsert('')]),
|
||||
super(
|
||||
type: 'text',
|
||||
attributes: attributes ?? {},
|
||||
);
|
||||
|
||||
Delta _delta;
|
||||
Delta get delta => _delta;
|
||||
set delta(Delta v) {
|
||||
_delta = v;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Object> toJson() {
|
||||
final map = super.toJson();
|
||||
map['delta'] = delta.toJson();
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
TextNode copyWith({
|
||||
String? type = 'text',
|
||||
LinkedList<Node>? children,
|
||||
Attributes? attributes,
|
||||
Delta? delta,
|
||||
}) {
|
||||
final textNode = TextNode(
|
||||
children: children,
|
||||
attributes: attributes ?? this.attributes,
|
||||
delta: delta ?? this.delta,
|
||||
);
|
||||
if (children == null && this.children.isNotEmpty) {
|
||||
for (final child in this.children) {
|
||||
textNode.children.add(
|
||||
child.copyWith()..parent = textNode,
|
||||
);
|
||||
}
|
||||
}
|
||||
return textNode;
|
||||
}
|
||||
|
||||
String toPlainText() => _delta.toPlainText();
|
||||
}
|
||||
|
|
@ -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 invertAttributes(Attributes? attr, Attributes? base) {
|
||||
attr ??= {};
|
||||
Attributes? composeAttributes(
|
||||
Attributes? base,
|
||||
Attributes? other, {
|
||||
keepNull = false,
|
||||
}) {
|
||||
base ??= {};
|
||||
final Attributes baseInverted = base.keys.fold({}, (memo, key) {
|
||||
if (base![key] != attr![key] && attr.containsKey(key)) {
|
||||
memo[key] = base[key];
|
||||
}
|
||||
return memo;
|
||||
});
|
||||
return attr.keys.fold(baseInverted, (memo, key) {
|
||||
if (attr![key] != base![key] && !base.containsKey(key)) {
|
||||
memo[key] = null;
|
||||
}
|
||||
return memo;
|
||||
});
|
||||
}
|
||||
|
||||
Attributes? composeAttributes(Attributes? a, Attributes? b,
|
||||
[bool keepNull = false]) {
|
||||
a ??= {};
|
||||
b ??= {};
|
||||
Attributes attributes = {...b};
|
||||
other ??= {};
|
||||
Attributes attributes = {
|
||||
...base,
|
||||
...other,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
attributes = Attributes.from(attributes)
|
||||
..removeWhere((_, value) => value == null);
|
||||
}
|
||||
|
||||
return attributes.isNotEmpty ? attributes : null;
|
||||
}
|
||||
|
||||
Attributes invertAttributes(Attributes? base, Attributes? other) {
|
||||
base ??= {};
|
||||
other ??= {};
|
||||
final Attributes attributes = base.keys.fold({}, (previousValue, key) {
|
||||
if (other!.containsKey(key) && other[key] != base![key]) {
|
||||
previousValue[key] = base[key];
|
||||
}
|
||||
return previousValue;
|
||||
});
|
||||
return other.keys.fold(attributes, (previousValue, key) {
|
||||
if (!base!.containsKey(key) && other![key] != base[key]) {
|
||||
previousValue[key] = null;
|
||||
}
|
||||
return previousValue;
|
||||
});
|
||||
}
|
||||
|
||||
int hashAttributes(Attributes base) => Object.hashAllUnordered(
|
||||
base.entries.map((e) => Object.hash(e.key, e.value)),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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,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';
|
||||
|
|
|
|||
|
|
@ -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,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';
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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,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,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,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';
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue