diff --git a/kernel/api/search.go b/kernel/api/search.go index e66fcc643..dc39a3d6e 100644 --- a/kernel/api/search.go +++ b/kernel/api/search.go @@ -138,8 +138,8 @@ func searchEmbedBlock(c *gin.Context) { if nil != headingModeArg { headingMode = int(headingModeArg.(float64)) } - blocks := model.SearchEmbedBlock(stmt, excludeIDs, headingMode) + blocks := model.SearchEmbedBlock(stmt, excludeIDs, headingMode) ret.Data = map[string]interface{}{ "blocks": blocks, } diff --git a/kernel/model/block.go b/kernel/model/block.go index 10f15d495..8d6b6f284 100644 --- a/kernel/model/block.go +++ b/kernel/model/block.go @@ -381,12 +381,15 @@ func getBlock(id string) (ret *Block, err error) { return } -func getBlockRendered(id string, headingMode int) (ret *Block) { - tree, _ := loadTreeByBlockID(id) +func getBlockRendered(trees map[string]*parse.Tree, sqlBlock *sql.Block, headingMode int) (block *Block, blockPaths []*BlockPath) { + tree, _ := trees[sqlBlock.RootID] + if nil == tree { + tree, _ = loadTreeByBlockID(sqlBlock.RootID) + } if nil == tree { return } - def := treenode.GetNodeInTree(tree, id) + def := treenode.GetNodeInTree(tree, sqlBlock.ID) if nil == def { return } @@ -430,6 +433,7 @@ func getBlockRendered(id string, headingMode int) (ret *Block) { luteEngine := NewLute() luteEngine.RenderOptions.ProtyleContenteditable = false // 不可编辑 dom := renderBlockDOMByNodes(nodes, luteEngine) - ret = &Block{Box: def.Box, Path: def.Path, HPath: b.HPath, ID: def.ID, Type: def.Type.String(), Content: dom} + block = &Block{Box: def.Box, Path: def.Path, HPath: b.HPath, ID: def.ID, Type: def.Type.String(), Content: dom} + blockPaths = buildBlockBreadcrumb(def) return } diff --git a/kernel/model/export.go b/kernel/model/export.go index 1bb70f985..594580ae4 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -1038,14 +1038,14 @@ func exportTree(tree *parse.Tree, wysiwyg, expandKaTexMacros, keepFold bool) (re var defMd string stmt := n.ChildByType(ast.NodeBlockQueryEmbedScript).TokensStr() stmt = html.UnescapeString(stmt) - blocks := searchEmbedBlock(stmt, nil, 0) - if 1 > len(blocks) { + embedBlocks := searchEmbedBlock(stmt, nil, 0) + if 1 > len(embedBlocks) { return ast.WalkContinue } defMdBuf := bytes.Buffer{} - for _, def := range blocks { - defMdBuf.WriteString(renderBlockMarkdownR(def.ID)) + for _, def := range embedBlocks { + defMdBuf.WriteString(renderBlockMarkdownR(def.Block.ID)) defMdBuf.WriteString("\n\n") } defMd = defMdBuf.String() diff --git a/kernel/model/search.go b/kernel/model/search.go index 14e65d11b..ef53bc9da 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -38,12 +38,17 @@ import ( "github.com/xrash/smetrics" ) -func SearchEmbedBlock(stmt string, excludeIDs []string, headingMode int) (ret []*Block) { +type EmbedBlock struct { + Block *Block `json:"block"` + BlockPath []*BlockPath `json:"blockPath"` +} + +func SearchEmbedBlock(stmt string, excludeIDs []string, headingMode int) (ret []*EmbedBlock) { WaitForWritingFiles() return searchEmbedBlock(stmt, excludeIDs, headingMode) } -func searchEmbedBlock(stmt string, excludeIDs []string, headingMode int) (ret []*Block) { +func searchEmbedBlock(stmt string, excludeIDs []string, headingMode int) (ret []*EmbedBlock) { sqlBlocks := sql.SelectBlocksRawStmtNoParse(stmt, Conf.Search.Limit) var tmp []*sql.Block for _, b := range sqlBlocks { @@ -52,16 +57,37 @@ func searchEmbedBlock(stmt string, excludeIDs []string, headingMode int) (ret [] } } sqlBlocks = tmp + + // 缓存最多 128 棵语法树 + trees := map[string]*parse.Tree{} + count := 0 for _, sb := range sqlBlocks { - block := getBlockRendered(sb.ID, headingMode) + if nil == trees[sb.RootID] { + tree, _ := loadTreeByBlockID(sb.RootID) + if nil == tree { + continue + } + trees[sb.RootID] = tree + count++ + } + if 127 < count { + break + } + } + + for _, sb := range sqlBlocks { + block, blockPaths := getBlockRendered(trees, sb, headingMode) if nil == block { continue } - ret = append(ret, block) + ret = append(ret, &EmbedBlock{ + Block: block, + BlockPath: blockPaths, + }) } if 1 > len(ret) { - ret = []*Block{} + ret = []*EmbedBlock{} } return }