splitWords function
Splits a string into words, whatever its case style (camelCase, kebab-case, snake_case, spaces…), in one pass. Acronyms and numbers are words of their own.
ts
import { splitWords } from 'utils';Signature
ts
export function splitWords(input: string): string[]Parameters
| Name | Description |
|---|---|
input | The identifier or sentence to split, in any case style. |
Returns
The words, with their original case; empty when there is none.
Example
ts
splitWords('XMLHttpRequest'); // ['XML', 'Http', 'Request']
splitWords('user_id-v2 Name'); // ['user', 'id', 'v', '2', 'Name']Tests
Line coverage: 100 %.
- ✅ splits "helloWorld"
- ✅ splits "HelloWorld"
- ✅ splits "hello-world"
- ✅ splits "hello_world"
- ✅ splits "HELLO_WORLD"
- ✅ splits " hello world "
- ✅ splits "XMLHttpRequest"
- ✅ splits "getHTTPStatus"
- ✅ splits "speed2Knots"
- ✅ splits "élémentÉtat"
- ✅ splits "a.b/c"
- ✅ returns no word for ""
- ✅ returns no word for " "
- ✅ returns no word for "-_./"
Source
src/string/split-words.ts (on GitHub)
Used by
camelCase: Converts a string to camelCase; acronyms are words (XMLHttpRequest→xmlHttpRequest).constantCase: Converts a string to CONSTANT_CASE: uppercase words joined with_, as in constants and environment variables.dotCase: Converts a string to dot.case: lower-case words joined with., as in translation keys and property paths.kebabCase: Converts a string to kebab-case: lowercase words joined with-, as in file names, CSS classes and URLs.lowerCase: Converts a string to lower-case words separated by spaces, splitting identifiers such ascamelCase.pascalCase: Converts a string to PascalCase: words joined, each capitalized, the rest in lower case.sentenceCase: Converts an identifier to a sentence, to turn a key into a label: the first word capitalized, the others in lower case, acronyms kept.snakeCase: Converts a string to snake_case: lowercase words joined with_, as in database columns and JSON keys.titleCase: Converts a string to Title Case: words separated by spaces, each capitalized, acronyms kept.trainCase: Converts a string to Train-Case: capitalized words joined with-, as in HTTP header names.upperCase: Converts a string to upper-case words separated by spaces, splitting identifiers such ascamelCase.
Source code
ts
const DIGIT_PATTERN = /^\p{N}$/v;
type CharacterKind = 'digit' | 'lower' | 'separator' | 'upper';
function isBoundary(previous: CharacterKind, current: CharacterKind): boolean {
const isLetterToDigit = (previous === 'digit') !== (current === 'digit');
return previous !== 'separator' && ((previous === 'lower' && current === 'upper') || isLetterToDigit);
}
function kindOf(character: string): CharacterKind {
if (character !== character.toLowerCase()) {
return 'upper';
}
if (character !== character.toUpperCase()) {
return 'lower';
}
return DIGIT_PATTERN.test(character) ? 'digit' : 'separator';
}
/**
* Splits a string into words, whatever its case style (camelCase, kebab-case, snake_case, spaces…), in one
* pass. Acronyms and numbers are words of their own.
*
* @param input - The identifier or sentence to split, in any case style.
* @returns The words, with their original case; empty when there is none.
* @example
* splitWords('XMLHttpRequest'); // ['XML', 'Http', 'Request']
* splitWords('user_id-v2 Name'); // ['user', 'id', 'v', '2', 'Name']
*/
export function splitWords(input: string): string[] {
const result: string[] = [];
let word = '';
let previous: CharacterKind = 'separator';
for (const character of input) {
const kind = kindOf(character);
if (kind === 'separator') {
if (word !== '') {
result.push(word);
}
word = '';
} else if (isBoundary(previous, kind)) {
result.push(word);
word = character;
} else if (previous === 'upper' && kind === 'lower' && word.length > 1) {
const lastCapital = word.slice(-1);
result.push(word.slice(0, -1));
word = lastCapital + character;
} else {
word += character;
}
previous = kind;
}
if (word !== '') {
result.push(word);
}
return result;
}Test file
ts
import { splitWords } from './split-words';
describe(splitWords, () => {
it.for([
['helloWorld', ['hello', 'World']],
['HelloWorld', ['Hello', 'World']],
['hello-world', ['hello', 'world']],
['hello_world', ['hello', 'world']],
['HELLO_WORLD', ['HELLO', 'WORLD']],
[' hello world ', ['hello', 'world']],
['XMLHttpRequest', ['XML', 'Http', 'Request']],
['getHTTPStatus', ['get', 'HTTP', 'Status']],
['speed2Knots', ['speed', '2', 'Knots']],
['élémentÉtat', ['élément', 'État']],
['a.b/c', ['a', 'b', 'c']],
] as const)('splits %j', ([input, expected]) => {
expect(splitWords(input)).toStrictEqual(expected);
});
it.for(['', ' '.repeat(3), '-_./'])('returns no word for %j', (input) => {
expect(splitWords(input)).toStrictEqual([]);
});
});Keywords: split, words, strings, function