hypertune
Version:
[Hypertune](https://www.hypertune.com/) is the most flexible platform for feature flags, A/B testing, analytics and app configuration. Built with full end-to-end type-safety, Git-style version control and local, synchronous, in-memory flag evaluation. Opt
62 lines (55 loc) • 2.03 kB
text/typescript
/**
* @param s A string in camel, pascal, snake, kebab and spaced case format.
* @returns The string broken into an array of words.
* @example toWords("convertMy_string") === ["convert", "My", "string"]
*/
export default function toWords(s: string): string[] {
if (!s) {
return [];
}
const starts: number[] = [0];
for (let i = 1; i < s.length; i += 1) {
if (
// Break if we've switched to uppercase e.g. someThing
(isLowerCase(s[i - 1]) && isUpperCase(s[i])) ||
// Break if we're about to switch to lowercase, e.g. HTTPRequest
(i + 1 < s.length && isUpperCase(s[i]) && isLowerCase(s[i + 1])) ||
// Break at numbers if we're not:
// - previously uppercase e.g. HTTP2
// - just 1 letter e.g. v2
// - just 2 letters and following character is not a number e.g. mp4
// - part of a sequence of numbers e.g. 1234
(isNumber(s[i]) &&
!isUpperCase(s[i - 1]) &&
!(i - starts[starts.length - 1] === 1) &&
!(
i - starts[starts.length - 1] === 2 &&
i + 1 < s.length &&
!isNumber(s[i + 1])
) &&
!isNumber(s[i - 1])) ||
// Break after separator symbols
isSeparator(s[i - 1])
) {
// Start new word if this character is upper case and previous one isn't
// or if this character is a number and previous one isn't
starts.push(i);
}
}
const words = starts.map((_, index) =>
s.slice(starts[index], starts[index + 1])
);
return words.map((word) => word.replace(/[_ -]/g, "").trim()).filter(Boolean);
}
function isUpperCase(char: string): boolean {
return !isNumber(char) && !isSeparator(char) && char === char.toUpperCase();
}
function isLowerCase(char: string): boolean {
return !isNumber(char) && !isSeparator(char) && char === char.toLowerCase();
}
function isNumber(char: string): boolean {
return "0123456789".includes(char);
}
function isSeparator(char: string): boolean {
return char === "_" || char === "-" || char === " ";
}