str-case-converter
Version:
A utility for converting strings between different case formats.
182 lines (167 loc) • 5.91 kB
JavaScript
/**
* Utility for converting strings between different case formats.
*
* @supported Case Types
* - camelCase: 'helloWorld'
* - PascalCase: 'HelloWorld'
* - snake_case: 'hello_world'
* - kebab-case: 'hello-world'
* - CONSTANT_CASE: 'HELLO_WORLD'
* - Title Case: 'Hello World'
* - dot.case: 'hello.world'
* - no case: 'hello world'
* - Sentence case: 'Hello world'
* - path/case: 'hello/world'
*
* @example
* // Basic usage (auto-detects source case)
* convertString.toCamel('hello-world') // 'helloWorld'
* convertString.toSnake('helloWorld') // 'hello_world'
*
* // With source case parameter for better performance
* convertString.toCamel('Hello World', 'title') // 'helloWorld'
* convertString.toSnake('HelloWorld', 'pascal') // 'hello_world'
*
* // Utility methods
* convertString.detect('helloWorld') // 'camel'
* convertString.toArray('hello-world') // ['hello', 'world']
* convertString.capitalize('hello') // 'Hello'
*/
const CASE_TYPES = {
CAMEL: 'camel',
PASCAL: 'pascal',
SNAKE: 'snake',
KEBAB: 'kebab',
CONSTANT: 'constant',
TITLE: 'title',
DOT: 'dot',
NO: 'no',
SENTENCE: 'sentence',
PATH: 'path',
};
/**
* Detects the case type of a given string
* @param {string} str - Input string
* @returns {string|null} Detected case type or null if unknown
*/
function detectCase(str) {
if (/^[a-z]+[A-Z][a-zA-Z0-9]*$/.test(str)) return CASE_TYPES.CAMEL;
if (/^[A-Z][a-zA-Z0-9]*$/.test(str)) return CASE_TYPES.PASCAL;
if (/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/.test(str)) return CASE_TYPES.SNAKE;
if (/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(str)) return CASE_TYPES.KEBAB;
if (/^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/.test(str)) return CASE_TYPES.CONSTANT;
if (/^[a-z][a-z0-9]*(\.[a-z0-9]+)*$/.test(str)) return CASE_TYPES.DOT;
if (/^[A-Z][a-z]*(\s[A-Z][a-z]*)*$/.test(str)) return CASE_TYPES.TITLE;
if (/^[a-z][a-z0-9]*(\s[a-z0-9]+)*$/.test(str)) return CASE_TYPES.NO;
if (/^[A-Z][a-z0-9]*(\s[a-z0-9]+)*$/.test(str)) return CASE_TYPES.SENTENCE;
if (/^[a-z][a-z0-9]*(\/[a-z0-9]+)*$/.test(str)) return CASE_TYPES.PATH;
return null;
}
/**
* Splits a string into an array of words based on its case type
* @param {string} str - Input string
* @param {string} sourceCase - Source case type
* @returns {string[]} Array of words
*/
function splitIntoWords(str, sourceCase) {
switch (sourceCase) {
case CASE_TYPES.CAMEL:
case CASE_TYPES.PASCAL:
return str
.replace(/(?<![A-Z])([A-Z])/g, ' $1')
.replace(/(?<![0-9])([0-9])/g, ' $1')
.trim()
.toLowerCase()
.split(' ')
.filter(Boolean);
case CASE_TYPES.SNAKE:
return str.split('_').filter(Boolean);
case CASE_TYPES.KEBAB:
return str.split('-').filter(Boolean);
case CASE_TYPES.CONSTANT:
return str.toLowerCase().split('_').filter(Boolean);
case CASE_TYPES.DOT:
return str.split('.').filter(Boolean);
case CASE_TYPES.TITLE:
case CASE_TYPES.SENTENCE:
return str.toLowerCase().split(' ').filter(Boolean);
case CASE_TYPES.NO:
return str.split(' ').filter(Boolean);
case CASE_TYPES.PATH:
return str.split('/').filter(Boolean);
default:
return str
.replace(/(?<![A-Z])([A-Z])/g, ' $1')
.replace(/(?<![0-9])([0-9])/g, ' $1')
.replace(/[-_\.]/g, ' ')
.replace(/\s+/g, ' ')
.trim()
.toLowerCase()
.split(' ')
.filter(Boolean);
}
}
/**
* Converts a string to an array of words regardless of its original case
* @param {string} str - Input string
* @param {string} [sourceCase] - Optional source case type for better performance
* ('camel', 'pascal', 'snake', 'kebab', 'constant', 'title', 'dot')
* @returns {string[]} Array of words
*/
function convertToArray(str, sourceCase) {
str = String(str);
return splitIntoWords(str, sourceCase || detectCase(str));
}
/**
* Capitalize the first character of a string
* @param {string} str - Input string
* @returns {string} The string capitalized
*/
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
/**
* String conversion utility object with methods for each case type
*/
export const convertString = {
toCamel: (str, sourceCase) => {
return convertToArray(str, sourceCase)
.map((word, i) => (i === 0 ? word : capitalize(word)))
.join('');
},
toPascal: (str, sourceCase) => {
return convertToArray(str, sourceCase)
.map((word) => capitalize(word))
.join('');
},
toSnake: (str, sourceCase) => {
return convertToArray(str, sourceCase).join('_');
},
toKebab: (str, sourceCase) => {
return convertToArray(str, sourceCase).join('-');
},
toConstant: (str, sourceCase) => {
return convertToArray(str, sourceCase).join('_').toUpperCase();
},
toTitle: (str, sourceCase) => {
return convertToArray(str, sourceCase)
.map((word) => capitalize(word))
.join(' ');
},
toDot: (str, sourceCase) => {
return convertToArray(str, sourceCase).join('.');
},
toNo: (str, sourceCase) => {
return convertToArray(str, sourceCase).join(' ');
},
toSentence: (str, sourceCase) => {
const words = convertToArray(str, sourceCase);
return words.map((word, i) => (i === 0 ? capitalize(word) : word)).join(' ');
},
toPath: (str, sourceCase) => {
return convertToArray(str, sourceCase).join('/');
},
detect: detectCase,
toArray: convertToArray,
capitalize: capitalize,
};