Releases: Zheruel/nano-string-utils
v0.28.0 - New String Utilities
New Functions
Enhanced Trimming (~270 bytes)
| Function | Description | Example |
|---|---|---|
trim | Remove custom chars from both ends | trim('///path///', '/') → 'path' |
trimStart | Remove custom chars from start | trimStart('///path', '/') → 'path' |
trimEnd | Remove custom chars from end | trimEnd('path///', '/') → 'path' |
String Masking (~200 bytes)
mask('4532123456789010') // '************9010' mask('john@example.com', { showStart: true }) // 'john************' mask('secret', { maskChar: '•' }) // '••cret'Word Wrapping (~190 bytes)
wrap('Hello world, how are you today?', 15) // 'Hello world,\nhow are you\ntoday?'Bundle Size
| Bundle | Size | Limit |
|---|---|---|
| ESM | 9.63 KB | 12 KB ✅ |
| CJS | 10.3 KB | 12.5 KB ✅ |
Full Changelog
https://github.com/Zheruel/nano-string-utils/blob/main/CHANGELOG.md#0280---2026-01-23
v0.27.0 - Node.js 20+ Requirement
Breaking Change
Minimum Node.js version is now 20 (Node 18 reached EOL in April 2025)
What's Changed
Dependencies Updated
- vitest 3.2.4 → 4.0.17
- tinybench 5.0.1 → 6.0.0
- size-limit 11.2.0 → 12.0.0
- @types/node 24.5.0 → 25.0.8
- vite 7.1.7 → 7.3.1 (docs-src)
- Plus 8 other dependency updates
CI/CD
- GitHub Actions updated to v6 (checkout, upload-artifact)
- CI now tests on Node.js 20, 22, and 24
Verification
- ✅ All 1516 tests pass
- ✅ Bundle size: 9.25 KB ESM / 9.91 KB CJS
- ✅ Zero vulnerabilities
Full Changelog: v0.26.0...v0.27.0
v0.26.0 - New Utility Functions
New Functions
This release adds 3 new utility functions, bringing the total to 55 functions.
isBlank(str) (~70 bytes)
Check if a string is empty or contains only whitespace.
isBlank('') // true isBlank(' ') // true isBlank('\t\n') // true isBlank('hello') // falseUse cases: Form validation, content presence checks, filtering empty values.
unescapeHtml(str) (~160 bytes)
Decode HTML entities back to their original characters. Complements escapeHtml().
unescapeHtml('<div>') // '<div>' unescapeHtml('Hello & World') // 'Hello & World' unescapeHtml('"quoted"') // '"quoted"'Supported entities: &, <, >, ", ', '
Roundtrip guarantee: unescapeHtml(escapeHtml(str)) === str
countSubstrings(str, sub) (~80 bytes)
Count non-overlapping occurrences of a substring.
countSubstrings('hello hello hello', 'hello') // 3 countSubstrings('ababa', 'aba') // 1 (non-overlapping) countSubstrings('banana', 'a') // 3Use cases: Text analysis, search result counts, log parsing.
Installation
npm install nano-string-utils# Deno / JSR deno add jsr:@zheruel/nano-string-utilsFull Changelog
https://github.com/Zheruel/nano-string-utils/blob/main/CHANGELOG.md
v0.25.0 - Enhanced Email Validation
Enhanced Email Validation with Apostrophe and International Character Support
This release significantly improves email validation to handle real-world email addresses more accurately.
✨ Key Features
- Apostrophe Support (Default): Emails like
o'connor@example.comandd'angelo@test.conow validate correctly - International Characters (Opt-in): Added
allowInternationaloption for Unicode email support (e.g.,josé@example.com,müller@domain.de) - Full Branded Type Integration: Updated
isValidEmail(),toEmail(), andassertEmail()with options support - TypeScript Overload Signatures: Better IDE autocomplete for
assertEmail()
⚠️ Breaking Changes
Apostrophes (') are now allowed by default in email addresses. This makes the validator more permissive to handle real-world names like O'Connor, D'Angelo, etc.
- Before:
isEmail("o'connor@example.com")→false - After:
isEmail("o'connor@example.com")→true
International characters remain rejected by default (opt-in only via { allowInternational: true }).
🧪 Testing
- 13+ new comprehensive tests
- 1,484 total tests passing
- 100% test coverage maintained
- Code quality review: 8.5/10 rating
📦 Bundle Size
- Minimal impact: ~30 bytes added
- ESM: 9.14 KB (well under 12 KB limit)
📖 Usage Examples
```typescript
// Apostrophes work by default
isEmail("o'connor@example.com") // true
// International characters require opt-in
isEmail("josé@example.com") // false
isEmail("josé@example.com", { allowInternational: true }) // true
// Branded types support options
const email = toEmail("müller@domain.de", { allowInternational: true })
assertEmail("user@café.com", { allowInternational: true })
```
Fixes: #57
Full Changelog: https://github.com/Zheruel/nano-string-utils/blob/main/CHANGELOG.md
v0.24.0 - Integer Validation & Enhanced Consistency
🎉 What's New
New Function: isInteger()
Validates if a string represents an integer value (whole number without decimals).
isInteger('42') // true isInteger('-17') // true isInteger('3.14') // false - rejects decimals isInteger('42.0') // false - rejects .0 suffix isInteger(' 42 ') // true - automatic trimmingKey Features:
- Handles positive and negative integers
- Rejects decimal numbers (key difference from
isNumeric) - Full branded type system integration (
IntegerString) - CLI support:
nano-string isInteger "42" - Bundle size: 120 bytes gzipped
- 80+ test scenarios
Use Cases:
- Age validation
- Pagination parameters (page, limit, offset)
- Database ID validation
- E-commerce quantities
- Form input processing
Enhanced Whitespace Handling
Updated 6 validation functions to consistently trim leading/trailing whitespace:
isASCII,isAlphanumeric,isEmail,isHexColor,isUUID,isUrl
This quality-of-life improvement handles common user input patterns like " user@email.com ".
Code Consistency Improvements
- Standardized variable naming across all validation functions
- All functions now use
const trimmed = str.trim()pattern - More explicit code that avoids parameter mutation
- Better maintainability
📊 Stats
- Function count: 51 → 52 utilities
- Bundle size: 9.05 KB ESM / 9.69 KB CJS (within limits)
- Test coverage: 100% maintained (1465 tests passing)
📦 Installation
npm install nano-string-utils@0.24.0Full changelog: https://github.com/Zheruel/nano-string-utils/blob/main/CHANGELOG.md#0240---2025-11-07
v0.23.0 - Add Three New Validation Functions
Added
New Validation Functions
-
isNumeric()- Validates if a string represents a numeric value (integer or decimal)- Handles positive and negative integers (
42,-17) - Supports decimal numbers (
3.14,-0.5) - Automatic whitespace trimming
- Rejects empty strings,
Infinity, and scientific notation - Bundle size: 122 bytes gzipped
- Handles positive and negative integers (
-
isAlphanumeric()- Validates if a string contains only alphanumeric characters (a-z, A-Z, 0-9)- Strict ASCII validation (no Unicode, special characters, or whitespace)
- Perfect for username validation, identifiers, and tokens
- Bundle size: 88 bytes gzipped
-
isUUID()- Validates if a string is a valid UUID in standard 8-4-4-4-12 format- Supports all UUID versions (v1-v5)
- Accepts NIL UUID (
00000000-0000-0000-0000-000000000000) - Case-insensitive validation
- Bundle size: 89 bytes gzipped
Branded Type Integration
Full type-safe handling for all three validation functions:
- New branded types:
NumericString,AlphanumericString,UUID - Type guards:
isValidNumeric(),isValidAlphanumeric(),isValidUUID() - Builder functions:
toNumericString(),toAlphanumericString(),toUUID() - Assertion functions:
assertNumericString(),assertAlphanumericString(),assertUUID() - Unsafe casts:
unsafeNumericString(),unsafeAlphanumericString(),unsafeUUID() - Zero runtime overhead - type safety enforced at compile time
CLI Support
All three functions available via `nano-string` command:
- `nano-string isNumeric "42"`
- `nano-string isAlphanumeric "user123"`
- `nano-string isUUID "550e8400-e29b-41d4-a716-446655440000"`
Documentation
- Updated function count from 48 to 51 utilities
- Added comprehensive JSDoc documentation with real-world usage examples
- Updated README with function descriptions, examples, and bundle sizes
- Regenerated bundle size and performance benchmark data
📦 Installation: `npm install nano-string-utils`
📚 Documentation: https://zheruel.github.io/nano-string-utils/
v0.22.0 - Enhanced Unicode Support
Enhanced Unicode Support for reverse() and truncate()
Improved
- Production-grade grapheme cluster handling for both
reverse()andtruncate()functions- ZWJ (Zero-Width Joiner) emoji sequences preserved: family emojis (👨👩👧👦), flags (🏴☠️, 🇺🇸), professions (👨⚕️, 👩🚀)
- Emoji with skin tone modifiers correctly handled (👍🏽, 👋🏾)
- Diacritics and combining marks preserved (café, Malmö, naïve, decomposed Unicode)
- ASCII fast-path optimization maintains performance for simple strings (no performance regression)
Performance
- Minimal bundle size impact for significant correctness improvement
reverse(): 67B → 307B (+240B for full Unicode support)truncate(): 226B → 477B (+251B for full Unicode support)- Total bundle: 8.99 KB → 8.92 KB (slight decrease due to optimizations)
- ASCII strings maintain original performance through fast-path checks
Test Coverage
- 26 new comprehensive test cases
- 11 tests for
reverse()covering ZWJ sequences, skin tones, diacritics, and mixed content - 15 tests for
truncate()covering grapheme boundaries, emoji preservation, and edge cases - 100% code coverage maintained across all functions
- 11 tests for
Documentation
- Updated JSDoc examples to demonstrate Unicode handling capabilities
- Enhanced documentation site with Unicode examples
- Regenerated benchmark data reflecting new bundle sizes
v0.21.0 - isHexColor validation function
Added
-
New Function:
isHexColor()- Validates hexadecimal color codes with comprehensive format support- Supports 3-digit (
#fff), 6-digit (#ffffff), 4-digit with alpha (#fff8), and 8-digit with alpha (#ffffff80) formats - Case-insensitive validation for all formats
- Pre-compiled regex for optimal performance
- Bundle size: 118 bytes raw, 103 bytes gzipped
- 100% test coverage with 32 test cases
- Use cases: design systems, theme validation, color picker validation, form validation
- Supports 3-digit (
-
Branded Type Integration for HexColor - Full type-safe color handling
- New
HexColorbranded type for compile-time safety - Type guard:
isValidHexColor()for type narrowing - Builder function:
toHexColor()returnsHexColor | nullwith validation - Assertion function:
assertHexColor()throwsBrandedTypeErroron invalid input - Unsafe cast:
unsafeHexColor()for trusted input (no validation) - Integrates seamlessly with existing branded type system
- New
Improved
- Benchmark Infrastructure - Enhanced function extraction for more accurate metrics
- Added exclusion list for 26 branded type system helpers
- Separates core utilities (49 functions) from type system infrastructure
- Prevents metric inflation in bundle size and performance benchmarks
- More accurate representation of library capabilities
- Better comparison with other libraries (lodash, es-toolkit)
Documentation
- Updated total function count from 48 to 49 core utilities
- Added
isHexColorto documentation site with interactive playground examples - Updated bundle size references to accurately reflect package size (< 12KB)
- Regenerated benchmark data with new function
Full Changelog: v0.20.0...v0.21.0
v0.20.0 - SafeHTML, TypeScript Strict Mode Fixes & Enhanced Documentation
Summary
This release introduces type-safe XSS prevention with the new SafeHTML branded type, fixes TypeScript strict mode violations, improves documentation with comprehensive examples, and streamlines benchmark reporting by replacing markdown files with JSON data for the interactive documentation site.
Changes
New Features
SafeHTML Branded Type - Compile-Time XSS Prevention
Added a new branded type SafeHTML that provides compile-time protection against XSS attacks:
toSafeHTML()- Builder function with opinionated secure defaults:- Strips all HTML by default for maximum security
- Removes script tags and dangerous content
- Removes non-printable characters
- Optional configuration to allow specific safe tags
unsafeSafeHTML()- Bypass for trusted input (use with caution)- Zero runtime overhead - Type safety enforced at compile time
- 11 comprehensive tests covering all sanitization scenarios
- Integrates seamlessly with existing branded types (Email, URL, Slug)
Branded Type Pattern Documentation
Added comprehensive documentation for extending the library with custom branded types:
- "Extending with Custom Branded Types" section in README
- Examples showing how to create domain-specific types (PhoneNumber, PostalCode, CreditCard)
- Demonstrates type-safe constructors and validation patterns
- Shows composability with built-in branded types
Enhanced JSDoc Examples
Improved developer experience with real-world examples across 20+ functions:
- All examples use proper ```ts code blocks for syntax highlighting
- Practical use cases: form validation, search normalization, file naming, etc.
- Functions enhanced:
capitalize,codePoints,deburr,detectScript,escapeHtml,graphemes,hashString,pad,padEnd,padStart,pluralize,randomString,reverse,singularize,smartSplit,stripHtml,toASCII
Bug Fixes
TypeScript Strict Mode Compliance
Resolved all TypeScript violations related to noUncheckedIndexedAccess:
- Added non-null assertions for guaranteed valid array access in
levenshtein,pad,fuzzyMatch,smartSplit - Fixed
randomStringto handle empty charset edge case with early return - Zero runtime cost - all assertions validated by algorithm guarantees
- All 1207 tests passing
Infrastructure Changes
Bundle Size Adjustments
Updated size limits to accommodate new SafeHTML feature while maintaining reasonable constraints:
- ESM: 9.1 KB → 9.5 KB (+400 bytes headroom)
- CJS: 9.5 KB → 10 KB (+500 bytes headroom)
- Current actual size: 8.84 KB ESM / 9.36 KB CJS (well under limits)
- SafeHTML adds ~500 bytes for compile-time XSS prevention
Benchmark Reporting Improvements
Streamlined benchmark output for better integration with documentation site:
- Removed:
benchmark-results.mdandbundle-size-results.mdmarkdown files - Kept:
bundle-sizes.jsonandperformance-benchmarks.jsonfor programmatic access - Updated
bundle-size.tsto generate JSON-only output - JSON files copied to
docs-src/public/for serving in interactive docs - Cleaner output with summary statistics in console
Documentation Updates
- CHANGELOG.md: Complete v0.20.0 release notes with categorized changes
- README.md:
- Added branded type extension guide with examples
- Updated benchmark instructions to reflect new workflow
- Linked to interactive benchmark viewer on documentation site
- Updated bundle size limits in documentation
Testing
- All 1207 tests passing
- Added 11 new tests for SafeHTML functionality
- Bundle size validation passing
- TypeScript strict mode compilation successful
Security Considerations
The SafeHTML branded type provides an additional layer of security for applications that need to handle user-generated content. By enforcing sanitization at the type level, it helps prevent XSS vulnerabilities by making it impossible to use unsanitized strings where safe HTML is expected.
Breaking Changes
None. This release is fully backward compatible.
v0.19.1: Enhanced NPM Discoverability
Changed
- Package Metadata - Enhanced NPM discoverability
- Expanded description to highlight key features: "49 tree-shakeable string utilities with zero dependencies. TypeScript-first, <1KB per function. Case conversion, validation, sanitization, fuzzy matching & more."
- Increased keywords from 9 to 20 for better search visibility
- Added targeted keywords:
string-manipulation,text-processing,case-conversion,kebabCase,pascalCase,email-validation,url-validation,fuzzy-match,levenshtein,sanitize,tree-shakeable,micro - Improved package findability for common use cases and search queries
Full Changelog: https://github.com/Zheruel/nano-string-utils/blob/main/CHANGELOG.md