get-reading-time 1.2.7 → 1.3.0
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 +142 -38
- package/dist/index.d.mts +124 -12
- package/dist/index.d.ts +124 -12
- package/dist/index.js +155 -64
- package/dist/index.mjs +152 -63
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
|
|
2
|
+
Here’s the updated README with the added **Markdown Table Converter** and **langTrans (Language Translation)** features:
|
|
3
|
+
|
|
4
|
+
|
|
2
5
|
# Text Analysis Tool
|
|
3
6
|
|
|
4
|
-
A simple text analysis tool that provides insights into text such as reading time, word count, sentiment, readability score, link count,
|
|
7
|
+
A simple text analysis tool that provides insights into text such as reading time, word count, sentiment, readability score, link count, SEO-friendly keywords, Markdown table conversion, and language translation.
|
|
5
8
|
|
|
6
9
|
## Features
|
|
7
10
|
|
|
@@ -13,8 +16,11 @@ A simple text analysis tool that provides insights into text such as reading tim
|
|
|
13
16
|
- **Readability Score**: Calculates the Flesch Reading Ease score to evaluate the text's readability.
|
|
14
17
|
- **Sentiment Analysis**: Analyzes the sentiment of the text (Positive, Negative, or Neutral).
|
|
15
18
|
- **SEO-friendly Keywords**: Extracts the top 5 SEO-friendly keywords or key phrases (bi-grams and tri-grams) from the text.
|
|
16
|
-
-
|
|
17
|
-
|
|
19
|
+
- **aiTexGen**: Allows users to generate content based on a search prompt using the Cohere AI API, with a specified word count.
|
|
20
|
+
|
|
21
|
+
- **Automatic Punctuation and Capitalization**: Automatically adds proper punctuation and capitalizes the beginning of sentences in a provided text.
|
|
22
|
+
- **Markdown Table Converter**: Converts tabular data from a string or text format into a structured markdown table.
|
|
23
|
+
- **langTrans (Language Translation)**: Translates text into any supported language.
|
|
18
24
|
|
|
19
25
|
## Installation
|
|
20
26
|
|
|
@@ -22,20 +28,24 @@ To install the package from npm, run:
|
|
|
22
28
|
|
|
23
29
|
```bash
|
|
24
30
|
npm i get-reading-time
|
|
31
|
+
|
|
25
32
|
```
|
|
26
33
|
|
|
27
34
|
Or using yarn:
|
|
28
35
|
|
|
29
36
|
```bash
|
|
30
37
|
yarn add get-reading-time
|
|
38
|
+
|
|
31
39
|
```
|
|
32
40
|
|
|
33
41
|
## Usage
|
|
42
|
+
### Text Analyze
|
|
34
43
|
|
|
35
44
|
Here’s how you can use the analyzeText function to analyze a piece of text:
|
|
36
45
|
|
|
37
46
|
```bash
|
|
38
47
|
import { analyzeText } from "get-reading-time/dist/index.js";
|
|
48
|
+
|
|
39
49
|
```
|
|
40
50
|
|
|
41
51
|
### Example Code
|
|
@@ -60,6 +70,7 @@ try {
|
|
|
60
70
|
console.error("Unknown error:", error);
|
|
61
71
|
}
|
|
62
72
|
}
|
|
73
|
+
|
|
63
74
|
```
|
|
64
75
|
|
|
65
76
|
### Example Output
|
|
@@ -82,32 +93,111 @@ try {
|
|
|
82
93
|
"sentiment": "Neutral",
|
|
83
94
|
"keywords": ["example", "text.", "contains", "words,", "sentences,"]
|
|
84
95
|
}
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Markdown Table Converter
|
|
100
|
+
|
|
101
|
+
This feature allows you to convert plain text content into a well-formatted markdown table.
|
|
102
|
+
|
|
103
|
+
### Example Code
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
import { tableMaker } from "get-reading-time/dist/index.js";
|
|
107
|
+
|
|
108
|
+
const content = `Fazle Rabbi Khadem Senior Brand Executive at Meghna Group of Industries rabbi@example.com
|
|
109
|
+
Abu Obaida Imon Brand Manager at Partex Star Group imon@example.com`;
|
|
110
|
+
|
|
111
|
+
async function TableConversion() {
|
|
112
|
+
try {
|
|
113
|
+
const result = await tableMaker(content);
|
|
114
|
+
console.log("Converted Markdown Table:");
|
|
115
|
+
console.log(result);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error("Error during table conversion:", error);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
TableConversion();
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Example Output
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
| Name | Position | Email |
|
|
129
|
+
|---------------------|-----------------------------------------------|---------------------|
|
|
130
|
+
| Fazle Rabbi Khadem | Senior Brand Executive at Meghna Group | rabbi@example.com |
|
|
131
|
+
| Abu Obaida Imon | Brand Manager at Partex Star Group | imon@example.com |
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### langTrans: Language Translation
|
|
136
|
+
|
|
137
|
+
This feature allows you to translate any text into different languages. Simply provide the target language, and the tool will return the translated content.
|
|
138
|
+
|
|
139
|
+
### Example Code
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
import { langTrans } from 'get-reading-time/dist/index.js';
|
|
143
|
+
|
|
144
|
+
const text = 'Hello, how are you?';
|
|
145
|
+
const targetLanguage = 'es'; // 'es' for Spanish. Full Name is also welcome
|
|
146
|
+
|
|
147
|
+
async function translateText() {
|
|
148
|
+
try {
|
|
149
|
+
const translated = await langTrans(text, targetLanguage);
|
|
150
|
+
console.log("Translated Text:");
|
|
151
|
+
console.log(translated);
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error("Error during translation:", error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
translateText();
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Example Output
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"original": "Hello, how are you?",
|
|
166
|
+
"translated": "Hola, ¿cómo estás?"
|
|
167
|
+
}
|
|
168
|
+
|
|
85
169
|
```
|
|
86
170
|
|
|
87
171
|
### aiTexGen: Generate your content
|
|
172
|
+
|
|
88
173
|
This new feature allows users to generate content using Cohere AI. You provide your Cohere API key, a search prompt, and a word count, and it will return the generated content.
|
|
89
174
|
|
|
90
175
|
### Usage
|
|
176
|
+
|
|
91
177
|
To use the **aiTexGen** feature, follow these steps:
|
|
178
|
+
|
|
92
179
|
```bash
|
|
93
180
|
import { aiTexGen } from "get-reading-time/dist/index.js";
|
|
181
|
+
|
|
94
182
|
```
|
|
95
183
|
|
|
96
184
|
### Example Code
|
|
97
|
-
|
|
185
|
+
|
|
98
186
|
```javascript
|
|
187
|
+
import { aiTexGen } from '../dist/index.js';
|
|
188
|
+
|
|
99
189
|
// Replace this with your Cohere API key
|
|
100
|
-
const
|
|
101
|
-
const generator = new aiTexGen(apiKey);
|
|
190
|
+
const generator = new aiTexGen();
|
|
102
191
|
|
|
103
|
-
async function
|
|
192
|
+
async function GenerateContent() {
|
|
104
193
|
try {
|
|
105
194
|
// Define a topic and word count for testing
|
|
106
|
-
const topic = '
|
|
195
|
+
const topic = 'Arduino';
|
|
107
196
|
const wordCount = 100;
|
|
108
197
|
|
|
109
198
|
// Call the generateContent method
|
|
110
|
-
const result = await generator.generateContent(topic, wordCount);
|
|
199
|
+
const result = await generator.generateContent(topic, wordCount, false);
|
|
200
|
+
//TODO: True is for **Markdown Formate**
|
|
111
201
|
|
|
112
202
|
// Output the result in JSON format
|
|
113
203
|
console.log('Generated Content (JSON Format):');
|
|
@@ -118,14 +208,18 @@ async function testGenerateContent() {
|
|
|
118
208
|
}
|
|
119
209
|
}
|
|
120
210
|
// Run the test
|
|
121
|
-
|
|
211
|
+
GenerateContent();
|
|
212
|
+
|
|
122
213
|
```
|
|
214
|
+
|
|
123
215
|
### Example Output
|
|
216
|
+
|
|
124
217
|
```json
|
|
125
218
|
{
|
|
126
219
|
"topic": "arduino",
|
|
127
220
|
"content": "Arduino is an open-source electronics platform based on easy-to-use hardware and software. It's designed to make interactive projects accessible to everyone, from artists and designers to hobbyists and engineers. \n\nAt the heart of the Arduino platform is the Arduino board, a simple microcontroller board that can read inputs and turn them into outputs, such as turning on an LED light or activating a motor. \n\nWhat makes Arduino unique is its user-friendly approach, with a simplified programming language and easy-to-use hardware, making it a popular choice for beginners and professionals alike. With its versatility and robust community support, Arduino has become a go-to platform for creating interactive, sensor-based projects and prototypes."
|
|
128
221
|
}
|
|
222
|
+
|
|
129
223
|
```
|
|
130
224
|
|
|
131
225
|
### Automatic Punctuation and Capitalization
|
|
@@ -133,18 +227,24 @@ testGenerateContent();
|
|
|
133
227
|
You can now pass an article to the `analyzeText` function, and it will automatically fix punctuation and capitalize the first letter of sentences. This feature helps to improve the readability of raw text.
|
|
134
228
|
|
|
135
229
|
#### Example Code
|
|
136
|
-
|
|
230
|
+
|
|
231
|
+
Import the package and follow the steps:
|
|
232
|
+
|
|
137
233
|
```javascript
|
|
138
234
|
import { getPunch } from 'get-reading-time/dist/index.js';
|
|
235
|
+
|
|
139
236
|
```
|
|
140
237
|
|
|
141
238
|
```javascript
|
|
142
239
|
// Example to test with a string
|
|
240
|
+
import { getPunch } from '../dist/index.js';
|
|
241
|
+
// Example to test with a string
|
|
143
242
|
const content = "once a lion a fox and a wolf went hunting they ultimately spotted a stag and killed him for their food while sharing the hunt quarter me this stag roared the lion and other animals skinned and cut the spoil into four equal parts";
|
|
144
243
|
async function GetPunch() {
|
|
145
244
|
try {
|
|
146
245
|
// Call the getPunch function with content
|
|
147
|
-
const result = await getPunch(content);
|
|
246
|
+
const result = await getPunch(content, true);
|
|
247
|
+
// TODO: true is for markdown | False is Default
|
|
148
248
|
|
|
149
249
|
// Check the result and log it as a formatted JSON response
|
|
150
250
|
if (result.status_code === 200) {
|
|
@@ -159,20 +259,23 @@ async function GetPunch() {
|
|
|
159
259
|
}
|
|
160
260
|
// Run the test
|
|
161
261
|
GetPunch();
|
|
262
|
+
|
|
162
263
|
```
|
|
163
264
|
|
|
164
265
|
### Example Output
|
|
266
|
+
|
|
165
267
|
```json
|
|
166
268
|
{
|
|
167
269
|
"content": "Once a Lion, a Fox and a Wolf went hunting, they ultimately found a stag and killed him for their food while sharing the hunt quarter me. This stag roared the Lion and other animals skinned and cut the spoil into four equal parts.",
|
|
168
270
|
"status_code": 200
|
|
169
271
|
}
|
|
272
|
+
|
|
170
273
|
```
|
|
274
|
+
|
|
171
275
|
## Parameters
|
|
172
276
|
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
- **apiKey**: Your Cohere API key to use this feature (required).
|
|
277
|
+
- text: The text to be analyzed (required).
|
|
278
|
+
- wordsPerMinute: The reading speed in words per minute (optional, default is 200 words per minute).
|
|
176
279
|
|
|
177
280
|
## Functions
|
|
178
281
|
|
|
@@ -180,31 +283,33 @@ GetPunch();
|
|
|
180
283
|
|
|
181
284
|
Analyzes the provided text and returns an object containing:
|
|
182
285
|
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
-
|
|
186
|
-
-
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
-
|
|
190
|
-
-
|
|
286
|
+
- readingTime: Estimated reading time in minutes and seconds.
|
|
287
|
+
- wordCount: Total word count.
|
|
288
|
+
- characterCount: Total character count (excluding spaces).
|
|
289
|
+
- sentenceCount: Total sentence count.
|
|
290
|
+
- linkCount: Number of links (URLs) in the text.
|
|
291
|
+
- readabilityScore: Flesch Reading Ease score (higher is easier to read).
|
|
292
|
+
- sentiment: Sentiment of the text (Positive, Negative, or Neutral).
|
|
293
|
+
- keywords: Top 5 SEO-friendly keywords or key phrases.
|
|
294
|
+
|
|
191
295
|
### Generate Content(topic: string, wordCount: number)
|
|
296
|
+
|
|
192
297
|
Generates content based on the given topic and word count using the Cohere AI API and returns the generated content.
|
|
193
298
|
|
|
194
299
|
### Helper Functions
|
|
195
300
|
|
|
196
|
-
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
200
|
-
-
|
|
201
|
-
-
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
-
|
|
205
|
-
-
|
|
206
|
-
-
|
|
207
|
-
-
|
|
301
|
+
- **cleanTextInput(text: string)**: Cleans and normalizes the input text.
|
|
302
|
+
- **calculateWordCount(text: string)**: Counts the number of words.
|
|
303
|
+
- **calculateCharacterCount(text: string)**: Counts the number of characters (excluding spaces).
|
|
304
|
+
- **calculateSentenceCount(text: string)**: Counts the number of sentences based on punctuation.
|
|
305
|
+
- **countLinks(text: string)**: Counts the number of links (URLs) in the text.
|
|
306
|
+
- **calculateReadabilityScore(text: string)**: Calculates the Flesch Reading Ease score.
|
|
307
|
+
- **analyzeSentiment(text: string)**: Analyzes sentiment using Sentiment.js.
|
|
308
|
+
- **extractKeywords(text: string)**: Extracts the top 5 SEO-friendly keywords or key phrases.
|
|
309
|
+
- **extractNGrams(words: string[])**: Extracts bi-grams and tri-grams from the list of words.
|
|
310
|
+
- **isStopWord(word: string, stopWords: Set)**: Checks if a word is a stop word to exclude from keyword extraction.
|
|
311
|
+
- **generateContent(words: string[])**: Generates text based on the query and word limit.
|
|
312
|
+
- **autoPunctuateAndCapitalize(text: string)**: Adds punctuation and capitalization to the content.
|
|
208
313
|
|
|
209
314
|
## Contributing
|
|
210
315
|
|
|
@@ -212,9 +317,8 @@ Feel free to fork the repository, make your changes, and submit a pull request.
|
|
|
212
317
|
|
|
213
318
|
## License
|
|
214
319
|
|
|
215
|
-
This project is licensed under the MIT License - see the [LICENSE](https://github.com/nurahmed123/get-reading-time/blob/main/LICENSE) file for details.
|
|
216
|
-
[](https://www.npmjs.com/get-reading-time)
|
|
320
|
+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/nurahmed123/get-reading-time/blob/main/LICENSE) file for details. [](https://www.npmjs.com/get-reading-time)
|
|
217
321
|
|
|
218
322
|
## Contact
|
|
219
323
|
|
|
220
|
-
For
|
|
324
|
+
For issues or suggestions, please open an issue or contact me directly via my [LinkedIn](https://www.linkedin.com/in/06nurahmed) or [GitHub](https://github.com/nurahmed123).
|
package/dist/index.d.mts
CHANGED
|
@@ -1,39 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the result of the text analysis.
|
|
3
|
+
*/
|
|
1
4
|
interface TextAnalysisResult {
|
|
5
|
+
/** Estimated reading time (minutes and seconds) */
|
|
2
6
|
readingTime: {
|
|
3
7
|
minutes: number;
|
|
4
8
|
seconds: number;
|
|
5
9
|
};
|
|
10
|
+
/** Total word count */
|
|
6
11
|
wordCount: number;
|
|
12
|
+
/** Total character count (excluding spaces) */
|
|
7
13
|
characterCount: number;
|
|
14
|
+
/** Total sentence count */
|
|
8
15
|
sentenceCount: number;
|
|
16
|
+
/** Total number of links found */
|
|
9
17
|
linkCount: number;
|
|
18
|
+
/** Array of detected links */
|
|
10
19
|
links: string[];
|
|
20
|
+
/** Flesch Reading Ease score */
|
|
11
21
|
readabilityScore: number;
|
|
22
|
+
/** Overall sentiment ("Positive", "Negative", or "Neutral") */
|
|
12
23
|
sentiment: string;
|
|
24
|
+
/** Top 5 SEO-friendly keywords or key phrases */
|
|
13
25
|
keywords: string[];
|
|
14
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Analyzes the given text and returns various metrics, including reading time, word count,
|
|
29
|
+
* character count, sentence count, link count, readability score, sentiment, and keywords.
|
|
30
|
+
*
|
|
31
|
+
* @param text - The text to be analyzed.
|
|
32
|
+
* @param wordsPerMinute - The reading speed (optional, defaults to DEFAULT_READING_SPEED).
|
|
33
|
+
* @returns A TextAnalysisResult object with detailed analysis metrics.
|
|
34
|
+
*
|
|
35
|
+
* @throws {Error} Throws an error if the input text is not a valid string.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const text = "This is an example text with a link: https://example.com";
|
|
40
|
+
* const result = analyzeText(text);
|
|
41
|
+
* console.log(result.readingTime); // { minutes: 0.05, seconds: 3.00 }
|
|
42
|
+
* console.log(result.wordCount); // 10
|
|
43
|
+
* console.log(result.links); // ["https://example.com"]
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
15
46
|
declare function analyzeText(text: string, wordsPerMinute?: number): TextAnalysisResult;
|
|
16
47
|
|
|
17
|
-
type ApiResponse = {
|
|
18
|
-
|
|
48
|
+
type ApiResponse$2 = {
|
|
49
|
+
/** The corrected text output */
|
|
50
|
+
content?: string;
|
|
51
|
+
/** Error message if the request fails */
|
|
19
52
|
error?: string;
|
|
53
|
+
/** HTTP Status Code (200 = Success, 500 = Error) */
|
|
20
54
|
status_code: number;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* ✨ Fixes capitalization and punctuation in a given text.
|
|
58
|
+
*
|
|
59
|
+
* @param text - The text that needs correction.
|
|
60
|
+
* @returns A Promise resolving to an object with the corrected text or an error message.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const result = await getPunch("hELLo, HOW Are YOU?");
|
|
65
|
+
* console.log(result.content); // "Hello, how are you?"
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
declare function getPunch(text: string): Promise<ApiResponse$2>;
|
|
69
|
+
|
|
70
|
+
type SupportedLanguages = "English" | "Spanish" | "French" | "German" | "Finnish" | "Chinese" | "Japanese" | "Arabic" | "Russian" | "Hindi" | "Bengali" | "Portuguese" | "Korean" | "Italian" | "Dutch" | "Turkish" | "Polish" | "Swedish" | "Thai" | "Greek" | "Hebrew" | "Vietnamese" | "Indonesian" | "Filipino" | "Romanian" | "Czech" | "Hungarian" | "Danish" | "Norwegian" | "Ukrainian" | "Malay" | "Urdu" | "Persian (Farsi)" | "Tamil" | "Telugu" | "Marathi" | "Gujarati" | "Punjabi" | "Swahili" | "Hausa" | "Yoruba" | "Zulu" | "Burmese" | "Khmer" | "Lao";
|
|
71
|
+
type ApiResponse$1 = {
|
|
72
|
+
/** The translated content */
|
|
21
73
|
content?: string;
|
|
74
|
+
/** Error message, if any */
|
|
75
|
+
error?: string;
|
|
76
|
+
/** Status code: 200 (success) or 500 (error) */
|
|
77
|
+
status_code: number;
|
|
22
78
|
};
|
|
23
|
-
|
|
79
|
+
/**
|
|
80
|
+
* 🌎 Translates a given text into a specified language.
|
|
81
|
+
*
|
|
82
|
+
* @param content - The text you want to translate.
|
|
83
|
+
* @param language - The target language for translation. Use one of the supported languages.
|
|
84
|
+
* @returns A Promise resolving to an object with the translated text or an error message.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const result = await langTrans("Hello, world!", "French");
|
|
89
|
+
* console.log(result.content); // "Bonjour, monde!"
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
declare function langTrans(content: string, language: SupportedLanguages): Promise<ApiResponse$1>;
|
|
24
93
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Represents the final response returned by the tableMaker function.
|
|
96
|
+
*/
|
|
97
|
+
interface ApiResponse {
|
|
98
|
+
/** The well-formatted Markdown table */
|
|
99
|
+
content?: string;
|
|
100
|
+
/** Error message if the request fails */
|
|
101
|
+
error?: string;
|
|
102
|
+
/** HTTP Status Code (200 = Success, 500 = Error) */
|
|
103
|
+
status_code: number;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Converts raw text data into a well-formatted Markdown table.
|
|
107
|
+
*
|
|
108
|
+
* This function sends the provided text to an AI service, which converts it into a
|
|
109
|
+
* clean, aligned Markdown table. The response is then post-processed to ensure that
|
|
110
|
+
* each column is uniformly spaced.
|
|
111
|
+
*
|
|
112
|
+
* @param content - The raw text data to be converted into a Markdown table.
|
|
113
|
+
* @returns A Promise that resolves to an object containing the formatted Markdown table or an error message.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const rawData = `This is bob and his age is 25 and lives in Los Angeles. Moreover, Alice lives in New York and her age is 30.`;
|
|
118
|
+
* const result = await tableMaker(rawData);
|
|
119
|
+
* console.log(result.content);
|
|
120
|
+
* // Expected output:
|
|
121
|
+
* // | Name | Age | City |
|
|
122
|
+
* // |-------|-----|-------------|
|
|
123
|
+
* // | Alice | 30 | New York |
|
|
124
|
+
* // | Bob | 25 | Los Angeles |
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
declare function tableMaker(content: string): Promise<ApiResponse>;
|
|
128
|
+
|
|
129
|
+
interface GenerateResponse {
|
|
130
|
+
topic: string;
|
|
131
|
+
content: string;
|
|
132
|
+
}
|
|
133
|
+
declare class aiTexGen {
|
|
134
|
+
private apiUrl;
|
|
135
|
+
constructor();
|
|
28
136
|
private validateInputs;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Generates content based on the topic and word count.
|
|
139
|
+
*
|
|
140
|
+
* @param topic The topic for the article (e.g., "Artificial Intelligence").
|
|
141
|
+
* @param wordCount The maximum number of words for the article (default is 100).
|
|
142
|
+
* @param markdown If true, returns the content in Markdown format (default is false).
|
|
143
|
+
* @returns A promise that resolves with the topic and generated content.
|
|
144
|
+
*/
|
|
145
|
+
generateContent(topic: string, wordCount?: number, markdown?: boolean): Promise<GenerateResponse>;
|
|
33
146
|
private processContent;
|
|
34
|
-
private extractTextFromObject;
|
|
35
147
|
private createErrorResponse;
|
|
36
148
|
private formatErrorDetails;
|
|
37
149
|
}
|
|
38
150
|
|
|
39
|
-
export {
|
|
151
|
+
export { aiTexGen, analyzeText, getPunch, langTrans, tableMaker };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,39 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the result of the text analysis.
|
|
3
|
+
*/
|
|
1
4
|
interface TextAnalysisResult {
|
|
5
|
+
/** Estimated reading time (minutes and seconds) */
|
|
2
6
|
readingTime: {
|
|
3
7
|
minutes: number;
|
|
4
8
|
seconds: number;
|
|
5
9
|
};
|
|
10
|
+
/** Total word count */
|
|
6
11
|
wordCount: number;
|
|
12
|
+
/** Total character count (excluding spaces) */
|
|
7
13
|
characterCount: number;
|
|
14
|
+
/** Total sentence count */
|
|
8
15
|
sentenceCount: number;
|
|
16
|
+
/** Total number of links found */
|
|
9
17
|
linkCount: number;
|
|
18
|
+
/** Array of detected links */
|
|
10
19
|
links: string[];
|
|
20
|
+
/** Flesch Reading Ease score */
|
|
11
21
|
readabilityScore: number;
|
|
22
|
+
/** Overall sentiment ("Positive", "Negative", or "Neutral") */
|
|
12
23
|
sentiment: string;
|
|
24
|
+
/** Top 5 SEO-friendly keywords or key phrases */
|
|
13
25
|
keywords: string[];
|
|
14
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Analyzes the given text and returns various metrics, including reading time, word count,
|
|
29
|
+
* character count, sentence count, link count, readability score, sentiment, and keywords.
|
|
30
|
+
*
|
|
31
|
+
* @param text - The text to be analyzed.
|
|
32
|
+
* @param wordsPerMinute - The reading speed (optional, defaults to DEFAULT_READING_SPEED).
|
|
33
|
+
* @returns A TextAnalysisResult object with detailed analysis metrics.
|
|
34
|
+
*
|
|
35
|
+
* @throws {Error} Throws an error if the input text is not a valid string.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const text = "This is an example text with a link: https://example.com";
|
|
40
|
+
* const result = analyzeText(text);
|
|
41
|
+
* console.log(result.readingTime); // { minutes: 0.05, seconds: 3.00 }
|
|
42
|
+
* console.log(result.wordCount); // 10
|
|
43
|
+
* console.log(result.links); // ["https://example.com"]
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
15
46
|
declare function analyzeText(text: string, wordsPerMinute?: number): TextAnalysisResult;
|
|
16
47
|
|
|
17
|
-
type ApiResponse = {
|
|
18
|
-
|
|
48
|
+
type ApiResponse$2 = {
|
|
49
|
+
/** The corrected text output */
|
|
50
|
+
content?: string;
|
|
51
|
+
/** Error message if the request fails */
|
|
19
52
|
error?: string;
|
|
53
|
+
/** HTTP Status Code (200 = Success, 500 = Error) */
|
|
20
54
|
status_code: number;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* ✨ Fixes capitalization and punctuation in a given text.
|
|
58
|
+
*
|
|
59
|
+
* @param text - The text that needs correction.
|
|
60
|
+
* @returns A Promise resolving to an object with the corrected text or an error message.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const result = await getPunch("hELLo, HOW Are YOU?");
|
|
65
|
+
* console.log(result.content); // "Hello, how are you?"
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
declare function getPunch(text: string): Promise<ApiResponse$2>;
|
|
69
|
+
|
|
70
|
+
type SupportedLanguages = "English" | "Spanish" | "French" | "German" | "Finnish" | "Chinese" | "Japanese" | "Arabic" | "Russian" | "Hindi" | "Bengali" | "Portuguese" | "Korean" | "Italian" | "Dutch" | "Turkish" | "Polish" | "Swedish" | "Thai" | "Greek" | "Hebrew" | "Vietnamese" | "Indonesian" | "Filipino" | "Romanian" | "Czech" | "Hungarian" | "Danish" | "Norwegian" | "Ukrainian" | "Malay" | "Urdu" | "Persian (Farsi)" | "Tamil" | "Telugu" | "Marathi" | "Gujarati" | "Punjabi" | "Swahili" | "Hausa" | "Yoruba" | "Zulu" | "Burmese" | "Khmer" | "Lao";
|
|
71
|
+
type ApiResponse$1 = {
|
|
72
|
+
/** The translated content */
|
|
21
73
|
content?: string;
|
|
74
|
+
/** Error message, if any */
|
|
75
|
+
error?: string;
|
|
76
|
+
/** Status code: 200 (success) or 500 (error) */
|
|
77
|
+
status_code: number;
|
|
22
78
|
};
|
|
23
|
-
|
|
79
|
+
/**
|
|
80
|
+
* 🌎 Translates a given text into a specified language.
|
|
81
|
+
*
|
|
82
|
+
* @param content - The text you want to translate.
|
|
83
|
+
* @param language - The target language for translation. Use one of the supported languages.
|
|
84
|
+
* @returns A Promise resolving to an object with the translated text or an error message.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const result = await langTrans("Hello, world!", "French");
|
|
89
|
+
* console.log(result.content); // "Bonjour, monde!"
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
declare function langTrans(content: string, language: SupportedLanguages): Promise<ApiResponse$1>;
|
|
24
93
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Represents the final response returned by the tableMaker function.
|
|
96
|
+
*/
|
|
97
|
+
interface ApiResponse {
|
|
98
|
+
/** The well-formatted Markdown table */
|
|
99
|
+
content?: string;
|
|
100
|
+
/** Error message if the request fails */
|
|
101
|
+
error?: string;
|
|
102
|
+
/** HTTP Status Code (200 = Success, 500 = Error) */
|
|
103
|
+
status_code: number;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Converts raw text data into a well-formatted Markdown table.
|
|
107
|
+
*
|
|
108
|
+
* This function sends the provided text to an AI service, which converts it into a
|
|
109
|
+
* clean, aligned Markdown table. The response is then post-processed to ensure that
|
|
110
|
+
* each column is uniformly spaced.
|
|
111
|
+
*
|
|
112
|
+
* @param content - The raw text data to be converted into a Markdown table.
|
|
113
|
+
* @returns A Promise that resolves to an object containing the formatted Markdown table or an error message.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const rawData = `This is bob and his age is 25 and lives in Los Angeles. Moreover, Alice lives in New York and her age is 30.`;
|
|
118
|
+
* const result = await tableMaker(rawData);
|
|
119
|
+
* console.log(result.content);
|
|
120
|
+
* // Expected output:
|
|
121
|
+
* // | Name | Age | City |
|
|
122
|
+
* // |-------|-----|-------------|
|
|
123
|
+
* // | Alice | 30 | New York |
|
|
124
|
+
* // | Bob | 25 | Los Angeles |
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
declare function tableMaker(content: string): Promise<ApiResponse>;
|
|
128
|
+
|
|
129
|
+
interface GenerateResponse {
|
|
130
|
+
topic: string;
|
|
131
|
+
content: string;
|
|
132
|
+
}
|
|
133
|
+
declare class aiTexGen {
|
|
134
|
+
private apiUrl;
|
|
135
|
+
constructor();
|
|
28
136
|
private validateInputs;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Generates content based on the topic and word count.
|
|
139
|
+
*
|
|
140
|
+
* @param topic The topic for the article (e.g., "Artificial Intelligence").
|
|
141
|
+
* @param wordCount The maximum number of words for the article (default is 100).
|
|
142
|
+
* @param markdown If true, returns the content in Markdown format (default is false).
|
|
143
|
+
* @returns A promise that resolves with the topic and generated content.
|
|
144
|
+
*/
|
|
145
|
+
generateContent(topic: string, wordCount?: number, markdown?: boolean): Promise<GenerateResponse>;
|
|
33
146
|
private processContent;
|
|
34
|
-
private extractTextFromObject;
|
|
35
147
|
private createErrorResponse;
|
|
36
148
|
private formatErrorDetails;
|
|
37
149
|
}
|
|
38
150
|
|
|
39
|
-
export {
|
|
151
|
+
export { aiTexGen, analyzeText, getPunch, langTrans, tableMaker };
|
package/dist/index.js
CHANGED
|
@@ -50,9 +50,11 @@ var __async = (__this, __arguments, generator) => {
|
|
|
50
50
|
// src/index.ts
|
|
51
51
|
var index_exports = {};
|
|
52
52
|
__export(index_exports, {
|
|
53
|
-
aiTexGen: () =>
|
|
53
|
+
aiTexGen: () => aiTexGen,
|
|
54
54
|
analyzeText: () => analyzeText,
|
|
55
|
-
getPunch: () => getPunch
|
|
55
|
+
getPunch: () => getPunch,
|
|
56
|
+
langTrans: () => langTrans,
|
|
57
|
+
tableMaker: () => tableMaker
|
|
56
58
|
});
|
|
57
59
|
module.exports = __toCommonJS(index_exports);
|
|
58
60
|
|
|
@@ -78,9 +80,7 @@ function analyzeText(text, wordsPerMinute = DEFAULT_READING_SPEED) {
|
|
|
78
80
|
characterCount,
|
|
79
81
|
sentenceCount,
|
|
80
82
|
linkCount: links.length,
|
|
81
|
-
// Link count remains for backward compatibility
|
|
82
83
|
links,
|
|
83
|
-
// Add all links in the result
|
|
84
84
|
readabilityScore,
|
|
85
85
|
sentiment,
|
|
86
86
|
keywords
|
|
@@ -101,9 +101,11 @@ function calculateSentenceCount(text) {
|
|
|
101
101
|
function calculateReadingTime(wordCount, wordsPerMinute) {
|
|
102
102
|
if (wordCount === 0) return { minutes: 0, seconds: 0 };
|
|
103
103
|
const readingTimeInMinutes = wordCount / wordsPerMinute;
|
|
104
|
-
const minutes = readingTimeInMinutes.toFixed(2);
|
|
105
|
-
const seconds = (
|
|
106
|
-
|
|
104
|
+
const minutes = parseFloat(readingTimeInMinutes.toFixed(2));
|
|
105
|
+
const seconds = parseFloat(
|
|
106
|
+
((readingTimeInMinutes - Math.floor(readingTimeInMinutes)) * 60).toFixed(2)
|
|
107
|
+
);
|
|
108
|
+
return { minutes, seconds };
|
|
107
109
|
}
|
|
108
110
|
function countLinks(text) {
|
|
109
111
|
const linkRegex = /https?:\/\/[^\s]+/g;
|
|
@@ -118,11 +120,11 @@ function calculateReadabilityScore(text) {
|
|
|
118
120
|
return 206.835 - 1.015 * (wordCount / sentenceCount) - 84.6 * (syllableCount / wordCount);
|
|
119
121
|
}
|
|
120
122
|
function calculateSyllableCount(text) {
|
|
121
|
-
return (text.match(/[aeiouy]{1,2}/
|
|
123
|
+
return (text.match(/[aeiouy]{1,2}/gi) || []).length;
|
|
122
124
|
}
|
|
123
125
|
function analyzeSentiment(text) {
|
|
124
|
-
const
|
|
125
|
-
const result =
|
|
126
|
+
const sentimentAnalyzer = new import_sentiment.default();
|
|
127
|
+
const result = sentimentAnalyzer.analyze(text);
|
|
126
128
|
return result.score > 0 ? "Positive" : result.score < 0 ? "Negative" : "Neutral";
|
|
127
129
|
}
|
|
128
130
|
function extractKeywords(text) {
|
|
@@ -146,7 +148,6 @@ function extractKeywords(text) {
|
|
|
146
148
|
"it",
|
|
147
149
|
"is",
|
|
148
150
|
"was",
|
|
149
|
-
"for",
|
|
150
151
|
"as",
|
|
151
152
|
"be",
|
|
152
153
|
"are",
|
|
@@ -169,14 +170,14 @@ function extractKeywords(text) {
|
|
|
169
170
|
wordFrequency.set(nGram, (wordFrequency.get(nGram) || 0) + 1);
|
|
170
171
|
}
|
|
171
172
|
});
|
|
172
|
-
return Array.from(wordFrequency).sort(([, countA], [, countB]) => countB - countA).slice(0, 5).map(([
|
|
173
|
+
return Array.from(wordFrequency).sort(([, countA], [, countB]) => countB - countA).slice(0, 5).map(([keyword]) => keyword);
|
|
173
174
|
}
|
|
174
175
|
function extractNGrams(words) {
|
|
175
176
|
const nGrams = [];
|
|
176
177
|
for (let i = 0; i < words.length - 1; i++) {
|
|
177
|
-
nGrams.push(words[i]
|
|
178
|
+
nGrams.push(`${words[i]} ${words[i + 1]}`);
|
|
178
179
|
if (i < words.length - 2) {
|
|
179
|
-
nGrams.push(words[i]
|
|
180
|
+
nGrams.push(`${words[i]} ${words[i + 1]} ${words[i + 2]}`);
|
|
180
181
|
}
|
|
181
182
|
}
|
|
182
183
|
return nGrams;
|
|
@@ -187,39 +188,139 @@ function isStopWord(word, stopWords) {
|
|
|
187
188
|
|
|
188
189
|
// src/utils/getPunch.ts
|
|
189
190
|
var import_axios = __toESM(require("axios"));
|
|
190
|
-
var API_URL = "
|
|
191
|
-
|
|
192
|
-
function getPunch(next) {
|
|
191
|
+
var API_URL = "https://ai.hackclub.com/chat/completions";
|
|
192
|
+
function getPunch(text) {
|
|
193
193
|
return __async(this, null, function* () {
|
|
194
|
-
var _a;
|
|
194
|
+
var _a, _b, _c, _d, _e, _f;
|
|
195
195
|
try {
|
|
196
196
|
const response = yield import_axios.default.post(API_URL, {
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
messages: [
|
|
198
|
+
{
|
|
199
|
+
role: "user",
|
|
200
|
+
content: `Fix the capitalization and punctuation of this text as plain text: "${text}"`
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
temperature: 0
|
|
204
|
+
// Keep corrections consistent
|
|
199
205
|
});
|
|
206
|
+
const correctedText = (_d = (_c = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content) == null ? void 0 : _d.trim();
|
|
207
|
+
if (!correctedText) {
|
|
208
|
+
console.warn("API returned no content.");
|
|
209
|
+
return { content: "No content generated", status_code: 200 };
|
|
210
|
+
}
|
|
211
|
+
return { content: correctedText, status_code: 200 };
|
|
212
|
+
} catch (error) {
|
|
213
|
+
console.error("Error :", error);
|
|
200
214
|
return {
|
|
201
|
-
|
|
202
|
-
status_code:
|
|
215
|
+
error: ((_f = (_e = error.response) == null ? void 0 : _e.data) == null ? void 0 : _f.error) || "Failed to get response from the AI server.",
|
|
216
|
+
status_code: 500
|
|
203
217
|
};
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// src/utils/langTrans.ts
|
|
223
|
+
var import_axios2 = __toESM(require("axios"));
|
|
224
|
+
var API_URL2 = "https://ai.hackclub.com/chat/completions";
|
|
225
|
+
function langTrans(content, language) {
|
|
226
|
+
return __async(this, null, function* () {
|
|
227
|
+
var _a, _b, _c, _d, _e, _f;
|
|
228
|
+
try {
|
|
229
|
+
const response = yield import_axios2.default.post(API_URL2, {
|
|
230
|
+
messages: [
|
|
231
|
+
{
|
|
232
|
+
role: "user",
|
|
233
|
+
content: `Translate this content "${content}" into "${language}".`
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
});
|
|
237
|
+
const translatedText = (_d = (_c = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content) == null ? void 0 : _d.trim();
|
|
238
|
+
if (!translatedText) {
|
|
239
|
+
console.warn("API returned no content.");
|
|
240
|
+
return { content: "No content generated", status_code: 200 };
|
|
241
|
+
}
|
|
242
|
+
return { content: translatedText, status_code: 200 };
|
|
204
243
|
} catch (error) {
|
|
244
|
+
console.error("Error :", error);
|
|
205
245
|
return {
|
|
206
|
-
error: ((
|
|
246
|
+
error: ((_f = (_e = error.response) == null ? void 0 : _e.data) == null ? void 0 : _f.error) || "Failed to get response from the AI server.",
|
|
207
247
|
status_code: 500
|
|
208
248
|
};
|
|
209
249
|
}
|
|
210
250
|
});
|
|
211
251
|
}
|
|
212
252
|
|
|
213
|
-
// src/utils/
|
|
214
|
-
var
|
|
215
|
-
var
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
253
|
+
// src/utils/tableMaker.ts
|
|
254
|
+
var import_axios3 = __toESM(require("axios"));
|
|
255
|
+
var API_URL3 = "https://ai.hackclub.com/chat/completions";
|
|
256
|
+
function tableMaker(content) {
|
|
257
|
+
return __async(this, null, function* () {
|
|
258
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
259
|
+
if (!content.trim()) {
|
|
260
|
+
return { error: "Input data cannot be empty.", status_code: 400 };
|
|
219
261
|
}
|
|
220
|
-
|
|
262
|
+
try {
|
|
263
|
+
const response = yield import_axios3.default.post(API_URL3, {
|
|
264
|
+
messages: [
|
|
265
|
+
{
|
|
266
|
+
role: "user",
|
|
267
|
+
content: `Convert the following data into a **clean, well-aligned Markdown table**.
|
|
268
|
+
- Ensure all columns have consistent widths.
|
|
269
|
+
- Do not wrap the output in markdown code blocks.
|
|
270
|
+
- Replace empty fields with "N/A".
|
|
271
|
+
- Do not escape "|" inside text.
|
|
272
|
+
|
|
273
|
+
Data:
|
|
274
|
+
|
|
275
|
+
"${content}"`
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
temperature: 0.4,
|
|
279
|
+
// Lower temperature ensures more consistent formatting.
|
|
280
|
+
max_tokens: 500
|
|
281
|
+
// Limits the response size.
|
|
282
|
+
});
|
|
283
|
+
let formattedTable = ((_d = (_c = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content) == null ? void 0 : _d.trim()) || "";
|
|
284
|
+
formattedTable = formattedTable.replace(/```markdown|```/g, "").trim();
|
|
285
|
+
formattedTable = formatMarkdownTable(formattedTable);
|
|
286
|
+
if (!formattedTable) {
|
|
287
|
+
console.warn("API returned no content.");
|
|
288
|
+
return { content: "No content generated.", status_code: 200 };
|
|
289
|
+
}
|
|
290
|
+
return { content: formattedTable, status_code: 200 };
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.error("Error:", error);
|
|
293
|
+
return {
|
|
294
|
+
error: ((_f = (_e = error.response) == null ? void 0 : _e.data) == null ? void 0 : _f.error) || "Failed to process request.",
|
|
295
|
+
status_code: ((_g = error.response) == null ? void 0 : _g.status) || 500
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function formatMarkdownTable(table) {
|
|
301
|
+
const lines = table.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
302
|
+
const columnWidths = [];
|
|
303
|
+
lines.forEach((line) => {
|
|
304
|
+
const columns = line.split("|").map((col) => col.trim());
|
|
305
|
+
columns.forEach((col, index) => {
|
|
306
|
+
columnWidths[index] = Math.max(columnWidths[index] || 0, col.length);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
const formattedLines = lines.map((line) => {
|
|
310
|
+
const columns = line.split("|").map((col) => col.trim());
|
|
311
|
+
return columns.map((col, index) => col.padEnd(columnWidths[index], " ")).join(" | ");
|
|
312
|
+
});
|
|
313
|
+
return formattedLines.join("\n");
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// src/utils/aiTexGen.ts
|
|
317
|
+
var import_axios4 = __toESM(require("axios"));
|
|
318
|
+
var aiTexGen = class {
|
|
319
|
+
// Constructor initializes the API URL
|
|
320
|
+
constructor() {
|
|
321
|
+
this.apiUrl = "https://ai.hackclub.com/chat/completions";
|
|
221
322
|
}
|
|
222
|
-
// Validate
|
|
323
|
+
// Validate the inputs before making the API call
|
|
223
324
|
validateInputs(topic, wordCount) {
|
|
224
325
|
if (typeof topic !== "string" || topic.trim().length === 0) {
|
|
225
326
|
throw this.createErrorResponse("INVALID_TOPIC", "Topic must be a non-empty string.", 400);
|
|
@@ -229,57 +330,45 @@ var AiTexGen = class {
|
|
|
229
330
|
wordCount = 100;
|
|
230
331
|
}
|
|
231
332
|
}
|
|
232
|
-
|
|
233
|
-
|
|
333
|
+
/**
|
|
334
|
+
* Generates content based on the topic and word count.
|
|
335
|
+
*
|
|
336
|
+
* @param topic The topic for the article (e.g., "Artificial Intelligence").
|
|
337
|
+
* @param wordCount The maximum number of words for the article (default is 100).
|
|
338
|
+
* @param markdown If true, returns the content in Markdown format (default is false).
|
|
339
|
+
* @returns A promise that resolves with the topic and generated content.
|
|
340
|
+
*/
|
|
341
|
+
generateContent(topic, wordCount = 100, markdown = false) {
|
|
234
342
|
return __async(this, null, function* () {
|
|
235
|
-
var _a;
|
|
343
|
+
var _a, _b, _c;
|
|
236
344
|
try {
|
|
237
345
|
this.validateInputs(topic, wordCount);
|
|
238
|
-
const
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
// Specify the model you want to use
|
|
346
|
+
const formatInstruction = markdown ? "Use proper Markdown formatting." : "Use plain text formatting.";
|
|
347
|
+
const prompt = `Write a detailed article about ${topic}, aiming for a maximum of ${wordCount} words. ${formatInstruction}`;
|
|
348
|
+
const response = yield import_axios4.default.post(this.apiUrl, {
|
|
242
349
|
messages: [
|
|
243
350
|
{
|
|
244
351
|
role: "user",
|
|
245
352
|
content: prompt
|
|
246
|
-
// Use the prompt with the topic and word count
|
|
247
353
|
}
|
|
248
354
|
]
|
|
249
355
|
});
|
|
250
|
-
const content = this.processContent((_a = response.
|
|
356
|
+
const content = this.processContent((_c = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content);
|
|
251
357
|
return {
|
|
252
358
|
topic,
|
|
253
359
|
content
|
|
254
360
|
};
|
|
255
361
|
} catch (error) {
|
|
256
|
-
console.error("Error generating content
|
|
257
|
-
throw this.createErrorResponse("API_ERROR", "Failed to generate content
|
|
362
|
+
console.error("Error generating content:", error);
|
|
363
|
+
throw this.createErrorResponse("API_ERROR", "Failed to generate content.", 500, this.formatErrorDetails(error));
|
|
258
364
|
}
|
|
259
365
|
});
|
|
260
366
|
}
|
|
261
|
-
//
|
|
367
|
+
// Process and clean up the generated content (e.g., remove extra spaces)
|
|
262
368
|
processContent(content) {
|
|
263
|
-
|
|
264
|
-
return "No content generated or content is empty.";
|
|
265
|
-
}
|
|
266
|
-
return content.map((item) => {
|
|
267
|
-
if (typeof item === "string") {
|
|
268
|
-
return item.trim();
|
|
269
|
-
} else if (typeof item === "object") {
|
|
270
|
-
return this.extractTextFromObject(item);
|
|
271
|
-
}
|
|
272
|
-
return "";
|
|
273
|
-
}).join(" ").trim();
|
|
274
|
-
}
|
|
275
|
-
// Helper method to safely extract text from an object, if needed
|
|
276
|
-
extractTextFromObject(obj) {
|
|
277
|
-
if (obj && obj.text) {
|
|
278
|
-
return obj.text.trim();
|
|
279
|
-
}
|
|
280
|
-
return "";
|
|
369
|
+
return (content == null ? void 0 : content.trim()) || "No content generated or content is empty.";
|
|
281
370
|
}
|
|
282
|
-
//
|
|
371
|
+
// Create a structured error response
|
|
283
372
|
createErrorResponse(code, message, statusCode, details) {
|
|
284
373
|
return {
|
|
285
374
|
error: {
|
|
@@ -290,7 +379,7 @@ var AiTexGen = class {
|
|
|
290
379
|
}
|
|
291
380
|
};
|
|
292
381
|
}
|
|
293
|
-
//
|
|
382
|
+
// Format error details based on the error object
|
|
294
383
|
formatErrorDetails(error) {
|
|
295
384
|
if (error instanceof Error) {
|
|
296
385
|
return error.message;
|
|
@@ -303,5 +392,7 @@ var AiTexGen = class {
|
|
|
303
392
|
0 && (module.exports = {
|
|
304
393
|
aiTexGen,
|
|
305
394
|
analyzeText,
|
|
306
|
-
getPunch
|
|
395
|
+
getPunch,
|
|
396
|
+
langTrans,
|
|
397
|
+
tableMaker
|
|
307
398
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -41,9 +41,7 @@ function analyzeText(text, wordsPerMinute = DEFAULT_READING_SPEED) {
|
|
|
41
41
|
characterCount,
|
|
42
42
|
sentenceCount,
|
|
43
43
|
linkCount: links.length,
|
|
44
|
-
// Link count remains for backward compatibility
|
|
45
44
|
links,
|
|
46
|
-
// Add all links in the result
|
|
47
45
|
readabilityScore,
|
|
48
46
|
sentiment,
|
|
49
47
|
keywords
|
|
@@ -64,9 +62,11 @@ function calculateSentenceCount(text) {
|
|
|
64
62
|
function calculateReadingTime(wordCount, wordsPerMinute) {
|
|
65
63
|
if (wordCount === 0) return { minutes: 0, seconds: 0 };
|
|
66
64
|
const readingTimeInMinutes = wordCount / wordsPerMinute;
|
|
67
|
-
const minutes = readingTimeInMinutes.toFixed(2);
|
|
68
|
-
const seconds = (
|
|
69
|
-
|
|
65
|
+
const minutes = parseFloat(readingTimeInMinutes.toFixed(2));
|
|
66
|
+
const seconds = parseFloat(
|
|
67
|
+
((readingTimeInMinutes - Math.floor(readingTimeInMinutes)) * 60).toFixed(2)
|
|
68
|
+
);
|
|
69
|
+
return { minutes, seconds };
|
|
70
70
|
}
|
|
71
71
|
function countLinks(text) {
|
|
72
72
|
const linkRegex = /https?:\/\/[^\s]+/g;
|
|
@@ -81,11 +81,11 @@ function calculateReadabilityScore(text) {
|
|
|
81
81
|
return 206.835 - 1.015 * (wordCount / sentenceCount) - 84.6 * (syllableCount / wordCount);
|
|
82
82
|
}
|
|
83
83
|
function calculateSyllableCount(text) {
|
|
84
|
-
return (text.match(/[aeiouy]{1,2}/
|
|
84
|
+
return (text.match(/[aeiouy]{1,2}/gi) || []).length;
|
|
85
85
|
}
|
|
86
86
|
function analyzeSentiment(text) {
|
|
87
|
-
const
|
|
88
|
-
const result =
|
|
87
|
+
const sentimentAnalyzer = new Sentiment();
|
|
88
|
+
const result = sentimentAnalyzer.analyze(text);
|
|
89
89
|
return result.score > 0 ? "Positive" : result.score < 0 ? "Negative" : "Neutral";
|
|
90
90
|
}
|
|
91
91
|
function extractKeywords(text) {
|
|
@@ -109,7 +109,6 @@ function extractKeywords(text) {
|
|
|
109
109
|
"it",
|
|
110
110
|
"is",
|
|
111
111
|
"was",
|
|
112
|
-
"for",
|
|
113
112
|
"as",
|
|
114
113
|
"be",
|
|
115
114
|
"are",
|
|
@@ -132,14 +131,14 @@ function extractKeywords(text) {
|
|
|
132
131
|
wordFrequency.set(nGram, (wordFrequency.get(nGram) || 0) + 1);
|
|
133
132
|
}
|
|
134
133
|
});
|
|
135
|
-
return Array.from(wordFrequency).sort(([, countA], [, countB]) => countB - countA).slice(0, 5).map(([
|
|
134
|
+
return Array.from(wordFrequency).sort(([, countA], [, countB]) => countB - countA).slice(0, 5).map(([keyword]) => keyword);
|
|
136
135
|
}
|
|
137
136
|
function extractNGrams(words) {
|
|
138
137
|
const nGrams = [];
|
|
139
138
|
for (let i = 0; i < words.length - 1; i++) {
|
|
140
|
-
nGrams.push(words[i]
|
|
139
|
+
nGrams.push(`${words[i]} ${words[i + 1]}`);
|
|
141
140
|
if (i < words.length - 2) {
|
|
142
|
-
nGrams.push(words[i]
|
|
141
|
+
nGrams.push(`${words[i]} ${words[i + 1]} ${words[i + 2]}`);
|
|
143
142
|
}
|
|
144
143
|
}
|
|
145
144
|
return nGrams;
|
|
@@ -150,39 +149,139 @@ function isStopWord(word, stopWords) {
|
|
|
150
149
|
|
|
151
150
|
// src/utils/getPunch.ts
|
|
152
151
|
import axios from "axios";
|
|
153
|
-
var API_URL = "
|
|
154
|
-
|
|
155
|
-
function getPunch(next) {
|
|
152
|
+
var API_URL = "https://ai.hackclub.com/chat/completions";
|
|
153
|
+
function getPunch(text) {
|
|
156
154
|
return __async(this, null, function* () {
|
|
157
|
-
var _a;
|
|
155
|
+
var _a, _b, _c, _d, _e, _f;
|
|
158
156
|
try {
|
|
159
157
|
const response = yield axios.post(API_URL, {
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
messages: [
|
|
159
|
+
{
|
|
160
|
+
role: "user",
|
|
161
|
+
content: `Fix the capitalization and punctuation of this text as plain text: "${text}"`
|
|
162
|
+
}
|
|
163
|
+
],
|
|
164
|
+
temperature: 0
|
|
165
|
+
// Keep corrections consistent
|
|
162
166
|
});
|
|
167
|
+
const correctedText = (_d = (_c = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content) == null ? void 0 : _d.trim();
|
|
168
|
+
if (!correctedText) {
|
|
169
|
+
console.warn("API returned no content.");
|
|
170
|
+
return { content: "No content generated", status_code: 200 };
|
|
171
|
+
}
|
|
172
|
+
return { content: correctedText, status_code: 200 };
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error("Error :", error);
|
|
163
175
|
return {
|
|
164
|
-
|
|
165
|
-
status_code:
|
|
176
|
+
error: ((_f = (_e = error.response) == null ? void 0 : _e.data) == null ? void 0 : _f.error) || "Failed to get response from the AI server.",
|
|
177
|
+
status_code: 500
|
|
166
178
|
};
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/utils/langTrans.ts
|
|
184
|
+
import axios2 from "axios";
|
|
185
|
+
var API_URL2 = "https://ai.hackclub.com/chat/completions";
|
|
186
|
+
function langTrans(content, language) {
|
|
187
|
+
return __async(this, null, function* () {
|
|
188
|
+
var _a, _b, _c, _d, _e, _f;
|
|
189
|
+
try {
|
|
190
|
+
const response = yield axios2.post(API_URL2, {
|
|
191
|
+
messages: [
|
|
192
|
+
{
|
|
193
|
+
role: "user",
|
|
194
|
+
content: `Translate this content "${content}" into "${language}".`
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
});
|
|
198
|
+
const translatedText = (_d = (_c = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content) == null ? void 0 : _d.trim();
|
|
199
|
+
if (!translatedText) {
|
|
200
|
+
console.warn("API returned no content.");
|
|
201
|
+
return { content: "No content generated", status_code: 200 };
|
|
202
|
+
}
|
|
203
|
+
return { content: translatedText, status_code: 200 };
|
|
167
204
|
} catch (error) {
|
|
205
|
+
console.error("Error :", error);
|
|
168
206
|
return {
|
|
169
|
-
error: ((
|
|
207
|
+
error: ((_f = (_e = error.response) == null ? void 0 : _e.data) == null ? void 0 : _f.error) || "Failed to get response from the AI server.",
|
|
170
208
|
status_code: 500
|
|
171
209
|
};
|
|
172
210
|
}
|
|
173
211
|
});
|
|
174
212
|
}
|
|
175
213
|
|
|
176
|
-
// src/utils/
|
|
177
|
-
import
|
|
178
|
-
var
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
214
|
+
// src/utils/tableMaker.ts
|
|
215
|
+
import axios3 from "axios";
|
|
216
|
+
var API_URL3 = "https://ai.hackclub.com/chat/completions";
|
|
217
|
+
function tableMaker(content) {
|
|
218
|
+
return __async(this, null, function* () {
|
|
219
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
220
|
+
if (!content.trim()) {
|
|
221
|
+
return { error: "Input data cannot be empty.", status_code: 400 };
|
|
182
222
|
}
|
|
183
|
-
|
|
223
|
+
try {
|
|
224
|
+
const response = yield axios3.post(API_URL3, {
|
|
225
|
+
messages: [
|
|
226
|
+
{
|
|
227
|
+
role: "user",
|
|
228
|
+
content: `Convert the following data into a **clean, well-aligned Markdown table**.
|
|
229
|
+
- Ensure all columns have consistent widths.
|
|
230
|
+
- Do not wrap the output in markdown code blocks.
|
|
231
|
+
- Replace empty fields with "N/A".
|
|
232
|
+
- Do not escape "|" inside text.
|
|
233
|
+
|
|
234
|
+
Data:
|
|
235
|
+
|
|
236
|
+
"${content}"`
|
|
237
|
+
}
|
|
238
|
+
],
|
|
239
|
+
temperature: 0.4,
|
|
240
|
+
// Lower temperature ensures more consistent formatting.
|
|
241
|
+
max_tokens: 500
|
|
242
|
+
// Limits the response size.
|
|
243
|
+
});
|
|
244
|
+
let formattedTable = ((_d = (_c = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content) == null ? void 0 : _d.trim()) || "";
|
|
245
|
+
formattedTable = formattedTable.replace(/```markdown|```/g, "").trim();
|
|
246
|
+
formattedTable = formatMarkdownTable(formattedTable);
|
|
247
|
+
if (!formattedTable) {
|
|
248
|
+
console.warn("API returned no content.");
|
|
249
|
+
return { content: "No content generated.", status_code: 200 };
|
|
250
|
+
}
|
|
251
|
+
return { content: formattedTable, status_code: 200 };
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.error("Error:", error);
|
|
254
|
+
return {
|
|
255
|
+
error: ((_f = (_e = error.response) == null ? void 0 : _e.data) == null ? void 0 : _f.error) || "Failed to process request.",
|
|
256
|
+
status_code: ((_g = error.response) == null ? void 0 : _g.status) || 500
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
function formatMarkdownTable(table) {
|
|
262
|
+
const lines = table.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
263
|
+
const columnWidths = [];
|
|
264
|
+
lines.forEach((line) => {
|
|
265
|
+
const columns = line.split("|").map((col) => col.trim());
|
|
266
|
+
columns.forEach((col, index) => {
|
|
267
|
+
columnWidths[index] = Math.max(columnWidths[index] || 0, col.length);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
const formattedLines = lines.map((line) => {
|
|
271
|
+
const columns = line.split("|").map((col) => col.trim());
|
|
272
|
+
return columns.map((col, index) => col.padEnd(columnWidths[index], " ")).join(" | ");
|
|
273
|
+
});
|
|
274
|
+
return formattedLines.join("\n");
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/utils/aiTexGen.ts
|
|
278
|
+
import axios4 from "axios";
|
|
279
|
+
var aiTexGen = class {
|
|
280
|
+
// Constructor initializes the API URL
|
|
281
|
+
constructor() {
|
|
282
|
+
this.apiUrl = "https://ai.hackclub.com/chat/completions";
|
|
184
283
|
}
|
|
185
|
-
// Validate
|
|
284
|
+
// Validate the inputs before making the API call
|
|
186
285
|
validateInputs(topic, wordCount) {
|
|
187
286
|
if (typeof topic !== "string" || topic.trim().length === 0) {
|
|
188
287
|
throw this.createErrorResponse("INVALID_TOPIC", "Topic must be a non-empty string.", 400);
|
|
@@ -192,57 +291,45 @@ var AiTexGen = class {
|
|
|
192
291
|
wordCount = 100;
|
|
193
292
|
}
|
|
194
293
|
}
|
|
195
|
-
|
|
196
|
-
|
|
294
|
+
/**
|
|
295
|
+
* Generates content based on the topic and word count.
|
|
296
|
+
*
|
|
297
|
+
* @param topic The topic for the article (e.g., "Artificial Intelligence").
|
|
298
|
+
* @param wordCount The maximum number of words for the article (default is 100).
|
|
299
|
+
* @param markdown If true, returns the content in Markdown format (default is false).
|
|
300
|
+
* @returns A promise that resolves with the topic and generated content.
|
|
301
|
+
*/
|
|
302
|
+
generateContent(topic, wordCount = 100, markdown = false) {
|
|
197
303
|
return __async(this, null, function* () {
|
|
198
|
-
var _a;
|
|
304
|
+
var _a, _b, _c;
|
|
199
305
|
try {
|
|
200
306
|
this.validateInputs(topic, wordCount);
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
// Specify the model you want to use
|
|
307
|
+
const formatInstruction = markdown ? "Use proper Markdown formatting." : "Use plain text formatting.";
|
|
308
|
+
const prompt = `Write a detailed article about ${topic}, aiming for a maximum of ${wordCount} words. ${formatInstruction}`;
|
|
309
|
+
const response = yield axios4.post(this.apiUrl, {
|
|
205
310
|
messages: [
|
|
206
311
|
{
|
|
207
312
|
role: "user",
|
|
208
313
|
content: prompt
|
|
209
|
-
// Use the prompt with the topic and word count
|
|
210
314
|
}
|
|
211
315
|
]
|
|
212
316
|
});
|
|
213
|
-
const content = this.processContent((_a = response.
|
|
317
|
+
const content = this.processContent((_c = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content);
|
|
214
318
|
return {
|
|
215
319
|
topic,
|
|
216
320
|
content
|
|
217
321
|
};
|
|
218
322
|
} catch (error) {
|
|
219
|
-
console.error("Error generating content
|
|
220
|
-
throw this.createErrorResponse("API_ERROR", "Failed to generate content
|
|
323
|
+
console.error("Error generating content:", error);
|
|
324
|
+
throw this.createErrorResponse("API_ERROR", "Failed to generate content.", 500, this.formatErrorDetails(error));
|
|
221
325
|
}
|
|
222
326
|
});
|
|
223
327
|
}
|
|
224
|
-
//
|
|
328
|
+
// Process and clean up the generated content (e.g., remove extra spaces)
|
|
225
329
|
processContent(content) {
|
|
226
|
-
|
|
227
|
-
return "No content generated or content is empty.";
|
|
228
|
-
}
|
|
229
|
-
return content.map((item) => {
|
|
230
|
-
if (typeof item === "string") {
|
|
231
|
-
return item.trim();
|
|
232
|
-
} else if (typeof item === "object") {
|
|
233
|
-
return this.extractTextFromObject(item);
|
|
234
|
-
}
|
|
235
|
-
return "";
|
|
236
|
-
}).join(" ").trim();
|
|
237
|
-
}
|
|
238
|
-
// Helper method to safely extract text from an object, if needed
|
|
239
|
-
extractTextFromObject(obj) {
|
|
240
|
-
if (obj && obj.text) {
|
|
241
|
-
return obj.text.trim();
|
|
242
|
-
}
|
|
243
|
-
return "";
|
|
330
|
+
return (content == null ? void 0 : content.trim()) || "No content generated or content is empty.";
|
|
244
331
|
}
|
|
245
|
-
//
|
|
332
|
+
// Create a structured error response
|
|
246
333
|
createErrorResponse(code, message, statusCode, details) {
|
|
247
334
|
return {
|
|
248
335
|
error: {
|
|
@@ -253,7 +340,7 @@ var AiTexGen = class {
|
|
|
253
340
|
}
|
|
254
341
|
};
|
|
255
342
|
}
|
|
256
|
-
//
|
|
343
|
+
// Format error details based on the error object
|
|
257
344
|
formatErrorDetails(error) {
|
|
258
345
|
if (error instanceof Error) {
|
|
259
346
|
return error.message;
|
|
@@ -263,7 +350,9 @@ var AiTexGen = class {
|
|
|
263
350
|
}
|
|
264
351
|
};
|
|
265
352
|
export {
|
|
266
|
-
|
|
353
|
+
aiTexGen,
|
|
267
354
|
analyzeText,
|
|
268
|
-
getPunch
|
|
355
|
+
getPunch,
|
|
356
|
+
langTrans,
|
|
357
|
+
tableMaker
|
|
269
358
|
};
|