Release v1.9.0: Custom Headers & Footers for Professional Document Exports

Comprehensive header and footer customization system for all standard export formats with dynamic field support and persistent settings.
 Major Features:
- Custom Headers & Footers for PDF, DOCX, ODT, and PowerPoint exports
- Three-column layout (Left/Center/Right) for both headers and footers
- Dynamic field support: $PAGE$, $TOTAL$, $DATE$, $TIME$, $TITLE$, $AUTHOR$, $FILENAME$
- Logo/image upload UI for header and footer branding
- Enable/disable toggle with persistent settings across sessions
- Field insertion helper dialog for quick dynamic field selection
- Complete dark theme support for all 22 themes
🎯 Export Format Support:
- PDF (Standard): LaTeX fancyhdr package with automatic page numbering
- DOCX (Standard): Word XML manipulation with PAGE and NUMPAGES fields
- ODT: OpenDocument format with Pandoc integration
- PowerPoint (PPTX): Footer text with dynamic field replacement
- Batch Converter: Full header/footer support for all formats
💡 Technical Implementation:
- processDynamicFields() function for field replacement
- LaTeX header generation with fancyhdr and lastpage packages
- Word XML manipulation using PizZip for DOCX headers/footers
- addHeaderFooterToDocx() function for post-processing DOCX exports
- buildPandocCommand() enhanced with header/footer parameters
- IPC handlers for dialog communication and settings management
🎨 User Interface:
- New "Header & Footer Settings..." menu option in File menu
- Professional configuration dialog with field previews
- Logo upload with file path display and clear buttons
- Dynamic field picker popup dialog
- Responsive grid layout for three-column design
- Smooth transitions and animations
📦 Integration Points:
- Menu system (File → Header & Footer Settings...)
- Standard export functions (PDF, DOCX, ODT, PPTX)
- Batch converter with full format support
- Settings persistence via electron-store
- Logo file management in userData directory
🔧 Code Changes:
- src/main.js: Added header/footer IPC handlers, state management, processDynamicFields(), addHeaderFooterToDocx(), enhanced buildPandocCommand() and performBatchConversion()
- src/index.html: Added header/footer dialog and field picker dialog
- src/renderer.js: Added dialog management, logo handling, field insertion
- src/styles.css: Added comprehensive dialog styling with dark theme support
- package.json: Updated version to 1.9.0
- CLAUDE.md: Documented v1.9.0 features and implementation details
📝 Note: Enhanced exports (DOCX Enhanced, PDF Enhanced) use Word templates with pre-configured headers/footers. This feature specifically targets standard (non-templated) exports.
🚀 Impact:
Users can now add professional headers and footers to all document exports with custom branding, dynamic page numbers, dates, and titles - significantly improving document presentation for business and academic use cases.
🤖 Generated with Claude Code
This commit is contained in:
2025-10-28 17:34:32 +05:30
parent 8fbfe68823
commit 6db204796f
6 changed files with 1092 additions and 139 deletions
+272
View File
@@ -3157,4 +3157,276 @@ body.printing-no-styles .preview-content pre,
.print-no-styles .preview-content blockquote {
color: #333 !important;
border-color: #999 !important;
}
/* ================================
Header & Footer Dialog Styles
================================ */
.hf-enable-section {
margin-bottom: 20px;
padding: 15px;
background: var(--bg-secondary, #f5f5f5);
border-radius: 5px;
}
.hf-enable-section label {
display: flex;
align-items: center;
font-weight: 600;
cursor: pointer;
}
.hf-enable-section input[type="checkbox"] {
margin-right: 10px;
width: 18px;
height: 18px;
cursor: pointer;
}
#hf-config-content {
transition: opacity 0.3s ease;
}
#hf-config-content.disabled {
opacity: 0.5;
pointer-events: none;
}
.hf-section {
margin-bottom: 25px;
padding: 20px;
background: var(--bg-tertiary, #fafafa);
border-radius: 8px;
border: 1px solid var(--border-color, #e0e0e0);
}
.hf-section h4 {
margin: 0 0 15px 0;
color: var(--text-primary, #333);
font-size: 16px;
border-bottom: 2px solid var(--accent-color, #007bff);
padding-bottom: 8px;
}
.hf-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
margin-bottom: 15px;
}
.hf-column {
display: flex;
flex-direction: column;
position: relative;
}
.hf-column label {
font-weight: 600;
margin-bottom: 5px;
color: var(--text-secondary, #666);
font-size: 13px;
}
.hf-column input[type="text"] {
padding: 8px 35px 8px 10px;
border: 1px solid var(--border-color, #ccc);
border-radius: 4px;
font-size: 14px;
background: var(--input-bg, white);
color: var(--text-primary, #333);
transition: border-color 0.2s ease;
}
.hf-column input[type="text"]:focus {
outline: none;
border-color: var(--accent-color, #007bff);
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.1);
}
.field-insert-btn {
position: absolute;
right: 5px;
bottom: 5px;
width: 28px;
height: 28px;
padding: 0;
background: var(--accent-color, #007bff);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 18px;
line-height: 1;
transition: all 0.2s ease;
}
.field-insert-btn:hover {
background: var(--accent-hover, #0056b3);
transform: scale(1.05);
}
.field-insert-btn:active {
transform: scale(0.95);
}
.hf-logo-row {
display: flex;
align-items: center;
gap: 10px;
padding: 15px;
background: var(--bg-secondary, #f5f5f5);
border-radius: 6px;
margin-top: 10px;
}
.hf-logo-row label {
font-weight: 600;
color: var(--text-secondary, #666);
min-width: 120px;
}
.hf-logo-row input[type="file"] {
flex: 1;
padding: 6px 10px;
border: 1px solid var(--border-color, #ccc);
border-radius: 4px;
background: var(--input-bg, white);
color: var(--text-primary, #333);
font-size: 13px;
cursor: pointer;
}
.hf-logo-row input[type="file"]::-webkit-file-upload-button {
padding: 5px 12px;
background: var(--button-bg, #6c757d);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
}
.hf-logo-row input[type="file"]::-webkit-file-upload-button:hover {
background: var(--button-hover, #5a6268);
}
.clear-btn {
padding: 6px 12px;
background: var(--danger-color, #dc3545);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
transition: background 0.2s ease;
}
.clear-btn:hover {
background: var(--danger-hover, #c82333);
}
.logo-preview {
font-size: 12px;
color: var(--text-secondary, #666);
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hf-help {
margin-top: 20px;
padding: 15px;
background: var(--info-bg, #e7f3ff);
border-left: 4px solid var(--info-color, #007bff);
border-radius: 4px;
}
.hf-help p {
margin: 0 0 10px 0;
font-weight: 600;
color: var(--text-primary, #333);
}
.hf-help ul {
margin: 0;
padding-left: 20px;
list-style-type: none;
}
.hf-help li {
margin-bottom: 6px;
color: var(--text-secondary, #555);
font-size: 13px;
}
.hf-help code {
background: rgba(0, 123, 255, 0.1);
padding: 2px 6px;
border-radius: 3px;
font-family: 'Courier New', monospace;
color: var(--accent-color, #007bff);
font-weight: 600;
}
/* Field Picker Dialog */
.field-picker-list {
display: grid;
grid-template-columns: 1fr;
gap: 8px;
}
.field-option {
padding: 12px 16px;
background: var(--bg-secondary, #f5f5f5);
border: 1px solid var(--border-color, #ddd);
border-radius: 6px;
text-align: left;
cursor: pointer;
font-size: 14px;
color: var(--text-primary, #333);
transition: all 0.2s ease;
}
.field-option:hover {
background: var(--accent-color, #007bff);
color: white;
border-color: var(--accent-color, #007bff);
transform: translateX(5px);
}
/* Dark Theme Support for Header/Footer Dialog */
body[data-theme="dark"] .hf-enable-section,
body[data-theme="dark"] .hf-logo-row {
background: #2d2d2d;
}
body[data-theme="dark"] .hf-section {
background: #252525;
border-color: #404040;
}
body[data-theme="dark"] .hf-column input[type="text"],
body[data-theme="dark"] .hf-logo-row input[type="file"] {
background: #2d2d2d;
color: #e0e0e0;
border-color: #404040;
}
body[data-theme="dark"] .hf-help {
background: rgba(0, 123, 255, 0.15);
border-left-color: #0d6efd;
}
body[data-theme="dark"] .field-option {
background: #2d2d2d;
border-color: #404040;
color: #e0e0e0;
}
body[data-theme="dark"] .field-option:hover {
background: #0d6efd;
color: white;
}