mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: rename state_tree to document and move document to core/state
This commit is contained in:
parent
d02c29426e
commit
5e7507c8e7
@ -98,7 +98,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
if (snapshot.hasData &&
|
if (snapshot.hasData &&
|
||||||
snapshot.connectionState == ConnectionState.done) {
|
snapshot.connectionState == ConnectionState.done) {
|
||||||
_editorState ??= EditorState(
|
_editorState ??= EditorState(
|
||||||
document: StateTree.fromJson(
|
document: Document.fromJson(
|
||||||
Map<String, Object>.from(
|
Map<String, Object>.from(
|
||||||
json.decode(snapshot.data!),
|
json.decode(snapshot.data!),
|
||||||
),
|
),
|
||||||
|
@ -7,7 +7,7 @@ export 'src/core/document/node.dart';
|
|||||||
export 'src/core/document/path.dart';
|
export 'src/core/document/path.dart';
|
||||||
export 'src/core/location/position.dart';
|
export 'src/core/location/position.dart';
|
||||||
export 'src/core/location/selection.dart';
|
export 'src/core/location/selection.dart';
|
||||||
export 'src/document/state_tree.dart';
|
export 'src/core/state/document.dart';
|
||||||
export 'src/core/document/text_delta.dart';
|
export 'src/core/document/text_delta.dart';
|
||||||
export 'src/core/document/attributes.dart';
|
export 'src/core/document/attributes.dart';
|
||||||
export 'src/document/built_in_attribute_keys.dart';
|
export 'src/document/built_in_attribute_keys.dart';
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import 'package:appflowy_editor/src/core/document/node.dart';
|
import 'package:appflowy_editor/src/core/document/node.dart';
|
||||||
import 'package:appflowy_editor/src/document/state_tree.dart';
|
import 'package:appflowy_editor/src/core/state/document.dart';
|
||||||
|
|
||||||
/// [NodeIterator] is used to traverse the nodes in visual order.
|
/// [NodeIterator] is used to traverse the nodes in visual order.
|
||||||
class NodeIterator implements Iterator<Node> {
|
class NodeIterator implements Iterator<Node> {
|
||||||
NodeIterator({
|
NodeIterator({
|
||||||
required this.stateTree,
|
required this.document,
|
||||||
required this.startNode,
|
required this.startNode,
|
||||||
this.endNode,
|
this.endNode,
|
||||||
});
|
});
|
||||||
|
|
||||||
final StateTree stateTree;
|
final Document document;
|
||||||
final Node startNode;
|
final Node startNode;
|
||||||
final Node? endNode;
|
final Node? endNode;
|
||||||
|
|
||||||
|
@ -69,4 +69,22 @@ extension PathExtensions on Path {
|
|||||||
..removeLast()
|
..removeLast()
|
||||||
..add(last + 1);
|
..add(last + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Path get previous {
|
||||||
|
Path previousPath = Path.from(this, growable: true);
|
||||||
|
if (isEmpty) {
|
||||||
|
return previousPath;
|
||||||
|
}
|
||||||
|
final last = previousPath.last;
|
||||||
|
return previousPath
|
||||||
|
..removeLast()
|
||||||
|
..add(max(0, last - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Path get parent {
|
||||||
|
if (isEmpty) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return Path.from(this, growable: true)..removeLast();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,118 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:appflowy_editor/src/core/document/node.dart';
|
||||||
|
import 'package:appflowy_editor/src/core/document/path.dart';
|
||||||
|
import 'package:appflowy_editor/src/core/document/text_delta.dart';
|
||||||
|
import '../document/attributes.dart';
|
||||||
|
|
||||||
|
/// [Document] reprensents a AppFlowy Editor document structure.
|
||||||
|
///
|
||||||
|
/// It stores the root of the document.
|
||||||
|
///
|
||||||
|
/// DO NOT directly mutate the properties of a [Document] object.
|
||||||
|
class Document {
|
||||||
|
Document({
|
||||||
|
required this.root,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory Document.fromJson(Map<String, dynamic> json) {
|
||||||
|
assert(json['document'] is Map);
|
||||||
|
|
||||||
|
final document = Map<String, Object>.from(json['document'] as Map);
|
||||||
|
final root = Node.fromJson(document);
|
||||||
|
return Document(root: root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a empty document with a single text node.
|
||||||
|
factory Document.empty() {
|
||||||
|
final root = Node(
|
||||||
|
type: 'editor',
|
||||||
|
children: LinkedList<Node>()..add(TextNode.empty()),
|
||||||
|
);
|
||||||
|
return Document(
|
||||||
|
root: root,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Node root;
|
||||||
|
|
||||||
|
/// Returns the node at the given [path].
|
||||||
|
Node? nodeAtPath(Path path) {
|
||||||
|
return root.childAtPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inserts a [Node]s at the given [Path].
|
||||||
|
bool insert(Path path, List<Node> nodes) {
|
||||||
|
if (path.isEmpty || nodes.isEmpty) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final target = nodeAtPath(path);
|
||||||
|
if (target != null) {
|
||||||
|
for (final node in nodes) {
|
||||||
|
target.insertBefore(node);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final parent = nodeAtPath(path.parent);
|
||||||
|
if (parent != null) {
|
||||||
|
for (final node in nodes) {
|
||||||
|
parent.insert(node, index: path.last);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes the [Node]s at the given [Path].
|
||||||
|
bool delete(Path path, [int length = 1]) {
|
||||||
|
if (path.isEmpty || length <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var target = nodeAtPath(path);
|
||||||
|
if (target == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (target != null && length > 0) {
|
||||||
|
final next = target.next;
|
||||||
|
target.unlink();
|
||||||
|
target = next;
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the [Node] at the given [Path]
|
||||||
|
bool update(Path path, Attributes attributes) {
|
||||||
|
if (path.isEmpty) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final target = nodeAtPath(path);
|
||||||
|
if (target == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
target.updateAttributes(attributes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the [TextNode] at the given [Path]
|
||||||
|
bool updateText(Path path, Delta delta) {
|
||||||
|
if (path.isEmpty) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final target = nodeAtPath(path);
|
||||||
|
if (target == null || target is! TextNode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
target.delta = target.delta.compose(delta);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> toJson() {
|
||||||
|
return {
|
||||||
|
'document': root.toJson(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,116 +0,0 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:appflowy_editor/src/core/document/node.dart';
|
|
||||||
import 'package:appflowy_editor/src/core/document/path.dart';
|
|
||||||
import 'package:appflowy_editor/src/core/document/text_delta.dart';
|
|
||||||
import '../core/document/attributes.dart';
|
|
||||||
|
|
||||||
class StateTree {
|
|
||||||
final Node root;
|
|
||||||
|
|
||||||
StateTree({
|
|
||||||
required this.root,
|
|
||||||
});
|
|
||||||
|
|
||||||
factory StateTree.empty() {
|
|
||||||
return StateTree(
|
|
||||||
root: Node.fromJson({
|
|
||||||
'type': 'editor',
|
|
||||||
'children': [
|
|
||||||
{
|
|
||||||
'type': 'text',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
factory StateTree.fromJson(Attributes json) {
|
|
||||||
assert(json['document'] is Map);
|
|
||||||
|
|
||||||
final document = Map<String, Object>.from(json['document'] as Map);
|
|
||||||
final root = Node.fromJson(document);
|
|
||||||
return StateTree(root: root);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> toJson() {
|
|
||||||
return {
|
|
||||||
'document': root.toJson(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Node? nodeAtPath(Path path) {
|
|
||||||
return root.childAtPath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool insert(Path path, List<Node> nodes) {
|
|
||||||
if (path.isEmpty) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Node? insertedNode = root.childAtPath(
|
|
||||||
path.sublist(0, path.length - 1) + [max(0, path.last - 1)],
|
|
||||||
);
|
|
||||||
if (insertedNode == null) {
|
|
||||||
final insertedNode = root.childAtPath(
|
|
||||||
path.sublist(0, path.length - 1),
|
|
||||||
);
|
|
||||||
if (insertedNode != null) {
|
|
||||||
for (final node in nodes) {
|
|
||||||
insertedNode.insert(node);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (path.last <= 0) {
|
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
|
||||||
final node = nodes[i];
|
|
||||||
insertedNode.insertBefore(node);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
|
||||||
final node = nodes[i];
|
|
||||||
insertedNode!.insertAfter(node);
|
|
||||||
insertedNode = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool textEdit(Path path, Delta delta) {
|
|
||||||
if (path.isEmpty) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final node = root.childAtPath(path);
|
|
||||||
if (node == null || node is! TextNode) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
node.delta = node.delta.compose(delta);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(Path path, [int length = 1]) {
|
|
||||||
if (path.isEmpty) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var deletedNode = root.childAtPath(path);
|
|
||||||
while (deletedNode != null && length > 0) {
|
|
||||||
final next = deletedNode.next;
|
|
||||||
deletedNode.unlink();
|
|
||||||
length--;
|
|
||||||
deletedNode = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool update(Path path, Attributes attributes) {
|
|
||||||
if (path.isEmpty) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final updatedNode = root.childAtPath(path);
|
|
||||||
if (updatedNode == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
updatedNode.updateAttributes(attributes);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,7 +6,7 @@ import 'package:appflowy_editor/src/service/service.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy_editor/src/core/location/selection.dart';
|
import 'package:appflowy_editor/src/core/location/selection.dart';
|
||||||
import 'package:appflowy_editor/src/document/state_tree.dart';
|
import 'package:appflowy_editor/src/core/state/document.dart';
|
||||||
import 'package:appflowy_editor/src/operation/operation.dart';
|
import 'package:appflowy_editor/src/operation/operation.dart';
|
||||||
import 'package:appflowy_editor/src/operation/transaction.dart';
|
import 'package:appflowy_editor/src/operation/transaction.dart';
|
||||||
import 'package:appflowy_editor/src/undo_manager.dart';
|
import 'package:appflowy_editor/src/undo_manager.dart';
|
||||||
@ -46,7 +46,7 @@ enum CursorUpdateReason {
|
|||||||
///
|
///
|
||||||
/// Mutating the document with document's API is not recommended.
|
/// Mutating the document with document's API is not recommended.
|
||||||
class EditorState {
|
class EditorState {
|
||||||
final StateTree document;
|
final Document document;
|
||||||
|
|
||||||
// Service reference.
|
// Service reference.
|
||||||
final service = FlowyService();
|
final service = FlowyService();
|
||||||
@ -105,7 +105,7 @@ class EditorState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
factory EditorState.empty() {
|
factory EditorState.empty() {
|
||||||
return EditorState(document: StateTree.empty());
|
return EditorState(document: Document.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the transaction to the state.
|
/// Apply the transaction to the state.
|
||||||
@ -167,7 +167,7 @@ class EditorState {
|
|||||||
} else if (op is DeleteOperation) {
|
} else if (op is DeleteOperation) {
|
||||||
document.delete(op.path, op.nodes.length);
|
document.delete(op.path, op.nodes.length);
|
||||||
} else if (op is TextEditOperation) {
|
} else if (op is TextEditOperation) {
|
||||||
document.textEdit(op.path, op.delta);
|
document.updateText(op.path, op.delta);
|
||||||
}
|
}
|
||||||
_observer.add(op);
|
_observer.add(op);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ void _handleCopy(EditorState editorState) async {
|
|||||||
final endNode = editorState.document.nodeAtPath(selection.end.path)!;
|
final endNode = editorState.document.nodeAtPath(selection.end.path)!;
|
||||||
|
|
||||||
final nodes = NodeIterator(
|
final nodes = NodeIterator(
|
||||||
stateTree: editorState.document,
|
document: editorState.document,
|
||||||
startNode: beginNode,
|
startNode: beginNode,
|
||||||
endNode: endNode,
|
endNode: endNode,
|
||||||
).toList();
|
).toList();
|
||||||
@ -321,7 +321,7 @@ void _deleteSelectedContent(EditorState editorState) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final traverser = NodeIterator(
|
final traverser = NodeIterator(
|
||||||
stateTree: editorState.document,
|
document: editorState.document,
|
||||||
startNode: beginNode,
|
startNode: beginNode,
|
||||||
endNode: endNode,
|
endNode: endNode,
|
||||||
);
|
);
|
||||||
|
@ -180,7 +180,7 @@ class _AppFlowySelectionState extends State<AppFlowySelection>
|
|||||||
final endNode = editorState.document.nodeAtPath(end);
|
final endNode = editorState.document.nodeAtPath(end);
|
||||||
if (startNode != null && endNode != null) {
|
if (startNode != null && endNode != null) {
|
||||||
final nodes = NodeIterator(
|
final nodes = NodeIterator(
|
||||||
stateTree: editorState.document,
|
document: editorState.document,
|
||||||
startNode: startNode,
|
startNode: startNode,
|
||||||
endNode: endNode,
|
endNode: endNode,
|
||||||
).toList();
|
).toList();
|
||||||
|
@ -14,7 +14,7 @@ void main() async {
|
|||||||
root.insert(node);
|
root.insert(node);
|
||||||
}
|
}
|
||||||
final nodes = NodeIterator(
|
final nodes = NodeIterator(
|
||||||
stateTree: StateTree(root: root),
|
document: Document(root: root),
|
||||||
startNode: root.childAtPath([0])!,
|
startNode: root.childAtPath([0])!,
|
||||||
endNode: root.childAtPath([10, 10]),
|
endNode: root.childAtPath([10, 10]),
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
group('documemnt.dart', () {
|
||||||
|
test('insert', () {
|
||||||
|
final document = Document.empty();
|
||||||
|
|
||||||
|
expect(document.insert([-1], []), false);
|
||||||
|
expect(document.insert([100], []), false);
|
||||||
|
|
||||||
|
final node0 = Node(type: '0');
|
||||||
|
final node1 = Node(type: '1');
|
||||||
|
expect(document.insert([0], [node0, node1]), true);
|
||||||
|
expect(document.nodeAtPath([0])?.type, '0');
|
||||||
|
expect(document.nodeAtPath([1])?.type, '1');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('delete', () {
|
||||||
|
final document = Document(root: Node(type: 'root'));
|
||||||
|
|
||||||
|
expect(document.delete([-1], 1), false);
|
||||||
|
expect(document.delete([100], 1), false);
|
||||||
|
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
final node = Node(type: '$i');
|
||||||
|
document.insert([i], [node]);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.delete([0], 10);
|
||||||
|
expect(document.root.children.isEmpty, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('update', () {
|
||||||
|
final node = Node(type: 'example', attributes: {'a': 'a'});
|
||||||
|
final document = Document(root: Node(type: 'root'));
|
||||||
|
document.insert([0], [node]);
|
||||||
|
|
||||||
|
final attributes = {
|
||||||
|
'a': 'b',
|
||||||
|
'b': 'c',
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(document.update([0], attributes), true);
|
||||||
|
expect(document.nodeAtPath([0])?.attributes, attributes);
|
||||||
|
|
||||||
|
expect(document.update([-1], attributes), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('updateText', () {
|
||||||
|
final delta = Delta()..insert('Editor');
|
||||||
|
final textNode = TextNode(delta: delta);
|
||||||
|
final document = Document(root: Node(type: 'root'));
|
||||||
|
document.insert([0], [textNode]);
|
||||||
|
document.updateText([0], Delta()..insert('AppFlowy'));
|
||||||
|
expect((document.nodeAtPath([0]) as TextNode).toPlainText(),
|
||||||
|
'AppFlowyEditor');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('serialize', () {
|
||||||
|
final json = {
|
||||||
|
'document': {
|
||||||
|
'type': 'editor',
|
||||||
|
'children': [
|
||||||
|
{
|
||||||
|
'type': 'text',
|
||||||
|
'delta': [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'attributes': {'a': 'a'}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
final document = Document.fromJson(json);
|
||||||
|
expect(document.toJson(), json);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -19,7 +19,7 @@ class EditorWidgetTester {
|
|||||||
EditorState get editorState => _editorState;
|
EditorState get editorState => _editorState;
|
||||||
Node get root => _editorState.document.root;
|
Node get root => _editorState.document.root;
|
||||||
|
|
||||||
StateTree get document => _editorState.document;
|
Document get document => _editorState.document;
|
||||||
int get documentLength => _editorState.document.root.children.length;
|
int get documentLength => _editorState.document.root.children.length;
|
||||||
Selection? get documentSelection =>
|
Selection? get documentSelection =>
|
||||||
_editorState.service.selectionService.currentSelection.value;
|
_editorState.service.selectionService.currentSelection.value;
|
||||||
@ -155,7 +155,7 @@ class EditorWidgetTester {
|
|||||||
|
|
||||||
EditorState _createEmptyDocument() {
|
EditorState _createEmptyDocument() {
|
||||||
return EditorState(
|
return EditorState(
|
||||||
document: StateTree(
|
document: Document(
|
||||||
root: _createEmptyEditorRoot(),
|
root: _createEmptyEditorRoot(),
|
||||||
),
|
),
|
||||||
)..disableSealTimer = true;
|
)..disableSealTimer = true;
|
||||||
|
@ -9,16 +9,16 @@ void main() {
|
|||||||
test('create state tree', () async {
|
test('create state tree', () async {
|
||||||
// final String response = await rootBundle.loadString('assets/document.json');
|
// final String response = await rootBundle.loadString('assets/document.json');
|
||||||
// final data = Map<String, Object>.from(json.decode(response));
|
// final data = Map<String, Object>.from(json.decode(response));
|
||||||
// final stateTree = StateTree.fromJson(data);
|
// final document = StateTree.fromJson(data);
|
||||||
// expect(stateTree.root.type, 'root');
|
// expect(document.root.type, 'root');
|
||||||
// expect(stateTree.root.toJson(), data['document']);
|
// expect(document.root.toJson(), data['document']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('search node by Path in state tree', () async {
|
test('search node by Path in state tree', () async {
|
||||||
// final String response = await rootBundle.loadString('assets/document.json');
|
// final String response = await rootBundle.loadString('assets/document.json');
|
||||||
// final data = Map<String, Object>.from(json.decode(response));
|
// final data = Map<String, Object>.from(json.decode(response));
|
||||||
// final stateTree = StateTree.fromJson(data);
|
// final document = StateTree.fromJson(data);
|
||||||
// final checkBoxNode = stateTree.root.childAtPath([1, 0]);
|
// final checkBoxNode = document.root.childAtPath([1, 0]);
|
||||||
// expect(checkBoxNode != null, true);
|
// expect(checkBoxNode != null, true);
|
||||||
// final textType = checkBoxNode!.attributes['text-type'];
|
// final textType = checkBoxNode!.attributes['text-type'];
|
||||||
// expect(textType != null, true);
|
// expect(textType != null, true);
|
||||||
@ -27,8 +27,8 @@ void main() {
|
|||||||
test('search node by Self in state tree', () async {
|
test('search node by Self in state tree', () async {
|
||||||
// final String response = await rootBundle.loadString('assets/document.json');
|
// final String response = await rootBundle.loadString('assets/document.json');
|
||||||
// final data = Map<String, Object>.from(json.decode(response));
|
// final data = Map<String, Object>.from(json.decode(response));
|
||||||
// final stateTree = StateTree.fromJson(data);
|
// final document = StateTree.fromJson(data);
|
||||||
// final checkBoxNode = stateTree.root.childAtPath([1, 0]);
|
// final checkBoxNode = document.root.childAtPath([1, 0]);
|
||||||
// expect(checkBoxNode != null, true);
|
// expect(checkBoxNode != null, true);
|
||||||
// final textType = checkBoxNode!.attributes['text-type'];
|
// final textType = checkBoxNode!.attributes['text-type'];
|
||||||
// expect(textType != null, true);
|
// expect(textType != null, true);
|
||||||
@ -39,21 +39,21 @@ void main() {
|
|||||||
test('insert node in state tree', () async {
|
test('insert node in state tree', () async {
|
||||||
// final String response = await rootBundle.loadString('assets/document.json');
|
// final String response = await rootBundle.loadString('assets/document.json');
|
||||||
// final data = Map<String, Object>.from(json.decode(response));
|
// final data = Map<String, Object>.from(json.decode(response));
|
||||||
// final stateTree = StateTree.fromJson(data);
|
// final document = StateTree.fromJson(data);
|
||||||
// final insertNode = Node.fromJson({
|
// final insertNode = Node.fromJson({
|
||||||
// 'type': 'text',
|
// 'type': 'text',
|
||||||
// });
|
// });
|
||||||
// bool result = stateTree.insert([1, 1], [insertNode]);
|
// bool result = document.insert([1, 1], [insertNode]);
|
||||||
// expect(result, true);
|
// expect(result, true);
|
||||||
// expect(identical(insertNode, stateTree.nodeAtPath([1, 1])), true);
|
// expect(identical(insertNode, document.nodeAtPath([1, 1])), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('delete node in state tree', () async {
|
test('delete node in state tree', () async {
|
||||||
// final String response = await rootBundle.loadString('assets/document.json');
|
// final String response = await rootBundle.loadString('assets/document.json');
|
||||||
// final data = Map<String, Object>.from(json.decode(response));
|
// final data = Map<String, Object>.from(json.decode(response));
|
||||||
// final stateTree = StateTree.fromJson(data);
|
// final document = StateTree.fromJson(data);
|
||||||
// stateTree.delete([1, 1], 1);
|
// document.delete([1, 1], 1);
|
||||||
// final node = stateTree.nodeAtPath([1, 1]);
|
// final node = document.nodeAtPath([1, 1]);
|
||||||
// expect(node != null, true);
|
// expect(node != null, true);
|
||||||
// expect(node!.attributes['tag'], '**');
|
// expect(node!.attributes['tag'], '**');
|
||||||
});
|
});
|
||||||
@ -61,10 +61,10 @@ void main() {
|
|||||||
test('update node in state tree', () async {
|
test('update node in state tree', () async {
|
||||||
// final String response = await rootBundle.loadString('assets/document.json');
|
// final String response = await rootBundle.loadString('assets/document.json');
|
||||||
// final data = Map<String, Object>.from(json.decode(response));
|
// final data = Map<String, Object>.from(json.decode(response));
|
||||||
// final stateTree = StateTree.fromJson(data);
|
// final document = StateTree.fromJson(data);
|
||||||
// final test = stateTree.update([1, 1], {'text-type': 'heading1'});
|
// final test = document.update([1, 1], {'text-type': 'heading1'});
|
||||||
// expect(test, true);
|
// expect(test, true);
|
||||||
// final updatedNode = stateTree.nodeAtPath([1, 1]);
|
// final updatedNode = document.nodeAtPath([1, 1]);
|
||||||
// expect(updatedNode != null, true);
|
// expect(updatedNode != null, true);
|
||||||
// expect(updatedNode!.attributes['text-type'], 'heading1');
|
// expect(updatedNode!.attributes['text-type'], 'heading1');
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:appflowy_editor/src/operation/operation.dart';
|
import 'package:appflowy_editor/src/operation/operation.dart';
|
||||||
import 'package:appflowy_editor/src/operation/transaction_builder.dart';
|
import 'package:appflowy_editor/src/operation/transaction_builder.dart';
|
||||||
import 'package:appflowy_editor/src/editor_state.dart';
|
import 'package:appflowy_editor/src/editor_state.dart';
|
||||||
import 'package:appflowy_editor/src/document/state_tree.dart';
|
import 'package:appflowy_editor/src/core/state/document.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
@ -56,7 +56,7 @@ void main() {
|
|||||||
item2,
|
item2,
|
||||||
item3,
|
item3,
|
||||||
]));
|
]));
|
||||||
final state = EditorState(document: StateTree(root: root));
|
final state = EditorState(document: Document(root: root));
|
||||||
|
|
||||||
expect(item1.path, [0]);
|
expect(item1.path, [0]);
|
||||||
expect(item2.path, [1]);
|
expect(item2.path, [1]);
|
||||||
@ -74,7 +74,7 @@ void main() {
|
|||||||
group("toJson", () {
|
group("toJson", () {
|
||||||
test("insert", () {
|
test("insert", () {
|
||||||
final root = Node(type: "root", attributes: {}, children: LinkedList());
|
final root = Node(type: "root", attributes: {}, children: LinkedList());
|
||||||
final state = EditorState(document: StateTree(root: root));
|
final state = EditorState(document: Document(root: root));
|
||||||
|
|
||||||
final item1 = Node(type: "node", attributes: {}, children: LinkedList());
|
final item1 = Node(type: "node", attributes: {}, children: LinkedList());
|
||||||
final tb = TransactionBuilder(state);
|
final tb = TransactionBuilder(state);
|
||||||
@ -100,7 +100,7 @@ void main() {
|
|||||||
..addAll([
|
..addAll([
|
||||||
item1,
|
item1,
|
||||||
]));
|
]));
|
||||||
final state = EditorState(document: StateTree(root: root));
|
final state = EditorState(document: Document(root: root));
|
||||||
final tb = TransactionBuilder(state);
|
final tb = TransactionBuilder(state);
|
||||||
tb.deleteNode(item1);
|
tb.deleteNode(item1);
|
||||||
final transaction = tb.finish();
|
final transaction = tb.finish();
|
||||||
|
@ -17,7 +17,7 @@ void main() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("HistoryItem #1", () {
|
test("HistoryItem #1", () {
|
||||||
final document = StateTree(root: _createEmptyEditorRoot());
|
final document = Document(root: _createEmptyEditorRoot());
|
||||||
final editorState = EditorState(document: document);
|
final editorState = EditorState(document: document);
|
||||||
|
|
||||||
final historyItem = HistoryItem();
|
final historyItem = HistoryItem();
|
||||||
@ -35,7 +35,7 @@ void main() async {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("HistoryItem #2", () {
|
test("HistoryItem #2", () {
|
||||||
final document = StateTree(root: _createEmptyEditorRoot());
|
final document = Document(root: _createEmptyEditorRoot());
|
||||||
final editorState = EditorState(document: document);
|
final editorState = EditorState(document: document);
|
||||||
|
|
||||||
final historyItem = HistoryItem();
|
final historyItem = HistoryItem();
|
||||||
|
Loading…
Reference in New Issue
Block a user