npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

string-extn

v1.2.0

Published

Extended string utility functions for JavaScript and TypeScript.

Readme

string-extn

A lightweight, TypeScript-first library for safe and functional string manipulation. It provides core string utilities, functional programming helpers, and Unicode-safe operations, designed for Node.js and browser environments.


Table of Contents


Features

✨ Core String Operations

  • trim - Remove leading/trailing whitespace
  • pad - Pad strings to a fixed length with custom characters
  • slice - Extract string substrings with flexible indexing
  • repeat - Repeat strings multiple times
  • truncate - Truncate strings with ellipsis
  • reverse - Reverse string character order

🔧 Functional Programming Helpers

  • map - Transform each character with a function
  • filter - Keep only characters matching a predicate
  • reduce - Accumulate values by processing characters
  • compose - Chain multiple functions for complex transformations

🔤 Case Conversion

  • toCamelCase - Convert to camelCase from kebab-case, snake_case, or spaces
  • toKebabCase - Convert to kebab-case from camelCase, snake_case, or spaces
  • toSnakeCase - Convert to snake_case from camelCase, kebab-case, or spaces
  • toPascalCase - Convert to PascalCase from any format

🔍 String Comparison & Similarity

  • diff - Find character differences between two strings
  • similarity - Calculate similarity score (0-1) using Levenshtein distance

🎭 String Masking & Redaction

  • mask - Mask sensitive information keeping only last N characters visible
  • redact - Redact portions matching regex patterns

🌐 URL & Filename Safe Conversion

  • slugify - Convert to URL-friendly slug format
  • filenameSafe - Remove invalid filesystem characters

✔️ String Validation (20 validators)

  • Email, UUID, Numeric, URL, Hex Color, Phone Number, Date
  • Strong Password, JSON, Base64, Alphabetic, Alphanumeric
  • Case validators, Whitespace, Palindrome, Hexadecimal, Roman Numeral
  • IPv4, IPv6 validation

🌍 Unicode-Safe Operations

  • lengthUnicode - Count Unicode grapheme clusters (handles emoji with modifiers)
  • unicodeSlice - Slice strings while respecting grapheme boundaries
  • reverseUnicode - Reverse strings with proper emoji and combining mark support

🌐 Internationalization

  • localeCompare - Locale-aware string comparison with configurable sensitivity
  • normalizeUnicode - Normalize strings to NFC/NFD/NFKC/NFKD

🔐 Security & Sanitization

  • escapeHTML - Escape HTML-reserved characters
  • escapeSQL - Escape SQL-sensitive characters
  • sanitizePath - Remove traversal and dot segments from paths

⚡ Performance Helpers

  • fastRepeat - Repeat strings using a fast doubling approach
  • fastPadLeft - Left-pad strings using fast repeat

🌊 Stream Utilities

  • chunkString - Split strings into fixed-size chunks
  • streamTransform - Transform chunks and concatenate results

🔗 Chaining & Fluent API

  • chain - Create chainable string transformations
  • StringChain - Fluent wrapper with trim, case, replace, and reverse

💤 Lazy Evaluation

  • lazy - Build lazy transformation pipelines
  • LazyString - Deferred execution via execute()

🧩 Template Interpolation

  • template - Replace {{key}} placeholders from a variable map

🧩 Plugin System

  • registerPlugin - Register a named string plugin
  • runPlugin - Execute a registered plugin
  • listPlugins - List registered plugin names

Installation

npm install string-extn

Or with Yarn:

yarn add string-extn

Quick Start

Core Functions

import { trim, pad, slice, repeat, truncate, reverse } from 'string-extn';

trim('  hello world  ');              // "hello world"
pad('abc', 5, '-');                  // "abc--"
slice('hello', 1, 4);                // "ell"
repeat('ha', 3);                     // "hahaha"
truncate('This is a long string', 10, '...'); // "This is a ..."
reverse('hello');                    // "olleh"

Functional Programming

import { map, filter, reduce, compose } from 'string-extn';

map('abc', c => c.toUpperCase());     // "ABC"
filter('abcdef', c => 'aeiou'.includes(c)); // "ae"
reduce('abc', (acc, c) => acc + c.charCodeAt(0), 0); // 294

const shout = compose(s => s + '!', s => s.toUpperCase());
shout('hello'); // "HELLO!"

Unicode-Safe Operations

import { lengthUnicode, unicodeSlice, reverseUnicode } from 'string-extn';

const emojiStr = '👍🏽👍';
lengthUnicode(emojiStr);          // 2 (counts emoji with skin tone as 1)
unicodeSlice(emojiStr, 0, 1);     // "👍🏽"
reverseUnicode(emojiStr);         // "👍👍🏽"

Chaining & Lazy Evaluation

import { chain, lazy } from 'string-extn';

const chained = chain('  Hello  ')
  .trim()
  .toLower()
  .replace('hello', 'hi')
  .reverse()
  .valueOf();
// "ih"

const pipeline = lazy('  Hello  ')
  .trim()
  .toUpper();

pipeline.execute(); // "HELLO"

Template Interpolation

import { template } from 'string-extn';

template('Hello {{name}}', { name: 'Ada' }); // "Hello Ada"

Plugin System

import { registerPlugin, runPlugin, listPlugins } from 'string-extn';

registerPlugin({
  name: 'wrap',
  fn: (input, left: string, right: string) => `${left}${input}${right}`
});

runPlugin('wrap', 'core', '[', ']'); // "[core]"
listPlugins(); // ["wrap"]

API Reference

Core Functions

| Function | Signature | Description | |----------|-----------|-------------| | trim | trim(str: string): string | Removes leading/trailing whitespace | | pad | pad(str: string, length: number, char?: string): string | Pads string to fixed length | | slice | slice(str: string, start: number, end?: number): string | Returns substring | | repeat | repeat(str: string, times: number): string | Repeats string N times | | truncate | truncate(str: string, max: number): string | Truncates with ellipsis (...) | | reverse | reverse(str: string): string | Reverses string characters |

Functional Programming

| Function | Signature | Description | |----------|-----------|-------------| | map | map(str: string, fn: (c: string) => string): string | Transforms each character | | filter | filter(str: string, fn: (c: string) => boolean): string | Filters characters by predicate | | reduce | reduce<T>(str: string, fn: (acc: T, c: string) => T, initial: T): T | Reduces string to accumulator value | | compose | compose(...fns: Function[]): (value: any) => any | Composes functions right-to-left |

Case Conversion

| Function | Signature | Description | |----------|-----------|-------------| | toCamelCase | toCamelCase(input: string): string | Converts to camelCase | | toKebabCase | toKebabCase(input: string): string | Converts to kebab-case | | toSnakeCase | toSnakeCase(input: string): string | Converts to snake_case | | toPascalCase | toPascalCase(input: string): string | Converts to PascalCase |

String Comparison & Similarity

| Function | Signature | Description | |----------|-----------|-------------| | diff | diff(a: string, b: string): string[] | Returns character differences between two strings | | similarity | similarity(a: string, b: string): number | Returns similarity score (0-1) using Levenshtein distance |

String Masking & Redaction

| Function | Signature | Description | |----------|-----------|-------------| | mask | mask(input: string, visible?: number, maskChar?: string): string | Masks string keeping last N characters visible | | redact | redact(input: string, patterns: RegExp[]): string | Redacts portions matching regex patterns |

URL & Filename Safe Conversion

| Function | Signature | Description | |----------|-----------|-------------| | slugify | slugify(input: string): string | Converts to URL-friendly slug format | | filenameSafe | filenameSafe(input: string): string | Removes invalid filesystem characters |

String Validation

| Function | Input | Returns | Purpose | |----------|-------|---------|---------| | isEmail | string | boolean | Validates email address format | | isUUID | string | boolean | Validates UUID format (v1-v5) | | isNumeric | string | boolean | Validates numeric strings | | isURL | string | boolean | Validates URL format | | isHexColor | string | boolean | Validates hex color codes | | isPhoneNumber | string | boolean | Validates E.164 phone numbers | | isDate | string | boolean | Validates date strings | | isStrongPassword | string | boolean | Validates strong password criteria | | isJSON | string | boolean | Validates JSON format | | isBase64 | string | boolean | Validates Base64 encoding | | isAlphabetic | string | boolean | Validates alphabetic strings only | | isAlphanumeric | string | boolean | Validates alphanumeric strings | | isLowerCase | string | boolean | Validates lowercase strings | | isUpperCase | string | boolean | Validates uppercase strings | | isWhitespace | string | boolean | Validates whitespace-only strings | | isPalindrome | string | boolean | Validates palindrome strings | | isHexadecimal | string | boolean | Validates hexadecimal format | | isRomanNumeral | string | boolean | Validates Roman numeral format | | isIPv4 | string | boolean | Validates IPv4 addresses | | isIPv6 | string | boolean | Validates IPv6 addresses |

Unicode Operations

| Function | Signature | Description | |----------|-----------|-------------| | lengthUnicode | lengthUnicode(str: string): number | Counts Unicode grapheme clusters | | unicodeSlice | unicodeSlice(str: string, start: number, end?: number): string | Slices by grapheme boundaries | | reverseUnicode | reverseUnicode(str: string): string | Reverses with emoji/modifier support |

Internationalization

| Function | Signature | Description | |----------|-----------|-------------| | localeCompare | localeCompare(a: string, b: string, locale?: string, sensitivity?: "base" | "accent" | "case" | "variant"): number | Locale-aware string comparison | | normalizeUnicode | normalizeUnicode(input: string, form?: "NFC" | "NFD" | "NFKC" | "NFKD"): string | Unicode normalization |

Security & Sanitization

| Function | Signature | Description | |----------|-----------|-------------| | escapeHTML | escapeHTML(input: string): string | Escapes HTML-reserved characters | | escapeSQL | escapeSQL(input: string): string | Escapes SQL-sensitive characters | | sanitizePath | sanitizePath(input: string): string | Removes traversal and dot segments |

Performance Helpers

| Function | Signature | Description | |----------|-----------|-------------| | fastRepeat | fastRepeat(input: string, count: number): string | Fast string repetition | | fastPadLeft | fastPadLeft(input: string, length: number, char?: string): string | Fast left padding |

Stream Utilities

| Function | Signature | Description | |----------|-----------|-------------| | chunkString | chunkString(input: string, size: number): string[] | Split string into chunks | | streamTransform | streamTransform(chunks: string[], transformer: (chunk: string) => string): string | Transform and concatenate |

Chaining & Fluent API

| Function | Signature | Description | |----------|-----------|-------------| | chain | chain(input: string): StringChain | Create a chainable string wrapper | | StringChain#trim | trim(): this | Trim leading/trailing whitespace | | StringChain#toUpper | toUpper(): this | Uppercase with default locale rules | | StringChain#toLower | toLower(): this | Lowercase with default locale rules | | StringChain#replace | replace(search: string | RegExp, replacement: string): this | Replace with string or RegExp | | StringChain#reverse | reverse(): this | Reverse by Unicode code points | | StringChain#valueOf | valueOf(): string | Get the current value | | StringChain#toString | toString(): string | String coercion output |

Lazy Evaluation

| Function | Signature | Description | |----------|-----------|-------------| | lazy | lazy(input: string): LazyString | Create a lazy string wrapper | | LazyString#map | map(fn: (input: string) => string): this | Register a deferred transform | | LazyString#trim | trim(): this | Register a trim operation | | LazyString#toUpper | toUpper(): this | Register uppercase conversion | | LazyString#toLower | toLower(): this | Register lowercase conversion | | LazyString#execute | execute(): string | Execute all operations in order |

Template Interpolation

| Function | Signature | Description | |----------|-----------|-------------| | template | template(input: string, variables: Record<string, any>): string | Replace {{key}} placeholders |

Plugin System

| Function | Signature | Description | |----------|-----------|-------------| | registerPlugin | registerPlugin(plugin: StringExtnPlugin): void | Register a named plugin | | runPlugin | runPlugin(name: string, input: string, ...args: any[]): string | Execute a plugin by name | | listPlugins | listPlugins(): string[] | List registered plugin names |


Examples

Example 1: Text Processing Pipeline

import { trim, map, filter } from 'string-extn';

const input = '  HELLO WORLD  ';
const result = trim(input)
  .toLowerCase()
  .split(' ')
  .map(word => filter(word, c => 'aeiou'.includes(c)))
  .join(',');

console.log(result); // "e,o"

Example 2: Case Conversion

import { toCamelCase, toKebabCase, toSnakeCase, toPascalCase } from 'string-extn';

const text = 'hello-world-example';

console.log(toCamelCase(text));    // "helloWorldExample"
console.log(toKebabCase('helloWorld')); // "hello-world"
console.log(toSnakeCase('helloWorld')); // "hello_world"
console.log(toPascalCase(text));   // "HelloWorldExample"

Example 3: String Similarity & Diff

import { similarity, diff } from 'string-extn';

const str1 = 'hello';
const str2 = 'hallo';

console.log(similarity(str1, str2)); // 0.8 (80% similar - one character different)
console.log(diff('abc', 'bcd'));    // ["-a", "+d"]

Example 4: Masking Sensitive Data

import { mask, redact } from 'string-extn';

// Mask credit card
const cardNumber = '4532111111111111';
console.log(mask(cardNumber, 4)); // "············1111"

// Redact email patterns
const text = 'Contact [email protected] or [email protected]';
console.log(redact(text, [/@\w+\.\w+/g])); // "Contact [REDACTED] or [REDACTED]"

Example 5: URL & Filename Safe Conversion

import { slugify, filenameSafe } from 'string-extn';

console.log(slugify('Hello World! Welcome'));    // "hello-world-welcome"
console.log(slugify('Café au Lait'));            // "cafe-au-lait"
console.log(filenameSafe('File<>Name?.txt'));    // "FileName.txt"

Example 6: String Validation

import { 
  isEmail, isURL, isStrongPassword, isIPv4, 
  isPalindrome, isJSON 
} from 'string-extn';

console.log(isEmail('[email protected]'));        // true
console.log(isURL('https://example.com'));       // true
console.log(isStrongPassword('MyPass@123'));     // true
console.log(isIPv4('192.168.1.1'));             // true
console.log(isPalindrome('A man a plan a canal Panama')); // true
console.log(isJSON('{"key":"value"}'));         // true

Example 7: Emoji Handling with Unicode

import { lengthUnicode, unicodeSlice, reverseUnicode } from 'string-extn';

const message = 'Hello 👨‍👩‍👧‍👦 World 🇺🇸';

console.log(lengthUnicode(message));  // Correctly counts family emoji as 1
console.log(unicodeSlice(message, 6, 8)); // "👨‍👩‍👧‍👦 "
console.log(reverseUnicode(message)); // Preserves emoji integrity

Example 8: Internationalization and Security

import { localeCompare, normalizeUnicode, escapeHTML, sanitizePath } from 'string-extn';

console.log(localeCompare('resume', 'résumé', 'en', 'accent')); // Non-zero
console.log(normalizeUnicode('e\u0301', 'NFC')); // "\u00e9"
console.log(escapeHTML('<script>alert(1)</script>')); // Escaped HTML entities
console.log(sanitizePath('/var/../tmp')); // "/var/tmp"

Example 9: Performance and Streams

import { fastRepeat, fastPadLeft, chunkString, streamTransform } from 'string-extn';

console.log(fastRepeat('ab', 4)); // "abababab"
console.log(fastPadLeft('7', 3, '0')); // "007"

const chunks = chunkString('abcdef', 2); // ["ab", "cd", "ef"]
console.log(streamTransform(chunks, c => c.toUpperCase())); // "ABCDEF"

Example 10: Function Composition

import { compose } from 'string-extn';

const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);
const addPrefix = (s: string) => 'Hello, ' + s;
const addExclamation = (s: string) => s + '!';

const greet = compose(addExclamation, addPrefix, capitalize);
console.log(greet('world')); // "Hello, World!"

Testing

Run the Test Suite

npm test

Build the Library

npm run build

This generates compiled JavaScript in the dist/ folder.

Link Locally for Testing

# In the string-extn folder
npm link

# In your test project folder
npm link string-extn

Development Commands

npm install     # Install dependencies
npm run build   # Build the library
npm test        # Run tests
npm link        # Link for local testing

License

MIT © Balaji Katta Venkatarathnam