From 5b79d7a2b669aa91ce09e62e70d3778aab687636 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Thu, 28 Nov 2024 09:42:31 +0800 Subject: [PATCH 1/4] :art: Improve exporting block ref https://github.com/siyuan-note/siyuan/issues/13283 --- app/src/protyle/export/index.ts | 3 +- app/src/protyle/preview/index.ts | 3 +- kernel/model/export.go | 64 +++++++++++++++++++++++++------- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/app/src/protyle/export/index.ts b/app/src/protyle/export/index.ts index 7f31ac046..c91c77102 100644 --- a/app/src/protyle/export/index.ts +++ b/app/src/protyle/export/index.ts @@ -441,7 +441,8 @@ const renderPDF = async (id: string) => { const linkAddress = target.getAttribute("href"); if (linkAddress.startsWith("#")) { // 导出预览模式点击块引转换后的脚注跳转不正确 https://github.com/siyuan-note/siyuan/issues/5700 - previewElement.querySelector(linkAddress).scrollIntoView(); + const hash = linkAddress.substring(1); + previewElement.querySelector('[data-node-id="' + hash + '"], [id="' + hash + '"]').scrollIntoView(); event.stopPropagation(); event.preventDefault(); return; diff --git a/app/src/protyle/preview/index.ts b/app/src/protyle/preview/index.ts index d74854d45..54791f88d 100644 --- a/app/src/protyle/preview/index.ts +++ b/app/src/protyle/preview/index.ts @@ -77,7 +77,8 @@ export class Preview { const linkAddress = target.getAttribute("href"); if (linkAddress.startsWith("#")) { // 导出预览模式点击块引转换后的脚注跳转不正确 https://github.com/siyuan-note/siyuan/issues/5700 - previewElement.querySelector(linkAddress).scrollIntoView(); + const hash = linkAddress.substring(1); + previewElement.querySelector('[data-node-id="' + hash + '"], [id="' + hash + '"]').scrollIntoView(); event.stopPropagation(); event.preventDefault(); break; diff --git a/kernel/model/export.go b/kernel/model/export.go index ad53b3dd7..6b34d27b7 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -2038,9 +2038,21 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool, treeCache := map[string]*parse.Tree{} treeCache[id] = ret depth := 0 - collectFootnotesDefs(ret.ID, &refFootnotes, &treeCache, &depth) + collectFootnotesDefs(ret, ret.ID, &refFootnotes, &treeCache, &depth) } + currentTreeNodeIDs := map[string]bool{} + ast.Walk(ret.Root, func(n *ast.Node, entering bool) ast.WalkStatus { + if !entering { + return ast.WalkContinue + } + + if "" != n.ID { + currentTreeNodeIDs[n.ID] = true + } + return ast.WalkContinue + }) + var unlinks []*ast.Node ast.Walk(ret.Root, func(n *ast.Node, entering bool) ast.WalkStatus { if !entering { @@ -2054,8 +2066,7 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool, return ast.WalkContinue } case ast.NodeHeading: - n.HeadingNormalizedID = n.IALAttr("id") - n.ID = n.HeadingNormalizedID + n.SetIALAttr("id", n.ID) case ast.NodeMathBlockContent: n.Tokens = bytes.TrimSpace(n.Tokens) // 导出 Markdown 时去除公式内容中的首尾空格 https://github.com/siyuan-note/siyuan/issues/4666 return ast.WalkContinue @@ -2086,12 +2097,7 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool, } // 处理引用节点 - defID, linkText := getExportBlockRefLinkText(n, blockRefTextLeft, blockRefTextRight) - defTree, _ := LoadTreeByBlockID(defID) - if nil == defTree { - return ast.WalkContinue - } switch blockRefMode { case 2: // 锚文本块链 @@ -2110,7 +2116,19 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool, n.InsertBefore(blockRefLink) unlinks = append(unlinks, n) case 4: // 脚注 + if currentTreeNodeIDs[defID] { + // 当前文档内不转换脚注,直接使用锚点哈希 https://github.com/siyuan-note/siyuan/issues/13283 + n.TextMarkType = "a" + n.TextMarkTextContent = linkText + n.TextMarkAHref = "#" + defID + return ast.WalkContinue + } + refFoot := getRefAsFootnotes(defID, &refFootnotes) + if nil == refFoot { + return ast.WalkContinue + } + n.InsertBefore(&ast.Node{Type: ast.NodeText, Tokens: []byte(linkText)}) n.InsertBefore(&ast.Node{Type: ast.NodeFootnotesRef, Tokens: []byte("^" + refFoot.refNum), FootnotesRefId: refFoot.refNum, FootnotesRefLabel: []byte("^" + refFoot.refNum)}) unlinks = append(unlinks, n) @@ -2705,7 +2723,7 @@ func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, rootID string, blockR return } -func collectFootnotesDefs(id string, refFootnotes *[]*refAsFootnotes, treeCache *map[string]*parse.Tree, depth *int) { +func collectFootnotesDefs(currentTree *parse.Tree, id string, refFootnotes *[]*refAsFootnotes, treeCache *map[string]*parse.Tree, depth *int) { *depth++ if 4096 < *depth { return @@ -2727,17 +2745,17 @@ func collectFootnotesDefs(id string, refFootnotes *[]*refAsFootnotes, treeCache logging.LogErrorf("not found node [%s] in tree [%s]", b.ID, t.Root.ID) return } - collectFootnotesDefs0(node, refFootnotes, treeCache, depth) + collectFootnotesDefs0(currentTree, node, refFootnotes, treeCache, depth) if ast.NodeHeading == node.Type { children := treenode.HeadingChildren(node) for _, c := range children { - collectFootnotesDefs0(c, refFootnotes, treeCache, depth) + collectFootnotesDefs0(currentTree, c, refFootnotes, treeCache, depth) } } return } -func collectFootnotesDefs0(node *ast.Node, refFootnotes *[]*refAsFootnotes, treeCache *map[string]*parse.Tree, depth *int) { +func collectFootnotesDefs0(currentTree *parse.Tree, node *ast.Node, refFootnotes *[]*refAsFootnotes, treeCache *map[string]*parse.Tree, depth *int) { ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus { if !entering { return ast.WalkContinue @@ -2746,6 +2764,10 @@ func collectFootnotesDefs0(node *ast.Node, refFootnotes *[]*refAsFootnotes, tree if treenode.IsBlockRef(n) { defID, refText, _ := treenode.GetBlockRef(n) if nil == getRefAsFootnotes(defID, refFootnotes) { + if isNodeInTree(defID, currentTree) { + // 当前文档内不转换脚注,直接使用锚点哈希 https://github.com/siyuan-note/siyuan/issues/13283 + return ast.WalkSkipChildren + } anchorText := refText if Conf.Editor.BlockRefDynamicAnchorTextMaxLen < utf8.RuneCountInString(anchorText) { anchorText = gulu.Str.SubStr(anchorText, Conf.Editor.BlockRefDynamicAnchorTextMaxLen) + "..." @@ -2755,13 +2777,29 @@ func collectFootnotesDefs0(node *ast.Node, refFootnotes *[]*refAsFootnotes, tree refNum: strconv.Itoa(len(*refFootnotes) + 1), refAnchorText: anchorText, }) - collectFootnotesDefs(defID, refFootnotes, treeCache, depth) + collectFootnotesDefs(currentTree, defID, refFootnotes, treeCache, depth) } return ast.WalkSkipChildren } return ast.WalkContinue }) } + +func isNodeInTree(id string, tree *parse.Tree) (ret bool) { + ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { + if !entering { + return ast.WalkContinue + } + + if n.ID == id { + ret = true + return ast.WalkStop + } + return ast.WalkContinue + }) + return +} + func getRefAsFootnotes(defID string, slice *[]*refAsFootnotes) *refAsFootnotes { for _, e := range *slice { if e.defID == defID { From 7884b6271894946335afbfd7f7d7be7db52415f7 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Thu, 28 Nov 2024 13:06:25 +0800 Subject: [PATCH 2/4] :art: Improve exporting block ref https://github.com/siyuan-note/siyuan/issues/13283 --- kernel/model/export.go | 57 +++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/kernel/model/export.go b/kernel/model/export.go index 6b34d27b7..bd82bf72c 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -2148,25 +2148,32 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool, if 4 == blockRefMode { // 块引转脚注 unlinks = nil - if footnotesDefBlock := resolveFootnotesDefs(&refFootnotes, ret.Root.ID, blockRefTextLeft, blockRefTextRight); nil != footnotesDefBlock { + if footnotesDefBlock := resolveFootnotesDefs(&refFootnotes, ret, currentTreeNodeIDs, blockRefTextLeft, blockRefTextRight); nil != footnotesDefBlock { // 如果是聚焦导出,可能存在没有使用的脚注定义块,在这里进行清理 // Improve focus export conversion of block refs to footnotes https://github.com/siyuan-note/siyuan/issues/10647 - footnotesRefs := ret.Root.ChildrenByType(ast.NodeFootnotesRef) - for footnotesDef := footnotesDefBlock.FirstChild; nil != footnotesDef; footnotesDef = footnotesDef.Next { - exist := false - for _, ref := range footnotesRefs { - if ref.FootnotesRefId == footnotesDef.FootnotesRefId { - exist = true - break - } - } - if !exist { - unlinks = append(unlinks, footnotesDef) - } - } - for _, n := range unlinks { - n.Unlink() - } + //footnotesRefs := ret.Root.ChildrenByType(ast.NodeFootnotesRef) + //for _, ref := range footnotesRefs { + // ast.Walk(ref, func(n *ast.Node, entering bool) ast.WalkStatus { + // if !entering { + // return ast.WalkContinue + // } + // + // if treenode.IsBlockRef(n) { + // refIDsInfnDefs[n.TextMarkBlockRefID] = true + // } + // return ast.WalkContinue + // }) + //} + // + //for footnotesDef := footnotesDefBlock.FirstChild; nil != footnotesDef; footnotesDef = footnotesDef.Next { + // exist := refIDsInfnDefs[footnotesDef.ID] + // if !exist { + // unlinks = append(unlinks, footnotesDef) + // } + //} + //for _, n := range unlinks { + // n.Unlink() + //} ret.Root.AppendChild(footnotesDefBlock) } @@ -2600,7 +2607,7 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool, return ret } -func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, rootID string, blockRefTextLeft, blockRefTextRight string) (footnotesDefBlock *ast.Node) { +func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, currentTree *parse.Tree, currentTreeNodeIDs map[string]bool, blockRefTextLeft, blockRefTextRight string) (footnotesDefBlock *ast.Node) { if 1 > len(*refFootnotes) { return nil } @@ -2617,7 +2624,7 @@ func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, rootID string, blockR var nodes []*ast.Node if ast.NodeHeading == defNode.Type { nodes = append(nodes, defNode) - if rootID != docID { + if currentTree.ID != docID { // 同文档块引转脚注缩略定义考虑容器块和标题块 https://github.com/siyuan-note/siyuan/issues/5917 children := treenode.HeadingChildren(defNode) nodes = append(nodes, children...) @@ -2648,6 +2655,16 @@ func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, rootID string, blockR n.InsertBefore(&ast.Node{Type: ast.NodeText, Tokens: []byte(blockRefTextLeft + f.refAnchorText + blockRefTextRight)}) n.InsertBefore(&ast.Node{Type: ast.NodeFootnotesRef, Tokens: []byte("^" + f.refNum), FootnotesRefId: f.refNum, FootnotesRefLabel: []byte("^" + f.refNum)}) unlinks = append(unlinks, n) + } else { + if isNodeInTree(defID, currentTree) { + if currentTreeNodeIDs[defID] { + // 当前文档内不转换脚注,直接使用锚点哈希 https://github.com/siyuan-note/siyuan/issues/13283 + n.TextMarkType = "a" + n.TextMarkTextContent = blockRefTextLeft + n.TextMarkTextContent + blockRefTextRight + n.TextMarkAHref = "#" + defID + return ast.WalkSkipChildren + } + } } return ast.WalkSkipChildren } else if ast.NodeBlockQueryEmbed == n.Type { @@ -2698,7 +2715,7 @@ func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, rootID string, blockR } docID := strings.TrimSuffix(path.Base(n.Path), ".sy") - if rootID == docID { + if currentTree.ID == docID { // 同文档块引转脚注缩略定义 https://github.com/siyuan-note/siyuan/issues/3299 if text := sql.GetRefText(n.ID); 64 < utf8.RuneCountInString(text) { var unlinkChildren []*ast.Node From e1a9051d76754096f58626aa0b100a147e14abcb Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Thu, 28 Nov 2024 13:25:24 +0800 Subject: [PATCH 3/4] :art: Improve exporting block ref https://github.com/siyuan-note/siyuan/issues/13283 --- kernel/model/export.go | 43 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/kernel/model/export.go b/kernel/model/export.go index bd82bf72c..f00e9c24a 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -2148,32 +2148,27 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool, if 4 == blockRefMode { // 块引转脚注 unlinks = nil - if footnotesDefBlock := resolveFootnotesDefs(&refFootnotes, ret, currentTreeNodeIDs, blockRefTextLeft, blockRefTextRight); nil != footnotesDefBlock { + footnotesDefBlock := resolveFootnotesDefs(&refFootnotes, ret, currentTreeNodeIDs, blockRefTextLeft, blockRefTextRight) + if nil != footnotesDefBlock { // 如果是聚焦导出,可能存在没有使用的脚注定义块,在这里进行清理 // Improve focus export conversion of block refs to footnotes https://github.com/siyuan-note/siyuan/issues/10647 - //footnotesRefs := ret.Root.ChildrenByType(ast.NodeFootnotesRef) - //for _, ref := range footnotesRefs { - // ast.Walk(ref, func(n *ast.Node, entering bool) ast.WalkStatus { - // if !entering { - // return ast.WalkContinue - // } - // - // if treenode.IsBlockRef(n) { - // refIDsInfnDefs[n.TextMarkBlockRefID] = true - // } - // return ast.WalkContinue - // }) - //} - // - //for footnotesDef := footnotesDefBlock.FirstChild; nil != footnotesDef; footnotesDef = footnotesDef.Next { - // exist := refIDsInfnDefs[footnotesDef.ID] - // if !exist { - // unlinks = append(unlinks, footnotesDef) - // } - //} - //for _, n := range unlinks { - // n.Unlink() - //} + footnotesRefs := ret.Root.ChildrenByType(ast.NodeFootnotesRef) + for footnotesDef := footnotesDefBlock.FirstChild; nil != footnotesDef; footnotesDef = footnotesDef.Next { + exist := false + for _, ref := range footnotesRefs { + if ref.FootnotesRefId == footnotesDef.FootnotesRefId { + exist = true + break + } + } + if !exist { + unlinks = append(unlinks, footnotesDef) + } + } + + for _, n := range unlinks { + n.Unlink() + } ret.Root.AppendChild(footnotesDefBlock) } From 3b22330b4b68a6f9c60c8d945bee89d4fc27278b Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Thu, 28 Nov 2024 15:37:45 +0800 Subject: [PATCH 4/4] :art: Improve exporting block ref https://github.com/siyuan-note/siyuan/issues/13283 --- kernel/model/export.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/model/export.go b/kernel/model/export.go index f00e9c24a..3bc0511e4 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -2153,6 +2153,11 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool, // 如果是聚焦导出,可能存在没有使用的脚注定义块,在这里进行清理 // Improve focus export conversion of block refs to footnotes https://github.com/siyuan-note/siyuan/issues/10647 footnotesRefs := ret.Root.ChildrenByType(ast.NodeFootnotesRef) + for footnotesDef := footnotesDefBlock.FirstChild; nil != footnotesDef; footnotesDef = footnotesDef.Next { + fnRefsInDef := footnotesDef.ChildrenByType(ast.NodeFootnotesRef) + footnotesRefs = append(footnotesRefs, fnRefsInDef...) + } + for footnotesDef := footnotesDefBlock.FirstChild; nil != footnotesDef; footnotesDef = footnotesDef.Next { exist := false for _, ref := range footnotesRefs {