textconvert
v3.0.0
Published
Lightweight, dependency-free text utilities for TypeScript -- redact PII (emails, phone numbers) from free-form text, plus case conversion, validation, and analysis.
Maintainers
Keywords
Readme
import { redact } from 'textconvert';
redact('Contact me at [email protected] or 555-123-4567');
// 'Contact me at jo**************** or 55**********'📚 Table of Contents
- 📚 Table of Contents
- 🚀 Getting Started
- ✨ Features
- Why Use textConvert?
- 📋 API Reference
- Quick Examples
- Advanced Examples
- Contributing
- Changelog
- Migration Guide
- License
- Contributors ✨
🚀 Getting Started
Installation
npm install textconvertUsage
import * as convert from 'textconvert';CLI
A redact command is included for sanitizing PII/secrets from the command line — no JS required:
npx textconvert redact input.log
npx textconvert redact input.log --types email,phone --mask-char '#'
cat input.log | npx textconvert redact > output.logReads from the given file, or from stdin if no file is given; always writes to stdout. Run npx textconvert --help for the full option list.
✨ Features
- PII redaction: mask emails, phone numbers, credit card numbers, and (opt-in) public IPv4 addresses, API keys/tokens, and JWTs embedded in free-form text, or partially mask a known value for display
scan(): the same PII/secret detection asredact(), returned as structured{ type, value, start, end }matches instead of masked in placesanitize()pipeline: trim, normalize whitespace, redact PII, and escape HTML in one configurable call, composed from the functions above- XSS-safe HTML escaping: escape/unescape the five HTML special characters per OWASP's XSS Prevention Cheat Sheet, without a dedicated escaping library
- CLI:
npx textconvert redact <file>sanitizes a file (or stdin) from the command line, no JS required - Case conversion: camelCase, PascalCase, snake_case, kebab-case, slugify, capitalize, Title Case
- Validation: email addresses, URLs, and phone numbers
- Extraction: pull email addresses, URLs, @mentions, and #hashtags out of a block of text
- Text analysis: word/letter/sentence/paragraph counting, reading time, readability scoring, palindrome checking, word frequency, etc.
- Text utilities: truncate with word-boundary awareness
- Language detection: English, French, Spanish, German, Italian, Portuguese, Dutch
- Number to words: Converts numbers < 100 million to English words
- Words to number: Parses English number-words back into a number, e.g.
'twelve thousand three hundred and forty-five'->12345 - Ordinal suffixes: turns
21into'21st' - Ordinal words: turns
21into'twenty-first' - Number formatting: adds thousands separators, e.g.
1234567.89->'1,234,567.89' - Number parsing: turns
'1,234,567.89'back into1234567.89 - Generation: cryptographically secure random strings for IDs, tokens, or test fixtures
- Grammar: pluralize English words for UI copy like "1 item" / "5 items"
- Normalization: strip diacritics, collapse whitespace, and normalize line endings
- Pure, dependency-free, and TypeScript-ready
Why Use textConvert?
- PII Redaction Built In: Mask emails and phone numbers embedded in free-form text — sanitize logs and user content without reaching for a full NLP-based PII detector or a paid API.
- Lightweight & Dependency-Free: No external dependencies, fast and easy to use.
- Comprehensive Text Utilities: Covers case conversion, text analysis, language detection, and more.
- TypeScript Support: Fully typed for safe and productive development.
- Modern API: Designed for clarity, performance, and extensibility.
- Actively Maintained: Open to contributions and new features.
📋 API Reference
| Function | Description |
| -------------------------------------------- | ------------------------------------------------------------------ |
| camelCase(text) | Convert to camelCase |
| pascalCase(text) | Convert to PascalCase |
| snakeCase(text) | Convert to snake_case |
| kebabCase(text) | Convert to kebab-case |
| slugify(text) | Convert to a URL-safe slug |
| capitalize(text) | Capitalize only the first letter |
| titleCase(text) | Capitalize the first letter of every word |
| clear(text) | Remove punctuation from text |
| count(text, countNumbers?) | Count letters (optionally including numbers) |
| countWords(text) | Count words |
| countSentences(text) | Count sentences |
| reverse(text) | Reverse a string (grapheme-cluster aware) |
| spread(text, clear?) | Split a string into an array of characters |
| truncate(text, maxLength, options?) | Shorten text to a max length, with an ellipsis (grapheme-safe cut) |
| maskText(text, options?) | Partially mask a string for display |
| redact(text, options?) | Mask PII/secrets embedded in text |
| scan(text, options?) | Find PII/secrets embedded in text as structured matches |
| getTextStats(text, wordsPerMinute?) | Full text statistics (counts, averages, reading time, readability) |
| isPalindrome(text) | Check if text is a palindrome |
| wordFrequency(text) | Count how many times each word appears |
| detectLanguage(text, minLength?, options?) | Detect the language of a piece of text |
| numbersToWords(number) | Convert a number under 100 million to English words |
| wordsToNumber(text) | Parse English number-words back into a number |
| ordinal(number) | Get a number's ordinal suffix form (21 -> '21st') |
| ordinalToWords(number) | Get a number's ordinal word form (21 -> 'twenty-first') |
| formatNumber(number, options?) | Add thousands separators to a number |
| parseNumber(text) | Parse a formatted number string back into a number |
| randomString(length, options?) | Generate a cryptographically secure random string |
| pluralize(word, count?) | Return the plural form of an English word |
| removeDiacritics(text) | Strip accents from accented characters |
| normalizeWhitespace(text) | Collapse whitespace runs into a single space |
| normalizeLineEndings(text) | Normalize CRLF/CR line endings to LF |
| isEmail(text) | Validate an email address |
| isUrl(text) | Validate a URL |
| isPhoneNumber(text) | Validate a phone number |
| extractEmails(text) | Extract all email addresses found in a block of text |
| extractUrls(text) | Extract all URLs found in a block of text |
| extractMentions(text) | Extract all @mentions found in a block of text |
| extractHashtags(text) | Extract all #hashtags found in a block of text |
| escapeHtml(text) | Escape the five HTML special characters |
| unescapeHtml(text) | Reverse escapeHtml's escaping |
| sanitize(text, options?) | Trim, normalize, redact, and escape in one configurable pipeline |
See docs/API.md for full parameter, return type, and edge-case details on every function, or browse the auto-generated API reference site.
Quick Examples
import { redact, camelCase, count, isEmail, isUrl, isPhoneNumber } from 'textconvert';
redact('Contact me at [email protected] or 555-123-4567');
// 'Contact me at jo**************** or 55**********'
camelCase('hello world'); // 'helloWorld'
count('Hello, world!'); // 10
isEmail('[email protected]'); // true
isUrl('https://example.com/path?query=123'); // true
isPhoneNumber('+1-202-555-0173'); // trueSee docs/API.md for a usage example, parameters, and edge cases for every function.
Advanced Examples
// Detect language with options
import { detectLanguage, Language } from 'textconvert';
const result = detectLanguage('Hola mundo', 4, { maxCharsToAnalyze: 300 });
if (result.language === Language.Spanish) {
console.log('Spanish detected!');
}
// Get detailed text statistics
const stats = convert.getTextStats('Hello world. This is a test.');
console.log(stats.wordCount, stats.readingTimeFormatted);
// Convert numbers to words
console.log(convert.numbersToWords(987654));
// "nine hundred eighty-seven thousand six hundred and fifty-four"Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines and workflow, and our Code of Conduct.
New to the codebase? docs/ARCHITECTURE.md covers the project structure and design principles.
If you are adding a new function, follow the step-by-step instructions in docs/ADDING_FUNCTION.md.
Changelog
See CHANGELOG.md for release history and updates.
Migration Guide
Upgrading across a major version? See MIGRATION.md for concrete before/after guidance on every breaking change.
License
This project is licensed under the MIT License.
Contributors ✨
This project follows the all-contributors specification. Contributions of any kind welcome!
