瀏覽代碼

:art: 导出 PDF 时支持将资源文件作为附件嵌入 https://github.com/siyuan-note/siyuan/issues/7414

Liang Ding 2 年之前
父節點
當前提交
a576708916
共有 5 個文件被更改,包括 54 次插入34 次删除
  1. 2 1
      app/src/util/onGetConfig.ts
  2. 2 1
      kernel/api/export.go
  3. 2 1
      kernel/go.mod
  4. 0 2
      kernel/go.sum
  5. 48 29
      kernel/model/export.go

+ 2 - 1
app/src/util/onGetConfig.ts

@@ -421,7 +421,8 @@ export const initWindow = () => {
                         fetchPost("/api/export/processPDF", {
                         fetchPost("/api/export/processPDF", {
                             id: ipcData.rootId,
                             id: ipcData.rootId,
                             merge: ipcData.mergeSubdocs,
                             merge: ipcData.mergeSubdocs,
-                            path: pdfFilePath
+                            path: pdfFilePath,
+                            removeAssets: ipcData.removeAssets,
                         }, () => {
                         }, () => {
                             afterExport(pdfFilePath, msgId);
                             afterExport(pdfFilePath, msgId);
                             if (ipcData.removeAssets) {
                             if (ipcData.removeAssets) {

+ 2 - 1
kernel/api/export.go

@@ -326,7 +326,8 @@ func processPDF(c *gin.Context) {
 	if nil != arg["merge"] {
 	if nil != arg["merge"] {
 		merge = arg["merge"].(bool)
 		merge = arg["merge"].(bool)
 	}
 	}
-	err := model.ProcessPDF(id, path, merge)
+	removeAssets := arg["removeAssets"].(bool)
+	err := model.ProcessPDF(id, path, merge, removeAssets)
 	if nil != err {
 	if nil != err {
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()

+ 2 - 1
kernel/go.mod

@@ -141,6 +141,7 @@ replace github.com/mattn/go-sqlite3 => github.com/88250/go-sqlite3 v1.14.13-0.20
 //replace github.com/siyuan-note/httpclient => D:\88250\httpclient
 //replace github.com/siyuan-note/httpclient => D:\88250\httpclient
 //replace github.com/siyuan-note/filelock => D:\88250\filelock
 //replace github.com/siyuan-note/filelock => D:\88250\filelock
 //replace github.com/88250/lute => D:\gogogo\src\github.com\88250\lute
 //replace github.com/88250/lute => D:\gogogo\src\github.com\88250\lute
-//replace github.com/88250/pdfcpu => D:\88250\pdfcpu
+replace github.com/88250/pdfcpu => D:\88250\pdfcpu
+
 //replace github.com/88250/gulu => D:\88250\gulu
 //replace github.com/88250/gulu => D:\88250\gulu
 //replace github.com/mattn/go-sqlite3 => D:\88250\go-sqlite3
 //replace github.com/mattn/go-sqlite3 => D:\88250\go-sqlite3

+ 0 - 2
kernel/go.sum

@@ -10,8 +10,6 @@ github.com/88250/gulu v1.2.3-0.20221117052724-cd06804db798 h1:sR/s/Y9wyl79ZRCUER
 github.com/88250/gulu v1.2.3-0.20221117052724-cd06804db798/go.mod h1:I1qBzsksFL2ciGSuqDE7R3XW4BUMrfDgOvSXEk7FsAI=
 github.com/88250/gulu v1.2.3-0.20221117052724-cd06804db798/go.mod h1:I1qBzsksFL2ciGSuqDE7R3XW4BUMrfDgOvSXEk7FsAI=
 github.com/88250/lute v1.7.6-0.20230220030205-b0f64d7ba66e h1:7UgFzsksh+z6IX2z+BKG3tt1TU7LJNb0zOHDbhLEaUc=
 github.com/88250/lute v1.7.6-0.20230220030205-b0f64d7ba66e h1:7UgFzsksh+z6IX2z+BKG3tt1TU7LJNb0zOHDbhLEaUc=
 github.com/88250/lute v1.7.6-0.20230220030205-b0f64d7ba66e/go.mod h1:cEoBGi0zArPqAsp0MdG9SKinvH/xxZZWXU7sRx8vHSA=
 github.com/88250/lute v1.7.6-0.20230220030205-b0f64d7ba66e/go.mod h1:cEoBGi0zArPqAsp0MdG9SKinvH/xxZZWXU7sRx8vHSA=
-github.com/88250/pdfcpu v0.3.14-0.20230223023428-417e2a8897ac h1:deLsfAbzg+KJy53yJDGNe/+9RZr6RR813rbMKOiW/uI=
-github.com/88250/pdfcpu v0.3.14-0.20230223023428-417e2a8897ac/go.mod h1:S5YT38L/GCjVjmB4PB84PymA1qfopjEhfhTNQilLpv4=
 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY=
 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY=
 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1/go.mod h1:U3pckKQIgxxkmZjV5yXQjHdGxQK0o/vEZeZ6cQsxfHw=
 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1/go.mod h1:U3pckKQIgxxkmZjV5yXQjHdGxQK0o/vEZeZ6cQsxfHw=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=

+ 48 - 29
kernel/model/export.go

@@ -654,7 +654,7 @@ func processIFrame(tree *parse.Tree) {
 	}
 	}
 }
 }
 
 
-func ProcessPDF(id, p string, merge bool) (err error) {
+func ProcessPDF(id, p string, merge, removeAssets bool) (err error) {
 	inFile := p
 	inFile := p
 	links, err := api.ListToCLinks(inFile)
 	links, err := api.ListToCLinks(inFile)
 	if nil != err {
 	if nil != err {
@@ -665,8 +665,6 @@ func ProcessPDF(id, p string, merge bool) (err error) {
 		return links[i].Page < links[j].Page
 		return links[i].Page < links[j].Page
 	})
 	})
 
 
-	pdfcpu.VersionStr = "SiYuan v" + util.Ver
-
 	bms := map[string]*pdfcpu.Bookmark{}
 	bms := map[string]*pdfcpu.Bookmark{}
 	for _, link := range links {
 	for _, link := range links {
 		linkID := link.URI[strings.LastIndex(link.URI, "/")+1:]
 		linkID := link.URI[strings.LastIndex(link.URI, "/")+1:]
@@ -774,38 +772,51 @@ func ProcessPDF(id, p string, merge bool) (err error) {
 		}
 		}
 	}
 	}
 
 
+	pdfCtx, ctxErr := api.ReadContextFile(inFile)
+	if nil != ctxErr {
+		logging.LogErrorf("read pdf context failed: %s", ctxErr)
+		return
+	}
+
 	if 0 < len(assetAbsPaths) {
 	if 0 < len(assetAbsPaths) {
-		//outFile := inFile + ".tmp"
-		//err = api.AddAttachmentsFile(inFile, outFile, assetAbsPaths, false, nil)
-		//if nil != err {
-		//	logging.LogErrorf("add attachment failed: %s", err)
-		//	return
-		//}
-		//
-		//err = os.Rename(outFile, inFile)
-		//if nil != err {
-		//	return
-		//}
-
-		assetLinks, listErr := api.ListAssetLinks(inFile)
+		assetLinks, otherLinks, listErr := api.ListLinks(inFile)
 		if nil != listErr {
 		if nil != listErr {
 			logging.LogErrorf("list asset links failed: %s", listErr)
 			logging.LogErrorf("list asset links failed: %s", listErr)
 			return
 			return
 		}
 		}
 
 
-		pdfCtx, ctxErr := api.ReadContextFile(inFile)
-		if nil != ctxErr {
-			logging.LogErrorf("read pdf context failed: %s", ctxErr)
-			return
+		if _, removeErr := pdfCtx.RemoveAnnotations(nil, nil, nil, false); nil != removeErr {
+			logging.LogWarnf("remove annotations failed: %s", removeErr)
 		}
 		}
 
 
-		linkMap := map[int][]*pdfcpu.IndirectRef{}
-		pdfCtx.RemoveAnnotations(nil, nil, nil, false)
+		linkMap := map[int][]pdfcpu.AnnotationRenderer{}
+		for _, link := range otherLinks {
+			if 1 > len(linkMap[link.Page]) {
+				linkMap[link.Page] = []pdfcpu.AnnotationRenderer{link}
+			} else {
+				linkMap[link.Page] = append(linkMap[link.Page], link)
+			}
+		}
+
+		attachementMap := map[int][]*pdfcpu.IndirectRef{}
 		now := pdfcpu.StringLiteral(pdfcpu.DateString(time.Now()))
 		now := pdfcpu.StringLiteral(pdfcpu.DateString(time.Now()))
 		for _, link := range assetLinks {
 		for _, link := range assetLinks {
 			link.URI = strings.ReplaceAll(link.URI, "http://127.0.0.1:6806/export/temp/", "")
 			link.URI = strings.ReplaceAll(link.URI, "http://127.0.0.1:6806/export/temp/", "")
 			link.URI, _ = url.PathUnescape(link.URI)
 			link.URI, _ = url.PathUnescape(link.URI)
 
 
+			if !removeAssets {
+				// 不移除资源文件夹的话将超链接指向资源文件夹
+				if 1 > len(linkMap[link.Page]) {
+					linkMap[link.Page] = []pdfcpu.AnnotationRenderer{link}
+				} else {
+					linkMap[link.Page] = append(linkMap[link.Page], link)
+				}
+
+				continue
+			}
+
+			// 移除资源文件夹的话使用内嵌附件
+
 			absPath, getErr := GetAssetAbsPath(link.URI)
 			absPath, getErr := GetAssetAbsPath(link.URI)
 			if nil != getErr {
 			if nil != getErr {
 				continue
 				continue
@@ -873,13 +884,20 @@ func ProcessPDF(id, p string, merge bool) (err error) {
 			}
 			}
 
 
 			if 1 > len(linkMap[link.Page]) {
 			if 1 > len(linkMap[link.Page]) {
-				linkMap[link.Page] = []*pdfcpu.IndirectRef{ann}
+				attachementMap[link.Page] = []*pdfcpu.IndirectRef{ann}
 			} else {
 			} else {
-				linkMap[link.Page] = append(linkMap[link.Page], ann)
+				attachementMap[link.Page] = append(attachementMap[link.Page], ann)
 			}
 			}
 		}
 		}
 
 
-		for page, anns := range linkMap {
+		if 0 < len(linkMap) {
+			if _, addErr := pdfCtx.AddAnnotationsMap(linkMap, false); nil != addErr {
+				logging.LogErrorf("add annotations map failed: %s", addErr)
+			}
+		}
+
+		// 添加附件注解指向内嵌的附件
+		for page, anns := range attachementMap {
 			pageDictIndRef, pageErr := pdfCtx.PageDictIndRef(page)
 			pageDictIndRef, pageErr := pdfCtx.PageDictIndRef(page)
 			if nil != pageErr {
 			if nil != pageErr {
 				logging.LogWarnf("page dict ind ref failed: %s", pageErr)
 				logging.LogWarnf("page dict ind ref failed: %s", pageErr)
@@ -926,11 +944,12 @@ func ProcessPDF(id, p string, merge bool) (err error) {
 			entry.Object = append(annots, array...)
 			entry.Object = append(annots, array...)
 			pdfCtx.EnsureVersionForWriting()
 			pdfCtx.EnsureVersionForWriting()
 		}
 		}
+	}
 
 
-		if writeErr := api.WriteContextFile(pdfCtx, inFile); nil != writeErr {
-			logging.LogErrorf("write pdf context failed: %s", writeErr)
-			return
-		}
+	pdfcpu.VersionStr = "SiYuan v" + util.Ver
+	if writeErr := api.WriteContextFile(pdfCtx, inFile); nil != writeErr {
+		logging.LogErrorf("write pdf context failed: %s", writeErr)
+		return
 	}
 	}
 
 
 	return
 	return