mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-10-01 17:29:29 +05:30
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:
+16
-7
@@ -5,6 +5,7 @@
|
||||
|
||||
const { ipcRenderer, webUtils } = require('electron');
|
||||
const { AutosaveController } = require('./renderer/autosave-client');
|
||||
const writingStats = require('./utils/writing-stats');
|
||||
|
||||
// Renderer-side autosave controller. The TabManager calls into this when a
|
||||
// tab becomes dirty so the current buffer is periodically persisted under
|
||||
@@ -1203,17 +1204,25 @@ class TabManager {
|
||||
const tab = this.tabs.get(this.activeTabId);
|
||||
if (!tab) return;
|
||||
const content = tab.content;
|
||||
const words = content.trim()
|
||||
? content
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
.filter((word) => word.length > 0).length
|
||||
: 0;
|
||||
// Words/chars used the raw buffer before — reading-time + grade level
|
||||
// need the markdown chrome (code fences, link URLs, image syntax) stripped
|
||||
// out, which writing-stats.stripMarkdown() does.
|
||||
const stats = writingStats.computeStats(content || '');
|
||||
const chars = content.length;
|
||||
const wordEl = document.getElementById('word-count');
|
||||
const charEl = document.getElementById('char-count');
|
||||
if (wordEl) wordEl.textContent = `Words: ${words}`;
|
||||
const timeEl = document.getElementById('reading-time');
|
||||
const gradeEl = document.getElementById('grade-level');
|
||||
if (wordEl) wordEl.textContent = `Words: ${stats.wordCount}`;
|
||||
if (charEl) charEl.textContent = `Chars: ${chars}`;
|
||||
if (timeEl) {
|
||||
const mins = stats.readingTimeMinutes;
|
||||
timeEl.textContent = mins < 1 ? '<1 min read' : `~${Math.ceil(mins)} min read`;
|
||||
}
|
||||
if (gradeEl) {
|
||||
gradeEl.textContent =
|
||||
stats.fleschKincaidGrade === null ? 'Grade —' : `Grade ${stats.fleschKincaidGrade}`;
|
||||
}
|
||||
}
|
||||
updateCursorPosition(view) {
|
||||
if (!view) return;
|
||||
|
||||
Reference in New Issue
Block a user