UNPKG

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
/** * @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 === " "; }