Parcourir la source

:art: Add a kernel API `/api/block/getBlockTreeInfos` https://github.com/siyuan-note/siyuan/issues/11311

Daniel il y a 1 an
Parent
commit
7d73482cfa
4 fichiers modifiés avec 120 ajouts et 22 suppressions
  1. 18 0
      kernel/api/block.go
  2. 1 0
      kernel/api/router.go
  3. 68 22
      kernel/model/block.go
  4. 33 0
      kernel/treenode/node.go

+ 18 - 0
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)

+ 1 - 0
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)

+ 68 - 22
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)

+ 33 - 0
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 {