- src/utils/csv-to-table.js — pure module. Auto-detects the delimiter
(tab wins over comma; comma wins over semicolon). RFC 4180-style
parsing handles quoted fields, escaped quotes (""), and CRLF. Cells
are escaped for markdown tables (\\ for backslashes, \| for pipes,
newlines stripped). Alignment: a column is right-aligned when every
non-empty cell matches a numeric pattern AND there are ≥2 rows or
≥1 multi-character cell (single-char numbers like "1" alone are
too ambiguous to call as numeric — could be labels). Single-row input
produces a header-only table (no fabricated "Column N" labels, no
body).
- src/editor/smart-paste.js — paste handler now tries CSV first (it
needs no async), falls back to the existing URL → title flow.
Tests (30 new, tests/csv-to-table.test.js):
- detectDelimiter: tab > comma > semicolon, empty/non-string safe
- parseRows: simple, RFC 4180 quoted, escaped quotes, CRLF, multi-line
- escapeCell: pipes, backslash-first escaping, newline strip, null/number
- csvToTable: simple CSV, single-row (header-only), TSV, empty input
- alignment: numeric detection (≥2 rows OR ≥1 multi-char cell), currency,
percentages, text columns stay left
- escaping inside cells (pipes, newlines)
- ragged-row padding
- looksLikeCsv: true for tab/comma multi-row, false for single row,
column-count mismatch, prose, very short input
Full suite: 72 suites, 861 tests, lint+format clean.
Amit Haridas
- src/utils/writing-stats.js — pure module: stripMarkdown() drops fenced
code blocks, inline code, image URLs, link URLs, headings, blockquote
markers, list bullets, and emphasis markers so the word count reflects
the prose a reader actually consumes (the convention used by Hemingway,
iA Writer). splitSentences / countSyllables use Flesch's standard
heuristics. computeStats returns wordCount, sentenceCount,
syllableCount, readingTimeMinutes (default 220 wpm),
fleschKincaidGrade, charCount.
- src/renderer.js — _updateStatusBar now calls computeStats and updates
three new status items: ~X min read, Grade N.N, and the existing Words
+ Chars counters use the stripped count.
- src/index.html — two new status items: #reading-time and #grade-level.
Tests (23 new, tests/writing-stats.test.js): markdown stripping (fenced,
inline, images, links, wikilinks, headings, lists, emphasis, HTML),
sentence splitter edge cases, syllable heuristic (short words, silent e,
empty), and computeStats with custom wpm + null-safe inputs.
Full suite: 68 suites, 789 tests, lint+format clean.
Amit Haridas
- 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
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).
- 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
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
- 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>
- 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