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

@acusti/textual

v0.10.0

Published

Utilities for transforming and formatting text (i.e. strings)

Readme

@acusti/textual

latest version maintenance status downloads per month bundle size

Utilities for transforming and formatting text (i.e. strings). These functions provide common text manipulation operations that are useful in UI development, from capitalizing text to extracting initials and parsing names from email addresses.

Installation

npm install @acusti/textual
# or
yarn add @acusti/textual

Key Features

  • Tree-shakeable - All functions are named exports for optimal bundling
  • Zero dependencies - Lightweight with no external dependencies
  • TypeScript support - Fully typed with comprehensive type definitions
  • Pure functions - No side effects, always return new values
  • Unicode aware - Handles international characters correctly

Quick Start

import {
    capitalize,
    getInitials,
    getNameFromEmail,
} from '@acusti/textual';

// Capitalize text like CSS text-transform: capitalize
const title = capitalize('hello world'); // => 'Hello World'

// Extract initials from names
const initials = getInitials('John Doe Smith'); // => 'JDS'

// Parse display name from email
const name = getNameFromEmail('[email protected]'); // => 'John Doe'

API Reference

capitalize(text: string): string

Returns input text with equivalent formatting to the text-transform: capitalize CSS property. Capitalizes the first letter of each word.

import { capitalize } from '@acusti/textual';

capitalize('hello world'); // => 'Hello World'
capitalize('iOS app development'); // => 'IOS App Development'
capitalize('mary-jane watson'); // => 'Mary-Jane Watson'
capitalize('hello.world'); // => 'Hello.World'
capitalize(''); // => ''

Parameters:

  • text (string): The text to capitalize

Returns:

  • (string): The capitalized text

getInitials(name: string, maxLength?: number): string

Extracts uppercase initials from the input string. For single words, uses uppercase letters and numbers. For multiple words, uses the first character of each word.

import { getInitials } from '@acusti/textual';

// Multiple words - first letter of each word
getInitials('John Doe Smith'); // => 'JDS'
getInitials('Mary-Jane Watson'); // => 'MJW'
getInitials('Dr. Martin Luther King Jr.'); // => 'DMLKJ'

// Single words - uppercase letters and numbers
getInitials('iPhone'); // => 'PI'
getInitials('iOS15'); // => 'IOS'
getInitials('user123'); // => 'U'

// Limit length
getInitials('Very Long Name Here', 2); // => 'VL'
getInitials('Single', 1); // => 'S'

// Edge cases
getInitials(''); // => ''
getInitials('123'); // => ''

Parameters:

  • name (string): The name to extract initials from
  • maxLength (number, optional): Maximum number of initials to return. Defaults to 3

Returns:

  • (string): The uppercase initials

getNameFromEmail(email: string): string

Converts an email address into a formatted display name by extracting the username part and treating . and + as space separators.

import { getNameFromEmail } from '@acusti/textual';

getNameFromEmail('[email protected]'); // => 'John Doe'
getNameFromEmail('[email protected]'); // => 'Mary Jane Watson'
getNameFromEmail('[email protected]'); // => 'User Tag'
getNameFromEmail('[email protected]'); // => 'Firstname Lastname Work'

// Handles edge cases
getNameFromEmail('[email protected]'); // => 'Singlename'
getNameFromEmail('[email protected]'); // => 'User123'
getNameFromEmail(''); // => ''
getNameFromEmail('invalid-email'); // => 'Invalid Email'

Parameters:

  • email (string): The email address to extract a name from

Returns:

  • (string): The formatted display name

Usage Examples

User Profile Display

import { getInitials, getNameFromEmail } from '@acusti/textual';

function UserAvatar({ user }) {
    const displayName = user.name || getNameFromEmail(user.email);
    const initials = getInitials(displayName);

    return (
        <div className="user-avatar">
            <div className="avatar-circle">
                {user.avatar ? (
                    <img src={user.avatar} alt={displayName} />
                ) : (
                    <span className="initials">{initials}</span>
                )}
            </div>
            <span className="display-name">{displayName}</span>
        </div>
    );
}

Form Field Formatting

import { capitalize } from '@acusti/textual';

function NameInput({ value, onChange }) {
    const handleBlur = (e) => {
        // Auto-capitalize names when user finishes editing
        const capitalized = capitalize(e.target.value.toLowerCase());
        onChange(capitalized);
    };

    return (
        <input
            type="text"
            value={value}
            onChange={(e) => onChange(e.target.value)}
            onBlur={handleBlur}
            placeholder="Enter full name"
        />
    );
}

Contact List

import { getInitials, capitalize } from '@acusti/textual';

function ContactCard({ contact }) {
    const initials = getInitials(contact.name);
    const formattedName = capitalize(contact.name);

    return (
        <div className="contact-card">
            <div
                className="contact-avatar"
                style={{ backgroundColor: getAvatarColor(initials) }}
            >
                {initials}
            </div>
            <div className="contact-info">
                <h3>{formattedName}</h3>
                <p>{contact.email}</p>
                <p>{contact.phone}</p>
            </div>
        </div>
    );
}

// Helper function to generate consistent colors based on initials
function getAvatarColor(initials) {
    const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'];
    const index = initials.charCodeAt(0) % colors.length;
    return colors[index];
}

Email Suggestion

import { getNameFromEmail, capitalize } from '@acusti/textual';

function EmailSignup({ email, onNameSuggest }) {
    const suggestedName = email ? getNameFromEmail(email) : '';

    return (
        <form>
            <input
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder="Enter your email"
            />

            {suggestedName && (
                <div className="name-suggestion">
                    <p>Is your name {capitalize(suggestedName)}?</p>
                    <button
                        type="button"
                        onClick={() =>
                            onNameSuggest(capitalize(suggestedName))
                        }
                    >
                        Yes, use this name
                    </button>
                </div>
            )}
        </form>
    );
}

Team Member Directory

import {
    getInitials,
    getNameFromEmail,
    capitalize,
} from '@acusti/textual';

function TeamDirectory({ members }) {
    return (
        <div className="team-directory">
            {members.map((member) => {
                const displayName =
                    member.name || getNameFromEmail(member.email);
                const formattedName = capitalize(displayName);
                const initials = getInitials(displayName);

                return (
                    <div key={member.id} className="team-member">
                        <div className="member-avatar">
                            {member.photo ? (
                                <img
                                    src={member.photo}
                                    alt={formattedName}
                                />
                            ) : (
                                <div
                                    className="initials-avatar"
                                    title={formattedName}
                                >
                                    {initials}
                                </div>
                            )}
                        </div>

                        <div className="member-info">
                            <h3>{formattedName}</h3>
                            <p className="role">
                                {capitalize(member.role || 'team member')}
                            </p>
                            <p className="department">
                                {capitalize(member.department || '')}
                            </p>
                        </div>
                    </div>
                );
            })}
        </div>
    );
}

Comment System

import { getInitials, getNameFromEmail } from '@acusti/textual';

function CommentCard({ comment }) {
    const authorName =
        comment.author?.name ||
        getNameFromEmail(comment.author?.email || '');
    const authorInitials = getInitials(authorName);

    return (
        <div className="comment">
            <div className="comment-avatar">
                <span className="avatar-text">{authorInitials}</span>
            </div>

            <div className="comment-content">
                <div className="comment-header">
                    <span className="author-name">{authorName}</span>
                    <time className="comment-date">
                        {new Date(comment.createdAt).toLocaleDateString()}
                    </time>
                </div>

                <p className="comment-text">{comment.text}</p>
            </div>
        </div>
    );
}

Common Use Cases

  • User avatars - Generate initials for profile pictures
  • Display names - Create readable names from email addresses
  • Form validation - Auto-capitalize user input for consistency
  • Contact lists - Format names consistently across the application
  • User onboarding - Suggest display names during account creation
  • Team directories - Display member information uniformly
  • Comment systems - Show author names and initials
  • Email templates - Format recipient names properly

Best Practices

Input Sanitization

Always validate input before processing:

import { capitalize, getInitials } from '@acusti/textual';

function safeCapitalize(input) {
    if (typeof input !== 'string') return '';
    return capitalize(input.trim());
}

function safeGetInitials(input, maxLength = 3) {
    if (typeof input !== 'string') return '';
    return getInitials(input.trim(), maxLength);
}

Internationalization

The functions works fully with unicode characters where the concept of capitalization makes sense.

import { capitalize } from '@acusti/textual';

// Works with international characters
capitalize('josé maría'); // => 'José María'
capitalize('björk guðmundsdóttir'); // => 'Björk Guðmundsdóttir'
capitalize('ælfgyva'); // => 'Ælfgyva'
getInitials('ólafur arnalds'); // => 'ÓA'

Performance

All functions are optimized for performance and can handle large datasets:

import { getInitials } from '@acusti/textual';

// Efficient for processing large lists
const userInitials = users.map((user) => ({
    ...user,
    initials: getInitials(user.name),
}));