import {hideMessage, showMessage} from "../../dialog/message"; import {Constants} from "../../constants"; /// #if !BROWSER import {ipcRenderer, OpenDialogReturnValue} from "electron"; import {BrowserWindow, dialog} from "@electron/remote"; import * as fs from "fs"; import * as path from "path"; import {afterExport} from "./util"; /// #endif import {confirmDialog} from "../../dialog/confirmDialog"; import {setInlineStyle} from "../../util/assets"; import {fetchPost} from "../../util/fetch"; import {Dialog} from "../../dialog"; import {lockFile} from "../../dialog/processSystem"; import {pathPosix} from "../../util/pathName"; import {replaceLocalPath} from "../../editor/rename"; export const saveExport = (option: { type: string, id: string }) => { /// #if !BROWSER if (option.type === "pdf") { if (window.siyuan.config.appearance.mode === 1) { confirmDialog(window.siyuan.languages.pdfTip, window.siyuan.languages.pdfConfirm, () => { renderPDF(option.id); }); } else { renderPDF(option.id); } } else if (option.type === "word") { const localData = localStorage.getItem(Constants.LOCAL_EXPORTWORD); const wordDialog = new Dialog({ title: "Word " + window.siyuan.languages.config, content: `
`, width: "520px", }); const btnsElement = wordDialog.element.querySelectorAll(".b3-button"); btnsElement[0].addEventListener("click", () => { wordDialog.destroy(); }); btnsElement[1].addEventListener("click", () => { const removeAssets = (wordDialog.element.querySelector("#removeAssets") as HTMLInputElement).checked; localStorage.setItem(Constants.LOCAL_EXPORTWORD, removeAssets.toString()); getExportPath(option, removeAssets); wordDialog.destroy(); }); } else { getExportPath(option); } /// #endif }; /// #if !BROWSER const destroyWin = (win: Electron.BrowserWindow) => { win.destroy(); }; const renderPDF = (id: string) => { const localData = JSON.parse(localStorage.getItem(Constants.LOCAL_EXPORTPDF) || JSON.stringify({ printBackground: true, landscape: false, marginsType: 0, scaleFactor: 100, pageSize: "A4", removeAssets: true, })); const servePath = window.location.protocol + "//" + window.location.host; const win = new BrowserWindow({ show: true, width: 1032, resizable: false, frame: "darwin" === window.siyuan.config.system.os, icon: path.join(window.siyuan.config.system.appDir, 'stage', 'icon-large.png'), titleBarStyle: "hidden", webPreferences: { contextIsolation: false, nodeIntegration: true, webviewTag: true, webSecurity: false, }, }); ipcRenderer.on(Constants.SIYUAN_EXPORT_CLOSE, () => { win.destroy(); }); ipcRenderer.on(Constants.SIYUAN_EXPORT_PDF, (e, ipcData) => { dialog.showOpenDialog({ title: window.siyuan.languages.export + " PDF", properties: ["createDirectory", "openDirectory"], }).then((result: OpenDialogReturnValue) => { if (result.canceled) { destroyWin(win); return; } setTimeout(() => { const msgId = showMessage(window.siyuan.languages.exporting, -1); const filePath = result.filePaths[0].endsWith(ipcData.rootTitle) ? result.filePaths[0] : path.join(result.filePaths[0], replaceLocalPath(ipcData.rootTitle)); localStorage.setItem(Constants.LOCAL_EXPORTPDF, JSON.stringify(Object.assign(ipcData.pdfOptions, {removeAssets: ipcData.removeAssets}))); try { win.webContents.printToPDF(ipcData.pdfOptions).then((pdfData) => { fetchPost("/api/export/exportHTML", { id: ipcData.rootId, pdf: true, removeAssets: ipcData.removeAssets, savePath: filePath }, () => { const pdfFilePath = path.join(filePath, path.basename(filePath) + ".pdf"); fs.writeFileSync(pdfFilePath, pdfData); destroyWin(win); fetchPost("/api/export/addPDFOutline", { id: ipcData.rootId, path: pdfFilePath }, () => { afterExport(pdfFilePath, msgId); if (ipcData.removeAssets) { const removePromise = (dir: string) => { return new Promise(function (resolve) { //先读文件夹 fs.stat(dir, function (err, stat) { if (stat) { if (stat.isDirectory()) { fs.readdir(dir, function (err, files) { files = files.map(file => path.join(dir, file)); // a/b a/m Promise.all(files.map(file => removePromise(file))).then(function () { fs.rmdir(dir, resolve); }); }); } else { fs.unlink(dir, resolve); } } }); }); }; removePromise(path.join(filePath, "assets")); } }); }); }).catch((error: string) => { showMessage("Export PDF error:" + error, 0, "error", msgId); destroyWin(win); }); } catch (e) { showMessage("Export PDF failed: " + e, 0, "error", msgId); destroyWin(win); } }, 200); }); }); let pdfWidth = ""; if (localData.pageSize === "A3") { if (localData.landscape) { pdfWidth = "16.5"; } else { pdfWidth = "11.7"; } } else if (localData.pageSize === "A4") { if (localData.landscape) { pdfWidth = "11.7"; } else { pdfWidth = "8.8"; } } else if (localData.pageSize === "A5") { if (localData.landscape) { pdfWidth = "8.3"; } else { pdfWidth = "5.8"; } } else if (localData.pageSize === "Legal") { if (localData.landscape) { pdfWidth = "14"; } else { pdfWidth = "8.5"; } } else if (localData.pageSize === "Letter") { if (localData.landscape) { pdfWidth = "11"; } else { pdfWidth = "8.5"; } } else if (localData.pageSize === "Tabloid") { if (localData.landscape) { pdfWidth = "17"; } else { pdfWidth = "11"; } } let pdfMargin = "0.66"; if (localData.landscape) { pdfMargin = "1.69"; } if (localData.marginsType !== 0) { if (localData.landscape) { pdfMargin = "1.69"; } else { pdfMargin = "0.3"; } } const html = ` ${window.siyuan.languages.export} PDF - {tpl.name}

${window.siyuan.languages.config}

{tpl.content}
`; win.loadURL("data:text/html;charset=UTF-8," + encodeURIComponent(`
`)); win.webContents.on("did-finish-load", () => { if (win.webContents.getURL().startsWith("data:text/html;charset=UTF-8,")) { fetchPost("/api/export/exportPreviewHTML", { id, tpl: html }, response => { if (response.code === 1) { document.getElementById("message").firstElementChild.innerHTML === ""; showMessage(response.msg, undefined, "error"); destroyWin(win); return; } win.loadURL(response.data.url); }); } }); }; const getExportPath = (option: { type: string, id: string }, removeAssets?: boolean) => { fetchPost("/api/block/getBlockInfo", { id: option.id }, (response) => { if (response.code === 2) { // 文件被锁定 lockFile(response.data); return; } let exportType = "HTML (SiYuan)"; switch (option.type) { case "htmlmd": exportType = "HTML (Markdown)"; break; case "word": exportType = "Word .docx"; break; case "pdf": exportType = "PDF"; break; } dialog.showOpenDialog({ title: window.siyuan.languages.export + " " + exportType, properties: ["createDirectory", "openDirectory"], }).then((result: OpenDialogReturnValue) => { if (!result.canceled) { const msgId = showMessage(window.siyuan.languages.exporting, -1); let url = "/api/export/exportHTML"; if (option.type === "htmlmd") { url = "/api/export/exportMdHTML"; } else if (option.type === "word") { url = "/api/export/exportDocx"; } const savePath = result.filePaths[0].endsWith(response.data.rootTitle) ? result.filePaths[0] : path.join(result.filePaths[0], replaceLocalPath(response.data.rootTitle)); fetchPost(url, { id: option.id, pdf: option.type === "pdf", removeAssets, savePath }, exportResponse => { if (option.type === "word") { if (exportResponse.code === 1) { showMessage(exportResponse.msg, undefined, "error"); hideMessage(msgId); return; } afterExport(savePath, msgId); } else { onExport(exportResponse, savePath, option.type, removeAssets, msgId); } }); } }); }); }; const onExport = (data: IWebSocketData, filePath: string, type: string, removeAssets?: boolean, msgId?: string) => { let themeName = window.siyuan.config.appearance.themeLight; let mode = 0; if (["html", "htmlmd"].includes(type) && window.siyuan.config.appearance.mode === 1) { themeName = window.siyuan.config.appearance.themeDark; mode = 1; } const html = ` ${pathPosix().basename(filePath)} - ${window.siyuan.languages.siyuanNote} v${Constants.SIYUAN_VERSION}
${data.data.content}
`; const htmlPath = path.join(filePath, "index.html"); fs.writeFileSync(htmlPath, html); afterExport(htmlPath, msgId); }; /// #endif