diff --git a/README.md b/README.md index 67171b6..bddf747 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,7 @@ const count = stringzy.analyze.wordCount('Hello world'); // 2 - [formatNumber](#formatnumber) - Formats a number string with thousand separators - [formatPhone](#formatphone) - Formats a phone number string to standard format - [formatDuration](#formatduration) - Converts a duration in seconds or milliseconds into a human-readable string +- [trim](#trim) - Removes unnecessary whitespace from a string. ## 📋 API Reference @@ -1289,6 +1290,18 @@ formatDuration(1234567, { unit: 'milliseconds', includeMs: true }); // "20m 34s | - includeMs | boolean | false | Whether to include milliseconds in output | | - delimiter | string | ' ' | The delimiter between time units | +#### `trim(str)` + +Removes unnecessary whitespace from a string, including leading/trailing spaces, multiple spaces between words, tabs, and line breaks. + +```javascript +trim(' hello world '); // 'hello world' +trim('line \n breaks\tand tabs'); // 'line breaks and tabs' +``` +| Parameter | Type | Default | Description | +| --------- | ------ | -------- | ------------------------------------ | +| str | string | required | The input string to trim and normalize.| + ## 🔧 Usage Patterns ### Individual Function Imports diff --git a/src/formatting/index.ts b/src/formatting/index.ts index 5601156..65e4acb 100644 --- a/src/formatting/index.ts +++ b/src/formatting/index.ts @@ -2,15 +2,18 @@ export { capitalize } from './capitalize'; export { formatNumber } from './number'; export { formatPhone } from './phone'; export { formatDuration } from './duration'; +export { trim } from './trim'; import { capitalize } from './capitalize'; import { formatNumber } from './number'; import { formatPhone } from './phone'; import { formatDuration } from './duration'; +import { trim } from './trim'; export const formatting = { capitalize, formatNumber, formatPhone, formatDuration, + trim }; diff --git a/src/formatting/trim.ts b/src/formatting/trim.ts new file mode 100644 index 0000000..700bcda --- /dev/null +++ b/src/formatting/trim.ts @@ -0,0 +1,18 @@ +/** + * Removes unnecessary whitespace from a string. + * This includes leading/trailing spaces, multiple consecutive spaces, tabs, and line breaks. + * The result is a clean, single-spaced string. + * + * @param {string} str - The input string to format. + * @returns {string} The trimmed and normalized string. + * @throws {TypeError} If the input is not a string. + */ +export function trim(str: string): string { + if (typeof str !== 'string') { + throw new TypeError('Input must be a string'); + } + + // 1. Trim leading/trailing whitespace (including newlines/tabs) + // 2. Replace multiple internal whitespace chars (including \n, \t) with a single space + return str.trim().replace(/\s+/g, ' '); +} \ No newline at end of file diff --git a/src/tests/formatting/trim.test.ts b/src/tests/formatting/trim.test.ts new file mode 100644 index 0000000..c6a5ef1 --- /dev/null +++ b/src/tests/formatting/trim.test.ts @@ -0,0 +1,43 @@ +import { describe, it } from 'node:test'; +import assert from 'node:assert'; +// NOTE: Adjust this import path to match your project structure +import { trim } from '../../formatting/trim'; + +describe('trim', () => { + it('removes simple leading and trailing spaces', () => { + assert.strictEqual(trim(' hello world '), 'hello world'); + assert.strictEqual(trim(' leading'), 'leading'); + assert.strictEqual(trim('trailing '), 'trailing'); + }); + + it('collapses multiple spaces between words into one', () => { + assert.strictEqual(trim('multiple spaces'), 'multiple spaces'); + assert.strictEqual(trim('one two three four'), 'one two three four'); + }); + + it('handles tabs and line breaks as whitespace', () => { + assert.strictEqual(trim('line \n breaks\tand tabs'), 'line breaks and tabs'); + assert.strictEqual(trim('tabs\tbetween\twords'), 'tabs between words'); + assert.strictEqual(trim('new\nlines\n\nand\r\nwindows'), 'new lines and windows'); + }); + + it('handles a complex mix of all whitespace types', () => { + const input = ' \n \t hello \n\n world \t ! '; + const expected = 'hello world !'; + assert.strictEqual(trim(input), expected); + }); + + it('handles edge cases: empty and whitespace-only strings', () => { + assert.strictEqual(trim(''), ''); + assert.strictEqual(trim(' '), ''); + assert.strictEqual(trim(' \n \t \r\n '), ''); + }); + + it('throws an error if input is not a string', () => { + assert.throws(() => trim(123 as any), /Input must be a string/); + assert.throws(() => trim(null as any), /Input must be a string/); + assert.throws(() => trim(undefined as any), /Input must be a string/); + assert.throws(() => trim({} as any), /Input must be a string/); + assert.throws(() => trim([] as any), /Input must be a string/); + }); +}); \ No newline at end of file