Convert camelCaseText to Title Case Text
Asked Answered
B

28

276

How can I convert a string either like 'helloThere' or 'HelloThere' to 'Hello There' in JavaScript?

Banda answered 29/8, 2011 at 2:3 Comment(7)
hmm.. what is your expected output for iLiveInTheUSA ?Blancheblanchette
I Live In The U... oh crap! - But in my case, I have a limited set of strings and there are no such strings that could break a simple converter. Good catch though!Banda
Similarly uSBPort should result in "USB Port"Polyphyletic
@wim: iLiveInTheUSA should be iLiveInTheUsa in correct camel case notation, but that would present different problems.Lashondalashonde
HelloThere -> Hello There is not sentence case that is title caseCynde
A sentence case answer here: https://mcmap.net/q/110378/-convert-camel-case-to-sentence-case-in-javascriptAbbasid
@Polyphyletic incorrect. Read the task again. uSBPort would correctly become: U SB Port, well, unless you had a typo in your comment.Promising
M
372

const text = 'helloThereMister';
const result = text.replace(/([A-Z])/g, " $1");
const finalResult = result.charAt(0).toUpperCase() + result.slice(1);
console.log(finalResult);

capitalize the first letter - as an example. Note the space in " $1".


Here's a typescript function that does it as well:

function camelCaseToWords(s: string) {
  const result = s.replace(/([A-Z])/g, ' $1');
  return result.charAt(0).toUpperCase() + result.slice(1);
}

Of course, in case the first letter is already capital - you would have a spare space to remove.

Mimimimic answered 29/8, 2011 at 2:11 Comment(12)
I dig the use of spaces in text.replace, I've been padding function calls with 2+ arguments with spaces for readability tooMythology
uSBPorts=>U S B Ports, not what I expect, I want a USB PortsPolyphyletic
what about writing like Non-GoogleChrome?Witching
@Polyphyletic Man, if somebody wrote the lowercase usb ports as uSBPorts, I'd steal the shift keys out of their keyboard. I'd hope it'd be usbPorts. In cases such as theUSA, you could have an option, such as consecutiveCapsMode, with different modes: lower and split, for instance. Then do camelToSentence('theUSA', { consecutiveCapsMode: 'lower' }) should return theUsa, etc.Grudge
Further to above, that'd be something like: camelToKebab = (str, mode) { let rgx = /defaultRgx/; switch(mode) { 'lower': rgx = /lowerRgx/; break; } ... }Grudge
I just wanted to mention that this code adds an extra space at the beginning of each textDanie
@VladTopala Only if the first letter is capital. And it's mentioned in the answer.Mimimimic
I wanted to convert strings that started with an uppercase character, so I modified it a little to only consider uppercase characters after a lowercase character, eg: LeftVM would become "Left VM" const result = key.replace( /([a-z])([A-Z])/g, "$1 $2" );Leper
To modify this to handle camelCase strings with numbers, use this pattern instead: /([A-Z]|([0-9]+))/gPontifex
if using this text in HTML, you can apply text-transform: capitalize css rule to capitalize all words.Jotting
@Jotting Regardless of the CSS capitalization actually being able to do what is required, I would argue that this a bad practice, as capitalization here is more likely to not for cosmetic purposes only and carries a semantic significance. Thus doing capitalization in CSS you mix your concerns and insert what is, essentially, a business logic into your CSS.Mimimimic
this gives breaking result for all cap non underscored stringIndividuate
H
196

Alternatively using lodash:

lodash.startCase(str);

Example:

_.startCase('helloThere');
// ➜ 'Hello There'

Lodash is a fine library to give shortcut to many everyday js tasks.There are many other similar string manipulation functions such as camelCase, kebabCase etc.

Haemostat answered 28/7, 2016 at 11:49 Comment(5)
If you will try for hello world then output should be Hello There, In this case loadash will be not helpful.Gingergingerbread
@AbhishekKumar startCase of lodash will actually convert hello world to Hello World lodash.com/docs/4.17.15#upperFirstLepp
You are right bro. By mistake I have written hello there to hello world.Gingergingerbread
Every time I think "there's no way lodash does this as well", it does.Contredanse
Be careful as of v4 this function remove special characters like ä and converts them to ASCII ones (a in this case)Sergo
B
67

I had a similar problem and dealt with it like this:

stringValue.replace(/([A-Z]+)*([A-Z][a-z])/g, "$1 $2")

For a more robust solution:

stringValue.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1")

http://jsfiddle.net/PeYYQ/

Input:

 helloThere 
 HelloThere 
 ILoveTheUSA
 iLoveTheUSA

Output:

 hello There 
 Hello There 
 I Love The USA
 i Love The USA
Bassett answered 29/8, 2011 at 2:17 Comment(4)
it puts an extra space in startWheelsman
It is not sentence case as OP asked. First letter should be capitalized.Divestiture
In addition, it adds an extra space between wordsPhotocell
This should solve the space issues: stringValue.replace(/([A-Z]+)*([A-Z][a-z])/g, "$1 $2").trim()Hackbut
N
56

Example without side effects.

function camel2title(camelCase) {
  // no side-effects
  return camelCase
    // inject space before the upper case letters
    .replace(/([A-Z])/g, function(match) {
       return " " + match;
    })
    // replace first char with upper case
    .replace(/^./, function(match) {
      return match.toUpperCase();
    });
}

In ES6

const camel2title = (camelCase) => camelCase
  .replace(/([A-Z])/g, (match) => ` ${match}`)
  .replace(/^./, (match) => match.toUpperCase())
  .trim();
Nestle answered 27/9, 2016 at 7:32 Comment(5)
Solid, +1 for the es6 snippet.Folie
FYI, this adds extra whitespace to the beginning of the sentence.Harbourage
@DaleZak, belated thank you! I had been meaning to get to it, but apparently the community robot fixed for me... ?Nestle
@DaleZak is it still a case? I tested in firefox 100x and node 16x and it doesn't add whitespacePulchritudinous
@DaleZak it will only add space if provided string is starting with upper case letter, which is invalid camelCase.Pulchritudinous
M
45

The best string I've found for testing camel-case-to-title-case functions is this ridiculously nonsensical example, which tests a lot of edge cases. To the best of my knowledge, none of the previously posted functions handle this correctly:

__ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser_456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D

This should be converted to:

To Get Your GED In Time A Song About The 26 ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D

If you want just a simple function that handles cases like the one above (and more cases than many of the previously answers), here's the one I wrote. This code isn't particularly elegant or fast, but it's simple, understandable, and works.

The snippet below contains an online runnable example:

var mystrings = [ "__ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser_456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D", "helloThere", "HelloThere", "ILoveTheUSA", "iLoveTheUSA", "DBHostCountry", "SetSlot123ToInput456", "ILoveTheUSANetworkInTheUSA", "Limit_IOC_Duration", "_This_is_a_Test_of_Network123_in_12__days_",  "ASongAboutTheABCsIsFunToSing", "CFDs", "DBSettings", "IWouldLove1Apple", "Employee22IsCool", "SubIDIn",  "ConfigureABCsImmediately", "UseMainNameOnBehalfOfSubNameInOrders" ];

// Take a single camel case string and convert it to a string of separate words (with spaces) at the camel-case boundaries.
// 
// E.g.:
//    __ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser_456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D
//                                            --> To Get Your GED In Time A Song About The 26 ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D
//    helloThere                              --> Hello There
//    HelloThere                              --> Hello There 
//    ILoveTheUSA                             --> I Love The USA
//    iLoveTheUSA                             --> I Love The USA
//    DBHostCountry                           --> DB Host Country
//    SetSlot123ToInput456                    --> Set Slot 123 To Input 456
//    ILoveTheUSANetworkInTheUSA              --> I Love The USA Network In The USA
//    Limit_IOC_Duration                      --> Limit IOC Duration
//    This_is_a_Test_of_Network123_in_12_days --> This Is A Test Of Network 123 In 12 Days
//    ASongAboutTheABCsIsFunToSing            --> A Song About The ABCs Is Fun To Sing
//    CFDs                                    --> CFDs
//    DBSettings                              --> DB Settings
//    IWouldLove1Apple                        --> I Would Love 1 Apple
//    Employee22IsCool                        --> Employee 22 Is Cool
//    SubIDIn                                 --> Sub ID In
//    ConfigureCFDsImmediately                --> Configure CFDs Immediately
//    UseTakerLoginForOnBehalfOfSubIDInOrders --> Use Taker Login For On Behalf Of Sub ID In Orders
//
function camelCaseToTitleCase(in_camelCaseString) {
        var result = in_camelCaseString                         // "__ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser_456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D"
            .replace(/(_)+/g, ' ')                              // " ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser 456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D"
            .replace(/([a-z])([A-Z][a-z])/g, "$1 $2")           // " To Get YourGEDIn TimeASong About The26ABCs IsOf The Essence ButAPersonalIDCard For User456In Room26AContainingABC26Times IsNot AsEasy As123ForC3POOrR2D2Or2R2D"
            .replace(/([A-Z][a-z])([A-Z])/g, "$1 $2")           // " To Get YourGEDIn TimeASong About The26ABCs Is Of The Essence ButAPersonalIDCard For User456In Room26AContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([a-z])([A-Z]+[a-z])/g, "$1 $2")          // " To Get Your GEDIn Time ASong About The26ABCs Is Of The Essence But APersonal IDCard For User456In Room26AContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([A-Z]+)([A-Z][a-z][a-z])/g, "$1 $2")     // " To Get Your GEDIn Time A Song About The26ABCs Is Of The Essence But A Personal ID Card For User456In Room26A ContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([a-z]+)([A-Z0-9]+)/g, "$1 $2")           // " To Get Your GEDIn Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC26Times Is Not As Easy As 123For C3POOr R2D2Or 2R2D"
            
            // Note: the next regex includes a special case to exclude plurals of acronyms, e.g. "ABCs"
            .replace(/([A-Z]+)([A-Z][a-rt-z][a-z]*)/g, "$1 $2") // " To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC26Times Is Not As Easy As 123For C3PO Or R2D2Or 2R2D"
            .replace(/([0-9])([A-Z][a-z]+)/g, "$1 $2")          // " To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC 26Times Is Not As Easy As 123For C3PO Or R2D2Or 2R2D"  

            // Note: the next two regexes use {2,} instead of + to add space on phrases like Room26A and 26ABCs but not on phrases like R2D2 and C3PO"
            .replace(/([A-Z]{2,})([0-9]{2,})/g, "$1 $2")        // " To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D"
            .replace(/([0-9]{2,})([A-Z]{2,})/g, "$1 $2")        // " To Get Your GED In Time A Song About The 26 ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D"
            .trim()                                             // "To Get Your GED In Time A Song About The 26 ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D"
           ;

  // capitalize the first letter
  return result.charAt(0).toUpperCase() + result.slice(1);
}

for (var i = 0; i < mystrings.length; i++) {
  jQuery(document.body).append("<br />\"");
  jQuery(document.body).append(camelCaseToTitleCase(mystrings[i]));
  jQuery(document.body).append("\"<br>(was: \"");
  jQuery(document.body).append(mystrings[i]);
  jQuery(document.body).append("\") <br />");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
Milli answered 12/3, 2016 at 3:14 Comment(3)
The undercore spaced test cases do not work anymore, just a heads up. Adding: .replace(/_/g,' ') solves this. Also, adding .replace(\&\, ' & ') supports ampersand splittingWelldisposed
Thanks for pointing that out @JustinDalrymple. Our internal code wraps the camelCaseToTitleCase() function above in a helper that handles the underscores, so I didn't notice the omission when I posted it. I'll fix the code above now.Milli
This is the most complete solution I found so far. Thank you!Horsehair
B
18

Based on one of the examples above I came up with this:

const camelToTitle = (camelCase) => camelCase
  .replace(/([A-Z])/g, (match) => ` ${match}`)
  .replace(/^./, (match) => match.toUpperCase())
  .trim()

It works for me because it uses .trim() to handle the edge case where the first letter is capitalized and you end up with a extra leading space.

Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim

Bludge answered 1/10, 2018 at 2:47 Comment(0)
J
13

Ok, I'm a few years late to the game, but I had a similar question, and I wanted to make a one-replace solution for every possible input. I must give most of the credit to @ZenMaster in this thread and @Benjamin Udink ten Cate in this thread. Here's the code:

var camelEdges = /([A-Z](?=[A-Z][a-z])|[^A-Z](?=[A-Z])|[a-zA-Z](?=[^a-zA-Z]))/g;
var textArray = ["lowercase",
                 "Class",
                 "MyClass",
                 "HTML",
                 "PDFLoader",
                 "AString",
                 "SimpleXMLParser",
                 "GL11Version",
                 "99Bottles",
                 "May5",
                 "BFG9000"];
var text;
var resultArray = [];
for (var i = 0; i < textArray.length; i++){
    text = textArray[i];
    text = text.replace(camelEdges,'$1 ');
    text = text.charAt(0).toUpperCase() + text.slice(1);
    resultArray.push(text);
}

It has three clauses, all using lookahead to prevent the regex engine from consuming too many characters:

  1. [A-Z](?=[A-Z][a-z]) looks for a capital letter that is followed by a capital then a lowercase. This is to end acronyms like USA.
  2. [^A-Z](?=[A-Z]) looks for a non-capital-letter followed by a capital letter. This ends words like myWord and symbols like 99Bottles.
  3. [a-zA-Z](?=[^a-zA-Z]) looks for a letter followed by a non-letter. This ends words before symbols like BFG9000.

This question was at the top of my search results, so hopefully I can save others some time!

Jilljillana answered 8/1, 2016 at 15:49 Comment(0)
B
9

Here's my version of it. It adds a space before every UpperCase english letter that comes after a lowercase english letter and also capitalizes the first letter if needed:

For example:
thisIsCamelCase --> This Is Camel Case
this IsCamelCase --> This Is Camel Case
thisIsCamelCase123 --> This Is Camel Case123

  function camelCaseToTitleCase(camelCase){
    if (camelCase == null || camelCase == "") {
      return camelCase;
    }

    camelCase = camelCase.trim();
    var newText = "";
    for (var i = 0; i < camelCase.length; i++) {
      if (/[A-Z]/.test(camelCase[i])
          && i != 0
          && /[a-z]/.test(camelCase[i-1])) {
        newText += " ";
      }
      if (i == 0 && /[a-z]/.test(camelCase[i]))
      {
        newText += camelCase[i].toUpperCase();
      } else {
        newText += camelCase[i];
      }
    }

    return newText;
  }
Badderlocks answered 26/5, 2014 at 13:47 Comment(0)
H
8

This implementation takes consecutive uppercase letters and numbers in consideration.

function camelToTitleCase(str) {
  return str
    .replace(/[0-9]{2,}/g, match => ` ${match} `)
    .replace(/[^A-Z0-9][A-Z]/g, match => `${match[0]} ${match[1]}`)
    .replace(/[A-Z][A-Z][^A-Z0-9]/g, match => `${match[0]} ${match[1]}${match[2]}`)
    .replace(/[ ]{2,}/g, match => ' ')
    .replace(/\s./g, match => match.toUpperCase())
    .replace(/^./, match => match.toUpperCase())
    .trim();
}

// ----------------------------------------------------- //

var testSet = [
    'camelCase',
    'camelTOPCase',
    'aP2PConnection',
    'superSimpleExample',
    'aGoodIPAddress',
    'goodNumber90text',
    'bad132Number90text',
];

testSet.forEach(function(item) {
    console.log(item, '->', camelToTitleCase(item));
});

Expected output:

camelCase -> Camel Case
camelTOPCase -> Camel TOP Case
aP2PConnection -> A P2P Connection
superSimpleExample -> Super Simple Example
aGoodIPAddress -> A Good IP Address
goodNumber90text -> Good Number 90 Text
bad132Number90text -> Bad 132 Number 90 Text
Humus answered 4/1, 2020 at 10:52 Comment(2)
I'd use Chris Kline's answer which accomodates for strings like "IP Address" (where this function turns it into "I P Address"Clearcut
@JohnHamm Your input is "IP Address", right? It is not a camel case! Read about what camel case is here: en.wikipedia.org/wiki/Camel_case Do not put space between and input "IPAddress" only. This function works fine.Humus
S
5

You can use a function like this:

function fixStr(str) {
    var out = str.replace(/^\s*/, "");  // strip leading spaces
    out = out.replace(/^[a-z]|[^\s][A-Z]/g, function(str, offset) {
        if (offset == 0) {
            return(str.toUpperCase());
        } else {
            return(str.substr(0,1) + " " + str.substr(1).toUpperCase());
        }
    });
    return(out);
}

"hello World" ==> "Hello World"
"HelloWorld" ==> "Hello World"
"FunInTheSun" ==? "Fun In The Sun"

Code with a bunch of test strings here: http://jsfiddle.net/jfriend00/FWLuV/.

Alternate version that keeps leading spaces here: http://jsfiddle.net/jfriend00/Uy2ac/.

Siliqua answered 29/8, 2011 at 2:18 Comment(5)
I know it wasn't a requirement in the question, but your solution doesn't work for " helloWorld", for example.Mimimimic
Yep, that's a new requirement. I tried to do exactly what you originally asked for. Anyway, the short cut way is easy to stip off leading spaces if you don't need them there anyway. If you wanted them left in place, that could be done also.Siliqua
Here's a jsFiddle that shows a method that works with the new require of " helloWorld" and keeps the leading space (if you want that): jsfiddle.net/jfriend00/Uy2ac.Siliqua
Nice. I wonder about the performance of it, though. The handler function will be called on every match, won't it?Mimimimic
If you're doing a zillion of these in a performance-sensitive setting, it would take a some jsperf testing in a bunch of browsers to see what the fastest solution would be. Calling a callback is no big deal. Regular expressions, of any kind, are rarely the fastest solution vs. special purpose code, but they save a lot of code (and often some bugs) so are often the desired choice. It depends upon your requirements.Siliqua
T
5

One more solution based on RegEx.

respace(str) {
  const regex = /([A-Z])(?=[A-Z][a-z])|([a-z])(?=[A-Z])/g;
  return str.replace(regex, '$& ');
}

Explanation

The above RegEx consist of two similar parts separated by OR operator. The first half:

  1. ([A-Z]) - matches uppercase letters...
  2. (?=[A-Z][a-z]) - followed by a sequence of uppercase and lowercase letters.

When applied to sequence FOo, this effectively matches its F letter.

Or the second scenario:

  1. ([a-z]) - matches lowercase letters...
  2. (?=[A-Z]) - followed by an uppercase letter.

When applied to sequence barFoo, this effectively matches its r letter.

When all replace candidates were found, the last thing to do is to replace them with the same letter but with an additional space character. For this we can use '$& ' as a replacement, and it will resolve to a matched substring followed by a space character.

Example

const regex = /([A-Z])(?=[A-Z][a-z])|([a-z])(?=[A-Z])/g
const testWords = ['ACoolExample', 'fooBar', 'INAndOUT', 'QWERTY', 'fooBBar']

testWords.map(w => w.replace(regex, '$& '))
->(5) ["A Cool Example", "foo Bar", "IN And OUT", "QWERTY", "foo B Bar"]
Topside answered 21/4, 2020 at 15:27 Comment(5)
This is fantastic. If you add a {2,} just before the end of the second group it can also handle baseURLs (i.e. it keeps the "s" attached to "URL").Ligon
@Ligon Yeah, you're right, just tested it and this can be really useful.Topside
ah but that fails with "canAPIDoTask" - you get "can APIDo Task". Those two letter words are a problem.Ligon
@Ligon Works for me: 'canAPIDoTask'.replace(regex, '$& ') returns: 'can API Do Task'.Topside
Sorry, I was referring to the modification I had suggested.Ligon
U
5

If you deal with Capital Camel Case this snippet can help you, also it contains some specs so you could be sure that it matches appropriate to your case.

export const fromCamelCaseToSentence = (word) =>
  word
    .replace(/([A-Z][a-z]+)/g, ' $1')
    .replace(/([A-Z]{2,})/g, ' $1')
    .replace(/\s{2,}/g, ' ')
    .trim();

And specs:

describe('fromCamelCaseToSentence', () => {
 test('does not fall with a single word', () => {
   expect(fromCamelCaseToSentence('Approved')).toContain('Approved')
   expect(fromCamelCaseToSentence('MDA')).toContain('MDA')
 })

 test('does not fall with an empty string', () => {
   expect(fromCamelCaseToSentence('')).toContain('')
 })

 test('returns the separated by space words', () => {
   expect(fromCamelCaseToSentence('NotApprovedStatus')).toContain('Not Approved Status')
   expect(fromCamelCaseToSentence('GDBState')).toContain('GDB State')
   expect(fromCamelCaseToSentence('StatusDGG')).toContain('Status DGG')
 })
})
Unavoidable answered 23/4, 2020 at 14:9 Comment(1)
Great code, but this is Title Case not Sentence caseDonets
P
5

Using JS's String.prototype.replace() and String.prototype.toUpperCase()

const str = "thisIsATestString";
const res = str.replace(/^[a-z]|[A-Z]/g, (c, i) => (i? " " : "") + c.toUpperCase());

console.log(res);  // "This Is A Test String"
Promising answered 28/1, 2021 at 8:22 Comment(0)
P
5

My split case solution which behaves the way I want:

const splitCase = s => !s || s.indexOf(' ') >= 0 ? s :
    (s.charAt(0).toUpperCase() + s.substring(1))
        .split(/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g)
        .map(x => x.replace(/([0-9]+)/g,'$1 '))
        .join(' ')

Input

'a,abc,TheId,TheID,TheIDWord,TheID2Word,Leave me Alone!'
.split(',').map(splitCase)
.forEach(x => console.log(x))

Output

A
Abc
The Id
The ID
The ID Word
The ID2 Word
Leave me Alone!

As this above function requires Lookbehind in JS which isn't currently implemented in Safari, I've rewritten the implementation to not use RegEx below:

const isUpper = c => c >= 'A' && c <= 'Z'
const isDigit = c => c >= '0' && c <= '9'
const upperOrDigit = c => isUpper(c) || isDigit(c)

function splitCase(s) {
    let to = []
    if (typeof s != 'string') return to
    let lastSplit = 0
    for (let i=0; i<s.length; i++) {
        let c = s[i]
        let prev = i>0 ? s[i-1] : null
        let next = i+1 < s.length ? s[i+1] : null
        if (upperOrDigit(c) && (!upperOrDigit(prev) || !upperOrDigit(next))) {
            to.push(s.substring(lastSplit, i))
            lastSplit = i
        }
    }
    to.push(s.substring(lastSplit, s.length))
    return to.filter(x => !!x)
}
Pinpoint answered 18/2, 2022 at 3:41 Comment(2)
This is slick, but it's worth noting that if you need to support Safari, the regex uses lookbehind, which is not supported in Safari yet.Barkentine
@Barkentine yeah I found out about the issue in Safari later, I've updated my answer with the non-RegEx solution I've ended up using.Pinpoint
M
4

try this library

http://sugarjs.com/api/String/titleize

'man from the boondocks'.titleize()>"Man from the Boondocks"
'x-men: the last stand'.titleize()>"X Men: The Last Stand"
'TheManWithoutAPast'.titleize()>"The Man Without a Past"
'raiders_of_the_lost_ark'.titleize()>"Raiders of the Lost Ark"
Mlawsky answered 20/2, 2014 at 15:38 Comment(0)
B
4

The most compatible answer for consecutive capital-case words is this:

const text = 'theKD';
const result = text.replace(/([A-Z]{1,})/g, " $1");
const finalResult = result.charAt(0).toUpperCase() + result.slice(1);
console.log(finalResult);
  • It's also compatible with The KD and it will not convert it to The K D.
Bolshevist answered 15/4, 2021 at 16:19 Comment(1)
What do I need to do make this correct "totalCODCollected". When I use your code its becoming like "Total CODCollected"Pontic
P
3
HTTPRequest_ToServer-AndWaiting --> HTTP Request To Server And Waiting

function toSpaceCase(str) {
  return str
    .replace(/[-_]/g, ' ')
    // insert a space between lower & upper: HttpRequest => Http Request
    .replace(/([a-z])([A-Z])/g, '$1 $2')
    // space before last upper in a sequence followed by lower: XMLHttp => XML Http
    .replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1 $2$3')
    // add space between numbers and letters: Col1 => Col 1
    .replace(/([a-zA-Z])([0-9])/g, '$1 $2').replace(/([0-9])([a-zA-Z])/g, '$1 $2')
    // uppercase the first character
    .replace(/^./, firstChar => firstChar.toUpperCase())
    // replace multiple whitespaces with one
    .replace(/\s+/g, ' ')
    .trim();
}
console.log('HTTPRequest_ToServer-AndWaiting','->', toSpaceCase('HTTPRequest_ToServer-AndWaiting'))
console.log('simple','->', toSpaceCase('simple'))
console.log('testCol1','->', toSpaceCase('testCol1'))
Pupil answered 29/4, 2022 at 17:45 Comment(0)
T
2

None of the answers above worked perfectly for me, so had to come with own bicycle:

function camelCaseToTitle(camelCase) {
    if (!camelCase) {
        return '';
    }

    var pascalCase = camelCase.charAt(0).toUpperCase() + camelCase.substr(1);
    return pascalCase
        .replace(/([a-z])([A-Z])/g, '$1 $2')
        .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')
        .replace(/([a-z])([0-9])/gi, '$1 $2')
        .replace(/([0-9])([a-z])/gi, '$1 $2');
}

Test cases:

null => ''
'' => ''
'simpleString' => 'Simple String'
'stringWithABBREVIATIONInside => 'String With ABBREVIATION Inside'
'stringWithNumber123' => 'String With Number 123'
'complexExampleWith123ABBR890Etc' => 'Complex Example With 123 ABBR 890 Etc'
Towrope answered 12/2, 2016 at 12:27 Comment(0)
I
2

This works for me check this out

CamelcaseToWord("MyName"); // returns My Name

    function CamelcaseToWord(string){
      return string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1");
    }
Inefficacy answered 23/6, 2016 at 12:10 Comment(2)
Welcome to SO :) Please add at least one explanatory line to your code. Also ensure it is your intellectual work or cite the source(s).Bezanson
You should remove space in a lat one " $1". string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, "$1");Piapiacenza
N
2

I didn't try everyone's answer, but the few solutions I tinkered with did not match all of my requirements.

I was able to come up with something that did...

export const jsObjToCSSString = (o={}) =>
    Object.keys(o)
          .map(key => ({ key, value: o[key] }))
          .map(({key, value}) =>
              ({
                key: key.replace( /([A-Z])/g, "-$1").toLowerCase(),
                value
              })
          )
          .reduce(
              (css, {key, value}) => 
                  `${css} ${key}: ${value}; `.trim(), 
              '')
Nodal answered 21/10, 2016 at 22:20 Comment(0)
S
2

I think this can be done just with the reg exp /([a-z]|[A-Z]+)([A-Z])/g and replacement "$1 $2".

ILoveTheUSADope -> I Love The USA Dope

Secrete answered 23/9, 2018 at 0:11 Comment(1)
Not exactly, for string QWERTY it returns QWERT Y.Topside
L
1

Below is link which demonstrates camel case string to sentence string using regex.

Input

myCamelCaseSTRINGToSPLITDemo

Output

my Camel Case STRING To SPLIT Demo


This is regex for conversion of camel case to sentence text

(?=[A-Z][a-z])|([A-Z]+)([A-Z][a-rt-z][a-z]\*)

with $1 $2 as subsitution.

Click to view the conversion on regex

Lum answered 21/6, 2018 at 12:51 Comment(1)
Provide the relevant content from your link in the body of your answer.Flitting
D
1

Input javaScript

Output Java Script

   var text = 'javaScript';
    text.replace(/([a-z])([A-Z][a-z])/g, "$1 $2").charAt(0).toUpperCase()+text.slice(1).replace(/([a-z])([A-Z][a-z])/g, "$1 $2");
Danell answered 19/8, 2019 at 11:31 Comment(0)
W
0

Undercover C programmer. If like me you want to preserve acronyms and don't want to look at cryptic patterns, then perhaps you may like this:

function isUpperCase (str) {
  return str === str.toUpperCase()
}

export function camelCaseToTitle (str) {
  for (let i = str.length - 1; i > 0; i--) {
    if (!isUpperCase(str[i - 1]) && isUpperCase(str[i])) {
      str = str.slice(0, i) + ' ' + str.slice(i)
    }
  }
  return str.charAt(0).toUpperCase() + str.slice(1)
}
Winter answered 3/12, 2020 at 18:17 Comment(0)
B
0

This solution works also for other Unicode characters which are not in the [A-Z] range. E.g. Ä, Ö, Å.

let camelCaseToTitleCase = (s) => (
  s.split("").reduce(
    (acc, letter, i) => (
      i === 0 || console.log(acc, letter, i)
        ? [...acc, letter.toUpperCase()] 
        : letter === letter.toUpperCase()
        ? [...acc, " ", letter]
        : [...acc, letter] 
    ), []
  ).join("")
)

const myString = "ArchipelagoOfÅland"
camelCaseToTitleCase(myString)
Balaton answered 17/8, 2021 at 17:39 Comment(0)
S
0
.replace(/([a-z])([A-Z])/g, '$1 $2')
.replace(/([A-Z]+)([A-Z][a-z]+)/g, '$1 $2')
.replace(/^./, m => m.toUpperCase())

First RE: replaces ‘xyzABCDef’ with ‘xyz ABCDef’

Second RE: replaces ‘xyz ABCDef’ with ‘xyz ABC Def’

Third one: uppercases first letter

Sestet answered 8/3, 2023 at 13:56 Comment(3)
Never write an regexp anywhere without a comment or a description on what it does. This goes twice here on SO - answers without it are just useless.Gabel
Is the edited version ok now?Sestet
I like this answer for simplicity. I just added a little from the HTTPRequest_ToServer-AndWaiting --> HTTP Request To Server And Waiting answer to get what I wanted:Cheeky
O
0

The above solutions all work great. Here's another if there are multiple consecutive capital letters:

const myString = 'helloWorldUSA'

const myOutput = myString.replace(/([a-z])([A-Z])/gu, '$1 $2')
  .replace(/([A-Z]+)([A-Z][a-z])/gu, '$1 $2')
  .replace(/^./u, (str) => str.toUpperCase());
  
 console.log(myOutput) // Hello World USA
Oilskin answered 11/4 at 8:27 Comment(0)
O
-1

Adding yet another ES6 solution that I liked better after not being happy with a few thoughts above.

https://codepen.io/902Labs/pen/mxdxRv?editors=0010#0

const camelize = (str) => str
    .split(' ')
    .map(([first, ...theRest]) => (
        `${first.toUpperCase()}${theRest.join('').toLowerCase()}`)
    )
    .join(' ');
Oliver answered 9/3, 2018 at 2:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.