mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-05-17 17:40:42 +08:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
d59c131170
12
API.md
12
API.md
@ -457,13 +457,12 @@ View API token in <kbd>Settings - About</kbd>, request header: `Authorization: T
|
|||||||
* `/api/asset/upload`
|
* `/api/asset/upload`
|
||||||
* The parameter is an HTTP Multipart form
|
* The parameter is an HTTP Multipart form
|
||||||
|
|
||||||
* `assetsDirPath`: The folder path where the assets are stored. The arguments have the following three cases
|
* `assetsDirPath`: The folder path where assets are stored, with the data folder as the root path, for example:
|
||||||
|
* `"/assets/"`: workspace/data/assets/ folder
|
||||||
|
* `"/assets/sub/"`: workspace/data/assets/sub/ folder
|
||||||
|
|
||||||
1. `"/assets/"`: Workspace/data/assets folder
|
Under normal circumstances, it is recommended to use the first method, which is stored in the assets folder
|
||||||
2. `"/Test Notebook/assets/"`: Assets folder under `Test Notebook`
|
of the workspace.
|
||||||
3. `"/Test Notebook/foo/assets/"`: Assets folder under foo folder under `Test notebook`
|
|
||||||
|
|
||||||
It is recommended to use the first one, which is stored in the workspace assets folder uniformly.
|
|
||||||
* `file[]`: Uploaded file list
|
* `file[]`: Uploaded file list
|
||||||
* Return value
|
* Return value
|
||||||
|
|
||||||
@ -814,6 +813,7 @@ View API token in <kbd>Settings - About</kbd>, request header: `Authorization: T
|
|||||||
"path": "F:\\SiYuan\\data\\templates\\foo.md"
|
"path": "F:\\SiYuan\\data\\templates\\foo.md"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
* `id`: The ID of the document where the rendering is called
|
* `id`: The ID of the document where the rendering is called
|
||||||
* `path`: Template file absolute path
|
* `path`: Template file absolute path
|
||||||
* Return value
|
* Return value
|
||||||
|
10
API_zh_CN.md
10
API_zh_CN.md
@ -454,13 +454,11 @@
|
|||||||
* `/api/asset/upload`
|
* `/api/asset/upload`
|
||||||
* 参数为 HTTP Multipart 表单
|
* 参数为 HTTP Multipart 表单
|
||||||
|
|
||||||
* `assetsDirPath`:资源文件存放的文件夹路径,实参有以下三种情况
|
* `assetsDirPath`:资源文件存放的文件夹路径,以 data 文件夹作为根路径,比如:
|
||||||
|
* `"/assets/"`:工作空间/data/assets/ 文件夹
|
||||||
|
* `"/assets/sub/"`:工作空间/data/assets/sub/ 文件夹
|
||||||
|
|
||||||
1. `"/assets/"`:工作空间/data/assets 文件夹
|
常规情况下建议用第一种,统一存放到工作空间资源文件夹下。
|
||||||
2. `"/测试笔记本/assets/"`:`测试笔记本`下的 assets 文件夹
|
|
||||||
3. `"/测试笔记本/foo/assets/"`:`测试笔记本`下 foo 文件夹下的 assets 文件夹
|
|
||||||
|
|
||||||
建议用第一种,统一存放到工作空间资源文件夹下。
|
|
||||||
* `file[]`:上传的文件列表
|
* `file[]`:上传的文件列表
|
||||||
* 返回值
|
* 返回值
|
||||||
|
|
||||||
|
@ -199,9 +199,10 @@
|
|||||||
"exportPDF1": "Landscape page",
|
"exportPDF1": "Landscape page",
|
||||||
"exportPDF2": "Page margins",
|
"exportPDF2": "Page margins",
|
||||||
"exportPDF3": "Page Scale",
|
"exportPDF3": "Page Scale",
|
||||||
"exportPDF4": "Remove assets directory",
|
"exportPDF4": "Embed assets",
|
||||||
"exportPDF5": "Keep folded",
|
"exportPDF5": "Keep folded",
|
||||||
"exportPDF6": "Merge subdocuments",
|
"mergeSubdocs": "Merge subdocuments",
|
||||||
|
"removeAssetsFolder": "Remove assets directory",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"reminderTip": "The reminder time cannot be less than the current time",
|
"reminderTip": "The reminder time cannot be less than the current time",
|
||||||
"wechatTip": "The content block will be sent to the cloud in clear text, and pushed through the WeChat MP template message when it expires",
|
"wechatTip": "The content block will be sent to the cloud in clear text, and pushed through the WeChat MP template message when it expires",
|
||||||
|
@ -199,9 +199,10 @@
|
|||||||
"exportPDF1": "Página apaisada",
|
"exportPDF1": "Página apaisada",
|
||||||
"exportPDF2": "Márgenes de la página",
|
"exportPDF2": "Márgenes de la página",
|
||||||
"exportPDF3": "Escala de la página",
|
"exportPDF3": "Escala de la página",
|
||||||
"exportPDF4": "Eliminar directorio de activos",
|
"exportPDF4": "Activos incrustados",
|
||||||
"exportPDF5": "Mantener doblado",
|
"exportPDF5": "Mantener doblado",
|
||||||
"exportPDF6": "Fusionar subdocumentos",
|
"mergeSubdocs": "Fusionar subdocumentos",
|
||||||
|
"removeAssetsFolder": "Eliminar directorio de activos",
|
||||||
"upload": "Subir",
|
"upload": "Subir",
|
||||||
"reminderTip": "La hora del recordatorio no puede ser inferior a la hora actual",
|
"reminderTip": "La hora del recordatorio no puede ser inferior a la hora actual",
|
||||||
"wechatTip": "El bloque de contenido se enviará a la nube en texto claro, y se empujará a través del mensaje de plantilla de WeChat MP cuando caduque",
|
"wechatTip": "El bloque de contenido se enviará a la nube en texto claro, y se empujará a través del mensaje de plantilla de WeChat MP cuando caduque",
|
||||||
|
@ -199,9 +199,10 @@
|
|||||||
"exportPDF1": "Page paysage",
|
"exportPDF1": "Page paysage",
|
||||||
"exportPDF2": "Marges de page",
|
"exportPDF2": "Marges de page",
|
||||||
"exportPDF3": "Échelle de page",
|
"exportPDF3": "Échelle de page",
|
||||||
"exportPDF4": "Supprimer le répertoire des actifs",
|
"exportPDF4": "Incorporer des ressources",
|
||||||
"exportPDF5": "Garder plié",
|
"exportPDF5": "Garder plié",
|
||||||
"exportPDF6": "Fusionner les sous-documents",
|
"mergeSubdocs": "Fusionner les sous-documents",
|
||||||
|
"removeAssetsFolder": "Supprimer le répertoire des actifs",
|
||||||
"upload": "Télécharger",
|
"upload": "Télécharger",
|
||||||
"reminderTip": "The reminder time cannot be less than the current time",
|
"reminderTip": "The reminder time cannot be less than the current time",
|
||||||
"wechatTip": "Le bloc de contenu sera envoyé au cloud en texte clair et transmis au message du modèle de compte officiel WeChat à son expiration.",
|
"wechatTip": "Le bloc de contenu sera envoyé au cloud en texte clair et transmis au message du modèle de compte officiel WeChat à son expiration.",
|
||||||
|
@ -199,9 +199,10 @@
|
|||||||
"exportPDF1": "橫向頁面",
|
"exportPDF1": "橫向頁面",
|
||||||
"exportPDF2": "頁面邊距",
|
"exportPDF2": "頁面邊距",
|
||||||
"exportPDF3": "頁面縮放",
|
"exportPDF3": "頁面縮放",
|
||||||
"exportPDF4": "移除 assets 目錄",
|
"exportPDF4": "嵌入資源文件",
|
||||||
"exportPDF5": "保持折疊狀態",
|
"exportPDF5": "保持折疊狀態",
|
||||||
"exportPDF6": "合併子文檔",
|
"mergeSubdocs": "合併子文檔",
|
||||||
|
"removeAssetsFolder": "移除 assets 目錄",
|
||||||
"upload": "上傳",
|
"upload": "上傳",
|
||||||
"reminderTip": "提醒時間不能小於當前時間",
|
"reminderTip": "提醒時間不能小於當前時間",
|
||||||
"wechatTip": "該內容塊將以明文形式發送到雲端,到期時通過微信公眾號模板消息進行推送",
|
"wechatTip": "該內容塊將以明文形式發送到雲端,到期時通過微信公眾號模板消息進行推送",
|
||||||
|
@ -199,9 +199,10 @@
|
|||||||
"exportPDF1": "横向页面",
|
"exportPDF1": "横向页面",
|
||||||
"exportPDF2": "页面边距",
|
"exportPDF2": "页面边距",
|
||||||
"exportPDF3": "页面缩放",
|
"exportPDF3": "页面缩放",
|
||||||
"exportPDF4": "移除 assets 目录",
|
"exportPDF4": "嵌入资源文件",
|
||||||
"exportPDF5": "保持折叠状态",
|
"exportPDF5": "保持折叠状态",
|
||||||
"exportPDF6": "合并子文档",
|
"mergeSubdocs": "合并子文档",
|
||||||
|
"removeAssetsFolder": "移除 assets 目录",
|
||||||
"upload": "上传",
|
"upload": "上传",
|
||||||
"reminderTip": "提醒时间不能小于当前时间",
|
"reminderTip": "提醒时间不能小于当前时间",
|
||||||
"wechatTip": "该内容块将以明文形式发送到云端,到期时通过微信公众号模板消息进行推送",
|
"wechatTip": "该内容块将以明文形式发送到云端,到期时通过微信公众号模板消息进行推送",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {hideMessage, showMessage} from "../../dialog/message";
|
import {hideMessage, showMessage} from "../../dialog/message";
|
||||||
import {Constants} from "../../constants";
|
import {Constants} from "../../constants";
|
||||||
/// #if !BROWSER
|
/// #if !BROWSER
|
||||||
import {OpenDialogReturnValue, ipcRenderer} from "electron";
|
import {ipcRenderer, OpenDialogReturnValue} from "electron";
|
||||||
import {app, BrowserWindow, dialog, getCurrentWindow} from "@electron/remote";
|
import {app, BrowserWindow, dialog, getCurrentWindow} from "@electron/remote";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
@ -33,14 +33,14 @@ export const saveExport = (option: { type: string, id: string }) => {
|
|||||||
content: `<div class="b3-dialog__content">
|
content: `<div class="b3-dialog__content">
|
||||||
<label class="fn__flex b3-label">
|
<label class="fn__flex b3-label">
|
||||||
<div class="fn__flex-1">
|
<div class="fn__flex-1">
|
||||||
${window.siyuan.languages.exportPDF4}
|
${window.siyuan.languages.removeAssetsFolder}
|
||||||
</div>
|
</div>
|
||||||
<span class="fn__space"></span>
|
<span class="fn__space"></span>
|
||||||
<input id="removeAssets" class="b3-switch" type="checkbox" ${localData.removeAssets ? "checked" : ""}>
|
<input id="removeAssets" class="b3-switch" type="checkbox" ${localData.removeAssets ? "checked" : ""}>
|
||||||
</label>
|
</label>
|
||||||
<label class="fn__flex b3-label">
|
<label class="fn__flex b3-label">
|
||||||
<div class="fn__flex-1">
|
<div class="fn__flex-1">
|
||||||
${window.siyuan.languages.exportPDF6}
|
${window.siyuan.languages.mergeSubdocs}
|
||||||
</div>
|
</div>
|
||||||
<span class="fn__space"></span>
|
<span class="fn__space"></span>
|
||||||
<input id="mergeSubdocs" class="b3-switch" type="checkbox" ${localData.mergeSubdocs ? "checked" : ""}>
|
<input id="mergeSubdocs" class="b3-switch" type="checkbox" ${localData.mergeSubdocs ? "checked" : ""}>
|
||||||
@ -215,7 +215,7 @@ const renderPDF = (id: string) => {
|
|||||||
</label>
|
</label>
|
||||||
<label class="b3-label">
|
<label class="b3-label">
|
||||||
<div>
|
<div>
|
||||||
${window.siyuan.languages.exportPDF6}
|
${window.siyuan.languages.mergeSubdocs}
|
||||||
</div>
|
</div>
|
||||||
<span class="fn__hr"></span>
|
<span class="fn__hr"></span>
|
||||||
<input id="mergeSubdocs" class="b3-switch" type="checkbox" ${localData.mergeSubdocs ? "checked" : ""}>
|
<input id="mergeSubdocs" class="b3-switch" type="checkbox" ${localData.mergeSubdocs ? "checked" : ""}>
|
||||||
|
@ -3,7 +3,7 @@ import {exportLayout, getInstanceById, JSONToLayout, resetLayout, resizeDrag, re
|
|||||||
import {hotKey2Electron, setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility";
|
import {hotKey2Electron, setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility";
|
||||||
/// #if !BROWSER
|
/// #if !BROWSER
|
||||||
import {dialog, getCurrentWindow} from "@electron/remote";
|
import {dialog, getCurrentWindow} from "@electron/remote";
|
||||||
import {webFrame, ipcRenderer, OpenDialogReturnValue} from "electron";
|
import {ipcRenderer, OpenDialogReturnValue, webFrame} from "electron";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import {afterExport} from "../protyle/export/util";
|
import {afterExport} from "../protyle/export/util";
|
||||||
@ -418,10 +418,11 @@ export const initWindow = () => {
|
|||||||
const pdfFilePath = path.join(result.filePaths[0], replaceLocalPath(ipcData.rootTitle) + ".pdf");
|
const pdfFilePath = path.join(result.filePaths[0], replaceLocalPath(ipcData.rootTitle) + ".pdf");
|
||||||
fs.writeFileSync(pdfFilePath, pdfData);
|
fs.writeFileSync(pdfFilePath, pdfData);
|
||||||
window.siyuan.printWin.destroy();
|
window.siyuan.printWin.destroy();
|
||||||
fetchPost("/api/export/addPDFOutline", {
|
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) {
|
||||||
|
@ -311,7 +311,7 @@ func exportHTML(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addPDFOutline(c *gin.Context) {
|
func processPDF(c *gin.Context) {
|
||||||
ret := gulu.Ret.NewResult()
|
ret := gulu.Ret.NewResult()
|
||||||
defer c.JSON(http.StatusOK, ret)
|
defer c.JSON(http.StatusOK, ret)
|
||||||
|
|
||||||
@ -326,7 +326,8 @@ func addPDFOutline(c *gin.Context) {
|
|||||||
if nil != arg["merge"] {
|
if nil != arg["merge"] {
|
||||||
merge = arg["merge"].(bool)
|
merge = arg["merge"].(bool)
|
||||||
}
|
}
|
||||||
err := model.AddPDFOutline(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()
|
||||||
|
@ -233,7 +233,7 @@ func ServeAPI(ginServer *gin.Engine) {
|
|||||||
ginServer.Handle("POST", "/api/export/exportPreviewHTML", model.CheckAuth, exportPreviewHTML)
|
ginServer.Handle("POST", "/api/export/exportPreviewHTML", model.CheckAuth, exportPreviewHTML)
|
||||||
ginServer.Handle("POST", "/api/export/exportMdHTML", model.CheckAuth, exportMdHTML)
|
ginServer.Handle("POST", "/api/export/exportMdHTML", model.CheckAuth, exportMdHTML)
|
||||||
ginServer.Handle("POST", "/api/export/exportDocx", model.CheckAuth, exportDocx)
|
ginServer.Handle("POST", "/api/export/exportDocx", model.CheckAuth, exportDocx)
|
||||||
ginServer.Handle("POST", "/api/export/addPDFOutline", model.CheckAuth, addPDFOutline)
|
ginServer.Handle("POST", "/api/export/processPDF", model.CheckAuth, processPDF)
|
||||||
ginServer.Handle("POST", "/api/export/preview", model.CheckAuth, exportPreview)
|
ginServer.Handle("POST", "/api/export/preview", model.CheckAuth, exportPreview)
|
||||||
ginServer.Handle("POST", "/api/export/exportAsFile", model.CheckAuth, exportAsFile)
|
ginServer.Handle("POST", "/api/export/exportAsFile", model.CheckAuth, exportAsFile)
|
||||||
ginServer.Handle("POST", "/api/export/exportData", model.CheckAuth, exportData)
|
ginServer.Handle("POST", "/api/export/exportData", model.CheckAuth, exportData)
|
||||||
|
@ -7,7 +7,7 @@ require (
|
|||||||
github.com/88250/css v0.1.2
|
github.com/88250/css v0.1.2
|
||||||
github.com/88250/gulu v1.2.3-0.20221117052724-cd06804db798
|
github.com/88250/gulu v1.2.3-0.20221117052724-cd06804db798
|
||||||
github.com/88250/lute v1.7.6-0.20230220030205-b0f64d7ba66e
|
github.com/88250/lute v1.7.6-0.20230220030205-b0f64d7ba66e
|
||||||
github.com/88250/pdfcpu v0.3.13
|
github.com/88250/pdfcpu v0.3.14-0.20230223031826-d2ae187e1c38
|
||||||
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1
|
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1
|
||||||
github.com/ClarkThan/ahocorasick v0.0.0-20230216061320-bccdb98581a3
|
github.com/ClarkThan/ahocorasick v0.0.0-20230216061320-bccdb98581a3
|
||||||
github.com/ConradIrwin/font v0.0.0-20210318200717-ce8d41cc0732
|
github.com/ConradIrwin/font v0.0.0-20210318200717-ce8d41cc0732
|
||||||
|
@ -10,8 +10,8 @@ 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.13 h1:touMWMZkCGalMIbEg9bxYp7rETM+zwb9hXjwhqi4I7Q=
|
github.com/88250/pdfcpu v0.3.14-0.20230223031826-d2ae187e1c38 h1:MaFRabDTXOpLBrdP4qkZnjFBIUTu/rk8S6fu7hC6jCY=
|
||||||
github.com/88250/pdfcpu v0.3.13/go.mod h1:S5YT38L/GCjVjmB4PB84PymA1qfopjEhfhTNQilLpv4=
|
github.com/88250/pdfcpu v0.3.14-0.20230223031826-d2ae187e1c38/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=
|
||||||
|
@ -654,7 +654,7 @@ func processIFrame(tree *parse.Tree) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddPDFOutline(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 {
|
||||||
@ -764,36 +764,220 @@ func AddPDFOutline(id, p string, merge bool) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//var assetAbsPaths []string
|
var assetAbsPaths []string
|
||||||
//for _, dest := range assetDests {
|
for _, dest := range assetDests {
|
||||||
// absPath, _ := GetAssetAbsPath(dest)
|
absPath, _ := GetAssetAbsPath(dest)
|
||||||
// if "" != absPath {
|
if "" != absPath {
|
||||||
// assetAbsPaths = append(assetAbsPaths, absPath)
|
assetAbsPaths = append(assetAbsPaths, absPath)
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//if 0 < len(assetAbsPaths) {
|
pdfCtx, ctxErr := api.ReadContextFile(inFile)
|
||||||
// outFile := inFile + ".tmp"
|
if nil != ctxErr {
|
||||||
// err = api.AddAttachmentsFile(inFile, outFile, assetAbsPaths, false, nil)
|
logging.LogErrorf("read pdf context failed: %s", ctxErr)
|
||||||
// if nil != err {
|
return
|
||||||
// logging.LogErrorf("add attachment failed: %s", err)
|
}
|
||||||
// return
|
|
||||||
// }
|
if 0 < len(assetAbsPaths) {
|
||||||
//
|
assetLinks, otherLinks, listErr := api.ListLinks(inFile)
|
||||||
// err = os.Rename(outFile, inFile)
|
if nil != listErr {
|
||||||
// if nil != err {
|
logging.LogErrorf("list asset links failed: %s", listErr)
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
//}
|
|
||||||
//
|
if _, removeErr := pdfCtx.RemoveAnnotations(nil, nil, nil, false); nil != removeErr {
|
||||||
//assetLinks, err := api.ListAssetLinks(inFile)
|
logging.LogWarnf("remove annotations failed: %s", removeErr)
|
||||||
//if nil == err {
|
}
|
||||||
// logging.LogInfof("pdf annotation: %+v", assetLinks)
|
|
||||||
//}
|
linkMap := map[int][]pdfcpu.AnnotationRenderer{}
|
||||||
|
for _, link := range otherLinks {
|
||||||
|
link.URI, _ = url.PathUnescape(link.URI)
|
||||||
|
if 1 > len(linkMap[link.Page]) {
|
||||||
|
linkMap[link.Page] = []pdfcpu.AnnotationRenderer{link}
|
||||||
|
} else {
|
||||||
|
linkMap[link.Page] = append(linkMap[link.Page], link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attachmentMap := map[int][]*pdfcpu.IndirectRef{}
|
||||||
|
now := pdfcpu.StringLiteral(pdfcpu.DateString(time.Now()))
|
||||||
|
for _, link := range assetLinks {
|
||||||
|
link.URI = strings.ReplaceAll(link.URI, "http://127.0.0.1:6806/export/temp/", "")
|
||||||
|
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)
|
||||||
|
if nil != getErr {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ir, newErr := pdfCtx.XRefTable.NewEmbeddedFileStreamDict(absPath)
|
||||||
|
if nil != newErr {
|
||||||
|
logging.LogWarnf("new embedded file stream dict failed: %s", newErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fn := filepath.Base(absPath)
|
||||||
|
fileSpecDict, newErr := pdfCtx.XRefTable.NewFileSpecDict(fn, pdfcpu.EncodeUTF16String(fn), "attached by SiYuan", *ir)
|
||||||
|
if nil != newErr {
|
||||||
|
logging.LogWarnf("new file spec dict failed: %s", newErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ir, indErr := pdfCtx.XRefTable.IndRefForNewObject(fileSpecDict)
|
||||||
|
if nil != indErr {
|
||||||
|
logging.LogWarnf("ind ref for new object failed: %s", indErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
lx := link.Rect.LL.X + link.Rect.Width()
|
||||||
|
ly := link.Rect.LL.Y + link.Rect.Height()/2
|
||||||
|
ux := lx + link.Rect.Height()/2
|
||||||
|
uy := ly + link.Rect.Height()/2
|
||||||
|
|
||||||
|
d := pdfcpu.Dict(
|
||||||
|
map[string]pdfcpu.Object{
|
||||||
|
"Type": pdfcpu.Name("Annot"),
|
||||||
|
"Subtype": pdfcpu.Name("FileAttachment"),
|
||||||
|
"Contents": pdfcpu.StringLiteral(""),
|
||||||
|
"Rect": pdfcpu.Rect(lx, ly, ux, uy).Array(),
|
||||||
|
"P": link.P,
|
||||||
|
"M": now,
|
||||||
|
"F": pdfcpu.Integer(0),
|
||||||
|
"Border": pdfcpu.NewIntegerArray(0, 0, 1),
|
||||||
|
"C": pdfcpu.NewNumberArray(0.5, 0.0, 0.5),
|
||||||
|
"CA": pdfcpu.Float(0.95),
|
||||||
|
"CreationDate": now,
|
||||||
|
"Name": pdfcpu.Name("FileAttachment"),
|
||||||
|
"FS": *ir,
|
||||||
|
"NM": pdfcpu.StringLiteral(""),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ann, indErr := pdfCtx.XRefTable.IndRefForNewObject(d)
|
||||||
|
if nil != indErr {
|
||||||
|
logging.LogWarnf("ind ref for new object failed: %s", indErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
pageDictIndRef, pageErr := pdfCtx.PageDictIndRef(link.Page)
|
||||||
|
if nil != pageErr {
|
||||||
|
logging.LogWarnf("page dict ind ref failed: %s", pageErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
d, defErr := pdfCtx.DereferenceDict(*pageDictIndRef)
|
||||||
|
if nil != defErr {
|
||||||
|
logging.LogWarnf("dereference dict failed: %s", defErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 > len(attachmentMap[link.Page]) {
|
||||||
|
attachmentMap[link.Page] = []*pdfcpu.IndirectRef{ann}
|
||||||
|
} else {
|
||||||
|
attachmentMap[link.Page] = append(attachmentMap[link.Page], ann)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 < len(linkMap) {
|
||||||
|
if _, addErr := pdfCtx.AddAnnotationsMap(linkMap, false); nil != addErr {
|
||||||
|
logging.LogErrorf("add annotations map failed: %s", addErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加附件注解指向内嵌的附件
|
||||||
|
for page, anns := range attachmentMap {
|
||||||
|
pageDictIndRef, pageErr := pdfCtx.PageDictIndRef(page)
|
||||||
|
if nil != pageErr {
|
||||||
|
logging.LogWarnf("page dict ind ref failed: %s", pageErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
pageDict, defErr := pdfCtx.DereferenceDict(*pageDictIndRef)
|
||||||
|
if nil != defErr {
|
||||||
|
logging.LogWarnf("dereference dict failed: %s", defErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
array := pdfcpu.Array{}
|
||||||
|
for _, ann := range anns {
|
||||||
|
array = append(array, *ann)
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, found := pageDict.Find("Annots")
|
||||||
|
if !found {
|
||||||
|
pageDict.Insert("Annots", array)
|
||||||
|
pdfCtx.EnsureVersionForWriting()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ir, ok := obj.(pdfcpu.IndirectRef)
|
||||||
|
if !ok {
|
||||||
|
pageDict.Update("Annots", append(obj.(pdfcpu.Array), array...))
|
||||||
|
pdfCtx.EnsureVersionForWriting()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annots array is an IndirectReference.
|
||||||
|
|
||||||
|
o, err := pdfCtx.Dereference(ir)
|
||||||
|
if err != nil || o == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
annots, _ := o.(pdfcpu.Array)
|
||||||
|
entry, ok := pdfCtx.FindTableEntryForIndRef(&ir)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
entry.Object = append(annots, array...)
|
||||||
|
pdfCtx.EnsureVersionForWriting()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func annotRect(i int, w, h, d, l float64) *pdfcpu.Rectangle {
|
||||||
|
// d..distance between annotation rectangles
|
||||||
|
// l..side length of rectangle
|
||||||
|
|
||||||
|
// max number of rectangles fitting into w
|
||||||
|
xmax := int((w - d) / (l + d))
|
||||||
|
|
||||||
|
// max number of rectangles fitting into h
|
||||||
|
ymax := int((h - d) / (l + d))
|
||||||
|
|
||||||
|
col := float64(i % xmax)
|
||||||
|
row := float64(i / xmax % ymax)
|
||||||
|
|
||||||
|
llx := d + col*(l+d)
|
||||||
|
lly := d + row*(l+d)
|
||||||
|
|
||||||
|
urx := llx + l
|
||||||
|
ury := lly + l
|
||||||
|
|
||||||
|
return pdfcpu.Rect(llx, lly, urx, ury)
|
||||||
|
}
|
||||||
|
|
||||||
func ExportStdMarkdown(id string) string {
|
func ExportStdMarkdown(id string) string {
|
||||||
tree, err := loadTreeByBlockID(id)
|
tree, err := loadTreeByBlockID(id)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -674,6 +674,10 @@ func GetDecks() (decks []*riff.Deck) {
|
|||||||
if 1 > len(decks) {
|
if 1 > len(decks) {
|
||||||
decks = []*riff.Deck{}
|
decks = []*riff.Deck{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort.Slice(decks, func(i, j int) bool {
|
||||||
|
return decks[i].Updated > decks[j].Updated
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +130,11 @@ func Upload(c *gin.Context) {
|
|||||||
docDirLocalPath := filepath.Join(util.DataDir, bt.BoxID, path.Dir(bt.Path))
|
docDirLocalPath := filepath.Join(util.DataDir, bt.BoxID, path.Dir(bt.Path))
|
||||||
assetsDirPath = getAssetsDir(filepath.Join(util.DataDir, bt.BoxID), docDirLocalPath)
|
assetsDirPath = getAssetsDir(filepath.Join(util.DataDir, bt.BoxID), docDirLocalPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relAssetsDirPath := "assets"
|
||||||
if nil != form.Value["assetsDirPath"] {
|
if nil != form.Value["assetsDirPath"] {
|
||||||
assetsDirPath = form.Value["assetsDirPath"][0]
|
relAssetsDirPath = form.Value["assetsDirPath"][0]
|
||||||
assetsDirPath = filepath.Join(util.DataDir, assetsDirPath)
|
assetsDirPath = filepath.Join(util.DataDir, relAssetsDirPath)
|
||||||
}
|
}
|
||||||
if !gulu.File.IsExist(assetsDirPath) {
|
if !gulu.File.IsExist(assetsDirPath) {
|
||||||
if err = os.MkdirAll(assetsDirPath, 0755); nil != err {
|
if err = os.MkdirAll(assetsDirPath, 0755); nil != err {
|
||||||
@ -187,7 +189,7 @@ func Upload(c *gin.Context) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
succMap[baseName] = "assets/" + fName
|
succMap[baseName] = path.Join(relAssetsDirPath, fName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user