Skip to content

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 →