Case Converter — JavaScript source
Convert text between UPPER, lower, Title, Sentence, camelCase, PascalCase, snake_case, kebab-case, CONSTANT_CASE and slug. Live, one-click copy.
This is the JavaScript implementation — the same logic the interactive tool runs, in a shareable, citable form.
// case-converter - JavaScript polyglot showcase port.
//
// Pure, deterministic text-case transformations: split any input into word
// tokens and re-emit it in upper / lower / title / sentence / camel / pascal /
// snake / kebab / constant / slug case.
//
// Ported from src/lib/case.ts (the canonical TypeScript that powers the live
// Case Converter tool on dev.cosmolabs.org). Functionally equivalent - same
// inputs produce the same outputs, including edge cases.
//
// This is display source - part of CosmoDev's polyglot tool pages (one tool,
// six language references). stdlib only, no dependencies.
/**
* Tokenize an arbitrary string into lowercase-friendly word units.
*
* Three-step pipeline mirroring the TypeScript reference:
* 1. Insert a space at every camelCase boundary - a lowercase letter or
* digit immediately followed by an uppercase letter.
* 2. Split on runs of whitespace, underscore, hyphen, or dot.
* 3. Strip any remaining non-alphanumeric characters and drop empty tokens.
*
* @param {string} s
* @returns {string[]}
*/
export function words(s) {
return s
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
.split(/[\s_\-.]+/)
.map((w) => w.replace(/[^a-zA-Z0-9]/g, ''))
.filter(Boolean);
}
/**
* Capitalize the first character and lowercase the rest.
*
* @param {string} s
* @returns {string}
*/
export function cap(s) {
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
}
/**
* The case-transform registry: each entry maps a CaseId to a pure function.
* Keys mirror the TypeScript `caseTransforms` object 1:1.
*
* @type {Record<string, (s: string) => string>}
*/
export const caseTransforms = {
upper: (s) => s.toUpperCase(),
lower: (s) => s.toLowerCase(),
// \w\S* matches each maximal run that starts with a word character. Internal
// punctuation and the spacing between runs are preserved verbatim, so only
// the first character of each run is touched.
title: (s) => s.replace(/\w\S*/g, cap),
sentence: (s) => {
const t = s.toLowerCase().trim();
return t ? t.charAt(0).toUpperCase() + t.slice(1) : '';
},
// camelCase: the first word stays lowercase, every later word is capitalized.
camel: (s) => words(s).map((w, i) => (i === 0 ? w.toLowerCase() : cap(w))).join(''),
pascal: (s) => words(s).map(cap).join(''),
snake: (s) => words(s).join('_').toLowerCase(),
kebab: (s) => words(s).join('-').toLowerCase(),
constant: (s) => words(s).join('_').toUpperCase(),
slug: (s) => words(s).join('-').toLowerCase(),
};
/**
* Apply a named case transform.
*
* Convenience dispatcher over `caseTransforms`; the registry itself remains the
* primary public surface, matching the TypeScript reference.
*
* @param {string} caseId one of the keys of `caseTransforms`
* @param {string} s
* @returns {string}
* @throws {Error} if `caseId` is not a known case
*/
export function convert(caseId, s) {
const fn = caseTransforms[caseId];
if (!fn) throw new Error(`Unknown case: ${caseId}`);
return fn(s);
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →