textConvert is a lightweight, dependency-free TypeScript library for text conversion, validation, and analysis — including redact(), which masks PII embedded in free-form text before it hits a log or a database.
import { redact } from 'textconvert';
redact('Contact me at jordan@example.com or 555-123-4567');
// 'Contact me at jo**************** or 55**********'
npm install textconvert
import * as convert from 'textconvert';
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.log
Reads 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.
scan(): the same PII/secret detection as redact(), 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 abovenpx textconvert redact <file> sanitizes a file (or stdin) from the command line, no JS required'twelve thousand three hundred and forty-five' -> 1234521 into '21st'21 into 'twenty-first'1234567.89 -> '1,234,567.89''1,234,567.89' back into 1234567.89| 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.
import { redact, camelCase, count, isEmail, isUrl, isPhoneNumber } from 'textconvert';
redact('Contact me at jordan@example.com or 555-123-4567');
// 'Contact me at jo**************** or 55**********'
camelCase('hello world'); // 'helloWorld'
count('Hello, world!'); // 10
isEmail('user@example.com'); // true
isUrl('https://example.com/path?query=123'); // true
isPhoneNumber('+1-202-555-0173'); // true
See docs/API.md for a usage example, parameters, and edge cases for every function.
// 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"
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.
See CHANGELOG.md for release history and updates.
Upgrading across a major version? See MIGRATION.md for concrete before/after guidance on every breaking change.
This project is licensed under the MIT License.
Nicolas Alkhoury 💬 🐛 💼 💻 🔣 🎨 📖 🤔 🚇 🚧 🧑🏫 📦 🔌 📆 🔬 👀 ⚠️ 🔧 📓 |
Madesh 💻 📖 💡 ⚠️ |
Kuba 💻 📖 💡 |
This project follows the all-contributors specification. Contributions of any kind welcome!