diff --git a/kernel/api/block.go b/kernel/api/block.go index 1e7ea0722..e9b5049bc 100644 --- a/kernel/api/block.go +++ b/kernel/api/block.go @@ -29,6 +29,24 @@ import ( "github.com/siyuan-note/siyuan/kernel/util" ) +func getBlockTreeInfos(c *gin.Context) { + ret := gulu.Ret.NewResult() + defer c.JSON(http.StatusOK, ret) + + arg, ok := util.JsonArg(c, ret) + if !ok { + return + } + + var ids []string + idsArg := arg["ids"].([]interface{}) + for _, id := range idsArg { + ids = append(ids, id.(string)) + } + + ret.Data = model.GetBlockTreeInfos(ids) +} + func getBlockSiblingID(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret) diff --git a/kernel/api/router.go b/kernel/api/router.go index 6b5f53015..b0b3d07b5 100644 --- a/kernel/api/router.go +++ b/kernel/api/router.go @@ -199,6 +199,7 @@ func ServeAPI(ginServer *gin.Engine) { ginServer.Handle("POST", "/api/block/swapBlockRef", model.CheckAuth, model.CheckReadonly, swapBlockRef) ginServer.Handle("POST", "/api/block/transferBlockRef", model.CheckAuth, model.CheckReadonly, transferBlockRef) ginServer.Handle("POST", "/api/block/getBlockSiblingID", model.CheckAuth, getBlockSiblingID) + ginServer.Handle("POST", "/api/block/getBlockTreeInfos", model.CheckAuth, getBlockTreeInfos) ginServer.Handle("POST", "/api/file/getFile", model.CheckAuth, getFile) ginServer.Handle("POST", "/api/file/putFile", model.CheckAuth, model.CheckReadonly, putFile) diff --git a/kernel/model/block.go b/kernel/model/block.go index 8073bf9b0..4f551bda4 100644 --- a/kernel/model/block.go +++ b/kernel/model/block.go @@ -26,6 +26,7 @@ import ( "github.com/88250/lute/ast" "github.com/88250/lute/parse" "github.com/open-spaced-repetition/go-fsrs" + "github.com/siyuan-note/siyuan/kernel/filesys" "github.com/siyuan-note/siyuan/kernel/sql" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" @@ -114,6 +115,66 @@ type Path struct { Created string `json:"created"` // 创建时间 } +type BlockTreeInfo struct { + ID string `json:"id"` + Type string `json:"type"` + ParentID string `json:"parentID"` + ParentType string `json:"parentType"` + PreviousID string `json:"previousID"` + PreviousType string `json:"previousType"` + NextID string `json:"nextID"` + NextType string `json:"nextType"` +} + +func GetBlockTreeInfos(ids []string) (ret map[string]*BlockTreeInfo) { + ret = map[string]*BlockTreeInfo{} + luteEngine := util.NewLute() + treeCache := map[string]*parse.Tree{} + for _, id := range ids { + bt := treenode.GetBlockTree(id) + if nil == bt { + ret[id] = &BlockTreeInfo{ID: id} + continue + } + + tree := treeCache[bt.RootID] + if nil == tree { + tree, _ = filesys.LoadTree(bt.BoxID, bt.Path, luteEngine) + if nil == tree { + ret[id] = &BlockTreeInfo{ID: id} + continue + } + + treeCache[bt.RootID] = tree + } + + node := treenode.GetNodeInTree(tree, id) + if nil == node { + ret[id] = &BlockTreeInfo{ID: id} + continue + } + + bti := &BlockTreeInfo{ID: id, Type: node.Type.String()} + ret[id] = bti + parent := treenode.ParentBlock(node) + if nil != parent { + bti.ParentID = parent.ID + bti.ParentType = parent.Type.String() + } + previous := treenode.PreviousBlock(node) + if nil != previous { + bti.PreviousID = previous.ID + bti.PreviousType = previous.Type.String() + } + next := treenode.NextBlock(node) + if nil != next { + bti.NextID = next.ID + bti.NextType = next.Type.String() + } + } + return +} + func GetBlockSiblingID(id string) (parent, previous, next string) { tree, err := LoadTreeByBlockID(id) if nil != err { @@ -147,14 +208,14 @@ func GetBlockSiblingID(id string) (parent, previous, next string) { if parentListItem.Previous != nil { previous = parentListItem.Previous.ID - if flb := firstChild(parentListItem.Previous); nil != flb { + if flb := treenode.FirstChildBlock(parentListItem.Previous); nil != flb { previous = flb.ID } } if parentListItem.Next != nil { next = parentListItem.Next.ID - if flb := firstChild(parentListItem.Next); nil != flb { + if flb := treenode.FirstChildBlock(parentListItem.Next); nil != flb { next = flb.ID } } @@ -167,7 +228,7 @@ func GetBlockSiblingID(id string) (parent, previous, next string) { if nil != current.Parent && current.Parent.IsBlock() { parent = current.Parent.ID - if flb := firstChild(current.Parent); nil != flb { + if flb := treenode.FirstChildBlock(current.Parent); nil != flb { parent = flb.ID } @@ -176,28 +237,28 @@ func GetBlockSiblingID(id string) (parent, previous, next string) { if nil != current.Previous && current.Previous.IsBlock() { previous = current.Previous.ID - if flb := firstChild(current.Previous); nil != flb { + if flb := treenode.FirstChildBlock(current.Previous); nil != flb { previous = flb.ID } } if nil != current.Next && current.Next.IsBlock() { next = current.Next.ID - if flb := firstChild(current.Next); nil != flb { + if flb := treenode.FirstChildBlock(current.Next); nil != flb { next = flb.ID } } } else { if nil != current.Parent.Previous && current.Parent.Previous.IsBlock() { previous = current.Parent.Previous.ID - if flb := firstChild(current.Parent.Previous); nil != flb { + if flb := treenode.FirstChildBlock(current.Parent.Previous); nil != flb { previous = flb.ID } } if nil != current.Parent.Next && current.Parent.Next.IsBlock() { next = current.Parent.Next.ID - if flb := firstChild(current.Parent.Next); nil != flb { + if flb := treenode.FirstChildBlock(current.Parent.Next); nil != flb { next = flb.ID } } @@ -207,21 +268,6 @@ func GetBlockSiblingID(id string) (parent, previous, next string) { return } -func firstChild(node *ast.Node) (ret *ast.Node) { - ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus { - if !entering { - return ast.WalkContinue - } - - if n.IsBlock() { - ret = n - return ast.WalkStop - } - return ast.WalkContinue - }) - return -} - func IsBlockFolded(id string) bool { for i := 0; i < 32; i++ { b, _ := getBlock(id, nil) diff --git a/kernel/treenode/node.go b/kernel/treenode/node.go index 72d1a2bb5..035de13e4 100644 --- a/kernel/treenode/node.go +++ b/kernel/treenode/node.go @@ -401,6 +401,39 @@ func ParentBlock(node *ast.Node) *ast.Node { return nil } +func PreviousBlock(node *ast.Node) *ast.Node { + for n := node.Previous; nil != n; n = n.Previous { + if "" != n.ID && n.IsBlock() { + return n + } + } + return nil +} + +func NextBlock(node *ast.Node) *ast.Node { + for n := node.Next; nil != n; n = n.Next { + if "" != n.ID && n.IsBlock() { + return n + } + } + return nil +} + +func FirstChildBlock(node *ast.Node) (ret *ast.Node) { + ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus { + if !entering { + return ast.WalkContinue + } + + if n.IsBlock() { + ret = n + return ast.WalkStop + } + return ast.WalkContinue + }) + return +} + func GetNodeInTree(tree *parse.Tree, id string) (ret *ast.Node) { ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { if !entering {