Documentation / String

String

Utilities for transforming and validating strings. Import from the root or from koyojs/String.

// Root import
import { capitalize, slugify, isEmail } from "koyojs";

// Per-module import
import { capitalize } from "koyojs/String";
capitalizecapitalize(input: string): string

Capitalizes the first character of a string, leaving the rest unchanged.

ParameterTypeDescription
inputstringThe input string.
returnsstring
import { capitalize } from "koyojs";

capitalize("hello world");  // "Hello world"
capitalize("javaScript");   // "JavaScript"
capitalize("");             // ""

// Note: only the very first character is changed — the rest stays as-is
capitalize("hELLO");  // "HELLO"

// Common use: format a user's display name from a form field
const name = capitalize(user.firstName.trim());

toCamelCasetoCamelCase(input: string): string

Converts a string with spaces, hyphens, or underscores to camelCase.

ParameterTypeDescription
inputstringThe input string.
returnsstring
import { toCamelCase } from "koyojs";

toCamelCase("hello world");     // "helloWorld"
toCamelCase("my-variable");     // "myVariable"
toCamelCase("some_prop_name");  // "somePropName"
toCamelCase("--weird  input_"); // "weirdInput"

// Transform snake_case API response keys to camelCase for JS
const apiResponse = { user_id: 1, first_name: "Alice", is_admin: false };

const camel = Object.fromEntries(
  Object.entries(apiResponse).map(([k, v]) => [toCamelCase(k), v])
);
// { userId: 1, firstName: "Alice", isAdmin: false }

toSnakeCasetoSnakeCase(input: string): string

Converts a string to snake_case — all lowercase with words separated by underscores.

ParameterTypeDescription
inputstringThe input string.
returnsstring
import { toSnakeCase } from "koyojs";

toSnakeCase("Hello World");   // "hello_world"
toSnakeCase("myVariable");    // "my_variable"
toSnakeCase("camelCaseKey");  // "camel_case_key"
toSnakeCase("already_snake"); // "already_snake"

// Serialize JS camelCase keys to snake_case for a REST API payload
const body = { firstName: "Alice", maxResults: 10, includeDeleted: false };

const snakeBody = Object.fromEntries(
  Object.entries(body).map(([k, v]) => [toSnakeCase(k), v])
);
// { first_name: "Alice", max_results: 10, include_deleted: false }

toTitleCasetoTitleCase(input: string): string

Converts a string to Title Case — first letter of each word capitalized.

ParameterTypeDescription
inputstringThe input string.
returnsstring
import { toTitleCase } from "koyojs";

toTitleCase("hello world");          // "Hello World"
toTitleCase("the quick brown fox");  // "The Quick Brown Fox"
toTitleCase("already Title Case");   // "Already Title Case"

// Render a blog post title stored in lowercase
const post = { title: "getting started with solidjs and vite" };
<h1>{toTitleCase(post.title)}</h1>
// "Getting Started With Solidjs And Vite"

// Format category labels coming from a database
const category = "science_and_technology";
toTitleCase(category.replace(/_/g, " "));
// "Science And Technology"

slugifyslugify(input: string): string

Converts a string into a URL-friendly slug — lowercase, spaces replaced with hyphens, special characters and diacritics removed.

ParameterTypeDescription
inputstringThe input string.
returnsstring
import { slugify } from "koyojs";

slugify("Hello World!");           // "hello-world"
slugify("My Blog Post Title #1");  // "my-blog-post-title-1"
slugify("  extra   spaces  ");     // "extra-spaces"
slugify("Déjà vu!");               // "deja-vu"

// Generate a permalink from a post title
const post = { title: "10 Tips for Writing Clean TypeScript" };
const url = `/blog/${slugify(post.title)}`;
// "/blog/10-tips-for-writing-clean-typescript"

// Build a URL-safe product ID
const product = { name: "Wireless Headphones Pro (2025 Edition)" };
const path = `/products/${slugify(product.name)}`;
// "/products/wireless-headphones-pro-2025-edition"

truncatetruncate(input: string, maxLength: number): string

Hard-cuts a string to at most maxLength characters. No ellipsis is added — the string is simply sliced at that position. Throws a RangeError if maxLength is negative. Use `ellipsify` if you want a trailing "..." appended automatically.

ParameterTypeDescription
inputstringThe input string.
maxLengthnumberMaximum number of characters to keep. Must be ≥ 0.
returnsstring
import { truncate } from "koyojs";

truncate("Hello, World!", 8);  // "Hello, W"
truncate("Short", 10);         // "Short"  — already fits, returned as-is
truncate("", 5);               // ""

// Enforce a database column length before INSERT
const bio = "This is a very long biography that goes on and on...";
const stored = truncate(bio, 255);

// Fit a string into a fixed-width terminal column
const label = truncate(filename, 20).padEnd(20);

ellipsifyellipsify(input: string, maxLength: number): string

Caps the total output at maxLength characters. If the string is longer, it is cut so the final result including the trailing "..." is at most maxLength chars. The "..." counts toward the limit — `ellipsify(s, 8)` returns at most 5 visible characters plus "...". Throws a RangeError if maxLength is negative.

ParameterTypeDescription
inputstringThe input string.
maxLengthnumberTotal character limit of the returned string, including the trailing ellipsis. Must be ≥ 0.
returnsstring
import { ellipsify } from "koyojs";

ellipsify("A longer sentence here", 12);  // "A longer ..."
ellipsify("Short", 10);                   // "Short"  — fits, no ellipsis added
ellipsify("Hello World", 8);              // "Hello..."

// "..." is 3 chars, so visible text = length - 3
ellipsify("1234567890", 7);  // "1234..."

// Card description preview — limit to 80 characters
const card = { desc: "This product has many remarkable features worth exploring in depth." };
const preview = ellipsify(card.desc, 80);

// Notification message in a toast
const msg = ellipsify(errorMessage, 60);

isEmailisEmail(input: string): boolean

Returns true if the string is a valid e-mail address. Enforces the RFC 5321 practical length limit (320 characters) and requires a non-empty local part, an @ symbol, and a domain with at least a two-character TLD.

ParameterTypeDescription
inputstringThe string to test.
returnsboolean
import { isEmail } from "koyojs";

isEmail("user@example.com");      // true
isEmail("user+tag@domain.co.uk"); // true
isEmail("not-an-email");          // false
isEmail("@domain.com");           // false
isEmail("a@b");                   // false
isEmail("");                      // false

// Form validation before submitting
function handleSubmit(formData: { email: string }) {
  if (!isEmail(formData.email)) {
    setError("Please enter a valid email address.");
    return;
  }
  submitForm(formData);
}

// Filter out invalid emails from an import list
const validEmails = rawList.filter(isEmail);

isURLisURL(input: string): boolean

Returns true if the string is a well-formed HTTP or HTTPS URL. Uses the WHATWG URL parser internally — if the string is not a valid URL the constructor throws and false is returned. Only http: and https: protocols are accepted; all other schemes return false.

ParameterTypeDescription
inputstringThe string to test.
returnsboolean
import { isURL } from "koyojs";

isURL("https://example.com");            // true
isURL("http://localhost:3000");          // true
isURL("https://sub.domain.io/path?q=1"); // true
isURL("ftp://files.io/x");              // false — only http/https
isURL("//example.com");                 // false — must include protocol
isURL("not a url");                     // false

// Validate a user-submitted website link before storing
function saveProfile(data: { website: string }) {
  if (data.website && !isURL(data.website)) {
    throw new Error("Website must be a valid http/https URL");
  }
  db.save(data);
}

// Render a clickable link only when the value is a real URL
const href = isURL(user.website) ? user.website : null;

isPhoneNumberisPhoneNumber(input: string): boolean

Returns true if the string matches a common phone number pattern. Strips formatting characters (spaces, hyphens, dots, parentheses) then checks that the remaining digit string is 7–15 digits, optionally prefixed with +, per ITU-T E.164.

ParameterTypeDescription
inputstringThe string to test.
returnsboolean
import { isPhoneNumber } from "koyojs";

isPhoneNumber("+1 (555) 123-4567");  // true
isPhoneNumber("+44 20 7946 0958");   // true
isPhoneNumber("555-123-4567");       // true
isPhoneNumber("5551234567");         // true
isPhoneNumber("123");                // false — too short
isPhoneNumber("abc");                // false

// Contact form validation
function validateContact(form: { phone: string }) {
  if (form.phone && !isPhoneNumber(form.phone)) {
    return "Enter a valid phone number (e.g. +1 555 123-4567)";
  }
}