Skip to content

Commit

Permalink
Change merging rule
Browse files Browse the repository at this point in the history
  • Loading branch information
hackerwins committed Nov 3, 2023
1 parent a5af300 commit 8a9db21
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 7 deletions.
14 changes: 10 additions & 4 deletions pkg/document/crdt/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,10 +602,16 @@ func (t *Tree) Edit(from, to *TreePos,

// NOTE(hackerwins): If the node overlaps as an opening tag with the
// range then we need to move the remaining children to fromParent.
// TODO(hackerwins): Define more clearly merge-able rules between fromParent
// and toParent. For now, if fromParent and toParent are the same
// type, then we can merge them.
if !node.IsText() && contain == index.OpeningContained && fromParent.Type == toParent.Type {
if !node.IsText() && contain == index.OpeningContained {
// TODO(hackerwins): Define more clearly merge-able rules
// between two parents For now, we only merge two parents are
// both element nodes having text children.
// e.g. <p>a|b</p><p>c|d</p> -> <p>a|d</p>
if !fromParent.Value.IndexTreeNode.HasTextChild() &&
toParent.Value.IndexTreeNode.HasTextChild() {
return
}

for _, child := range node.IndexTreeNode.Children() {
if slices.Contains(toBeRemoveds, child.Value) {
continue
Expand Down
27 changes: 27 additions & 0 deletions pkg/document/crdt/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,33 @@ func TestTree(t *testing.T) {
assert.Equal(t, "<root><p>@ad</p></root>", tree.ToXML())
})

t.Run("delete nodes between elements in different levels test", func(t *testing.T) {
// 01. Create a tree with 2 paragraphs.
// 0 1 2 3 4 5 6 7 8 9 10
// <root> <p> <b> a b </b> </p> <p> c d </p> </root>

ctx := helper.TextChangeContext(helper.TestRoot())
tree := crdt.NewTree(crdt.NewTreeNode(helper.IssuePos(ctx), "root", nil), helper.IssueTime(ctx))
_, err := tree.EditByIndex(0, 0, nil, []*crdt.TreeNode{crdt.NewTreeNode(helper.IssuePos(ctx), "p", nil)}, helper.IssueTime(ctx))
assert.NoError(t, err)
_, err = tree.EditByIndex(1, 1, nil, []*crdt.TreeNode{crdt.NewTreeNode(helper.IssuePos(ctx), "b", nil)}, helper.IssueTime(ctx))
assert.NoError(t, err)
_, err = tree.EditByIndex(2, 2, nil, []*crdt.TreeNode{crdt.NewTreeNode(helper.IssuePos(ctx), "text", nil, "ab")}, helper.IssueTime(ctx))
assert.NoError(t, err)
_, err = tree.EditByIndex(6, 6, nil, []*crdt.TreeNode{crdt.NewTreeNode(helper.IssuePos(ctx), "p", nil)}, helper.IssueTime(ctx))
assert.NoError(t, err)
_, err = tree.EditByIndex(7, 7, nil, []*crdt.TreeNode{crdt.NewTreeNode(helper.IssuePos(ctx), "text", nil, "cd")}, helper.IssueTime(ctx))
assert.NoError(t, err)
assert.Equal(t, "<root><p><b>ab</b></p><p>cd</p></root>", tree.ToXML())

// 02. delete b, c and first paragraph.
// 0 1 2 3 4 5
// <root> <p> <b> a d </b> </root>
_, err = tree.EditByIndex(3, 8, nil, nil, helper.IssueTime(ctx))
assert.NoError(t, err)
assert.Equal(t, "<root><p><b>ad</b></p></root>", tree.ToXML())
})

t.Run("style node with element attributes test", func(t *testing.T) {
// 01. style attributes to an element node.
ctx := helper.TextChangeContext(helper.TestRoot())
Expand Down
6 changes: 3 additions & 3 deletions pkg/index/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,8 @@ func (n *Node[V]) InsertAfter(newNode, referenceNode *Node[V]) error {
return nil
}

// hasTextChild returns true if the node has a text child.
func (n *Node[V]) hasTextChild() bool {
// HasTextChild returns true if the node has a text child.
func (n *Node[V]) HasTextChild() bool {
for _, child := range n.Children() {
if child.IsText() {
return true
Expand Down Expand Up @@ -765,7 +765,7 @@ func (t *Tree[V]) PathToTreePos(path []int) (*TreePos[V], error) {
}
}

if node.hasTextChild() {
if node.HasTextChild() {
return findTextPos(node, path[len(path)-1])
}
if len(node.Children()) < path[len(path)-1] {
Expand Down

0 comments on commit 8a9db21

Please sign in to comment.