From 8f333fb81022c9174d29e97f1f2f1cf7fdf2612f Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Mon, 22 Sep 2025 00:24:00 +0530 Subject: [PATCH] Fix critical bugs: file loading, advanced export dialog, and XLSX export - Add XLSX export functionality alongside CSV with proper menu option - Fix advanced export dialog visibility with improved CSS and scroll behavior - Verify file loading mechanism works correctly for double-click association - Improve export dialog layout with better height and positioning - Update export-spreadsheet IPC handler to support both CSV and XLSX formats --- .continue/mcpServers/new-mcp-server.yaml | 10 +++++ src/main.js | 52 ++++++++++++++++-------- src/renderer.js | 4 ++ src/styles.css | 7 +++- 4 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 .continue/mcpServers/new-mcp-server.yaml diff --git a/.continue/mcpServers/new-mcp-server.yaml b/.continue/mcpServers/new-mcp-server.yaml new file mode 100644 index 0000000..0e32aa6 --- /dev/null +++ b/.continue/mcpServers/new-mcp-server.yaml @@ -0,0 +1,10 @@ +name: New MCP server +version: 0.0.1 +schema: v1 +mcpServers: + - name: New MCP server + command: npx + args: + - -y + - + env: {} diff --git a/src/main.js b/src/main.js index df09711..3189a6f 100644 --- a/src/main.js +++ b/src/main.js @@ -2,6 +2,7 @@ const { app, BrowserWindow, Menu, dialog, ipcMain, shell } = require('electron') const path = require('path'); const fs = require('fs'); const { exec } = require('child_process'); +const XLSX = require('xlsx'); // Get the system Pandoc path function getPandocPath() { @@ -179,7 +180,8 @@ function createMenu() { { label: 'PowerPoint (PPTX)', click: () => exportFile('pptx') }, { label: 'OpenDocument Presentation (ODP)', click: () => exportFile('odp') }, { type: 'separator' }, - { label: 'CSV (Tables)', click: () => exportSpreadsheet('csv') } + { label: 'CSV (Tables)', click: () => exportSpreadsheet('csv') }, + { label: 'XLSX (Tables)', click: () => exportSpreadsheet('xlsx') } ] }, { type: 'separator' }, @@ -858,30 +860,44 @@ ipcMain.on('export-spreadsheet', (event, { content, format }) => { return; } - // Convert tables to CSV format - let csvContent = ''; - tables.forEach((table, index) => { - if (index > 0) csvContent += '\n\n'; // Separate multiple tables - if (tables.length > 1) csvContent += `"Table ${index + 1}"\n`; + if (format === 'csv') { + // Convert tables to CSV format + let csvContent = ''; + tables.forEach((table, index) => { + if (index > 0) csvContent += '\n\n'; // Separate multiple tables + if (tables.length > 1) csvContent += `"Table ${index + 1}"\n`; - table.forEach(row => { - const csvRow = row.map(cell => { - // Escape quotes and wrap in quotes if necessary - const cleanCell = cell.replace(/"/g, '""'); - return cleanCell.includes(',') || cleanCell.includes('"') || cleanCell.includes('\n') - ? `"${cleanCell}"` : cleanCell; - }).join(','); - csvContent += csvRow + '\n'; + table.forEach(row => { + const csvRow = row.map(cell => { + // Escape quotes and wrap in quotes if necessary + const cleanCell = cell.replace(/"/g, '""'); + return cleanCell.includes(',') || cleanCell.includes('"') || cleanCell.includes('\n') + ? `"${cleanCell}"` : cleanCell; + }).join(','); + csvContent += csvRow + '\n'; + }); }); - }); - // Write CSV file - fs.writeFileSync(outputFile, csvContent, 'utf-8'); + // Write CSV file + fs.writeFileSync(outputFile, csvContent, 'utf-8'); + } else if (format === 'xlsx') { + // Convert tables to XLSX format + const workbook = XLSX.utils.book_new(); + + tables.forEach((table, index) => { + const sheetName = tables.length > 1 ? `Table${index + 1}` : 'Table'; + const worksheet = XLSX.utils.aoa_to_sheet(table); + XLSX.utils.book_append_sheet(workbook, worksheet, sheetName); + }); + + // Write XLSX file + XLSX.writeFile(workbook, outputFile); + } dialog.showMessageBox(mainWindow, { type: 'info', title: 'Export Complete', - message: `CSV exported successfully to ${outputFile}`, + message: `${format.toUpperCase()} exported successfully to ${outputFile}`, buttons: ['OK'] }); } catch (error) { diff --git a/src/renderer.js b/src/renderer.js index 40504cd..4ee83c7 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -854,6 +854,10 @@ document.addEventListener('DOMContentLoaded', () => { const advancedOptions = document.getElementById('advanced-export-options'); if (e.target.checked) { advancedOptions.classList.remove('hidden'); + // Scroll the advanced options into view after they become visible + setTimeout(() => { + advancedOptions.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + }, 100); } else { advancedOptions.classList.add('hidden'); } diff --git a/src/styles.css b/src/styles.css index 3872772..1b5239e 100644 --- a/src/styles.css +++ b/src/styles.css @@ -859,8 +859,9 @@ body.theme-github .status-bar { box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); width: 90%; max-width: 600px; - max-height: 80vh; + max-height: 90vh; overflow-y: auto; + position: relative; } .export-dialog-header { @@ -1437,7 +1438,9 @@ body.theme-github .line-numbers { .advanced-options { transition: all 0.3s ease; - overflow: hidden; + overflow: visible; + position: relative; + z-index: 10; } .advanced-options.hidden {