Browse Source

:zap: 改进重命名资源文件性能 https://github.com/siyuan-note/siyuan/issues/7322
改进建立引用索引 https://github.com/siyuan-note/siyuan/issues/7320

Liang Ding 2 years ago
parent
commit
b6ea32462e

+ 7 - 6
kernel/api/block_op.go

@@ -17,14 +17,15 @@
 package api
 package api
 
 
 import (
 import (
-	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"net/http"
 	"net/http"
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute"
 	"github.com/88250/lute"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
+	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -44,7 +45,7 @@ func appendBlock(c *gin.Context) {
 		return
 		return
 	}
 	}
 	if "markdown" == dataType {
 	if "markdown" == dataType {
-		luteEngine := model.NewLute()
+		luteEngine := util.NewLute()
 		data = dataBlockDOM(data, luteEngine)
 		data = dataBlockDOM(data, luteEngine)
 	}
 	}
 
 
@@ -89,7 +90,7 @@ func prependBlock(c *gin.Context) {
 		return
 		return
 	}
 	}
 	if "markdown" == dataType {
 	if "markdown" == dataType {
-		luteEngine := model.NewLute()
+		luteEngine := util.NewLute()
 		data = dataBlockDOM(data, luteEngine)
 		data = dataBlockDOM(data, luteEngine)
 	}
 	}
 
 
@@ -150,7 +151,7 @@ func insertBlock(c *gin.Context) {
 	}
 	}
 
 
 	if "markdown" == dataType {
 	if "markdown" == dataType {
-		luteEngine := model.NewLute()
+		luteEngine := util.NewLute()
 		data = dataBlockDOM(data, luteEngine)
 		data = dataBlockDOM(data, luteEngine)
 	}
 	}
 
 
@@ -197,7 +198,7 @@ func updateBlock(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	luteEngine := model.NewLute()
+	luteEngine := util.NewLute()
 	if "markdown" == dataType {
 	if "markdown" == dataType {
 		data = dataBlockDOM(data, luteEngine)
 		data = dataBlockDOM(data, luteEngine)
 	}
 	}
@@ -217,7 +218,7 @@ func updateBlock(c *gin.Context) {
 
 
 	var transactions []*model.Transaction
 	var transactions []*model.Transaction
 	if "NodeDocument" == block.Type {
 	if "NodeDocument" == block.Type {
-		oldTree, err := model.LoadTree(block.Box, block.Path)
+		oldTree, err := filesys.LoadTree(block.Box, block.Path, luteEngine)
 		if nil != err {
 		if nil != err {
 			ret.Code = -1
 			ret.Code = -1
 			ret.Msg = "load tree failed: " + err.Error()
 			ret.Msg = "load tree failed: " + err.Error()

+ 7 - 3
kernel/api/filetree.go

@@ -28,6 +28,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -86,7 +87,8 @@ func heading2Doc(c *gin.Context) {
 	}
 	}
 
 
 	model.WaitForWritingFiles()
 	model.WaitForWritingFiles()
-	tree, err := model.LoadTree(targetNotebook, targetPath)
+	luteEngine := util.NewLute()
+	tree, err := filesys.LoadTree(targetNotebook, targetPath, luteEngine)
 	if nil != err {
 	if nil != err {
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
@@ -130,7 +132,8 @@ func li2Doc(c *gin.Context) {
 	}
 	}
 
 
 	model.WaitForWritingFiles()
 	model.WaitForWritingFiles()
-	tree, err := model.LoadTree(targetNotebook, targetPath)
+	luteEngine := util.NewLute()
+	tree, err := filesys.LoadTree(targetNotebook, targetPath, luteEngine)
 	if nil != err {
 	if nil != err {
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
@@ -424,7 +427,8 @@ func createDailyNote(c *gin.Context) {
 
 
 	box := model.Conf.Box(notebook)
 	box := model.Conf.Box(notebook)
 	model.WaitForWritingFiles()
 	model.WaitForWritingFiles()
-	tree, err := model.LoadTree(box.ID, p)
+	luteEngine := util.NewLute()
+	tree, err := filesys.LoadTree(box.ID, p, luteEngine)
 	if nil != err {
 	if nil != err {
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()

+ 1 - 1
kernel/api/lute.go

@@ -62,7 +62,7 @@ func html2BlockDOM(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	luteEngine := model.NewLute()
+	luteEngine := util.NewLute()
 	var unlinks []*ast.Node
 	var unlinks []*ast.Node
 	tree := parse.Parse("", []byte(markdown), luteEngine.ParseOptions)
 	tree := parse.Parse("", []byte(markdown), luteEngine.ParseOptions)
 	ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
 	ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {

+ 4 - 1
kernel/filesys/tree.go

@@ -40,6 +40,7 @@ func LoadTree(boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err erro
 	filePath := filepath.Join(util.DataDir, boxID, p)
 	filePath := filepath.Join(util.DataDir, boxID, p)
 	data, err := filelock.ReadFile(filePath)
 	data, err := filelock.ReadFile(filePath)
 	if nil != err {
 	if nil != err {
+		logging.LogErrorf("load tree [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 
 
@@ -50,7 +51,9 @@ func LoadTree(boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err erro
 func LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {
 func LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {
 	ret = parseJSON2Tree(boxID, p, data, luteEngine)
 	ret = parseJSON2Tree(boxID, p, data, luteEngine)
 	if nil == ret {
 	if nil == ret {
-		return nil, errors.New("parse tree failed")
+		logging.LogErrorf("parse tree [%s] failed", p)
+		err = errors.New("parse tree failed")
+		return
 	}
 	}
 	ret.Path = p
 	ret.Path = p
 	ret.Root.Path = p
 	ret.Root.Path = p

+ 4 - 4
kernel/model/assets.go

@@ -434,7 +434,7 @@ func RemoveUnusedAssets() (ret []string) {
 		IncSync()
 		IncSync()
 	}
 	}
 
 
-	indexHistoryDir(filepath.Base(historyDir), NewLute())
+	indexHistoryDir(filepath.Base(historyDir), util.NewLute())
 	cache.LoadAssets()
 	cache.LoadAssets()
 	return
 	return
 }
 }
@@ -468,7 +468,7 @@ func RemoveUnusedAsset(p string) (ret string) {
 	ret = absPath
 	ret = absPath
 	IncSync()
 	IncSync()
 
 
-	indexHistoryDir(filepath.Base(historyDir), NewLute())
+	indexHistoryDir(filepath.Base(historyDir), util.NewLute())
 	cache.RemoveAsset(p)
 	cache.RemoveAsset(p)
 	return
 	return
 }
 }
@@ -504,7 +504,7 @@ func RenameAsset(oldPath, newName string) (err error) {
 		return
 		return
 	}
 	}
 
 
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	for _, notebook := range notebooks {
 	for _, notebook := range notebooks {
 		pages := pagedPaths(filepath.Join(util.DataDir, notebook.ID), 32)
 		pages := pagedPaths(filepath.Join(util.DataDir, notebook.ID), 32)
 
 
@@ -562,7 +562,7 @@ func UnusedAssets() (ret []string) {
 	if nil != err {
 	if nil != err {
 		return
 		return
 	}
 	}
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	for _, notebook := range notebooks {
 	for _, notebook := range notebooks {
 		dests := map[string]bool{}
 		dests := map[string]bool{}
 
 

+ 1 - 1
kernel/model/backlink.go

@@ -665,7 +665,7 @@ func searchBackmention(mentionKeywords []string, keyword string, excludeBacklink
 	}
 	}
 	blocks := fromSQLBlocks(&sqlBlocks, strings.Join(terms, search.TermSep), beforeLen)
 	blocks := fromSQLBlocks(&sqlBlocks, strings.Join(terms, search.TermSep), beforeLen)
 
 
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	var tmp []*Block
 	var tmp []*Block
 	for _, b := range blocks {
 	for _, b := range blocks {
 		tree := parse.Parse("", gulu.Str.ToBytes(b.Markdown), luteEngine.ParseOptions)
 		tree := parse.Parse("", gulu.Str.ToBytes(b.Markdown), luteEngine.ParseOptions)

+ 3 - 3
kernel/model/block.go

@@ -294,7 +294,7 @@ func GetHeadingDeleteTransaction(id string) (transaction *Transaction, err error
 	nodes = append(nodes, treenode.HeadingChildren(node)...)
 	nodes = append(nodes, treenode.HeadingChildren(node)...)
 
 
 	transaction = &Transaction{}
 	transaction = &Transaction{}
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	for _, n := range nodes {
 	for _, n := range nodes {
 		op := &Operation{}
 		op := &Operation{}
 		op.ID = n.ID
 		op.ID = n.ID
@@ -347,7 +347,7 @@ func GetHeadingChildrenDOM(id string) (ret string) {
 	nodes := append([]*ast.Node{}, heading)
 	nodes := append([]*ast.Node{}, heading)
 	children := treenode.HeadingChildren(heading)
 	children := treenode.HeadingChildren(heading)
 	nodes = append(nodes, children...)
 	nodes = append(nodes, children...)
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	ret = renderBlockDOMByNodes(nodes, luteEngine)
 	ret = renderBlockDOMByNodes(nodes, luteEngine)
 	return
 	return
 }
 }
@@ -383,7 +383,7 @@ func GetHeadingLevelTransaction(id string, level int) (transaction *Transaction,
 	}
 	}
 
 
 	transaction = &Transaction{}
 	transaction = &Transaction{}
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	for _, c := range childrenHeadings {
 	for _, c := range childrenHeadings {
 		op := &Operation{}
 		op := &Operation{}
 		op.ID = c.ID
 		op.ID = c.ID

+ 3 - 1
kernel/model/box.go

@@ -38,6 +38,7 @@ import (
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/conf"
+	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/task"
 	"github.com/siyuan-note/siyuan/kernel/task"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
@@ -386,12 +387,13 @@ func (box *Box) renameSubTrees(tree *parse.Tree) {
 func (box *Box) moveTrees0(files []*FileInfo) {
 func (box *Box) moveTrees0(files []*FileInfo) {
 	totals := len(files) + 5
 	totals := len(files) + 5
 	showProgress := 64 < totals
 	showProgress := 64 < totals
+	luteEngine := util.NewLute()
 	for i, subFile := range files {
 	for i, subFile := range files {
 		if !strings.HasSuffix(subFile.path, ".sy") {
 		if !strings.HasSuffix(subFile.path, ".sy") {
 			continue
 			continue
 		}
 		}
 
 
-		subTree, err := LoadTree(box.ID, subFile.path) // LoadTree 会重新构造 HPath
+		subTree, err := filesys.LoadTree(box.ID, subFile.path, luteEngine) // LoadTree 会重新构造 HPath
 		if nil != err {
 		if nil != err {
 			continue
 			continue
 		}
 		}

+ 3 - 1
kernel/model/export_merge.go

@@ -19,6 +19,7 @@ package model
 import (
 import (
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
+	"github.com/siyuan-note/siyuan/kernel/filesys"
 )
 )
 
 
 func mergeSubDocs(rootTree *parse.Tree) (ret *parse.Tree, err error) {
 func mergeSubDocs(rootTree *parse.Tree) (ret *parse.Tree, err error) {
@@ -74,7 +75,8 @@ func walkBlock(insertPoint *ast.Node, block *Block, level int) (err error) {
 }
 }
 
 
 func loadTreeNodes(box string, p string, level int) (ret []*ast.Node, err error) {
 func loadTreeNodes(box string, p string, level int) (ret []*ast.Node, err error) {
-	tree, err := LoadTree(box, p)
+	luteEngine := NewLute()
+	tree, err := filesys.LoadTree(box, p, luteEngine)
 	if nil != err {
 	if nil != err {
 		return
 		return
 	}
 	}

+ 28 - 21
kernel/model/file.go

@@ -19,7 +19,6 @@ package model
 import (
 import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"github.com/siyuan-note/siyuan/kernel/task"
 	"math"
 	"math"
 	"os"
 	"os"
 	"path"
 	"path"
@@ -31,6 +30,7 @@ import (
 	"unicode/utf8"
 	"unicode/utf8"
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
+	"github.com/88250/lute"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
@@ -44,6 +44,7 @@ import (
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
+	"github.com/siyuan-note/siyuan/kernel/task"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -378,7 +379,7 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
 }
 }
 
 
 func ContentStat(content string) (ret *util.BlockStatResult) {
 func ContentStat(content string) (ret *util.BlockStatResult) {
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	tree := luteEngine.BlockDOM2Tree(content)
 	tree := luteEngine.BlockDOM2Tree(content)
 	runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat()
 	runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat()
 	return &util.BlockStatResult{
 	return &util.BlockStatResult{
@@ -393,6 +394,7 @@ func ContentStat(content string) (ret *util.BlockStatResult) {
 func BlocksWordCount(ids []string) (ret *util.BlockStatResult) {
 func BlocksWordCount(ids []string) (ret *util.BlockStatResult) {
 	ret = &util.BlockStatResult{}
 	ret = &util.BlockStatResult{}
 	trees := map[string]*parse.Tree{} // 缓存
 	trees := map[string]*parse.Tree{} // 缓存
+	luteEngine := util.NewLute()
 	for _, id := range ids {
 	for _, id := range ids {
 		bt := treenode.GetBlockTree(id)
 		bt := treenode.GetBlockTree(id)
 		if nil == bt {
 		if nil == bt {
@@ -402,7 +404,7 @@ func BlocksWordCount(ids []string) (ret *util.BlockStatResult) {
 
 
 		tree := trees[bt.RootID]
 		tree := trees[bt.RootID]
 		if nil == tree {
 		if nil == tree {
-			tree, _ = LoadTree(bt.BoxID, bt.Path)
+			tree, _ = filesys.LoadTree(bt.BoxID, bt.Path, luteEngine)
 			if nil == tree {
 			if nil == tree {
 				continue
 				continue
 			}
 			}
@@ -927,7 +929,7 @@ func CreateDocByMd(boxID, p, title, md string, sorts []string) (tree *parse.Tree
 		return
 		return
 	}
 	}
 
 
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	dom := luteEngine.Md2BlockDOM(md, false)
 	dom := luteEngine.Md2BlockDOM(md, false)
 	tree, err = createDoc(box.ID, p, title, dom)
 	tree, err = createDoc(box.ID, p, title, dom)
 	if nil != err {
 	if nil != err {
@@ -946,7 +948,7 @@ func CreateWithMarkdown(boxID, hPath, md string) (id string, err error) {
 	}
 	}
 
 
 	WaitForWritingFiles()
 	WaitForWritingFiles()
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	dom := luteEngine.Md2BlockDOM(md, false)
 	dom := luteEngine.Md2BlockDOM(md, false)
 	id, _, err = createDocsByHPath(box.ID, hPath, dom)
 	id, _, err = createDocsByHPath(box.ID, hPath, dom)
 	return
 	return
@@ -958,7 +960,8 @@ func GetHPathByPath(boxID, p string) (hPath string, err error) {
 		return
 		return
 	}
 	}
 
 
-	tree, err := LoadTree(boxID, p)
+	luteEngine := util.NewLute()
+	tree, err := filesys.LoadTree(boxID, p, luteEngine)
 	if nil != err {
 	if nil != err {
 		return
 		return
 	}
 	}
@@ -1038,8 +1041,9 @@ func MoveDocs(fromPaths []string, toBoxID, toPath string) (err error) {
 	}
 	}
 
 
 	WaitForWritingFiles()
 	WaitForWritingFiles()
+	luteEngine := util.NewLute()
 	for fromPath, fromBox := range pathsBoxes {
 	for fromPath, fromBox := range pathsBoxes {
-		_, err = moveDoc(fromBox, fromPath, toBox, toPath)
+		_, err = moveDoc(fromBox, fromPath, toBox, toPath, luteEngine)
 		if nil != err {
 		if nil != err {
 			return
 			return
 		}
 		}
@@ -1055,7 +1059,7 @@ func MoveDocs(fromPaths []string, toBoxID, toPath string) (err error) {
 	return
 	return
 }
 }
 
 
-func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string) (newPath string, err error) {
+func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string, luteEngine *lute.Lute) (newPath string, err error) {
 	isSameBox := fromBox.ID == toBox.ID
 	isSameBox := fromBox.ID == toBox.ID
 
 
 	if isSameBox {
 	if isSameBox {
@@ -1070,7 +1074,7 @@ func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string) (newPath
 		}
 		}
 	}
 	}
 
 
-	tree, err := LoadTree(fromBox.ID, fromPath)
+	tree, err := filesys.LoadTree(fromBox.ID, fromPath, luteEngine)
 	if nil != err {
 	if nil != err {
 		err = ErrBlockNotFound
 		err = ErrBlockNotFound
 		return
 		return
@@ -1083,9 +1087,9 @@ func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string) (newPath
 	if !moveToRoot {
 	if !moveToRoot {
 		var toTree *parse.Tree
 		var toTree *parse.Tree
 		if isSameBox {
 		if isSameBox {
-			toTree, err = LoadTree(fromBox.ID, toPath)
+			toTree, err = filesys.LoadTree(fromBox.ID, toPath, luteEngine)
 		} else {
 		} else {
-			toTree, err = LoadTree(toBox.ID, toPath)
+			toTree, err = filesys.LoadTree(toBox.ID, toPath, luteEngine)
 		}
 		}
 		if nil != err {
 		if nil != err {
 			err = ErrBlockNotFound
 			err = ErrBlockNotFound
@@ -1136,7 +1140,7 @@ func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string) (newPath
 			return
 			return
 		}
 		}
 
 
-		tree, err = LoadTree(fromBox.ID, newPath)
+		tree, err = filesys.LoadTree(fromBox.ID, newPath, luteEngine)
 		if nil != err {
 		if nil != err {
 			return
 			return
 		}
 		}
@@ -1152,7 +1156,7 @@ func moveDoc(fromBox *Box, fromPath string, toBox *Box, toPath string) (newPath
 			return
 			return
 		}
 		}
 
 
-		tree, err = LoadTree(toBox.ID, newPath)
+		tree, err = filesys.LoadTree(toBox.ID, newPath, luteEngine)
 		if nil != err {
 		if nil != err {
 			return
 			return
 		}
 		}
@@ -1180,7 +1184,8 @@ func RemoveDoc(boxID, p string) {
 	}
 	}
 
 
 	WaitForWritingFiles()
 	WaitForWritingFiles()
-	removeDoc(box, p)
+	luteEngine := util.NewLute()
+	removeDoc(box, p, luteEngine)
 	IncSync()
 	IncSync()
 	return
 	return
 }
 }
@@ -1192,14 +1197,15 @@ func RemoveDocs(paths []string) {
 	paths = util.FilterSelfChildDocs(paths)
 	paths = util.FilterSelfChildDocs(paths)
 	pathsBoxes := getBoxesByPaths(paths)
 	pathsBoxes := getBoxesByPaths(paths)
 	WaitForWritingFiles()
 	WaitForWritingFiles()
+	luteEngine := util.NewLute()
 	for p, box := range pathsBoxes {
 	for p, box := range pathsBoxes {
-		removeDoc(box, p)
+		removeDoc(box, p, luteEngine)
 	}
 	}
 	return
 	return
 }
 }
 
 
-func removeDoc(box *Box, p string) {
-	tree, _ := LoadTree(box.ID, p)
+func removeDoc(box *Box, p string, luteEngine *lute.Lute) {
+	tree, _ := filesys.LoadTree(box.ID, p, luteEngine)
 	if nil == tree {
 	if nil == tree {
 		return
 		return
 	}
 	}
@@ -1231,7 +1237,7 @@ func removeDoc(box *Box, p string) {
 			return
 			return
 		}
 		}
 	}
 	}
-	indexHistoryDir(filepath.Base(historyDir), NewLute())
+	indexHistoryDir(filepath.Base(historyDir), util.NewLute())
 
 
 	if existChildren {
 	if existChildren {
 		if err = box.Remove(childrenDir); nil != err {
 		if err = box.Remove(childrenDir); nil != err {
@@ -1274,7 +1280,8 @@ func RenameDoc(boxID, p, title string) (err error) {
 	}
 	}
 
 
 	WaitForWritingFiles()
 	WaitForWritingFiles()
-	tree, err := LoadTree(box.ID, p)
+	luteEngine := util.NewLute()
+	tree, err := filesys.LoadTree(box.ID, p, luteEngine)
 	if nil != err {
 	if nil != err {
 		return
 		return
 	}
 	}
@@ -1370,7 +1377,7 @@ func CreateDailyNote(boxID string) (p string, existed bool, err error) {
 		if nil == err {
 		if nil == err {
 			tree.Root.FirstChild.Unlink()
 			tree.Root.FirstChild.Unlink()
 
 
-			luteEngine := NewLute()
+			luteEngine := util.NewLute()
 			newTree := luteEngine.BlockDOM2Tree(dom)
 			newTree := luteEngine.BlockDOM2Tree(dom)
 			var children []*ast.Node
 			var children []*ast.Node
 			for c := newTree.Root.FirstChild; nil != c; c = c.Next {
 			for c := newTree.Root.FirstChild; nil != c; c = c.Next {
@@ -1450,7 +1457,7 @@ func createDoc(boxID, p, title, dom string) (tree *parse.Tree, err error) {
 		return
 		return
 	}
 	}
 
 
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	tree = luteEngine.BlockDOM2Tree(dom)
 	tree = luteEngine.BlockDOM2Tree(dom)
 	tree.Box = boxID
 	tree.Box = boxID
 	tree.Path = p
 	tree.Path = p

+ 1 - 1
kernel/model/format.go

@@ -105,5 +105,5 @@ func generateFormatHistory(tree *parse.Tree) {
 		return
 		return
 	}
 	}
 
 
-	indexHistoryDir(filepath.Base(historyDir), NewLute())
+	indexHistoryDir(filepath.Base(historyDir), util.NewLute())
 }
 }

+ 2 - 1
kernel/model/graph.go

@@ -18,6 +18,7 @@ package model
 
 
 import (
 import (
 	"bytes"
 	"bytes"
+	"github.com/siyuan-note/siyuan/kernel/util"
 	"math"
 	"math"
 	"strings"
 	"strings"
 	"unicode/utf8"
 	"unicode/utf8"
@@ -693,7 +694,7 @@ func query2Stmt(queryStr string) (ret string) {
 		buf.WriteString("id = '" + queryStr + "'")
 		buf.WriteString("id = '" + queryStr + "'")
 	} else {
 	} else {
 		var tags []string
 		var tags []string
-		luteEngine := NewLute()
+		luteEngine := util.NewLute()
 		t := parse.Inline("", []byte(queryStr), luteEngine.ParseOptions)
 		t := parse.Inline("", []byte(queryStr), luteEngine.ParseOptions)
 		ast.Walk(t.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
 		ast.Walk(t.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
 			if !entering {
 			if !entering {

+ 1 - 1
kernel/model/heading.go

@@ -290,7 +290,7 @@ func Heading2Doc(srcHeadingID, targetBoxID, targetPath string) (srcRootBlockID,
 	}
 	}
 	headingNode.RemoveIALAttr("fold")
 	headingNode.RemoveIALAttr("fold")
 
 
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	newTree := &parse.Tree{Root: &ast.Node{Type: ast.NodeDocument, ID: srcHeadingID}, Context: &parse.Context{ParseOption: luteEngine.ParseOptions}}
 	newTree := &parse.Tree{Root: &ast.Node{Type: ast.NodeDocument, ID: srcHeadingID}, Context: &parse.Context{ParseOption: luteEngine.ParseOptions}}
 	children = treenode.HeadingChildren(headingNode)
 	children = treenode.HeadingChildren(headingNode)
 	for _, c := range children {
 	for _, c := range children {

+ 2 - 2
kernel/model/history.go

@@ -482,7 +482,7 @@ func (box *Box) generateDocHistory0() {
 		}
 		}
 	}
 	}
 
 
-	indexHistoryDir(filepath.Base(historyDir), NewLute())
+	indexHistoryDir(filepath.Base(historyDir), util.NewLute())
 	return
 	return
 }
 }
 
 
@@ -593,7 +593,7 @@ func ReindexHistory() (err error) {
 	defer util.PushClearProgress()
 	defer util.PushClearProgress()
 
 
 	sql.InitHistoryDatabase(true)
 	sql.InitHistoryDatabase(true)
-	lutEngine := NewLute()
+	lutEngine := util.NewLute()
 	for _, historyDir := range historyDirs {
 	for _, historyDir := range historyDirs {
 		if !historyDir.IsDir() {
 		if !historyDir.IsDir() {
 			continue
 			continue

+ 2 - 2
kernel/model/import.go

@@ -53,7 +53,7 @@ import (
 
 
 func HTML2Markdown(htmlStr string) (markdown string, err error) {
 func HTML2Markdown(htmlStr string) (markdown string, err error) {
 	assetDirPath := filepath.Join(util.DataDir, "assets")
 	assetDirPath := filepath.Join(util.DataDir, "assets")
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	luteEngine.SetProtyleWYSIWYG(false)
 	luteEngine.SetProtyleWYSIWYG(false)
 	tree := luteEngine.HTML2Tree(htmlStr)
 	tree := luteEngine.HTML2Tree(htmlStr)
 	ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
 	ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
@@ -387,7 +387,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 		absPath := filepath.Join(targetDir, treePath)
 		absPath := filepath.Join(targetDir, treePath)
 		p := strings.TrimPrefix(absPath, boxAbsPath)
 		p := strings.TrimPrefix(absPath, boxAbsPath)
 		p = filepath.ToSlash(p)
 		p = filepath.ToSlash(p)
-		tree, err := LoadTree(boxID, p)
+		tree, err := filesys.LoadTree(boxID, p, luteEngine)
 		if nil != err {
 		if nil != err {
 			logging.LogErrorf("load tree [%s] failed: %s", treePath, err)
 			logging.LogErrorf("load tree [%s] failed: %s", treePath, err)
 			continue
 			continue

+ 56 - 33
kernel/model/index.go

@@ -17,18 +17,22 @@
 package model
 package model
 
 
 import (
 import (
+	"bytes"
 	"fmt"
 	"fmt"
+	"path/filepath"
 	"runtime"
 	"runtime"
 	"runtime/debug"
 	"runtime/debug"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"github.com/88250/gulu"
+	"github.com/88250/lute/ast"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
-	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/panjf2000/ants/v2"
 	"github.com/panjf2000/ants/v2"
 	"github.com/siyuan-note/eventbus"
 	"github.com/siyuan-note/eventbus"
+	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
@@ -68,7 +72,7 @@ func index(boxID string) {
 	bootProgressPart := 30.0 / float64(boxLen) / float64(len(files))
 	bootProgressPart := 30.0 / float64(boxLen) / float64(len(files))
 
 
 	start := time.Now()
 	start := time.Now()
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	var treeCount int
 	var treeCount int
 	var treeSize int64
 	var treeSize int64
 	i := 0
 	i := 0
@@ -135,53 +139,72 @@ func IndexRefs() {
 	util.SetBootDetails("Resolving refs...")
 	util.SetBootDetails("Resolving refs...")
 	util.PushStatusBar(Conf.Language(54))
 	util.PushStatusBar(Conf.Language(54))
 
 
-	// 引用入库
 	util.SetBootDetails("Indexing refs...")
 	util.SetBootDetails("Indexing refs...")
-	refBlocks := sql.GetRefExistedBlocks()
-	refTreeIDs := hashset.New()
-	for _, refBlock := range refBlocks {
-		refTreeIDs.Add(refBlock.RootID)
-	}
 
 
-	i := 0
-	if 0 < refTreeIDs.Size() {
-		luteEngine := NewLute()
-		bootProgressPart := 10.0 / float64(refTreeIDs.Size())
-		for _, box := range Conf.GetOpenedBoxes() {
-			sql.DeleteBoxRefsQueue(box.ID)
-
-			files := box.ListFiles("/")
-			for _, file := range files {
-				if file.isdir || !strings.HasSuffix(file.name, ".sy") {
+	var defBlockIDs []string
+	luteEngine := util.NewLute()
+	boxes := Conf.GetOpenedBoxes()
+	for _, box := range boxes {
+		sql.DeleteBoxRefsQueue(box.ID)
+
+		pages := pagedPaths(filepath.Join(util.DataDir, box.ID), 32)
+		for _, paths := range pages {
+			for _, treeAbsPath := range paths {
+				data, readErr := filelock.ReadFile(treeAbsPath)
+				if nil != readErr {
+					logging.LogWarnf("get data [path=%s] failed: %s", treeAbsPath, readErr)
 					continue
 					continue
 				}
 				}
 
 
-				if file.isdir || !strings.HasSuffix(file.name, ".sy") {
+				if !bytes.Contains(data, []byte("TextMarkBlockRefID")) && !bytes.Contains(data, []byte("TextMarkFileAnnotationRefID")) {
 					continue
 					continue
 				}
 				}
 
 
-				id := strings.TrimSuffix(file.name, ".sy")
-				if !refTreeIDs.Contains(id) {
+				p := filepath.ToSlash(strings.TrimPrefix(treeAbsPath, filepath.Join(util.DataDir, box.ID)))
+				tree, parseErr := filesys.LoadTreeByData(data, box.ID, p, luteEngine)
+				if nil != parseErr {
+					logging.LogWarnf("parse json to tree [%s] failed: %s", treeAbsPath, parseErr)
 					continue
 					continue
 				}
 				}
 
 
-				util.IncBootProgress(bootProgressPart, "Indexing ref "+util.ShortPathForBootingDisplay(file.path))
+				ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
+					if !entering {
+						return ast.WalkContinue
+					}
+
+					if n.IsTextMarkType("block-ref") {
+						defBlockIDs = append(defBlockIDs, n.TextMarkBlockRefID)
+					} else if n.IsTextMarkType("file-annotation-ref") {
+						defBlockIDs = append(defBlockIDs, n.TextMarkFileAnnotationRefID)
+					}
+					return ast.WalkContinue
+				})
+			}
+		}
+	}
 
 
-				tree, err := filesys.LoadTree(box.ID, file.path, luteEngine)
-				if nil != err {
-					logging.LogErrorf("parse box [%s] tree [%s] failed", box.ID, file.path)
-					continue
-				}
+	defBlockIDs = gulu.Str.RemoveDuplicatedElem(defBlockIDs)
 
 
-				sql.InsertRefsTreeQueue(tree)
-				if 1 < i && 0 == i%64 {
-					util.PushStatusBar(fmt.Sprintf(Conf.Language(55), i))
-				}
-				i++
+	i := 0
+	size := len(defBlockIDs)
+	if 0 < size {
+		bootProgressPart := 10.0 / float64(size)
+
+		for _, defBlockID := range defBlockIDs {
+			defTree, loadErr := LoadTreeByID(defBlockID)
+			if nil != loadErr {
+				continue
+			}
+
+			util.IncBootProgress(bootProgressPart, "Indexing ref "+defTree.ID)
+			sql.InsertRefsTreeQueue(defTree)
+			if 1 < i && 0 == i%64 {
+				util.PushStatusBar(fmt.Sprintf(Conf.Language(55), i))
 			}
 			}
+			i++
 		}
 		}
 	}
 	}
-	logging.LogInfof("resolved refs [%d] in [%dms]", len(refBlocks), time.Now().Sub(start).Milliseconds())
+	logging.LogInfof("resolved refs [%d] in [%dms]", size, time.Now().Sub(start).Milliseconds())
 	util.PushStatusBar(fmt.Sprintf(Conf.Language(55), i))
 	util.PushStatusBar(fmt.Sprintf(Conf.Language(55), i))
 }
 }
 
 

+ 12 - 8
kernel/model/index_fix.go

@@ -27,10 +27,12 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
+	"github.com/88250/lute"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/logging"
+	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/task"
 	"github.com/siyuan-note/siyuan/kernel/task"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
@@ -107,6 +109,7 @@ func fixBlockTreeByFileSys() {
 
 
 	util.PushStatusBar(Conf.Language(58))
 	util.PushStatusBar(Conf.Language(58))
 	boxes := Conf.GetOpenedBoxes()
 	boxes := Conf.GetOpenedBoxes()
+	luteEngine := lute.New()
 	for _, box := range boxes {
 	for _, box := range boxes {
 		boxPath := filepath.Join(util.DataDir, box.ID)
 		boxPath := filepath.Join(util.DataDir, box.ID)
 		var paths []string
 		var paths []string
@@ -133,7 +136,7 @@ func fixBlockTreeByFileSys() {
 				continue
 				continue
 			}
 			}
 
 
-			reindexTreeByPath(box.ID, p, i, size)
+			reindexTreeByPath(box.ID, p, i, size, luteEngine)
 			if util.IsExiting {
 			if util.IsExiting {
 				break
 				break
 			}
 			}
@@ -166,6 +169,7 @@ func fixDatabaseIndexByBlockTree() {
 func reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap map[string]string) {
 func reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap map[string]string) {
 	i := -1
 	i := -1
 	size := len(rootUpdatedMap)
 	size := len(rootUpdatedMap)
+	luteEngine := util.NewLute()
 	for rootID, updated := range rootUpdatedMap {
 	for rootID, updated := range rootUpdatedMap {
 		i++
 		i++
 
 
@@ -176,13 +180,13 @@ func reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap map[string]string) {
 		rootUpdated := dbRootUpdatedMap[rootID]
 		rootUpdated := dbRootUpdatedMap[rootID]
 		if "" == rootUpdated {
 		if "" == rootUpdated {
 			//logging.LogWarnf("not found tree [%s] in database, reindex it", rootID)
 			//logging.LogWarnf("not found tree [%s] in database, reindex it", rootID)
-			reindexTree(rootID, i, size)
+			reindexTree(rootID, i, size, luteEngine)
 			continue
 			continue
 		}
 		}
 
 
 		if "" == updated {
 		if "" == updated {
 			// BlockTree 迁移,v2.6.3 之前没有 updated 字段
 			// BlockTree 迁移,v2.6.3 之前没有 updated 字段
-			reindexTree(rootID, i, size)
+			reindexTree(rootID, i, size, luteEngine)
 			continue
 			continue
 		}
 		}
 
 
@@ -190,7 +194,7 @@ func reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap map[string]string) {
 		dbUpdated, _ := time.Parse("20060102150405", rootUpdated)
 		dbUpdated, _ := time.Parse("20060102150405", rootUpdated)
 		if dbUpdated.Before(btUpdated.Add(-10 * time.Minute)) {
 		if dbUpdated.Before(btUpdated.Add(-10 * time.Minute)) {
 			logging.LogWarnf("tree [%s] is not up to date, reindex it", rootID)
 			logging.LogWarnf("tree [%s] is not up to date, reindex it", rootID)
-			reindexTree(rootID, i, size)
+			reindexTree(rootID, i, size, luteEngine)
 			continue
 			continue
 		}
 		}
 
 
@@ -231,8 +235,8 @@ func reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap map[string]string) {
 	sql.BatchRemoveTreeQueue(toRemoveRootIDs)
 	sql.BatchRemoveTreeQueue(toRemoveRootIDs)
 }
 }
 
 
-func reindexTreeByPath(box, p string, i, size int) {
-	tree, err := LoadTree(box, p)
+func reindexTreeByPath(box, p string, i, size int, luteEngine *lute.Lute) {
+	tree, err := filesys.LoadTree(box, p, luteEngine)
 	if nil != err {
 	if nil != err {
 		return
 		return
 	}
 	}
@@ -240,14 +244,14 @@ func reindexTreeByPath(box, p string, i, size int) {
 	reindexTree0(tree, i, size)
 	reindexTree0(tree, i, size)
 }
 }
 
 
-func reindexTree(rootID string, i, size int) {
+func reindexTree(rootID string, i, size int, luteEngine *lute.Lute) {
 	root := treenode.GetBlockTree(rootID)
 	root := treenode.GetBlockTree(rootID)
 	if nil == root {
 	if nil == root {
 		logging.LogWarnf("root block [%s] not found", rootID)
 		logging.LogWarnf("root block [%s] not found", rootID)
 		return
 		return
 	}
 	}
 
 
-	tree, err := LoadTree(root.BoxID, root.Path)
+	tree, err := filesys.LoadTree(root.BoxID, root.Path, luteEngine)
 	if nil != err {
 	if nil != err {
 		if os.IsNotExist(err) {
 		if os.IsNotExist(err) {
 			// 文件系统上没有找到该 .sy 文件,则订正块树
 			// 文件系统上没有找到该 .sy 文件,则订正块树

+ 1 - 1
kernel/model/listitem.go

@@ -76,7 +76,7 @@ func ListItem2Doc(srcListItemID, targetBoxID, targetPath string) (srcRootBlockID
 		children = append(children, newNode)
 		children = append(children, newNode)
 	}
 	}
 
 
-	luteEngine := NewLute()
+	luteEngine := util.NewLute()
 	newTree := &parse.Tree{Root: &ast.Node{Type: ast.NodeDocument, ID: srcListItemID}, Context: &parse.Context{ParseOption: luteEngine.ParseOptions}}
 	newTree := &parse.Tree{Root: &ast.Node{Type: ast.NodeDocument, ID: srcListItemID}, Context: &parse.Context{ParseOption: luteEngine.ParseOptions}}
 	for _, c := range children {
 	for _, c := range children {
 		newTree.Root.AppendChild(c)
 		newTree.Root.AppendChild(c)

+ 1 - 1
kernel/model/repository.go

@@ -1075,7 +1075,7 @@ func processSyncMergeResult(exit, byHand bool, start time.Time, mergeResult *dej
 		// 云端同步发生冲突时生成副本 https://github.com/siyuan-note/siyuan/issues/5687
 		// 云端同步发生冲突时生成副本 https://github.com/siyuan-note/siyuan/issues/5687
 
 
 		historyDir := filepath.Join(util.HistoryDir, mergeResult.Time.Format("2006-01-02-150405")+"-sync")
 		historyDir := filepath.Join(util.HistoryDir, mergeResult.Time.Format("2006-01-02-150405")+"-sync")
-		luteEngine := NewLute()
+		luteEngine := util.NewLute()
 		for _, file := range mergeResult.Conflicts {
 		for _, file := range mergeResult.Conflicts {
 			if !strings.HasSuffix(file.Path, ".sy") {
 			if !strings.HasSuffix(file.Path, ".sy") {
 				continue
 				continue

+ 3 - 1
kernel/model/sync.go

@@ -32,6 +32,7 @@ import (
 	"github.com/siyuan-note/dejavu/cloud"
 	"github.com/siyuan-note/dejavu/cloud"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/conf"
+	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -267,6 +268,7 @@ func incReindex(upserts, removes []string) {
 	msg := fmt.Sprintf(Conf.Language(35))
 	msg := fmt.Sprintf(Conf.Language(35))
 	util.PushStatusBar(msg)
 	util.PushStatusBar(msg)
 
 
+	luteEngine := util.NewLute()
 	// 先执行 remove,否则移动文档时 upsert 会被忽略,导致未被索引
 	// 先执行 remove,否则移动文档时 upsert 会被忽略,导致未被索引
 	bootProgressPart := 10 / float64(len(removes))
 	bootProgressPart := 10 / float64(len(removes))
 	for _, removeFile := range removes {
 	for _, removeFile := range removes {
@@ -311,7 +313,7 @@ func incReindex(upserts, removes []string) {
 		util.IncBootProgress(bootProgressPart, msg)
 		util.IncBootProgress(bootProgressPart, msg)
 		util.PushStatusBar(msg)
 		util.PushStatusBar(msg)
 
 
-		tree, err0 := LoadTree(box, p)
+		tree, err0 := filesys.LoadTree(box, p, luteEngine)
 		if nil != err0 {
 		if nil != err0 {
 			continue
 			continue
 		}
 		}

+ 10 - 9
kernel/model/transaction.go

@@ -26,6 +26,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
+	"github.com/88250/lute"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/editor"
 	"github.com/88250/lute/editor"
 	"github.com/88250/lute/lex"
 	"github.com/88250/lute/lex"
@@ -34,6 +35,7 @@ import (
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
+	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -419,8 +421,7 @@ func (tx *Transaction) doPrependInsert(operation *Operation) (ret *TxErr) {
 	}
 	}
 
 
 	data := strings.ReplaceAll(operation.Data.(string), editor.FrontEndCaret, "")
 	data := strings.ReplaceAll(operation.Data.(string), editor.FrontEndCaret, "")
-	luteEngine := NewLute()
-	subTree := luteEngine.BlockDOM2Tree(data)
+	subTree := tx.luteEngine.BlockDOM2Tree(data)
 	insertedNode := subTree.Root.FirstChild
 	insertedNode := subTree.Root.FirstChild
 	if nil == insertedNode {
 	if nil == insertedNode {
 		return &TxErr{code: TxErrCodeBlockNotFound, msg: "invalid data tree", id: block.ID}
 		return &TxErr{code: TxErrCodeBlockNotFound, msg: "invalid data tree", id: block.ID}
@@ -507,8 +508,7 @@ func (tx *Transaction) doAppendInsert(operation *Operation) (ret *TxErr) {
 	}
 	}
 
 
 	data := strings.ReplaceAll(operation.Data.(string), editor.FrontEndCaret, "")
 	data := strings.ReplaceAll(operation.Data.(string), editor.FrontEndCaret, "")
-	luteEngine := NewLute()
-	subTree := luteEngine.BlockDOM2Tree(data)
+	subTree := tx.luteEngine.BlockDOM2Tree(data)
 	insertedNode := subTree.Root.FirstChild
 	insertedNode := subTree.Root.FirstChild
 	if nil == insertedNode {
 	if nil == insertedNode {
 		return &TxErr{code: TxErrCodeBlockNotFound, msg: "invalid data tree", id: block.ID}
 		return &TxErr{code: TxErrCodeBlockNotFound, msg: "invalid data tree", id: block.ID}
@@ -720,8 +720,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
 	}
 	}
 
 
 	data := strings.ReplaceAll(operation.Data.(string), editor.FrontEndCaret, "")
 	data := strings.ReplaceAll(operation.Data.(string), editor.FrontEndCaret, "")
-	luteEngine := NewLute()
-	subTree := luteEngine.BlockDOM2Tree(data)
+	subTree := tx.luteEngine.BlockDOM2Tree(data)
 
 
 	p := block.Path
 	p := block.Path
 	assets := getAssetsDir(filepath.Join(util.DataDir, block.BoxID), filepath.Dir(filepath.Join(util.DataDir, block.BoxID, p)))
 	assets := getAssetsDir(filepath.Join(util.DataDir, block.BoxID), filepath.Dir(filepath.Join(util.DataDir, block.BoxID, p)))
@@ -870,8 +869,7 @@ func (tx *Transaction) doUpdate(operation *Operation) (ret *TxErr) {
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
-	luteEngine := NewLute()
-	subTree := luteEngine.BlockDOM2Tree(data)
+	subTree := tx.luteEngine.BlockDOM2Tree(data)
 	subTree.ID, subTree.Box, subTree.Path = tree.ID, tree.Box, tree.Path
 	subTree.ID, subTree.Box, subTree.Path = tree.ID, tree.Box, tree.Path
 	oldNode := treenode.GetNodeInTree(tree, id)
 	oldNode := treenode.GetNodeInTree(tree, id)
 	if nil == oldNode {
 	if nil == oldNode {
@@ -1034,6 +1032,8 @@ type Transaction struct {
 
 
 	trees map[string]*parse.Tree
 	trees map[string]*parse.Tree
 	nodes map[string]*ast.Node
 	nodes map[string]*ast.Node
+
+	luteEngine *lute.Lute
 }
 }
 
 
 func (tx *Transaction) begin() (err error) {
 func (tx *Transaction) begin() (err error) {
@@ -1042,6 +1042,7 @@ func (tx *Transaction) begin() (err error) {
 	}
 	}
 	tx.trees = map[string]*parse.Tree{}
 	tx.trees = map[string]*parse.Tree{}
 	tx.nodes = map[string]*ast.Node{}
 	tx.nodes = map[string]*ast.Node{}
+	tx.luteEngine = util.NewLute()
 	return
 	return
 }
 }
 
 
@@ -1077,7 +1078,7 @@ func (tx *Transaction) loadTree(id string) (ret *parse.Tree, err error) {
 		return
 		return
 	}
 	}
 
 
-	ret, err = LoadTree(box, p)
+	ret, err = filesys.LoadTree(box, p, tx.luteEngine)
 	if nil != err {
 	if nil != err {
 		return
 		return
 	}
 	}

+ 3 - 14
kernel/model/tree.go

@@ -164,19 +164,8 @@ func loadTreeByBlockID(id string) (ret *parse.Tree, err error) {
 
 
 		return nil, ErrBlockNotFound
 		return nil, ErrBlockNotFound
 	}
 	}
-	ret, err = LoadTree(bt.BoxID, bt.Path)
-	if nil != err {
-		return
-	}
-	return
-}
 
 
-func LoadTree(boxID, p string) (*parse.Tree, error) {
-	luteEngine := NewLute()
-	tree, err := filesys.LoadTree(boxID, p, luteEngine)
-	if nil != err {
-		logging.LogErrorf("load tree [%s] failed: %s", boxID+p, err)
-		return nil, err
-	}
-	return tree, nil
+	luteEngine := util.NewLute()
+	ret, err = filesys.LoadTree(bt.BoxID, bt.Path, luteEngine)
+	return
 }
 }

+ 0 - 16
kernel/sql/block_query.go

@@ -555,22 +555,6 @@ func GetAllChildBlocks(rootID, condition string) (ret []*Block) {
 	return
 	return
 }
 }
 
 
-func GetRefExistedBlocks() (ret []*Block) {
-	stmt := "SELECT * FROM blocks WHERE markdown LIKE ? OR markdown LIKE ?"
-	rows, err := query(stmt, "%((20%", "%<<20%")
-	if nil != err {
-		logging.LogErrorf("sql query [%s] failed: %s", stmt, err)
-		return
-	}
-	defer rows.Close()
-	for rows.Next() {
-		if block := scanBlockRows(rows); nil != block {
-			ret = append(ret, block)
-		}
-	}
-	return
-}
-
 func GetBlock(id string) (ret *Block) {
 func GetBlock(id string) (ret *Block) {
 	ret = getBlockCache(id)
 	ret = getBlockCache(id)
 	if nil != ret {
 	if nil != ret {