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

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.

Readme


import { redact } from 'textconvert';

redact('Contact me at [email protected] or 555-123-4567');
// 'Contact me at jo**************** or 55**********'

📚 Table of Contents


🚀 Getting Started

Installation

npm install textconvert

Usage

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.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.


✨ 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 as redact(), returned as structured { type, value, start, end } matches instead of masked in place
  • sanitize() 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 21 into '21st'
  • Ordinal words: turns 21 into 'twenty-first'
  • Number formatting: adds thousands separators, e.g. 1234567.89 -> '1,234,567.89'
  • Number parsing: turns '1,234,567.89' back into 1234567.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'); // true

See 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!