From d1647f9222618ffd76fc2bcade6222c7f470bfef Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sat, 20 Apr 2024 10:02:44 +0800 Subject: [PATCH] :art: Supports replacing text elements with other elements https://github.com/siyuan-note/siyuan/issues/11058 --- kernel/model/search.go | 54 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/kernel/model/search.go b/kernel/model/search.go index 1b812d998..f1849adbe 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -534,6 +534,8 @@ func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids } } } else { + luteEngine := util.NewLute() + var unlinks []*ast.Node ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus { if !entering { return ast.WalkContinue @@ -545,7 +547,9 @@ func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids return ast.WalkContinue } - replaceNodeTokens(n, method, keyword, replacement, r) + if replaceTextNode(n, method, keyword, replacement, r, luteEngine) { + unlinks = append(unlinks, n) + } case ast.NodeLinkDest: if !replaceTypes["imgSrc"] { return ast.WalkContinue @@ -728,6 +732,10 @@ func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids return ast.WalkContinue }) + for _, unlink := range unlinks { + unlink.Unlink() + } + if err = writeTreeUpsertQueue(tree); nil != err { return } @@ -765,6 +773,50 @@ func replaceNodeTextMarkTextContent(n *ast.Node, method int, keyword string, rep } } +// replaceTextNode 替换文本节点为其他节点。 +// Supports replacing text elements with other elements https://github.com/siyuan-note/siyuan/issues/11058 +func replaceTextNode(text *ast.Node, method int, keyword string, replacement string, r *regexp.Regexp, luteEngine *lute.Lute) bool { + if 0 == method { + if bytes.Contains(text.Tokens, []byte(keyword)) { + newContent := bytes.ReplaceAll(text.Tokens, []byte(keyword), []byte(replacement)) + tree := parse.Inline("", newContent, luteEngine.ParseOptions) + if nil == tree.Root.FirstChild { + return false + } + parse.NestedInlines2FlattedSpans(tree, false) + + var replaceNodes []*ast.Node + for rNode := tree.Root.FirstChild.FirstChild; nil != rNode; rNode = rNode.Next { + replaceNodes = append(replaceNodes, rNode) + } + + for _, rNode := range replaceNodes { + text.InsertBefore(rNode) + } + return true + } + } else if 3 == method { + if nil != r && r.MatchString(string(text.Tokens)) { + newContent := bytes.ReplaceAll(text.Tokens, []byte(keyword), []byte(replacement)) + tree := parse.Inline("", newContent, luteEngine.ParseOptions) + if nil == tree.Root.FirstChild { + return false + } + + var replaceNodes []*ast.Node + for rNode := tree.Root.FirstChild; nil != rNode; rNode = rNode.Next { + replaceNodes = append(replaceNodes, rNode) + } + + for _, rNode := range replaceNodes { + text.InsertBefore(rNode) + } + return true + } + } + return false +} + func replaceNodeTokens(n *ast.Node, method int, keyword string, replacement string, r *regexp.Regexp) { if 0 == method { if bytes.Contains(n.Tokens, []byte(keyword)) {