diff --git a/app/src/config/repos.ts b/app/src/config/repos.ts index 53b144695..700b5c83d 100644 --- a/app/src/config/repos.ts +++ b/app/src/config/repos.ts @@ -316,13 +316,18 @@ const bindProviderEvent = () => { concurrentReqs = 16; } (providerPanelElement.querySelector("#timeout") as HTMLInputElement).value = timeout.toString(); + let endpoint = (providerPanelElement.querySelector("#endpoint") as HTMLInputElement).value; + endpoint = endpoint.trim().replace("http://http(s)://", "https://"); + if (!endpoint.startsWith("http")) { + endpoint = "http://" + endpoint; + } const s3 = { - endpoint: (providerPanelElement.querySelector("#endpoint") as HTMLInputElement).value, - accessKey: (providerPanelElement.querySelector("#accessKey") as HTMLInputElement).value, - secretKey: (providerPanelElement.querySelector("#secretKey") as HTMLInputElement).value, - bucket: (providerPanelElement.querySelector("#bucket") as HTMLInputElement).value, + endpoint: endpoint, + accessKey: (providerPanelElement.querySelector("#accessKey") as HTMLInputElement).value.trim(), + secretKey: (providerPanelElement.querySelector("#secretKey") as HTMLInputElement).value.trim(), + bucket: (providerPanelElement.querySelector("#bucket") as HTMLInputElement).value.trim(), pathStyle: (providerPanelElement.querySelector("#pathStyle") as HTMLInputElement).value === "true", - region: (providerPanelElement.querySelector("#region") as HTMLInputElement).value, + region: (providerPanelElement.querySelector("#region") as HTMLInputElement).value.trim(), skipTlsVerify: (providerPanelElement.querySelector("#s3SkipTlsVerify") as HTMLInputElement).value === "true", timeout: timeout, concurrentReqs: concurrentReqs, @@ -346,10 +351,15 @@ const bindProviderEvent = () => { concurrentReqs = 16; } (providerPanelElement.querySelector("#timeout") as HTMLInputElement).value = timeout.toString(); + let endpoint = (providerPanelElement.querySelector("#endpoint") as HTMLInputElement).value; + endpoint = endpoint.trim().replace("http://http(s)://", "https://"); + if (!endpoint.startsWith("http")) { + endpoint = "http://" + endpoint; + } const webdav = { - endpoint: (providerPanelElement.querySelector("#endpoint") as HTMLInputElement).value, - username: (providerPanelElement.querySelector("#username") as HTMLInputElement).value, - password: (providerPanelElement.querySelector("#password") as HTMLInputElement).value, + endpoint: endpoint, + username: (providerPanelElement.querySelector("#username") as HTMLInputElement).value.trim(), + password: (providerPanelElement.querySelector("#password") as HTMLInputElement).value.trim(), skipTlsVerify: (providerPanelElement.querySelector("#webdavSkipTlsVerify") as HTMLInputElement).value === "true", timeout: timeout, concurrentReqs: concurrentReqs, diff --git a/kernel/api/block.go b/kernel/api/block.go index 2b69ef069..2e5f8df91 100644 --- a/kernel/api/block.go +++ b/kernel/api/block.go @@ -438,11 +438,12 @@ func getRefIDs(c *gin.Context) { } id := arg["id"].(string) - refIDs, refTexts, defIDs := model.GetBlockRefs(id, true) - ret.Data = map[string][]string{ - "refIDs": refIDs, - "refTexts": refTexts, - "defIDs": defIDs, + refIDs, refTexts, defIDs, originalRefBlockIDs := model.GetBlockRefs(id, true) + ret.Data = map[string]any{ + "refIDs": refIDs, + "refTexts": refTexts, + "defIDs": defIDs, + "originalRefBlockIDs": originalRefBlockIDs, } } diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go index 9d116cb79..1b04c5550 100644 --- a/kernel/model/backlink.go +++ b/kernel/model/backlink.go @@ -78,7 +78,7 @@ func GetBackmentionDoc(defID, refTreeID, keyword string, containChildren, highli refs := sql.QueryRefsByDefID(defID, containChildren) refs = removeDuplicatedRefs(refs) - linkRefs, _, excludeBacklinkIDs := buildLinkRefs(rootID, refs, keywords) + linkRefs, _, excludeBacklinkIDs, originalRefBlockIDs := buildLinkRefs(rootID, refs, keywords) tmpMentions, mentionKeywords := buildTreeBackmention(sqlBlock, linkRefs, keyword, excludeBacklinkIDs, beforeLen) luteEngine := util.NewLute() var mentions []*Block @@ -106,7 +106,7 @@ func GetBackmentionDoc(defID, refTreeID, keyword string, containChildren, highli var refTree *parse.Tree trees := filesys.LoadTrees(mentionBlockIDs) for id, tree := range trees { - backlink := buildBacklink(id, tree, mentionKeywords, highlight, luteEngine) + backlink := buildBacklink(id, tree, originalRefBlockIDs, mentionKeywords, highlight, luteEngine) if nil != backlink { ret = append(ret, backlink) } @@ -148,7 +148,7 @@ func GetBacklinkDoc(defID, refTreeID, keyword string, containChildren, highlight } refs = removeDuplicatedRefs(refs) - linkRefs, _, _ := buildLinkRefs(rootID, refs, keywords) + linkRefs, _, _, originalRefBlockIDs := buildLinkRefs(rootID, refs, keywords) refTree, err := LoadTreeByBlockID(refTreeID) if err != nil { logging.LogWarnf("load ref tree [%s] failed: %s", refTreeID, err) @@ -157,7 +157,7 @@ func GetBacklinkDoc(defID, refTreeID, keyword string, containChildren, highlight luteEngine := util.NewLute() for _, linkRef := range linkRefs { - backlink := buildBacklink(linkRef.ID, refTree, keywords, highlight, luteEngine) + backlink := buildBacklink(linkRef.ID, refTree, originalRefBlockIDs, keywords, highlight, luteEngine) if nil != backlink { ret = append(ret, backlink) } @@ -198,13 +198,13 @@ func sortBacklinks(backlinks []*Backlink, tree *parse.Tree) { }) } -func buildBacklink(refID string, refTree *parse.Tree, keywords []string, highlight bool, luteEngine *lute.Lute) (ret *Backlink) { +func buildBacklink(refID string, refTree *parse.Tree, originalRefBlockIDs map[string]string, keywords []string, highlight bool, luteEngine *lute.Lute) (ret *Backlink) { node := treenode.GetNodeInTree(refTree, refID) if nil == node { return } - renderNodes, expand := getBacklinkRenderNodes(node) + renderNodes, expand := getBacklinkRenderNodes(node, originalRefBlockIDs) if highlight && 0 < len(keywords) { for _, renderNode := range renderNodes { @@ -244,7 +244,7 @@ func buildBacklink(refID string, refTree *parse.Tree, keywords []string, highlig return } -func getBacklinkRenderNodes(n *ast.Node) (ret []*ast.Node, expand bool) { +func getBacklinkRenderNodes(n *ast.Node, originalRefBlockIDs map[string]string) (ret []*ast.Node, expand bool) { expand = true if ast.NodeListItem == n.Type { if nil == n.FirstChild { @@ -257,13 +257,19 @@ func getBacklinkRenderNodes(n *ast.Node) (ret []*ast.Node, expand bool) { } if c != n.LastChild { // 存在子列表 - for liFirstBlockSpan := c.FirstChild; nil != liFirstBlockSpan; liFirstBlockSpan = liFirstBlockSpan.Next { - if treenode.IsBlockRef(liFirstBlockSpan) { + for ; nil != c; c = c.Next { + if originalRefBlockIDs[n.ID] != c.ID { continue } - if "" != strings.TrimSpace(liFirstBlockSpan.Text()) { - expand = false - break + + for liFirstBlockSpan := c.FirstChild; nil != liFirstBlockSpan; liFirstBlockSpan = liFirstBlockSpan.Next { + if treenode.IsBlockRef(liFirstBlockSpan) { + continue + } + if "" != strings.TrimSpace(liFirstBlockSpan.Text()) { + expand = false + break + } } } } @@ -313,7 +319,7 @@ func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode refs := sql.QueryRefsByDefID(id, containChildren) refs = removeDuplicatedRefs(refs) - linkRefs, linkRefsCount, excludeBacklinkIDs := buildLinkRefs(rootID, refs, keywords) + linkRefs, linkRefsCount, excludeBacklinkIDs, _ := buildLinkRefs(rootID, refs, keywords) tmpBacklinks := toFlatTree(linkRefs, 0, "backlink", nil) for _, l := range tmpBacklinks { l.Blocks = nil @@ -509,7 +515,7 @@ func GetBacklink(id, keyword, mentionKeyword string, beforeLen int, containChild return } -func buildLinkRefs(defRootID string, refs []*sql.Ref, keywords []string) (ret []*Block, refsCount int, excludeBacklinkIDs *hashset.Set) { +func buildLinkRefs(defRootID string, refs []*sql.Ref, keywords []string) (ret []*Block, refsCount int, excludeBacklinkIDs *hashset.Set, originalRefBlockIDs map[string]string) { // 为了减少查询,组装好 IDs 后一次查出 defSQLBlockIDs, refSQLBlockIDs := map[string]bool{}, map[string]bool{} var queryBlockIDs []string @@ -582,19 +588,18 @@ func buildLinkRefs(defRootID string, refs []*sql.Ref, keywords []string) (ret [] sqlParagraphParents := sql.GetBlocks(paragraphParentIDs) paragraphParents := fromSQLBlocks(&sqlParagraphParents, "", 12) + originalRefBlockIDs = map[string]string{} processedParagraphs := hashset.New() - for _, p := range paragraphParents { - // 改进标题下方块和列表项子块引用时的反链定位 https://github.com/siyuan-note/siyuan/issues/7484 - if "NodeListItem" == p.Type { - refBlock := parentRefParagraphs[p.ID] - if nil != refBlock && p.FContent == refBlock.Content { // 使用内容判断是否是列表项下第一个子块 - // 如果是列表项下第一个子块,则后续会通过列表项传递或关联处理,所以这里就不处理这个段落了 - processedParagraphs.Add(p.ID) - if !matchBacklinkKeyword(p, keywords) { + for _, parent := range paragraphParents { + if "NodeListItem" == parent.Type || "NodeBlockquote" == parent.Type || "NodeSuperBlock" == parent.Type { + if refBlock := parentRefParagraphs[parent.ID]; nil != refBlock { + processedParagraphs.Add(parent.ID) + originalRefBlockIDs[parent.ID] = refBlock.ID + if !matchBacklinkKeyword(parent, keywords) { refsCount-- continue } - ret = append(ret, p) + ret = append(ret, parent) } } } diff --git a/kernel/model/blockinfo.go b/kernel/model/blockinfo.go index dc0b1f48d..ab092852a 100644 --- a/kernel/model/blockinfo.go +++ b/kernel/model/blockinfo.go @@ -91,7 +91,7 @@ func GetDocInfo(blockID string) (ret *BlockInfo) { } ret.RefIDs, _ = sql.QueryRefIDsByDefID(blockID, Conf.Editor.BacklinkContainChildren) - buildBacklinkListItemRefs(&ret.RefIDs) + buildBacklinkListItemRefs(&ret.RefIDs, &map[string]string{}) ret.RefCount = len(ret.RefIDs) // 填充块引计数 // 填充属性视图角标 Display the database title on the block superscript https://github.com/siyuan-note/siyuan/issues/10545 @@ -320,10 +320,11 @@ func getNodeRefText0(node *ast.Node, maxLen int, removeLineBreak bool) string { return ret } -func GetBlockRefs(defID string, isBacklink bool) (refIDs, refTexts, defIDs []string) { +func GetBlockRefs(defID string, isBacklink bool) (refIDs, refTexts, defIDs []string, originalRefIDs map[string]string) { refIDs = []string{} refTexts = []string{} defIDs = []string{} + originalRefIDs = map[string]string{} bt := treenode.GetBlockTree(defID) if nil == bt { return @@ -338,7 +339,7 @@ func GetBlockRefs(defID string, isBacklink bool) (refIDs, refTexts, defIDs []str } if isBacklink { - buildBacklinkListItemRefs(&refIDs) + buildBacklinkListItemRefs(&refIDs, &originalRefIDs) } return } @@ -557,16 +558,19 @@ func buildBlockBreadcrumb(node *ast.Node, excludeTypes []string, isEmbedBlock bo return } -func buildBacklinkListItemRefs(refIDs *[]string) { +func buildBacklinkListItemRefs(refIDs *[]string, originalRefIDs *map[string]string) { refBts := treenode.GetBlockTrees(*refIDs) for i, refID := range *refIDs { - if bt := refBts[refID]; nil != bt { - if "p" == bt.Type { - if parent := treenode.GetBlockTree(bt.ParentID); nil != parent && "i" == parent.Type { - // 引用计数浮窗请求,需要按照反链逻辑组装 https://github.com/siyuan-note/siyuan/issues/6853 - (*refIDs)[i] = parent.ID - } - } + bt := refBts[refID] + if nil == bt || "p" != bt.Type { + continue + } + + if parent := treenode.GetBlockTree(bt.ParentID); nil != parent && + ("i" == parent.Type || "b" == parent.Type || "s" == parent.Type) { + // 引用计数浮窗请求,需要按照反链逻辑组装 https://github.com/siyuan-note/siyuan/issues/6853 + (*refIDs)[i] = parent.ID + (*originalRefIDs)[parent.ID] = refID } } } diff --git a/kernel/model/file.go b/kernel/model/file.go index 0f3c2a938..0af69204d 100644 --- a/kernel/model/file.go +++ b/kernel/model/file.go @@ -603,7 +603,9 @@ func GetDoc(startID, endID, id string, index int, query string, queryTypes map[s var nodes []*ast.Node if isBacklink { // 引用计数浮窗请求,需要按照反链逻辑组装 https://github.com/siyuan-note/siyuan/issues/6853 - nodes, isBacklinkExpand = getBacklinkRenderNodes(node) + originalRefBlockIDs := map[string]string{} + // TODO 需要增加参数,使用 getRefIDs 返回的 originalRefBlockIDs 增加这个参数后才能支持计数浮窗内计算折叠状态 https://github.com/siyuan-note/siyuan/issues/13776 + nodes, isBacklinkExpand = getBacklinkRenderNodes(node, originalRefBlockIDs) } else { // 如果同时存在 startID 和 endID,并且是动态加载的情况,则只加载 startID 和 endID 之间的块 [startID, endID] if "" != startID && "" != endID && scroll { diff --git a/kernel/model/push_reload.go b/kernel/model/push_reload.go index 5c58b66a5..906f00040 100644 --- a/kernel/model/push_reload.go +++ b/kernel/model/push_reload.go @@ -17,9 +17,6 @@ package model import ( - "github.com/88250/lute" - "github.com/88250/lute/render" - "github.com/siyuan-note/siyuan/kernel/filesys" "os" "path" "path/filepath" @@ -28,10 +25,13 @@ import ( "github.com/88250/go-humanize" "github.com/88250/gulu" + "github.com/88250/lute" "github.com/88250/lute/ast" "github.com/88250/lute/parse" + "github.com/88250/lute/render" "github.com/emirpasic/gods/sets/hashset" "github.com/siyuan-note/siyuan/kernel/av" + "github.com/siyuan-note/siyuan/kernel/filesys" "github.com/siyuan-note/siyuan/kernel/sql" "github.com/siyuan-note/siyuan/kernel/task" "github.com/siyuan-note/siyuan/kernel/treenode" @@ -157,7 +157,7 @@ func refreshRefCount(rootID, blockID string) { for _, count := range refCounts { rootRefCount += count } - refIDs, _, _ := GetBlockRefs(blockID, false) + refIDs, _, _, _ := GetBlockRefs(blockID, false) util.PushSetDefRefCount(rootID, blockID, refIDs, refCount, rootRefCount) } @@ -238,6 +238,15 @@ func refreshDynamicRefTexts(updatedDefNodes map[string]*ast.Node, updatedTrees m } // 2. 更新属性视图主键内容 + updateAttributeViewBlockText(updatedDefNodes) + + // 3. 保存变更 + for _, tree := range changedRefTree { + indexWriteTreeUpsertQueue(tree) + } +} + +func updateAttributeViewBlockText(updatedDefNodes map[string]*ast.Node) { var parents []*ast.Node for _, updatedDefNode := range updatedDefNodes { for parent := updatedDefNode.Parent; nil != parent && ast.NodeDocument != parent.Type; parent = parent.Parent { @@ -287,11 +296,6 @@ func refreshDynamicRefTexts(updatedDefNodes map[string]*ast.Node, updatedTrees m } } } - - // 3. 保存变更 - for _, tree := range changedRefTree { - indexWriteTreeUpsertQueue(tree) - } } // ReloadAttrView 用于重新加载属性视图。 diff --git a/kernel/model/search.go b/kernel/model/search.go index 8fdd9296f..f127222c1 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -536,6 +536,7 @@ func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids luteEngine := util.NewLute() var reloadTreeIDs []string + updateNodes := map[string]*ast.Node{} for i, id := range ids { bt := treenode.GetBlockTree(id) if nil == bt { @@ -863,6 +864,8 @@ func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids } } + updateNodes[id] = node + util.PushEndlessProgress(fmt.Sprintf(Conf.Language(206), i+1, len(ids))) } @@ -880,6 +883,8 @@ func FindReplace(keyword, replacement string, replaceTypes map[string]bool, ids refreshProtyle(id) } + updateAttributeViewBlockText(updateNodes) + sql.FlushQueue() util.PushClearProgress() return diff --git a/kernel/model/sync.go b/kernel/model/sync.go index d77aecde2..7bd209ee9 100644 --- a/kernel/model/sync.go +++ b/kernel/model/sync.go @@ -495,6 +495,13 @@ func SetSyncProviderLocal(local *conf.Local) (err error) { return } + if util.IsSubPath(absPath, util.WorkspaceDir) { + msg := fmt.Sprintf("endpoint [%s] is parent of workspace", local.Endpoint) + logging.LogErrorf(msg) + err = errors.New(fmt.Sprintf(Conf.Language(77), msg)) + return + } + local.Timeout = util.NormalizeTimeout(local.Timeout) local.ConcurrentReqs = util.NormalizeConcurrentReqs(local.ConcurrentReqs, conf.ProviderLocal)