From e8ac568b3d564d168c40180b85042479237d4b5b Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sat, 24 Jun 2023 11:06:42 +0800 Subject: [PATCH 1/6] :art: Set the default workspace path to `~/SiYuan/` on the desktop end https://github.com/siyuan-note/siyuan/issues/8602 --- .../20210808180303-xaduj2o/20200924100717-yzwzn64.sy | 2 +- .../20210808180321-hbvl5c2/20200828105441-r76vmu5.sy | 2 +- .../20211226121203-rjjngpz/20211226122358-hctqcn5.sy | 2 +- kernel/util/working.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-xaduj2o/20200924100717-yzwzn64.sy b/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-xaduj2o/20200924100717-yzwzn64.sy index eb98ef277..755be3515 100644 --- a/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-xaduj2o/20200924100717-yzwzn64.sy +++ b/app/guide/20210808180117-6v0mkxr/20200923234011-ieuun1p/20210808180303-xaduj2o/20200924100717-yzwzn64.sy @@ -44,7 +44,7 @@ { "Type": "NodeTextMark", "TextMarkType": "code", - "TextMarkTextContent": "~/Documents/SiYuan/" + "TextMarkTextContent": "~/SiYuan/" }, { "Type": "NodeText", diff --git a/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180321-hbvl5c2/20200828105441-r76vmu5.sy b/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180321-hbvl5c2/20200828105441-r76vmu5.sy index 3a32b08b9..3ec0a9254 100644 --- a/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180321-hbvl5c2/20200828105441-r76vmu5.sy +++ b/app/guide/20210808180117-czj9bvb/20200812220555-lj3enxa/20210808180321-hbvl5c2/20200828105441-r76vmu5.sy @@ -56,7 +56,7 @@ "id": "" }, "TextMarkType": "code", - "TextMarkTextContent": "~/Documents/SiYuan/" + "TextMarkTextContent": "~/SiYuan/" }, { "Type": "NodeText", diff --git a/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226121203-rjjngpz/20211226122358-hctqcn5.sy b/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226121203-rjjngpz/20211226122358-hctqcn5.sy index 3e8b95c24..a45a0e6ca 100644 --- a/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226121203-rjjngpz/20211226122358-hctqcn5.sy +++ b/app/guide/20211226090932-5lcq56f/20211226115423-d5z1joq/20211226121203-rjjngpz/20211226122358-hctqcn5.sy @@ -55,7 +55,7 @@ "id": "" }, "TextMarkType": "code", - "TextMarkTextContent": "~/Documents/SiYuan/" + "TextMarkTextContent": "~/SiYuan/" }, { "Type": "NodeText", diff --git a/kernel/util/working.go b/kernel/util/working.go index 781830c35..608fa43f2 100644 --- a/kernel/util/working.go +++ b/kernel/util/working.go @@ -57,7 +57,7 @@ func Boot() { initMime() initHttpClient() - workspacePath := flag.String("workspace", "", "dir path of the workspace, default to ~/Documents/SiYuan/") + workspacePath := flag.String("workspace", "", "dir path of the workspace, default to ~/SiYuan/") wdPath := flag.String("wd", WorkingDir, "working directory of SiYuan") port := flag.String("port", "0", "port of the HTTP server") readOnly := flag.String("readonly", "false", "read-only mode") From 1d3925b1b50f988f46d03582f82faf6f4c4688b9 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sat, 24 Jun 2023 16:00:26 +0800 Subject: [PATCH 2/6] :fire: macOS systems prior to `10.15` are no longer supported https://github.com/siyuan-note/siyuan/issues/8604 --- app/electron-builder-darwin-arm64.yml | 1 + app/electron-builder-darwin.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/app/electron-builder-darwin-arm64.yml b/app/electron-builder-darwin-arm64.yml index e9fda38a4..69b8e2136 100644 --- a/app/electron-builder-darwin-arm64.yml +++ b/app/electron-builder-darwin-arm64.yml @@ -21,6 +21,7 @@ mac: extendInfo: - NSMicrophoneUsageDescription: "This app requires microphone access to record audio." entitlementsInherit: "../../entitlements.mas.plist" + minimumSystemVersion: "10.15" extraResources: - from: "kernel-darwin-arm64" to: "kernel" diff --git a/app/electron-builder-darwin.yml b/app/electron-builder-darwin.yml index 0474c1957..48373d35d 100644 --- a/app/electron-builder-darwin.yml +++ b/app/electron-builder-darwin.yml @@ -21,6 +21,7 @@ mac: extendInfo: - NSMicrophoneUsageDescription: "This app requires microphone access to record audio." entitlementsInherit: "../../entitlements.mas.plist" + minimumSystemVersion: "10.15" extraResources: - from: "kernel-darwin" to: "kernel" From 24f6f6337940d1f0c752efa4460550824ac2283c Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sat, 24 Jun 2023 17:01:11 +0800 Subject: [PATCH 3/6] :art: Convert `[[wikilink]]` and `#Tag` syntax when importing Markdown https://github.com/siyuan-note/siyuan/issues/8603 --- kernel/model/import.go | 192 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 181 insertions(+), 11 deletions(-) diff --git a/kernel/model/import.go b/kernel/model/import.go index a23869e1e..a8e3c8d9a 100644 --- a/kernel/model/import.go +++ b/kernel/model/import.go @@ -502,7 +502,6 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) { assetsDone := map[string]string{} // md 转换 sy - i := 0 filepath.Walk(localPath, func(currentPath string, info os.FileInfo, walkErr error) error { if strings.HasPrefix(info.Name(), ".") { if info.IsDir() { @@ -538,9 +537,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) { if info.IsDir() { tree = treenode.NewTree(boxID, targetPath, hPath, title) - if err = indexWriteJSONQueue(tree); nil != err { - return io.EOF - } + importTrees = append(importTrees, tree) return nil } @@ -623,12 +620,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) { }) reassignIDUpdated(tree) - indexWriteJSONQueue(tree) - - i++ - if 0 == i%4 { - util.PushEndlessProgress(fmt.Sprintf(Conf.Language(66), fmt.Sprintf("%d ", i)+util.ShortPathForBootingDisplay(tree.Path))) - } + importTrees = append(importTrees, tree) return nil }) } else { // 导入单个文件 @@ -707,7 +699,23 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) { }) reassignIDUpdated(tree) - indexWriteJSONQueue(tree) + importTrees = append(importTrees, tree) + } + + if 0 < len(importTrees) { + initSearchLinks() + convertWikiLinksAndTags() + buildBlockRefInText() + + for i, tree := range importTrees { + indexWriteJSONQueue(tree) + if 0 == i%4 { + util.PushEndlessProgress(fmt.Sprintf(Conf.Language(66), fmt.Sprintf("%d/%d ", i, len(importTrees))+tree.HPath)) + } + } + + importTrees = []*parse.Tree{} + searchLinks = map[string]string{} } IncSync() @@ -909,3 +917,165 @@ func domAttrValue(n *html.Node, attrName string) string { } return "" } + +var importTrees []*parse.Tree +var searchLinks = map[string]string{} + +func initSearchLinks() { + for _, tree := range importTrees { + ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { + if !entering || (ast.NodeDocument != n.Type && ast.NodeHeading != n.Type) { + return ast.WalkContinue + } + + nodePath := tree.HPath + "#" + if ast.NodeHeading == n.Type { + nodePath += n.Text() + } + + searchLinks[nodePath] = n.ID + return ast.WalkContinue + }) + } +} + +func convertWikiLinksAndTags() { + for _, tree := range importTrees { + convertWikiLinksAndTags0(tree) + } +} + +func convertWikiLinksAndTags0(tree *parse.Tree) { + ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { + if !entering || ast.NodeText != n.Type { + return ast.WalkContinue + } + + text := n.TokensStr() + length := len(text) + start, end := 0, length + for { + part := text[start:end] + if idx := strings.Index(part, "]]"); 0 > idx { + break + } else { + end = start + idx + } + if idx := strings.Index(part, "[["); 0 > idx { + break + } else { + start += idx + } + if end <= start { + break + } + + link := path.Join(path.Dir(tree.HPath), text[start+2:end]) // 统一转为绝对路径方便后续查找 + linkText := path.Base(link) + if linkParts := strings.Split(link, "|"); 1 < len(linkParts) { + link = linkParts[0] + linkText = linkParts[1] + } + link, linkText = strings.TrimSpace(link), strings.TrimSpace(linkText) + if !strings.Contains(link, "#") { + link += "#" // 在结尾统一带上锚点方便后续查找 + } + + id := searchLinkID(link) + if "" == id { + start, end = end, length + continue + } + + linkText = strings.TrimPrefix(linkText, "/") + repl := "((" + id + " '" + linkText + "'))" + end += 2 + text = text[:start] + repl + text[end:] + start, end = start+len(repl), len(text) + length = end + } + + text = convertTags(text) // 导入标签语法 + n.Tokens = gulu.Str.ToBytes(text) + return ast.WalkContinue + }) +} + +func convertTags(text string) (ret string) { + pos, i := -1, 0 + tokens := []byte(text) + for ; i < len(tokens); i++ { + if '#' == tokens[i] && (0 == i || ' ' == tokens[i-1] || (-1 < pos && '#' == tokens[pos])) { + if i < len(tokens)-1 && '#' == tokens[i+1] { + pos = -1 + continue + } + pos = i + continue + } + + if -1 < pos && ' ' == tokens[i] { + tokens = append(tokens, 0) + copy(tokens[i+1:], tokens[i:]) + tokens[i] = '#' + pos = -1 + i++ + } + } + if -1 < pos && pos < i { + tokens = append(tokens, '#') + } + return string(tokens) +} + +// buildBlockRefInText 将文本节点进行结构化处理。 +func buildBlockRefInText() { + lute := NewLute() + for _, tree := range importTrees { + var unlinkTextNodes []*ast.Node + ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { + if !entering || ast.NodeText != n.Type { + return ast.WalkContinue + } + + if nil == n.Tokens { + return ast.WalkContinue + } + + t := parse.Inline("", n.Tokens, lute.ParseOptions) // 使用行级解析 + var children []*ast.Node + for c := t.Root.FirstChild.FirstChild; nil != c; c = c.Next { + children = append(children, c) + } + for _, c := range children { + n.InsertBefore(c) + } + unlinkTextNodes = append(unlinkTextNodes, n) + return ast.WalkContinue + }) + + for _, node := range unlinkTextNodes { + node.Unlink() + } + } +} + +func searchLinkID(link string) (id string) { + id = searchLinks[link] + if "" != id { + return + } + + baseName := path.Base(link) + for searchLink, searchID := range searchLinks { + if path.Base(searchLink) == baseName { + return searchID + } + } + return +} + +func cleanImport() { + importTrees = []*parse.Tree{} + searchLinks = map[string]string{} +} From ed6a4a5141fdb369431801c6c751b61e2bd90085 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sat, 24 Jun 2023 17:08:03 +0800 Subject: [PATCH 4/6] :art: Convert `[[wikilink]]` and `#Tag` syntax when importing Markdown https://github.com/siyuan-note/siyuan/issues/8603 --- kernel/model/import.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/model/import.go b/kernel/model/import.go index a8e3c8d9a..bfe3c67ed 100644 --- a/kernel/model/import.go +++ b/kernel/model/import.go @@ -972,9 +972,11 @@ func convertWikiLinksAndTags0(tree *parse.Tree) { link := path.Join(path.Dir(tree.HPath), text[start+2:end]) // 统一转为绝对路径方便后续查找 linkText := path.Base(link) + dynamicAnchorText := true if linkParts := strings.Split(link, "|"); 1 < len(linkParts) { link = linkParts[0] linkText = linkParts[1] + dynamicAnchorText = false } link, linkText = strings.TrimSpace(link), strings.TrimSpace(linkText) if !strings.Contains(link, "#") { @@ -989,6 +991,9 @@ func convertWikiLinksAndTags0(tree *parse.Tree) { linkText = strings.TrimPrefix(linkText, "/") repl := "((" + id + " '" + linkText + "'))" + if !dynamicAnchorText { + repl = "((" + id + " \"" + linkText + "\"))" + } end += 2 text = text[:start] + repl + text[end:] start, end = start+len(repl), len(text) From 0f519f62b196199f837f7e52ee9344e337f29557 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sat, 24 Jun 2023 17:47:16 +0800 Subject: [PATCH 5/6] :art: After invoking kernel API `setBlockAttrs` then auto refresh dynamic anchor text of block refs Fix https://github.com/siyuan-note/siyuan/issues/8605 --- kernel/model/blockial.go | 6 ++++++ kernel/model/transaction.go | 18 ++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/kernel/model/blockial.go b/kernel/model/blockial.go index 8d0ee4174..63e3c7e15 100644 --- a/kernel/model/blockial.go +++ b/kernel/model/blockial.go @@ -29,6 +29,7 @@ import ( "github.com/88250/lute/parse" "github.com/araddon/dateparse" "github.com/siyuan-note/siyuan/kernel/cache" + "github.com/siyuan-note/siyuan/kernel/sql" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -135,6 +136,11 @@ func setNodeAttrs(node *ast.Node, tree *parse.Tree, nameValues map[string]string cache.PutBlockIAL(node.ID, parse.IAL2Map(node.KramdownIAL)) pushBroadcastAttrTransactions(oldAttrs, node) + + go func() { + sql.WaitForWritingDatabase() + refreshDynamicRefText(node, tree) + }() return } diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 954cbc344..2b0192af3 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -1059,7 +1059,7 @@ func (tx *Transaction) commit() (err error) { return } } - refreshDynamicRefText(tx.nodes, tx.trees) + refreshDynamicRefTexts(tx.nodes, tx.trees) IncSync() tx.trees = nil return @@ -1099,9 +1099,17 @@ func (tx *Transaction) writeTree(tree *parse.Tree) (err error) { return } -func refreshDynamicRefText(updatedDefNodes map[string]*ast.Node, updatedTrees map[string]*parse.Tree) { - // 这个实现依赖了数据库缓存,导致外部调用时可能需要阻塞等待数据库写入后才能获取到 refs +// refreshDynamicRefText 用于刷新引用块的动态锚文本。 +// 该实现依赖了数据库缓存,导致外部调用时可能需要阻塞等待数据库写入后才能获取到 refs +func refreshDynamicRefText(updatedDefNode *ast.Node, updatedTree *parse.Tree) { + changedDefs := map[string]*ast.Node{updatedDefNode.ID: updatedDefNode} + changedTrees := map[string]*parse.Tree{updatedTree.ID: updatedTree} + refreshDynamicRefTexts(changedDefs, changedTrees) +} +// refreshDynamicRefTexts 用于批量刷新引用块的动态锚文本。 +// 该实现依赖了数据库缓存,导致外部调用时可能需要阻塞等待数据库写入后才能获取到 refs +func refreshDynamicRefTexts(updatedDefNodes map[string]*ast.Node, updatedTrees map[string]*parse.Tree) { treeRefNodeIDs := map[string]*hashset.Set{} for _, updateNode := range updatedDefNodes { refs := sql.GetRefsCacheByDefID(updateNode.ID) @@ -1183,9 +1191,7 @@ func flushUpdateRefTextRenameDoc() { defer updateRefTextRenameDocLock.Unlock() for _, tree := range updateRefTextRenameDocs { - changedDefs := map[string]*ast.Node{tree.ID: tree.Root} - changedTrees := map[string]*parse.Tree{tree.ID: tree} - refreshDynamicRefText(changedDefs, changedTrees) + refreshDynamicRefText(tree.Root, tree) } updateRefTextRenameDocs = map[string]*parse.Tree{} } From bb0bbaf5a0c09d537726fabe496f8e0bfa1c8c5e Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sat, 24 Jun 2023 17:48:57 +0800 Subject: [PATCH 6/6] :art: After invoking kernel API `setBlockAttrs` then auto refresh dynamic anchor text of block refs Fix https://github.com/siyuan-note/siyuan/issues/8605 --- kernel/model/blockial.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/model/blockial.go b/kernel/model/blockial.go index 63e3c7e15..64575b010 100644 --- a/kernel/model/blockial.go +++ b/kernel/model/blockial.go @@ -138,7 +138,9 @@ func setNodeAttrs(node *ast.Node, tree *parse.Tree, nameValues map[string]string pushBroadcastAttrTransactions(oldAttrs, node) go func() { - sql.WaitForWritingDatabase() + if !sql.IsEmptyQueue() { + sql.WaitForWritingDatabase() + } refreshDynamicRefText(node, tree) }() return