Codementor Events

Case Conversion in JavaScript

Published Jan 09, 2021Last updated Jul 07, 2021
Case Conversion in JavaScript

I got fed-up searching Google for case conversion utilities. The useful ones I found (Voca and change-case) both require an environment that allows me to use npm.

But I was using Vanilla JavaScript. I did not want to include any toolchains in this project, and I’m reluctant to send an asynchronous request to download a module just for case-conversion.

So I decided to write a set of conversion utilities myself.

It’s simpler than I thought.

The Common Cases

I usually use these cases when writing HTML, CSS, and JavaScript:

  • camelCase
  • kebab-case
  • Sentence case
  • Title Case

I don’t use these two cases, but I know they exist.

  • snake_case
  • PascalCase

So far, I’ve relied on simple functions that convert from one case to another. But I was fed-up with writing things like camelToTitle or camelToKebab. It’s much nicer to have a function that converts all cases to the one I need.

Converting any case to kebab-case

I started converting stuff into kebab-case because that was what I needed when I searched for case conversion utilities.

To convert all cases into kebab-case, I had to consider the possible cases. Here are the cases once again:

  • camelCase
  • PascalCase
  • snake_case
  • Sentence case
  • Title Case

Converting snake_case, Sentence case and Title Case into kebab-case is easy. I only need to do two things:

  1. Lowercase everything
  2. Replace _ and spaces with -

But I cannot begin by lowercasing everything if I wanted to support case conversion from camelCase and PascalCase. I would lose the word-break point.

So I had to begin by searching for the capital letters which denote the start of a new word (for camelCase and PascalCase). The easiest way is to loop through each letter and run a simple /[A-Z]/ regex. This regex searches for any letter that’s between A and Z.

function toKebab (string) {
  return string
    .split('')
    .map((letter, index) => {
      if (/[A-Z]/.test(letter)) {
        // Capital letters
      }
      return letter
    })
    .join('')
}

Then I lowercased the capital letters and added a space in front of them. (It doesn’t matter whether I add space or _, both are fine since I’m going to replace them with - later).

function toKebab (string) {
  return string
    .split('')
    .map((letter, index) => {
      if (/[A-Z]/.test(letter)) {
        return ` ${letter.toLowerCase()}`
      }
      return letter
    })
    .join('')
}

Note: I’m pretty sure there’s a regex that can do these three steps in one. It probably uses capturing groups and substitution, which I’m not familiar with. I didn’t try it since I didn’t have the time nor energy to research further. If you know a good regex for this, let me know!

This step converts the cases into the following:

  • camel case
  • pascal case
  • snake_case
  • sentence case
  • title case

There’s a space at the start of some cases. I removed them withtrim.

function toKebab (string) {
  return string
    .split('')
    .map((letter, index) => {
      if (/[A-Z]/.test(letter)) {
        return ` ${letter.toLowerCase()}`
      }
      return letter
    })
    .join('')
    .trim()
}

This gives me the following:

  • camel case
  • pascal case
  • snake_case
  • sentence case
  • title case

I can now replace both _ and spaces with -. This can be done with two replace calls like this:

    1. First replace uses /_/g to replace all occurences of _.
    1. Second replace uses /\s+/ to replace all spaces into -. The + indicates “one or more”, so it matches the two spaces in title case.
export function toKebab (string) {
  return string
    // ...
    .replace(/_/g, '-')
    .replace(/\s+/g, '-')
}

I can combine both replace calls into a single regex with []. The square brackets indicate an OR value.

export function toKebab (string) {
  return string
    // ...
    .replace(/[_\s]+/g, '-')
}

That gives me the this:

  • camel-case
  • pascal-case
  • snake-case
  • sentence-case
  • title-case

It even works for complicated mixed cases too. For example, if you try case_With-long name you’ll get case-with-long-name.

Converting anything to Sentence case

I worked on this utility next since I wanted to convert camelCase into Sentence case.

At first, I dreaded the thought of finding the similarities between all 6 cases again. It felt like a lot of work.

But I realized I can use my toKebab function to convert everything into kebab-case first. This takes advantage of the work I’ve already done.

I was against this idea at first because it seems like a “waste of resources” to run another function first from a performance standpoint. But I realized I was being idealistic. From a practical standpoint, it doesn’t have much impact on performance since the operations are really fast.

// Starting with toKebab
function toTitle (string) {
  return toKebab(string)
}

Now I just need to convert kebab-case to Title Case.

Here, I only need to do the following:

  1. Split the string at -. This gives me an array of words.
  2. Capitalize the first letter of each word.
  3. Join the array with space.
export function toTitle (string) {
  return toKebab(string)
    .split('-')
    .map(word => {
      return word.slice(0, 1).toUpperCase() + word.slice(1)
    })
    .join(' ')
}

And I’m done!

Converting anything into Sentence Case

It’s equally easy to convert all cases into Sentence case. Once again, I started by converting things into kebab-case.

export function toSentence (string) {
  return toKebab(string)
}

Now I only need to convert kebab-case into Sentence case. There are two things to do:

  • Capitalize the first letter
  • replace - with space.

I can do either step first. In this case, I chose to do the replace step first since I can chain it after toKebab.

export function toSentence (string) {
  const interim = toKebab(string)
    .replace(/-/g, ' ')
  return interim.slice(0, 1).toUpperCase() + interim.slice(1)
}

Convert anything into camelCase

Finally, I want to be able to convert any string back into camel case.

I start with toKebab as usual.

export function toCamel (string) {
  return toKebab(string)
}

At this point, I only need to convert kebab-case into camelCase.

I can do this by:

  1. Splitting the word at each -. This creates an array of words.
  2. Loop through the array and capitalize the first letter if it’s not the first word.
function toCamel (string) {
  return toKebab(string)
    .split('-')
    .map((word, index) => {
      if (index === 0) return word
      return word.slice(0, 1).toUpperCase() + word.slice(1).toLowerCase()
    })
    .join('')
}

Simple as that!

Case Conversion Library

I placed added these case-conversion utilities into my JavaScript repository. You can grab them if you want them 😃


Thanks for reading. This article was originally posted on my blog. Sign up for my newsletter if you want more articles to help you become a better frontend developer.

Discover and read more posts from Zell Liew
get started
post comments1Reply
Garrett Smith
4 years ago

At first glance, none of the code examples will do anything other than return the input string.

This is because return statements rely on Automatic Semicolon Insertion (ASI).

When a continue, break, return, throw, or yield token is encountered and a LineTerminator is encountered before the next token, a semicolon is automatically inserted after the continue, break, return, throw, or yield token.

Thus, this function:—

export function toKebab (string) {
  return string
    // ...
    .replace(/[_\s]+/g, '-')
}

Will return the input string when called; nothing more.