mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-02 10:00:17 +05:30
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:
+85
@@ -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
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user