feat(statusbar): word count + reading time + Flesch-Kincaid grade

- 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
This commit is contained in:
2026-09-14 08:54:28 +05:30
parent da97369b44
commit 7397e7f618
4 changed files with 347 additions and 7 deletions
+4
View File
@@ -2847,6 +2847,10 @@
<span class="status-separator">|</span>
<span class="status-item" id="char-count">Chars: 0</span>
<span class="status-separator">|</span>
<span class="status-item" id="reading-time" title="Estimated reading time at 220 words/minute">~0 min read</span>
<span class="status-separator">|</span>
<span class="status-item" id="grade-level" title="Flesch-Kincaid grade level (lower = easier)">Grade —</span>
<span class="status-separator">|</span>
<span class="status-item" id="line-col">Ln 1, Col 1</span>
<span class="status-separator">|</span>
<span class="status-item" id="encoding">UTF-8</span>