get-reading-time 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,13 +26,13 @@ A simple text analysis tool that provides insights into text such as reading tim
26
26
 
27
27
  To install the package from npm, run:
28
28
  ``` bash
29
- npm install text-analysis-tool
29
+ npm i get-reading-time
30
30
  ```
31
31
 
32
32
 
33
33
  Or using yarn:
34
34
  ```bash
35
- yarn add get-reading-time
35
+ yarn add get-reading-time
36
36
  ```
37
37
 
38
38
  ## Usage
@@ -0,0 +1,16 @@
1
+ interface TextAnalysisResult {
2
+ readingTime: {
3
+ minutes: number;
4
+ seconds: number;
5
+ };
6
+ wordCount: number;
7
+ characterCount: number;
8
+ sentenceCount: number;
9
+ linkCount: number;
10
+ readabilityScore: number;
11
+ sentiment: string;
12
+ keywords: string[];
13
+ }
14
+ declare function analyzeText(text: string, wordsPerMinute?: number): TextAnalysisResult;
15
+
16
+ export { analyzeText };
@@ -0,0 +1,16 @@
1
+ interface TextAnalysisResult {
2
+ readingTime: {
3
+ minutes: number;
4
+ seconds: number;
5
+ };
6
+ wordCount: number;
7
+ characterCount: number;
8
+ sentenceCount: number;
9
+ linkCount: number;
10
+ readabilityScore: number;
11
+ sentiment: string;
12
+ keywords: string[];
13
+ }
14
+ declare function analyzeText(text: string, wordsPerMinute?: number): TextAnalysisResult;
15
+
16
+ export { analyzeText };
package/dist/index.js ADDED
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ analyzeText: () => analyzeText
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+ var import_sentiment = __toESM(require("sentiment"));
37
+ var DEFAULT_READING_SPEED = 200;
38
+ function analyzeText(text, wordsPerMinute = DEFAULT_READING_SPEED) {
39
+ if (!text || typeof text !== "string") {
40
+ throw new Error("Invalid text input. Please provide a valid string.");
41
+ }
42
+ const cleanText = cleanTextInput(text);
43
+ const wordCount = calculateWordCount(cleanText);
44
+ const characterCount = calculateCharacterCount(cleanText);
45
+ const sentenceCount = calculateSentenceCount(cleanText);
46
+ const { minutes, seconds } = calculateReadingTime(wordCount, wordsPerMinute);
47
+ const linkCount = countLinks(cleanText);
48
+ const readabilityScore = calculateReadabilityScore(cleanText);
49
+ const sentiment = analyzeSentiment(cleanText);
50
+ const keywords = extractKeywords(cleanText);
51
+ return {
52
+ readingTime: { minutes, seconds },
53
+ wordCount,
54
+ characterCount,
55
+ sentenceCount,
56
+ linkCount,
57
+ readabilityScore,
58
+ sentiment,
59
+ keywords
60
+ };
61
+ }
62
+ function cleanTextInput(text) {
63
+ return text.replace(/\s+/g, " ").trim();
64
+ }
65
+ function calculateWordCount(text) {
66
+ return text.split(/\s+/).length;
67
+ }
68
+ function calculateCharacterCount(text) {
69
+ return text.replace(/\s+/g, "").length;
70
+ }
71
+ function calculateSentenceCount(text) {
72
+ return (text.match(/[.!?]+/g) || []).length;
73
+ }
74
+ function calculateReadingTime(wordCount, wordsPerMinute) {
75
+ if (wordCount === 0) return { minutes: 0, seconds: 0 };
76
+ const readingTimeInMinutes = wordCount / wordsPerMinute;
77
+ const minutes = readingTimeInMinutes.toFixed(2);
78
+ const seconds = ((readingTimeInMinutes - Math.floor(readingTimeInMinutes)) * 60).toFixed(2);
79
+ return { minutes: parseFloat(minutes), seconds: parseFloat(seconds) };
80
+ }
81
+ function countLinks(text) {
82
+ const linkRegex = /https?:\/\/[^\s]+/g;
83
+ const matches = text.match(linkRegex);
84
+ return matches ? matches.length : 0;
85
+ }
86
+ function calculateReadabilityScore(text) {
87
+ const wordCount = calculateWordCount(text);
88
+ const sentenceCount = calculateSentenceCount(text);
89
+ const syllableCount = calculateSyllableCount(text);
90
+ if (wordCount === 0 || sentenceCount === 0) return 0;
91
+ return 206.835 - 1.015 * (wordCount / sentenceCount) - 84.6 * (syllableCount / wordCount);
92
+ }
93
+ function calculateSyllableCount(text) {
94
+ return (text.match(/[aeiouy]{1,2}/g) || []).length;
95
+ }
96
+ function analyzeSentiment(text) {
97
+ const sentiment = new import_sentiment.default();
98
+ const result = sentiment.analyze(text);
99
+ return result.score > 0 ? "Positive" : result.score < 0 ? "Negative" : "Neutral";
100
+ }
101
+ function extractKeywords(text) {
102
+ const words = text.toLowerCase().split(/\s+/);
103
+ const wordFrequency = /* @__PURE__ */ new Map();
104
+ const stopWords = /* @__PURE__ */ new Set([
105
+ "the",
106
+ "and",
107
+ "a",
108
+ "to",
109
+ "of",
110
+ "in",
111
+ "on",
112
+ "for",
113
+ "with",
114
+ "at",
115
+ "by",
116
+ "an",
117
+ "this",
118
+ "that",
119
+ "it",
120
+ "is",
121
+ "was",
122
+ "for",
123
+ "as",
124
+ "be",
125
+ "are",
126
+ "which",
127
+ "or",
128
+ "but",
129
+ "not",
130
+ "from",
131
+ "have",
132
+ "has"
133
+ ]);
134
+ words.forEach((word) => {
135
+ if (!isStopWord(word, stopWords) && word.length > 2) {
136
+ wordFrequency.set(word, (wordFrequency.get(word) || 0) + 1);
137
+ }
138
+ });
139
+ const nGrams = extractNGrams(words);
140
+ nGrams.forEach((nGram) => {
141
+ if (!isStopWord(nGram, stopWords)) {
142
+ wordFrequency.set(nGram, (wordFrequency.get(nGram) || 0) + 1);
143
+ }
144
+ });
145
+ return Array.from(wordFrequency).sort(([, countA], [, countB]) => countB - countA).slice(0, 5).map(([key]) => key);
146
+ }
147
+ function extractNGrams(words) {
148
+ const nGrams = [];
149
+ for (let i = 0; i < words.length - 1; i++) {
150
+ nGrams.push(words[i] + " " + words[i + 1]);
151
+ if (i < words.length - 2) {
152
+ nGrams.push(words[i] + " " + words[i + 1] + " " + words[i + 2]);
153
+ }
154
+ }
155
+ return nGrams;
156
+ }
157
+ function isStopWord(word, stopWords) {
158
+ return stopWords.has(word);
159
+ }
160
+ // Annotate the CommonJS export names for ESM import in node:
161
+ 0 && (module.exports = {
162
+ analyzeText
163
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,128 @@
1
+ // src/index.ts
2
+ import Sentiment from "sentiment";
3
+ var DEFAULT_READING_SPEED = 200;
4
+ function analyzeText(text, wordsPerMinute = DEFAULT_READING_SPEED) {
5
+ if (!text || typeof text !== "string") {
6
+ throw new Error("Invalid text input. Please provide a valid string.");
7
+ }
8
+ const cleanText = cleanTextInput(text);
9
+ const wordCount = calculateWordCount(cleanText);
10
+ const characterCount = calculateCharacterCount(cleanText);
11
+ const sentenceCount = calculateSentenceCount(cleanText);
12
+ const { minutes, seconds } = calculateReadingTime(wordCount, wordsPerMinute);
13
+ const linkCount = countLinks(cleanText);
14
+ const readabilityScore = calculateReadabilityScore(cleanText);
15
+ const sentiment = analyzeSentiment(cleanText);
16
+ const keywords = extractKeywords(cleanText);
17
+ return {
18
+ readingTime: { minutes, seconds },
19
+ wordCount,
20
+ characterCount,
21
+ sentenceCount,
22
+ linkCount,
23
+ readabilityScore,
24
+ sentiment,
25
+ keywords
26
+ };
27
+ }
28
+ function cleanTextInput(text) {
29
+ return text.replace(/\s+/g, " ").trim();
30
+ }
31
+ function calculateWordCount(text) {
32
+ return text.split(/\s+/).length;
33
+ }
34
+ function calculateCharacterCount(text) {
35
+ return text.replace(/\s+/g, "").length;
36
+ }
37
+ function calculateSentenceCount(text) {
38
+ return (text.match(/[.!?]+/g) || []).length;
39
+ }
40
+ function calculateReadingTime(wordCount, wordsPerMinute) {
41
+ if (wordCount === 0) return { minutes: 0, seconds: 0 };
42
+ const readingTimeInMinutes = wordCount / wordsPerMinute;
43
+ const minutes = readingTimeInMinutes.toFixed(2);
44
+ const seconds = ((readingTimeInMinutes - Math.floor(readingTimeInMinutes)) * 60).toFixed(2);
45
+ return { minutes: parseFloat(minutes), seconds: parseFloat(seconds) };
46
+ }
47
+ function countLinks(text) {
48
+ const linkRegex = /https?:\/\/[^\s]+/g;
49
+ const matches = text.match(linkRegex);
50
+ return matches ? matches.length : 0;
51
+ }
52
+ function calculateReadabilityScore(text) {
53
+ const wordCount = calculateWordCount(text);
54
+ const sentenceCount = calculateSentenceCount(text);
55
+ const syllableCount = calculateSyllableCount(text);
56
+ if (wordCount === 0 || sentenceCount === 0) return 0;
57
+ return 206.835 - 1.015 * (wordCount / sentenceCount) - 84.6 * (syllableCount / wordCount);
58
+ }
59
+ function calculateSyllableCount(text) {
60
+ return (text.match(/[aeiouy]{1,2}/g) || []).length;
61
+ }
62
+ function analyzeSentiment(text) {
63
+ const sentiment = new Sentiment();
64
+ const result = sentiment.analyze(text);
65
+ return result.score > 0 ? "Positive" : result.score < 0 ? "Negative" : "Neutral";
66
+ }
67
+ function extractKeywords(text) {
68
+ const words = text.toLowerCase().split(/\s+/);
69
+ const wordFrequency = /* @__PURE__ */ new Map();
70
+ const stopWords = /* @__PURE__ */ new Set([
71
+ "the",
72
+ "and",
73
+ "a",
74
+ "to",
75
+ "of",
76
+ "in",
77
+ "on",
78
+ "for",
79
+ "with",
80
+ "at",
81
+ "by",
82
+ "an",
83
+ "this",
84
+ "that",
85
+ "it",
86
+ "is",
87
+ "was",
88
+ "for",
89
+ "as",
90
+ "be",
91
+ "are",
92
+ "which",
93
+ "or",
94
+ "but",
95
+ "not",
96
+ "from",
97
+ "have",
98
+ "has"
99
+ ]);
100
+ words.forEach((word) => {
101
+ if (!isStopWord(word, stopWords) && word.length > 2) {
102
+ wordFrequency.set(word, (wordFrequency.get(word) || 0) + 1);
103
+ }
104
+ });
105
+ const nGrams = extractNGrams(words);
106
+ nGrams.forEach((nGram) => {
107
+ if (!isStopWord(nGram, stopWords)) {
108
+ wordFrequency.set(nGram, (wordFrequency.get(nGram) || 0) + 1);
109
+ }
110
+ });
111
+ return Array.from(wordFrequency).sort(([, countA], [, countB]) => countB - countA).slice(0, 5).map(([key]) => key);
112
+ }
113
+ function extractNGrams(words) {
114
+ const nGrams = [];
115
+ for (let i = 0; i < words.length - 1; i++) {
116
+ nGrams.push(words[i] + " " + words[i + 1]);
117
+ if (i < words.length - 2) {
118
+ nGrams.push(words[i] + " " + words[i + 1] + " " + words[i + 2]);
119
+ }
120
+ }
121
+ return nGrams;
122
+ }
123
+ function isStopWord(word, stopWords) {
124
+ return stopWords.has(word);
125
+ }
126
+ export {
127
+ analyzeText
128
+ };
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "get-reading-time",
3
- "version": "1.0.0",
4
- "main": "index.js",
3
+ "version": "1.0.2",
4
+ "main": "/dist/index.js",
5
+ "module": "/dist/index.mjs",
6
+ "types": "/dist/index.d.ts",
5
7
  "scripts": {
6
- "build": "tsc",
8
+ "build": "tsup",
7
9
  "start": "node dist/test.js"
8
10
  },
9
11
  "repository": {
@@ -137,6 +139,7 @@
137
139
  "typescript": "^5.7.2"
138
140
  },
139
141
  "dependencies": {
140
- "sentiment": "^5.0.2"
142
+ "sentiment": "^5.0.2",
143
+ "tsup": "^8.3.5"
141
144
  }
142
145
  }
package/src/index.ts DELETED
@@ -1,163 +0,0 @@
1
- import Sentiment from "sentiment";
2
-
3
- // Constants
4
- const DEFAULT_READING_SPEED = 200; // Default reading speed (words per minute)
5
-
6
- // Type Definitions
7
- interface TextAnalysisResult {
8
- readingTime: { minutes: number; seconds: number };
9
- wordCount: number;
10
- characterCount: number;
11
- sentenceCount: number;
12
- linkCount: number;
13
- readabilityScore: number;
14
- sentiment: string;
15
- keywords: string[];
16
- }
17
-
18
- // Main Analysis Function
19
- export function analyzeText(
20
- text: string,
21
- wordsPerMinute: number = DEFAULT_READING_SPEED
22
- ): TextAnalysisResult {
23
- if (!text || typeof text !== "string") {
24
- throw new Error("Invalid text input. Please provide a valid string.");
25
- }
26
-
27
- // Clean the input text for further analysis
28
- const cleanText = cleanTextInput(text);
29
-
30
- // Perform analysis
31
- const wordCount = calculateWordCount(cleanText);
32
- const characterCount = calculateCharacterCount(cleanText);
33
- const sentenceCount = calculateSentenceCount(cleanText);
34
- const { minutes, seconds } = calculateReadingTime(wordCount, wordsPerMinute);
35
- const linkCount = countLinks(cleanText);
36
- const readabilityScore = calculateReadabilityScore(cleanText);
37
- const sentiment = analyzeSentiment(cleanText);
38
- const keywords = extractKeywords(cleanText);
39
-
40
- return {
41
- readingTime: { minutes, seconds },
42
- wordCount,
43
- characterCount,
44
- sentenceCount,
45
- linkCount,
46
- readabilityScore,
47
- sentiment,
48
- keywords
49
- };
50
- }
51
-
52
- // Clean the input text by removing extra spaces and special characters
53
- function cleanTextInput(text: string): string {
54
- return text.replace(/\s+/g, " ").trim();
55
- }
56
-
57
- // Calculate word count
58
- function calculateWordCount(text: string): number {
59
- return text.split(/\s+/).length;
60
- }
61
-
62
- // Calculate character count excluding spaces
63
- function calculateCharacterCount(text: string): number {
64
- return text.replace(/\s+/g, "").length;
65
- }
66
-
67
- // Calculate sentence count based on punctuation marks
68
- function calculateSentenceCount(text: string): number {
69
- return (text.match(/[.!?]+/g) || []).length;
70
- }
71
-
72
- // Calculate reading time in minutes and seconds
73
- function calculateReadingTime(wordCount: number, wordsPerMinute: number): { minutes: number; seconds: number } {
74
- if (wordCount === 0) return { minutes: 0, seconds: 0 }; // Avoid division by zero
75
-
76
- const readingTimeInMinutes = wordCount / wordsPerMinute;
77
- const minutes = readingTimeInMinutes.toFixed(2); // Convert to 2 decimal places
78
- const seconds = ((readingTimeInMinutes - Math.floor(readingTimeInMinutes)) * 60).toFixed(2); // Seconds as float with 2 decimal places
79
-
80
- return { minutes: parseFloat(minutes), seconds: parseFloat(seconds) };
81
- }
82
-
83
- // Count the number of links (URLs) in the text
84
- function countLinks(text: string): number {
85
- const linkRegex = /https?:\/\/[^\s]+/g;
86
- const matches = text.match(linkRegex);
87
- return matches ? matches.length : 0;
88
- }
89
-
90
- // Calculate readability score using Flesch Reading Ease formula
91
- function calculateReadabilityScore(text: string): number {
92
- const wordCount = calculateWordCount(text);
93
- const sentenceCount = calculateSentenceCount(text);
94
- const syllableCount = calculateSyllableCount(text);
95
-
96
- if (wordCount === 0 || sentenceCount === 0) return 0; // Avoid division by zero
97
-
98
- return 206.835 - 1.015 * (wordCount / sentenceCount) - 84.6 * (syllableCount / wordCount);
99
- }
100
-
101
- // Simple syllable count based on vowels (simplified version)
102
- function calculateSyllableCount(text: string): number {
103
- return (text.match(/[aeiouy]{1,2}/g) || []).length;
104
- }
105
-
106
- // Perform sentiment analysis using Sentiment.js
107
- function analyzeSentiment(text: string): string {
108
- const sentiment = new Sentiment();
109
- const result = sentiment.analyze(text);
110
- return result.score > 0 ? "Positive" : result.score < 0 ? "Negative" : "Neutral";
111
- }
112
-
113
- // Extract top 5 SEO-friendly keywords from the text
114
- function extractKeywords(text: string): string[] {
115
- const words = text.toLowerCase().split(/\s+/);
116
- const wordFrequency: Map<string, number> = new Map();
117
-
118
- // Use a Set for fast stop word lookup
119
- const stopWords = new Set([
120
- "the", "and", "a", "to", "of", "in", "on", "for", "with", "at", "by", "an", "this",
121
- "that", "it", "is", "was", "for", "as", "be", "are", "which", "or", "but", "not", "from", "have", "has"
122
- ]);
123
-
124
- // Count word frequency
125
- words.forEach((word) => {
126
- if (!isStopWord(word, stopWords) && word.length > 2) { // Only consider words longer than 2 characters
127
- wordFrequency.set(word, (wordFrequency.get(word) || 0) + 1);
128
- }
129
- });
130
-
131
- // Extract meaningful n-grams (bi-grams and tri-grams)
132
- const nGrams = extractNGrams(words);
133
- nGrams.forEach((nGram) => {
134
- if (!isStopWord(nGram, stopWords)) {
135
- wordFrequency.set(nGram, (wordFrequency.get(nGram) || 0) + 1);
136
- }
137
- });
138
-
139
- // Sort words and n-grams by frequency and return top 5
140
- return Array.from(wordFrequency)
141
- .sort(([, countA], [, countB]) => countB - countA)
142
- .slice(0, 5)
143
- .map(([key]) => key);
144
- }
145
-
146
- // Extract n-grams (bi-grams and tri-grams) from the list of words
147
- function extractNGrams(words: string[]): string[] {
148
- const nGrams: string[] = [];
149
-
150
- for (let i = 0; i < words.length - 1; i++) {
151
- nGrams.push(words[i] + " " + words[i + 1]); // Bi-grams
152
- if (i < words.length - 2) {
153
- nGrams.push(words[i] + " " + words[i + 1] + " " + words[i + 2]); // Tri-grams
154
- }
155
- }
156
-
157
- return nGrams;
158
- }
159
-
160
- // Check if a word is a common stop word (to exclude from keywords)
161
- function isStopWord(word: string, stopWords: Set<string>): boolean {
162
- return stopWords.has(word);
163
- }
package/src/test.ts DELETED
@@ -1,61 +0,0 @@
1
- import { analyzeText } from "./index";
2
-
3
- // Example text to analyze
4
- const exampleText = `
5
- How do I decide what to put in a paragraph?
6
- Before you can begin to determine what the composition of a particular paragraph will be, you must first decide on an argument and a working thesis statement for your paper. What is the most important idea that you are trying to convey to your reader? The information in each paragraph must be related to that idea. In other words, your paragraphs should remind your reader that there is a recurrent relationship between your thesis and the information in each paragraph. A working thesis functions like a seed from which your paper, and your ideas, will grow. The whole process is an organic one—a natural progression from a seed to a full-blown paper where there are direct, familial relationships between all of the ideas in the paper.
7
-
8
- The decision about what to put into your paragraphs begins with the germination of a seed of ideas; this “germination process” is better known as brainstorming. There are many techniques for brainstorming; whichever one you choose, this stage of paragraph development cannot be skipped. Building paragraphs can be like building a skyscraper: there must be a well-planned foundation that supports what you are building. Any cracks, inconsistencies, or other corruptions of the foundation can cause your whole paper to crumble.
9
-
10
- So, let’s suppose that you have done some brainstorming to develop your thesis. What else should you keep in mind as you begin to create paragraphs? Every paragraph in a paper should be:
11
-
12
- Unified: All of the sentences in a single paragraph should be related to a single controlling idea (often expressed in the topic sentence of the paragraph).
13
- Clearly related to the thesis: The sentences should all refer to the central idea, or thesis, of the paper (Rosen and Behrens 119).
14
- Coherent: The sentences should be arranged in a logical manner and should follow a definite plan for development (Rosen and Behrens 119).
15
- Well-developed: Every idea discussed in the paragraph should be adequately explained and supported through evidence and details that work together to explain the paragraph’s controlling idea (Rosen and Behrens 119).
16
- How do I organize a paragraph?
17
- There are many different ways to organize a paragraph. The organization you choose will depend on the controlling idea of the paragraph. Below are a few possibilities for organization, with links to brief examples:
18
-
19
- Narration: Tell a story. Go chronologically, from start to finish. (See an example.)
20
- Description: Provide specific details about what something looks, smells, tastes, sounds, or feels like. Organize spatially, in order of appearance, or by topic. (See an example.)
21
- Process: Explain how something works, step by step. Perhaps follow a sequence—first, second, third. (See an example.)
22
- Classification: Separate into groups or explain the various parts of a topic. (See an example.)
23
- Illustration: Give examples and explain how those examples support your point. (See an example in the 5-step process below.)
24
- Illustration paragraph: a 5-step example
25
- From the list above, let’s choose “illustration” as our rhetorical purpose. We’ll walk through a 5-step process for building a paragraph that illustrates a point in an argument. For each step there is an explanation and example. Our example paragraph will be about human misconceptions of piranhas.
26
-
27
- Step 1. Decide on a controlling idea and create a topic sentence
28
- Paragraph development begins with the formulation of the controlling idea. This idea directs the paragraph’s development. Often, the controlling idea of a paragraph will appear in the form of a topic sentence. In some cases, you may need more than one sentence to express a paragraph’s controlling idea.
29
-
30
- Controlling idea and topic sentence — Despite the fact that piranhas are relatively harmless, many people continue to believe the pervasive myth that piranhas are dangerous to humans.
31
-
32
- Step 2. Elaborate on the controlling idea
33
- Paragraph development continues with an elaboration on the controlling idea, perhaps with an explanation, implication, or statement about significance. Our example offers a possible explanation for the pervasiveness of the myth.
34
-
35
- Elaboration — This impression of piranhas is exacerbated by their mischaracterization in popular media.
36
-
37
- Step 3. Give an example (or multiple examples)
38
- Paragraph development progresses with an example (or more) that illustrates the claims made in the previous sentences.
39
-
40
- Example — For example, the promotional poster for the 1978 horror film Piranha features an oversized piranha poised to bite the leg of an unsuspecting woman.
41
-
42
- Step 4. Explain the example(s)
43
- The next movement in paragraph development is an explanation of each example and its relevance to the topic sentence. The explanation should demonstrate the value of the example as evidence to support the major claim, or focus, in your paragraph.
44
-
45
- Continue the pattern of giving examples and explaining them until all points/examples that the writer deems necessary have been made and explained. NONE of your examples should be left unexplained. You might be able to explain the relationship between the example and the topic sentence in the same sentence which introduced the example. More often, however, you will need to explain that relationship in a separate sentence.`;
46
-
47
- // Analyze the text
48
- try {
49
- const analysis = analyzeText(exampleText);
50
-
51
- // Output the analysis results
52
- console.log("Text Analysis Result:");
53
- console.log(JSON.stringify(analysis, null, 2));
54
- } catch (error) {
55
- // Narrow the type of error to Error
56
- if (error instanceof Error) {
57
- console.error("Error analyzing text:", error.message);
58
- } else {
59
- console.error("Unknown error:", error);
60
- }
61
- }
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES6",
4
- "module": "CommonJS",
5
- "outDir": "dist",
6
- "strict": true,
7
- "esModuleInterop": true
8
- },
9
- "include": ["src/**/*.ts"],
10
- "exclude": ["node_modules"]
11
- }
12
-