Fix v1.9.0 header/footer visibility issues

This commit fixes two critical issues in the v1.9.0 header/footer feature:
1. **Logo Upload Error Fix**:
   - Fixed "path undefined" error when uploading logos
   - Added validation in main.js to check filePath before processing
   - Added fallback in renderer.js to use webUtils.getPathForFile if file.path is undefined
   - Added file existence check before copying
2. **Header/Footer Visibility Fix**:
   - Added header/footer support to tryPdfFallback function (PDF fallback engines)
   - Previously, only performExportWithOptions had header/footer logic
   - Now all PDF export paths include headers/footers when enabled
   - Fallback engines now generate fancyhdr LaTeX code for headers/footers
Technical details:
- src/main.js:667-709: Enhanced logo upload handler with error checking
- src/main.js:1289-1319: Added header/footer to tryPdfFallback function
- src/renderer.js:2661-2678: Fixed logo file path handling
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
2025-10-28 17:41:37 +05:30
parent 6db204796f
commit 53871d788b
2 changed files with 93 additions and 1 deletions
+85
View File
@@ -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}"`;
+8 -1
View File
@@ -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 });