Jelajahi Sumber

:art: Supports replacing text elements with other elements https://github.com/siyuan-note/siyuan/issues/11058

Daniel 1 tahun lalu
induk
melakukan
d1647f9222
1 mengubah file dengan 53 tambahan dan 1 penghapusan
  1. 53 1
      kernel/model/search.go

+ 53 - 1
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)) {