diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index 132e48454..2ee133cd2 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -941,6 +941,9 @@ "export24": "After enabling, add some general metadata information at the beginning of the exported Markdown file", "export25": "Export Word .docx template path", "export26": "The absolute path of the template used when exporting Word .docx files, that is, Pandoc --reference-doc parameter value", + "export27": "Export PDF watermark", + "export28": "Watermark text or watermark file path", + "export29": "Watermark position, size and style, etc.", "theme11": "Use theme in light mode", "theme12": "Use theme in dark mode", "theme2": "Select the icons used in the user interface", diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 0eb160ea1..e84f16213 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -941,6 +941,9 @@ "export24": "Después de habilitar, agregue información general de metadatos al comienzo del archivo Markdown exportado", "export25": "Exportar ruta de plantilla .docx de Word", "export26": "La ruta absoluta de la plantilla utilizada al exportar archivos .docx de Word, es decir, Pandoc --reference-doc valor del parámetro", + "export27": "Exportar marca de agua PDF", + "export28": "Texto de marca de agua o ruta del archivo de marca de agua", + "export29": "Posición, tamaño y estilo de la marca de agua, etc.", "theme11": "Usar tema en modo claro", "theme12": "Usar tema en modo oscuro", "theme2": "Selecciona los iconos utilizados en la interfaz de usuario", diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index 749f42d4f..0e8d3d641 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -941,6 +941,9 @@ "export24": "Après l'activation, ajoutez des informations générales sur les métadonnées au début du fichier Markdown exporté", "export25": "Chemin d'exportation du modèle Word .docx", "export26": "Le chemin absolu du modèle utilisé lors de l'exportation de fichiers Word .docx, c'est-à-dire Pandoc --reference-doc valeur du paramètre", + "export27": "Exporter le filigrane PDF", + "export28": "Texte du filigrane ou chemin du fichier de filigrane", + "export29": "Position, taille et style du filigrane, etc.", "theme11": "Utiliser le thème en mode Clair", "theme12": "Utiliser le thème en mode sombre", "theme2": "Sélectionnez les icônes utilisées dans l'interface utilisateur", diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index f1ece6de7..2d4f41590 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -941,6 +941,9 @@ "export24": "啟用後在導出的 Markdown 文件開頭處添加一些較為通用的元資料資訊", "export25": "導出 Word .docx 模板路徑", "export26": "導出 Word .docx 文件時使用的模板絕對路徑,即 Pandoc --reference-doc 參數的值", + "export27": "導出 PDF 浮水印", + "export28": "浮水印文字或浮水印檔案路徑", + "export29": "浮水印位置、大小和樣式等", "theme11": "淺色模式下使用主題", "theme12": "深色模式下使用主題", "theme2": "選擇外觀使用的圖示", diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index f792cec0a..1887c80bd 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -941,6 +941,9 @@ "export24": "启用后在导出的 Markdown 文件开头处添加一些较为通用的元数据信息", "export25": "导出 Word .docx 模板路径", "export26": "导出 Word .docx 文件时使用的模板绝对路径,即 Pandoc --reference-doc 参数的值", + "export27": "导出 PDF 水印", + "export28": "水印文本或水印文件路径", + "export29": "水印位置、大小和样式等", "theme11": "明亮模式下使用主题", "theme12": "暗黑模式下使用主题", "theme2": "选择外观使用的图标", diff --git a/app/src/config/exportConfig.ts b/app/src/config/exportConfig.ts index 662029ab8..b4b997239 100644 --- a/app/src/config/exportConfig.ts +++ b/app/src/config/exportConfig.ts @@ -77,6 +77,17 @@ export const exportConfig = { +
+
+ ${window.siyuan.languages.export27} +
${window.siyuan.languages.export28}
+
+ +
+
${window.siyuan.languages.export29}
+
+ +
${window.siyuan.languages.export25} @@ -139,6 +150,8 @@ export const exportConfig = { bindEvent: () => { (exportConfig.element.querySelector("#docxTemplate") as HTMLInputElement).value = window.siyuan.config.export.docxTemplate; (exportConfig.element.querySelector("#pdfFooter") as HTMLInputElement).value = window.siyuan.config.export.pdfFooter; + (exportConfig.element.querySelector("#pdfWatermarkStr") as HTMLInputElement).value = window.siyuan.config.export.pdfWatermarkStr; + (exportConfig.element.querySelector("#pdfWatermarkDesc") as HTMLInputElement).value = window.siyuan.config.export.pdfWatermarkDesc; (exportConfig.element.querySelector("#blockRefTextLeft") as HTMLInputElement).value = window.siyuan.config.export.blockRefTextLeft; (exportConfig.element.querySelector("#blockRefTextRight") as HTMLInputElement).value = window.siyuan.config.export.blockRefTextRight; (exportConfig.element.querySelector("#tagOpenMarker") as HTMLInputElement).value = window.siyuan.config.export.tagOpenMarker; @@ -153,6 +166,8 @@ export const exportConfig = { blockEmbedMode: parseInt((exportConfig.element.querySelector("#blockEmbedMode") as HTMLSelectElement).value, 10), fileAnnotationRefMode: parseInt((exportConfig.element.querySelector("#fileAnnotationRefMode") as HTMLSelectElement).value, 10), pdfFooter: (exportConfig.element.querySelector("#pdfFooter") as HTMLInputElement).value, + pdfWatermarkStr: (exportConfig.element.querySelector("#pdfWatermarkStr") as HTMLInputElement).value, + pdfWatermarkDesc: (exportConfig.element.querySelector("#pdfWatermarkDesc") as HTMLInputElement).value, docxTemplate: (exportConfig.element.querySelector("#docxTemplate") as HTMLInputElement).value, blockRefTextLeft: (exportConfig.element.querySelector("#blockRefTextLeft") as HTMLInputElement).value, blockRefTextRight: (exportConfig.element.querySelector("#blockRefTextRight") as HTMLInputElement).value, diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts index c44977adc..27f26d44b 100644 --- a/app/src/types/index.d.ts +++ b/app/src/types/index.d.ts @@ -594,6 +594,8 @@ interface IExport { addTitle: boolean; markdownYFM: boolean; pdfFooter: string; + pdfWatermarkStr: string; + pdfWatermarkDesc: string; docxTemplate: string; } diff --git a/kernel/conf/export.go b/kernel/conf/export.go index 7918b8ddc..b420a266e 100644 --- a/kernel/conf/export.go +++ b/kernel/conf/export.go @@ -30,6 +30,8 @@ type Export struct { MarkdownYFM bool `json:"markdownYFM"` // Markdown 导出时是否添加 YAML Front Matter https://github.com/siyuan-note/siyuan/issues/7727 PDFFooter string `json:"pdfFooter"` // PDF 导出时页脚内容 DocxTemplate string `json:"docxTemplate"` // Docx 导出时模板文件路径 + PDFWatermarkStr string `json:"pdfWatermarkStr"` // PDF 导出时水印文本或水印文件路径 + PDFWatermarkDesc string `json:"pdfWatermarkDesc"` // PDF 导出时水印位置、大小和样式等 } func NewExport() *Export { diff --git a/kernel/model/export.go b/kernel/model/export.go index 3bc24bf16..fcf2229c8 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -818,7 +818,7 @@ func ProcessPDF(id, p string, merge, removeAssets bool) (err error) { processPDFBookmarks(pdfCtx, headings) processPDFLinkEmbedAssets(pdfCtx, assetDests, removeAssets) - // processPDFWatermark(pdfCtx, "text", "Test", "") + processPDFWatermark(pdfCtx) pdfcpu.VersionStr = "SiYuan v" + util.Ver if writeErr := api.WriteContextFile(pdfCtx, p); nil != writeErr { @@ -828,32 +828,45 @@ func ProcessPDF(id, p string, merge, removeAssets bool) (err error) { return } -func processPDFWatermark(pdfCtx *pdfcpu.Context, mode, watermark, desc string) { +func processPDFWatermark(pdfCtx *pdfcpu.Context) { // Support adding the watermark on export PDF https://github.com/siyuan-note/siyuan/issues/9961 // https://pdfcpu.io/core/watermark + str := Conf.Export.PDFWatermarkStr + if "" == str { + return + } + if !IsPaidUser() { return } - if "" == watermark { - return + desc := Conf.Export.PDFWatermarkDesc + f, e := pdfCtx.ExtractFont(1) + if nil == e { + desc = "fontname:" + f.Name } - if "text" != mode && "image" != mode && "pdf" != mode { - logging.LogErrorf("invalid watermark type: %s", mode) - return + mode := "text" + if gulu.File.IsExist(str) { + if ".pdf" == strings.ToLower(filepath.Ext(str)) { + mode = "pdf" + } else { + mode = "image" + } } + logging.LogInfof("add PDF watermark [mode=%s, str=%s, desc=%s]", mode, str, desc) + var wm *pdfcpu.Watermark var err error switch mode { case "text": - wm, err = pdfcpu.ParseTextWatermarkDetails(watermark, desc, false, pdfcpu.POINTS) + wm, err = pdfcpu.ParseTextWatermarkDetails(str, desc, false, pdfcpu.POINTS) case "image": - wm, err = pdfcpu.ParseImageWatermarkDetails(watermark, desc, false, pdfcpu.POINTS) + wm, err = pdfcpu.ParseImageWatermarkDetails(str, desc, false, pdfcpu.POINTS) case "pdf": - wm, err = pdfcpu.ParsePDFWatermarkDetails(watermark, desc, false, pdfcpu.POINTS) + wm, err = pdfcpu.ParsePDFWatermarkDetails(str, desc, false, pdfcpu.POINTS) } if nil != err {