diff --git a/kernel/api/block.go b/kernel/api/block.go index 187cc2d36..9e578bb83 100644 --- a/kernel/api/block.go +++ b/kernel/api/block.go @@ -813,6 +813,42 @@ func getBlockKramdown(c *gin.Context) { } } +func getBlockKramdowns(c *gin.Context) { + ret := gulu.Ret.NewResult() + defer c.JSON(http.StatusOK, ret) + + arg, ok := util.JsonArg(c, ret) + if !ok { + return + } + + idsArg := arg["ids"].([]interface{}) + var ids []string + for _, id := range idsArg { + idStr := id.(string) + // 验证 ID 格式,跳过无效的 ID + if !util.InvalidIDPattern(idStr, nil) { + ids = append(ids, idStr) + } + } + + // md:Markdown 标记符模式,使用标记符导出 + // textmark:文本标记模式,使用 span 标签导出 + // https://github.com/siyuan-note/siyuan/issues/13183 + mode := "md" + if modeArg := arg["mode"]; nil != modeArg { + mode = modeArg.(string) + if "md" != mode && "textmark" != mode { + ret.Code = -1 + ret.Msg = "Invalid mode" + return + } + } + + kramdowns := model.GetBlockKramdowns(ids, mode) + ret.Data = kramdowns +} + func getChildBlocks(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 d36fe83a6..4549c35a5 100644 --- a/kernel/api/router.go +++ b/kernel/api/router.go @@ -188,6 +188,7 @@ func ServeAPI(ginServer *gin.Engine) { ginServer.Handle("POST", "/api/block/getBlockDOMWithEmbed", model.CheckAuth, getBlockDOMWithEmbed) ginServer.Handle("POST", "/api/block/getBlockDOMsWithEmbed", model.CheckAuth, getBlockDOMsWithEmbed) ginServer.Handle("POST", "/api/block/getBlockKramdown", model.CheckAuth, getBlockKramdown) + ginServer.Handle("POST", "/api/block/getBlockKramdowns", model.CheckAuth, getBlockKramdowns) ginServer.Handle("POST", "/api/block/getChildBlocks", model.CheckAuth, getChildBlocks) ginServer.Handle("POST", "/api/block/getTailChildBlocks", model.CheckAuth, getTailChildBlocks) ginServer.Handle("POST", "/api/block/getBlockBreadcrumb", model.CheckAuth, getBlockBreadcrumb) diff --git a/kernel/model/block.go b/kernel/model/block.go index 3418b7e4d..557045451 100644 --- a/kernel/model/block.go +++ b/kernel/model/block.go @@ -1034,6 +1034,43 @@ func GetBlockKramdown(id, mode string) (ret string) { return } +func GetBlockKramdowns(ids []string, mode string) (ret map[string]string) { + ret = map[string]string{} + if 0 == len(ids) { + return + } + + luteEngine := NewLute() + if "md" == mode { + // `/api/block/getBlockKramdown` link/image URLs are no longer encoded with spaces https://github.com/siyuan-note/siyuan/issues/15611 + luteEngine.SetPreventEncodeLinkSpace(true) + } + + trees := filesys.LoadTrees(ids) + for id, tree := range trees { + node := treenode.GetNodeInTree(tree, id) + if nil == node { + continue + } + + addBlockIALNodes(tree, false) + root := &ast.Node{Type: ast.NodeDocument} + root.AppendChild(node.Next) // IAL + root.PrependChild(node) + + var kramdown string + if "md" == mode { + kramdown = treenode.ExportNodeStdMd(root, luteEngine) + } else { + tree.Root = root + formatRenderer := render.NewFormatRenderer(tree, luteEngine.RenderOptions, luteEngine.ParseOptions) + kramdown = string(formatRenderer.Render()) + } + ret[id] = kramdown + } + return +} + type ChildBlock struct { ID string `json:"id"` Type string `json:"type"`