Skip to content

Commit b82fa21

Browse files
committed
Update reading time functionality
1 parent c2a8ccb commit b82fa21

File tree

8 files changed

+109
-28
lines changed

8 files changed

+109
-28
lines changed

README.md

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
</div>
44

55
<p align="center">
6-
A lightweight React hook for analyzing text and providing various statistics such as word count, character count, search frequency, and more.
6+
A lightweight React hook for analyzing text and providing various statistics such as estimated reading time, search frequency, word count, and more.
77
</p>
88

99
<div align="center">
@@ -31,7 +31,9 @@ yarn add use-text-analyzer
3131

3232
- **Lightweight 🪶:** Less than 1KB in size, making it lightweight and efficient.
3333
- **TypeScript Support 🇹🇸:** Works seamlessly with both JavaScript and TypeScript projects.
34-
- **Efficient Algorithms ⚡:** Utilizes efficient algorithms for finding the most and least frequent words/characters.
34+
- **Advanced Reading Time Estimation 🕒:** Provides detailed reading time estimates in minutes and seconds, along with a human-readable format for immediate use in interfaces.
35+
- **Efficient Algorithms ⚡:** Utilizes efficient algorithms for finding the most and least frequent words/
36+
characters.
3537

3638
## Usage 📝
3739

@@ -60,14 +62,18 @@ function TextAnalyzerExample() {
6062
return (
6163
<div>
6264
<h2>Text Analysis Result</h2>
65+
<p>
66+
Estimated reading time: {readingTime.minutes}m {readingTime.seconds}s
67+
</p>
68+
<p>Total reading time in seconds: {readingTime.total}</p>
69+
<p>Human-readable reading time: {readingTime.text}</p>
70+
<p>
71+
Search frequency of '{searchTerm}': {searchFrequency}
72+
</p>
6373
<p>Word count: {wordCount}</p>
6474
<p>Character count: {charCount}</p>
6575
<p>Sentence count: {sentenceCount}</p>
6676
<p>Paragraph count: {paragraphCount}</p>
67-
<p>
68-
Search frequency of '{searchTerm}': {searchFrequency}
69-
</p>
70-
<p>Estimated reading time: {readingTime} seconds</p>
7177
<p>Most frequent word: {mostFrequentWord}</p>
7278
<p>Least frequent word: {leastFrequentWord}</p>
7379
<p>Most frequent character: {mostFrequentCharacter}</p>
@@ -87,22 +93,27 @@ A React hook that analyzes the given text and returns various statistics about i
8793

8894
#### Parameters
8995

90-
- `options` (required): An object containing options for text analysis.
96+
- `options` (`TextAnalyzerOptions`, required): An object containing options for text analysis.
9197
- `text` (string, required): The text to analyze.
9298
- `searchTerm` (string, optional): The term to search for in the text.
9399
- `ignoreCase` (boolean, optional, default: true): Whether to ignore case when searching for the term and calculating word and character frequencies.
94100
- `trimText` (boolean, optional, default: true): Whether to trim the text before analysis.
101+
- `wordsPerMinute` (number, optional, default: 250): Custom reading speed in words per minute.
95102

96103
#### Returns
97104

98-
An object containing various statistics about the text.
105+
A `TextAnalysisResult` object containing various statistics about the text.
99106

107+
- `readingTime` (object):
108+
- `minutes` (number): The total estimated reading time expressed in whole minutes.
109+
- `seconds` (number): Remaining seconds beyond the counted minutes.
110+
- `total` (number): The total estimated reading time expressed in total seconds.
111+
- `text` (string): A human-readable summary of the reading time.
112+
- `searchFrequency` (number): The frequency of the search term in the text.
100113
- `wordCount` (number): The number of words in the text.
101114
- `charCount` (number): The number of characters in the text.
102115
- `sentenceCount` (number): The number of sentences in the text.
103116
- `paragraphCount` (number): The number of paragraphs in the text.
104-
- `searchFrequency` (number): The frequency of the search term in the text.
105-
- `readingTime` (number): The estimated reading time of the text in seconds.
106117
- `mostFrequentWord` (string): The most frequent word in the text.
107118
- `leastFrequentWord` (string): The least frequent word in the text.
108119
- `mostFrequentCharacter` (string): The most frequent character in the text.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
"text-analysis",
4545
"word-frequency",
4646
"wordcount",
47+
"reading",
48+
"time",
4749
"reading-time"
4850
],
4951
"author": "invulner <[email protected]>",

src/constants/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1-
// Assuming average reading speed of 200 words per minute
2-
export const WORDS_PER_MINUTE = 200;
1+
// The default reading speed is set to 250 words per minute.
2+
// This rate is an average based on extensive research into reading habits.
3+
// https://www.sciencedirect.com/science/article/abs/pii/S0749596X19300786
4+
// Users can adjust this setting to match their reading speed or the specific
5+
// requirements of different text types.
6+
export const WORDS_PER_MINUTE = 250;

src/interfaces/index.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ export interface TextAnalyzerOptions {
2020
* @default true
2121
*/
2222
trimText?: boolean;
23+
/**
24+
* The number of words a person can read per minute.
25+
* @default 250
26+
*/
27+
wordsPerMinute?: number;
2328
}
2429

2530
/**
@@ -47,9 +52,26 @@ export interface TextAnalysisResult {
4752
*/
4853
searchFrequency: number;
4954
/**
50-
* The estimated reading time of the text in seconds.
55+
* The estimated reading time of the text, detailed in minutes and seconds.
5156
*/
52-
readingTime: number;
57+
readingTime: {
58+
/**
59+
* Estimated minutes to read the text.
60+
*/
61+
minutes: number;
62+
/**
63+
* Remaining seconds beyond counted minutes.
64+
*/
65+
seconds: number;
66+
/**
67+
* Total estimated reading time in seconds.
68+
*/
69+
total: number;
70+
/**
71+
* Human-readable summary of the reading time.
72+
*/
73+
text: string;
74+
};
5375
/**
5476
* The most frequent word in the text.
5577
*/

src/useTextAnalyzer.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useMemo } from 'react';
22

33
import { TextAnalysisResult, TextAnalyzerOptions } from './interfaces';
44
import { calculateStats } from './utils/calculateStats';
5+
import { WORDS_PER_MINUTE } from './constants';
56

67
/**
78
* Analyzes the given text and returns various statistics about it.
@@ -13,12 +14,18 @@ function useTextAnalyzer({
1314
searchTerm = '',
1415
ignoreCase = true,
1516
trimText = true,
17+
wordsPerMinute = WORDS_PER_MINUTE,
1618
}: TextAnalyzerOptions): TextAnalysisResult {
1719
const processedText = trimText ? text.trim() : text;
1820

1921
const analysisResult = useMemo(() => {
20-
return calculateStats(processedText, searchTerm, ignoreCase);
21-
}, [processedText, searchTerm, ignoreCase]);
22+
return calculateStats({
23+
text: processedText,
24+
searchTerm,
25+
ignoreCase,
26+
wordsPerMinute,
27+
});
28+
}, [processedText, searchTerm, ignoreCase, wordsPerMinute]);
2229

2330
return analysisResult;
2431
}

src/utils/calculateStats.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,25 @@ import { calculateCharFrequencies } from './calculateCharFrequencies';
88
import { calculateWordFrequencies } from './calculateWordFrequencies';
99
import { findMostAndLeastFrequent } from './findMostAndLeastFrequent';
1010

11-
import { TextAnalysisResult } from '../interfaces';
11+
import { TextAnalysisResult, TextAnalyzerOptions } from '../interfaces';
1212

1313
/**
14-
* Calculates text analysis statistics.
15-
* @param text - The text to analyze.
16-
* @param searchTerm - The term to search for.
17-
* @param ignoreCase - Whether to ignore case when searching for the term and calculating word and character frequencies.
18-
* @returns The text analysis statistics.
14+
* Analyzes the given text and returns various statistics about it.
15+
* @param {TextAnalyzerOptions} options - Options for text analysis.
16+
* @returns {TextAnalysisResult} An object containing various statistics about the text.
1917
*/
20-
export function calculateStats(text: string, searchTerm: string, ignoreCase: boolean): TextAnalysisResult {
18+
export function calculateStats({
19+
text,
20+
searchTerm,
21+
ignoreCase,
22+
wordsPerMinute,
23+
}: TextAnalyzerOptions): TextAnalysisResult {
2124
const wordCount = countWords(text);
2225
const charCount = countCharacters(text);
2326
const sentenceCount = countSentences(text);
2427
const paragraphCount = countParagraphs(text);
2528
const searchFrequency = countSearchFrequency(text, searchTerm, ignoreCase);
26-
const readingTime = estimateReadingTime(wordCount);
29+
const readingTime = estimateReadingTime(wordCount, wordsPerMinute);
2730
const wordsMap = calculateWordFrequencies(text, ignoreCase);
2831
const charsMap = calculateCharFrequencies(text, ignoreCase);
2932
const [mostFrequentWord, leastFrequentWord] = findMostAndLeastFrequent(wordsMap);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Formats the reading time into a human-readable string.
3+
* @param {number} minutes - The total number of minutes.
4+
* @returns {string} The formatted reading time as a human-readable string.
5+
*/
6+
export function formatReadingTimeText(minutes: number): string {
7+
if (minutes < 1) {
8+
return 'less than a minute read';
9+
}
10+
11+
return `${minutes} min read`;
12+
}

src/utils/estimateReadingTime.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,30 @@
1-
import { WORDS_PER_MINUTE } from '../constants';
1+
import { formatReadingTimeText } from './common/formatReadingTimeText';
22

33
/**
44
* Estimates the reading time of the text in seconds.
5-
* @param {number} wordCount - The number of words in the text.
5+
* @param wordCount - The number of words in the text.
6+
* @param wordsPerMinute - The number of words a person can read per minute (optional, default from constants).
67
* @returns {number} The estimated reading time of the text in seconds.
78
*/
8-
export function estimateReadingTime(wordCount: number): number {
9-
return Math.ceil(wordCount / (WORDS_PER_MINUTE / 60));
9+
export function estimateReadingTime(
10+
wordCount: number,
11+
wordsPerMinute: number,
12+
): {
13+
minutes: number;
14+
seconds: number;
15+
total: number;
16+
text: string;
17+
} {
18+
const totalMinutes = wordCount / wordsPerMinute;
19+
const roundedMinutes = Math.floor(totalMinutes);
20+
const seconds = Math.round((totalMinutes - roundedMinutes) * 60);
21+
const totalSeconds = Math.round(totalMinutes * 60);
22+
const readableText = formatReadingTimeText(roundedMinutes);
23+
24+
return {
25+
minutes: roundedMinutes,
26+
seconds,
27+
total: totalSeconds,
28+
text: readableText,
29+
};
1030
}

0 commit comments

Comments
 (0)