From 4bc9d9496e95fddfe2e6d28a7bd755870baaeb2e Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Mon, 12 Jan 2026 11:56:16 +0800 Subject: [PATCH 1/3] :art: Improve handling of assets when exporting to Word .docx format https://github.com/siyuan-note/siyuan/issues/15253 Signed-off-by: Daniel <845765@qq.com> --- kernel/model/assets.go | 43 +++++++++++++++++++++++++----------------- kernel/model/export.go | 16 +++------------- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/kernel/model/assets.go b/kernel/model/assets.go index 984b70d98..a7586768d 100644 --- a/kernel/model/assets.go +++ b/kernel/model/assets.go @@ -187,10 +187,6 @@ func NetAssets2LocalAssets(rootID string, onlyImg bool, originalURL string) (err return } - var files int - var size int64 - msgId := gulu.Rand.String(7) - docDirLocalPath := filepath.Join(util.DataDir, tree.Box, path.Dir(tree.Path)) assetsDirPath := getAssetsDir(filepath.Join(util.DataDir, tree.Box), docDirLocalPath) if !gulu.File.IsExist(assetsDirPath) { @@ -199,6 +195,15 @@ func NetAssets2LocalAssets(rootID string, onlyImg bool, originalURL string) (err } } + err = netAssets2LocalAssets0(tree, onlyImg, originalURL, assetsDirPath, true) + return +} + +func netAssets2LocalAssets0(tree *parse.Tree, onlyImg bool, originalURL string, assetsDirPath string, needWriteTree bool) (err error) { + var files int + var size int64 + msgId := gulu.Rand.String(7) + browserClient := util.NewCustomReqClient() // 自定义了 TLS 指纹,增加下载成功率 forbiddenCount := 0 @@ -284,6 +289,7 @@ func NetAssets2LocalAssets(rootID string, onlyImg bool, originalURL string) (err if 64 < len(displayU) { displayU = displayU[:64] + "..." } + util.PushUpdateMsg(msgId, fmt.Sprintf(Conf.Language(119), displayU), 15000) request := browserClient.R() request.SetRetryCount(1).SetRetryFixedInterval(3 * time.Second) @@ -365,21 +371,24 @@ func NetAssets2LocalAssets(rootID string, onlyImg bool, originalURL string) (err } util.PushClearMsg(msgId) - if 0 < files { - msgId = util.PushMsg(Conf.Language(113), 7000) - if err = writeTreeUpsertQueue(tree); err != nil { - return - } - util.PushUpdateMsg(msgId, fmt.Sprintf(Conf.Language(120), files, humanize.BytesCustomCeil(uint64(size), 2)), 5000) - if 0 < forbiddenCount { - util.PushErrMsg(fmt.Sprintf(Conf.Language(255), forbiddenCount), 5000) - } - } else { - if 0 < forbiddenCount { - util.PushErrMsg(fmt.Sprintf(Conf.Language(255), forbiddenCount), 5000) + if needWriteTree { + if 0 < files { + msgId = util.PushMsg(Conf.Language(113), 7000) + if err = writeTreeUpsertQueue(tree); err != nil { + return + } + util.PushUpdateMsg(msgId, fmt.Sprintf(Conf.Language(120), files, humanize.BytesCustomCeil(uint64(size), 2)), 5000) + + if 0 < forbiddenCount { + util.PushErrMsg(fmt.Sprintf(Conf.Language(255), forbiddenCount), 5000) + } } else { - util.PushMsg(Conf.Language(121), 3000) + if 0 < forbiddenCount { + util.PushErrMsg(fmt.Sprintf(Conf.Language(255), forbiddenCount), 5000) + } else { + util.PushMsg(Conf.Language(121), 3000) + } } } return diff --git a/kernel/model/export.go b/kernel/model/export.go index eebb188e9..de0eb3370 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -716,7 +716,7 @@ func ExportDocx(id, savePath string, removeAssets, merge bool) (fullPath string, content = strings.ReplaceAll(content, " \n", "
\n") tmpDocxPath := filepath.Join(tmpDir, name+".docx") - args := []string{ // pandoc -f html --resource-path=请从这里开始 请从这里开始\index.html -o test.docx + args := []string{ "-f", "html+tex_math_dollars", "--resource-path", tmpDir, "-o", tmpDocxPath, @@ -796,17 +796,7 @@ func ExportMarkdownHTML(id, savePath string, docx, merge bool) (name, dom string } if docx { - ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { - if ast.NodeLinkDest == n.Type { - if bytes.HasPrefix(n.Tokens, []byte("file://")) { - n.Tokens = bytes.ReplaceAll(n.Tokens, []byte("\\"), []byte("/")) - if !bytes.HasPrefix(n.Tokens, []byte("file:///")) { - n.Tokens = bytes.ReplaceAll(n.Tokens, []byte("file://"), []byte("file:///")) - } - } - } - return ast.WalkContinue - }) + netAssets2LocalAssets0(tree, true, "", filepath.Join(savePath, "assets"), false) } assets := getAssetsLinkDests(tree.Root, docx) @@ -814,7 +804,7 @@ func ExportMarkdownHTML(id, savePath string, docx, merge bool) (name, dom string if !util.IsAssetLinkDest([]byte(asset), docx) { continue } - + if strings.Contains(asset, "?") { asset = asset[:strings.LastIndex(asset, "?")] } From 5c85f67e49072630b470ab390cb4d7c9cf8b4a0b Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Mon, 12 Jan 2026 12:05:56 +0800 Subject: [PATCH 2/3] :art: https://github.com/siyuan-note/siyuan/issues/14800#issuecomment-3736650990 Signed-off-by: Daniel <845765@qq.com> --- kernel/model/export.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/model/export.go b/kernel/model/export.go index de0eb3370..6cb09acb9 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -95,6 +95,8 @@ func ExportCodeBlock(blockID string) (filePath string, err error) { return } + code.Tokens = bytes.ReplaceAll(code.Tokens, []byte(editor.Zwj+"```"), []byte("```")) + writePath := filepath.Join(exportFolder, name) err = filelock.WriteFile(writePath, code.Tokens) if nil != err { From 568d396a902d8e84ac869438b33313557e878f35 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Mon, 12 Jan 2026 12:21:23 +0800 Subject: [PATCH 3/3] :bug: Fix https://github.com/siyuan-note/siyuan/issues/16815 Signed-off-by: Daniel <845765@qq.com> --- kernel/av/av.go | 11 ++++++----- kernel/model/attribute_view_render.go | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/kernel/av/av.go b/kernel/av/av.go index e8eb15cfa..9af93258b 100644 --- a/kernel/av/av.go +++ b/kernel/av/av.go @@ -410,11 +410,12 @@ type Viewable interface { func NewAttributeView(id string) (ret *AttributeView) { view, blockKey, selectKey := NewTableViewWithBlockKey(ast.NewNodeID()) ret = &AttributeView{ - Spec: CurrentSpec, - ID: id, - KeyValues: []*KeyValues{{Key: blockKey}, {Key: selectKey}}, - ViewID: view.ID, - Views: []*View{view}, + Spec: CurrentSpec, + ID: id, + KeyValues: []*KeyValues{{Key: blockKey}, {Key: selectKey}}, + ViewID: view.ID, + Views: []*View{view}, + RenderedViewables: map[string]Viewable{}, } return } diff --git a/kernel/model/attribute_view_render.go b/kernel/model/attribute_view_render.go index 49591cbf1..cb2c44bcf 100644 --- a/kernel/model/attribute_view_render.go +++ b/kernel/model/attribute_view_render.go @@ -502,7 +502,7 @@ func RenderRepoSnapshotAttributeView(indexID, avID string) (viewable av.Viewable return } - attrView = &av.AttributeView{RenderedViewables: map[string]av.Viewable{}} + attrView = av.NewAttributeView(avID) if err = gulu.JSON.UnmarshalJSON(data, attrView); err != nil { logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err) return @@ -547,7 +547,7 @@ func RenderHistoryAttributeView(blockID, avID, viewID, query string, page, pageS return } - attrView = &av.AttributeView{RenderedViewables: map[string]av.Viewable{}} + attrView = av.NewAttributeView(avID) if err = gulu.JSON.UnmarshalJSON(data, attrView); err != nil { logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err) return