🎨 Improve search result highlight and positioning https://github.com/siyuan-note/siyuan/issues/8274

This commit is contained in:
Liang Ding 2023-05-19 10:18:25 +08:00
parent 19dd0cd796
commit 0f90105527
No known key found for this signature in database
GPG key ID: 136F30F901A2231D
3 changed files with 55 additions and 8 deletions

View file

@ -675,11 +675,24 @@ func getDoc(c *gin.Context) {
if nil != idx {
index = int(idx.(float64))
}
k := arg["k"]
var keyword string
if nil != k {
keyword = k.(string)
var query string
if queryArg := arg["query"]; nil != queryArg {
query = queryArg.(string)
}
var queryMethod int
if queryMethodArg := arg["queryMethod"]; nil != queryMethodArg {
queryMethod = int(queryMethodArg.(float64))
}
var queryTypes map[string]bool
if queryTypesArg := arg["queryTypes"]; nil != queryTypesArg {
typesArg := queryTypesArg.(map[string]interface{})
queryTypes = map[string]bool{}
for t, b := range typesArg {
queryTypes[t] = b.(bool)
}
}
m := arg["mode"] // 0: 仅当前 ID1向上 2向下3上下都加载4加载末尾
mode := 0
if nil != m {
@ -705,7 +718,7 @@ func getDoc(c *gin.Context) {
isBacklink = isBacklinkArg.(bool)
}
blockCount, content, parentID, parent2ID, rootID, typ, eof, scroll, boxID, docPath, isBacklinkExpand, err := model.GetDoc(startID, endID, id, index, keyword, mode, size, isBacklink)
blockCount, content, parentID, parent2ID, rootID, typ, eof, scroll, boxID, docPath, isBacklinkExpand, err := model.GetDoc(startID, endID, id, index, query, queryTypes, queryMethod, mode, size, isBacklink)
if model.ErrBlockNotFound == err {
ret.Code = 3
return

View file

@ -488,7 +488,7 @@ func StatTree(id string) (ret *util.BlockStatResult) {
}
}
func GetDoc(startID, endID, id string, index int, keyword string, mode int, size int, isBacklink bool) (blockCount int, dom, parentID, parent2ID, rootID, typ string, eof, scroll bool, boxID, docPath string, isBacklinkExpand bool, err error) {
func GetDoc(startID, endID, id string, index int, query string, queryTypes map[string]bool, queryMethod, mode int, size int, isBacklink bool) (blockCount int, dom, parentID, parent2ID, rootID, typ string, eof, scroll bool, boxID, docPath string, isBacklinkExpand bool, err error) {
//os.MkdirAll("pprof", 0755)
//cpuProfile, _ := os.Create("pprof/GetDoc")
//pprof.StartCPUProfile(cpuProfile)
@ -671,8 +671,12 @@ func GetDoc(startID, endID, id string, index int, keyword string, mode int, size
virtualBlockRefKeywords := getBlockVirtualRefKeywords(tree.Root)
subTree := &parse.Tree{ID: rootID, Root: &ast.Node{Type: ast.NodeDocument}, Marks: tree.Marks}
keyword = strings.Join(strings.Split(keyword, " "), search.TermSep)
keywords := search.SplitKeyword(keyword)
var keywords []string
if 0 == queryMethod || 1 == queryMethod { // 只有关键字搜索和查询语法搜索才支持高亮
typeFilter := buildTypeFilter(queryTypes)
keywords = highlightByQuery(query, typeFilter, rootID)
}
for _, n := range nodes {
var unlinks []*ast.Node

View file

@ -782,6 +782,35 @@ func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy strin
return
}
func highlightByQuery(query, typeFilter, id string) (ret []string) {
const limit = 256
table := "blocks_fts"
if !Conf.Search.CaseSensitive {
table = "blocks_fts_case_insensitive"
}
projections := "id, parent_id, root_id, hash, box, path, " +
"highlight(" + table + ", 6, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "') AS hpath, " +
"highlight(" + table + ", 7, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "') AS name, " +
"highlight(" + table + ", 8, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "') AS alias, " +
"highlight(" + table + ", 9, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "') AS memo, " +
"tag, " +
"highlight(" + table + ", 11, '" + search.SearchMarkLeft + "', '" + search.SearchMarkRight + "') AS content, " +
"fcontent, markdown, length, type, subtype, ial, sort, created, updated"
stmt := "SELECT " + projections + " FROM " + table + " WHERE (`" + table + "` MATCH '" + columnFilter() + ":(" + query + ")'"
stmt += ") AND type IN " + typeFilter
stmt += " AND root_id = '" + id + "'"
stmt += " LIMIT " + strconv.Itoa(limit)
sqlBlocks := sql.SelectBlocksRawStmt(stmt, 1, limit)
for _, block := range sqlBlocks {
keyword := gulu.Str.SubstringsBetween(block.Content, search.SearchMarkLeft, search.SearchMarkRight)
if 0 < len(keyword) {
ret = append(ret, keyword...)
}
}
ret = gulu.Str.RemoveDuplicatedElem(ret)
return
}
func fullTextSearchCount(query, boxFilter, pathFilter, typeFilter string) (matchedBlockCount, matchedRootCount int) {
query = gulu.Str.RemoveInvisible(query)
if ast.IsNodeIDPattern(query) {
@ -1017,6 +1046,7 @@ func markReplaceSpan(n *ast.Node, unlinks *[]*ast.Node, keywords []string, markS
}
} else if ast.NodeTextMark == n.Type {
// 搜索结果高亮支持大部分行级元素 https://github.com/siyuan-note/siyuan/issues/6745
if n.IsTextMarkType("inline-math") || n.IsTextMarkType("inline-memo") {
return false
}