From a8b1b51c96a55c540a1376fe5cc4332d2beab21f Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 5 Mar 2024 20:24:23 +0800 Subject: [PATCH] :art: Add kernel API `/api/filetree/listDocTree` Fix https://github.com/siyuan-note/siyuan/issues/10482 --- kernel/api/filetree.go | 103 +++++++++++++++++++++++++++++++++++++++++ kernel/api/router.go | 1 + 2 files changed, 104 insertions(+) diff --git a/kernel/api/filetree.go b/kernel/api/filetree.go index 357b2ce19..38fee2383 100644 --- a/kernel/api/filetree.go +++ b/kernel/api/filetree.go @@ -20,7 +20,9 @@ import ( "fmt" "math" "net/http" + "os" "path" + "path/filepath" "regexp" "strings" "unicode/utf8" @@ -33,6 +35,107 @@ import ( "github.com/siyuan-note/siyuan/kernel/util" ) +func listDocTree(c *gin.Context) { + // Add kernel API `/api/filetree/listDocTree` https://github.com/siyuan-note/siyuan/issues/10482 + + ret := gulu.Ret.NewResult() + defer c.JSON(http.StatusOK, ret) + + arg, ok := util.JsonArg(c, ret) + if !ok { + return + } + + notebook := arg["notebook"].(string) + if util.InvalidIDPattern(notebook, ret) { + return + } + + p := arg["path"].(string) + var doctree []*DocFile + root := filepath.Join(util.WorkspaceDir, "data", notebook, p) + dir, err := os.ReadDir(root) + if nil != err { + ret.Code = -1 + ret.Msg = err.Error() + return + } + + ids := map[string]bool{} + for _, entry := range dir { + if entry.IsDir() { + if strings.HasPrefix(entry.Name(), ".") { + continue + } + + if !ast.IsNodeIDPattern(entry.Name()) { + continue + } + + parent := &DocFile{ID: entry.Name()} + ids[parent.ID] = true + doctree = append(doctree, parent) + + subPath := filepath.Join(root, entry.Name()) + if err = walkDocTree(subPath, parent, &ids); nil != err { + ret.Code = -1 + ret.Msg = err.Error() + return + } + } else { + doc := &DocFile{ID: strings.TrimSuffix(entry.Name(), ".sy")} + if !ids[doc.ID] { + doctree = append(doctree, doc) + } + ids[doc.ID] = true + } + } + + ret.Data = map[string]interface{}{ + "tree": doctree, + } +} + +type DocFile struct { + ID string `json:"id"` + Children []*DocFile `json:"children,omitempty"` +} + +func walkDocTree(p string, docFile *DocFile, ids *map[string]bool) (err error) { + dir, err := os.ReadDir(p) + if nil != err { + return + } + + for _, entry := range dir { + if entry.IsDir() { + if strings.HasPrefix(entry.Name(), ".") { + continue + } + + if !ast.IsNodeIDPattern(entry.Name()) { + continue + } + + parent := &DocFile{ID: entry.Name()} + (*ids)[parent.ID] = true + docFile.Children = append(docFile.Children, parent) + + subPath := filepath.Join(p, entry.Name()) + if err = walkDocTree(subPath, parent, ids); nil != err { + return + } + } else { + doc := &DocFile{ID: strings.TrimSuffix(entry.Name(), ".sy")} + if !(*ids)[doc.ID] { + docFile.Children = append(docFile.Children, doc) + } + (*ids)[doc.ID] = true + } + } + return +} + func upsertIndexes(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 791aef45b..071734604 100644 --- a/kernel/api/router.go +++ b/kernel/api/router.go @@ -115,6 +115,7 @@ func ServeAPI(ginServer *gin.Engine) { ginServer.Handle("POST", "/api/filetree/refreshFiletree", model.CheckAuth, model.CheckReadonly, refreshFiletree) ginServer.Handle("POST", "/api/filetree/upsertIndexes", model.CheckAuth, model.CheckReadonly, upsertIndexes) ginServer.Handle("POST", "/api/filetree/removeIndexes", model.CheckAuth, model.CheckReadonly, removeIndexes) + ginServer.Handle("POST", "/api/filetree/listDocTree", model.CheckAuth, model.CheckReadonly, listDocTree) ginServer.Handle("POST", "/api/format/autoSpace", model.CheckAuth, model.CheckReadonly, autoSpace) ginServer.Handle("POST", "/api/format/netImg2LocalAssets", model.CheckAuth, model.CheckReadonly, netImg2LocalAssets)