diff --git a/README.md b/README.md
index 76f0273..f822b62 100644
--- a/README.md
+++ b/README.md
@@ -101,6 +101,8 @@ const count = stringzy.analyze.wordCount('Hello world'); // 2
### Analysis
- [wordCount](#wordcount) - Counts the number of words in a string
+- [contentWordCount](#contentwordcount)- Counts the number of content words (nouns, verbs, adjectives, adverbs, etc.) in a string.
+- [functionWordCount](#functionwordcount)- Counts the number of function words (prepositions, pronouns, conjunctions, articles, etc.) in a string.
- [readingDuration](#readingduration) - Calculates the reading duration of a given string
- [characterCount](#charactercount) - Counts the number of characters in a string
- [characterFrequency](#characterfrequency) - Analyzes character frequency in a string
@@ -871,6 +873,64 @@ complexity('');
- `uniqueness` (number): Measure of character uniqueness
- `length` (number): Length of the input string
+feature/content-words
+
+#### contentWordCount(text)
+
+Counts the number of content words (nouns, verbs, adjectives, adverbs, etc.) in a string.
+
+```javascript
+
+import { contentWordCount } from 'stringzy';
+
+contentWordCount("Learning JavaScript improves coding skills!");
+// Returns: { count: 5 }
+
+contentWordCount("The cat sleeps on the warm windowsill.");
+// Returns: { count: 5 }
+
+contentWordCount("Wow! Such a beautiful day.");
+// Returns: { count: 4 }
+```
+
+| Parameter | Type | Default | Description |
+| --------- | ------ | -------- | -------------------------------------- |
+| text | string | required | The input string to analyze content words |
+
+**Returns:** An object containing:
+
+- `count` (number): Total number of content words in the string
+
+
+#### functionWordCount(text)
+
+Counts the number of function words (prepositions, pronouns, conjunctions, articles, etc.) in a string.
+
+```javascript
+
+import { functionWordCount } from 'stringzy';
+
+functionWordCount("She and I are going to the park.");
+// Returns: { count: 7 }
+
+functionWordCount("It is an example of proper grammar usage.");
+// Returns: { count: 8 }
+
+functionWordCount("Can you see the stars tonight?");
+// Returns: { count: 5 }
+```
+
+| Parameter | Type | Default | Description |
+| --------- | ------ | -------- | -------------------------------------- |
+| text | string | required | The input string to analyze function words |
+
+**Returns:** An object containing:
+
+- `count` (number): Total number of function words in the string
+
+
+
+
#### `patternCount(text, pattern)`
Counts the number of times a substring (pattern) occurs in a string, including overlapping occurrences.
@@ -908,6 +968,8 @@ vowelConsonantCount('');
| --------- | ------ | -------- | -------------------------------------------------- |
| str | string | required | The input string to count vowels and consonants in |
+feature/content-words
+
#### checkMultiplePatterns(text, patterns)
Finds occurrences of multiple patterns within a given text using the Rabin–Karp algorithm.
@@ -931,6 +993,7 @@ checkMultiplePatterns('hello world', ['xyz', '123']);
| text | string | required | The text to search within. |
| patterns | string\[ ] | required | An array of patterns to search for (each must be a string). |
+
---
### 🎨 Formatting
diff --git a/package-lock.json b/package-lock.json
index 159a654..3bb9a0e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,9 @@
"name": "stringzy",
"version": "4.0.0",
"license": "MIT",
+ "dependencies": {
+ "stringzy": "^3.0.0"
+ },
"devDependencies": {
"@types/node": "^24.5.2",
"prettier": "^3.6.2",
@@ -40,6 +43,12 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
+ "node_modules/stringzy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stringzy/-/stringzy-3.0.0.tgz",
+ "integrity": "sha512-bq5FuxrWouAUwIOKTS7mKdRgBxH3mo5RXGmWknWCaH5IXJdTHxuCgnh41u5sgMeScQGXE1RzRXN3NIRt6jW6JQ==",
+ "license": "MIT"
+ },
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
diff --git a/package.json b/package.json
index 6888631..4b30c36 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
- "test": "npm run build && node --test",
+ "test": " npm run build && node --test",
"prepublishOnly": "npm run build",
"format": "prettier --write ."
},
diff --git a/src/analyzing/contentWordCount.ts b/src/analyzing/contentWordCount.ts
new file mode 100644
index 0000000..3c3af11
--- /dev/null
+++ b/src/analyzing/contentWordCount.ts
@@ -0,0 +1,23 @@
+import { functionWordCount } from './functionWordCount';
+import { wordCount } from './wordCount';
+
+/**
+ * Counts the number of content words in a given text.
+ *
+ * Content words are words that carry lexical meaning (nouns, verbs, adjectives, adverbs),
+ * excluding function words such as prepositions, pronouns, and articles.
+ *
+ * @param {string} text - The text to analyze.
+ * @returns {number} The count of content words in the text.
+ * @throws {TypeError} If the input is not a string.
+ */
+export function contentWordCount(text: string): number {
+ if (typeof text !== 'string') {
+ throw new TypeError('Input must be a string');
+ }
+
+ const totalWords = wordCount(text);
+ const functionWords = functionWordCount(text);
+
+ return totalWords - functionWords;
+}
diff --git a/src/analyzing/functionWordCount.ts b/src/analyzing/functionWordCount.ts
new file mode 100644
index 0000000..de0e383
--- /dev/null
+++ b/src/analyzing/functionWordCount.ts
@@ -0,0 +1,34 @@
+/**
+ * Counts the number of function words in a given text.
+ *
+ * Function words are common words (e.g., prepositions, pronouns, conjunctions, articles, etc.)
+ * that carry grammatical meaning rather than lexical meaning.
+ *
+ * @param {string} text - The text to analyze.
+ * @returns {number} The count of function words in the text.
+ * @throws {TypeError} If the input is not a string.
+ */
+export function functionWordCount(text: string): number {
+ if (typeof text !== 'string') {
+ throw new TypeError('Input must be a string');
+ }
+
+ const functionWords = new Set([
+ 'a', 'an', 'the', 'and', 'but', 'or', 'nor', 'so', 'yet',
+ 'for', 'of', 'in', 'on', 'at', 'by', 'to', 'from', 'with', 'about',
+ 'as', 'into', 'like', 'through', 'after', 'over', 'between', 'out',
+ 'against', 'during', 'without', 'before', 'under', 'around', 'among',
+ 'is', 'am', 'are', 'was', 'were', 'be', 'been', 'being',
+ 'he', 'she', 'it', 'they', 'we', 'you', 'i', 'me', 'him', 'her',
+ 'them', 'us', 'my', 'your', 'his', 'their', 'our',
+ 'this', 'that', 'these', 'those',
+ 'who', 'whom', 'which', 'what', 'when', 'where', 'why', 'how'
+ ]);
+
+ // ✅ Normalize text: lowercase + remove punctuation
+ const cleanedText = text.toLowerCase().replace(/[^\w\s]/g, '');
+
+ const words = cleanedText.trim().split(/\s+/);
+
+ return words.filter(word => functionWords.has(word)).length;
+}
diff --git a/src/analyzing/index.ts b/src/analyzing/index.ts
index 3c2de40..4ed49d5 100644
--- a/src/analyzing/index.ts
+++ b/src/analyzing/index.ts
@@ -8,6 +8,10 @@ export { patternCount } from './patternCount';
export { vowelConsonantCount } from './vowelConsonantCount';
export { checkMultiplePatterns } from './checkMultiplePatterns';
+export { functionWordCount } from './functionWordCount';
+export { contentWordCount } from './contentWordCount';
+
+
import { characterCount } from './characterCount';
import { characterFrequency } from './characterFrequency';
import { complexity } from './complexity';
@@ -18,6 +22,8 @@ import { patternCount } from './patternCount';
import { vowelConsonantCount } from './vowelConsonantCount';
import { checkMultiplePatterns } from './checkMultiplePatterns';
+
+
export const analyzing = {
characterCount,
characterFrequency,
diff --git a/src/tests/analyzing/contentWordCount.test.ts b/src/tests/analyzing/contentWordCount.test.ts
new file mode 100644
index 0000000..621b051
--- /dev/null
+++ b/src/tests/analyzing/contentWordCount.test.ts
@@ -0,0 +1,19 @@
+import test from "node:test";
+import assert from "node:assert/strict";
+import { contentWordCount } from "../../analyzing/contentWordCount.js";
+
+test("counts content words in a normal sentence", () => {
+ assert.equal(contentWordCount("This is a test of the system"), 2);
+});
+
+test("returns 0 when there are no content words", () => {
+ assert.equal(contentWordCount("is the at of"), 0);
+});
+
+test("ignores case and punctuation", () => {
+ assert.equal(contentWordCount("Elephants, ELEPHANTS, elephants!"), 3);
+});
+
+test("returns 0 for empty string", () => {
+ assert.equal(contentWordCount(""), 0);
+});
diff --git a/src/tests/analyzing/functionWordCount.test.ts b/src/tests/analyzing/functionWordCount.test.ts
new file mode 100644
index 0000000..ee69264
--- /dev/null
+++ b/src/tests/analyzing/functionWordCount.test.ts
@@ -0,0 +1,19 @@
+import test from "node:test";
+import assert from "node:assert/strict";
+import { functionWordCount } from "../../analyzing/functionWordCount.js";
+
+test("counts function words in a normal sentence", () => {
+ assert.equal(functionWordCount("This is a test of the system"), 5);
+});
+
+test("returns 0 when there are no function words", () => {
+ assert.equal(functionWordCount("Elephants run fast"), 0);
+});
+
+test("ignores case and punctuation", () => {
+ assert.equal(functionWordCount("The, THE, the!"), 3);
+});
+
+test("returns 0 for empty string", () => {
+ assert.equal(functionWordCount(""), 0);
+});