diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json
index e9e761a11..8b853e145 100644
--- a/app/appearance/langs/en_US.json
+++ b/app/appearance/langs/en_US.json
@@ -1,4 +1,5 @@
{
+ "visitCommunityShare": "Visit community share",
"clearContextSucc": "The context has been cleared",
"emptyMobilePlaceholder": "Record something",
"emptyPlaceholder": "Write something, ' / ' for commands",
@@ -466,6 +467,7 @@
"floatWindowMode1": "Press and hold ${hotkey}+Hover",
"floatWindowMode2": "Do not trigger",
"codeSnippet": "Code Snippet",
+ "codeSnippetTip": "Fine-tune the interface or functionality through code snippets",
"expandDown": "Expand Down",
"expandUp": "Expand Up",
"goForward": "Go forward",
diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json
index 1a7f1cbed..f9c8dcaef 100644
--- a/app/appearance/langs/es_ES.json
+++ b/app/appearance/langs/es_ES.json
@@ -1,4 +1,5 @@
{
+ "visitCommunityShare": "Visitar la comunidad compartida",
"clearContextSucc": "Se ha borrado el contexto",
"emptyMobilePlaceholder": "Grabar algo",
"emptyPlaceholder": "Escribe algo, ' / ' para los comandos",
@@ -466,6 +467,7 @@
"floatWindowMode1": "Presione y mantenga presionado ${hotkey}+Flotar",
"floatWindowMode2": "No activar",
"codeSnippet": "Fragmento de código",
+ "codeSnippetTip": "Ajusta la interfaz o la funcionalidad mediante fragmentos de código",
"expandDown": "Expandir hacia abajo",
"expandUp": "Expandir hacia arriba",
"goForward": "Ir hacia adelante",
diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json
index 1319a0112..4a9cfabb9 100644
--- a/app/appearance/langs/fr_FR.json
+++ b/app/appearance/langs/fr_FR.json
@@ -1,4 +1,5 @@
{
+ "visitCommunityShare": "Visiter le partage communautaire",
"clearContextSucc": "Le contexte a été effacé",
"emptyMobilePlaceholder": "Enregistrer quelque chose",
"emptyPlaceholder": "Écrivez quelque chose, ' / ' pour les commandes",
@@ -466,6 +467,7 @@
"floatWindowMode1": "Appuyez et maintenez ${hotkey}+Flotter",
"floatWindowMode2": "Ne pas déclencher",
"codeSnippet": "Extrait de code",
+ "codeSnippetTip": "Affiner l'interface ou les fonctionnalités grâce à des extraits de code",
"expandDown": "Développer vers le bas",
"expandUp": "Développer vers le haut",
"goForward": "Suivant",
diff --git a/app/appearance/langs/ja_JP.json b/app/appearance/langs/ja_JP.json
index c45735c4b..ca0fa4aba 100644
--- a/app/appearance/langs/ja_JP.json
+++ b/app/appearance/langs/ja_JP.json
@@ -1,4 +1,5 @@
{
+ "visitCommunityShare": "コミュニティシェアを訪問",
"clearContextSucc": "コンテキストがクリアされました",
"emptyMobilePlaceholder": "何かを記録する",
"emptyPlaceholder": "何か書いてください。コマンドの場合は「/」",
@@ -466,6 +467,7 @@
"floatWindowMode1": "${hotkey} を押しながらホバー",
"floatWindowMode2": "表示しない",
"codeSnippet": "コードスニペット",
+ "codeSnippetTip": "コード スニペットを通じてインターフェイスまたは機能を微調整します",
"expandDown": "選択範囲を下に拡張",
"expandUp": "選択範囲を上に拡張",
"goForward": "進む",
diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json
index fb5127291..c87e52021 100644
--- a/app/appearance/langs/zh_CHT.json
+++ b/app/appearance/langs/zh_CHT.json
@@ -1,4 +1,5 @@
{
+ "visitCommunityShare": "訪問社區分享",
"clearContextSucc": "上下文已清空",
"emptyMobilePlaceholder": "記錄點什麼",
"emptyPlaceholder": "寫點什麼,或按下 ' / ' 查看指令",
@@ -466,6 +467,7 @@
"floatWindowMode1": "按住 ${hotkey}+懸停",
"floatWindowMode2": "不觸發浮窗",
"codeSnippet": "代碼片段",
+ "codeSnippetTip": "透過程式碼片段對介面或功能進行微調",
"expandDown": "向下擴選",
"expandUp": "向上擴選",
"goForward": "前進",
diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json
index 1d72dda1a..8444223d1 100644
--- a/app/appearance/langs/zh_CN.json
+++ b/app/appearance/langs/zh_CN.json
@@ -1,4 +1,5 @@
{
+ "visitCommunityShare": "访问社区分享",
"clearContextSucc": "上下文已清空",
"emptyMobilePlaceholder": "记录点什么",
"emptyPlaceholder": "写点什么,或按下 ' / ' 查看命令",
@@ -466,6 +467,7 @@
"floatWindowMode1": "按住 ${hotkey}+悬停",
"floatWindowMode2": "不触发浮窗",
"codeSnippet": "代码片段",
+ "codeSnippetTip": "通过代码片段对界面或功能进行微调",
"expandDown": "向下扩选",
"expandUp": "向上扩选",
"goForward": "前进",
diff --git a/app/src/config/appearance.ts b/app/src/config/appearance.ts
index 0ece8950f..30246620a 100644
--- a/app/src/config/appearance.ts
+++ b/app/src/config/appearance.ts
@@ -121,8 +121,13 @@ export const appearance = {
${window.siyuan.languages.codeSnippet}
+
${window.siyuan.languages.codeSnippetTip}
+
+ ${window.siyuan.languages.visitCommunityShare}
+
+
diff --git a/kernel/api/workspace.go b/kernel/api/workspace.go
index be1d90eb3..1cec139eb 100644
--- a/kernel/api/workspace.go
+++ b/kernel/api/workspace.go
@@ -27,7 +27,6 @@ import (
"unicode/utf8"
"github.com/88250/gulu"
- "github.com/facette/natsort"
"github.com/gin-gonic/gin"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/model"
@@ -252,10 +251,10 @@ func getWorkspaces(c *gin.Context) {
}
}
sort.Slice(openedWorkspaces, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible(filepath.Base(openedWorkspaces[i].Path)), util.RemoveEmojiInvisible(filepath.Base(openedWorkspaces[j].Path)))
+ return util.NaturalCompare(filepath.Base(openedWorkspaces[i].Path), filepath.Base(openedWorkspaces[j].Path))
})
sort.Slice(closedWorkspaces, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible(filepath.Base(closedWorkspaces[i].Path)), util.RemoveEmojiInvisible(filepath.Base(closedWorkspaces[j].Path)))
+ return util.NaturalCompare(filepath.Base(closedWorkspaces[i].Path), filepath.Base(closedWorkspaces[j].Path))
})
workspaces = append(workspaces, openedWorkspaces...)
workspaces = append(workspaces, closedWorkspaces...)
diff --git a/kernel/av/sort.go b/kernel/av/sort.go
index 5b18b372c..a2505cd59 100644
--- a/kernel/av/sort.go
+++ b/kernel/av/sort.go
@@ -44,7 +44,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int {
switch value.Type {
case KeyTypeBlock:
if nil != value.Block && nil != other.Block {
- return strings.Compare(value.Block.Content, other.Block.Content)
+ if util.PinYinCompare(value.Block.Content, other.Block.Content) {
+ return -1
+ }
+ return 1
}
case KeyTypeText:
if nil != value.Text && nil != other.Text {
@@ -56,7 +59,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int {
} else if "" == other.Text.Content {
return -1
}
- return strings.Compare(value.Text.Content, other.Text.Content)
+ if util.PinYinCompare(value.Text.Content, other.Text.Content) {
+ return -1
+ }
+ return 1
}
case KeyTypeNumber:
if nil != value.Number && nil != other.Number {
@@ -223,7 +229,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int {
for _, v := range other.MAsset {
v2 += v.Content
}
- return strings.Compare(v1, v2)
+ if util.PinYinCompare(v1, v2) {
+ return -1
+ }
+ return 1
}
case KeyTypeTemplate:
if nil != value.Template && nil != other.Template {
@@ -238,7 +247,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int {
}
return 0
}
- return strings.Compare(value.Template.Content, other.Template.Content)
+ if util.PinYinCompare(value.Template.Content, other.Template.Content) {
+ return -1
+ }
+ return 1
}
case KeyTypeCheckbox:
if nil != value.Checkbox && nil != other.Checkbox {
@@ -278,7 +290,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int {
oContentBuf.WriteByte(' ')
}
oContent := strings.TrimSpace(oContentBuf.String())
- return strings.Compare(vContent, oContent)
+ if util.PinYinCompare(vContent, oContent) {
+ return -1
+ }
+ return 1
}
case KeyTypeRollup:
if nil != value.Rollup && nil != other.Rollup {
@@ -308,7 +323,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int {
oContentBuf.WriteByte(' ')
}
oContent := strings.TrimSpace(oContentBuf.String())
- return strings.Compare(vContent, oContent)
+ if util.PinYinCompare(vContent, oContent) {
+ return -1
+ }
+ return 1
}
}
return 0
diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go
index 524ddc6c6..36ce476ce 100644
--- a/kernel/model/attribute_view.go
+++ b/kernel/model/attribute_view.go
@@ -75,6 +75,23 @@ func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]*
v.UpdatedAt = now
keyValues.Values = append(keyValues.Values, v)
+
+ if av.KeyTypeSelect == v.Type || av.KeyTypeMSelect == v.Type {
+ // 保存选项 https://github.com/siyuan-note/siyuan/issues/12475
+ key, _ := attrView.GetKey(v.KeyID)
+ if nil != key && 0 < len(v.MSelect) {
+ for _, valOpt := range v.MSelect {
+ if opt := key.GetOption(valOpt.Content); nil == opt {
+ // 不存在的选项新建保存
+ opt = &av.SelectOption{Name: valOpt.Content, Color: valOpt.Color}
+ key.Options = append(key.Options, opt)
+ } else {
+ // 已经存在的选项颜色需要保持不变
+ valOpt.Color = opt.Color
+ }
+ }
+ }
+ }
}
}
diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go
index 8950ed4ca..f8a35a659 100644
--- a/kernel/model/backlink.go
+++ b/kernel/model/backlink.go
@@ -29,7 +29,6 @@ import (
"github.com/88250/lute/ast"
"github.com/88250/lute/parse"
"github.com/emirpasic/gods/sets/hashset"
- "github.com/facette/natsort"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/search"
"github.com/siyuan-note/siyuan/kernel/sql"
@@ -275,13 +274,13 @@ func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode
case util.SortModeCreatedASC:
return backlinks[i].Created < backlinks[j].Created
case util.SortModeNameDESC:
- return util.PinYinCompare(util.RemoveEmojiInvisible(backlinks[j].Name), util.RemoveEmojiInvisible(backlinks[i].Name))
+ return util.PinYinCompare(backlinks[j].Name, backlinks[i].Name)
case util.SortModeNameASC:
- return util.PinYinCompare(util.RemoveEmojiInvisible(backlinks[i].Name), util.RemoveEmojiInvisible(backlinks[j].Name))
+ return util.PinYinCompare(backlinks[i].Name, backlinks[j].Name)
case util.SortModeAlphanumDESC:
- return natsort.Compare(util.RemoveEmojiInvisible(backlinks[j].Name), util.RemoveEmojiInvisible(backlinks[i].Name))
+ return util.NaturalCompare(backlinks[j].Name, backlinks[i].Name)
case util.SortModeAlphanumASC:
- return natsort.Compare(util.RemoveEmojiInvisible(backlinks[i].Name), util.RemoveEmojiInvisible(backlinks[j].Name))
+ return util.NaturalCompare(backlinks[i].Name, backlinks[j].Name)
}
return backlinks[i].ID > backlinks[j].ID
})
@@ -304,13 +303,13 @@ func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode
case util.SortModeCreatedASC:
return backmentions[i].Created < backmentions[j].Created
case util.SortModeNameDESC:
- return util.PinYinCompare(util.RemoveEmojiInvisible(backmentions[j].Name), util.RemoveEmojiInvisible(backmentions[i].Name))
+ return util.PinYinCompare(backmentions[j].Name, backmentions[i].Name)
case util.SortModeNameASC:
- return util.PinYinCompare(util.RemoveEmojiInvisible(backmentions[i].Name), util.RemoveEmojiInvisible(backmentions[j].Name))
+ return util.PinYinCompare(backmentions[i].Name, backmentions[j].Name)
case util.SortModeAlphanumDESC:
- return natsort.Compare(util.RemoveEmojiInvisible(backmentions[j].Name), util.RemoveEmojiInvisible(backmentions[i].Name))
+ return util.NaturalCompare(backmentions[j].Name, backmentions[i].Name)
case util.SortModeAlphanumASC:
- return natsort.Compare(util.RemoveEmojiInvisible(backmentions[i].Name), util.RemoveEmojiInvisible(backmentions[j].Name))
+ return util.NaturalCompare(backmentions[i].Name, backmentions[j].Name)
}
return backmentions[i].ID > backmentions[j].ID
})
@@ -520,7 +519,7 @@ func buildLinkRefs(defRootID string, refs []*sql.Ref, keyword string) (ret []*Bl
}
var paragraphParentIDs []string
- for parentID, _ := range parentRefParagraphs {
+ for parentID := range parentRefParagraphs {
paragraphParentIDs = append(paragraphParentIDs, parentID)
}
sqlParagraphParents := sql.GetBlocks(paragraphParentIDs)
diff --git a/kernel/model/box.go b/kernel/model/box.go
index 20f1304bb..3135e5d72 100644
--- a/kernel/model/box.go
+++ b/kernel/model/box.go
@@ -34,7 +34,6 @@ import (
"github.com/88250/lute/html"
"github.com/88250/lute/lex"
"github.com/88250/lute/parse"
- "github.com/facette/natsort"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/cache"
@@ -150,30 +149,30 @@ func ListNotebooks() (ret []*Box, err error) {
switch Conf.FileTree.Sort {
case util.SortModeNameASC:
sort.Slice(ret, func(i, j int) bool {
- return util.PinYinCompare(util.RemoveEmojiInvisible(ret[i].Name), util.RemoveEmojiInvisible(ret[j].Name))
+ return util.PinYinCompare(ret[i].Name, ret[j].Name)
})
case util.SortModeNameDESC:
sort.Slice(ret, func(i, j int) bool {
- return util.PinYinCompare(util.RemoveEmojiInvisible(ret[j].Name), util.RemoveEmojiInvisible(ret[i].Name))
+ return util.PinYinCompare(ret[j].Name, ret[i].Name)
})
case util.SortModeUpdatedASC:
case util.SortModeUpdatedDESC:
case util.SortModeAlphanumASC:
sort.Slice(ret, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible(ret[i].Name), util.RemoveEmojiInvisible(ret[j].Name))
+ return util.NaturalCompare(ret[i].Name, ret[j].Name)
})
case util.SortModeAlphanumDESC:
sort.Slice(ret, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible(ret[j].Name), util.RemoveEmojiInvisible(ret[i].Name))
+ return util.NaturalCompare(ret[j].Name, ret[i].Name)
})
case util.SortModeCustom:
sort.Slice(ret, func(i, j int) bool { return ret[i].Sort < ret[j].Sort })
case util.SortModeRefCountASC:
case util.SortModeRefCountDESC:
case util.SortModeCreatedASC:
- sort.Slice(ret, func(i, j int) bool { return natsort.Compare(ret[j].ID, ret[i].ID) })
+ sort.Slice(ret, func(i, j int) bool { return util.NaturalCompare(ret[j].ID, ret[i].ID) })
case util.SortModeCreatedDESC:
- sort.Slice(ret, func(i, j int) bool { return natsort.Compare(ret[j].ID, ret[i].ID) })
+ sort.Slice(ret, func(i, j int) bool { return util.NaturalCompare(ret[j].ID, ret[i].ID) })
}
return
}
diff --git a/kernel/model/export.go b/kernel/model/export.go
index 02c379b25..5a1b8138e 100644
--- a/kernel/model/export.go
+++ b/kernel/model/export.go
@@ -454,6 +454,8 @@ func ExportData() (zipPath string, err error) {
func exportData(exportFolder string) (zipPath string, err error) {
WaitForWritingFiles()
+ logging.LogInfof("exporting data...")
+
baseFolderName := "data-" + util.CurrentTimeSecondsStr()
if err = os.MkdirAll(exportFolder, 0755); err != nil {
logging.LogErrorf("create export temp folder failed: %s", err)
@@ -489,6 +491,7 @@ func exportData(exportFolder string) (zipPath string, err error) {
}
os.RemoveAll(exportFolder)
+ logging.LogInfof("export data done [%s]", zipPath)
return
}
diff --git a/kernel/model/file.go b/kernel/model/file.go
index 3f67730aa..5765b5d93 100644
--- a/kernel/model/file.go
+++ b/kernel/model/file.go
@@ -37,7 +37,6 @@ import (
"github.com/88250/lute/html"
"github.com/88250/lute/parse"
util2 "github.com/88250/lute/util"
- "github.com/facette/natsort"
jsoniter "github.com/json-iterator/go"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
@@ -388,11 +387,11 @@ func ListDocTree(boxID, listPath string, sortMode int, flashcard, showHidden boo
switch sortMode {
case util.SortModeNameASC:
sort.Slice(docs, func(i, j int) bool {
- return util.PinYinCompare(util.RemoveEmojiInvisible(docs[i].Name), util.RemoveEmojiInvisible(docs[j].Name))
+ return util.PinYinCompare(docs[i].Name, docs[j].Name)
})
case util.SortModeNameDESC:
sort.Slice(docs, func(i, j int) bool {
- return util.PinYinCompare(util.RemoveEmojiInvisible(docs[j].Name), util.RemoveEmojiInvisible(docs[i].Name))
+ return util.PinYinCompare(docs[j].Name, docs[i].Name)
})
case util.SortModeUpdatedASC:
sort.Slice(docs, func(i, j int) bool { return docs[i].Mtime < docs[j].Mtime })
@@ -400,11 +399,11 @@ func ListDocTree(boxID, listPath string, sortMode int, flashcard, showHidden boo
sort.Slice(docs, func(i, j int) bool { return docs[i].Mtime > docs[j].Mtime })
case util.SortModeAlphanumASC:
sort.Slice(docs, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible(docs[i].Name), util.RemoveEmojiInvisible(docs[j].Name))
+ return util.NaturalCompare(docs[i].Name, docs[j].Name)
})
case util.SortModeAlphanumDESC:
sort.Slice(docs, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible(docs[j].Name), util.RemoveEmojiInvisible(docs[i].Name))
+ return util.NaturalCompare(docs[j].Name, docs[i].Name)
})
case util.SortModeCustom:
fileTreeFiles := docs
diff --git a/kernel/model/tag.go b/kernel/model/tag.go
index 1f598fdb7..8a84cdd48 100644
--- a/kernel/model/tag.go
+++ b/kernel/model/tag.go
@@ -24,7 +24,6 @@ import (
"github.com/88250/lute/ast"
"github.com/emirpasic/gods/sets/hashset"
- "github.com/facette/natsort"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/search"
"github.com/siyuan-note/siyuan/kernel/sql"
@@ -216,7 +215,7 @@ func BuildTags() (ret *Tags) {
ret = &Tags{}
labels := labelTags()
tags := Tags{}
- for label, _ := range labels {
+ for label := range labels {
tags = buildTags(tags, strings.Split(label, "/"), 0)
}
appendTagChildren(&tags, labels)
@@ -248,19 +247,19 @@ func sortTags(tags Tags) {
switch Conf.Tag.Sort {
case util.SortModeNameASC:
sort.Slice(tags, func(i, j int) bool {
- return util.PinYinCompare(util.RemoveEmojiInvisible(tags[i].Name), util.RemoveEmojiInvisible(tags[j].Name))
+ return util.PinYinCompare(tags[i].Name, tags[j].Name)
})
case util.SortModeNameDESC:
sort.Slice(tags, func(j, i int) bool {
- return util.PinYinCompare(util.RemoveEmojiInvisible(tags[i].Name), util.RemoveEmojiInvisible(tags[j].Name))
+ return util.PinYinCompare(tags[i].Name, tags[j].Name)
})
case util.SortModeAlphanumASC:
sort.Slice(tags, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible((tags)[i].Name), util.RemoveEmojiInvisible((tags)[j].Name))
+ return util.NaturalCompare((tags)[i].Name, (tags)[j].Name)
})
case util.SortModeAlphanumDESC:
sort.Slice(tags, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible((tags)[j].Name), util.RemoveEmojiInvisible((tags)[i].Name))
+ return util.NaturalCompare((tags)[j].Name, (tags)[i].Name)
})
case util.SortModeRefCountASC:
sort.Slice(tags, func(i, j int) bool { return (tags)[i].Count < (tags)[j].Count })
@@ -268,7 +267,7 @@ func sortTags(tags Tags) {
sort.Slice(tags, func(i, j int) bool { return (tags)[i].Count > (tags)[j].Count })
default:
sort.Slice(tags, func(i, j int) bool {
- return natsort.Compare(util.RemoveEmojiInvisible((tags)[i].Name), util.RemoveEmojiInvisible((tags)[j].Name))
+ return util.NaturalCompare((tags)[i].Name, (tags)[j].Name)
})
}
}
@@ -278,7 +277,7 @@ func SearchTags(keyword string) (ret []string) {
defer logging.Recover() // 定位 无法添加题头图标签 https://github.com/siyuan-note/siyuan/issues/6756
labels := labelBlocksByKeyword(keyword)
- for label, _ := range labels {
+ for label := range labels {
_, t := search.MarkText(label, keyword, 1024, Conf.Search.CaseSensitive)
ret = append(ret, t)
}
diff --git a/kernel/util/sort.go b/kernel/util/sort.go
index 41fdea64d..57c45aedc 100644
--- a/kernel/util/sort.go
+++ b/kernel/util/sort.go
@@ -21,11 +21,21 @@ import (
"io"
"strings"
+ "github.com/facette/natsort"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
+func NaturalCompare(str1, str2 string) bool {
+ str1 = RemoveEmojiInvisible(str1)
+ str2 = RemoveEmojiInvisible(str2)
+ return natsort.Compare(str1, str2)
+}
+
func PinYinCompare(str1, str2 string) bool {
+ str1 = RemoveEmojiInvisible(str1)
+ str2 = RemoveEmojiInvisible(str2)
+
// Doc tree, backlinks, tags and templates ignores case when sorting alphabetically by name https://github.com/siyuan-note/siyuan/issues/8360
str1 = strings.ToLower(str1)
str2 = strings.ToLower(str2)