diff --git a/kernel/api/block_op.go b/kernel/api/block_op.go index 1584d3e4a..8a054c14e 100644 --- a/kernel/api/block_op.go +++ b/kernel/api/block_op.go @@ -123,13 +123,16 @@ func insertBlock(c *gin.Context) { data := arg["data"].(string) dataType := arg["dataType"].(string) - var parentID, previousID string + var parentID, previousID, nextID string if nil != arg["parentID"] { parentID = arg["parentID"].(string) } if nil != arg["previousID"] { previousID = arg["previousID"].(string) } + if nil != arg["nextID"] { + nextID = arg["nextID"].(string) + } if "markdown" == dataType { luteEngine := model.NewLute() @@ -144,6 +147,7 @@ func insertBlock(c *gin.Context) { Data: data, ParentID: parentID, PreviousID: previousID, + NextID: nextID, }, }, }, diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index fad01e0da..10bd0b730 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -708,11 +708,15 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) { if nil == block { block = treenode.GetBlockTree(operation.PreviousID) if nil == block { - msg := fmt.Sprintf("not found previous block [id=%s]", operation.PreviousID) - logging.LogErrorf(msg) - return &TxErr{code: TxErrCodeBlockNotFound, id: operation.PreviousID} + block = treenode.GetBlockTree(operation.NextID) } } + if nil == block { + msg := fmt.Sprintf("not found next block [id=%s]", operation.NextID) + logging.LogErrorf(msg) + return &TxErr{code: TxErrCodeBlockNotFound, id: operation.NextID} + } + tree, err := tx.loadTree(block.ID) if errors.Is(err, filelock.ErrUnableAccessFile) { return &TxErr{code: TxErrCodeUnableAccessFile, msg: err.Error(), id: block.ID} @@ -780,8 +784,20 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) { } var node *ast.Node + nextID := operation.NextID previousID := operation.PreviousID - if "" != previousID { + if "" != nextID { + node = treenode.GetNodeInTree(tree, nextID) + if nil == node { + logging.LogErrorf("get node [%s] in tree [%s] failed", nextID, tree.Root.ID) + return &TxErr{code: TxErrCodeBlockNotFound, id: nextID} + } + + if ast.NodeList == insertedNode.Type && nil != node.Parent && ast.NodeList == node.Parent.Type { + insertedNode = insertedNode.FirstChild + } + node.InsertBefore(insertedNode) + } else if "" != previousID { node = treenode.GetNodeInTree(tree, previousID) if nil == node { logging.LogErrorf("get node [%s] in tree [%s] failed", previousID, tree.Root.ID) @@ -973,6 +989,7 @@ type Operation struct { ID string `json:"id"` ParentID string `json:"parentID"` PreviousID string `json:"previousID"` + NextID string `json:"nextID"` RetData interface{} `json:"retData"` discard bool // 用于标识是否在事务合并中丢弃 diff --git a/kernel/treenode/node.go b/kernel/treenode/node.go index 29a2238b6..a01d7e91b 100644 --- a/kernel/treenode/node.go +++ b/kernel/treenode/node.go @@ -195,11 +195,18 @@ func CountBlockNodes(node *ast.Node) (ret int) { } func ParentNodes(node *ast.Node) (parents []*ast.Node) { + const maxDepth = 256 + i := 0 for n := node.Parent; nil != n; n = n.Parent { + i++ parents = append(parents, n) if ast.NodeDocument == n.Type { return } + if maxDepth < i { + logging.LogWarnf("parent nodes of node [%s] is too deep", node.ID) + return + } } return }