Compare commits

..
12 Commits
Author SHA1 Message Date
amitwhandClaude 5376bddc59 Release v1.4.0: Advanced Export Options and Batch Conversion
Major Features:
• Fixed file association loading issue with proper timing
• Advanced export options dialog with templates and metadata support
• Batch file conversion system with progress tracking
• Enhanced UI with professional modal dialogs

Technical Improvements:
• Fixed renderer initialization timing for file association
• Added comprehensive Pandoc options support (templates, metadata, variables)
• Implemented recursive folder processing for batch operations
• Enhanced error handling and user feedback systems
• Theme-aware styling for all new components

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-14 22:42:53 +05:30
amitwhandClaude d3b67b1388 Bump version to v1.3.7
- Updated package.json version to 1.3.7
- Updated version in About dialog to 1.3.7
- Prepared for new release with Linux packages

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-01 23:34:38 +05:30
amitwhandClaude aac496923e Add font size adjustment menu and fix theme styling
Features:
• Added Font Size menu in View with increase/decrease/reset options
• Keyboard shortcuts: Ctrl+Shift+Plus/Minus/0 for font adjustment
• Font size persists between sessions using localStorage
• Font sizes adjustable from 10px to 24px

Theme Fixes:
• Fixed missing Monokai theme styles for tabs and editor
• Added complete tab styling for Solarized theme
• Added complete tab styling for GitHub theme
• All themes now have consistent tab bar appearance

Other Changes:
• Updated CLAUDE.md with v1.3.x features documentation
• Version bumped to 1.3.4

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-01 21:41:28 +05:30
amitwhandClaude 256f944b88 Increase editor and preview font sizes to 15px
Enhanced font sizes for improved readability:
• Editor font size increased from 14px to 15px
• Preview font size set to 15px for both #preview and .preview-content
• Better visual experience across all themes and content types

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-01 21:30:57 +05:30
amitwh dbe57d2fad Fix v1.3.2: Restore proper preview text spacing and typography
- Restored ideal preview text spacing from earlier versions
- Extended all preview styles to work with new .preview-content class
- Added proper margins, padding, and line-height for readability
- Updated theme support for all preview elements across all themes
- Improved typography with balanced font size and spacing
- Fixed double padding issue with better container structure
- Enhanced readability with proper heading margins and paragraph spacing
- Updated to version 1.3.2 with improved preview typography
2025-09-01 21:24:40 +05:30
amitwh 9a45849003 Update README.md for v1.3.1 release 2025-09-01 21:08:29 +05:30
amitwh dfb603c2ea Fix v1.3.1: File associations and 50/50 pane layout
- Enhanced file association handling for double-clicking .md files
- Added proper file associations in package.json build config
- Fixed preview/source pane layout to be equally distributed 50/50
- Updated CSS for tab-content structure with proper flex layout
- Added theme support for new pane selectors
- Improved command line argument processing for file opening
- Updated version to 1.3.1 with file association feature
2025-09-01 21:05:01 +05:30
amitwh fda173d9a1 Merge branch 'master' into macos 2025-09-01 20:58:00 +05:30
amitwh 5cbcfa466d Merge branch 'master' into macos 2025-09-01 20:53:29 +05:30
amitwh edb163eab4 Merge master with comprehensive v1.2.0 editor enhancements 2025-09-01 20:29:13 +05:30
amitwh 7b5165bcb1 Update README.md with v1.2.0 features and remove CLAUDE.md 2025-09-01 20:07:13 +05:30
amitwh bd38c5342d Update About dialog to version 1.2.0 with new features list 2025-09-01 20:03:08 +05:30
9 changed files with 2088 additions and 103 deletions
+88 -10
View File
@@ -4,9 +4,9 @@
**PanConverter** is a cross-platform Markdown editor and converter powered by Pandoc, built with Electron. It provides professional-grade editing capabilities with comprehensive export options.
**Current Version**: v1.2.1
**Author**: Amit Haridas (amit.wh@gmail.com)
**License**: MIT
**Current Version**: v1.4.0
**Author**: Amit Haridas (amit.wh@gmail.com)
**License**: MIT
**Repository**: https://github.com/amitwh/pan-converter
## Architecture & Technology Stack
@@ -23,14 +23,15 @@
```
src/
├── main.js # Electron main process, menu system, IPC handlers
├── renderer.js # UI logic, editor functionality, event handling
├── index.html # Application layout and components
├── renderer.js # TabManager class, multi-file editing, event handling
├── index.html # Application layout with tabbed interface
└── styles.css # Comprehensive styling with multi-theme support
assets/
└── icon.png # Application icon
package.json # Dependencies and build configuration
CLAUDE.md # Development documentation for AI assistants
```
## Development Commands
@@ -108,6 +109,72 @@ gh release create v1.2.1 --title "Title" --notes "Release notes" \
## Feature Implementation Guide
### v1.4.0 Advanced Export & Batch Processing (Latest)
#### 🔧 Fixed File Association Support
**File Loading Fix** (`src/main.js:385-390`, `src/renderer.js:485-486`)
- Fixed timing issue with file association loading
- Added proper `renderer-ready` event to ensure TabManager is initialized
- Files now open correctly when double-clicked or opened via right-click menu
- Command-line file arguments are properly handled on startup
#### 🎛️ Advanced Export Options Dialog
**Template & Metadata Support** (`src/main.js:247-357`, `src/index.html:117-212`)
- Comprehensive export options dialog with professional UI
- Template selection (default or custom template files)
- Metadata fields (title, author, date, subject) with dynamic field addition
- Document options: Table of Contents, section numbering, citations
- PDF-specific options: Engine selection (XeLaTeX, PDFLaTeX, LuaLaTeX), custom margins
- Bibliography support: .bib, .yaml, .json files with CSL styling
- All export formats now use enhanced options dialog
#### 📁 Batch File Conversion System
**Multi-File Processing** (`src/main.js:179-186`, `src/main.js:559-690`)
- New "Batch" menu for converting entire folders
- Recursive folder processing with progress tracking
- Support for all export formats with advanced options
- Real-time progress bar and file-by-file status updates
- Maintains folder structure in output directory
- Error handling with completion statistics
#### 🎨 Enhanced UI Components
**Dialog System** (`src/styles.css:838-1361`)
- Professional modal dialogs with backdrop and animations
- Theme-aware styling for all new components
- Responsive layouts with proper accessibility
- Form validation and user feedback systems
- Progress indicators for long-running operations
### v1.3.x Tabbed Interface & Enhanced Features
#### 🗂️ Tabbed Multi-File Support (v1.3.0)
**TabManager Class** (`src/renderer.js`)
- Complete tab management system for multiple files
- Tab switching, creation, and closure
- State preservation per tab (content, cursor position, scroll)
- File path tracking for each tab
- Keyboard shortcuts: `Ctrl/Cmd+T` (new tab), `Ctrl/Cmd+W` (close tab)
#### 🎯 Enhanced PDF Export (v1.3.0)
**Multi-Engine Fallback System** (`src/main.js:239-280`)
- Primary: XeLaTeX with proper margins
- Fallback 1: PDFLaTeX
- Fallback 2: wkhtmltopdf
- Automatic engine detection and switching
#### 📁 File Association Support (v1.3.1)
**OS Integration** (`src/main.js:452-498`, `package.json:50-65`)
- Double-click .md files to open in PanConverter
- Command-line argument handling
- Pending file queue for startup loading
#### 🎨 Typography & Spacing (v1.3.2-1.3.3)
**Preview Enhancement** (`src/styles.css`)
- Restored ideal text spacing from v1.0
- Font sizes increased to 15px for better readability
- Comprehensive selector coverage for legacy and new containers
- Theme-aware typography for all content types
### v1.2.1 Comprehensive Editor Enhancements
#### ✨ Advanced Editor Features
@@ -189,19 +256,24 @@ gh release create v1.2.1 --title "Title" --notes "Release notes" \
## File Structure & Key Components
### Main Process (`src/main.js`)
- **Menu System**: Comprehensive menu with file operations, editing, conversion, view options
- **Menu System**: Comprehensive menu with file operations, editing, conversion, view options, batch processing
- **IPC Handlers**: Communication between main and renderer processes
- **File Operations**: Open, save, import/export functionality
- **File Operations**: Open, save, import/export functionality with file association support
- **Export System**: Advanced export with templates, metadata, and Pandoc integration
- **Batch Processing**: Multi-file conversion with progress tracking and error handling
- **Theme Management**: Persistent theme storage and application
- **Spreadsheet Export**: Table extraction and XLSX generation
- **About Dialog**: Application information and feature list
### Renderer Process (`src/renderer.js`)
- **Editor Initialization**: CodeMirror-like functionality with custom implementation
- **TabManager System**: Multi-file editing with state management
- **Find & Replace Engine**: Search algorithms with regex support
- **Undo/Redo Manager**: History stack management
- **Auto-indentation Logic**: Smart list continuation
- **Live Preview**: Real-time markdown rendering with DOMPurify
- **Export Dialog Management**: Advanced options collection and validation
- **Batch Conversion Interface**: Folder selection, progress tracking, and user feedback
- **Event Handling**: Keyboard shortcuts and UI interactions
- **Statistics Tracking**: Word/character counting
@@ -214,8 +286,11 @@ gh release create v1.2.1 --title "Title" --notes "Release notes" \
### HTML Structure (`src/index.html`)
- **Toolbar**: Feature buttons with SVG icons
- **Tab Bar**: Multi-file navigation with close buttons
- **Find Dialog**: Search and replace interface
- **Editor Container**: Line numbers and text editor
- **Export Options Dialog**: Advanced export configuration with templates and metadata
- **Batch Conversion Dialog**: Folder selection and conversion progress
- **Editor Container**: Line numbers and text editor with tab content management
- **Preview Pane**: Rendered markdown display
- **Status Bar**: Statistics and application status
@@ -227,6 +302,9 @@ gh release create v1.2.1 --title "Title" --notes "Release notes" \
- [ ] Line numbers sync correctly with content
- [ ] Undo/redo preserves cursor position
- [ ] Auto-indentation works with various list types
- [ ] File association loading (double-click .md files)
- [ ] Export options dialog with templates and metadata
- [ ] Batch conversion with progress tracking
- [ ] All themes render correctly for new components
- [ ] Export functions work with various document formats
- [ ] Table creation and export functionality
@@ -299,5 +377,5 @@ gh release create v1.2.1 --title "Title" --notes "Release notes" \
---
**Last Updated**: September 1, 2025
**Claude Assistant**: Development completed for v1.2.1 comprehensive editor enhancements
**Last Updated**: September 14, 2025
**Claude Assistant**: Development completed for v1.4.0 with fixed file associations, advanced export options with templates and metadata, batch file conversion system, and enhanced UI components.
+378
View File
@@ -0,0 +1,378 @@
\hypertarget{panconverter}{%
\section{PanConverter}\label{panconverter}}
A cross-platform Markdown editor and converter powered by Pandoc.
\begin{figure}
\centering
\includegraphics{assets/icon.png}
\caption{PanConverter}
\end{figure}
\hypertarget{features}{%
\subsection{Features}\label{features}}
\hypertarget{advanced-markdown-editor}{%
\subsubsection{✨ Advanced Markdown
Editor}\label{advanced-markdown-editor}}
\begin{itemize}
\tightlist
\item
🗂️ \textbf{Tabbed Interface} - Work with multiple files simultaneously
in separate tabs
\item
📝 \textbf{Rich Text Editor} - Full-featured editor with syntax
highlighting and comprehensive toolbar
\item
🔍 \textbf{Find \& Replace} - Powerful search and replace with match
highlighting and navigation
\item
🔢 \textbf{Line Numbers} - Toggle line numbers for easier code editing
and navigation
\item
↩️ \textbf{Smart Auto-Indentation} - Automatic list continuation and
intelligent indentation
\item
⏪ \textbf{Undo/Redo} - Full undo/redo support with keyboard shortcuts
\item
⌨️ \textbf{Advanced Shortcuts} - Tab indentation, line selection, and
smart text formatting
\item
📂 \textbf{File Association Support} - Open markdown files directly
from file manager
\end{itemize}
\hypertarget{themes-interface}{%
\subsubsection{🎨 Themes \& Interface}\label{themes-interface}}
\begin{itemize}
\tightlist
\item
👁️ \textbf{Live Preview} - See your markdown rendered in real-time
with synchronized scrolling
\item
🎨 \textbf{Multiple Themes} - Choose from Light, Dark, Solarized,
Monokai, or GitHub themes
\item
💾 \textbf{Auto-Save} - Never lose your work with automatic saving
every 30 seconds
\end{itemize}
\hypertarget{export-conversion}{%
\subsubsection{📤 Export \& Conversion}\label{export-conversion}}
\begin{itemize}
\tightlist
\item
📄 \textbf{Enhanced PDF Export} - Robust PDF generation with multiple
LaTeX engine fallbacks (XeLaTeX, PDFLaTeX, wkhtmltopdf)
\item
📄 \textbf{Document Export} - Convert to HTML, DOCX, LaTeX, RTF, ODT,
EPUB, PowerPoint (PPTX), and OpenDocument Presentation (ODP)
\item
📊 \textbf{Spreadsheet Export} - Export markdown tables to Excel
(XLSX/XLS) and OpenDocument Spreadsheet (ODS) formats
\item
📥 \textbf{Document Import} - Import DOCX, ODT, RTF, HTML, PDF, and
presentation files to markdown
\item
📋 \textbf{Table Creation Helper} - Built-in table generator for easy
markdown table creation
\end{itemize}
\hypertarget{platform-support}{%
\subsubsection{🖥️ Platform Support}\label{platform-support}}
\begin{itemize}
\tightlist
\item
\textbf{Cross-Platform} - Works seamlessly on Windows, macOS, and
Linux
\end{itemize}
\hypertarget{installation}{%
\subsection{Installation}\label{installation}}
\hypertarget{prerequisites}{%
\subsubsection{Prerequisites}\label{prerequisites}}
\begin{itemize}
\tightlist
\item
\href{https://pandoc.org/installing.html}{Pandoc} must be installed
for export functionality
\begin{itemize}
\tightlist
\item
\textbf{Ubuntu/Debian}: \texttt{sudo\ apt-get\ install\ pandoc}
\item
\textbf{macOS}: \texttt{brew\ install\ pandoc}
\item
\textbf{Windows}: Download installer from Pandoc website
\end{itemize}
\end{itemize}
\hypertarget{pdf-export-requirements}{%
\subsubsection{PDF Export Requirements}\label{pdf-export-requirements}}
For optimal PDF export, install a LaTeX engine (recommended): -
\textbf{Ubuntu/Debian}:
\texttt{sudo\ apt-get\ install\ texlive-xetex\ texlive-latex-base} -
\textbf{macOS}: \texttt{brew\ install\ -\/-cask\ mactex} -
\textbf{Windows}: Install MiKTeX or TeX Live - \textbf{Alternative}:
\texttt{sudo\ apt-get\ install\ wkhtmltopdf} (fallback option)
\hypertarget{download}{%
\subsubsection{Download}\label{download}}
Download the latest release for your platform from the
\href{https://github.com/amitwh/pan-converter/releases}{Releases} page.
\hypertarget{linux}{%
\paragraph{Linux}\label{linux}}
\begin{itemize}
\tightlist
\item
\textbf{AppImage}: \texttt{PanConverter-1.3.1.AppImage} (universal,
may require \texttt{-\/-no-sandbox} flag)
\item
\textbf{Debian Package}: \texttt{pan-converter\_1.3.1\_amd64.deb}
\item
\textbf{Snap Package}: \texttt{pan-converter\_1.3.1\_amd64.snap}
\end{itemize}
\hypertarget{install-from-source}{%
\subsubsection{Install from Source}\label{install-from-source}}
\begin{Shaded}
\begin{Highlighting}[]
\FunctionTok{git}\NormalTok{ clone https://github.com/amitwh/pan{-}converter.git}
\BuiltInTok{cd}\NormalTok{ pan{-}converter}
\ExtensionTok{npm}\NormalTok{ install}
\ExtensionTok{npm}\NormalTok{ start}
\end{Highlighting}
\end{Shaded}
\hypertarget{usage}{%
\subsection{Usage}\label{usage}}
\hypertarget{basic-workflow}{%
\subsubsection{Basic Workflow}\label{basic-workflow}}
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\tightlist
\item
\textbf{Write} - Use the editor to write your Markdown content
\item
\textbf{Preview} - Toggle the preview pane to see rendered output
\item
\textbf{Theme} - Choose your preferred theme from the View menu
\item
\textbf{Export} - Export your document to various formats
\end{enumerate}
\hypertarget{export-options}{%
\subsubsection{Export Options}\label{export-options}}
\begin{itemize}
\tightlist
\item
\textbf{Documents}: HTML, PDF, DOCX, LaTeX, RTF, ODT, EPUB
\item
\textbf{Presentations}: PowerPoint (PPTX), OpenDocument Presentation
(ODP)
\item
\textbf{Spreadsheets}: Excel (XLSX/XLS), OpenDocument Spreadsheet
(ODS)
\end{itemize}
\hypertarget{import-conversion}{%
\subsubsection{Import \& Conversion}\label{import-conversion}}
\begin{itemize}
\tightlist
\item
\textbf{Import Documents}: Convert DOCX, ODT, RTF, HTML, PDF, and
presentation files to Markdown
\item
\textbf{Cross-Format Conversion}: Convert current file between
multiple formats
\item
\textbf{Smart Presentation Handling}: Automatic slide-level formatting
for PPTX/ODP exports
\end{itemize}
\hypertarget{table-creation}{%
\subsubsection{Table Creation}\label{table-creation}}
\begin{itemize}
\tightlist
\item
Click the table button in the toolbar
\item
Specify number of rows and columns
\item
Automatically generates properly formatted Markdown tables
\end{itemize}
\hypertarget{keyboard-shortcuts}{%
\subsection{Keyboard Shortcuts}\label{keyboard-shortcuts}}
\hypertarget{file-operations}{%
\subsubsection{File Operations}\label{file-operations}}
\begin{itemize}
\tightlist
\item
\texttt{Ctrl/Cmd\ +\ N} - New file/tab
\item
\texttt{Ctrl/Cmd\ +\ T} - New tab
\item
\texttt{Ctrl/Cmd\ +\ W} - Close current tab
\item
\texttt{Ctrl/Cmd\ +\ Tab} - Switch to next tab
\item
\texttt{Ctrl/Cmd\ +\ O} - Open file
\item
\texttt{Ctrl/Cmd\ +\ S} - Save file
\item
\texttt{Ctrl/Cmd\ +\ Shift\ +\ S} - Save as
\item
\texttt{Ctrl/Cmd\ +\ I} - Import document
\end{itemize}
\hypertarget{editor-features}{%
\subsubsection{Editor Features}\label{editor-features}}
\begin{itemize}
\tightlist
\item
\texttt{Ctrl/Cmd\ +\ F} - Find \& Replace
\item
\texttt{Ctrl/Cmd\ +\ Z} - Undo
\item
\texttt{Ctrl/Cmd\ +\ Shift\ +\ Z} - Redo
\item
\texttt{Tab} - Indent lines or insert 4 spaces
\item
\texttt{Shift\ +\ Tab} - Outdent selected lines
\item
\texttt{Enter} - Auto-continue lists with proper indentation
\end{itemize}
\hypertarget{view-navigation}{%
\subsubsection{View \& Navigation}\label{view-navigation}}
\begin{itemize}
\tightlist
\item
\texttt{Ctrl/Cmd\ +\ P} - Toggle preview
\item
\texttt{Ctrl/Cmd\ +\ Enter} - Toggle preview (alternative)
\item
\texttt{Escape} - Close find dialog
\end{itemize}
\hypertarget{building}{%
\subsection{Building}\label{building}}
\begin{Shaded}
\begin{Highlighting}[]
\CommentTok{\# Install dependencies}
\ExtensionTok{npm}\NormalTok{ install}
\CommentTok{\# Generate icons}
\ExtensionTok{npm}\NormalTok{ run generate{-}icons}
\CommentTok{\# Build for current platform}
\ExtensionTok{npm}\NormalTok{ run build}
\CommentTok{\# Build for specific platform}
\ExtensionTok{npm}\NormalTok{ run build:win }\CommentTok{\# Windows}
\ExtensionTok{npm}\NormalTok{ run build:mac }\CommentTok{\# macOS }
\ExtensionTok{npm}\NormalTok{ run build:linux }\CommentTok{\# Linux (generates .deb, .AppImage, and .snap)}
\CommentTok{\# Build for all platforms}
\ExtensionTok{npm}\NormalTok{ run dist:all}
\end{Highlighting}
\end{Shaded}
\hypertarget{version-history}{%
\subsection{Version History}\label{version-history}}
\begin{itemize}
\tightlist
\item
\textbf{v1.3.1} - Bug fixes: Fixed file associations for
double-clicking .md files, corrected 50/50 layout alignment for
editor/preview panes
\item
\textbf{v1.3.0} - Major update: Tabbed interface for multiple files,
enhanced PDF export with LaTeX engines, fixed file associations,
removed redundant converter menu, improved UI architecture
\item
\textbf{v1.2.1} - Comprehensive editor enhancements: Find \& Replace,
Line Numbers, Undo/Redo, Auto-indentation, PowerPoint export, document
conversion menu, table creation helper, spreadsheet export
\item
\textbf{v1.1.0} - Added Excel/ODS spreadsheet export, updated author
information, renamed to PanConverter
\item
\textbf{v1.0.0} - Initial release with basic markdown editing, themes,
and Pandoc export
\end{itemize}
\hypertarget{known-issues}{%
\subsection{Known Issues}\label{known-issues}}
\begin{itemize}
\tightlist
\item
AppImage may require \texttt{-\/-no-sandbox} flag on some Linux
systems
\item
Windows/Mac builds require platform-specific build environments
\item
Large files may cause performance issues
\end{itemize}
\hypertarget{contributing}{%
\subsection{Contributing}\label{contributing}}
Contributions are welcome! Please feel free to submit a Pull Request to
the \href{https://github.com/amitwh/pan-converter}{GitHub repository}.
\hypertarget{license}{%
\subsection{License}\label{license}}
MIT License - see LICENSE file for details.
\hypertarget{author}{%
\subsection{Author}\label{author}}
\textbf{Amit Haridas} -
\href{mailto:amit.wh@gmail.com}{\nolinkurl{amit.wh@gmail.com}}
\hypertarget{acknowledgments}{%
\subsection{Acknowledgments}\label{acknowledgments}}
\begin{itemize}
\tightlist
\item
Built with \href{https://www.electronjs.org/}{Electron}
\item
Markdown parsing by \href{https://marked.js.org/}{marked}
\item
Export functionality powered by \href{https://pandoc.org/}{Pandoc}
\item
Syntax highlighting by \href{https://highlightjs.org/}{highlight.js}
\item
Spreadsheet export by \href{https://www.npmjs.com/package/xlsx}{XLSX}
\item
HTML sanitization by
\href{https://www.npmjs.com/package/dompurify}{DOMPurify}
\end{itemize}
+4 -3
View File
@@ -50,9 +50,9 @@ For optimal PDF export, install a LaTeX engine (recommended):
Download the latest release for your platform from the [Releases](https://github.com/amitwh/pan-converter/releases) page.
#### Linux
- **AppImage**: `PanConverter-1.3.0.AppImage` (universal, may require `--no-sandbox` flag)
- **Debian Package**: `pan-converter_1.3.0_amd64.deb`
- **Snap Package**: `pan-converter_1.3.0_amd64.snap`
- **AppImage**: `PanConverter-1.3.1.AppImage` (universal, may require `--no-sandbox` flag)
- **Debian Package**: `pan-converter_1.3.1_amd64.deb`
- **Snap Package**: `pan-converter_1.3.1_amd64.snap`
### Install from Source
```bash
@@ -133,6 +133,7 @@ npm run dist:all
## Version History
- **v1.3.1** - Bug fixes: Fixed file associations for double-clicking .md files, corrected 50/50 layout alignment for editor/preview panes
- **v1.3.0** - Major update: Tabbed interface for multiple files, enhanced PDF export with LaTeX engines, fixed file associations, removed redundant converter menu, improved UI architecture
- **v1.2.1** - Comprehensive editor enhancements: Find & Replace, Line Numbers, Undo/Redo, Auto-indentation, PowerPoint export, document conversion menu, table creation helper, spreadsheet export
- **v1.1.0** - Added Excel/ODS spreadsheet export, updated author information, renamed to PanConverter
BIN
View File
Binary file not shown.
+17 -1
View File
@@ -1,6 +1,6 @@
{
"name": "pan-converter",
"version": "1.3.0",
"version": "1.4.0",
"description": "Cross-platform Markdown editor and converter using Pandoc",
"main": "src/main.js",
"scripts": {
@@ -47,6 +47,22 @@
"node_modules/**/*",
"package.json"
],
"fileAssociations": [
{
"ext": "md",
"name": "Markdown Document",
"description": "Markdown Document",
"mimeType": "text/markdown",
"role": "Editor"
},
{
"ext": "markdown",
"name": "Markdown Document",
"description": "Markdown Document",
"mimeType": "text/markdown",
"role": "Editor"
}
],
"mac": {
"category": "public.app-category.productivity",
"icon": "assets/icon.icns"
+165 -1
View File
@@ -113,7 +113,171 @@
<span id="find-count">0 matches</span>
</div>
</div>
<!-- Export Options Dialog -->
<div id="export-dialog" class="export-dialog hidden">
<div class="export-dialog-content">
<div class="export-dialog-header">
<h3 id="export-dialog-title">Export Options</h3>
<button id="export-dialog-close" title="Close">×</button>
</div>
<div class="export-dialog-body">
<div class="export-section">
<label for="export-template">Template:</label>
<select id="export-template">
<option value="default">Default</option>
<option value="custom">Custom (Browse...)</option>
</select>
<input type="file" id="template-file-input" accept=".tex,.html,.docx,.odt" style="display: none;">
<input type="text" id="custom-template-path" placeholder="Template file path..." style="display: none;">
</div>
<div class="export-section">
<label>Metadata:</label>
<div class="metadata-container">
<div class="metadata-field">
<input type="text" placeholder="title" class="metadata-key">
<input type="text" placeholder="Document title" class="metadata-value">
</div>
<div class="metadata-field">
<input type="text" placeholder="author" class="metadata-key">
<input type="text" placeholder="Author name" class="metadata-value">
</div>
<div class="metadata-field">
<input type="text" placeholder="date" class="metadata-key">
<input type="text" placeholder="Date" class="metadata-value">
</div>
<div class="metadata-field">
<input type="text" placeholder="subject" class="metadata-key">
<input type="text" placeholder="Subject" class="metadata-value">
</div>
</div>
<button id="add-metadata-field" type="button">+ Add Field</button>
</div>
<div class="export-section">
<label>Document Options:</label>
<div class="checkbox-group">
<label><input type="checkbox" id="export-toc"> Table of Contents</label>
<label><input type="checkbox" id="export-number-sections"> Number Sections</label>
<label><input type="checkbox" id="export-citeproc"> Process Citations</label>
</div>
<div class="form-row">
<label for="export-toc-depth">TOC Depth:</label>
<input type="number" id="export-toc-depth" min="1" max="6" value="3">
</div>
</div>
<div class="export-section pdf-only">
<label>PDF Options:</label>
<div class="form-row">
<label for="pdf-engine">PDF Engine:</label>
<select id="pdf-engine">
<option value="xelatex">XeLaTeX (Recommended)</option>
<option value="pdflatex">PDFLaTeX</option>
<option value="lualatex">LuaLaTeX</option>
</select>
</div>
<div class="form-row">
<label for="pdf-geometry">Page Margins:</label>
<select id="pdf-geometry">
<option value="margin=1in">1 inch (Default)</option>
<option value="margin=0.75in">0.75 inch</option>
<option value="margin=1.25in">1.25 inch</option>
<option value="margin=2cm">2 cm</option>
<option value="margin=2.5cm">2.5 cm</option>
<option value="custom">Custom...</option>
</select>
<input type="text" id="custom-geometry" placeholder="e.g., margin=1.5in" style="display: none;">
</div>
</div>
<div class="export-section">
<label>Bibliography:</label>
<div class="form-row">
<input type="text" id="bibliography-file" placeholder="Bibliography file (.bib, .yaml, .json)">
<button id="browse-bibliography">Browse</button>
</div>
<div class="form-row">
<input type="text" id="csl-file" placeholder="Citation style file (.csl)">
<button id="browse-csl">Browse</button>
</div>
</div>
</div>
<div class="export-dialog-footer">
<button id="export-cancel">Cancel</button>
<button id="export-confirm" class="primary">Export</button>
</div>
</div>
</div>
<!-- Batch Conversion Dialog -->
<div id="batch-dialog" class="batch-dialog hidden">
<div class="batch-dialog-content">
<div class="batch-dialog-header">
<h3>Batch File Conversion</h3>
<button id="batch-dialog-close" title="Close">×</button>
</div>
<div class="batch-dialog-body">
<div class="batch-section">
<label>Input Folder:</label>
<div class="folder-input-group">
<input type="text" id="batch-input-folder" placeholder="Select folder containing markdown files..." readonly>
<button id="browse-input-folder">Browse</button>
</div>
</div>
<div class="batch-section">
<label>Output Folder:</label>
<div class="folder-input-group">
<input type="text" id="batch-output-folder" placeholder="Select output folder..." readonly>
<button id="browse-output-folder">Browse</button>
</div>
</div>
<div class="batch-section">
<label for="batch-format">Output Format:</label>
<select id="batch-format">
<option value="html">HTML</option>
<option value="pdf">PDF</option>
<option value="docx">DOCX</option>
<option value="latex">LaTeX</option>
<option value="rtf">RTF</option>
<option value="odt">ODT</option>
<option value="epub">EPUB</option>
<option value="pptx">PowerPoint (PPTX)</option>
<option value="odp">OpenDocument Presentation (ODP)</option>
</select>
</div>
<div class="batch-section">
<label>
<input type="checkbox" id="batch-include-subfolders" checked>
Include subfolders (recursive)
</label>
</div>
<div class="batch-section">
<button id="batch-show-options" type="button">Advanced Export Options...</button>
</div>
<div id="batch-progress" class="batch-progress hidden">
<div class="progress-bar">
<div class="progress-fill" id="batch-progress-fill"></div>
</div>
<div class="progress-text">
<span id="batch-progress-text">Processing...</span>
<span id="batch-progress-count">0 / 0</span>
</div>
</div>
</div>
<div class="batch-dialog-footer">
<button id="batch-cancel">Cancel</button>
<button id="batch-start" class="primary" disabled>Start Conversion</button>
</div>
</div>
</div>
<div class="editor-container">
<div class="tab-content active" id="tab-content-1" data-tab-id="1">
<div id="editor-pane-1" class="pane">
+292 -38
View File
@@ -49,13 +49,7 @@ function createWindow() {
mainWindow = null;
});
// Handle pending file from file association
if (app.pendingFile) {
mainWindow.webContents.once('dom-ready', () => {
openFileFromPath(app.pendingFile);
app.pendingFile = null;
});
}
// Handle pending file from file association will be handled by renderer-ready event
}
function createMenu() {
@@ -153,6 +147,27 @@ function createMenu() {
]
},
{ type: 'separator' },
{
label: 'Font Size',
submenu: [
{
label: 'Increase Font Size',
accelerator: 'CmdOrCtrl+Shift+Plus',
click: () => mainWindow.webContents.send('adjust-font-size', 'increase')
},
{
label: 'Decrease Font Size',
accelerator: 'CmdOrCtrl+Shift+-',
click: () => mainWindow.webContents.send('adjust-font-size', 'decrease')
},
{
label: 'Reset Font Size',
accelerator: 'CmdOrCtrl+Shift+0',
click: () => mainWindow.webContents.send('adjust-font-size', 'reset')
}
]
},
{ type: 'separator' },
{ label: 'Reload', accelerator: 'CmdOrCtrl+R', role: 'reload' },
{ label: 'Toggle DevTools', accelerator: 'F12', role: 'toggleDevTools' },
{ type: 'separator' },
@@ -161,6 +176,15 @@ function createMenu() {
{ label: 'Reset Zoom', accelerator: 'CmdOrCtrl+0', role: 'resetZoom' }
]
},
{
label: 'Batch',
submenu: [
{
label: 'Convert Folder...',
click: () => showBatchConversionDialog()
}
]
},
{
label: 'Help',
submenu: [
@@ -171,7 +195,7 @@ function createMenu() {
type: 'info',
title: 'About PanConverter',
message: 'PanConverter',
detail: 'A cross-platform Markdown editor and converter using Pandoc.\n\nVersion: 1.3.0\nAuthor: Amit Haridas\nEmail: amit.wh@gmail.com\nLicense: MIT\n\nFeatures:\n• Tabbed interface for multiple files\n• Advanced markdown editing with live preview\n• Enhanced PDF export with LaTeX engines\n• Find & replace with match highlighting\n• Line numbers and auto-indentation\n• Export to multiple formats via Pandoc\n• PowerPoint & presentation export\n• Export tables to Excel/ODS spreadsheets\n• Document import & conversion\n• Table creation helper\n• Multiple themes support\n• Undo/redo functionality',
detail: 'A cross-platform Markdown editor and converter using Pandoc.\n\nVersion: 1.4.0\nAuthor: Amit Haridas\nEmail: amit.wh@gmail.com\nLicense: MIT\n\nFeatures:\n• Tabbed interface for multiple files\n• Advanced markdown editing with live preview\n• Enhanced PDF export with LaTeX engines\n• File association support for .md files (Fixed in v1.4.0)\n• Advanced export options with templates and metadata\n• Batch file conversion with progress tracking\n• Improved preview typography and spacing\n• Adjustable font sizes via menu (Ctrl+Shift+Plus/Minus)\n• Complete theme support including Monokai fixes\n• Find & replace with match highlighting\n• Line numbers and auto-indentation\n• Export to multiple formats via Pandoc\n• PowerPoint & presentation export\n• Export tables to Excel/ODS spreadsheets\n• Document import & conversion\n• Table creation helper\n• Multiple themes support\n• Undo/redo functionality',
buttons: ['OK']
});
}
@@ -225,6 +249,19 @@ function exportFile(format) {
return;
}
// Show export options dialog
showExportOptionsDialog(format);
}
function showExportOptionsDialog(format) {
mainWindow.webContents.send('show-export-dialog', format);
}
function showBatchConversionDialog() {
mainWindow.webContents.send('show-batch-dialog');
}
function performExportWithOptions(format, options) {
const outputFile = dialog.showSaveDialogSync(mainWindow, {
defaultPath: currentFile.replace(/\.[^/.]+$/, `.${format}`),
filters: [
@@ -234,36 +271,50 @@ function exportFile(format) {
if (outputFile) {
let pandocCmd = `pandoc "${currentFile}" -o "${outputFile}"`;
// Add template if specified
if (options.template && options.template !== 'default') {
pandocCmd += ` --template="${options.template}"`;
}
// Add metadata
if (options.metadata) {
for (const [key, value] of Object.entries(options.metadata)) {
if (value.trim()) {
pandocCmd += ` -M ${key}="${value.replace(/"/g, '\\"')}"`;
}
}
}
// Add variables
if (options.variables) {
for (const [key, value] of Object.entries(options.variables)) {
if (value.trim()) {
pandocCmd += ` -V ${key}="${value.replace(/"/g, '\\"')}"`;
}
}
}
// Add other options
if (options.toc) pandocCmd += ' --toc';
if (options.tocDepth) pandocCmd += ` --toc-depth=${options.tocDepth}`;
if (options.numberSections) pandocCmd += ' --number-sections';
if (options.citeproc) pandocCmd += ' --citeproc';
if (options.bibliography) pandocCmd += ` --bibliography="${options.bibliography}"`;
if (options.csl) pandocCmd += ` --csl="${options.csl}"`;
// Add specific options for PDF export to ensure proper generation
if (format === 'pdf') {
pandocCmd = `pandoc "${currentFile}" --pdf-engine=xelatex -V geometry:margin=1in -o "${outputFile}"`;
// Try with different PDF engines if xelatex fails
const pdfEngine = options.pdfEngine || 'xelatex';
const geometry = options.geometry || 'margin=1in';
pandocCmd += ` --pdf-engine=${pdfEngine} -V geometry:${geometry}`;
// Try with specified PDF engine
exec(pandocCmd, (error, stdout, stderr) => {
if (error) {
// Fallback to pdflatex
const fallbackCmd = `pandoc "${currentFile}" --pdf-engine=pdflatex -V geometry:margin=1in -o "${outputFile}"`;
exec(fallbackCmd, (fallbackError, fallbackStdout, fallbackStderr) => {
if (fallbackError) {
// Final fallback to wkhtmltopdf
const htmlToPdfCmd = `pandoc "${currentFile}" -t html5 | wkhtmltopdf - "${outputFile}"`;
exec(htmlToPdfCmd, (finalError) => {
if (finalError) {
dialog.showErrorBox('PDF Export Error',
`Failed to export PDF. Please ensure you have one of the following installed:\n` +
`• XeLaTeX (recommended): sudo apt-get install texlive-xetex\n` +
`• PDFLaTeX: sudo apt-get install texlive-latex-base\n` +
`• wkhtmltopdf: sudo apt-get install wkhtmltopdf\n\n` +
`Error: ${finalError.message}`
);
} else {
showExportSuccess(outputFile);
}
});
} else {
showExportSuccess(outputFile);
}
});
// Try fallback engines if the specified one fails
const fallbackEngines = ['pdflatex', 'lualatex'];
tryPdfFallback(currentFile, outputFile, fallbackEngines, 0, options, error);
} else {
showExportSuccess(outputFile);
}
@@ -280,6 +331,44 @@ function exportFile(format) {
}
}
function tryPdfFallback(inputFile, outputFile, engines, index, options, lastError) {
if (index >= engines.length) {
dialog.showErrorBox('PDF Export Error',
`Failed to export PDF with all available engines. Please ensure you have one of the following installed:\n` +
`• XeLaTeX (recommended): sudo apt-get install texlive-xetex\n` +
`• PDFLaTeX: sudo apt-get install texlive-latex-base\n` +
`• LuaLaTeX: sudo apt-get install texlive-luatex\n\n` +
`Last error: ${lastError.message}`
);
return;
}
const engine = engines[index];
const geometry = options.geometry || 'margin=1in';
let pandocCmd = `pandoc "${inputFile}" --pdf-engine=${engine} -V geometry:${geometry} -o "${outputFile}"`;
// Add all other options
if (options.template && options.template !== 'default') {
pandocCmd += ` --template="${options.template}"`;
}
if (options.metadata) {
for (const [key, value] of Object.entries(options.metadata)) {
if (value.trim()) {
pandocCmd += ` -M ${key}="${value.replace(/"/g, '\\"')}"`;
}
}
}
exec(pandocCmd, (error, stdout, stderr) => {
if (error) {
tryPdfFallback(inputFile, outputFile, engines, index + 1, options, error);
} else {
showExportSuccess(outputFile);
}
});
}
function showExportSuccess(outputFile) {
dialog.showMessageBox(mainWindow, {
type: 'info',
@@ -366,6 +455,35 @@ ipcMain.on('set-current-file', (event, filePath) => {
currentFile = filePath;
});
// Handle renderer ready for file association
ipcMain.on('renderer-ready', (event) => {
if (app.pendingFile) {
openFileFromPath(app.pendingFile);
app.pendingFile = null;
}
});
// Handle export with options
ipcMain.on('export-with-options', (event, { format, options }) => {
performExportWithOptions(format, options);
});
// Handle batch conversion
ipcMain.on('batch-convert', (event, { inputFolder, outputFolder, format, options }) => {
performBatchConversion(inputFolder, outputFolder, format, options);
});
// Handle folder selection for batch conversion
ipcMain.on('select-folder', (event, type) => {
const folder = dialog.showOpenDialogSync(mainWindow, {
properties: ['openDirectory']
});
if (folder && folder[0]) {
event.reply('folder-selected', { type, path: folder[0] });
}
});
ipcMain.on('export-spreadsheet', (event, { content, format }) => {
const outputFile = dialog.showSaveDialogSync(mainWindow, {
defaultPath: currentFile.replace(/\.[^/.]+$/, `.${format}`),
@@ -449,14 +567,150 @@ function extractTablesFromMarkdown(markdown) {
return tables;
}
function performBatchConversion(inputFolder, outputFolder, format, options) {
if (!fs.existsSync(inputFolder)) {
dialog.showErrorBox('Error', 'Input folder does not exist');
return;
}
// Create output folder if it doesn't exist
if (!fs.existsSync(outputFolder)) {
try {
fs.mkdirSync(outputFolder, { recursive: true });
} catch (error) {
dialog.showErrorBox('Error', `Failed to create output folder: ${error.message}`);
return;
}
}
// Find all markdown files in input folder
const markdownFiles = [];
function findMarkdownFiles(dir) {
const files = fs.readdirSync(dir);
for (const file of files) {
const fullPath = path.join(dir, file);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
findMarkdownFiles(fullPath); // Recursive search
} else if (file.match(/\.(md|markdown)$/i)) {
markdownFiles.push(fullPath);
}
}
}
findMarkdownFiles(inputFolder);
if (markdownFiles.length === 0) {
dialog.showErrorBox('No Files Found', 'No markdown files found in the selected folder');
return;
}
// Show progress dialog
let completedCount = 0;
const totalCount = markdownFiles.length;
// Process each file
const processNextFile = (index) => {
if (index >= markdownFiles.length) {
// All files processed
dialog.showMessageBox(mainWindow, {
type: 'info',
title: 'Batch Conversion Complete',
message: `Successfully converted ${completedCount} out of ${totalCount} files to ${format.toUpperCase()}.`,
buttons: ['OK']
});
return;
}
const inputFile = markdownFiles[index];
const relativePath = path.relative(inputFolder, inputFile);
const baseName = path.basename(relativePath, path.extname(relativePath));
const outputFile = path.join(outputFolder, relativePath.replace(/\.(md|markdown)$/i, `.${format}`));
// Create subdirectories in output folder if needed
const outputDir = path.dirname(outputFile);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// Build pandoc command
let pandocCmd = `pandoc "${inputFile}" -o "${outputFile}"`;
// Add template if specified
if (options.template && options.template !== 'default') {
pandocCmd += ` --template="${options.template}"`;
}
// Add metadata
if (options.metadata) {
for (const [key, value] of Object.entries(options.metadata)) {
if (value.trim()) {
pandocCmd += ` -M ${key}="${value.replace(/"/g, '\\"')}"`;
}
}
}
// Add variables
if (options.variables) {
for (const [key, value] of Object.entries(options.variables)) {
if (value.trim()) {
pandocCmd += ` -V ${key}="${value.replace(/"/g, '\\"')}"`;
}
}
}
// Add other options
if (options.toc) pandocCmd += ' --toc';
if (options.tocDepth) pandocCmd += ` --toc-depth=${options.tocDepth}`;
if (options.numberSections) pandocCmd += ' --number-sections';
if (options.citeproc) pandocCmd += ' --citeproc';
if (options.bibliography) pandocCmd += ` --bibliography="${options.bibliography}"`;
if (options.csl) pandocCmd += ` --csl="${options.csl}"`;
// Add PDF-specific options
if (format === 'pdf') {
const pdfEngine = options.pdfEngine || 'xelatex';
const geometry = options.geometry || 'margin=1in';
pandocCmd += ` --pdf-engine=${pdfEngine} -V geometry:${geometry}`;
}
// Execute conversion
exec(pandocCmd, (error, stdout, stderr) => {
if (!error) {
completedCount++;
}
// Update progress (you could send this to renderer for a progress bar)
mainWindow.webContents.send('batch-progress', {
completed: index + 1,
total: totalCount,
currentFile: path.basename(inputFile),
success: !error
});
// Process next file
processNextFile(index + 1);
});
};
// Start processing
processNextFile(0);
}
app.whenReady().then(() => {
createWindow();
// Handle file association on app startup
if (process.argv.length > 1) {
const filePath = process.argv.find(arg => arg.endsWith('.md') || arg.endsWith('.markdown'));
if (filePath && fs.existsSync(filePath)) {
openFileFromPath(filePath);
// Process all command line arguments except the first two (node and script path)
const fileArgs = process.argv.slice(2);
for (const arg of fileArgs) {
if ((arg.endsWith('.md') || arg.endsWith('.markdown')) && fs.existsSync(arg)) {
// Store the file to open after window is ready
app.pendingFile = arg;
break;
}
}
});
+406 -2
View File
@@ -478,9 +478,12 @@ let tabManager;
document.addEventListener('DOMContentLoaded', () => {
tabManager = new TabManager();
// Request current theme
ipcRenderer.send('get-theme');
// Signal that renderer is ready for file operations
ipcRenderer.send('renderer-ready');
// Set up auto-save interval
setInterval(() => {
@@ -537,4 +540,405 @@ ipcRenderer.on('toggle-find', () => {
ipcRenderer.on('theme-changed', (event, theme) => {
document.body.className = `theme-${theme}`;
});
});
// Font size adjustment
let currentFontSize = parseInt(localStorage.getItem('fontSize')) || 15;
function updateFontSizes(size) {
const editors = document.querySelectorAll('#editor, .editor-textarea');
const previews = document.querySelectorAll('#preview, .preview-content');
editors.forEach(editor => {
editor.style.fontSize = `${size}px`;
});
previews.forEach(preview => {
preview.style.fontSize = `${size}px`;
});
localStorage.setItem('fontSize', size);
}
// Apply saved font size on load
updateFontSizes(currentFontSize);
ipcRenderer.on('adjust-font-size', (event, action) => {
if (action === 'increase' && currentFontSize < 24) {
currentFontSize++;
} else if (action === 'decrease' && currentFontSize > 10) {
currentFontSize--;
} else if (action === 'reset') {
currentFontSize = 15;
}
updateFontSizes(currentFontSize);
});
// Export Dialog functionality
let currentExportFormat = null;
ipcRenderer.on('show-export-dialog', (event, format) => {
currentExportFormat = format;
showExportDialog(format);
});
function showExportDialog(format) {
const dialog = document.getElementById('export-dialog');
const title = document.getElementById('export-dialog-title');
title.textContent = `Export as ${format.toUpperCase()}`;
dialog.setAttribute('data-format', format);
dialog.classList.remove('hidden');
// Initialize form values
initializeExportForm(format);
}
function hideExportDialog() {
const dialog = document.getElementById('export-dialog');
dialog.classList.add('hidden');
currentExportFormat = null;
}
function initializeExportForm(format) {
// Reset form to defaults
document.getElementById('export-template').value = 'default';
document.getElementById('custom-template-path').style.display = 'none';
// Clear metadata fields
const metadataFields = document.querySelectorAll('.metadata-field');
metadataFields.forEach((field, index) => {
if (index < 4) { // Keep first 4 default fields
field.querySelector('.metadata-key').value = ['title', 'author', 'date', 'subject'][index] || '';
field.querySelector('.metadata-value').value = '';
} else {
field.remove(); // Remove additional fields
}
});
// Reset checkboxes and other fields
document.getElementById('export-toc').checked = false;
document.getElementById('export-number-sections').checked = false;
document.getElementById('export-citeproc').checked = false;
document.getElementById('export-toc-depth').value = 3;
// PDF-specific fields
if (format === 'pdf') {
document.getElementById('pdf-engine').value = 'xelatex';
document.getElementById('pdf-geometry').value = 'margin=1in';
document.getElementById('custom-geometry').style.display = 'none';
}
// Clear bibliography fields
document.getElementById('bibliography-file').value = '';
document.getElementById('csl-file').value = '';
}
function collectExportOptions() {
const options = {
template: document.getElementById('export-template').value,
metadata: {},
variables: {},
toc: document.getElementById('export-toc').checked,
tocDepth: document.getElementById('export-toc-depth').value,
numberSections: document.getElementById('export-number-sections').checked,
citeproc: document.getElementById('export-citeproc').checked
};
// Collect custom template path
if (options.template === 'custom') {
options.template = document.getElementById('custom-template-path').value.trim();
}
// Collect metadata
const metadataFields = document.querySelectorAll('.metadata-field');
metadataFields.forEach(field => {
const key = field.querySelector('.metadata-key').value.trim();
const value = field.querySelector('.metadata-value').value.trim();
if (key && value) {
options.metadata[key] = value;
}
});
// PDF-specific options
if (currentExportFormat === 'pdf') {
options.pdfEngine = document.getElementById('pdf-engine').value;
const geometrySelect = document.getElementById('pdf-geometry');
if (geometrySelect.value === 'custom') {
options.geometry = document.getElementById('custom-geometry').value.trim() || 'margin=1in';
} else {
options.geometry = geometrySelect.value;
}
}
// Bibliography
const bibFile = document.getElementById('bibliography-file').value.trim();
const cslFile = document.getElementById('csl-file').value.trim();
if (bibFile) options.bibliography = bibFile;
if (cslFile) options.csl = cslFile;
return options;
}
// Event listeners for export dialog
document.addEventListener('DOMContentLoaded', () => {
// Template selection
document.getElementById('export-template').addEventListener('change', (e) => {
const customPath = document.getElementById('custom-template-path');
const fileInput = document.getElementById('template-file-input');
if (e.target.value === 'custom') {
customPath.style.display = 'block';
fileInput.style.display = 'block';
} else {
customPath.style.display = 'none';
fileInput.style.display = 'none';
customPath.value = '';
}
});
// Template file input
document.getElementById('template-file-input').addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
document.getElementById('custom-template-path').value = file.path;
}
});
// PDF geometry selection
document.getElementById('pdf-geometry').addEventListener('change', (e) => {
const customGeometry = document.getElementById('custom-geometry');
if (e.target.value === 'custom') {
customGeometry.style.display = 'block';
} else {
customGeometry.style.display = 'none';
}
});
// Add metadata field
document.getElementById('add-metadata-field').addEventListener('click', () => {
const container = document.querySelector('.metadata-container');
const newField = document.createElement('div');
newField.className = 'metadata-field';
newField.innerHTML = `
<input type="text" placeholder="key" class="metadata-key">
<input type="text" placeholder="value" class="metadata-value">
`;
container.appendChild(newField);
});
// Browse bibliography
document.getElementById('browse-bibliography').addEventListener('click', () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.bib,.yaml,.yml,.json';
input.onchange = (e) => {
const file = e.target.files[0];
if (file) {
document.getElementById('bibliography-file').value = file.path;
}
};
input.click();
});
// Browse CSL
document.getElementById('browse-csl').addEventListener('click', () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.csl';
input.onchange = (e) => {
const file = e.target.files[0];
if (file) {
document.getElementById('csl-file').value = file.path;
}
};
input.click();
});
// Dialog close buttons
document.getElementById('export-dialog-close').addEventListener('click', hideExportDialog);
document.getElementById('export-cancel').addEventListener('click', hideExportDialog);
// Export confirm
document.getElementById('export-confirm').addEventListener('click', () => {
const options = collectExportOptions();
ipcRenderer.send('export-with-options', {
format: currentExportFormat,
options: options
});
hideExportDialog();
});
// Close on backdrop click
document.getElementById('export-dialog').addEventListener('click', (e) => {
if (e.target === document.getElementById('export-dialog')) {
hideExportDialog();
}
});
// Close on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && !document.getElementById('export-dialog').classList.contains('hidden')) {
hideExportDialog();
}
});
});
// Batch Conversion Dialog functionality
let currentBatchOptions = {};
ipcRenderer.on('show-batch-dialog', () => {
showBatchDialog();
});
ipcRenderer.on('batch-progress', (event, progress) => {
updateBatchProgress(progress);
});
ipcRenderer.on('folder-selected', (event, { type, path }) => {
if (type === 'input') {
document.getElementById('batch-input-folder').value = path;
} else if (type === 'output') {
document.getElementById('batch-output-folder').value = path;
}
validateBatchForm();
});
function showBatchDialog() {
const dialog = document.getElementById('batch-dialog');
dialog.classList.remove('hidden');
// Reset form
document.getElementById('batch-input-folder').value = '';
document.getElementById('batch-output-folder').value = '';
document.getElementById('batch-format').value = 'html';
document.getElementById('batch-include-subfolders').checked = true;
document.getElementById('batch-progress').classList.add('hidden');
document.getElementById('batch-start').disabled = true;
currentBatchOptions = {
template: 'default',
metadata: {},
variables: {},
toc: false,
tocDepth: 3,
numberSections: false,
citeproc: false
};
}
function hideBatchDialog() {
const dialog = document.getElementById('batch-dialog');
dialog.classList.add('hidden');
}
function updateBatchProgress(progress) {
const progressSection = document.getElementById('batch-progress');
const progressFill = document.getElementById('batch-progress-fill');
const progressText = document.getElementById('batch-progress-text');
const progressCount = document.getElementById('batch-progress-count');
progressSection.classList.remove('hidden');
const percentage = Math.round((progress.completed / progress.total) * 100);
progressFill.style.width = `${percentage}%`;
if (progress.completed === progress.total) {
progressText.textContent = 'Conversion complete!';
} else {
progressText.textContent = `Processing: ${progress.currentFile}`;
}
progressCount.textContent = `${progress.completed} / ${progress.total}`;
}
function validateBatchForm() {
const inputFolder = document.getElementById('batch-input-folder').value.trim();
const outputFolder = document.getElementById('batch-output-folder').value.trim();
const startButton = document.getElementById('batch-start');
startButton.disabled = !inputFolder || !outputFolder;
}
// Event listeners for batch dialog
document.addEventListener('DOMContentLoaded', () => {
// Browse input folder
document.getElementById('browse-input-folder').addEventListener('click', () => {
ipcRenderer.send('select-folder', 'input');
});
// Browse output folder
document.getElementById('browse-output-folder').addEventListener('click', () => {
ipcRenderer.send('select-folder', 'output');
});
// Show advanced options
document.getElementById('batch-show-options').addEventListener('click', () => {
const format = document.getElementById('batch-format').value;
currentExportFormat = format;
showExportDialog(format);
});
// Dialog close buttons
document.getElementById('batch-dialog-close').addEventListener('click', hideBatchDialog);
document.getElementById('batch-cancel').addEventListener('click', hideBatchDialog);
// Start batch conversion
document.getElementById('batch-start').addEventListener('click', () => {
const inputFolder = document.getElementById('batch-input-folder').value.trim();
const outputFolder = document.getElementById('batch-output-folder').value.trim();
const format = document.getElementById('batch-format').value;
if (!inputFolder || !outputFolder) {
return;
}
// Use current export options from advanced dialog if they were set
const options = currentBatchOptions;
// Start batch conversion
ipcRenderer.send('batch-convert', {
inputFolder,
outputFolder,
format,
options
});
// Show progress
document.getElementById('batch-progress').classList.remove('hidden');
document.getElementById('batch-start').disabled = true;
});
// Close on backdrop click
document.getElementById('batch-dialog').addEventListener('click', (e) => {
if (e.target === document.getElementById('batch-dialog')) {
hideBatchDialog();
}
});
// Close on Escape key (modified to handle both dialogs)
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
if (!document.getElementById('export-dialog').classList.contains('hidden')) {
hideExportDialog();
} else if (!document.getElementById('batch-dialog').classList.contains('hidden')) {
hideBatchDialog();
}
}
});
// Input validation
document.getElementById('batch-input-folder').addEventListener('input', validateBatchForm);
document.getElementById('batch-output-folder').addEventListener('input', validateBatchForm);
});
// Override the export dialog confirm to also save batch options
const originalExportConfirm = document.getElementById('export-confirm');
if (originalExportConfirm) {
originalExportConfirm.addEventListener('click', () => {
// If batch dialog is open, save options for batch conversion
if (!document.getElementById('batch-dialog').classList.contains('hidden')) {
currentBatchOptions = collectExportOptions();
}
});
}
+738 -48
View File
File diff suppressed because it is too large Load Diff