mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-02-25 00:14:07 +01:00
🎨 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>
This commit is contained in:
parent
cdf60c1105
commit
ca24bea936
5 changed files with 51 additions and 40 deletions
|
|
@ -177,7 +177,7 @@ func DocAssets(rootID string) (ret []string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
ret = getAssetsLinkDests(tree.Root)
|
||||
ret = getAssetsLinkDests(tree.Root, false)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -521,7 +521,7 @@ func UploadAssets2Cloud(id string, ignorePushMsg bool) (count int, err error) {
|
|||
|
||||
var assets []string
|
||||
for _, n := range nodes {
|
||||
assets = append(assets, getAssetsLinkDests(n)...)
|
||||
assets = append(assets, getAssetsLinkDests(n, false)...)
|
||||
assets = append(assets, getQueryEmbedNodesAssetsLinkDests(n)...)
|
||||
}
|
||||
assets = gulu.Str.RemoveDuplicatedElem(assets)
|
||||
|
|
@ -937,13 +937,13 @@ func UnusedAssets() (ret []string) {
|
|||
trees = append(trees, tree)
|
||||
}
|
||||
for _, tree := range trees {
|
||||
for _, d := range getAssetsLinkDests(tree.Root) {
|
||||
for _, d := range getAssetsLinkDests(tree.Root, false) {
|
||||
dests[d] = true
|
||||
}
|
||||
|
||||
if titleImgPath := treenode.GetDocTitleImgPath(tree.Root); "" != titleImgPath {
|
||||
// 题头图计入
|
||||
if !util.IsAssetLinkDest([]byte(titleImgPath)) {
|
||||
if !util.IsAssetLinkDest([]byte(titleImgPath), false) {
|
||||
continue
|
||||
}
|
||||
dests[titleImgPath] = true
|
||||
|
|
@ -1100,13 +1100,13 @@ func MissingAssets() (ret []string) {
|
|||
trees = append(trees, tree)
|
||||
}
|
||||
for _, tree := range trees {
|
||||
for _, d := range getAssetsLinkDests(tree.Root) {
|
||||
for _, d := range getAssetsLinkDests(tree.Root, false) {
|
||||
dests[d] = true
|
||||
}
|
||||
|
||||
if titleImgPath := treenode.GetDocTitleImgPath(tree.Root); "" != titleImgPath {
|
||||
// 题头图计入
|
||||
if !util.IsAssetLinkDest([]byte(titleImgPath)) {
|
||||
if !util.IsAssetLinkDest([]byte(titleImgPath), false) {
|
||||
continue
|
||||
}
|
||||
dests[titleImgPath] = true
|
||||
|
|
@ -1204,7 +1204,7 @@ func getQueryEmbedNodesAssetsLinkDests(node *ast.Node) (ret []string) {
|
|||
continue
|
||||
}
|
||||
|
||||
ret = append(ret, getAssetsLinkDests(embedNode)...)
|
||||
ret = append(ret, getAssetsLinkDests(embedNode, false)...)
|
||||
}
|
||||
return ast.WalkContinue
|
||||
})
|
||||
|
|
@ -1212,7 +1212,7 @@ func getQueryEmbedNodesAssetsLinkDests(node *ast.Node) (ret []string) {
|
|||
return
|
||||
}
|
||||
|
||||
func getAssetsLinkDests(node *ast.Node) (ret []string) {
|
||||
func getAssetsLinkDests(node *ast.Node, includePublic bool) (ret []string) {
|
||||
ret = []string{}
|
||||
ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||
if n.IsBlock() {
|
||||
|
|
@ -1222,7 +1222,7 @@ func getAssetsLinkDests(node *ast.Node) (ret []string) {
|
|||
k := kv[0]
|
||||
if strings.HasPrefix(k, "custom-data-assets") {
|
||||
dest := kv[1]
|
||||
if "" == dest || !util.IsAssetLinkDest([]byte(dest)) {
|
||||
if "" == dest || !util.IsAssetLinkDest([]byte(dest), includePublic) {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, dest)
|
||||
|
|
@ -1238,21 +1238,21 @@ func getAssetsLinkDests(node *ast.Node) (ret []string) {
|
|||
}
|
||||
|
||||
if ast.NodeLinkDest == n.Type {
|
||||
if !util.IsAssetLinkDest(n.Tokens) {
|
||||
if !util.IsAssetLinkDest(n.Tokens, includePublic) {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
dest := strings.TrimSpace(string(n.Tokens))
|
||||
ret = append(ret, dest)
|
||||
} else if n.IsTextMarkType("a") {
|
||||
if !util.IsAssetLinkDest(gulu.Str.ToBytes(n.TextMarkAHref)) {
|
||||
if !util.IsAssetLinkDest(gulu.Str.ToBytes(n.TextMarkAHref), includePublic) {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
dest := strings.TrimSpace(n.TextMarkAHref)
|
||||
ret = append(ret, dest)
|
||||
} else if n.IsTextMarkType("file-annotation-ref") {
|
||||
if !util.IsAssetLinkDest(gulu.Str.ToBytes(n.TextMarkFileAnnotationRefID)) {
|
||||
if !util.IsAssetLinkDest(gulu.Str.ToBytes(n.TextMarkFileAnnotationRefID), includePublic) {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
|
|
@ -1278,7 +1278,7 @@ func getAssetsLinkDests(node *ast.Node) (ret []string) {
|
|||
|
||||
for _, asset := range value.MAsset {
|
||||
dest := asset.Content
|
||||
if !util.IsAssetLinkDest([]byte(dest)) {
|
||||
if !util.IsAssetLinkDest([]byte(dest), includePublic) {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, strings.TrimSpace(dest))
|
||||
|
|
@ -1288,7 +1288,7 @@ func getAssetsLinkDests(node *ast.Node) (ret []string) {
|
|||
for _, value := range keyValues.Values {
|
||||
if nil != value.URL {
|
||||
dest := value.URL.Content
|
||||
if !util.IsAssetLinkDest([]byte(dest)) {
|
||||
if !util.IsAssetLinkDest([]byte(dest), includePublic) {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, strings.TrimSpace(dest))
|
||||
|
|
@ -1303,13 +1303,13 @@ func getAssetsLinkDests(node *ast.Node) (ret []string) {
|
|||
// 兼容两种属性名 custom-data-assets 和 data-assets https://github.com/siyuan-note/siyuan/issues/4122#issuecomment-1154796568
|
||||
dataAssets = n.IALAttr("data-assets")
|
||||
}
|
||||
if !util.IsAssetLinkDest([]byte(dataAssets)) {
|
||||
if !util.IsAssetLinkDest([]byte(dataAssets), includePublic) {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
ret = append(ret, dataAssets)
|
||||
} else { // HTMLBlock/InlineHTML/IFrame/Audio/Video
|
||||
dest := treenode.GetNodeSrcTokens(n)
|
||||
if !util.IsAssetLinkDest([]byte(dest)) {
|
||||
if !util.IsAssetLinkDest([]byte(dest), includePublic) {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
ret = append(ret, dest)
|
||||
|
|
@ -1379,7 +1379,7 @@ func getRemoteAssetsLinkDests(node *ast.Node, onlyImg bool) (ret []string) {
|
|||
if onlyImg {
|
||||
if ast.NodeLinkDest == node.Type {
|
||||
if node.ParentIs(ast.NodeImage) {
|
||||
if !util.IsAssetLinkDest(node.Tokens) {
|
||||
if !util.IsAssetLinkDest(node.Tokens, false) {
|
||||
ret = append(ret, string(node.Tokens))
|
||||
}
|
||||
|
||||
|
|
@ -1406,7 +1406,7 @@ func getRemoteAssetsLinkDests(node *ast.Node, onlyImg bool) (ret []string) {
|
|||
}
|
||||
|
||||
dest := asset.Content
|
||||
if !util.IsAssetLinkDest([]byte(dest)) {
|
||||
if !util.IsAssetLinkDest([]byte(dest), false) {
|
||||
ret = append(ret, strings.TrimSpace(dest))
|
||||
}
|
||||
}
|
||||
|
|
@ -1415,16 +1415,16 @@ func getRemoteAssetsLinkDests(node *ast.Node, onlyImg bool) (ret []string) {
|
|||
}
|
||||
} else {
|
||||
if ast.NodeLinkDest == node.Type {
|
||||
if !util.IsAssetLinkDest(node.Tokens) {
|
||||
if !util.IsAssetLinkDest(node.Tokens, false) {
|
||||
ret = append(ret, string(node.Tokens))
|
||||
}
|
||||
} else if node.IsTextMarkType("a") {
|
||||
if !util.IsAssetLinkDest([]byte(node.TextMarkAHref)) {
|
||||
if !util.IsAssetLinkDest([]byte(node.TextMarkAHref), false) {
|
||||
ret = append(ret, node.TextMarkAHref)
|
||||
}
|
||||
} else if ast.NodeAudio == node.Type || ast.NodeVideo == node.Type {
|
||||
src := treenode.GetNodeSrcTokens(node)
|
||||
if !util.IsAssetLinkDest([]byte(src)) {
|
||||
if !util.IsAssetLinkDest([]byte(src), false) {
|
||||
ret = append(ret, src)
|
||||
}
|
||||
} else if ast.NodeAttributeView == node.Type {
|
||||
|
|
@ -1445,7 +1445,7 @@ func getRemoteAssetsLinkDests(node *ast.Node, onlyImg bool) (ret []string) {
|
|||
|
||||
for _, asset := range value.MAsset {
|
||||
dest := asset.Content
|
||||
if !util.IsAssetLinkDest([]byte(dest)) {
|
||||
if !util.IsAssetLinkDest([]byte(dest), false) {
|
||||
ret = append(ret, strings.TrimSpace(dest))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ func Export2Liandi(id string) (err error) {
|
|||
return errors.New(Conf.Language(204))
|
||||
}
|
||||
|
||||
assets := getAssetsLinkDests(tree.Root)
|
||||
assets := getAssetsLinkDests(tree.Root, false)
|
||||
embedAssets := getQueryEmbedNodesAssetsLinkDests(tree.Root)
|
||||
assets = append(assets, embedAssets...)
|
||||
assets = gulu.Str.RemoveDuplicatedElem(assets)
|
||||
|
|
@ -795,9 +795,20 @@ func ExportMarkdownHTML(id, savePath string, docx, merge bool) (name, dom string
|
|||
return
|
||||
}
|
||||
|
||||
assets := getAssetsLinkDests(tree.Root)
|
||||
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("/"))
|
||||
}
|
||||
}
|
||||
return ast.WalkContinue
|
||||
})
|
||||
}
|
||||
|
||||
assets := getAssetsLinkDests(tree.Root, docx)
|
||||
for _, asset := range assets {
|
||||
if strings.HasPrefix(asset, "assets/") {
|
||||
if strings.HasPrefix(asset, "assets/") || strings.HasPrefix(asset, "public/") {
|
||||
if strings.Contains(asset, "?") {
|
||||
asset = asset[:strings.LastIndex(asset, "?")]
|
||||
}
|
||||
|
|
@ -991,7 +1002,7 @@ func ExportHTML(id, savePath string, pdf, image, keepFold, merge bool) (name, do
|
|||
return
|
||||
}
|
||||
|
||||
assets := getAssetsLinkDests(tree.Root)
|
||||
assets := getAssetsLinkDests(tree.Root, false)
|
||||
for _, asset := range assets {
|
||||
if strings.Contains(asset, "?") {
|
||||
asset = asset[:strings.LastIndex(asset, "?")]
|
||||
|
|
@ -1174,7 +1185,7 @@ func ProcessPDF(id, p string, merge, removeAssets, watermark bool) (err error) {
|
|||
}
|
||||
|
||||
var headings []*ast.Node
|
||||
assetDests := getAssetsLinkDests(tree.Root)
|
||||
assetDests := getAssetsLinkDests(tree.Root, false)
|
||||
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||
if !entering {
|
||||
return ast.WalkContinue
|
||||
|
|
@ -1874,10 +1885,10 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
|
|||
copiedAssets := hashset.New()
|
||||
for _, tree := range trees {
|
||||
var assets []string
|
||||
assets = append(assets, getAssetsLinkDests(tree.Root)...)
|
||||
assets = append(assets, getAssetsLinkDests(tree.Root, false)...)
|
||||
titleImgPath := treenode.GetDocTitleImgPath(tree.Root) // Export .sy.zip doc title image is not exported https://github.com/siyuan-note/siyuan/issues/8748
|
||||
if "" != titleImgPath {
|
||||
if util.IsAssetLinkDest([]byte(titleImgPath)) {
|
||||
if util.IsAssetLinkDest([]byte(titleImgPath), false) {
|
||||
assets = append(assets, titleImgPath)
|
||||
}
|
||||
}
|
||||
|
|
@ -2073,7 +2084,7 @@ func exportAv(avID, exportStorageAvDir, exportFolder string, assetPathMap map[st
|
|||
case av.KeyTypeMAsset: // 导出资源文件列 https://github.com/siyuan-note/siyuan/issues/9919
|
||||
for _, value := range keyValues.Values {
|
||||
for _, asset := range value.MAsset {
|
||||
if !util.IsAssetLinkDest([]byte(asset.Content)) {
|
||||
if !util.IsAssetLinkDest([]byte(asset.Content), false) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -2218,17 +2229,17 @@ func exportMarkdownContent0(id string, tree *parse.Tree, cloudAssetsBase string,
|
|||
}
|
||||
|
||||
if ast.NodeLinkDest == n.Type {
|
||||
if util.IsAssetLinkDest(n.Tokens) {
|
||||
if util.IsAssetLinkDest(n.Tokens, false) {
|
||||
n.Tokens = bytes.ReplaceAll(n.Tokens, []byte(" "), []byte("_"))
|
||||
}
|
||||
} else if n.IsTextMarkType("a") {
|
||||
href := n.TextMarkAHref
|
||||
if util.IsAssetLinkDest([]byte(href)) {
|
||||
if util.IsAssetLinkDest([]byte(href), false) {
|
||||
n.TextMarkAHref = strings.ReplaceAll(href, " ", "_")
|
||||
}
|
||||
} else if ast.NodeIFrame == n.Type || ast.NodeAudio == n.Type || ast.NodeVideo == n.Type {
|
||||
dest := treenode.GetNodeSrcTokens(n)
|
||||
if util.IsAssetLinkDest([]byte(dest)) {
|
||||
if util.IsAssetLinkDest([]byte(dest), false) {
|
||||
setAssetsLinkDest(n, dest, strings.ReplaceAll(dest, " ", "_"))
|
||||
}
|
||||
}
|
||||
|
|
@ -3353,7 +3364,7 @@ func exportPandocConvertZip(baseFolderName string, docPaths, defBlockIDs []strin
|
|||
// 解析导出后的标准 Markdown,汇总 assets
|
||||
tree = parse.Parse("", gulu.Str.ToBytes(md), luteEngine.ParseOptions)
|
||||
var assets []string
|
||||
assets = append(assets, getAssetsLinkDests(tree.Root)...)
|
||||
assets = append(assets, getAssetsLinkDests(tree.Root, false)...)
|
||||
for _, asset := range assets {
|
||||
asset = string(html.DecodeDestination([]byte(asset)))
|
||||
if strings.Contains(asset, "?") {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ func docTagSpans(n *ast.Node) (ret []*Span) {
|
|||
|
||||
func docTitleImgAsset(root *ast.Node, boxLocalPath, docDirLocalPath string) *Asset {
|
||||
if p := treenode.GetDocTitleImgPath(root); "" != p {
|
||||
if !util.IsAssetLinkDest([]byte(p)) {
|
||||
if !util.IsAssetLinkDest([]byte(p), false) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) (
|
|||
|
||||
// assetsLinkDestsInTree
|
||||
|
||||
if !util.IsAssetLinkDest(destNode.Tokens) {
|
||||
if !util.IsAssetLinkDest(destNode.Tokens, false) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -686,7 +686,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) (
|
|||
|
||||
if n.IsTextMarkType("a") {
|
||||
dest := n.TextMarkAHref
|
||||
if util.IsAssetLinkDest([]byte(dest)) {
|
||||
if util.IsAssetLinkDest([]byte(dest), false) {
|
||||
var title string
|
||||
if titleNode := n.ChildByType(ast.NodeLinkTitle); nil != titleNode {
|
||||
title = gulu.Str.FromBytes(titleNode.Tokens)
|
||||
|
|
@ -776,7 +776,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) (
|
|||
return
|
||||
}
|
||||
|
||||
if !util.IsAssetLinkDest(src) {
|
||||
if !util.IsAssetLinkDest(src, false) {
|
||||
walkStatus = ast.WalkContinue
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,8 +316,8 @@ func FilterSelfChildDocs(paths []string) (ret []string) {
|
|||
return
|
||||
}
|
||||
|
||||
func IsAssetLinkDest(dest []byte) bool {
|
||||
return bytes.HasPrefix(dest, []byte("assets/"))
|
||||
func IsAssetLinkDest(dest []byte, includePublic bool) bool {
|
||||
return bytes.HasPrefix(dest, []byte("assets/")) || (includePublic && bytes.HasPrefix(dest, []byte("public/")))
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue