mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-27 20:08:49 +01:00
🎨 Desktop export PDF supports no pagination https://ld246.com/article/1764933918963 (#16537)
This commit is contained in:
parent
cfd25e85b6
commit
cef8ca8cf7
18 changed files with 117 additions and 35 deletions
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "مقياس الصفحة",
|
||||
"exportPDF4": "تضمين الأصول",
|
||||
"exportPDF5": "البقاء مطوية",
|
||||
"paged": "ترقيم الصفحات",
|
||||
"mergeSubdocs": "إبقاء مطوياً",
|
||||
"removeAssetsFolder": "إزالة دليل الأصول",
|
||||
"upload": "رفع",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Seitenmaßstab",
|
||||
"exportPDF4": "Assets einbetten",
|
||||
"exportPDF5": "Aufgeklappt beibehalten",
|
||||
"paged": "Seitenumbruch",
|
||||
"mergeSubdocs": "Unterdokumente zusammenführen",
|
||||
"removeAssetsFolder": "Assets-Verzeichnis entfernen",
|
||||
"upload": "Hochladen",
|
||||
|
|
@ -1459,7 +1460,7 @@
|
|||
"22": "Das Captcha ist falsch",
|
||||
"23": "Das Daten-Repository ist beschädigt, bitte setzen Sie das Daten-Repository zurück",
|
||||
"24": "Netzwerkzeitüberschreitung, bitte versuchen Sie es später erneut",
|
||||
"25": "Der Attributname darf nur Kleinbuchstaben, Ziffern und Bindestriche enthalten und muss mit einem Kleinbuchstaben beginnen",
|
||||
"25": "Der Attributname unterstützt nur englische Buchstaben und Ziffern",
|
||||
"26": "Bitte initialisieren Sie zuerst den Schlüssel des Daten-Repositorys in [Einstellungen - Über - Schlüssel des Daten-Repositorys]",
|
||||
"27": "Hochladen [%v]",
|
||||
"28": "Das Netzwerk ist abnormal, bitte versuchen Sie es später erneut",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Page Scale",
|
||||
"exportPDF4": "Embed assets",
|
||||
"exportPDF5": "Keep folded",
|
||||
"paged": "Paged",
|
||||
"mergeSubdocs": "Merge subdocuments",
|
||||
"removeAssetsFolder": "Remove assets directory",
|
||||
"upload": "Upload",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Escala de la página",
|
||||
"exportPDF4": "Activos incrustados",
|
||||
"exportPDF5": "Mantener doblado",
|
||||
"paged": "Paginado",
|
||||
"mergeSubdocs": "Fusionar subdocumentos",
|
||||
"removeAssetsFolder": "Eliminar directorio de activos",
|
||||
"upload": "Subir",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Échelle de page",
|
||||
"exportPDF4": "Incorporer des ressources",
|
||||
"exportPDF5": "Garder plié",
|
||||
"paged": "Pagination",
|
||||
"mergeSubdocs": "Fusionner les sous-documents",
|
||||
"removeAssetsFolder": "Supprimer le répertoire des actifs",
|
||||
"upload": "Télécharger",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "קנה מידה של עמוד",
|
||||
"exportPDF4": "הכנס נכסים",
|
||||
"exportPDF5": "שמור מקופל",
|
||||
"paged": "עמודים",
|
||||
"mergeSubdocs": "מזג תתי-מסמכים",
|
||||
"removeAssetsFolder": "הסר תיקיית נכסים",
|
||||
"upload": "העלה",
|
||||
|
|
@ -1459,7 +1460,7 @@
|
|||
"22": "ה-captcha לא נכון",
|
||||
"23": "מאגר הנתונים פגום, אנא אפס את מאגר הנתונים",
|
||||
"24": "החיבור לרשת פג, אנא נסה שוב מאוחר יותר",
|
||||
"25": "שם המאפיין יכול להכיל רק אותיות אנגליות קטנות, ספרות ומקפים, ויש להתחיל באות אנגלית קטנה",
|
||||
"25": "שם המאפיין תומך רק באותיות אנגליות ובתווים",
|
||||
"26": "אנא אתחל קודם את מפתח מאגר הנתונים ב[הגדרות - אודות - מפתח מאגר הנתונים]",
|
||||
"27": "מעלה [%v]",
|
||||
"28": "חיבור לרשת בלתי תקין, אנא נסה שוב מאוחר יותר",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Scala pagina",
|
||||
"exportPDF4": "Incorpora asset",
|
||||
"exportPDF5": "Mantieni piegato",
|
||||
"paged": "Paginazione",
|
||||
"mergeSubdocs": "Unisci sotto-documenti",
|
||||
"removeAssetsFolder": "Rimuovi directory asset",
|
||||
"upload": "Carica",
|
||||
|
|
@ -1459,7 +1460,7 @@
|
|||
"22": "Il captcha è errato",
|
||||
"23": "Il repository dei dati è corrotto, per favore ripristina il repository dei dati",
|
||||
"24": "La rete ha impiegato troppo tempo, riprova più tardi",
|
||||
"25": "Il nome dell'attributo può contenere solo lettere minuscole, numeri e trattini e deve iniziare con una lettera minuscola",
|
||||
"25": "Il nome dell'attributo supporta solo lettere e numeri",
|
||||
"26": "Si prega di inizializzare prima la chiave del repository dati in [Impostazioni - Informazioni - Chiave del repository dati]",
|
||||
"27": "Caricamento [%v]",
|
||||
"28": "La rete è anormale, riprova più tardi",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "ページスケール",
|
||||
"exportPDF4": "アセットの埋め込み",
|
||||
"exportPDF5": "折りたたみを保持",
|
||||
"paged": "ページ分割",
|
||||
"mergeSubdocs": "サブドキュメントをマージ",
|
||||
"removeAssetsFolder": "アセットディレクトリを削除",
|
||||
"upload": "アップロード",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "페이지 비율",
|
||||
"exportPDF4": "에셋 임베드",
|
||||
"exportPDF5": "접힌 상태 유지",
|
||||
"paged": "페이지 분할",
|
||||
"mergeSubdocs": "하위 문서 병합",
|
||||
"removeAssetsFolder": "assets 디렉토리 제거",
|
||||
"upload": "업로드",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Skala strony",
|
||||
"exportPDF4": "Osadź zasoby",
|
||||
"exportPDF5": "Zachowaj złożone",
|
||||
"paged": "Stronicowanie",
|
||||
"mergeSubdocs": "Scal poddokumenty",
|
||||
"removeAssetsFolder": "Usuń katalog zasobów",
|
||||
"upload": "Prześlij",
|
||||
|
|
@ -1459,7 +1460,7 @@
|
|||
"22": "Captcha jest nieprawidłowa",
|
||||
"23": "Repozytorium danych jest uszkodzone, proszę zresetować repozytorium danych",
|
||||
"24": "Czas oczekiwania w sieci, proszę spróbować ponownie później",
|
||||
"25": "Nazwa atrybutu może zawierać tylko małe litery angielskie, cyfry i myślniki i musi zaczynać się od małej litery angielskiej",
|
||||
"25": "Nazwa atrybutu obsługuje tylko litery angielskie i cyfry",
|
||||
"26": "Proszę najpierw zainicjować klucz repozytorium danych w [Ustawienia - O - Klucz repozytorium danych]",
|
||||
"27": "Przesyłanie [%v]",
|
||||
"28": "Sieć jest nieprawidłowa, proszę spróbować ponownie później",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Escala da página",
|
||||
"exportPDF4": "Incorporar ativos",
|
||||
"exportPDF5": "Manter dobrado",
|
||||
"paged": "Paginação",
|
||||
"mergeSubdocs": "Mesclar subdocumentos",
|
||||
"removeAssetsFolder": "Remover diretório de ativos",
|
||||
"upload": "Enviar",
|
||||
|
|
@ -1459,7 +1460,7 @@
|
|||
"22": "O captcha está incorreto",
|
||||
"23": "O repositório de dados está corrompido, por favor redefina o repositório de dados",
|
||||
"24": "Tempo limite da rede, por favor tente novamente mais tarde",
|
||||
"25": "O nome do atributo pode conter apenas letras minúsculas, dígitos e hífens e deve começar com uma letra minúscula",
|
||||
"25": "O nome do atributo só suporta letras inglesas e dígitos",
|
||||
"26": "Por favor, inicialize a chave do repositório de dados primeiro em [Configurações - Sobre - Chave do repositório de dados]",
|
||||
"27": "Enviando [%v]",
|
||||
"28": "A rede está anormal, por favor tente novamente mais tarde",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Масштаб страницы",
|
||||
"exportPDF4": "Встраивать ресурсы",
|
||||
"exportPDF5": "Сохранить сложенные",
|
||||
"paged": "Разбивка на страницы",
|
||||
"mergeSubdocs": "Объединить поддокументы",
|
||||
"removeAssetsFolder": "Удалить директорию ресурсов",
|
||||
"upload": "Загрузить",
|
||||
|
|
@ -1459,7 +1460,7 @@
|
|||
"22": "Капча неверна",
|
||||
"23": "Репозиторий данных поврежден, пожалуйста, сбросьте репозиторий данных",
|
||||
"24": "Таймаут сети, пожалуйста, попробуйте позже",
|
||||
"25": "Имя атрибута может содержать только строчные английские буквы, цифры и дефисы и должно начинаться со строчной английской буквы",
|
||||
"25": "Имя атрибута поддерживает только английские буквы и цифры",
|
||||
"26": "Пожалуйста, сначала инициализируйте ключ репозитория данных в [Настройки - О программе - Ключ репозитория данных]",
|
||||
"27": "Загрузка [%v]",
|
||||
"28": "Сеть аномальная, пожалуйста, попробуйте позже",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "Sayfa ölçeği",
|
||||
"exportPDF4": "Varlıkları göm",
|
||||
"exportPDF5": "Daraltılmış alanları koru",
|
||||
"paged": "Sayfalandırılmış",
|
||||
"mergeSubdocs": "Alt belgeleri birleştir",
|
||||
"removeAssetsFolder": "Varlıklar klasörünü kaldır",
|
||||
"upload": "Yükle",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "頁面縮放",
|
||||
"exportPDF4": "嵌入資源文件",
|
||||
"exportPDF5": "保持折疊狀態",
|
||||
"paged": "分頁",
|
||||
"mergeSubdocs": "合併子文檔",
|
||||
"removeAssetsFolder": "移除 assets 目錄",
|
||||
"upload": "上傳",
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@
|
|||
"exportPDF3": "页面缩放",
|
||||
"exportPDF4": "嵌入资源文件",
|
||||
"exportPDF5": "保持折叠状态",
|
||||
"paged": "分页",
|
||||
"mergeSubdocs": "合并子文档",
|
||||
"removeAssetsFolder": "移除 assets 目录",
|
||||
"upload": "上传",
|
||||
|
|
|
|||
|
|
@ -221,6 +221,9 @@ export const initWindow = async (app: App) => {
|
|||
});
|
||||
ipcRenderer.on(Constants.SIYUAN_EXPORT_PDF, async (e, ipcData) => {
|
||||
const msgId = showMessage(window.siyuan.languages.exporting, -1);
|
||||
const isPaged = ipcData.paged !== undefined ? ipcData.paged : true;
|
||||
// 分页模式下 pageSize 是字符串,不分页模式下是对象,统一使用 pageSizeValue 获取原始页面大小
|
||||
const pageSizeValue = ipcData.pageSizeValue !== undefined ? ipcData.pageSizeValue : (isPaged ? ipcData.pdfOptions.pageSize : "A4");
|
||||
window.siyuan.storage[Constants.LOCAL_EXPORTPDF] = {
|
||||
removeAssets: ipcData.removeAssets,
|
||||
keepFold: ipcData.keepFold,
|
||||
|
|
@ -228,16 +231,17 @@ export const initWindow = async (app: App) => {
|
|||
watermark: ipcData.watermark,
|
||||
landscape: ipcData.pdfOptions.landscape,
|
||||
marginType: ipcData.pdfOptions.marginType,
|
||||
pageSize: ipcData.pdfOptions.pageSize,
|
||||
pageSize: pageSizeValue,
|
||||
scale: ipcData.pdfOptions.scale,
|
||||
marginTop: ipcData.pdfOptions.margins.top,
|
||||
marginRight: ipcData.pdfOptions.margins.right,
|
||||
marginBottom: ipcData.pdfOptions.margins.bottom,
|
||||
marginLeft: ipcData.pdfOptions.margins.left,
|
||||
paged: isPaged,
|
||||
};
|
||||
setStorageVal(Constants.LOCAL_EXPORTPDF, window.siyuan.storage[Constants.LOCAL_EXPORTPDF]);
|
||||
try {
|
||||
if (window.siyuan.config.export.pdfFooter.trim()) {
|
||||
if (window.siyuan.config.export.pdfFooter.trim() && isPaged) {
|
||||
const response = await fetchSyncPost("/api/template/renderSprig", {template: window.siyuan.config.export.pdfFooter});
|
||||
ipcData.pdfOptions.displayHeaderFooter = true;
|
||||
ipcData.pdfOptions.headerTemplate = "<span></span>";
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ const renderPDF = async (id: string) => {
|
|||
${window.siyuan.languages.exportPDF1}
|
||||
</div>
|
||||
<span class="fn__hr"></span>
|
||||
<input id="landscape" class="b3-switch" type="checkbox" ${localData.landscape ? "checked" : ""}>
|
||||
<input id="landscape" class="b3-switch" type="checkbox" ${localData.landscape && localData.paged ? "checked" : ""}>
|
||||
</label>
|
||||
<label class="b3-label">
|
||||
<div>
|
||||
|
|
@ -334,6 +334,13 @@ const renderPDF = async (id: string) => {
|
|||
<span class="fn__hr"></span>
|
||||
<input id="watermark" class="b3-switch" type="checkbox" ${localData.watermark ? "checked" : ""}>
|
||||
</label>
|
||||
<label class="b3-label">
|
||||
<div>
|
||||
${window.siyuan.languages.paged}
|
||||
</div>
|
||||
<span class="fn__hr"></span>
|
||||
<input id="paged" class="b3-switch" type="checkbox" ${(localData.paged === undefined ? true : localData.paged) ? "checked" : ""}>
|
||||
</label>
|
||||
</div>
|
||||
<div class="fn__flex" style="padding: 0 16px">
|
||||
<div class="fn__flex-1"></div>
|
||||
|
|
@ -555,7 +562,7 @@ ${getIconScript(servePath)}
|
|||
renderPreview(response2.data);
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
actionElement.querySelector("#scale").addEventListener("input", () => {
|
||||
const scale = actionElement.querySelector("#scale").value;
|
||||
actionElement.querySelector("#scaleTip").innerText = scale;
|
||||
|
|
@ -585,38 +592,93 @@ ${getIconScript(servePath)}
|
|||
actionElement.querySelector("#marginsLeft").addEventListener('change', () => {
|
||||
setPadding();
|
||||
});
|
||||
actionElement.querySelector("#landscape").addEventListener('change', () => {
|
||||
actionElement.querySelector("#landscape").addEventListener('change', (e) => {
|
||||
if (e.target.checked) {
|
||||
actionElement.querySelector("#paged").checked = true;
|
||||
}
|
||||
setPadding();
|
||||
});
|
||||
actionElement.querySelector("#paged").addEventListener('change', (e) => {
|
||||
// 不分页模式没有适配横向页面,强制纵向
|
||||
if (!e.target.checked) {
|
||||
const landscapeElement = actionElement.querySelector("#landscape");
|
||||
if (landscapeElement.checked) {
|
||||
landscapeElement.checked = false;
|
||||
setPadding();
|
||||
}
|
||||
}
|
||||
});
|
||||
actionElement.querySelector('.b3-button--cancel').addEventListener('click', () => {
|
||||
const {ipcRenderer} = require("electron");
|
||||
ipcRenderer.send("${Constants.SIYUAN_CMD}", "destroy")
|
||||
});
|
||||
actionElement.querySelector('.b3-button--text').addEventListener('click', () => {
|
||||
const {ipcRenderer} = require("electron");
|
||||
ipcRenderer.send("${Constants.SIYUAN_EXPORT_PDF}", {
|
||||
title: "${window.siyuan.languages.export} PDF",
|
||||
pdfOptions:{
|
||||
printBackground: true,
|
||||
landscape: actionElement.querySelector("#landscape").checked,
|
||||
marginType: actionElement.querySelector("#marginsType").value,
|
||||
margins: {
|
||||
top: parseFloat(document.querySelector("#marginsTop").value),
|
||||
bottom: parseFloat(document.querySelector("#marginsBottom").value),
|
||||
left: parseFloat(document.querySelector("#marginsLeft").value),
|
||||
right: parseFloat(document.querySelector("#marginsRight").value),
|
||||
},
|
||||
scale: parseFloat(actionElement.querySelector("#scale").value),
|
||||
pageSize: actionElement.querySelector("#pageSize").value,
|
||||
},
|
||||
keepFold: keepFoldElement.checked,
|
||||
mergeSubdocs: mergeSubdocsElement.checked,
|
||||
watermark: watermarkElement.checked,
|
||||
removeAssets: actionElement.querySelector("#removeAssets").checked,
|
||||
rootId: "${id}",
|
||||
rootTitle: response.data.name,
|
||||
parentWindowId: ${currentWindowId},
|
||||
})
|
||||
const pageSizeValue = actionElement.querySelector("#pageSize").value;
|
||||
const isPaged = actionElement.querySelector("#paged").checked;
|
||||
|
||||
const buildExportConfig = (pageSize) => {
|
||||
// https://www.electronjs.org/docs/latest/api/web-contents#contentsprinttopdfoptions
|
||||
// https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
|
||||
return {
|
||||
title: "${window.siyuan.languages.export} PDF",
|
||||
pdfOptions: {
|
||||
printBackground: true,
|
||||
landscape: actionElement.querySelector("#landscape").checked,
|
||||
marginType: actionElement.querySelector("#marginsType").value,
|
||||
margins: {
|
||||
top: parseFloat(document.querySelector("#marginsTop").value) || 0,
|
||||
bottom: parseFloat(document.querySelector("#marginsBottom").value) || 0,
|
||||
left: parseFloat(document.querySelector("#marginsLeft").value) || 0,
|
||||
right: parseFloat(document.querySelector("#marginsRight").value) || 0,
|
||||
},
|
||||
scale: parseFloat(actionElement.querySelector("#scale").value),
|
||||
pageSize: pageSize,
|
||||
},
|
||||
keepFold: keepFoldElement.checked,
|
||||
mergeSubdocs: mergeSubdocsElement.checked,
|
||||
watermark: watermarkElement.checked,
|
||||
removeAssets: actionElement.querySelector("#removeAssets").checked,
|
||||
paged: isPaged,
|
||||
pageSizeValue: pageSizeValue,
|
||||
rootId: "${id}",
|
||||
rootTitle: response.data.name,
|
||||
parentWindowId: ${currentWindowId},
|
||||
};
|
||||
};
|
||||
|
||||
if (!isPaged) {
|
||||
const getPageSizeDimensions = (pageSizeName) => {
|
||||
// https://github.com/electron/electron/blob/3df3a6a736b93e0d69fa3b0c403b33f201287780/lib/browser/api/web-contents.ts#L89-L101
|
||||
const pageSizes = {
|
||||
"A3": { width: 11.7, height: 16.54 },
|
||||
"A4": { width: 8.27, height: 11.7 },
|
||||
"A5": { width: 5.83, height: 8.27 },
|
||||
"Legal": { width: 8.5, height: 14 },
|
||||
"Letter": { width: 8.5, height: 11 },
|
||||
"Tabloid": { width: 11, height: 17 },
|
||||
};
|
||||
return pageSizes[pageSizeName] || pageSizes["A4"];
|
||||
};
|
||||
|
||||
const previewContent = previewElement.querySelector(".protyle-wysiwyg") || previewElement;
|
||||
const contentHeight = previewContent.scrollHeight || previewContent.offsetHeight;
|
||||
// 英寸 = 像素 / PPI,但不知道 PPI 怎么得到,直接使用经典 96 DPI,实际导出之后页面末尾会有空白
|
||||
const heightInches = contentHeight / 96;
|
||||
// 获取页面大小对应的宽度
|
||||
const selectedPageSize = getPageSizeDimensions(pageSizeValue);
|
||||
// 高度根据内容动态计算
|
||||
const marginTop = parseFloat(document.querySelector("#marginsTop").value) || 0;
|
||||
const marginBottom = parseFloat(document.querySelector("#marginsBottom").value) || 0;
|
||||
const totalHeightInches = heightInches + marginTop + marginBottom;
|
||||
const dynamicPageSize = {
|
||||
width: selectedPageSize.width,
|
||||
height: totalHeightInches
|
||||
};
|
||||
ipcRenderer.send("${Constants.SIYUAN_EXPORT_PDF}", buildExportConfig(dynamicPageSize));
|
||||
} else {
|
||||
ipcRenderer.send("${Constants.SIYUAN_EXPORT_PDF}", buildExportConfig(pageSizeValue));
|
||||
}
|
||||
previewElement.classList.add("exporting");
|
||||
previewElement.style.zoom = "";
|
||||
previewElement.style.paddingTop = "6px";
|
||||
|
|
|
|||
|
|
@ -440,7 +440,8 @@ export const getLocalStorage = (cb: () => void) => {
|
|||
removeAssets: true,
|
||||
keepFold: false,
|
||||
mergeSubdocs: false,
|
||||
watermark: false
|
||||
watermark: false,
|
||||
paged: true
|
||||
};
|
||||
defaultStorage[Constants.LOCAL_EXPORTIMG] = {
|
||||
keepFold: false,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue