Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 |

#### <a id="trim"></a>`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
Expand Down
3 changes: 3 additions & 0 deletions src/formatting/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
18 changes: 18 additions & 0 deletions src/formatting/trim.ts
Original file line number Diff line number Diff line change
@@ -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, ' ');
}
43 changes: 43 additions & 0 deletions src/tests/formatting/trim.test.ts
Original file line number Diff line number Diff line change
@@ -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/);
});
});