diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index 936d6db16..24c0ce21b 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -526,7 +526,7 @@ "md35": "Virtual Reference keyword exclusion list", "md36": "Use the English comma , to separate, the comma itself can be escaped by \\,", "md37": "The maximum length of block ref dynamic anchor text", - "md38": "The maximum length of the anchor text that is automatically rendered when the block ref anchor text is not customized, the default is 64 characters", + "md38": "The maximum length of the anchor text that is automatically rendered when the block ref anchor text is not customized, the default is 96 characters", "md39": "PlantUML Serve Address", "md40": "Leave blank to restore default https://www.plantuml.com/plantuml/svg/~1", "fileTree2": "The doc tree will automatically select the current document when the editor tab is switched", diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index 7262178c8..d557b871e 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -526,7 +526,7 @@ "md35": "Liste d'exclusion des mots-clés de la référence virtuelle", "md36": "Utiliser la virgule anglaise , pour séparer, la virgule elle-même peut être échappée par \\,", "md37": "La longueur maximale du texte d'ancrage dynamique de référence de bloc", - "md38": "La longueur maximale du texte d'ancrage qui est automatiquement rendu lorsque le texte d'ancrage de la référence de bloc n'est pas personnalisé, la valeur par défaut est de 64 caractères", + "md38": "La longueur maximale du texte d'ancrage qui est automatiquement rendu lorsque le texte d'ancrage de la référence de bloc n'est pas personnalisé, la valeur par défaut est de 96 caractères", "md39": "Adresse Servo PlantUML", "md40": "Laissez vide pour restaurer https://www.plantuml.com/plantuml/svg/~1/code> par défaut", "fileTree2": "L'arbre des Docs sélectionne automatiquement le document en cours lorsque l'on change d'onglet d'édition", diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index 16000f442..67717426f 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -526,7 +526,7 @@ "md35": "虛擬引用關鍵字排除列表", "md36": "使用英文狀態下的逗號 , 進行分隔,逗號自身可通過 \\, 轉義", "md37": "塊引動態錨文本最大長度", - "md38": "不自訂塊引錨文本時自動渲染錨文本的最大長度,預設為 64 個字元", + "md38": "不自訂塊引錨文本時自動渲染錨文本的最大長度,預設為 96 個字元", "md39": "PlantUML 伺服地址", "md40": "留空將恢復默認值 https://www.plantuml.com/plantuml/svg/~1", "fileTree2": "在編輯器切換分頁時文檔樹會自動選中當前的文檔", diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index 0133b69f1..c2e11a190 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -527,7 +527,7 @@ "md35": "虚拟引用关键字排除列表", "md36": "使用英文状态下的逗号 , 进行分隔,逗号自身可通过 \\, 转义", "md37": "块引动态锚文本最大长度", - "md38": "不自定义块引锚文本时自动渲染锚文本的最大长度,默认为 64 个字符", + "md38": "不自定义块引锚文本时自动渲染锚文本的最大长度,默认为 96 个字符", "md39": "PlantUML 伺服地址", "md40": "留空将恢复默认值 https://www.plantuml.com/plantuml/svg/~1", "fileTree2": "在编辑器页签切换时文档树会自动选中当前的文档", diff --git a/kernel/conf/editor.go b/kernel/conf/editor.go index 888c788a4..0e4e90ae8 100644 --- a/kernel/conf/editor.go +++ b/kernel/conf/editor.go @@ -47,7 +47,7 @@ func NewEditor() *Editor { HistoryRetentionDays: 30, Emoji: []string{}, VirtualBlockRef: false, - BlockRefDynamicAnchorTextMaxLen: 64, + BlockRefDynamicAnchorTextMaxLen: 96, PlantUMLServePath: "https://www.plantuml.com/plantuml/svg/~1", } } diff --git a/kernel/model/search.go b/kernel/model/search.go index 94da07002..c8c40945f 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -26,7 +26,6 @@ import ( "github.com/88250/gulu" "github.com/88250/lute/ast" - "github.com/88250/lute/html" "github.com/88250/lute/parse" "github.com/jinzhu/copier" "github.com/siyuan-note/siyuan/kernel/conf" @@ -249,12 +248,12 @@ func fullTextSearchRefBlock(keyword string, beforeLen int) (ret []*Block) { } projections := "id, parent_id, root_id, hash, box, path, " + - "highlight(" + table + ", 6, '__@mark__', '__mark@__') AS hpath, " + - "highlight(" + table + ", 7, '__@mark__', '__mark@__') AS name, " + - "highlight(" + table + ", 8, '__@mark__', '__mark@__') AS alias, " + - "highlight(" + table + ", 9, '__@mark__', '__mark@__') AS memo, " + + "snippet(" + table + ", 6, '__r', '', '...', 64) AS hpath, " + + "snippet(" + table + ", 7, '__r', '', '...', 64) AS name, " + + "snippet(" + table + ", 8, '__r', '', '...', 64) AS alias, " + + "snippet(" + table + ", 9, '__r', '', '...', 64) AS memo, " + "tag, " + - "highlight(" + table + ", 11, '__@mark__', '__mark@__') AS content, " + + "snippet(" + table + ", 11, '__r', '', '...', 64) AS content, " + "fcontent, markdown, length, type, subtype, ial, sort, created, updated" stmt := "SELECT " + projections + " FROM " + table + " WHERE " + table + " MATCH '" + columnFilter() + ":(" + quotedKeyword + ")' AND type IN " + Conf.Search.TypeFilter() orderBy := ` order by case @@ -383,19 +382,28 @@ func query2Stmt(queryStr string) (ret string) { return } -func markSearch(text string, keyword string, beforeLen int) (pos int, marked string, score float64) { +func markSearch(text string, keyword string, beforeLen int) (marked string, score float64) { if 0 == len(keyword) { marked = text if maxLen := 5120; maxLen < utf8.RuneCountInString(marked) { marked = gulu.Str.SubStr(marked, maxLen) + "..." } - marked = html.EscapeString(marked) - marked = strings.ReplaceAll(marked, "__@mark__", "") - marked = strings.ReplaceAll(marked, "__mark@__", "") + + if strings.Contains(marked, "__r") { // 使用 FTS snippet() 处理过高亮片段,这里简单替换后就返回 + marked = strings.ReplaceAll(marked, "__r", "") + return + } + + keywords := util.SubstringsBetween(marked, "__@mark__", "__mark@__") + keywords = util.RemoveDuplicatedElem(keywords) + keyword = strings.Join(keywords, search.TermSep) + marked = strings.ReplaceAll(marked, "__@mark__", "") + marked = strings.ReplaceAll(marked, "__mark@__", "") + _, marked = search.MarkText(marked, keyword, beforeLen, Conf.Search.CaseSensitive) return } - pos, marked = search.MarkText(text, keyword, beforeLen, Conf.Search.CaseSensitive) + pos, marked := search.MarkText(text, keyword, beforeLen, Conf.Search.CaseSensitive) if -1 < pos { if 0 == pos { score = 1 @@ -424,7 +432,7 @@ func fromSQLBlock(sqlBlock *sql.Block, terms string, beforeLen int) (block *Bloc content := sqlBlock.Content p := sqlBlock.Path - _, content, _ = markSearch(content, terms, beforeLen) + content, _ = markSearch(content, terms, beforeLen) markdown := maxContent(sqlBlock.Markdown, 5120) content = maxContent(content, 5120) @@ -454,20 +462,20 @@ func fromSQLBlock(sqlBlock *sql.Block, terms string, beforeLen int) (block *Bloc } } - _, hPath, _ := markSearch(sqlBlock.HPath, terms, 18) + hPath, _ := markSearch(sqlBlock.HPath, terms, 18) if !strings.HasPrefix(hPath, "/") { hPath = "/" + hPath } block.HPath = hPath if "" != block.Name { - _, block.Name, _ = markSearch(block.Name, terms, 256) + block.Name, _ = markSearch(block.Name, terms, 256) } if "" != block.Alias { - _, block.Alias, _ = markSearch(block.Alias, terms, 256) + block.Alias, _ = markSearch(block.Alias, terms, 256) } if "" != block.Memo { - _, block.Memo, _ = markSearch(block.Memo, terms, 256) + block.Memo, _ = markSearch(block.Memo, terms, 256) } return }