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

lex-module

v1.3.2

Published

A comprehensive JavaScript string manipulation library with fluent API

Readme

lex-module

A lightweight, chainable JavaScript string manipulation library with comprehensive text processing capabilities.

Features

  • Chainable API: Fluent method chaining for elegant string operations
  • Comprehensive Methods: 54+ string manipulation utilities
  • Input Validation: Built-in validation for robust error handling
  • Zero Dependencies: Pure JavaScript implementation
  • Well Tested: Comprehensive test suite with Mocha (529+ tests)
  • HTML-Safe Truncation: Smart text truncation that preserves HTML structure
  • Smart Truncation: Word boundary truncation for better readability
  • Comprehensive Validation: Email, IP, phone number, and date validation
  • Modular Architecture: Well-organized source code in 15 functional modules

Project Structure

The library has been refactored into a modular architecture for better maintainability:

src/
  core/           # Core string operations (length, split, toString, duplicate, inverse, trim)
  case/           # Case manipulation (uppercase, lowercase, ucFirst, capitalize)
  search/         # Search and truncation (startsWith, endsWith, contains, truncate, truncateRight, truncateWithTags, smartTruncate)
  words/          # Word operations (words, wordsCount, wordsFreq, firstWord, lastWord, randomWord, randomizeWords, acronym)
  comparison/     # String comparison (compareByChar, compareByWord)
  replace/        # Replacement (replace, replaceFirst, compile)
  html/           # HTML handling (stripTags, isHtml, highlight)
  url/            # URL parsing (isUrl, urlScheme, urlDomain, urlRoute, queryParams, slug)
  path/           # File path operations (baseFileName, pathToFile, toFileNameWithExtension, fileExtension)
  validation/     # Validation (isNumeric, isInt, isJSON, validEmail, validIP, validPhoneNumber, validDate)
  random/         # Random generation (randomLetter, randomChars, insertTypo)
  text/           # Text utilities (sentences, lines)
  counting/       # Character counting (lettersCount, digitsCount, punctuationCount, emailsCount, ipCount, urlCount)
  crypto/         # Cryptographic (hash, hashEquals)
  distance/       # Distance calculation (levenstain)
  StringObj.js    # Main class that composes all modules
  index.js        # Entry point

test/             # Test files mirroring src/ structure (529+ tests)

Key Design Principles

  • Composability: The main StringObj class inherits from StringCore and mixes in methods from 14 functional modules
  • Backward Compatibility: All methods work exactly as before; the public API remains unchanged
  • Testability: Each module has its own test file, enabling focused unit testing

Installation

npm install lex-module

Or with yarn:

yarn add lex-module

Bundle Formats

The library is distributed in multiple formats for maximum compatibility:

  • CommonJS (dist/lex-module.cjs.js) - For Node.js and older bundlers
  • ES Modules (dist/lex-module.mjs) - For modern bundlers (webpack, rollup, esbuild)
  • UMD (dist/lex-module.umd.js) - For direct browser usage via CDN

Minified versions are also available:

  • dist/lex-module.cjs.min.js (~12 KB)
  • dist/lex-module.mjs.min.js (~12 KB)
  • dist/lex-module.umd.min.js (~13 KB)

75% size reduction from the original unminified version!

CDN Usage

You can use the library directly in browsers via CDN:

<!-- Using unpkg -->
<script src="https://unpkg.com/lex-module@latest/dist/lex-module.umd.min.js"></script>

<!-- Using jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/lex-module@latest/dist/lex-module.umd.min.js"></script>

<script>
  const result = LexModule('hello world').uppercase().toString();
  console.log(result); // "HELLO WORLD"
</script>

Quick Start

const str = require('lex-module');

// Basic usage
const result = str('hello world')
  .uppercase()
  .replace('WORLD', 'Universe')
  .toString();

console.log(result); // "HELLO UNIVERSE"

// Method chaining
const text = str('  the quick brown fox  ')
  .trim()
  .capitalize()
  .words();
  // Returns: ['The', 'Quick', 'Brown', 'Fox']

API Reference

String Transformation

uppercase()

Converts the entire string to uppercase.

str('hello world').uppercase(); // "HELLO WORLD"

lowercase()

Converts the entire string to lowercase.

str('HELLO WORLD').lowercase(); // "hello world"

ucFirst()

Capitalizes only the first character of the string.

str('hello world').ucFirst(); // "Hello world"

capitalize()

Capitalizes the first character of each word.

str('hello world').capitalize(); // "Hello World"

inverse()

Reverses the string character by character.

str('hello').inverse(); // "olleh"

duplicate()

Duplicates the string content.

str('hello').duplicate(); // "hellohello"

Search and Match

startsWith(needle)

Checks if the string starts with the specified substring.

str('hello world').startsWith('hello'); // true
str('hello world').startsWith('world'); // false

endsWith(needle)

Checks if the string ends with the specified substring.

str('hello world').endsWith('world'); // true
str('hello world').endsWith('hello'); // false

contains(needle)

Checks if the string contains the specified substring.

str('hello world').contains('world'); // true
str('hello world').contains('foo'); // false

Replacement

replace(from, to)

Replaces all occurrences of a pattern or array of patterns. Supports both string and array parameters.

// Simple replacement
str('hello world').replace('world', 'universe'); // "hello universe"

// Array replacement
str('one two three').replace(['one', 'two'], ['1', '2']); // "1 2 three"

// Multiple replacements with arrays
str('The village was not so large')
  .replace(['village', 'not '], ['town', '']); // "The town was so large"

Throws: Error if from parameter is undefined/null or if to parameter is undefined.

replaceFirst(from, to)

Replaces only the first occurrence of a pattern or array of patterns.

str('one two one').replaceFirst('one', '1'); // "1 two one"

// Array replacement
str('The village was not so large. The village was small.')
  .replaceFirst(['village', 'not '], ['town', '']); // "The town was so large. The village was small."

Throws: Error if from parameter is undefined/null or if to parameter is undefined.

compile(params, template)

Replaces wildcards in the string with values from a params object.

// Default template {key}
str('Hello {name}, you are {age} years old')
  .compile({ name: 'John', age: 30 }); // "Hello John, you are 30 years old"

// Custom template
str('Hello #{name}').compile({ name: 'World' }, /#\{(\w*)\}/g); // "Hello World"

// Handles missing params gracefully
str('Hello {name}').compile({}); // "Hello {name}"

Parameters:

  • params (Object): Key-value pairs for replacement
  • template (RegExp, optional): Custom regex template (default: /\{(\w*)\}/g)

Throws: Error if params is null or not an object.

Text Analysis

words()

Extracts all words from the string as an array of lowercase strings.

str('Hello, World! This is a Test.').words();
// Returns: ['hello', 'world', 'this', 'is', 'a', 'test']

wordsCount()

Returns the number of words in the string.

str('Hello world').wordsCount(); // 2

wordsFreq()

Returns word frequency analysis as a two-element array: [words, frequencies].

str('hello world hello').wordsFreq();
// Returns: [['hello', 'world'], [2, 1]]

sentences()

Splits the string into an array of sentences.

str('First sentence. Second one! What about third?').sentences();
// Returns: ['First sentence.', 'Second one!', 'What about third?']

lines()

Splits the string into an array of lines using various line ending formats.

str('line1\nline2\nline3').lines(); // ['line1', 'line2', 'line3']
str('line1\r\nline2\r\nline3').lines(); // ['line1', 'line2', 'line3'] (Windows)
str('line1\rline2\rline3').lines(); // ['line1', 'line2', 'line3'] (old Mac)
str('line1\n\nline2').lines(); // ['line1', '', 'line2'] (empty lines preserved)

Note: This is a getter method that returns an array directly (not this for chaining). Supports Unix (\n), Windows (\r\n), and old Mac (\r) line endings.

lettersCount()

Counts the number of letter characters (a-z, A-Z) in the string.

str('hello world').lettersCount(); // 10
str('ABC-123-XYZ').lettersCount(); // 6

Note: Only ASCII letters are counted. International characters (accents, Cyrillic, etc.) are not included.

digitsCount()

Counts the number of digit characters (0-9) in the string.

str('hello123world').digitsCount(); // 3
str('ABC-123-XYZ').digitsCount(); // 3

Note: Only ASCII digits are counted.

punctuationCount()

Counts the number of ASCII punctuation characters in the string.

str('Hello, World!').punctuationCount(); // 2
str('arr[i]++;').punctuationCount(); // 5

Note: Counts ASCII punctuation: !"#$%&'()*+,-./:;<=>?@[]^_`{|}~

emailsCount()

Counts the number of email addresses in the string.

str('Contact us at [email protected]').emailsCount(); // 1
str('[email protected] and [email protected]').emailsCount(); // 2

ipCount()

Counts the number of IP addresses (IPv4 and IPv6) in the string.

str('Server: 192.168.1.1').ipCount(); // 1
str('IPv4: 192.168.1.1, IPv6: ::1').ipCount(); // 2

Note: Supports IPv4 (xxx.xxx.xxx.xxx) and IPv6 formats including mixed notation.

urlCount()

Counts the number of URLs (with http/https/www prefix) in the string.

str('Visit http://example.com').urlCount(); // 1
str('www.google.com and https://github.com').urlCount(); // 2

Note: Only counts URLs with scheme (http://, https://) or www prefix.

length()

Returns the length of the string.

str('hello').length(); // 5

acronym()

Creates an acronym by taking the first letter of each word.

str('Hello World').acronym(); // 'HW'
str('JavaScript Object Notation').acronym(); // 'JON'
str('Hyper Text Markup Language').acronym(); // 'HTML'
str('3D Studio Max').acronym(); // '3DSM' (numbers included)
str('C++ Programming').acronym(); // 'CP' (special chars skipped)

Note: This is a getter method that returns a string directly (not this for chaining). Only ASCII alphanumeric characters are supported; international characters are skipped. The previous typo acronim() is kept as a backward-compatible alias.

isNumeric()

Checks if the string represents a numeric value (integer or float).

str('123').isNumeric(); // true
str('-123.45').isNumeric(); // true
str('123.').isNumeric(); // true (trailing decimal allowed)
str('.5').isNumeric(); // false (leading decimal not allowed)
str('1e10').isNumeric(); // false (scientific notation not supported)

Throws: Error if input is null or undefined

isInt()

Checks if the string represents an integer value (no decimal points).

str('123').isInt(); // true
str('-123').isInt(); // true
str('123.45').isInt(); // false (has decimal point)
str('123.').isInt(); // false (trailing decimal not allowed)
str('0').isInt(); // true
str('-0').isInt(); // true

Throws: Error if input is null or undefined

Note: This validates the string format, not that the number is safely representable in JavaScript. Numbers exceeding Number.MAX_SAFE_INTEGER will return true but lose precision when parsed.

isJSON()

Checks if the string contains valid JSON data.

str('{"name":"John","age":30}').isJSON(); // true
str('[1,2,3]').isJSON(); // true
str('"hello"').isJSON(); // true (JSON string)
str('true').isJSON(); // true (JSON boolean)
str('null').isJSON(); // true (JSON null)
str('{name:"John"}').isJSON(); // false (missing quotes around keys)
str('').isJSON(); // false (empty string)

Throws: Error if input is null or undefined

validEmail()

Validates if the string is a properly formatted email address.

str('[email protected]').validEmail(); // true
str('[email protected]').validEmail(); // true
str('[email protected]').validEmail(); // true (dots in local part)
str('[email protected]').validEmail(); // true (plus sign in local part)
str('[email protected]').validEmail(); // true (hyphen in local part)
str('[email protected]').validEmail(); // true (subdomains)

str('invalid-email').validEmail(); // false
str('user@').validEmail(); // false (missing domain)
str('@example.com').validEmail(); // false (missing local part)
str('[email protected]').validEmail(); // false (domain starts with dot)
str('user@domain').validEmail(); // false (missing TLD)
str('[email protected]').validEmail(); // false (double dots in domain)

Throws: Error if input is null or undefined

Note: This validates email format, not that the email actually exists. The regex pattern is intentionally permissive to accommodate most valid email formats.

validIP()

Validates if the string is a valid IPv4 or IPv6 address.

// IPv4 addresses
str('192.168.1.1').validIP(); // true
str('10.0.0.1').validIP(); // true
str('0.0.0.0').validIP(); // true
str('255.255.255.255').validIP(); // true
str('8.8.8.8').validIP(); // true (Google DNS)

// IPv6 addresses
str('2001:0db8:85a3:0000:0000:8a2e:0370:7334').validIP(); // true (full format)
str('2001:db8:85a3:0:0:8a2e:370:7334').validIP(); // true (leading zeros omitted)
str('2001:db8:85a3::8a2e:370:7334').validIP(); // true (compressed)
str('::1').validIP(); // true (localhost)
str('::ffff:192.0.2.1').validIP(); // true (mixed IPv4/IPv6)

// Invalid addresses
str('256.1.2.3').validIP(); // false (octet > 255)
str('192.168.1').validIP(); // false (missing octet)
str('192.168.01.1').validIP(); // false (leading zero)
str('gggg::1').validIP(); // false (invalid hex)

Throws: Error if input is null or undefined

Note:

  • IPv4: Each octet must be 0-255, no leading zeros allowed (except '0' itself)
  • IPv6: Supports full format, compressed (::), and mixed IPv4/IPv6 notation

validPhoneNumber()

Validates if the string is a valid international phone number. Permissive validation focusing on digit count (7-15 digits).

// US/Canada numbers
str('+1 (555) 123-4567').validPhoneNumber(); // true
str('1-555-123-4567').validPhoneNumber(); // true
str('(555) 123-4567').validPhoneNumber(); // true
str('555-123-4567').validPhoneNumber(); // true

// European numbers
str('+44 20 7123 4567').validPhoneNumber(); // true (UK)
str('+33 1 23 45 67 89').validPhoneNumber(); // true (France)
str('+49 30 12345678').validPhoneNumber(); // true (Germany)

// Asian numbers
str('+86 10 1234 5678').validPhoneNumber(); // true (China)
str('+81 3 1234 5678').validPhoneNumber(); // true (Japan)

// Invalid numbers
str('123').validPhoneNumber(); // false (too short)
str('abc-def-ghij').validPhoneNumber(); // false (contains letters)
str('111-111-1111').validPhoneNumber(); // false (all same digits)

Throws: Error if input is null or undefined

Note: This is a basic permissive validator (7-15 digits). For production use with strict validation, consider using a dedicated library like libphonenumber-js or google-libphonenumber.

validDate()

Validates if the string is a valid date and checks for logical validity. Supports multiple date formats.

// ISO 8601 format (YYYY-MM-DD)
str('2024-01-15').validDate(); // true
str('2020-02-29').validDate(); // true (leap year)
str('2000-02-29').validDate(); // true (leap year divisible by 400)

// US format (MM/DD/YYYY)
str('01/15/2024').validDate(); // true
str('12/31/2024').validDate(); // true
str('02/29/2020').validDate(); // true (leap year)

// European format (DD/MM/YYYY)
str('15/01/2024').validDate(); // true
str('31/12/2024').validDate(); // true
str('29/02/2020').validDate(); // true (leap year)

// Short year formats
str('01/01/24').validDate(); // true (2024)
str('01/01/50').validDate(); // true (1950)

// Invalid dates - date rollover
str('2024-02-30').validDate(); // false (February never has 30 days)
str('2024-02-31').validDate(); // false (February never has 31 days)
str('2024-04-31').validDate(); // false (April has only 30 days)

// Invalid dates - non-leap year February 29
str('2023-02-29').validDate(); // false (2023 is not a leap year)
str('1900-02-29').validDate(); // false (1900 is not leap year)

// Invalid dates - impossible values
str('2024-13-01').validDate(); // false (month 13 doesn't exist)
str('2024-01-00').validDate(); // false (day 0 doesn't exist)
str('2024-01-32').validDate(); // false (day 32 doesn't exist)

Throws: Error if input is null or undefined

Note: Supported formats include ISO 8601 (YYYY-MM-DD), US format (MM/DD/YYYY), European format (DD/MM/YYYY), and short year formats (YY/MM/DD, DD/MM/YY). Validates leap years, month boundaries, and days per month correctly.

Manipulation

truncate(length, start)

Truncates the string to specified length from an optional start position.

str('hello world').truncate(5); // "hello"
str('hello world').truncate(5, 6); // "world"
str('hello world').truncate(7, 3); // "lo worl"

truncateRight(count)

Truncates the string by removing the specified number of characters from the right side.

str('hello world').truncateRight(5); // "hello "
str('filename.txt').truncateRight(4); // "filename"
str('document.pdf').truncateRight(4); // "document"
str('test').truncateRight(4); // "" (remove entire string)
str('test').truncateRight(0); // "test" (keep entire string)

Parameters:

  • count (Number): The number of characters to remove from the right (must be >= 0)

Throws: Error if count is not provided or is invalid

smartTruncate(maxLength, append)

Truncates the string at word boundaries for better readability. Avoids cutting words in half.

str('Hello world test').smartTruncate(8); // "Hello..."
str('The quick brown fox').smartTruncate(10); // "The..."
str('Hello world test').smartTruncate(8, ' [more]'); // "Hello [more]"
str('Short').smartTruncate(10); // "Short" (no truncation needed)

Parameters:

  • maxLength (Number): Maximum length of truncated string (excluding append string)
  • append (String, optional): String to append when truncation occurs (default: '...')

Throws: Error if maxLength is not provided or is invalid

truncateWithTags(maxLength)

Truncates the string while preserving HTML/XML tag structure. Ensures all opened tags are properly closed.

str('<p>Hello world</p>').truncateWithTags(7); // "<p>Hello...</p>"
str('<div><span>Text</span></div>').truncateWithTags(4); // "<div><span>Text</span></div>"
str('<p><strong>Bold text</strong></p>').truncateWithTags(6); // "<p><strong>Bold...</strong></p>"
str('<p>Text<br/>more</p>').truncateWithTags(4); // "<p>Text...</p>"

Parameters:

  • maxLength (Number): Maximum length of truncated string (excluding closing tags)

Throws: Error if maxLength is not provided or is invalid

Note: Does not sanitize HTML. Sanitize user-supplied content first to prevent XSS attacks.

split(delimiter)

Splits the string by the specified delimiter.

str('a,b,c').split(','); // ['a', 'b', 'c']

randomizeWords()

Randomly shuffles the words in the string.

const result = str('hello world test').randomizeWords();
// Possible result: "test world hello"

insertTypo()

Inserts a random typo into the string (useful for testing fuzzy search).

const result = str('hello').insertTypo();
// Possible result: "hlelo", "ehllo", "helo", etc.

HTML Processing

stripTags()

Removes all HTML/XML tags from the string.

str('<p>Hello <b>world</b>!</p>').stripTags(); // "Hello world!"

isHtml()

Checks if the string contains HTML tags.

str('<p>Hello</p>').isHtml(); // true
str('Hello world').isHtml(); // false

highlight(words, template)

Highlights specified words in the string using a template.

// Default highlighting
str('hello world').highlight('world'); // "hello <mark>world</mark>"

// Custom template
str('hello world').highlight('world', '<span class="hl">$&</span>');
// "hello <span class="hl">world</span>"

// Multiple words
str('hello world test').highlight(['hello', 'test']);
// "<mark>hello</mark> world <mark>test</mark>"

URL Processing

isUrl()

Checks if the string is a valid URL.

str('https://example.com').isUrl(); // true
str('example.com').isUrl(); // true
str('not a url').isUrl(); // false

urlScheme()

Extracts the URL scheme (http, https).

str('https://example.com').urlScheme(); // "https"
str('http://example.com').urlScheme(); // "http"
str('example.com').urlScheme(); // null

urlDomain()

Extracts the domain from the URL.

str('https://example.com').urlDomain(); // "example.com"
str('http://sub.example.com').urlDomain(); // "sub.example.com"

urlRoute()

Extracts the route/path from the URL.

str('https://example.com/path/to/resource').urlRoute(); // "/path/to/resource"
str('http://example.com/').urlRoute(); // "/"

queryParams()

Extracts query parameters from a URL string.

str('https://example.com?name=John&age=30').queryParams();
// Returns: { name: 'John', age: '30' }

// Handles arrays
str('https://example.com?name[]=John&name[]=Doe').queryParams();
// Returns: { name: ['John', 'Doe'] }

// Handles multiple same keys
str('https://example.com?name=John&name=Doe').queryParams();
// Returns: { name: ['John', 'Doe'] }

// Handles encoded characters
str('https://example.com?name=John%20Doe').queryParams();
// Returns: { name: 'John Doe' }

File Operations

fileExtension()

Extracts the file extension from a filename or path.

str('example.txt').fileExtension(); // "txt"
str('archive.tar.gz').fileExtension(); // "gz"
str('path/to/file.js').fileExtension(); // "js"
str('image.png?width=200').fileExtension(); // "png"
str('noextension').fileExtension(); // null

Note: The previous typo fileExtention() is kept as a backward-compatible alias.

baseFileName()

Extracts the base filename from a file path, removing both the directory path and file extension.

str('/path/to/file.txt').baseFileName(); // "file"
str('C:\\Users\\John\\document.pdf').baseFileName(); // "document"
str('/path/to/.gitignore').baseFileName(); // ".gitignore"
str('archive.tar.gz').baseFileName(); // "archive"
str('/path/to/').baseFileName(); // "" (trailing slash, empty filename)

Throws: Error if input is null or undefined

pathToFile()

Extracts the directory path from a file path, removing the filename and extension.

str('/path/to/file.txt').pathToFile(); // "/path/to"
str('C:\\Users\\John\\document.pdf').pathToFile(); // "C:\\Users\\John"
str('relative/path/to/image.png').pathToFile(); // "relative/path/to"
str('file.txt').pathToFile(); // "" (no directory path)
str('/').pathToFile(); // "/" (root directory)
str('https://example.com/path/to/file.txt').pathToFile(); // "https://example.com/path/to"

Throws: Error if input is null or undefined

toFileNameWithExtension()

Converts strings to safe filenames with extensions, removing invalid characters.

str('My Document').toFileNameWithExtension().toString(); // 'My_Document'
str('report.pdf').toFileNameWithExtension().toString(); // 'report.pdf'
str('file:name*.txt').toFileNameWithExtension().toString(); // 'filename.txt'
str('path/to/file.txt').toFileNameWithExtension().toString(); // 'file.txt'
str('.env').toFileNameWithExtension().toString(); // '.env'
str('archive.tar.gz').toFileNameWithExtension().toString(); // 'archive.tar.gz'

Note: This is a transformer method (returns this for chaining). Removes invalid characters (< > : " / \ | ? *), replaces whitespace with underscores, and preserves file extensions. Truncates to 255 characters max. The previous typo toFileNameWithExtention() is kept as a backward-compatible alias.

Limitations: Does not validate Windows reserved device names (CON, PRN, AUX, NUL, COM1-9, LPT1-9).

Text Formatting

slug()

Converts the string to a URL-friendly slug format.

str('Hello World').slug(); // "hello-world"
str('My Very Long Sentence!').slug(); // "my-very-long-sentence"
str('CAFÉ Résumé').slug(); // "cafe-resume"
str('Test @#$% String***').slug(); // "test-string"

Throws: Error if input is null or undefined.

firstWord()

Extracts and returns the first word from the string.

str('Hello World').firstWord(); // "hello"
str('My very long sentence').firstWord(); // "my"
str('@#$% Test').firstWord(); // "test"

Throws: Error if input is null or undefined.

lastWord()

Extracts and returns the last word from the string.

str('Hello World').lastWord(); // "world"
str('My very long sentence').lastWord(); // "sentence"
str('Test @#$%').lastWord(); // "test"

Throws: Error if input is null or undefined.

Comparison

compareByChar(strToCompare)

Performs character-by-character comparison and returns an array of equal/diff objects.

str('abc').compareByChar('abc');
// Returns: [{ type: 'eq', content: 'abc' }]

str('abcxyz').compareByChar('abcpqr');
// Returns: [
//   { type: 'eq', content: 'abc' },
//   { type: 'diff', left: 'xyz', right: 'pqr' }
// ]

Conversion

toString()

Returns the current string value (useful for ending chains).

str('hello').uppercase().toString(); // "HELLO"

Chaining Examples

The library supports method chaining for complex operations:

const result = str('  the quick brown fox jumps over the lazy dog  ')
  .trim()
  .capitalize()
  .replace('fox', 'cat')
  .truncate(20)
  .toString();
// Result: "The Quick Brown Cat"
// Complex URL processing
const url = str('https://EXAMPLE.com/path/To/Resource?name=John+Doe&age=30')
  .lowercase()
  .queryParams();
// Result: { name: 'john doe', age: '30' }
// Smart truncation with HTML preservation
const html = '<p>This is a long paragraph with <strong>bold text</strong> that needs to be truncated.</p>';
const truncated = str(html).truncateWithTags(20);
// Result: "<p>This is a long...</p>"
// Word boundary truncation
const text = 'The quick brown fox jumps over the lazy dog';
const smart = str(text).smartTruncate(15);
// Result: "The quick..."
// Text processing pipeline
const text = str('  <p>Hello, WORLD!</p> This is a TEST.  ')
  .stripTags()
  .trim()
  .lowercase()
  .capitalize()
  .words();
// Result: ['Hello,', 'World', 'This', 'Is', 'A', 'Test.']

Error Handling

Recent methods include comprehensive input validation:

// replace() validation
str('test').replace(undefined, 'x'); // Throws: Error
str('test').replace(null, 'x'); // Throws: Error
str('test').replace('x', undefined); // Throws: Error

// compile() validation
str('Hello {name}').compile(null); // Throws: Error
str('Hello {name}').compile(undefined); // Throws: Error

// slug() validation
str(null).slug(); // Throws: Error
str(undefined).slug(); // Throws: Error

Testing

The library includes a comprehensive test suite. Run tests with:

npm test

Tests cover:

  • Basic string operations
  • Edge cases and error handling
  • Method chaining
  • Complex scenarios with multiple operations

Browser Support

The library uses modern JavaScript features and should work in all current browsers and Node.js versions.

License

MIT

Author

Alexey Afanasyev [email protected]

Version

Current version: 1.3.1

Changelog

v1.3.0 (January 2025)

  • New Validation Functions: Added three comprehensive validation methods
    • validIP() - IPv4 and IPv6 address validation with full format support
    • validPhoneNumber() - International phone number validation (7-15 digits)
    • validDate() - Multi-format date validation (ISO, US, European formats)
  • Enhanced Testing: Added 64 new tests (total: 498 tests)
  • Updated Documentation: Comprehensive API documentation for new validation functions
  • Input Validation: All functions include null/undefined checks and type conversion
  • Refactored Architecture: Split monolithic index.js into 15 modular source files for better maintainability
  • Bug Fixes: Fixed duplicate sentences() method and typos in method names:
    • fileExtension() (corrected from fileExtention)
    • acronym() (corrected from acronim)
    • toFileNameWithExtension() (corrected from toFileNameWithExtention)
  • Backward Compatibility: All corrected method names retain aliases for the old typos

v1.2.0 (January 2025)

  • 🚀 Major Performance Improvement: Added minified builds (75% size reduction)
  • 📦 Multiple Format Support: Now distributed in CommonJS, ES Modules, and UMD formats
  • 🌐 CDN Support: Available via unpkg and jsDelivr
  • ⚡ Tree-shakeable: Optimized for modern bundlers
  • 🔧 Build Process: Automated build with Rollup
  • ✅ 100% Backward Compatible: No breaking changes

v1.1.5

  • Added comprehensive input validation
  • Enhanced error messages

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Roadmap

The library has an extensive list of planned features (see commented TODO items in source code), including:

  • Random character and word generation
  • Hash functions and comparison
  • Email, IP, and phone validation
  • Levenshtein distance calculations
  • Advanced text comparison methods
  • Query string manipulation
  • JSON validation
  • And many more...

For a complete list of planned features, refer to the source code comments.