Word & Character Counter
Count words, characters, sentences, paragraphs, and estimate reading/speaking time.
The Word & Character Counter measures seven stats live as you type: Words, Characters, Characters (no spaces), Sentences, Paragraphs, Reading Time (~200wpm), and Speaking Time (~150wpm) — each on its own card with a descriptive emoji. The StepIndicator walks Input → Results, but the stats grid actually updates on every keystroke via countStats dispatched into Redux, so you are never stuck waiting on a second step for the numbers.
Share encodes your text into a URL hash (copyShareableUrl / decodeToolConfig) rather than posting it to a server — the toast says "Link copied!" and reopening that link restores the full text on mount. Clear resets everything with a "Cleared!" toast. Empty input returns all zeros and "0 min" times, so a fresh page reads cleanly. The card describes the job plainly: "Count words, characters, sentences, paragraphs, and estimate reading/speaking time."
How it works
lib/wordCounter.ts countStats computes characters as the raw length, no-spaces by stripping \s, words via trim().split(/\s+/).filter(Boolean), sentences by splitting on [.!?]+ and keeping non-empty pieces, and paragraphs by splitting on blank lines (\n\s*\n) with a fallback of 1 when any text is present. Reading time is words/200 minutes and speaking time words/150 minutes, each rounded up with a "< 1 min" special case.
The wordCounterSlice holds text and result; an effect dispatches resultSet on every text change so the seven cards stay in lockstep with the textarea. Share builds a client-side URL hash containing your config and, on mount, decodeToolConfig('word-counter') dispatches textSet to restore it — no API server is involved in either direction. Stats recompute fully in the browser.
How to use
- On Step 1 "Input", paste or type into "Input Text" (placeholder "Type or paste your text here...").
- Watch the stats grid update live on every keystroke (countStats → resultSet).
- Read the seven cards: Words, Characters, Characters (no spaces), Sentences, Paragraphs, Reading Time (~200wpm), Speaking Time (~150wpm).
- Click "Share" to copy a URL hash containing your text — toast "Link copied!" (or "Failed to copy link" on denial).
- Reopen a shared link — the text restores on mount via decodeToolConfig('word-counter').
- Click "Clear" to reset state (toast "Cleared!") and return the flow to Step 1 "Input".
Tips
- Reading time assumes 200 words per minute and speaking 150 wpm — both rates are printed right on the card labels.
- Empty text returns all zeros and "0 min" times from countStats, so clearing gives an honest baseline.
- Paragraphs require a blank line between blocks (\n\s*\n) — a single unbroken block counts as exactly 1 paragraph.
- Share is a URL hash, not an upload — anyone you send the link to can decode the same text client-side, so share accordingly.
Word & Character Counter FAQ
How is reading time computed?
words / 200 minutes, rounded up, with "< 1 min" shown under a minute (lib/wordCounter.ts).
What counts as a sentence?
Text split on [.!?]+ with non-empty pieces counted — each punctuation run ends a sentence.
Does Share upload my text?
No server call — copyShareableUrl encodes the config into the URL hash, and the toast "Link copied!" confirms the clipboard copy.
Can I restore from a link?
Yes — a mount effect reads decodeToolConfig('word-counter') from the hash and dispatches textSet to refill the input.
Credits
- In-repo countStats — All counting logic in lib/wordCounter.ts; share via src/lib/shareableUrl.ts (client-side hash)