diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go
index 1aa599ec7..37a3e71d3 100644
--- a/kernel/model/backlink.go
+++ b/kernel/model/backlink.go
@@ -300,10 +300,14 @@ func buildBacklink(refID string, refTree *parse.Tree, mentionKeywords []string,
}
if ast.NodeText == n.Type {
text := string(n.Tokens)
- text = search.EncloseHighlighting(text, mentionKeywords, "", "", Conf.Search.CaseSensitive)
- n.Tokens = gulu.Str.ToBytes(text)
+ newText := markReplaceSpan(text, mentionKeywords, searchMarkSpanStart, searchMarkSpanEnd)
+ if text == newText {
+ return ast.WalkContinue
+ }
+
+ n.Tokens = gulu.Str.ToBytes(newText)
if bytes.Contains(n.Tokens, []byte("search-mark")) {
- n.Tokens = bytes.ReplaceAll(n.Tokens, []byte("\\"), []byte("\\\\"))
+ n.Tokens = bytes.ReplaceAll(n.Tokens, []byte("\\"+searchMarkSpanStart), []byte("\\\\"+searchMarkSpanEnd))
linkTree := parse.Inline("", n.Tokens, luteEngine.ParseOptions)
var children []*ast.Node
for c := linkTree.Root.FirstChild.FirstChild; nil != c; c = c.Next {
@@ -789,8 +793,21 @@ func searchBackmention(mentionKeywords []string, keyword string, excludeBacklink
text = strings.ToLower(text)
var contain bool
for _, mentionKeyword := range mentionKeywords {
- if strings.Contains(text, strings.ToLower(mentionKeyword)) {
- contain = true
+ parts := strings.Split(text, " ")
+ for _, part := range parts {
+ if gulu.Str.IsASCII(mentionKeyword) {
+ if part == mentionKeyword {
+ contain = true
+ break
+ }
+ } else {
+ if strings.Contains(part, strings.ToLower(mentionKeyword)) {
+ contain = true
+ break
+ }
+ }
+ }
+ if contain {
break
}
}
diff --git a/kernel/model/file.go b/kernel/model/file.go
index 4cf6f2963..f9191c5ca 100644
--- a/kernel/model/file.go
+++ b/kernel/model/file.go
@@ -449,6 +449,8 @@ func StatTree(id string) (ret *util.BlockStatResult) {
}
const (
+ searchMarkSpanStart = ""
+ searchMarkSpanEnd = ""
virtualBlockRefSpanStart = ""
virtualBlockRefSpanEnd = ""
)
@@ -657,10 +659,10 @@ func GetDoc(startID, endID, id string, index int, keyword string, mode int, size
if hitBlock {
// 搜索高亮
text := string(n.Tokens)
- text = search.EncloseHighlighting(text, keywords, "", "", Conf.Search.CaseSensitive)
+ text = search.EncloseHighlighting(text, keywords, searchMarkSpanStart, searchMarkSpanEnd, Conf.Search.CaseSensitive)
n.Tokens = gulu.Str.ToBytes(text)
if bytes.Contains(n.Tokens, []byte("search-mark")) {
- n.Tokens = bytes.ReplaceAll(n.Tokens, []byte("\\"), []byte("\\\\"))
+ n.Tokens = bytes.ReplaceAll(n.Tokens, []byte("\\"+searchMarkSpanStart), []byte("\\\\"+searchMarkSpanEnd))
linkTree := parse.Inline("", n.Tokens, luteEngine.ParseOptions)
var children []*ast.Node
for c := linkTree.Root.FirstChild.FirstChild; nil != c; c = c.Next {
@@ -680,26 +682,7 @@ func GetDoc(startID, endID, id string, index int, keyword string, mode int, size
parentBlock := treenode.ParentBlock(n)
if nil != parentBlock && 1 > refCount[parentBlock.ID] {
content := string(n.Tokens)
- parts := strings.Split(content, " ")
- for i, part := range parts {
- if "" == part {
- continue
- }
-
- for _, k := range virtualBlockRefKeywords {
- if gulu.Str.IsASCII(k) {
- if part == k {
- parts[i] = virtualBlockRefSpanStart + k + virtualBlockRefSpanEnd
- }
- } else {
- if strings.Contains(part, k) {
- parts[i] = strings.ReplaceAll(part, k, virtualBlockRefSpanStart+k+virtualBlockRefSpanEnd)
- }
- }
- }
- }
- newContent := strings.Join(parts, " ")
-
+ newContent := markReplaceSpan(content, virtualBlockRefKeywords, virtualBlockRefSpanStart, virtualBlockRefSpanEnd)
if content != newContent {
// 虚拟引用排除命中自身块命名和别名的情况 https://github.com/siyuan-note/siyuan/issues/3185
var blockKeys []string
diff --git a/kernel/model/history.go b/kernel/model/history.go
index 6de56b0f1..3e345363d 100644
--- a/kernel/model/history.go
+++ b/kernel/model/history.go
@@ -182,10 +182,10 @@ func GetDocHistoryContent(historyPath, keyword string) (id, rootID, content stri
if 0 < len(keywords) {
// 搜索高亮
text := string(n.Tokens)
- text = search.EncloseHighlighting(text, keywords, "", "", false)
+ text = search.EncloseHighlighting(text, keywords, searchMarkSpanStart, searchMarkSpanEnd, false)
n.Tokens = gulu.Str.ToBytes(text)
if bytes.Contains(n.Tokens, []byte("search-mark")) {
- n.Tokens = bytes.ReplaceAll(n.Tokens, []byte("\\"), []byte("\\\\"))
+ n.Tokens = bytes.ReplaceAll(n.Tokens, []byte("\\"+searchMarkSpanStart), []byte("\\\\"+searchMarkSpanStart))
linkTree := parse.Inline("", n.Tokens, luteEngine.ParseOptions)
var children []*ast.Node
for c := linkTree.Root.FirstChild.FirstChild; nil != c; c = c.Next {
diff --git a/kernel/model/search.go b/kernel/model/search.go
index 2ea6ebc05..b02220a22 100644
--- a/kernel/model/search.go
+++ b/kernel/model/search.go
@@ -639,3 +639,25 @@ func stringQuery(query string) string {
}
return strings.TrimSpace(buf.String())
}
+
+func markReplaceSpan(text string, keywords []string, replacementStart, replacementEnd string) string {
+ parts := strings.Split(text, " ")
+ for i, part := range parts {
+ if "" == part {
+ continue
+ }
+
+ for _, k := range keywords {
+ if gulu.Str.IsASCII(k) {
+ if part == k {
+ parts[i] = replacementStart + k + replacementEnd
+ }
+ } else {
+ if strings.Contains(part, k) {
+ parts[i] = strings.ReplaceAll(part, k, replacementStart+k+replacementEnd)
+ }
+ }
+ }
+ }
+ return strings.Join(parts, " ")
+}