Package Exports
- nano-string-utils
Readme
nano-string-utils
Ultra-lightweight string utilities with zero dependencies. Tree-shakeable, fully typed, and optimized for modern JavaScript.
Features
- 🚀 Zero dependencies - No bloat, just pure functions
- 📦 < 1KB per function - Minimal bundle impact
- 🌳 Tree-shakeable - Only import what you need
- 💪 Fully typed - Complete TypeScript support
- ⚡ ESM & CJS - Works everywhere
- 🧪 100% tested - Reliable and production-ready
- 🔒 Type-safe - Written in strict TypeScript
- 📝 Well documented - JSDoc comments for all functions
Installation
From npm
npm install nano-string-utils
yarn add nano-string-utils
pnpm add nano-string-utils
From JSR
npx jsr add @zheruel/nano-string-utils
deno add @zheruel/nano-string-utils
Usage
ESM
import { slugify, camelCase, truncate } from "nano-string-utils";
slugify("Hello World!"); // 'hello-world'
camelCase("hello-world"); // 'helloWorld'
truncate("Long text here", 10); // 'Long te...'
CommonJS
const { slugify, camelCase, truncate } = require("nano-string-utils");
slugify("Hello World!"); // 'hello-world'
camelCase("hello-world"); // 'helloWorld'
truncate("Long text here", 10); // 'Long te...'
API Reference
String Transformation
template(str: string, data: Record<string, any>, options?: TemplateOptions): string
Interpolates variables in a template string.
template("Hello {{name}}!", { name: "World" }); // 'Hello World!'
template("{{user.name}} is {{user.age}}", {
user: { name: "Alice", age: 30 },
}); // 'Alice is 30'
template(
"Hello ${name}!",
{ name: "World" },
{
delimiters: ["${", "}"],
}
); // 'Hello World!'
templateSafe(str: string, data: Record<string, any>, options?: TemplateOptions): string
Interpolates variables with HTML escaping for safe output.
templateSafe("Hello {{name}}!", {
name: '<script>alert("XSS")</script>',
}); // 'Hello <script>alert("XSS")</script>!'
slugify(str: string): string
Converts a string to a URL-safe slug.
slugify("Hello World!"); // 'hello-world'
slugify(" Multiple Spaces "); // 'multiple-spaces'
camelCase(str: string): string
Converts a string to camelCase.
camelCase("hello world"); // 'helloWorld'
camelCase("hello-world"); // 'helloWorld'
camelCase("hello_world"); // 'helloWorld'
snakeCase(str: string): string
Converts a string to snake_case.
snakeCase("hello world"); // 'hello_world'
snakeCase("helloWorld"); // 'hello_world'
snakeCase("hello-world"); // 'hello_world'
kebabCase(str: string): string
Converts a string to kebab-case.
kebabCase("hello world"); // 'hello-world'
kebabCase("helloWorld"); // 'hello-world'
kebabCase("hello_world"); // 'hello-world'
pascalCase(str: string): string
Converts a string to PascalCase.
pascalCase("hello world"); // 'HelloWorld'
pascalCase("hello-world"); // 'HelloWorld'
pascalCase("hello_world"); // 'HelloWorld'
constantCase(str: string): string
Converts a string to CONSTANT_CASE.
constantCase("hello world"); // 'HELLO_WORLD'
constantCase("helloWorld"); // 'HELLO_WORLD'
constantCase("hello-world"); // 'HELLO_WORLD'
constantCase("XMLHttpRequest"); // 'XML_HTTP_REQUEST'
dotCase(str: string): string
Converts a string to dot.case.
dotCase("hello world"); // 'hello.world'
dotCase("helloWorld"); // 'hello.world'
dotCase("hello-world"); // 'hello.world'
dotCase("XMLHttpRequest"); // 'xml.http.request'
dotCase("com/example/package"); // 'com.example.package'
capitalize(str: string): string
Capitalizes the first letter of a string and lowercases the rest.
capitalize("hello world"); // 'Hello world'
capitalize("HELLO"); // 'Hello'
reverse(str: string): string
Reverses a string.
reverse("hello"); // 'olleh'
reverse("world"); // 'dlrow'
deburr(str: string): string
Removes diacritics/accents from Latin characters.
deburr("café"); // 'cafe'
deburr("naïve"); // 'naive'
deburr("Bjørn"); // 'Bjorn'
deburr("São Paulo"); // 'Sao Paulo'
deburr("Müller"); // 'Muller'
titleCase(str: string, options?: { exceptions?: string[] }): string
Converts a string to title case with proper capitalization rules.
titleCase("the quick brown fox"); // 'The Quick Brown Fox'
titleCase("a tale of two cities"); // 'A Tale of Two Cities'
titleCase("mother-in-law"); // 'Mother-in-Law'
titleCase("don't stop believing"); // "Don't Stop Believing"
titleCase("NASA launches rocket"); // 'NASA Launches Rocket'
titleCase("2001: a space odyssey"); // '2001: A Space Odyssey'
// With custom exceptions
titleCase("the lord of the rings", {
exceptions: ["versus"],
}); // 'The Lord of the Rings'
sentenceCase(str: string): string
Converts a string to sentence case (first letter of each sentence capitalized).
sentenceCase("hello world"); // 'Hello world'
sentenceCase("HELLO WORLD"); // 'Hello world'
sentenceCase("hello. world! how are you?"); // 'Hello. World! How are you?'
sentenceCase("this is the first. this is the second."); // 'This is the first. This is the second.'
sentenceCase("the u.s.a. is large"); // 'The u.s.a. is large'
sentenceCase("i love javascript"); // 'I love javascript'
sentenceCase("what? when? where?"); // 'What? When? Where?'
pathCase(str: string): string
Converts a string to path/case (forward slash separated).
pathCase("hello world"); // 'hello/world'
pathCase("helloWorld"); // 'hello/world'
pathCase("hello-world"); // 'hello/world'
pathCase("hello_world"); // 'hello/world'
pathCase("XMLHttpRequest"); // 'xml/http/request'
pathCase("src.components.Header"); // 'src/components/header'
pathCase("com.example.package"); // 'com/example/package'
String Manipulation
truncate(str: string, length: number, suffix?: string): string
Truncates a string to a specified length with an optional suffix.
truncate("Long text here", 10); // 'Long te...'
truncate("Long text here", 10, "→"); // 'Long tex→'
stripHtml(str: string): string
Removes HTML tags from a string.
stripHtml("<p>Hello <b>world</b>!</p>"); // 'Hello world!'
stripHtml("<div>Text</div>"); // 'Text'
escapeHtml(str: string): string
Escapes HTML special characters.
escapeHtml('<div>Hello & "world"</div>'); // '<div>Hello & "world"</div>'
escapeHtml("It's <b>bold</b>"); // 'It's <b>bold</b>'
wordCount(str: string): number
Counts the number of words in a string.
wordCount("Hello world test"); // 3
wordCount("One-word counts as one"); // 5
pad(str: string, length: number, chars?: string): string
Pads a string to a given length by adding characters to both sides (centers the string).
pad("Hi", 6); // ' Hi '
pad("Hi", 6, "-"); // '--Hi--'
pad("Hi", 7, "-"); // '--Hi---'
padStart(str: string, length: number, chars?: string): string
Pads a string to a given length by adding characters to the left.
padStart("5", 3, "0"); // '005'
padStart("Hi", 5, "."); // '...Hi'
padStart("Hi", 6, "=-"); // '=-=-Hi'
padEnd(str: string, length: number, chars?: string): string
Pads a string to a given length by adding characters to the right.
padEnd("Hi", 5, "."); // 'Hi...'
padEnd("Hi", 6, "=-"); // 'Hi=-=-'
padEnd("5", 3, "0"); // '500'
String Generation
randomString(length: number, charset?: string): string
Generates a random string of specified length.
randomString(10); // 'aBc123XyZ9'
randomString(5, "abc"); // 'abcab'
randomString(8, "0123456789"); // '42318765'
hashString(str: string): number
Generates a simple hash from a string (non-cryptographic).
hashString("hello"); // 99162322
hashString("world"); // 113318802
String Validation
isEmail(str: string): boolean
Validates if a string is a valid email format.
isEmail("user@example.com"); // true
isEmail("invalid.email"); // false
isEmail("test@sub.domain.com"); // true
isUrl(str: string): boolean
Validates if a string is a valid URL format.
isUrl("https://example.com"); // true
isUrl("http://localhost:3000"); // true
isUrl("not a url"); // false
isUrl("ftp://files.com/file.zip"); // true
Bundle Size
Each utility is optimized to be as small as possible:
Function | Size (minified) |
---|---|
slugify | ~200 bytes |
camelCase | ~250 bytes |
snakeCase | ~220 bytes |
kebabCase | ~200 bytes |
pascalCase | ~180 bytes |
constantCase | ~230 bytes |
dotCase | ~210 bytes |
pathCase | ~210 bytes |
sentenceCase | ~280 bytes |
titleCase | ~320 bytes |
capitalize | ~100 bytes |
truncate | ~150 bytes |
stripHtml | ~120 bytes |
escapeHtml | ~180 bytes |
randomString | ~200 bytes |
hashString | ~150 bytes |
reverse | ~80 bytes |
deburr | ~200 bytes |
isEmail | ~180 bytes |
isUrl | ~200 bytes |
wordCount | ~100 bytes |
template | ~350 bytes |
templateSafe | ~400 bytes |
pad | ~180 bytes |
padStart | ~150 bytes |
padEnd | ~150 bytes |
Total package size: < 5KB minified + gzipped
Requirements
- Node.js >= 18
- TypeScript >= 5.0 (for TypeScript users)
Development
# Clone the repository
git clone https://github.com/Zheruel/nano-string-utils.git
cd nano-string-utils
# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Build the library
npm run build
# Type check
npm run typecheck
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
License
MIT © [Zheruel]
Why nano-string-utils?
In a world of bloated dependencies, nano-string-utils
stands out by providing exactly what you need and nothing more:
- Security First: Zero dependencies means zero supply chain vulnerabilities
- Performance: Each function is optimized for speed and size
- Developer Experience: Full TypeScript support with comprehensive JSDoc comments
- Production Ready: 100% test coverage with extensive edge case handling
- Modern: Built for ES2022+ with full ESM support and CommonJS compatibility
Comparison with Alternatives
Library | Bundle Size | Dependencies | Tree-shakeable | TypeScript |
---|---|---|---|---|
nano-string-utils | < 5KB | 0 | ✅ | ✅ |
lodash | ~70KB | 0 | ⚠️ Requires lodash-es | ✅ |
underscore.string | ~20KB | 0 | ❌ | ❌ |
voca | ~30KB | 0 | ❌ | ✅ |