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
|
// Save header/footer logo image
|
||||||
ipcMain.on('save-header-footer-logo', async (event, { position, filePath }) => {
|
ipcMain.on('save-header-footer-logo', async (event, { position, filePath }) => {
|
||||||
try {
|
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
|
// Copy image to userData directory for persistent storage
|
||||||
const userDataPath = app.getPath('userData');
|
const userDataPath = app.getPath('userData');
|
||||||
const logoDir = path.join(userDataPath, 'logos');
|
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 });
|
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
|
// Generate unique filename
|
||||||
const ext = path.extname(filePath);
|
const ext = path.extname(filePath);
|
||||||
const filename = `${position}_${Date.now()}${ext}`;
|
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 });
|
event.reply('header-footer-logo-saved', { position, path: destPath });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Logo save error:', error);
|
||||||
dialog.showErrorBox('Logo Error', `Failed to save logo: ${error.message}`);
|
dialog.showErrorBox('Logo Error', `Failed to save logo: ${error.message}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1196,6 +1208,38 @@ function performExportWithOptions(format, options) {
|
|||||||
pandocCmd += ` --pdf-engine="${pdfEngine}"`;
|
pandocCmd += ` --pdf-engine="${pdfEngine}"`;
|
||||||
if (options.geometry) pandocCmd += ` -V geometry:"${options.geometry}"`;
|
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
|
// Try with specified PDF engine
|
||||||
exec(pandocCmd, (error) => {
|
exec(pandocCmd, (error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -1209,6 +1253,15 @@ function performExportWithOptions(format, options) {
|
|||||||
} else if (format === 'docx') {
|
} else if (format === 'docx') {
|
||||||
pandocCmd += ' -t docx';
|
pandocCmd += ' -t docx';
|
||||||
exportWithPandoc(pandocCmd, outputFile, format);
|
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 {
|
} else {
|
||||||
// Generic export for other formats
|
// Generic export for other formats
|
||||||
exportWithPandoc(pandocCmd, outputFile, format);
|
exportWithPandoc(pandocCmd, outputFile, format);
|
||||||
@@ -1233,6 +1286,38 @@ function tryPdfFallback(inputFile, outputFile, engines, index, options, lastErro
|
|||||||
// Add geometry if specified
|
// Add geometry if specified
|
||||||
if (options.geometry) pandocCmd = pandocCmd.replace(` -o `, ` -V geometry:"${options.geometry}" -o `);
|
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
|
// Add all other options
|
||||||
if (options.template && options.template !== 'default') {
|
if (options.template && options.template !== 'default') {
|
||||||
pandocCmd += ` --template="${options.template}"`;
|
pandocCmd += ` --template="${options.template}"`;
|
||||||
|
|||||||
+8
-1
@@ -2663,7 +2663,14 @@ function handleLogoSelection(position) {
|
|||||||
const input = document.getElementById(`${position}-logo`);
|
const input = document.getElementById(`${position}-logo`);
|
||||||
|
|
||||||
if (input.files && input.files[0]) {
|
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
|
// Send to main process to save
|
||||||
ipcRenderer.send('save-header-footer-logo', { position, filePath });
|
ipcRenderer.send('save-header-footer-logo', { position, filePath });
|
||||||
|
|||||||
Reference in New Issue
Block a user