From 53871d788b9bb9b882f31d44892d22db73e2f7d9 Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Tue, 28 Oct 2025 17:41:37 +0530 Subject: [PATCH] =?UTF-8?q?Fix=20v1.9.0=20header/footer=20visibility=20iss?= =?UTF-8?q?ues=20This=20commit=20fixes=20two=20critical=20issues=20in=20th?= =?UTF-8?q?e=20v1.9.0=20header/footer=20feature:=201.=20**Logo=20Upload=20?= =?UTF-8?q?Error=20Fix**:=20=20=20=20-=20Fixed=20"path=20undefined"=20erro?= =?UTF-8?q?r=20when=20uploading=20logos=20=20=20=20-=20Added=20validation?= =?UTF-8?q?=20in=20main.js=20to=20check=20filePath=20before=20processing?= =?UTF-8?q?=20=20=20=20-=20Added=20fallback=20in=20renderer.js=20to=20use?= =?UTF-8?q?=20webUtils.getPathForFile=20if=20file.path=20is=20undefined=20?= =?UTF-8?q?=20=20=20-=20Added=20file=20existence=20check=20before=20copyin?= =?UTF-8?q?g=202.=20**Header/Footer=20Visibility=20Fix**:=20=20=20=20-=20A?= =?UTF-8?q?dded=20header/footer=20support=20to=20tryPdfFallback=20function?= =?UTF-8?q?=20(PDF=20fallback=20engines)=20=20=20=20-=20Previously,=20only?= =?UTF-8?q?=20performExportWithOptions=20had=20header/footer=20logic=20=20?= =?UTF-8?q?=20=20-=20Now=20all=20PDF=20export=20paths=20include=20headers/?= =?UTF-8?q?footers=20when=20enabled=20=20=20=20-=20Fallback=20engines=20no?= =?UTF-8?q?w=20generate=20fancyhdr=20LaTeX=20code=20for=20headers/footers?= =?UTF-8?q?=20Technical=20details:=20-=20src/main.js:667-709:=20Enhanced?= =?UTF-8?q?=20logo=20upload=20handler=20with=20error=20checking=20-=20src/?= =?UTF-8?q?main.js:1289-1319:=20Added=20header/footer=20to=20tryPdfFallbac?= =?UTF-8?q?k=20function=20-=20src/renderer.js:2661-2678:=20Fixed=20logo=20?= =?UTF-8?q?file=20path=20handling=20=F0=9F=A4=96=20Generated=20with=20[Cla?= =?UTF-8?q?ude=20Code](https://claude.com/claude-code)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.js | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ src/renderer.js | 9 +++++- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/main.js b/src/main.js index e95ea56..7b10665 100644 --- a/src/main.js +++ b/src/main.js @@ -666,6 +666,11 @@ ipcMain.on('save-header-footer-settings', (event, settings) => { // Save header/footer logo image ipcMain.on('save-header-footer-logo', async (event, { position, filePath }) => { try { + if (!filePath) { + dialog.showErrorBox('Logo Error', 'Failed to save logo: The "path" argument must be of type string. Received undefined'); + return; + } + // Copy image to userData directory for persistent storage const userDataPath = app.getPath('userData'); const logoDir = path.join(userDataPath, 'logos'); @@ -675,6 +680,12 @@ ipcMain.on('save-header-footer-logo', async (event, { position, filePath }) => { fs.mkdirSync(logoDir, { recursive: true }); } + // Verify source file exists + if (!fs.existsSync(filePath)) { + dialog.showErrorBox('Logo Error', `Source file not found: ${filePath}`); + return; + } + // Generate unique filename const ext = path.extname(filePath); const filename = `${position}_${Date.now()}${ext}`; @@ -692,6 +703,7 @@ ipcMain.on('save-header-footer-logo', async (event, { position, filePath }) => { event.reply('header-footer-logo-saved', { position, path: destPath }); } catch (error) { + console.error('Logo save error:', error); dialog.showErrorBox('Logo Error', `Failed to save logo: ${error.message}`); } }); @@ -1196,6 +1208,38 @@ function performExportWithOptions(format, options) { pandocCmd += ` --pdf-engine="${pdfEngine}"`; if (options.geometry) pandocCmd += ` -V geometry:"${options.geometry}"`; + // Add header/footer if enabled + if (headerFooterSettings.enabled) { + const filename = currentFile ? path.basename(currentFile, path.extname(currentFile)) : 'document'; + const metadata = { filename, title: filename, author: '' }; + + const headerLeft = processDynamicFields(headerFooterSettings.header.left, metadata); + const headerCenter = processDynamicFields(headerFooterSettings.header.center, metadata); + const headerRight = processDynamicFields(headerFooterSettings.header.right, metadata); + const footerLeft = processDynamicFields(headerFooterSettings.footer.left, metadata); + const footerCenter = processDynamicFields(headerFooterSettings.footer.center, metadata); + const footerRight = processDynamicFields(headerFooterSettings.footer.right, metadata); + + // Create LaTeX header + const latexHeader = ` +\\usepackage{fancyhdr} +\\pagestyle{fancy} +\\fancyhf{} +\\lhead{${headerLeft.replace(/\\/g, '\\\\')}} +\\chead{${headerCenter.replace(/\\/g, '\\\\')}} +\\rhead{${headerRight.replace(/\\/g, '\\\\')}} +\\lfoot{${footerLeft.replace(/\\/g, '\\\\')}} +\\cfoot{${footerCenter.replace(/[$]PAGE[$]/g, '\\\\thepage').replace(/[$]TOTAL[$]/g, '\\\\pageref{LastPage}').replace(/\\/g, '\\\\')}} +\\rfoot{${footerRight.replace(/\\/g, '\\\\')}} +\\renewcommand{\\headrulewidth}{0.4pt} +\\renewcommand{\\footrulewidth}{0.4pt} +`; + const headerFile = path.join(require('os').tmpdir(), `header_export_${Date.now()}.tex`); + fs.writeFileSync(headerFile, latexHeader, 'utf-8'); + pandocCmd += ` --include-in-header="${headerFile}"`; + pandocCmd += ' --variable header-includes="\\\\usepackage{lastpage}"'; + } + // Try with specified PDF engine exec(pandocCmd, (error) => { if (error) { @@ -1209,6 +1253,15 @@ function performExportWithOptions(format, options) { } else if (format === 'docx') { pandocCmd += ' -t docx'; exportWithPandoc(pandocCmd, outputFile, format); + } else if (format === 'pptx') { + // Add PowerPoint footer if enabled + if (headerFooterSettings.enabled && headerFooterSettings.footer.center) { + const filename = currentFile ? path.basename(currentFile, path.extname(currentFile)) : 'document'; + const metadata = { filename, title: filename, author: '' }; + const footerText = processDynamicFields(headerFooterSettings.footer.center, metadata); + pandocCmd += ` --variable footer="${footerText}"`; + } + exportWithPandoc(pandocCmd, outputFile, format); } else { // Generic export for other formats exportWithPandoc(pandocCmd, outputFile, format); @@ -1233,6 +1286,38 @@ function tryPdfFallback(inputFile, outputFile, engines, index, options, lastErro // Add geometry if specified if (options.geometry) pandocCmd = pandocCmd.replace(` -o `, ` -V geometry:"${options.geometry}" -o `); + // Add header/footer if enabled + if (headerFooterSettings.enabled) { + const filename = path.basename(inputFile, path.extname(inputFile)); + const metadata = { filename, title: filename, author: options.metadata?.author || '' }; + + const headerLeft = processDynamicFields(headerFooterSettings.header.left, metadata); + const headerCenter = processDynamicFields(headerFooterSettings.header.center, metadata); + const headerRight = processDynamicFields(headerFooterSettings.header.right, metadata); + const footerLeft = processDynamicFields(headerFooterSettings.footer.left, metadata); + const footerCenter = processDynamicFields(headerFooterSettings.footer.center, metadata); + const footerRight = processDynamicFields(headerFooterSettings.footer.right, metadata); + + // Create LaTeX header for fancyhdr + const latexHeader = ` +\\usepackage{fancyhdr} +\\usepackage{lastpage} +\\pagestyle{fancy} +\\fancyhf{} +\\lhead{${headerLeft.replace(/\\/g, '\\\\')}} +\\chead{${headerCenter.replace(/\\/g, '\\\\')}} +\\rhead{${headerRight.replace(/\\/g, '\\\\')}} +\\lfoot{${footerLeft.replace(/\\/g, '\\\\')}} +\\cfoot{${footerCenter.replace(/\$PAGE\$/g, '\\\\thepage').replace(/\$TOTAL\$/g, '\\\\pageref{LastPage}').replace(/\\/g, '\\\\')}} +\\rfoot{${footerRight.replace(/\\/g, '\\\\')}} +\\renewcommand{\\headrulewidth}{0.4pt} +\\renewcommand{\\footrulewidth}{0.4pt} +`; + const headerFile = path.join(require('os').tmpdir(), `header_fallback_${Date.now()}.tex`); + fs.writeFileSync(headerFile, latexHeader, 'utf-8'); + pandocCmd += ` --include-in-header="${headerFile}"`; + } + // Add all other options if (options.template && options.template !== 'default') { pandocCmd += ` --template="${options.template}"`; diff --git a/src/renderer.js b/src/renderer.js index fbe0dd7..90abce8 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -2663,7 +2663,14 @@ function handleLogoSelection(position) { const input = document.getElementById(`${position}-logo`); if (input.files && input.files[0]) { - const filePath = input.files[0].path; + const file = input.files[0]; + // Use webUtils to get the real file path in Electron + const filePath = file.path || (window.electron && window.electron.webUtils ? window.electron.webUtils.getPathForFile(file) : null); + + if (!filePath) { + alert('Error: Could not get file path. Please try again.'); + return; + } // Send to main process to save ipcRenderer.send('save-header-footer-logo', { position, filePath });