1

I found myself needing to do camel case to sentence case string conversion with sane acronym support, a google search for ideas led me to the following SO post:

Convert camelCaseText to Sentence Case Text

Which is actually asking about title case not sentence case so I came up with the following solution which maybe others will find helpful or can offer improvements to, it is using ES6 which is acceptable for me and can easily be polyfilled if there's some horrible IE requirement.

RichTurner
  • 797
  • 7
  • 14

1 Answers1

2

The below uses capitalised notation for acronyms; I don't agree with Microsoft's recommendation of capitalising when more than two characters so this expects the whole acronym to be capitalised even if it's at the start of the string (which technically means it's not camel case but it gives sane controllable output), multiple consecutive acronyms can be escaped with _ (e.g. parseDBM_MXL -> Parse DBM XML).

function camelToSentenceCase(str) {
    return str.split(/([A-Z]|\d)/).map((v, i, arr) => {
        // If first block then capitalise 1st letter regardless
        if (!i) return v.charAt(0).toUpperCase() + v.slice(1);
        // Skip empty blocks
        if (!v) return v;
        // Underscore substitution
        if (v === '_') return " ";
        // We have a capital or number
        if (v.length === 1 && v === v.toUpperCase()) {
            const previousCapital = !arr[i-1] || arr[i-1] === '_';
            const nextWord = i+1 < arr.length && arr[i+1] && arr[i+1] !== '_';
            const nextTwoCapitalsOrEndOfString = i+3 > arr.length || !arr[i+1] && !arr[i+3];
            // Insert space
            if (!previousCapital || nextWord) v = " " + v;
            // Start of word or single letter word
            if (nextWord || (!previousCapital && !nextTwoCapitalsOrEndOfString)) v = v.toLowerCase();
        }
        return v;
    }).join("");
}


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

var testSet = [
    'camelCase',
    'camelTOPCase',
    'aP2PConnection',
    'JSONIsGreat',
    'thisIsALoadOfJSON',
    'parseDBM_XML',
    'superSimpleExample',
    'aGoodIPAddress'
];

testSet.forEach(function(item) {
    console.log(item, '->', camelToSentenceCase(item));
});
RichTurner
  • 797
  • 7
  • 14
  • 1
    If you answer your own question you should still mark it as an accepted an accepted answer. Else others will think it is still unresolved – A_A Jan 13 '21 at 22:16
  • Can only do that after a certain amount of time has elapsed. – RichTurner Jan 15 '21 at 08:45