From 1a6ca50e03b3ac9c37ad78521f9380992f995138 Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Fri, 24 Oct 2025 22:14:53 +0530 Subject: [PATCH] =?UTF-8?q?Enhance=20print=20menu=20with=20preview-only=20?= =?UTF-8?q?printing=20options=20(v1.7.7)=20-=20Added=20Print=20submenu=20t?= =?UTF-8?q?o=20File=20menu=20with=20two=20print=20options:=20=20=20*=20Pri?= =?UTF-8?q?nt=20Preview=20(Ctrl+P):=20Black=20text,=20no=20colors,=20ink-s?= =?UTF-8?q?aving=20=20=20*=20Print=20Preview=20(With=20Styles):=20Full=20c?= =?UTF-8?q?olors=20and=20styling=20-=20Implemented=20print=20handler=20tha?= =?UTF-8?q?t=20hides=20all=20editor=20UI=20and=20shows=20only=20preview=20?= =?UTF-8?q?-=20Editor,=20toolbar,=20tabs,=20and=20status=20bar=20hidden=20?= =?UTF-8?q?during=20printing=20-=20Added=20comprehensive=20CSS=20print=20s?= =?UTF-8?q?tylesheet=20with:=20=20=20*=20Smart=20page=20breaks=20for=20hea?= =?UTF-8?q?dings,=20tables,=20and=20paragraphs=20=20=20*=20Optimized=20for?= =?UTF-8?q?matting=20for=20code=20blocks,=20lists,=20and=20tables=20=20=20?= =?UTF-8?q?*=20Professional=20typography=20(12pt=20font=20size,=201.6=20li?= =?UTF-8?q?ne=20height)=20=20=20*=20Image=20optimization=20and=20proper=20?= =?UTF-8?q?link=20handling=20=20=20*=20Support=20for=20blockquotes,=20hori?= =?UTF-8?q?zontal=20rules,=20and=20other=20elements=20-=20Print-specific?= =?UTF-8?q?=20CSS=20classes=20for=20styling=20control=20-=20Preview=20auto?= =?UTF-8?q?matically=20restored=20after=20printing=20Features:=20-=20Print?= =?UTF-8?q?s=20only=20the=20rendered=20markdown=20preview=20(not=20source)?= =?UTF-8?q?=20-=20Two=20print=20modes:=20simple=20(black)=20and=20styled?= =?UTF-8?q?=20(colored)=20-=20Native=20OS=20print=20dialogs=20for=20all=20?= =?UTF-8?q?platforms=20-=20Professional=20output=20formatting=20with=20pag?= =?UTF-8?q?e=20breaks=20-=20Cross-platform=20support=20(Windows,=20macOS,?= =?UTF-8?q?=20Linux)=20=F0=9F=A4=96=20Generated=20with=20[Claude=20Code](h?= =?UTF-8?q?ttps://claude.com/claude-code)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 85 +++++++++++++++++++----- src/main.js | 52 +++++++++++---- src/renderer.js | 40 ++++++++++-- src/styles.css | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 311 insertions(+), 34 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 75db7a6..b8e3a2e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -116,38 +116,91 @@ gh release create v1.2.1 --title "Title" --notes "Release notes" \ ### v1.7.7 Print & Enhanced PDF Support (Latest) #### 🖨️ Native Print Functionality -**Added Print Command** (`src/main.js:202-206`, `src/renderer.js:1152-1162`) -- **Print Menu Item**: Added to File menu with `Ctrl+P` keyboard shortcut +**Added Print Submenu to File Menu** (`src/main.js:202-215`, `src/renderer.js:1152-1188`, `src/styles.css:2828-2994`) +- **Print Menu**: Submenu in File menu with two print options + - **Print Preview** (`Ctrl+P`) - Prints preview in black text, no background colors (ink-saving) + - **Print Preview (With Styles)** - Prints with full theme colors and styling +- **Preview-Only Printing**: Only renders the markdown preview, hides all editor UI - **Native Print Dialog**: Uses Electron's webContents.print() for native OS print dialogs -- **Print Settings**: Configured with background color printing and proper margins -- **Preview-Based Printing**: Prints the rendered markdown preview for professional output +- **Professional Output**: Automatically hides editor, toolbar, tabs, and status bar during print +- **Print Optimization**: Smart page breaks, proper formatting for headings, code blocks, tables - **Cross-Platform**: Works on Windows, macOS, and Linux with native printer support +**Print Options:** +1. **Print Preview** (Ctrl+P) + - Black text on white background for professional printing + - No background colors to save ink + - Perfect for documents and reports + - Minimal ink consumption + +2. **Print Preview (With Styles)** + - Full theme colors and styling + - Preserves markdown formatting with visual hierarchy + - Better for design-focused documents + - Shows code blocks with colored syntax highlighting + **Technical Implementation:** ```javascript -// Main process handler -ipcMain.on('print-document', (event) => { - if (mainWindow) { +// Main process - two print handlers +ipcMain.on('print-preview', (event) => { + mainWindow.webContents.send('prepare-print-preview', false); + setTimeout(() => { + mainWindow.webContents.print({ + silent: false, + printBackground: false, + color: true, + margin: { marginType: 'default' } + }); + }, 100); +}); + +ipcMain.on('print-preview-styled', (event) => { + mainWindow.webContents.send('prepare-print-preview', true); + setTimeout(() => { mainWindow.webContents.print({ silent: false, printBackground: true, color: true, margin: { marginType: 'default' } }); - } + }, 100); }); -// Renderer process handler -ipcRenderer.on('print-document', () => { - const previewContent = document.getElementById('preview'); - if (previewContent && previewContent.innerHTML.trim()) { - window.print(); - } else { - alert('Nothing to print. Please create or open a document and ensure the preview is visible.'); +// Renderer process - prepares preview for printing +ipcRenderer.on('prepare-print-preview', (event, withStyles) => { + // Hide editor and UI elements + document.getElementById('editor-container').style.display = 'none'; + document.getElementById('toolbar').style.display = 'none'; + document.getElementById('tab-bar').style.display = 'none'; + document.getElementById('status-bar').style.display = 'none'; + + // Add print mode classes + const preview = document.getElementById('preview'); + preview.classList.add('print-mode'); + if (!withStyles) { + preview.classList.add('print-no-styles'); } + + // Restore UI after print + setTimeout(() => { + document.getElementById('editor-container').style.display = ''; + document.getElementById('toolbar').style.display = ''; + document.getElementById('tab-bar').style.display = ''; + document.getElementById('status-bar').style.display = ''; + preview.classList.remove('print-mode', 'print-no-styles'); + }, 500); }); ``` +**CSS Print Styles** (`src/styles.css:2828-2994`) +- Comprehensive @media print stylesheet +- Hides all UI elements in print view +- Optimizes preview for paper output +- Smart page breaks for headings and tables +- Proper formatting for code blocks, lists, tables +- Image optimization and link handling +- Professional typography with 12pt font size + #### 📦 Enhanced PDF Export Dependencies **Added Native PDF Generation Libraries** (package.json) - **PDFKit** (v0.14.0) - Native PDF generation without Pandoc dependency @@ -730,4 +783,4 @@ if (!gotTheLock) { --- **Last Updated**: October 24, 2025 -**Claude Assistant**: Development completed for v1.7.7 with native print functionality (Ctrl+P) and enhanced PDF support through PDFKit and html2pdf libraries. Added print command with native OS print dialogs for cross-platform printing of rendered markdown. Remapped Toggle Preview from Ctrl+P to Ctrl+Shift+P. Previous releases include v1.7.6 table header styling cleanup for cleaner preview appearance, and v1.7.5 critical file association fix with single-instance lock implementation. \ No newline at end of file +**Claude Assistant**: Development completed for v1.7.7 with enhanced print menu featuring two print options: "Print Preview" (Ctrl+P, black text, ink-saving) and "Print Preview (With Styles)" (full colors). Implemented comprehensive print handler that hides editor UI and shows only the rendered preview. Added extensive CSS print stylesheet with smart page breaks, optimized formatting for all markdown elements, and professional typography. Added PDFKit and html2pdf libraries for native PDF support without Pandoc dependency. Previous releases include v1.7.6 table header styling cleanup and v1.7.5 critical file association fix. \ No newline at end of file diff --git a/src/main.js b/src/main.js index 23ed8d8..dd2dca0 100644 --- a/src/main.js +++ b/src/main.js @@ -201,8 +201,17 @@ function createMenu() { { type: 'separator' }, { label: 'Print', - accelerator: 'CmdOrCtrl+P', - click: () => mainWindow.webContents.send('print-document') + submenu: [ + { + label: 'Print Preview', + accelerator: 'CmdOrCtrl+P', + click: () => mainWindow.webContents.send('print-preview') + }, + { + label: 'Print Preview (With Styles)', + click: () => mainWindow.webContents.send('print-preview-styled') + } + ] }, { type: 'separator' }, { @@ -1157,16 +1166,37 @@ ipcMain.on('set-current-file', (event, filePath) => { currentFile = filePath; }); -// Handle print document -ipcMain.on('print-document', (event) => { +// Handle print preview +ipcMain.on('print-preview', (event) => { if (mainWindow) { - // Open native print dialog - mainWindow.webContents.print({ - silent: false, - printBackground: true, - color: true, - margin: { marginType: 'default' } - }); + // Prepare for printing preview only (black text, no colors) + mainWindow.webContents.send('prepare-print-preview', false); + // Give renderer time to prepare, then print + setTimeout(() => { + mainWindow.webContents.print({ + silent: false, + printBackground: false, + color: true, + margin: { marginType: 'default' } + }); + }, 100); + } +}); + +// Handle print preview with styles +ipcMain.on('print-preview-styled', (event) => { + if (mainWindow) { + // Prepare for printing preview with colors + mainWindow.webContents.send('prepare-print-preview', true); + // Give renderer time to prepare, then print + setTimeout(() => { + mainWindow.webContents.print({ + silent: false, + printBackground: true, + color: true, + margin: { marginType: 'default' } + }); + }, 100); } }); diff --git a/src/renderer.js b/src/renderer.js index 5a4737e..5d45dc1 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -1149,16 +1149,42 @@ ipcRenderer.on('adjust-font-size', (event, action) => { updateFontSizes(currentFontSize); }); -// Print document handler -ipcRenderer.on('print-document', () => { - // Use the preview pane for printing +// Print preview handler - prepare for printing +ipcRenderer.on('prepare-print-preview', (event, withStyles) => { const previewContent = document.getElementById('preview'); - if (previewContent && previewContent.innerHTML.trim()) { - // Create a print window with the preview content - window.print(); - } else { + + if (!previewContent || !previewContent.innerHTML.trim()) { alert('Nothing to print. Please create or open a document and ensure the preview is visible.'); + return; } + + // Hide editor and other UI elements for print + document.getElementById('editor-container').style.display = 'none'; + document.getElementById('toolbar').style.display = 'none'; + document.getElementById('tab-bar').style.display = 'none'; + document.getElementById('status-bar').style.display = 'none'; + + // Show preview in full width + const preview = document.getElementById('preview'); + if (preview) { + preview.classList.add('print-mode'); + if (!withStyles) { + preview.classList.add('print-no-styles'); + } + } + + // Re-show everything after print + setTimeout(() => { + document.getElementById('editor-container').style.display = ''; + document.getElementById('toolbar').style.display = ''; + document.getElementById('tab-bar').style.display = ''; + document.getElementById('status-bar').style.display = ''; + + const preview = document.getElementById('preview'); + if (preview) { + preview.classList.remove('print-mode', 'print-no-styles'); + } + }, 500); }); // Export Dialog functionality diff --git a/src/styles.css b/src/styles.css index b240f54..1bf5075 100644 --- a/src/styles.css +++ b/src/styles.css @@ -2823,4 +2823,172 @@ body.theme-concrete-warm .status-bar { background: #3a3836; border-top-color: #9a9696; color: #e3e3e3; +} + +/* Print Styles */ +@media print { + /* Hide UI elements for clean print output */ + #toolbar, + #tab-bar, + #editor-container, + .editor-container, + #status-bar, + .status-bar { + display: none !important; + } + + /* Show preview in full width */ + #preview, + .preview, + .preview-content { + display: block !important; + width: 100% !important; + max-width: 100% !important; + height: auto !important; + margin: 0 !important; + padding: 20px !important; + overflow: visible !important; + } + + /* Optimize preview content for printing */ + .preview-content { + line-height: 1.6; + font-size: 12pt; + color: #000 !important; + background: white !important; + } + + /* Text formatting */ + .preview-content h1, + .preview-content h2, + .preview-content h3, + .preview-content h4, + .preview-content h5, + .preview-content h6 { + page-break-after: avoid; + margin-top: 1em; + margin-bottom: 0.5em; + } + + .preview-content p { + margin-bottom: 0.5em; + page-break-inside: avoid; + } + + /* Code blocks */ + .preview-content pre { + background: #f5f5f5 !important; + border: 1px solid #ddd !important; + page-break-inside: avoid; + padding: 10px; + font-size: 10pt; + } + + .preview-content code { + background: #f5f5f5 !important; + color: #000 !important; + font-size: 10pt; + } + + /* Lists */ + .preview-content ul, + .preview-content ol { + margin-left: 20px; + page-break-inside: avoid; + } + + .preview-content li { + page-break-inside: avoid; + margin-bottom: 0.3em; + } + + /* Tables */ + .preview-content table { + width: 100%; + border-collapse: collapse; + page-break-inside: avoid; + margin-bottom: 1em; + } + + .preview-content th, + .preview-content td { + border: 1px solid #999 !important; + padding: 8px !important; + text-align: left; + } + + .preview-content th { + background: #f0f0f0 !important; + font-weight: bold; + } + + /* Links - remove underline for print */ + .preview-content a { + color: #000 !important; + text-decoration: none; + } + + /* Blockquotes */ + .preview-content blockquote { + border-left: 3px solid #ccc; + padding-left: 15px; + margin-left: 0; + color: #333 !important; + } + + /* Images */ + .preview-content img { + max-width: 100%; + height: auto; + page-break-inside: avoid; + } + + /* Horizontal rules */ + .preview-content hr { + border: none; + border-top: 1px solid #999; + margin: 1em 0; + } +} + +/* Print mode classes */ +.print-mode { + display: block !important; + width: 100% !important; + max-width: 100% !important; +} + +.print-no-styles .preview-content { + color: #000 !important; + background: white !important; +} + +.print-no-styles .preview-content h1, +.print-no-styles .preview-content h2, +.print-no-styles .preview-content h3, +.print-no-styles .preview-content h4, +.print-no-styles .preview-content h5, +.print-no-styles .preview-content h6 { + color: #000 !important; + border-color: #999 !important; +} + +.print-no-styles .preview-content code { + background: #f5f5f5 !important; + color: #000 !important; +} + +.print-no-styles .preview-content pre { + background: #f5f5f5 !important; + color: #000 !important; + border-color: #999 !important; +} + +.print-no-styles .preview-content a { + color: #000 !important; +} + +.print-no-styles .preview-content blockquote { + color: #333 !important; + border-color: #999 !important; } \ No newline at end of file