浏览代码

:art: Find replace supports selecting element types https://github.com/siyuan-note/siyuan/issues/9895

Daniel 1 年之前
父节点
当前提交
23a24b28e6
共有 3 个文件被更改,包括 196 次插入47 次删除
  1. 12 1
      kernel/api/search.go
  2. 178 41
      kernel/model/search.go
  3. 6 5
      kernel/treenode/node.go

+ 12 - 1
kernel/api/search.go

@@ -81,7 +81,18 @@ func findReplace(c *gin.Context) {
 	for _, id := range idsArg {
 	for _, id := range idsArg {
 		ids = append(ids, id.(string))
 		ids = append(ids, id.(string))
 	}
 	}
-	err := model.FindReplace(k, r, ids, paths, boxes, types, method, orderBy, groupBy)
+
+	replaceTypes := map[string]bool{}
+	// text, img-text, img-title, img-src, a-text, a-title, a-href, code, em, strong, inline-math, inline-memo, kbd, mark, s, sub, sup, tag, u
+	// doc-title, code-block, math-block, html-block
+	if nil != arg["replaceTypes"] {
+		replaceTypesArg := arg["replaceTypes"].(map[string]interface{})
+		for t, b := range replaceTypesArg {
+			replaceTypes[t] = b.(bool)
+		}
+	}
+
+	err := model.FindReplace(k, r, replaceTypes, ids, paths, boxes, types, method, orderBy, groupBy)
 	if nil != err {
 	if nil != err {
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()

+ 178 - 41
kernel/model/search.go

@@ -265,7 +265,7 @@ func prependNotebookNameInHPath(blocks []*Block) {
 	}
 	}
 }
 }
 
 
-func FindReplace(keyword, replacement string, ids []string, paths, boxes []string, types map[string]bool, method, orderBy, groupBy int) (err error) {
+func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids []string, paths, boxes []string, types map[string]bool, method, orderBy, groupBy int) (err error) {
 	// method:0:文本,1:查询语法,2:SQL,3:正则表达式
 	// method:0:文本,1:查询语法,2:SQL,3:正则表达式
 	if 1 == method || 2 == method {
 	if 1 == method || 2 == method {
 		err = errors.New(Conf.Language(132))
 		err = errors.New(Conf.Language(132))
@@ -353,6 +353,10 @@ func FindReplace(keyword, replacement string, ids []string, paths, boxes []strin
 		}
 		}
 
 
 		if ast.NodeDocument == node.Type {
 		if ast.NodeDocument == node.Type {
+			if !replaceTypes["doc-title"] {
+				continue
+			}
+
 			title := node.IALAttr("title")
 			title := node.IALAttr("title")
 			if 0 == method {
 			if 0 == method {
 				if strings.Contains(title, keyword) {
 				if strings.Contains(title, keyword) {
@@ -372,18 +376,54 @@ func FindReplace(keyword, replacement string, ids []string, paths, boxes []strin
 				}
 				}
 
 
 				switch n.Type {
 				switch n.Type {
-				case ast.NodeText, ast.NodeLinkDest, ast.NodeLinkText, ast.NodeLinkTitle, ast.NodeCodeBlockCode, ast.NodeMathBlockContent, ast.NodeHTMLBlock:
-					if 0 == method {
-						if bytes.Contains(n.Tokens, []byte(keyword)) {
-							n.Tokens = bytes.ReplaceAll(n.Tokens, []byte(keyword), []byte(replacement))
-						}
-					} else if 3 == method {
-						if nil != r && r.MatchString(string(n.Tokens)) {
-							n.Tokens = []byte(r.ReplaceAllString(string(n.Tokens), replacement))
-						}
+				case ast.NodeText:
+					if !replaceTypes["text"] {
+						return ast.WalkContinue
+					}
+
+					replaceNodeTokens(n, method, keyword, replacement, r)
+				case ast.NodeLinkDest:
+					if !replaceTypes["img-src"] {
+						return ast.WalkContinue
+					}
+
+					replaceNodeTokens(n, method, keyword, replacement, r)
+				case ast.NodeLinkText:
+					if !replaceTypes["img-text"] {
+						return ast.WalkContinue
+					}
+
+					replaceNodeTokens(n, method, keyword, replacement, r)
+				case ast.NodeLinkTitle:
+					if !replaceTypes["img-title"] {
+						return ast.WalkContinue
+					}
+
+					replaceNodeTokens(n, method, keyword, replacement, r)
+				case ast.NodeCodeBlockCode:
+					if !replaceTypes["code-block"] {
+						return ast.WalkContinue
+					}
+
+					replaceNodeTokens(n, method, keyword, replacement, r)
+				case ast.NodeMathBlockContent:
+					if !replaceTypes["math-block"] {
+						return ast.WalkContinue
 					}
 					}
+
+					replaceNodeTokens(n, method, keyword, replacement, r)
+				case ast.NodeHTMLBlock:
+					if !replaceTypes["html-block"] {
+						return ast.WalkContinue
+					}
+
+					replaceNodeTokens(n, method, keyword, replacement, r)
 				case ast.NodeTextMark:
 				case ast.NodeTextMark:
 					if n.IsTextMarkType("code") {
 					if n.IsTextMarkType("code") {
+						if !replaceTypes["code"] {
+							return ast.WalkContinue
+						}
+
 						if 0 == method {
 						if 0 == method {
 							if strings.Contains(n.TextMarkTextContent, escapedKey) {
 							if strings.Contains(n.TextMarkTextContent, escapedKey) {
 								n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, escapedKey, replacement)
 								n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, escapedKey, replacement)
@@ -393,50 +433,123 @@ func FindReplace(keyword, replacement string, ids []string, paths, boxes []strin
 								n.TextMarkTextContent = escapedR.ReplaceAllString(n.TextMarkTextContent, replacement)
 								n.TextMarkTextContent = escapedR.ReplaceAllString(n.TextMarkTextContent, replacement)
 							}
 							}
 						}
 						}
-					} else {
-						if 0 == method {
-							if bytes.Contains(n.Tokens, []byte(keyword)) {
-								n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, keyword, replacement)
+					} else if n.IsTextMarkType("a") {
+						if replaceTypes["a-text"] {
+							if 0 == method {
+								if bytes.Contains(n.Tokens, []byte(keyword)) {
+									n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, keyword, replacement)
+								}
+							} else if 3 == method {
+								if nil != r && r.MatchString(n.TextMarkTextContent) {
+									n.TextMarkTextContent = r.ReplaceAllString(n.TextMarkTextContent, replacement)
+								}
 							}
 							}
-						} else if 3 == method {
-							if nil != r && r.MatchString(n.TextMarkTextContent) {
-								n.TextMarkTextContent = r.ReplaceAllString(n.TextMarkTextContent, replacement)
+						}
+
+						if replaceTypes["a-title"] {
+							if 0 == method {
+								if strings.Contains(n.TextMarkATitle, keyword) {
+									n.TextMarkATitle = strings.ReplaceAll(n.TextMarkATitle, keyword, replacement)
+								}
+							} else if 3 == method {
+								if nil != r && r.MatchString(n.TextMarkATitle) {
+									n.TextMarkATitle = r.ReplaceAllString(n.TextMarkATitle, replacement)
+								}
 							}
 							}
 						}
 						}
-					}
 
 
-					if 0 == method {
-						if strings.Contains(n.TextMarkTextContent, keyword) {
-							n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, keyword, replacement)
+						if replaceTypes["a-href"] {
+							if 0 == method {
+								if strings.Contains(n.TextMarkAHref, keyword) {
+									n.TextMarkAHref = strings.ReplaceAll(n.TextMarkAHref, keyword, replacement)
+								}
+							} else if 3 == method {
+								if nil != r && r.MatchString(n.TextMarkAHref) {
+									n.TextMarkAHref = r.ReplaceAllString(n.TextMarkAHref, replacement)
+								}
+							}
+						}
+
+					} else if n.IsTextMarkType("em") {
+						if !replaceTypes["em"] {
+							return ast.WalkContinue
+						}
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("strong") {
+						if !replaceTypes["strong"] {
+							return ast.WalkContinue
+						}
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("kbd") {
+						if !replaceTypes["kbd"] {
+							return ast.WalkContinue
 						}
 						}
-						if strings.Contains(n.TextMarkInlineMathContent, keyword) {
-							n.TextMarkInlineMathContent = strings.ReplaceAll(n.TextMarkInlineMathContent, keyword, replacement)
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("mark") {
+						if !replaceTypes["mark"] {
+							return ast.WalkContinue
 						}
 						}
-						if strings.Contains(n.TextMarkInlineMemoContent, keyword) {
-							n.TextMarkInlineMemoContent = strings.ReplaceAll(n.TextMarkInlineMemoContent, keyword, replacement)
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("s") {
+						if !replaceTypes["s"] {
+							return ast.WalkContinue
 						}
 						}
-						if strings.Contains(n.TextMarkATitle, keyword) {
-							n.TextMarkATitle = strings.ReplaceAll(n.TextMarkATitle, keyword, replacement)
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("sub") {
+						if !replaceTypes["sub"] {
+							return ast.WalkContinue
 						}
 						}
-						if strings.Contains(n.TextMarkAHref, keyword) {
-							n.TextMarkAHref = strings.ReplaceAll(n.TextMarkAHref, keyword, replacement)
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("sup") {
+						if !replaceTypes["sup"] {
+							return ast.WalkContinue
 						}
 						}
-					} else if 3 == method {
-						if nil != r {
-							if r.MatchString(n.TextMarkTextContent) {
-								n.TextMarkTextContent = r.ReplaceAllString(n.TextMarkTextContent, replacement)
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("tag") {
+						if !replaceTypes["tag"] {
+							return ast.WalkContinue
+						}
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("u") {
+						if !replaceTypes["u"] {
+							return ast.WalkContinue
+						}
+
+						replaceNodeTextMarkTextContent(n, method, keyword, replacement, r)
+					} else if n.IsTextMarkType("inline-math") {
+						if !replaceTypes["inline-math"] {
+							return ast.WalkContinue
+						}
+
+						if 0 == method {
+							if strings.Contains(n.TextMarkInlineMathContent, keyword) {
+								n.TextMarkInlineMathContent = strings.ReplaceAll(n.TextMarkInlineMathContent, keyword, replacement)
 							}
 							}
-							if r.MatchString(n.TextMarkInlineMathContent) {
+						} else if 3 == method {
+							if nil != r && r.MatchString(n.TextMarkInlineMathContent) {
 								n.TextMarkInlineMathContent = r.ReplaceAllString(n.TextMarkInlineMathContent, replacement)
 								n.TextMarkInlineMathContent = r.ReplaceAllString(n.TextMarkInlineMathContent, replacement)
 							}
 							}
-							if r.MatchString(n.TextMarkInlineMemoContent) {
-								n.TextMarkInlineMemoContent = r.ReplaceAllString(n.TextMarkInlineMemoContent, replacement)
-							}
-							if r.MatchString(n.TextMarkATitle) {
-								n.TextMarkATitle = r.ReplaceAllString(n.TextMarkATitle, replacement)
+						}
+					} else if n.IsTextMarkType("inline-memo") {
+						if !replaceTypes["inline-memo"] {
+							return ast.WalkContinue
+						}
+
+						if 0 == method {
+							if strings.Contains(n.TextMarkInlineMemoContent, keyword) {
+								n.TextMarkInlineMemoContent = strings.ReplaceAll(n.TextMarkInlineMemoContent, keyword, replacement)
 							}
 							}
-							if r.MatchString(n.TextMarkAHref) {
-								n.TextMarkAHref = r.ReplaceAllString(n.TextMarkAHref, replacement)
+						} else if 3 == method {
+							if nil != r && r.MatchString(n.TextMarkInlineMemoContent) {
+								n.TextMarkInlineMemoContent = r.ReplaceAllString(n.TextMarkInlineMemoContent, replacement)
 							}
 							}
 						}
 						}
 					}
 					}
@@ -469,6 +582,30 @@ func FindReplace(keyword, replacement string, ids []string, paths, boxes []strin
 	return
 	return
 }
 }
 
 
+func replaceNodeTextMarkTextContent(n *ast.Node, method int, keyword string, replacement string, r *regexp.Regexp) {
+	if 0 == method {
+		if strings.Contains(n.TextMarkTextContent, keyword) {
+			n.TextMarkTextContent = strings.ReplaceAll(n.TextMarkTextContent, keyword, replacement)
+		}
+	} else if 3 == method {
+		if nil != r && r.MatchString(n.TextMarkTextContent) {
+			n.TextMarkTextContent = r.ReplaceAllString(n.TextMarkTextContent, replacement)
+		}
+	}
+}
+
+func replaceNodeTokens(n *ast.Node, method int, keyword string, replacement string, r *regexp.Regexp) {
+	if 0 == method {
+		if bytes.Contains(n.Tokens, []byte(keyword)) {
+			n.Tokens = bytes.ReplaceAll(n.Tokens, []byte(keyword), []byte(replacement))
+		}
+	} else if 3 == method {
+		if nil != r && r.MatchString(string(n.Tokens)) {
+			n.Tokens = []byte(r.ReplaceAllString(string(n.Tokens), replacement))
+		}
+	}
+}
+
 // FullTextSearchBlock 搜索内容块。
 // FullTextSearchBlock 搜索内容块。
 //
 //
 // method:0:关键字,1:查询语法,2:SQL,3:正则表达式
 // method:0:关键字,1:查询语法,2:SQL,3:正则表达式

+ 6 - 5
kernel/treenode/node.go

@@ -419,11 +419,12 @@ var typeAbbrMap = map[string]string{
 	"NodeThematicBreak":    "tb",
 	"NodeThematicBreak":    "tb",
 	"NodeVideo":            "video",
 	"NodeVideo":            "video",
 	"NodeAudio":            "audio",
 	"NodeAudio":            "audio",
-	"NodeText":             "text",
-	"NodeImage":            "img",
-	"NodeLinkText":         "link_text",
-	"NodeLinkDest":         "link_dest",
-	"NodeTextMark":         "textmark",
+	// 行级元素
+	"NodeText":     "text",
+	"NodeImage":    "img",
+	"NodeLinkText": "link_text",
+	"NodeLinkDest": "link_dest",
+	"NodeTextMark": "textmark",
 }
 }
 
 
 var abbrTypeMap = map[string]string{}
 var abbrTypeMap = map[string]string{}