skip to main content

-- Convert text to camelCase, snake_case, kebab-case and seven other formats, line by line --

each line is converted on its own: pasting a list does not merge it into a single identifier.

How to use it

Paste a value, or a list with one value per line. Each line is converted on its own into all ten formats: pasting a column of field names does not merge them into a single identifier.

The formats

FormatExampleTypical use
camelCasecreateAnElementJavaScript variables and functions
PascalCaseCreateAnElementReact components, classes, types
snake_casecreate_an_elementPython, SQL columns
kebab-casecreate-an-elementCSS classes, file names
CONSTANT_CASECREATE_AN_ELEMENTconstants, environment variables
Title CaseCreate An Elementheadings
Sentence caseCreate an elementsentences, labels
slugcreate-an-elementURL segments

kebab-case and slug look alike but do not do the same thing: the slug treats punctuation as a separator, case conversion removes it. So a/b becomes a-b as a slug and ab in kebab.

Splitting is the real work

Joining words back together is trivial. Splitting them correctly is where everything happens, and most naive implementations fail on three cases.

// an acronym followed by a word
"HTTPServerError"; // → http, server, error   (not h, t, t, p, server…)
 
// a digit against a letter
"version2Beta"; // → version, 2, beta
 
// accents and an initial capital
"Élément"; // → element   (not e, lement)

Accents must be stripped after splitting: normalising first loses the initial capital, and the word becomes indistinguishable from its lowercase form.

A conversion has to be idempotent

Re-applying a conversion to its own output must give the same output.

toKebabCase("Create an element"); // "create-an-element"
toKebabCase("create-an-element"); // "create-an-element" — identical

Without that property, a pipeline that converts twice — because two layers apply the same normalisation "just in case" — produces different identifiers on each pass.

Converting an object's keys

The most common concrete case: an API in snake_case, a front end in camelCase.

const toCamelKeys = (value) => {
  if (Array.isArray(value)) {
    return value.map(toCamelKeys);
  }
 
  if (value === null || typeof value !== "object") {
    return value;
  }
 
  return Object.fromEntries(
    Object.entries(value).map(([key, nested]) => [
      toCamelCase(key),
      toCamelKeys(nested),
    ])
  );
};

Watch the recursion: null is of type object in JavaScript, and without the explicit test the function crashes on the first null value.

topics covered

related reading