Export themes:
- Six presets in the export dialog (basic + advanced modes) for PDF/DOCX:
Default, Modern, Classic, Sepia, Minimal, Elegant
- PDF: LaTeX header (xcolor/titlesec) recolors headings, adds section
rules and colored links — core-TeX packages only, hex-literal only
(no injection surface)
- DOCX: styles.xml surgery recolors Heading1-6/Title/Subtitle/Hyperlink
and swaps heading/body fonts; verified end-to-end against a real
pandoc-produced docx
- Themes ride along in export presets (unknown ids fall back to Default)
Windows CI fixes:
- pdfjs standardFontDataUrl now a file:// URL (backslash paths failed
pdfjs's trailing-slash validation, breaking extractText/extractImages)
- sharp temp cleanup EPERM retries; path-separator assertions; pdfjs
test timeouts raised; batch suite testTimeout 30s
648/648 tests green; 4.7.1 linux+win artifacts rebuilt.
pdfjs validates standardFontDataUrl as a URL ending in a forward slash —
our raw path with a trailing path.sep is invalid on Windows (C:\...\),
failing extractText/extractImages (and every test that verifies through
them) with 'Invalid factory url: must include trailing slash'. Linux and
macOS passed only because / is also a valid URL slash. Convert with
pathToFileURL() so every platform sends file:///.../standard_fonts/.
Also escape path.sep in PDFBatchOperations' sanitizer test regex — a bare
backslash made new RegExp() a syntax error on Windows.
The Windows runner's git checkout rewrote assets/fonts/FiraCode-LICENSE.txt
line endings (autocrlf), changing its bytes and tripping the SHA-256 pin in
download-tools.js. A .gitattributes marks the license (-text) and all font/
image binaries as never-normalized so every platform checks out identical
bytes.
Branding:
- All app icons regenerated from the new vector brand kit (M↓ mark):
icon.png/icon@2x (app + packaging), favicon.png, tray-icon.png, and the
full assets/icons/ size set — generate-icons.js now rasterizes
app-icon.svg directly (docico1.png removed)
- index.html gets proper favicon/apple-touch links from the kit
- Welcome tab hero shows the new mark; README gets the horizontal wordmark
- assets/logo.png (ConcreteInfo) intentionally untouched
CI release fixes (win/mac jobs were failing):
- FiraCode download moved from moving raw/master URLs (hash drifted
upstream, tripping the pin) to the immutable 6.2 release asset; repo
fonts updated to the pinned 6.2 bits
- macOS pandoc extractor locates the binary in the archive instead of
assuming a bin/ layout that the macOS zip doesn't have
Stray upload archive (markdown-converter-assets (1).zip) excluded.
- electron-builder config moves to electron-builder.config.js so markitdown
bundling is conditional per platform (PyInstaller only builds for the host
OS; a missing binary now logs a warning and ships without it instead of
failing the build); package.json static build section removed, all npm
scripts pointed at the config; third-party-licenses/ added to packaged files
- FIX (pre-existing): packaged apps looked for bundled pandoc in
resources/bin, but extraFiles land next to the executable (Contents/ on
macOS) — packaged builds silently fell back to system pandoc since 4.5.
New bundledToolDir() resolves the real location for pandoc + markitdown
- download-tools.js pins the win32 pandoc.exe SHA-256 (fetched + verified)
- sharp packaging test accepts sharp 0.35's versioned binding filename
- release.yml: bundle-markitdown step (best-effort) on every OS and a new
macOS job; release aggregates linux+windows+macos artifacts
Local release artifacts built and verified (dist/):
- MarkdownConverter-4.7.0.AppImage (363MB, pandoc+markitdown bundled,
packaged app boots clean, tools resolve at the fixed path)
- markdown-converter_4.7.0_amd64.deb (293MB)
- MarkdownConverter-Setup-4.7.0.exe (223MB), portable exe (223MB), zip
(305MB) — pandoc bundled; markitdown omitted (cannot cross-build),
legal docs verified inside app.asar
637/637 tests green; lint clean.
Bundle (v4.7.0):
- MarkItDown frozen to a single ~75MB per-platform binary (PyInstaller via
npm run bundle:markitdown; ML extras excluded) — built and verified
locally: HTML/XLSX/PDF conversions pass through the bundled binary, and
the app resolves bin/linux/markitdown first at runtime
- Packaging copies bundled markitdown alongside Pandoc for win/mac/linux;
FFmpeg/sharp/KaTeX/fonts were already bundled
Legal artifacts:
- THIRD-PARTY-NOTICES.md: complete license inventory of everything
distributed (binaries, npm runtime deps, fonts, embedded Python packages)
- SOURCES.md: GPL §3(b) written source offers for Pandoc 3.9.0.2,
ffmpeg-static's GPL build, and the PyInstaller bootloader; LGPL relinking
note for libvips
- third-party-licenses/: canonical GPL-2.0, LGPL-2.1, MPL-2.0, Apache-2.0,
OFL-1.1, PSF-Python texts
- Help > Third-Party Notices & Licenses: in-app viewer for both documents
- README: 'Bundled Dependencies, Legal Notices & Credits' section
Hardening:
- download-tools.js now SHA-256 pins every artifact, verifies after
download AND against the cache on every run, and hard-fails on mismatch
(closes security finding D6)
Large tools intentionally not bundled (documented): LibreOffice,
MiKTeX/TeX Live, ImageMagick, PlantUML+JRE, Calibre.
637/637 tests green; lint clean; clean boot; bundled binary verified.
- File → Import with MarkItDown (Any Format)…: PDF, DOCX, PPTX, XLSX,
Outlook .msg/.eml, EPUB, images, CSV/JSON/XML, ZIP (audio/OCR via the
[all] extras) — verified live against HTML, XLSX (our own exporter's
output), and PDF fixtures
- Command auto-resolution with caching: markitdown binary → python -m
markitdown → python3 -m markitdown
- SEC-1 argv discipline (execFile only, user paths never through a shell),
50MB cap, 120s timeout, sanitized errors that surface markitdown's own
"pip install 'markitdown[pdf]'" hints for missing format extras
- Output lands next to the source as <name>.md (numeric suffix, never
overwrites) and opens in a new tab; markitdown:available/convert IPC
allowlisted for renderer flows
- Help → Dependencies lists MarkItDown; README/UPDATES updated (v4.6.1)
12 new tests (629 green); lint clean; clean app boot
Anthropic-compatible provider:
- New 'anthropic-compatible' option for any base URL speaking the Anthropic
messages schema (LiteLLM proxies, Bedrock gateways, local servers)
- Sends x-api-key AND Bearer auth when a key is set (gateway-friendly,
harmless for the official API); keyless proxies supported
- Tolerates base URLs with or without a trailing /v1 segment
- Settings modal, manifest, and provider docs updated
Runtime bug fixes found by booting the app (run-to-verify pass):
- PDF editor: File > Open PDF sends operation=null which matched no switch
case and crashed on getElementById(undefined); now defaults to the merge
section
- backlinks-panel: wrong require depth (../../utils -> ../utils) threw at
panel registration time
- writing-studio stack was written against a synchronous settings backend but
the real one is IPC-backed: GoalTracker/SnapshotManager/ProjectManager and
all four panels now await; JSON.parse(Promise) crashes eliminated
- manuscript panel used window.prompt (unavailable in Electron); replaced
with an inline dialog
- collaboration comment-store/save-load made async to match its IPC IO
617/617 tests green; 4 consecutive clean app boots (no uncaught errors)
- AI Assistant plugin: multi-provider chat (OpenAI/Anthropic/Ollama/LM Studio),
summarize/improve/translate commands, proofread via ai:analyze; calls
proxied through main so API keys stay out of the renderer
- Collaboration plugin: anchor-based comments in .comments/ sidecars with
drift detection and F8 navigation
- Local knowledge base: [[wiki-links]] with click-to-create + Backlinks panel
- Crash recovery: debounced session snapshots with restore prompt on launch
- Version history: pre-save snapshots, History panel with restore/diff/delete
- Real PDF encryption: swap pdf-lib for @cantoo/pdf-lib (probe-driven UI)
- XLSX export (native workbooks via JSZip), ODT headers/footers + page size
- Offline KaTeX (bundled CSS+fonts), local-first PlantUML rendering
- Editor: vim mode toggle, snippet Tab-expansion, zen word-goal setter,
writing heatmap, writing-studio panels wired with rail icons
- Quick Note global scratchpad (Ctrl+Alt+Q), markdownconverter:// deep links,
REPL first-run confirmation
- Fix: Ctrl+Shift+P collision, pandoc converter availability check, CLI
dangling --css/--reference-doc flags, dead converter button
8 new test suites; 613 tests green; lint clean
build.asarUnpack only claimed node_modules/sharp/**, so electron-builder
pruned the @img/sharp-* optionalDependencies: the asar kept 34 pure-JS
@img entries while the bundled libvips shared libraries never shipped.
At boot sharp's loader fell back to a system-libvips-linked binding and
dlopen failed, crashing the main process. Claim the prebuilt packages
explicitly (@img/** and @napi-rs/**) per the sharp+electron-builder
recipe, and guard the built output with a packaging regression test.
Amit Haridas
A missing/pruned @img/sharp-* binding made the top-level require('sharp')
crash src/main.js at startup, killing the packaged app before any window.
Load sharp through a cached lazy getter instead; when the native module
cannot load, executeOperation resolves the honest failure shape
{ success: false, error: 'Image operations unavailable: <sanitized>' }
(free of absolute paths), mirroring PDFOperations' Task-27 precedent.
Amit Haridas
electron-builder's .snap (Squashfs) artifact in dist/ registered as an
obsolete Jest snapshot file, failing the suite exit code despite all
516 tests passing. modulePathIgnorePatterns keeps the snapshot scanner
out of build output.
Amit Haridas
Final-review nit: the hardcoded-list rationale covers the dialog path
only; the drop stands on the trusted-argv precedent for --convert-to.
Amit Haridas
The interval split mode looped for (i = 0; i < totalPages; i += interval),
which spins forever when interval <= 0. Both the single-file dialog and the
batch dialog can reach it (the batch dialog's validateOperationData only
checks truthiness, so -1 passes). Guard at the source in the main process:
reject non-positive or non-integer intervals before the loop, protecting
both paths and any future caller.
Amit Haridas
The get-pdf-form-fields IPC pair (handler in main.js, renderer invoke and
event.reply('pdf-form-fields')) was missing from ALLOWED_SEND_CHANNELS and
ALLOWED_RECEIVE_CHANNELS. Under the planned preload migration an unlisted
channel is silently blocked, so the form-field fill/flatten feature would
break once the main window stops using the inline shim. Placed adjacent to
the sibling get-pdf-page-count/pdf-page-count pair it was modeled on.
Amit Haridas
Task-20-review finding: File.path removed in Electron 32, app on ^41.1.1,
~15 renderer file-picker sites read it and get undefined at runtime.
Amit Haridas
Replaces the two native OS dialogs used to configure the DOCX "Enhanced"
export template (an open-file picker + a message-box question) with a
single in-app modal that shows the currently active template state, per
Task 18's original audit finding that this state was invisible until a
user thought to reopen the menu. Consolidates the "Select Word
Template..."/"Template Settings..." menu items into one "Word Template
Settings..." entry wired to the new dialog; Browse still uses the native
file picker since there is genuinely no bundled folder of templates to
enumerate (confirmed by investigation — see task-18-report.md).
Also fixes a related dangling-reference bug: WordTemplateExporter's
hardcoded default template path (word_template.docx) was deleted from
the repo in an earlier commit, but the code still tried to read it and
threw ENOENT whenever no custom template was selected. convert() now
degrades gracefully by generating a minimal, valid DOCX shell (styles +
numbering matching what markdownToWordXml() already references) instead
of crashing, and the new dialog surfaces this state honestly ("using
default formatting, no default template is bundled") rather than
implying a working default exists.
Out of scope, per explicit instruction: bundling fabricated starter
.docx templates to populate a literal multi-item gallery (rejected as
disproportionate/fake-content scope), and an EPUB template gallery (no
EPUB template mechanism exists anywhere in this codebase to build one
for).
Amit Haridas
Task 17's three new IPC channels (plugin-export-formats-registered,
run-plugin-export-format, plugin-export-format-result) were missing
from preload.js's ALLOWED_SEND_CHANNELS/ALLOWED_RECEIVE_CHANNELS,
breaking the established convention that the allowlist is the
authoritative registry of every valid channel regardless of whether
it's accessed via window.electronAPI or raw ipcRenderer (see
toggle-sidebar-panel, set-current-file, save-recent-files).
Amit Haridas
Add context.formats.registerExportFormat(id, opts) to PluginContext,
backed by a new FormatRegistry (mirrors PluginRegistry's Map-based
shape). Plugins register namespaced (${pluginId}:${id}) export
formats with a label/extension/handler; the writing-studio built-in
plugin registers a trivial "sprint-summary" .txt export as a
worked example.
The plugin system lives entirely in the renderer process while the
Export menu is built in main.js, so wiring formats into the menu
required a small IPC round-trip: renderer sends format metadata to
main after plugin load (main rebuilds the menu via the already-
idempotent createMenu()), and a menu click sends the resolved save
path back to the renderer, which is the only process holding the
plugin's handler function.
Amit Haridas
Adds pdfGetFormFields (lists AcroForm fields with name/type/value) and
pdfFillForm (fills text fields by name, optionally flattens) to
PDFOperations.js, dispatched via 'formFields'/'fillForm' in
executeOperation. pdfFillForm skips unknown/non-text fields per-field
(logs + continues) rather than failing the whole batch, matching the
partial-success precedent set by pdfExtractImages.
Wires a "Fill Form" entry into the PDF editor dialog: selecting a PDF
fetches its fields via a new get-pdf-form-fields/pdf-form-fields IPC
round trip and renders one text input per field, plus a flatten
checkbox, following the same structure as the crop/pageNumbers dialogs.
Amit Haridas
Adds four new PDFOperations: pdfExtractText (pdfjs-dist getTextContent),
pdfAddPageNumbers (reuses pdfWatermark's position-mapping logic, extracted
into a shared resolvePosition helper), pdfCrop (page.setCropBox against the
existing MediaBox), and pdfExtractImages (pdfjs-dist operator list +
paintImageXObject + sharp). Wired into executeOperation's switch and the PDF
editor dialog UI (4 new sections/toolbar buttons/menu items) with no new IPC
channel needed.
pdfjs-dist v5 is ESM-only, so it's loaded via dynamic import() of its
Node-friendly legacy build; Jest needs --experimental-vm-modules to support
that, so the test scripts now set NODE_OPTIONS accordingly via cross-env.
Amit Haridas
Extends GitOperations.js with diff/branches/checkoutBranch/push/pull,
wires the 5 new IPC handlers in main.js (reusing the existing dir
resolution), whitelists the new channels in preload.js, and fixes the
Git sidebar panel's previously dead _gitDiff callback by wiring up a
diff view, branch list/create/checkout UI, and push/pull buttons.
Resolves Task 5, which deferred this work to this task.
Amit Haridas
Reviewer follow-up on Task 12: the task's own title/brief called for
batch support and no later task in the plan picks it up, so this closes
that gap. Adds a "Single File" / "Batch Folder" mode toggle to the
existing media-operations-dialog.js; batch mode swaps the per-file
input/output fields for an Input Folder + "Include subfolders" +
Output Folder trio while keeping every other parameter (width/height/
quality/angle/startTime/duration/crf/fps/format/fit) applied uniformly
to every matching file. Disabled for audio "Merge", which combines many
inputs into one output and doesn't fit a per-file batch model.
main.js: adds collectFilesByExtension() (src/main/collectFilesByExtension.js,
unit tested), a generalization of the inline collectFiles() closure inside
ipcMain.on('universal-convert-batch', ...) to match a set of extensions
instead of one format. runMediaBatchOperation() loops
ImageOperations/AudioOperations/VideoOperations.executeOperation() over
the matched files, reporting per-file progress via new
'media-batch-progress' events and a final 'media-batch-complete' event,
then shows a "Batch Conversion Complete" dialog.showMessageBox with
completed/failed counts, mirroring performBatchConversion()'s pattern.
Wired via three new ipcMain.on handlers: batch-image-operation,
batch-audio-operation, batch-video-operation.
preload.js: whitelists the three new send channels and the two new
receive channels (media-batch-progress, media-batch-complete).
Adds Tools > Image/Audio/Video Tools... menu items and a single dynamic
renderer dialog (src/renderer/media-operations-dialog.js) that lets the
user pick a media-kind-scoped operation, fill in its operation-specific
fields, and invoke process-image-operation/process-audio-operation/
process-video-operation (Tasks 9-11's backends). File selection reuses
the existing <input type="file"> + file.path convention; the one folder
picker need (video frame extraction) reuses the existing generic
select-folder/folder-selected IPC channels, so no new IPC handler was
required. Also removes the three dead electronAPI.image/audio/video
convenience blocks from preload.js (stale pre-Task-9-11 channel names,
unused everywhere).
Add src/main/VideoOperations.js with pure argument-builder functions
(buildConvertArgs, buildCompressArgs, buildTrimArgs, buildFramesArgs,
buildGifArgs) and a single executeOperation entry point that spawns
ffmpeg via dependency-injected execFileFn, mirroring AudioOperations.js.
Wire ipcMain.handle('process-video-operation', ...) in main.js using
getFFmpegPath() and sanitizeErrorMessage(). Update preload.js's
ALLOWED_SEND_CHANNELS: remove 6 stale video-* channel names, add
process-video-operation.
Amit Haridas
Adds AudioOperations.js with pure argument builders (convert/trim/extract/merge)
plus one executeOperation that spawns ffmpeg via a dependency-injected execFileFn,
so tests never invoke a real binary. Wires process-audio-operation in main.js and
updates preload.js's ALLOWED_SEND_CHANNELS to replace the 5 stale audio-* entries.
Amit Haridas
Three lines in tests/main/ImageOperations.test.js (copied verbatim
from the task brief's sample) exceeded the project's 100-char width,
failing npm run format:check. Ran npm run format to auto-fix; no
behavioral change.
Amit Haridas
Add src/main/ImageOperations.js (convert/resize/compress/rotate via
sharp), modeled on PDFOperations.js's executeOperation dispatcher.
Wire ipcMain.handle('process-image-operation', ...) in main.js using
sanitizeErrorMessage() on error paths, and replace the 5 stale/unused
image-* channel names in preload.js's ALLOWED_SEND_CHANNELS with
process-image-operation + select-image-folder (mirroring
select-pdf-folder for a later batch-UI task).
Amit Haridas
- Add jszip (^3.10.1) to dependencies; keep version-pinned in overrides
- Move sharp (^0.34.3) from devDependencies to dependencies for Phase B runtime use
- Add node_modules/sharp/** to build.asarUnpack so native bindings are not packed
Amit Haridas
Reviewer caught that the new View > Monospace Font menu channel was
missing from preload.js's ALLOWED_RECEIVE_CHANNELS, the sole gap among
29 raw ipcRenderer.on(...) channels used in renderer.js. Add it under
the existing Font section for consistency with adjust-font-size.
Amit Haridas
Add a View > Monospace Font menu (font family radio + ligatures
checkbox) — the app's existing reachable UI surface for this class of
preference (mirrors Theme/Font Size/Spell Check). The menu sends the
change to the renderer, which persists it via the already-working
ipcMain.handle('set-monospace-settings', ...) and applies it live via
the same applyMonospaceClasses() used on initial load.
Amit Haridas
Extract the sidebar Templates panel's inline load-into-new-tab callback into
a shared loadTemplateIntoNewTab() function, and add the missing
ipcRenderer.on('load-template-menu', ...) listener so the File > New from
Template submenu (which already sends this IPC event, already whitelisted in
preload.js) actually loads the selected template.
Amit Haridas
Extract the recent-files.json deletion logic into a standalone
clearRecentFilesOnDisk() function and call it from both the menu
click handler and the ipcMain.on handler. Previously the menu sent
the message in the wrong direction (main→renderer instead of
renderer→main), causing the feature to silently no-op. Both paths now
use the same function and send the correct 'recent-files-cleared'
notification to keep the renderer in sync.
Amit Haridas
Monospace font embedding feature release. Adds bundled JetBrains Mono +
Fira Code TTFs (asarUnpack), preview/print font picker with ligatures
toggle, and embedded fonts in PDF (xelatex fontspec), DOCX (OOXML
surgery), EPUB (--epub-embed-font + OPF manifest), and HTML (sidecar
CSS with base64 data URI).
Exercises the real export pipeline against the bundled JetBrains Mono TTFs:
- PdfFontHeader emits valid xelatex fontspec with correct family + Ligatures=NoCommon
- ExportCss.build emits @font-face with base64 data URI
- DocxFontEmbedder injects TTFs into pandoc-produced DOCX (word/fontTable.xml + word/fonts/)
- EpubFontEmbedder.patchManifest adds TTF entry to OPF <manifest>
- HTML export links the sidecar CSS which embeds the font
Run with: node tests/smoke-e2e-monospace.js
Renderer already calls window.electronAPI.invoke('get-monospace-settings')
to apply body classes; this wires up the channel allowlist and main-process
handlers so the IPC actually returns the active monospace settings and
persists updates.
Embeds regular + bold TTF of the active monospace family into pandoc's
DOCX output. ODT uses pandoc's built-in font handling; RTF has no font
embedding capability (documented limitation).
Replaces -V monofont=Consolas with a generated xelatex/lualatex header
that fontspec-loads the bundled JetBrains Mono or Fira Code TTF. Adds
a cached settings reader with proper invalidation on store.set, and
reorders fallback engines to prefer lualatex (fontspec-capable) before
pdflatex.
Inlines @font-face as base64 data URI so the iframe srcdoc can render
JetBrains Mono / Fira Code without depending on the parent window's
loaded @font-face sets. Reads family + ligature state from the
renderer-wide cache populated by applyMonospaceClasses().
Amit Haridas
Bundles JetBrains Mono + Fira Code TTFs in assets/fonts/. Embeds them into
DOCX (jszip), passes path via xelatex fontspec for PDF, base64-injects
@font-face for HTML/EPUB. Replaces Consolas (Windows-only) and Google Fonts
CDN load in the ASCII generator window.
Adds user-pickable monospace family + ligature toggle (default JBM, no
ligatures) for ASCII column alignment.
Closes: N/A
Refs: docs/superpowers/specs/2026-06-30-monospace-font-embedding-design.md
Amit Haridas
- Make the HTML preprocessor code-block and inline-code aware so code
examples containing <style> / <div> / comments are preserved.
- Strip all raw <div> tags (not just alignment attributes) to avoid
malformed output from unmatched closing tags.
- Handle uppercase tags and single/unquoted attributes.
- Create temporary DOCX input files inside private mkdtemp directories
instead of predictable names in the shared temp directory.
- Wrap batch DOCX preprocessing in try/catch so one unreadable file
does not abort the entire batch.
- Add regression tests for the edge cases above.
Pre-process markdown before Word/DOCX export to remove raw HTML artifacts
(<style> blocks, HTML comments, and <div align=...> tags) that were
visible in the generated document. Applies to single and batch DOCX exports
via both Pandoc and WordTemplateExporter paths.
- Normalize pandoc command parsing with path.basename() to support bundled binary paths
- Use bundled pandoc binary in convertWithPandoc instead of relying on PATH
- Forward includeSubfolders checkbox state from renderer to main process
- Add pandoc availability check before batch conversion
- Re-enable Start button when batch conversion completes
- Clean up obsolete dist build artifact causing test snapshot warning
- Bump version to 4.4.4
Documents project architecture, Pandoc dependency resolution, build
pipeline (electron-builder, no bundler), security model notes
(contextIsolation: false on this branch), and development commands
extracted from actual package.json and source.
Amit Haridas
This will help identify whether the issue is:
1. marked.parse returning a Promise instead of string
2. DOMPurify.sanitize failing
3. The preview element not existing
4. Libraries not being loaded
Amit Haridas
- Add missing updateUI() call at end of openFile() to set .active class
on tab content. Without this, the CSS rule .tab-content:not(.active)
{ display: none } kept newly opened files invisible.
- Add diagnostic logging to file-opened IPC handler and openFile()
to trace future file loading issues.
- Add diagnostic logging to openFileFromPath() in main process.
Amit Haridas
window.ModalManager was set unconditionally, causing "Identifier
'ModalManager' has already been declared" when script tag in HTML
also loaded ModalManager before renderer.js required it.
Now checks !window.ModalManager before setting.
Amit Haridas
require('dompurify') returns a factory function, not a sanitizer
instance. Calling .sanitize() on the factory threw a TypeError,
which was caught by the preview renderer's try-catch and displayed
a generic "Error rendering preview" message. Fix by invoking the
factory with the renderer's window object.
Amit Haridas
Restrict Electron permission requests to only clipboard operations.
Deny: camera, microphone, geolocation, notifications, and all other
permissions by default.
Implements setPermissionRequestHandler on web-contents-created event
to enforce security policy early in the app lifecycle.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add get-app-version IPC handler in main.js (returns app.getVersion())
- Expose electronAPI.getAppVersion() in preload.js
- index.html: replace hardcoded v4.2.0 span with dynamic population
from getAppVersion() in DOMContentLoaded
- welcome.js: accept appVersion param instead of hardcoded 4.1.0
- renderer.js: pass live version to createWelcomeContent()
- main.js about screen: use app.getVersion() instead of hardcoded 4.1.0
- Update stale @version 4.1.0 JSDoc comments to 4.3.0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
electron-builder detects git tags in CI and tries to auto-publish to
GitHub, failing with 'GH_TOKEN not set'. We handle the release
separately via softprops/action-gh-release, so suppress auto-publish.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add build:linux-ci script (deb + AppImage, no snap — snapcraft not
available on ubuntu-latest runners without extra setup)
- Switch release.yml linux build to npm run build:linux-ci
- release job: if: always() so Windows artifacts still get released
even if linux build fails
- Download artifact steps: continue-on-error so missing platform
doesn't block GitHub Release creation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove rpm from linux build targets (rpmbuild not available locally)
CI can add it back with apt-get if needed, but pandoc/ffmpeg are now
bundled so the rpm depends were incorrect anyway
- Remove rpmbuild apt install step from release.yml (not needed)
- Remove pandoc/ffmpeg from deb depends — they are now bundled binaries
- Keep imagemagick and libreoffice-common in deb depends (not bundled)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove package-lock.json from .gitignore so npm ci works in CI
- Refactor main.js: delegate PDF ops to src/main/PDFOperations.js,
git ops to src/main/GitOperations.js
- getPandocPath(): use bundled binary from resources/bin/ when packaged,
fall back to dev bin/ or system pandoc in development
- getFFmpegPath(): use ffmpeg-static (asarUnpack) when packaged
- Install ffmpeg-static (v5.3.0, bundled 76MB binary)
- Add scripts/download-tools.js to fetch pandoc binary at build time
(idempotent, runs on CI before electron-builder)
- electron-builder: add asarUnpack for ffmpeg-static, extraFiles for
pandoc binary per platform (linux + win32)
- release.yml: switch build-windows to windows-latest runner with native
NSIS support; add cert decode step; add download-tools step for both
linux and windows jobs
- Fix lint error: hoist outlinePanelContainer to module scope so
TabManager methods can reference it without no-undef errors
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add plugin system bootstrap in renderer.js after sidebar/commands init
- Wire status bar DOM insertion, editor API, and IPC adapters
- Add plugin-settings:get/set IPC channels to preload allowlist
- Add IPC handlers in main process using existing settings store
- Fix eqeqeq warning in EventBus.hasHandler
Amit Haridas
- PluginContext: scoped API with crash-safe command wrappers
- PluginRegistry: lifecycle management with graceful init failure
- SettingsStore: plugin-scoped key/value via IPC backend
- Export hooks: pre/post hooks on registry for cross-plugin integration
Amit Haridas
9 tasks across 8 chunks, strict TDD:
- EventBus with crash-safe handlers
- PluginAPI base class
- PluginLoader with manifest validation
- PluginContext with scoped API
- PluginRegistry with lifecycle management
- SettingsStore for plugin-scoped settings
- Export hooks integration
- Sample plugin + renderer wiring
Amit Haridas
- GGUF GPU: child process isolation with crash detection/restart
- Event bus: versioned payload schemas for all events
- Plugin sandbox: 5s handler timeout, IPC delegation for heavy ops
- AI streaming: full lifecycle with requestId, cancel, heartbeat, orphan cleanup
- Comment anchors: context-based positioning (not byte offsets) with re-anchor on file change
- Cross-plugin: capability discovery, 30s timeout, graceful degradation
- Bundle size: GPU variants as lazy downloads, not bundled by default
- Command uniqueness: registry rejects duplicates at load time
Amit Haridas
- Remove signAndEditExecutable:false so code signing works properly
- Add legalTrademarks and copyright metadata to build config
- Add publisherName via build.copyright (embedded in PE resources)
- Create scripts/create-selfsigned-cert.ps1 for local dev signing
- Update release.yml: build on windows-latest runner (not Wine),
auto-sign when CSC_LINK_BASE64/CSC_KEY_PASSWORD secrets present,
fall back to unsigned otherwise
- Add lint step to ci.yml (Phase 4.3 plan gap)
- Add .vscode/launch.json debug configs (Phase 4.3 plan gap)
- Fix .gitignore: exclude *.pfx/*.p12 cert files, track launch.json,
fix concatenated agents.md/coverage/ lines
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Zen mode hides all chrome and centers the editor with typewriter
scrolling, line dimming, and a floating word count HUD.
Toggle with F11, exit with Escape.
Amit Haridas
- Bump version to 4.1.0 in package.json and index.html
- Add build:local script for combined Linux + Windows local builds
- Add CI workflow: runs tests on push/PR to master
- Add Release workflow: tag-triggered (v*), parallel Linux + Windows
builds, publishes all packages to GitHub Releases
Amit Haridas
- Set backdrop z-index:0 and content z-index:1 to fix backdrop covering
modal content within the stacking context
- Force reflow between removing hidden and adding open class so CSS
opacity transition fires correctly
- Add transitionend listener + setTimeout fallback to restore hidden
class after close animation completes
- Override flex:1 on modal footer buttons to prevent full-width stretch
- Add min-width to modal size variants for consistent sizing
- Add 23 tests covering open/close lifecycle, keyboard, and destroy
Amit Haridas
Convert 10 dialogs from old classes (.export-dialog, .batch-dialog, .find-dialog)
to the new unified .modal structure with proper accessibility attributes.
Changes:
- find-dialog: small modal with find/replace controls
- export-dialog: large modal with export options
- print-preview-overlay: full-size modal for print preview
- table-generator-dialog: default modal for table creation
- ascii-art-dialog: large modal for ASCII art generation
- universal-converter-dialog: large modal for file conversion
- batch-dialog: large modal for batch processing
- pdf-editor-dialog: full-size modal for PDF editing
- header-footer-dialog: default modal for header/footer config
- field-picker-dialog: small modal for field selection
All dialogs now include:
- role="dialog" and aria-modal="true" for accessibility
- aria-labelledby pointing to title element
- .modal-backdrop with data-close attribute
- .modal-content with appropriate size class
- .modal-header with title and close button
- .modal-body for content
- .modal-footer with action buttons
Amit Haridas
- Create adapters/types.js with comprehensive type definitions
- Create adapters/electron/fs.js for file system operations
- Prepare structure for future migration to Tauri/Flutter
This abstraction layer makes future platform migration easier
and enables better testing with mock adapters.
Amit Haridas
- Add previewDebounceTimers map to track debounce timers per tab
- Add updatePreview(tabId, immediate) with optional immediate flag
- Debounce preview updates during typing (300ms delay)
- Use immediate=true for tab switches and file loads
- Refactor _renderPreview as internal method
This significantly improves editor responsiveness when typing
in large markdown files.
Amit Haridas
- Add tab type system ('markdown' and 'pdf')
- Create PDF tabs with their own state (page, zoom, rotation)
- Update closeTab to properly clean up PDF resources
- Update updateUI to handle PDF tabs (hide toolbar, etc.)
- Add visual indicators for PDF tabs in tab bar
- Add CSS styles for PDF tab containers
Fixes: PDF and markdown multitab function not working
Amit Haridas
- Add custom EditorView.theme for CodeMirror 6 with JetBrains Mono
- Update .editor-textarea and #editor font-family to prioritize JetBrains Mono
- Update preview code blocks (#preview code, .preview-content code) to use JetBrains Mono
- Ensures consistent monospace font across editor source and markdown rendering
Amit Haridas
CSS improvements:
- Standardize dark theme selectors to body[class*="dark"] pattern
- This ensures all dark themes (theme-dark, theme-dracula, etc.)
receive consistent styling
- Add semantic color variables (--text-primary, --bg-primary, etc.)
- Replace hardcoded colors with CSS variables in:
- Tab bar component
- Toolbar separator
- Pane resizer
- Status bar
- Add fallback values for backward compatibility
This improves maintainability and makes theming more consistent.
Amit Haridas
Accessibility improvements:
- Add global focus-visible styles for keyboard navigation
- Add focus-visible for sidebar panel close button
- Add skip-link styles for screen reader users
- Add .sr-only class for visually hidden content
- Add prefers-reduced-motion support for users sensitive to motion
- Add prefers-contrast: high support for high contrast mode
Amit Haridas
CSS improvements:
- Remove duplicate CSS reset from styles-modern.css
- Add focus-visible styles for sidebar icons
- Add error/loading state components (skeleton, spinner, messages)
- Add success, warning, info message components
- Add dark theme support for new components
Code quality:
- Replace inline error style with CSS class in renderer.js
Amit Haridas
- Fix duplicate editorContainer declaration in renderer.js
- Add missing browser globals to eslint config (prompt, FileReader, etc.)
- Add global object for Jest test setup
- Replace path.basename with portable string split in logo preview
Add unit tests for sidebar manager, command palette, print preview,
main process utilities, and markdown extensions. Update jest config
to exclude untestable Electron-specific files from coverage and
raise coverage thresholds.
Refactor inline command palette into a proper CommandPalette class
with search highlighting, keyboard navigation, and overlay UI.
Register all app actions including formatting, file ops, and sidebar
toggles.
- Grouped toolbar buttons into logical sections: Format, Structure, Insert, View
- Added toolbar-group CSS class for visual grouping
- Updated button titles with keyboard shortcut hints
- Enhanced status bar HTML structure with left/right layout
- Restructured status bar into left/right sections with separators
- Added character count, cursor line/column position, encoding, and language mode indicators
- Added cursor position tracking via CodeMirror onUpdate callback
- Added file path display that updates on tab switch
- Simplified word count display for cleaner status bar layout
Update worker path from .js to .mjs to match the new ESM-only build
structure in pdfjs-dist v5. Core API (getDocument, getPage, render)
remains compatible.
- Update marked from ^16.2.1 to ^17.0.3
- Add marked-highlight ^2.2.3 for syntax highlighting support
- Replace deprecated marked.setOptions() with marked.use() in renderer.js
- Extract highlight config into markedHighlight() extension (required in v17)
- Update test mock to reflect new API (use instead of setOptions)
Deleted various image, PDF, and DOCX files that are no longer needed, as well as a sample YAML configuration. Updated .claude/settings.local.json to add new allowed Bash commands for local development.
Major Features:
- Integrated PDF viewer with zoom, page navigation, and fit modes
- PDF editor toolbar with direct access to all PDF operations
- New app branding with docico1.png icon
- ConcreteInfo theme (light & dark variants)
- Comprehensive PDF editing: merge, split, compress, rotate, delete, reorder
- Watermark, encrypt, decrypt, and permissions management
- Overwrite original file option for all PDF operations
UI Improvements:
- PDF viewer takes full screen when active (hides tabs and toolbar)
- Compact modals with reduced font sizes
- Dark theme fixes for icons and dialogs
- Save/Save As options for PDF operations
- Improved PDF toolbar theming
Technical:
- Added isPdfViewerActive state tracking
- Proper PDF document lifecycle management
- Fixed hang issues when switching between PDF and markdown
- All dependencies are open-source (MIT, Apache 2.0, BSD)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduces IMPROVEMENT_PLAN.md outlining a comprehensive roadmap for PanConverter v3.0, including security hardening, testing infrastructure, code refactoring, developer experience, performance optimization, new features, and community building. The plan details phased implementation, success metrics, risk assessment, and resource requirements.
New Features:
• Export Profiles - Save and load export configurations
• Mermaid.js diagram support - Render flowcharts, sequence diagrams, and more
• Command Palette (Ctrl+Shift+P) - Quick access to all commands
• GitHub Light/Dark preview themes - Beautiful code preview styling
• Table Generator - Interactive table creation tool
• ASCII Art Generator - Create text banners, boxes, and templates
• Resizable Preview Pane - Drag divider to adjust editor/preview sizes
• Pop-out Preview Window - Open preview in separate window with live sync
UI/UX Improvements:
• Fixed advanced export dialog visibility (added .hidden CSS class)
• GitHub-style table headers with light grey background
• Removed gradients from table headers
• Clean, professional preview rendering
Technical Changes:
• Updated all UI components for new features
• Enhanced TabManager to support resizable panes
• Added MutationObserver for live preview sync in pop-out window
• Improved CSS styling consistency
🤖 Generated with Claude Code (https://claude.com/claude-code)
Fixed code block and ASCII art background to extend full paragraph width:
🔧 Background Fix:
- Moved shading (w:shd) from run level (<w:rPr>) to paragraph level (<w:pPr>)
- Background now extends full width like in the preview
- Applied to both createCodeBlockXml() and createAsciiArtXml() functions
📝 Technical Changes:
- src/wordTemplateExporter.js: Paragraph-level shading for full-width backgrounds
- Added w:ind with left="284" right="284" for consistent margins
- Removed redundant w:shd from run properties
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Fixed export of ASCII art, charts, tables, and flowcharts to match preview exactly:
🎨 ASCII Art Preservation:
- Code blocks now export exactly as shown in preview
- Each line rendered separately to preserve exact spacing and alignment
- Monospace font (Consolas) used consistently across all export formats
- Line breaks, spacing, and box-drawing characters preserved perfectly
📝 Word Template Exporter Improvements:
- createCodeBlockXml: Renders each line as separate paragraph with exact spacing
- Added <w:keepLines/> and <w:wordWrap w:val="0"/> for no-wrap behavior
- Enhanced isAsciiArt detection with more Unicode box-drawing characters
- Added support for rounded corners (╭╮╯╰), heavy box chars, more arrows
📄 PDF Export Enhancements:
- Added -V monofont="Consolas" for proper code block rendering
- Added --highlight-style=tango for syntax highlighting
- Applied to main export, fallback engines, and CLI conversion
🖨️ HTML/Electron PDF Improvements:
- Enhanced CSS: white-space: pre, word-wrap: normal
- font-family: Consolas, Monaco, 'Courier New', monospace
- Print media queries preserve code block formatting
- overflow: visible prevents content truncation
🔧 Technical Changes:
- src/wordTemplateExporter.js: Enhanced code block and ASCII art rendering
- src/main.js: Added monofont settings to all PDF export paths
- Updated version to 1.9.1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit fixes the logo upload issue and adds MiKTeX to the app's PATH for LaTeX/PDF support.
**Logo Upload Fix:**
- Replaced file input with Browse button that uses dialog.showOpenDialog
- Added browse-header-footer-logo IPC handler in main process
- Now gets reliable file paths without depending on file.path property
- Added browse-btn CSS styling
**MiKTeX PATH Addition:**
- Automatically adds MiKTeX bin directory to process.env.PATH on Windows
- Enables XeLaTeX/PDFLaTeX for PDF exports with headers/footers
- Logs PATH addition for debugging
**Files Changed:**
- src/main.js: Added MiKTeX PATH setup, browse logo IPC handler
- src/renderer.js: Changed to browseForLogo() function, updated event listeners
- src/index.html: Replaced file inputs with browse buttons
- src/styles.css: Added .browse-btn styling
**Testing Notes:**
- Logo upload now works without "path undefined" errors
- DOCX exports with headers/footers confirmed working
- PDF exports should now use Pandoc+XeLaTeX with MiKTeX in PATH
- Requires MiKTeX installation and PC restart for full functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
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)
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 release includes significant improvements to PDF Editor UI, enhanced PDF/Word
export functionality, print fixes, and configurable template settings.
🎯 v1.8.1 - Streamlined PDF Editor UI:
- Clean, focused interface showing only the selected PDF operation
- Smooth fade-in animations when switching between functions
- Optimized dialog sizing (max-width 600px, max-height 85vh)
- Enhanced file list styling with better contrast
- Complete dark theme support for all PDF editor components
- Better scrolling behavior for long forms
📄 v1.8.2 - Enhanced PDF Export & Print Fix:
- New "PDF (Enhanced)" export option using Word template + LibreOffice conversion
- Added to both single-file export and batch converter
- Keyboard shortcut: Ctrl+Shift+P for enhanced PDF export
- Fixed print preview showing blank output issue
- Simplified print handler using CSS @media print rules
- Better print styling with proper element hiding/showing
⚙️ v1.8.3 - Configurable Template Settings:
- Added "Template Settings..." menu option
- Configurable start page for Word template content insertion
- Choose from Pages 1-5 or custom page number (1-100)
- Settings persisted across sessions
- Updated WordTemplateExporter to use configurable start page
- Works with both DOCX (Enhanced) and PDF (Enhanced) export
- Applied to single-file and batch conversion workflows
🔧 Technical Improvements:
- Enhanced WordTemplateExporter constructor to accept startPage parameter
- Updated insertContentAfterPage method for flexible page insertion
- Added Template Settings dialog with quick-select buttons
- IPC communication for custom page number input
- Settings stored in userData/settings.json
- Improved CSS specificity with PDF editor-specific classes
- Fixed @media print rules to ensure preview content is visible
🎨 UI/UX Enhancements:
- PDF Editor sections now animate smoothly when switching
- File lists for merge operations styled with proper contrast
- Remove buttons styled with danger color (#dc3545)
- Template settings dialog shows current template and start page
- All enhancements support all 22 existing themes
The application now provides professional-grade PDF editing, enhanced export
capabilities with full control over template-based generation, and a streamlined
user interface that makes complex operations simple and intuitive.
🤖 Generated with Claude Code
Enhanced PDF Editor user experience with cleaner, more intuitive interface:
✨ UI Improvements:
- Streamlined PDF Editor dialog to show only selected function
- Removed cluttered "all functions at once" display
- Added smooth fade-in animation when showing function-specific sections
- Improved dialog sizing: max-width 600px, max-height 85vh
- Better visual separation with compact section spacing
🎨 Styling Enhancements:
- Added PDF editor-specific CSS classes for better organization
- Enhanced file list styling with better contrast
- Improved remove button styling with danger color
- Complete dark theme support for all PDF editor components
- Better scrolling behavior for long forms
🔧 Technical Improvements:
- Maintained existing show/hide logic (already working correctly)
- Enhanced CSS specificity with .pdf-editor-content and .pdf-editor-body classes
- Added @keyframes fadeIn animation for smooth transitions
- Improved overflow handling for better UX on smaller screens
🌙 Theme Support:
- Full dark mode styling for file lists and entries
- Proper color contrast for all interactive elements
- Consistent styling across all 22 themes
The PDF Editor now provides a clean, focused interface showing only the relevant
controls for each operation (merge, split, compress, rotate, delete, reorder,
watermark, encrypt, decrypt, permissions).
🤖 Generated with Claude Code
Added enhanced Word export with template support to the batch file converter,
enabling batch conversion of markdown files to professionally-styled DOCX
documents using custom templates.
New Features:
- Added "DOCX (Enhanced)" option to batch converter format selection
- Integrated WordTemplateExporter with batch conversion workflow
- Batch converter now supports template-based Word export with:
* Custom template preservation
* Professional table styling (orange headers, white data rows)
* Perfect ASCII art and flowchart alignment
* Red-colored arrows in flowcharts
* Markdown numbering stripped from headings and lists
Technical Changes:
- Modified performBatchConversion() to handle 'docx-enhanced' format
- Async/await pattern for WordTemplateExporter in batch processing
- Proper error handling and progress tracking for enhanced exports
- Updated version to v1.8.0 in package.json, main.js, and README.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Major Features:
- Template-based Word export with custom template selection
- File menu option to select and persist Word templates
- Table styling with orange headers and white data rows
- ASCII art and flowchart rendering with perfect alignment
- Red-colored arrows in flowcharts for enhanced visibility
- Markdown numbering stripped from headings and lists
Technical Improvements:
- Enhanced ASCII art detection for arrows and flowchart patterns
- Line-by-line rendering with no-wrap properties
- Arrow character detection and red coloring (↓→←↑)
- Template path persistence across sessions
- Word XML manipulation using PizZip
Files Modified:
- src/wordTemplateExporter.js: Enhanced ASCII art rendering, table styling
- src/main.js: Template selection function and menu integration
- CLAUDE.md: Comprehensive v1.7.9 documentation
- package.json: Version bump to 1.7.9
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Created wordTemplateExporter.js module using docx npm package
- Added "DOCX (Enhanced)" option in File → Export menu
- Keyboard shortcut: Ctrl+Shift+W
- Full markdown support: headings, formatting, code, lists, tables
- No external dependencies (Pandoc/Python not required)
- Proper numbering configuration for lists
- Professional Word document output
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Rewrote handlePrintPreview to explicitly hide all UI elements
- Store and restore original display values for clean restoration
- Make preview pane absolute positioned and full width for printing
- Hide toolbar, tab bar, status bar, editor pane, and dialogs
- Added proper timing for DOM updates before printing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Fixed command-line argument parsing for packaged apps using app.isPackaged
- Fixed print preview to show markdown content instead of toolbar
- Rewrote print handler to rely on CSS @media print rules
- Enhanced CSS with attribute selectors for dynamic preview panes
- Removed DevTools auto-open for production build
- Updated version to 1.7.8 across all files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Added null checks for toolbar, tab-bar, status-bar before accessing .style
- Prevents TypeError when elements don't exist
- Added executeJavaScript to send main process logs to renderer console
- Now we can see main process state in DevTools
- Print should now work without errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Added console.log statements throughout file loading flow
- Traces: command-line args → pendingFile → renderer-ready → openFileFromPath → file-opened
- Added logging to print-preview handlers
- Added logging to theme-changed and renderer-ready
- Enabled DevTools automatically for debugging
- Backup renderer-ready timeout (100ms) in case theme-changed doesn't fire
This debugging build will help identify exactly where the flow breaks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
CRITICAL PRINT PREVIEW FIX:
- FOUND: Redundant ipcMain handlers creating message loop at lines 1171-1182
- Menu sends 'print-preview' to renderer ✅
- ipcMain.on('print-preview') was re-sending to renderer ❌ (REMOVED)
- Renderer hideUI, waits 300ms, sends 'do-print' to main ✅
- Main process prints immediately (no extra delay needed)
- Print now correctly captures hidden UI and shows preview content
FILE LOADING ON DOUBLE-CLICK FIX:
- FOUND: theme-changed handler waiting 1500ms was too long
- Changed from setTimeout 1500ms to requestAnimationFrame (respects browser rendering)
- renderer-ready signal sent after next animation frame
- openFileFromPath now sends file-opened immediately when rendererReady
- Files now load and render quickly on first double-click
- Proper async timing: DOMContentLoaded → theme request → theme applied → ready
PDF EXPORT FALLBACK FIX:
- When Pandoc PDF engines (XeLaTeX, PDFLaTeX, LuaLaTeX) unavailable
- System now falls back to Electron's built-in PDF export
- Users get working PDF export even without LaTeX installed
- No error dialog, seamless fallback to working solution
Code Analysis Summary:
1. Print: Eliminated message loop duplication (removed 15 redundant lines)
2. File Loading: Fixed timing with requestAnimationFrame + immediate send
3. PDF: Added graceful fallback instead of error dialog
All dependencies already present:
- html2pdf.js ✅
- pdf-lib ✅
- pdfkit ✅🤖 Generated with [Claude Code](https://claude.com/claude-code)
PDF Export Fix:
- Fixed ReferenceError: geometry is not defined in PDF export
- Removed hardcoded undefined geometry variable from pandoc command
- Geometry option now properly extracted from options object when present
- PDF export now works without errors
Print Preview Timing:
- Changed from requestAnimationFrame to setTimeout for more reliable rendering
- Increased delay from 0ms to 300ms before sending print command
- Post-print UI restoration after 500ms to ensure printer captured output
- More reliable toolbar hiding before print dialog opens
File Loading Timing:
- Increased delay from 500ms to 2000ms (2 seconds) for file-opened message
- Ensures complete theme application and preview pane initialization
- Files now load and render consistently on first double-click
All timing issues related to browser rendering and DOM updates resolved.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Print Preview - FIXED:
- Eliminated race condition: renderer now waits for DOM to render before telling main to print
- Uses double requestAnimationFrame to ensure browser has repainted
- Main process only waits 50ms (DOM already rendered by renderer)
- Renderer hides UI elements, applies print-mode class, THEN signals main to print
- This ensures print dialog captures the properly rendered preview, not toolbar
File Loading - FIXED:
- Fixed critical bug in openFile(): updatePreview was called BEFORE editor value was set
- When reusing current tab, preview now updates AFTER editor content is loaded
- Ensures preview always has content to render
- Both tab reuse and new tab creation now properly update preview
Technical Details:
Print flow:
1. User clicks Print Preview
2. Menu sends 'print-preview' to renderer
3. Renderer: hide UI, set print-mode class
4. Renderer: requestAnimationFrame x2 (waits for repaints)
5. Renderer: sends 'do-print' to main (DOM fully rendered)
6. Main: small 50ms delay, then prints
7. Result: prints preview content, not toolbar!
File loading flow:
1. User double-clicks .md file (or file association)
2. Main process stores file path
3. Renderer signals ready after theme loads
4. Main sends file-opened message
5. Renderer openFile() called
6. Editor value set
7. THEN updatePreview() called (content exists)
8. Preview renders correctly!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Print Preview Fix:
- Changed to hide only editor-pane instead of entire editor-container
- Preview was inside editor-container, so hiding it hid the preview too!
- Now correctly shows preview-pane-{tabId} with print-mode class
- Hide all dialogs including find-dialog during print
- Preview now displays correctly for printing
File Loading Fix - Completely Rewritten:
- Root cause: renderer-ready was sent BEFORE theme was applied
- Solution: Moved renderer-ready signal INTO theme-changed handler
- Now waits 1500ms AFTER theme is applied before signaling ready
- Main process delay increased to 500ms for extra safety
- Ensures complete UI render cycle: DOMContentLoaded -> theme request -> theme applied -> wait -> renderer-ready -> file opens
- Files now load and render properly on first double-click
Technical Flow:
1. DOMContentLoaded fires, TabManager initializes
2. get-theme request sent to main
3. theme-changed received, theme applied to body
4. After 1500ms delay, renderer-ready sent
5. Main process waits 500ms more, then sends file-opened
6. Total delay: ~2 seconds ensures rock-solid first-load rendering
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Print Preview Fixes:
- Fixed print preview to show actual preview content instead of formatting menu
- Changed from generic 'preview' ID to active tab's 'preview-{tabId}' element
- Added CSS positioning to make preview fixed and full-screen during print
- Hide all dialog overlays (export, batch, PDF, converter) during print
- Restore dialogs after print completes
- Enhanced print-mode CSS with z-index and positioning for proper display
File Loading Timing Improvements:
- Increased renderer-ready delay from 500ms to 1000ms for slower first loads
- Increased openFileFromPath delay from 100ms to 300ms
- Ensures UI fully initializes before files are displayed
- Files now render correctly on first double-click launch
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Added 500ms delay to renderer-ready signal to ensure all UI initialization completes before opening files
- Added 100ms delay in openFileFromPath to ensure main process doesn't send file before renderer is fully prepared
- Prevents race condition where files would open before theme is applied and interface is ready
- Files now render properly on first launch regardless of app startup time
- Improved startup UX by ensuring smooth file rendering
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Fixed print-preview event handling by adding missing ipcRenderer listeners
- Renderer now properly relays print-preview and print-preview-styled events to main process
- Changed default theme from 'light' to 'github' for better visual appearance
- Rebuilt release with v1.7.7 fixes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Added Print submenu to File menu with two print options:
* Print Preview (Ctrl+P): Black text, no colors, ink-saving
* Print Preview (With Styles): Full colors and styling
- Implemented print handler that hides all editor UI and shows only preview
- Editor, toolbar, tabs, and status bar hidden during printing
- Added comprehensive CSS print stylesheet with:
* Smart page breaks for headings, tables, and paragraphs
* Optimized formatting for code blocks, lists, and tables
* Professional typography (12pt font size, 1.6 line height)
* Image optimization and proper link handling
* Support for blockquotes, horizontal rules, and other elements
- Print-specific CSS classes for styling control
- Preview automatically restored after printing
Features:
- Prints only the rendered markdown preview (not source)
- Two print modes: simple (black) and styled (colored)
- Native OS print dialogs for all platforms
- Professional output formatting with page breaks
- Cross-platform support (Windows, macOS, Linux)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Added Print menu item with Ctrl+P keyboard shortcut for native OS printing
- Implemented print IPC handlers in main and renderer processes
- Remapped Toggle Preview from Ctrl+P to Ctrl+Shift+P to avoid conflicts
- Added PDFKit (v0.14.0) for native PDF generation without Pandoc
- Added html2pdf.js (v0.10.1) for HTML to PDF conversion
- Enhanced CLAUDE.md with new v1.7.7 feature documentation
- Print supports cross-platform printing (Windows, macOS, Linux)
Features:
- Native print dialog with background color printing
- Professional PDF export without system dependencies
- Improved portability and offline support
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Added comprehensive documentation for:
- v1.7.6: Table header styling cleanup
- v1.7.5: Critical file association fix with single-instance lock
- Updated current version to v1.7.6
- Updated last modified summary
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Removed custom background colors from table headers to improve preview appearance and maintain consistency with normal theming.
## Changes
- Removed background-color from default theme table headers (was #f6f8fa)
- Removed dark theme table header background styling block
- Headers retain font-weight: 600 for visual distinction
- Table borders and alternating row colors remain intact
## User Request
User feedback: "remove the theming of table headers, it looks bad. Keep normal theming of preview"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This fix addresses the critical issue where double-clicking .md files would not open them in the installed PanConverter application on Windows.
## Root Cause
When a user double-clicks a file and the app is already running, Windows tries to launch a SECOND INSTANCE with the file path. Without single-instance lock handling, that second instance would exit and the first instance would never receive the file path.
## Changes
- Added single-instance lock handling in main.js (lines 52-85)
- Implemented second-instance event handler to capture file paths
- Focus existing window when second instance is attempted
- Pass file path to existing instance using openFileFromPath()
- Properly handle rendererReady state for file opening
## Testing
- Works in development mode (npm start)
- Should now work correctly in installed Windows app with double-click
- Maintains single instance behavior across all file opening methods
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Cleaned up debug logging from file opening investigation:
- Removed console.log from command line arg processing
- Removed console.log from renderer-ready handler
- Removed console.log from openFileFromPath function
- Removed console.log from file-opened IPC handler
The double-click file opening fix is confirmed working.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
CRITICAL BUG FIX: Files opened via double-click were not rendering in the application.
Root Cause:
- The openFileFromPath() function was sending IPC 'file-opened' message WITHOUT checking if rendererReady was true
- When files were double-clicked before renderer initialization, the IPC message was sent but lost
- The comment "Always try to send, the renderer will handle it when ready" was incorrect
The Fix (src/main.js:1586):
- Added rendererReady check to the conditional: if (mainWindow && mainWindow.webContents && rendererReady)
- Now properly stores file in app.pendingFile when renderer is not ready
- File is opened correctly when renderer-ready signal arrives
Flow:
1. File double-clicked → openFileFromPath() called
2. If renderer NOT ready → store in app.pendingFile
3. When renderer sends 'renderer-ready' → openFileFromPath(app.pendingFile) is called
4. This time renderer IS ready → file opens successfully
Version: 1.7.4
- Updated package.json version to 1.7.4
- Updated About dialog version to 1.7.4
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Fixed critical file opening bug and theme visibility issues, plus added ConcreteInfo branded themes.
Bug Fixes:
• Fixed double-click file opening race condition
- Removed setTimeout logic from did-finish-load handler
- Now relies solely on renderer-ready IPC signal for proper initialization
- Files from Windows Explorer now open correctly on first attempt
• Fixed theme preview text visibility for 14 themes
- Added proper .pane:last-child background overrides
- Fixed dark text on dark backgrounds and light text on light backgrounds
- Affected themes: Dracula, Nord, One Dark, Atom One Light, Material,
Gruvbox Dark/Light, Tokyo Night, Palenight, Ayu Dark/Light/Mirage,
Oceanic Next, Cobalt2
New Features:
• Added 3 ConcreteInfo branded themes
- Concrete Dark: Very dark theme with orange accents
- Concrete Light: Light theme with orange accents
- Concrete Warm: Mid-tone gray theme with orange accents
- All themes use ConcreteInfo brand colors: #0d0b09, #464646, #9a9696, #e3e3e3, #e5461f
• Updated theme count from 19 to 22 themes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## New Features
- Added 14 beautiful new themes (Dracula, Nord, One Dark, Atom One Light, Material, Gruvbox Dark/Light, Tokyo Night, Palenight, Ayu Dark/Light/Mirage, Oceanic Next, Cobalt2)
- Total of 19 professionally-designed themes now available
- All themes fully support glassmorphism effects from v1.7.1
## Bug Fixes
- Fixed undo/redo menu integration - connected Edit menu to custom undo/redo functionality
- Added IPC event listeners for proper keyboard shortcut support (Ctrl+Z, Ctrl+Shift+Z)
## Technical Improvements
- Complete CSS styling for all UI elements per theme (tabs, toolbar, editor, preview, status bar)
- Theme-aware color schemes for syntax highlighting
- Comprehensive CSS implementation (965+ lines for new themes)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Updated version from 1.7.0 to 1.7.1 in package.json
- Updated About dialog version in main.js
- Added modern glassmorphism UI as first feature
- Updated CLAUDE.md with v1.7.1 documentation
- Documented glassmorphism design system
- Listed all modern UI features and technical details
- Updated last modified date to October 11, 2025
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Created comprehensive modern CSS design system
- Glassmorphism effects with backdrop-filter blur
- Animated purple-blue gradient background
- Modern Inter and JetBrains Mono typography
- Smooth transitions and hover effects
- Enhanced tab, button, and dialog styling
- Custom scrollbars and progress bars
- CSS custom properties for consistent theming
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Added did-finish-load event listener to ensure window is fully loaded
- Added 500ms delay to allow TabManager initialization
- Improved openFileFromPath function with better logging
- Fixed race condition where files opened via double-click weren't rendering
Fixes #file-association-rendering-issue
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Major new features:
• Complete PDF Editor with 10 operations (merge, split, compress, rotate, delete, reorder, watermark, encrypt, decrypt, permissions)
• Universal File Converter supporting LibreOffice, ImageMagick, FFmpeg, and Pandoc
• Single file and batch folder conversion capabilities
• Advanced options for all conversion tools
PDF Editor Features:
• Merge multiple PDFs into one document
• Split PDFs by page ranges, intervals, or file size
• Compress PDFs to reduce file size
• Rotate pages at 90°, 180°, or 270°
• Delete unwanted pages from PDFs
• Reorder pages in any custom order
• Add text watermarks with customizable position, size, color, and opacity
• Password protect PDFs with 128-bit or 256-bit encryption
• Remove password protection from PDFs
• Set granular document permissions
Universal File Converter Features:
• LibreOffice: DOCX, PDF, ODT, RTF, TXT, HTML, XLSX, PPTX conversions
• ImageMagick: Image format conversions with quality, DPI, resize, compression options
• FFmpeg: Video/audio conversions with codec, bitrate, preset, framerate options
• Pandoc: Document markup conversions with advanced options
• Batch folder processing with recursive subfolder support
• 100% offline, open-source, no API keys required
Technical Implementation:
• Uses pdf-lib v1.17.1 for all PDF operations
• Full async/await implementation for optimal performance
• Comprehensive error handling and user feedback
• Progress indicators for long-running operations
• Page range parsing and validation
• RGB color conversion for watermarks
Files modified:
• src/main.js: Added 500+ lines of PDF operation functions and IPC handlers
• src/renderer.js: Added 480+ lines of UI event handlers and dialog management
• src/index.html: Added 600+ lines of comprehensive UI dialogs
• CLAUDE.md: Updated documentation with v1.7.0 features
• package.json: Version bump to 1.7.0
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Version 1.5.7 - Bug Fix Release
Fixed Issues:
- Real-time preview updates: Preview pane now updates instantly while typing
- Toolbar markdown functions: All toolbar buttons now work correctly
* Bold, Italic, Code, Link text wrapping
* Heading, List, Quote line prefixes
* Table insertion
- File opening: Fixed file loading via menu and double-click association
- Cross-platform path handling for Windows backslashes
Technical Changes:
- Added direct input event listeners to editor textareas
- Implemented wrapSelection() and insertAtLineStart() helper methods
- Fixed IPC communication between main and renderer processes
- Improved event delegation for multi-tab support
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Enhanced getPandocPath() to check common Windows installation locations
- Improved Pandoc path detection for AppData/Local/Pandoc installation
- Enhanced error reporting with more detailed feedback for export failures
- Added better logging for Pandoc command execution and output
- Fixed issue where DOCX exports would fail silently when Pandoc wasn't in PATH
- Now properly detects Pandoc in standard Windows installation locations
- 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
- Removed all custom icon references from build configuration
- Using default Electron icon for consistent, standard appearance
- Updated to version 1.5.2
- Rebuilt NSIS installers with default iconography
- Combined advanced export options with built-in fallbacks
- Integrated Windows context menu installation scripts
- Added CLI conversion functionality
- Enhanced error handling for pandoc availability
- Updated to version 1.5.0 with comprehensive feature set
- Resolved merge conflicts preserving all functionality
- Fixed export function issues with comprehensive pandoc detection
- Added built-in HTML and PDF export fallbacks (no pandoc required)
- Improved error handling with clear user messages
- Enhanced code quality with optional chaining and better error handling
- Fixed NSIS installer script issues for Windows build
- Added comprehensive logging and debugging for export process
- Created test files and documentation for export functionality
- Successfully builds Windows release with proper XLSX support
Resolves export failures and provides robust fallback mechanisms.
Major improvements including optional advanced export options, removed proprietary dependencies for better open-source compatibility, and comprehensive new features for enhanced user experience.
🔧 Export Functions & Advanced Options:
• Fixed export function issues after advanced options integration
• Added optional advanced export checkbox (unchecked by default)
• Clean UI separation between simple and advanced export workflows
🏗️ Open Source Compatibility:
• Removed bundled Pandoc binaries - requires system installation
• Replaced proprietary XLSX with open-source CSV export
• Eliminated licensing concerns with bundled dependencies
✨ Advanced User Experience Features:
• Auto-save system with visual indicators every 30 seconds
• Enhanced document statistics (lines, paragraphs, sentences, reading time)
• Recent files menu with persistent storage (last 10 files)
• Mathematical expression support with KaTeX rendering
• Improved export dialog with better user experience
📚 Updated documentation with new dependency requirements and features
🤖 Generated with [Claude Code](https://claude.ai/code)
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)
- Bump version to 1.4.0 for context menu feature release
- Add context menu integration to feature list in About dialog
- Include command-line interface in feature highlights
🤖 Generated with [Claude Code](https://claude.ai/code)
- Add context menu entries for all supported file types
- Implement CLI interface with --convert and --convert-to commands
- Create installation/uninstallation scripts (registry, PowerShell, batch)
- Add NSIS installer integration for automatic context menu setup
- Support direct conversion from right-click menu
- Include comprehensive documentation and usage instructions
🤖 Generated with [Claude Code](https://claude.ai/code)
- 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)
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)
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)
- 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
- 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
- Enhanced PDF export with multiple LaTeX engine fallbacks
- Fixed file association and direct file opening from OS
- Removed redundant converter menu, moved import to File menu
- Implemented comprehensive tabbed interface for multiple files
- Added tab management with keyboard shortcuts (Ctrl+N, Ctrl+W, Ctrl+Tab)
- Enhanced UI with tab bar and improved navigation
- Updated to version 1.3.0 with new features
- Improved main process and renderer architecture for multi-file support
- Add comprehensive Find & Replace with match highlighting
- Add toggleable line numbers with theme support
- Implement full undo/redo functionality with keyboard shortcuts
- Add smart auto-indentation for lists and code blocks
- Enhanced keyboard shortcuts for productivity
- Advanced tab handling for indentation/outdentation
- Updated About dialog with v1.2.0 and complete feature list
- Add Find & Replace to Edit menu
- Updated README.md with comprehensive feature documentation
🤖 Generated with [Claude Code](https://claude.ai/code)
- Add PowerPoint export (PPTX/ODP) with slide-level formatting
- Add comprehensive document conversion menu with import/export
- Add interactive table creation helper in markdown editor
- Update documentation with all new features and version history
- Improve menu organization for better user experience
🤖 Generated with [Claude Code](https://claude.ai/code)
- Added Excel (XLS/XLSX) and ODS export functionality
- Updated author to Amit Haridas (amit.wh@gmail.com)
- Renamed app from 'Pan Converter' to 'PanConverter'
- Version bump to 1.1.0
2025-09-01 19:44:48 +05:30
340 changed files with 78117 additions and 6917 deletions
**Application:** MarkdownConverter - Electron-based Markdown editor and document converter
**Target Version:** 4.0.0
**Assessor:** Security Audit Agent
---
## Executive Summary
This assessment identified **10 security findings** ranging from **Critical to Low severity**. The most significant concerns involve insecure Electron security configuration that could allow XSS attacks to escalate to full system access, arbitrary code execution via the REPL feature, and missing input validation on file operations.
| Severity | Count |
|----------|-------|
| Critical | 2 |
| High | 3 |
| Medium | 3 |
| Low | 2 |
---
## Vulnerability Findings
### CVE-MC-001: Insecure Electron Security Configuration (Critical)
**CVSS 3.1 Score: 9.6 (Critical)**
**CWE-265: CWE-1021: Improper Restriction of Renderers**
**Location:**`src/main.js` (lines 328-332)
```javascript
webPreferences:{
nodeIntegration:true,
contextIsolation:false,
spellcheck:true
},
```
**Description:**
The main application window has `nodeIntegration: true` and `contextIsolation: false`, which is the most insecure Electron configuration. This allows the renderer process direct access to Node.js APIs, meaning any XSS vulnerability in the markdown rendering or external content could lead to full system compromise.
**Exploitability:**
- An attacker who can inject malicious JavaScript (via markdown files, XSS in preview, or compromised dependencies) gains immediate access to:
- Full file system read/write via `fs` module
- Command execution via `child_process`
- Network access via `net` module
- All system resources
**Attack Scenario:**
1. User opens a malicious markdown file containing embedded JavaScript
2. The JavaScript executes in the renderer with full Node.js access
3. Attacker can read sensitive files, execute commands, exfiltrate data
**Remediation:**
```javascript
webPreferences:{
nodeIntegration:false,
contextIsolation:true,
sandbox:true,
preload:path.join(__dirname,'preload.js')
}
```
**Note:** The preload.js file already implements a secure IPC bridge but it is not being utilized for the main window.
---
### CVE-MC-002: Arbitrary Code Execution via REPL Feature (Critical)
**CVSS 3.1 Score: 9.3 (Critical)**
**CWE-94: Improper Control of Generation of Code ('Code Injection')**
**Location:**`src/main.js` (lines 4369-4396)
**Description:**
The `execute-code` IPC handler allows execution of arbitrary Python and Bash scripts through the REPL panel. While JavaScript execution appears to have been removed or limited, Python and Bash commands are executed via `execFile` with user-supplied code.
Apply secure configuration (`nodeIntegration: false`, `contextIsolation: true`) consistently across all windows.
---
### CVE-MC-009: Command Execution via External Tools (Low)
**CVSS 3.1 Score: 4.4 (Low)**
**CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')**
**Location:**`src/main.js` (lines 1915-1972)
**Description:**
While the application uses `execFile` instead of `exec` (good practice), external tools (Pandoc, LibreOffice, FFmpeg, ImageMagick) are invoked with file paths that could potentially be manipulated.
**Positive Finding:**
The code correctly uses `execFile` with argument arrays instead of shell commands, mitigating most command injection vectors.
**Remaining Risk:**
- File paths are not validated against malicious names
- Special characters in filenames could cause issues with external tools
**Remediation:**
- Validate file paths before passing to external tools
- Sanitize filenames of special characters
---
### CVE-MC-010: Missing Dependency Version Pinning (Low)
**CVSS 3.1 Score: 3.5 (Low)**
**CWE-1035: Using Components with Known Vulnerabilities**
**Location:**`package.json`
**Description:**
Dependencies use `^` version ranges which could allow automatic updates to versions with vulnerabilities:
The MarkdownConverter application has significant security vulnerabilities that could allow an attacker to execute arbitrary code, access sensitive files, and compromise the user's system. The most critical issue is the insecure Electron configuration combined with XSS attack vectors in the markdown rendering pipeline.
**Overall Security Rating: HIGH RISK**
The positive finding is that much of the security infrastructure (preload.js, DOMPurify) is already in place but not properly utilized. With focused remediation effort, the application can achieve a much stronger security posture.
The analysis identified **10 vulnerabilities** with a combined risk score of **7.8 (HIGH)**. The most critical issues enable complete system compromise through XSS-to-RCE attack chains.
The MarkdownConverter application has a **HIGH RISK** threat profile due to the combination of:
- Untrusted content rendering (markdown preview)
- Direct system access (nodeIntegration)
- Code execution capability (REPL)
**Immediate action required on P0 items to reduce attack surface.**
The fixes applied in this session (CSP, path traversal, UI accessibility) have reduced the risk profile, but the critical nodeIntegration issue requires significant refactoring.
# Comprehensive UI Design Review - MarkdownConverter Electron Application
## Executive Summary
This review covers the UI design of the MarkdownConverter Electron application, analyzing visual design, usability, code quality, and performance across all UI files. The application has a solid foundation but has several areas requiring attention.
---
## 1. Visual Design Review
### 1.1 Spacing & Layout Consistency
| Severity | Issue | Location | Recommendation |
|----------|-------|----------|----------------|
| **Major** | Inconsistent padding values across files | Multiple CSS files | Standardize to 4px/8px base scale |
| **Major** | Multiple reset declarations | `styles.css:1-5`, `styles-modern.css:42-47` | Consolidate resets into single file |
| **Minor** | Tab padding varies between themes | `styles.css:36`, `styles-modern.css:101` | Use CSS variables for consistent padding |
/* Create a single base.css or remove from styles-modern.css */
/* Use CSS variables for spacing scale */
:root{
--space-1:4px;
--space-2:8px;
--space-3:12px;
--space-4:16px;
--space-5:24px;
--space-6:32px;
}
```
### 1.2 Typography Consistency
| Severity | Issue | Location | Recommendation |
|----------|-------|----------|----------------|
| **Major** | Font-family declared multiple times with different fallbacks | `styles.css:8`, `styles-modern.css:50`, `styles-concreteinfo.css:32` | Standardize font stack |
The MarkdownConverter application has a functional UI with good visual variety through its theme system. However, there are significant opportunities for improvement in:
1.**Accessibility** - Critical for users with disabilities
2.**Code organization** - Reduce CSS duplication and improve maintainability
3.**Component consistency** - Standardize interactive element sizing and states
4.**Performance** - Optimize CSS loading and reduce bundle size
Addressing the Critical and Major issues will significantly improve both user experience and code maintainability.
Core application code lives in `src/`. Use `src/main.js` for the Electron main process, `src/preload.js` for the preload bridge, and `src/renderer.js` plus `src/editor/`, `src/sidebar/`, `src/repl/`, and `src/utils/` for renderer-side features. Electron adapter code is in `src/adapters/electron/`. Reusable markdown/document templates live in `src/templates/`. Static assets and icons are in `assets/`. Tests are in `tests/`, and build output goes to `dist/`.
## Build, Test, and Development Commands
-`npm start`: launch the Electron app locally.
-`npm test`: run the Jest suite once.
-`npm run test:watch`: rerun tests during local development.
-`npm run test:coverage`: generate coverage output.
-`npm run lint` / `npm run lint:fix`: check or fix ESLint issues in `src` and `tests`.
-`npm run format` / `npm run format:check`: apply or verify Prettier formatting.
-`npm run build:linux`, `npm run build:win`, `npm run build:mac`: create platform packages with `electron-builder`.
## Coding Style & Naming Conventions
This repo uses Prettier and ESLint. Follow `.prettierrc`: 2-space indentation, single quotes, semicolons, trailing commas where valid in ES5, and a 100-character line width. Prefer `camelCase` for variables/functions, `PascalCase` for classes, and kebab-case for file names only when already established. Keep module boundaries clear: UI logic in renderer modules, OS/file-system work behind Electron IPC and adapters.
## Testing Guidelines
Tests use Jest with `jest-environment-jsdom`. Add new tests under `tests/` with `*.test.js` names, mirroring the feature area when possible, for example `tests/sidebar.test.js` or `tests/print-preview.test.js`. Update or add regression tests for renderer behavior, preload APIs, and utility helpers when fixing bugs. Run `npm test` before opening a PR; use `npm run test:coverage` for larger refactors.
## Commit & Pull Request Guidelines
Recent history follows Conventional Commit prefixes such as `feat:`, `fix:`, and `refactor:`. Keep subjects short and imperative, for example `fix: guard modal cleanup on close`. PRs should describe the user-visible change, note test coverage, link any related issue, and include screenshots or GIFs for UI changes.
## Security & Configuration Tips
Do not bypass preload boundaries or introduce direct `eval`/dynamic code paths; ESLint already treats these as errors. Export and conversion features depend on external tools such as Pandoc, FFmpeg, ImageMagick, and LibreOffice, so document any new runtime dependency in `README.md` and packaging config.
> General code-quality, JavaScript, git, security, and testing standards are in the **global CLAUDE.md**. This file holds project- and branch-specific notes.
## Project Overview
## Project Overview
**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.
Electron desktop app for Markdown editing and universal file conversion powered by Pandoc. Cross-platform (Win/macOS/Linux). Features: multi-tab editor with live preview, 25+ themes, PDF viewer/editor (merge/split/compress/rotate/watermark/password), export to 20+ formats (PDF/DOCX/ODT/EPUB/HTML/LaTeX/RTF/PPTX), batch conversion, syntax highlighting, diagram support (Mermaid), Git integration, and a plugin system.
This is the **primary/release branch** — a vanilla JavaScript Electron app with no bundler or framework in the renderer. The renderer is a single large `renderer.js` (5,300+ lines) loaded directly via `src/index.html`. All UI is hand-rolled DOM manipulation.
├── index.html # Application layout with tabbed interface
├── styles.css # Base styling with multi-theme support
└── styles-modern.css # Modern glassmorphism UI design system (v1.7.1)
assets/
### Main Process (`src/main.js` — 4,260 lines)
└── icon.png # Application icon
Monolithic main process file. Contains all IPC handlers, Pandoc invocation, file operations, menu definitions (600+ lines), and window lifecycle. Key modules extracted:
-`src/main/PDFOperations.js` — PDF manipulation via `pdf-lib` (merge, split, compress, rotate, delete, reorder, watermark, encrypt, decrypt, permissions)
-`src/main/GitOperations.js` — Git status/stage/commit/log via `simple-git`
package.json # Dependencies and build configuration
### Renderer (`src/renderer.js` — 5,361 lines)
CLAUDE.md # Development documentation for AI assistants
Vanilla JS, no framework. Directly manipulates DOM. Loads CodeMirror 6 via `src/editor/codemirror-setup.js`. Uses `marked` + `highlight.js` + `DOMPurify` + `mermaid` for rendering. Lazy-loads sidebar panels, REPL, command palette, zen mode.
```
### Preload (`src/preload.js` — 448 lines)
Exists as IPC bridge, but **`contextIsolation: false` and `nodeIntegration: true`** — the renderer has full Node access. Preload is effectively a thin passthrough.
Manifest-based discovery (`manifest.json`). Built-in `writing-studio` plugin with sprint/goal/snapshot management. Plugin API exposed via `src/plugins/plugin-api.js`.
### Settings
Custom JSON file store at `<userData>/settings.json` (NOT `electron-store` despite the dependency). Recent files at `<userData>/recent-files.json`.
| **Pandoc** | Yes (for exports) | Downloaded to `bin/<platform>/pandoc` via `scripts/download-tools.js` (v3.9.0.2). Falls back to system PATH. Must be present for DOCX/ODT/EPUB/LaTeX/PPTX export. |
| **MiKTeX / TeX Live** | Optional | For LaTeX PDF export; MiKTeX PATH injected on Windows automatically |
| **ImageMagick** | Optional | Linux image conversion; listed as deb dependency |
| **LibreOffice** | Optional | Enhanced document conversion; listed as deb dependency |
## Development Commands
## Development Commands
### Prerequisites
```bash
```bash
# Install Node.js dependencies
npm start # Launch Electron app (dev mode)
npm install
npm test# Jest test suite
npm test:watch # Jest in watch mode
# Install Pandoc (required for export functionality)
npm test:coverage # Jest with coverage report
# Ubuntu/Debian:
npm run lint # ESLint check (src + tests)
sudo apt-get install pandoc
npm run lint:fix # ESLint auto-fix
npm run format # Prettier write
# macOS:
npm run format:check # Prettier check only
brew install pandoc
npm run download-tools # Download Pandoc binaries to bin/
npm run generate-icons # Generate app icons via sharp
# Windows: Download from https://pandoc.org/installing.html
```
```
### Running the Application
## Build & Package
```bash
# Start development server
**Tool:**`electron-builder` (v26.0.12), config inline in `package.json` (no separate config file).
npm start
| Target | Platforms |
# Start with debugging
|---|---|
npm start --enable-logging
| `npm run build` | electron-builder (default platform) |
```
| `npm run build:win` | Windows: NSIS installer + portable + zip (x64) |
| `npm run build:mac` | macOS: default dmg |
### Building & Packaging
| `npm run build:linux` | Linux: deb + AppImage + snap |
| `npm run dist` | Build without publish |
```bash
| `npm run dist:all` | Build for all platforms |
# Generate application icons
npm run generate-icons
**Bundled with builds:** Pandoc binary per platform. FFmpeg via `ffmpeg-static` (asarUnpacked). NSIS installer uses custom script at `scripts/nsis-installer.nsh`.
# Build for current platform
**Output:**`dist/` directory.
npm run build
**CI:** GitHub Actions workflows in `.github/workflows/` (ci.yml, release.yml).
# Platform-specific builds
npm run build:win # Windows
## Project Conventions / Gotchas
npm run build:mac # macOS
npm run build:linux # Linux (AppImage, .deb, .snap)
- **No bundler/transpilation.** The app uses vanilla CommonJS JavaScript. `src/main.js` is loaded directly by Electron. No webpack, no Vite, no TypeScript, no Babel.
- **Monolithic files.** `main.js` (4,260 lines) and `renderer.js` (5,361 lines) contain most logic. Not ideal but is the current state of this branch.
# Build for all platforms
- **CodeMirror 6** for the editor, configured in `src/editor/codemirror-setup.js`.
npm run dist:all
- **PDF rendering** uses `pdfjs-dist`; **PDF manipulation** uses `pdf-lib` in the main process.
```
- **Renderer security is weak** — full Node access in renderer. Do NOT introduce new privileged renderer code without understanding this.
- **Pandoc is external.** Must be installed separately or downloaded via `npm run download-tools`. HTML and built-in PDF export work without Pandoc; other formats require it.
**Claude Assistant**: Development completed for v1.7.2 with 14 new professionally-designed themes (Dracula, Nord, Tokyo Night, Gruvbox, Ayu, Material, Oceanic Next, Palenight, Cobalt2, and more) bringing total to 19 themes, plus fixed undo/redo menu integration for proper keyboard shortcut support.
A cross-platform Markdown editor and converter powered by Pandoc.
# MarkdownConverter

A powerful cross-platform Markdown editor and document converter powered by Pandoc, built with Electron. 100% open-source with no proprietary dependencies.
## Features
## Features
### ✨ Advanced Markdown Editor
### Markdown Editor
- 🗂️ **Tabbed Interface** - Work with multiple files simultaneously in separate tabs
- 🎨 **Multiple Themes** - Choose from Light, Dark, Solarized, Monokai, or GitHub themes
- 💾 **Auto-Save** - Never lose your work with automatic saving every 30 seconds
- 📊 **Enhanced Statistics** - Detailed document statistics including word count, character count, lines, paragraphs, sentences, and estimated reading time
- 🕒 **Recent Files** - Quick access to recently opened files via File menu
- **MarkItDown import** - Any file → Markdown via [Microsoft MarkItDown](https://github.com/microsoft/markitdown): PDF, DOCX, PPTX, XLSX, Outlook .msg, EPUB, images, ZIP (audio/OCR with the `[all]` extras)
- **Excel export** - Markdown tables to native .xlsx workbooks (one sheet per table)
- **AI Assistant** - Multi-provider AI help (OpenAI/Anthropic/Ollama/LM Studio): chat panel, summarize/improve/translate commands, grammar proofreading
- **Inline comments** - Anchor-based document comments in `.comments/` sidecars with F8 navigation
- **Wiki-links & Backlinks** - `[[Note]]` links with click-to-create and a "what links here?" panel (local knowledge base)
- **Crash recovery** - Session restore of open tabs and unsaved buffers after a crash
- **Version history** - Automatic pre-save snapshots with restore/diff/delete from the History panel
| Electron | 41.x | MIT | and its bundled Chromium (BSD-style licenses) / Node.js (MIT) / OpenSSL (Apache-2.0) — see <https://www.electronjs.org/blog/electron-licensing> |
### GPL source availability (GPL §3 offer)
Corresponding source for every GPL-licensed binary distributed with this app
is available on written request and from these permanent locations — see
**[SOURCES.md](SOURCES.md)** for exact versions and URLs.
### Python packages inside the bundled MarkItDown binary
The frozen MarkItDown binary embeds CPython and (each MIT/Apache-2.0/BSD-3/
- Vim keybindings (View → Vim Mode, persisted, live toggle via CodeMirror Compartment)
- Snippet Tab-expansion: type a snippet name and press Tab to insert it
- Zen Mode word-goal setter (the HUD progress bar finally has UI)
#### Export / Conversion
- **Real PDF encryption**: pdf-lib swapped for @cantoo/pdf-lib — encrypt/decrypt/permissions now actually work (UI auto-enables via the capability probe)
- **XLSX export**: markdown tables → native Excel workbook, one sheet per table (no Pandoc needed)
- **ODT headers/footers + page size**: real ODF styles.xml patching replaces the empty stub
- **Local PlantUML rendering**: diagrams render on-machine via the `plantuml` CLI when installed; plantuml.com stays as fallback
- **KaTeX bundled locally** (CSS + fonts): math renders offline, no CDN calls
- Writing heatmap (GitHub-style 30-day grid) in the writing-studio Goals panel
#### Platform
- Quick Note global scratchpad (Ctrl+Alt+Q, works when unfocused; appends to `notes/quick-notes.md`)
- Deep link protocol `markdownconverter://open?path=…`
- REPL confirmation dialog before first code execution per language per session (unsandboxed-execution guard rail)
- Writing-studio's four sidebar panels (Manuscript/Goals/Snapshots/Proofread) are now actually wired with rail icons
- Plugin sidebar panels get automatic rail icons via `registerPanel({icon})`
### Bug Fixes
-`Ctrl+Shift+P` collision: PDF (Enhanced) export now `Ctrl+Alt+Shift+P`; Command Palette keeps `Ctrl+Shift+P`
- Universal Converter's Pandoc tool no longer always reports "not installed" (`checkConverterAvailable` gained a pandoc case with bundled-binary check)
- CLI headless export: removed dangling `--css` / `--reference-doc` flags that made pandoc exit with an error; `--self-contained` replaced with `--standalone` (Pandoc 3.x)
- Removed dead "Open Export Options Dialog…" button from the converter dialog
- Removed duplicate `styles-zen.css` include
### Security
- AI provider requests carry size caps (200KB prompt), timeouts (120s), and user-safe error surfaces
- Version-history reads validate ids against traversal; history listing requires a valid document path
- PlantUML local rendering removes the diagram-text exfiltration path when a local CLI exists (CVE-MC-007 follow-up)
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.