index.js
 1  'use strict';
 2  
 3  const preserveCamelCase = (string, locale) => {
 4  	let isLastCharLower = false;
 5  	let isLastCharUpper = false;
 6  	let isLastLastCharUpper = false;
 7  
 8  	for (let i = 0; i < string.length; i++) {
 9  		const character = string[i];
10  
11  		if (isLastCharLower && /[\p{Lu}]/u.test(character)) {
12  			string = string.slice(0, i) + '-' + string.slice(i);
13  			isLastCharLower = false;
14  			isLastLastCharUpper = isLastCharUpper;
15  			isLastCharUpper = true;
16  			i++;
17  		} else if (isLastCharUpper && isLastLastCharUpper && /[\p{Ll}]/u.test(character)) {
18  			string = string.slice(0, i - 1) + '-' + string.slice(i - 1);
19  			isLastLastCharUpper = isLastCharUpper;
20  			isLastCharUpper = false;
21  			isLastCharLower = true;
22  		} else {
23  			isLastCharLower = character.toLocaleLowerCase(locale) === character && character.toLocaleUpperCase(locale) !== character;
24  			isLastLastCharUpper = isLastCharUpper;
25  			isLastCharUpper = character.toLocaleUpperCase(locale) === character && character.toLocaleLowerCase(locale) !== character;
26  		}
27  	}
28  
29  	return string;
30  };
31  
32  const preserveConsecutiveUppercase = input => {
33  	return input.replace(/^[\p{Lu}](?![\p{Lu}])/gu, m1 => m1.toLowerCase());
34  };
35  
36  const postProcess = (input, options) => {
37  	return input.replace(/[_.\- ]+([\p{Alpha}\p{N}_]|$)/gu, (_, p1) => p1.toLocaleUpperCase(options.locale))
38  		.replace(/\d+([\p{Alpha}\p{N}_]|$)/gu, m => m.toLocaleUpperCase(options.locale));
39  };
40  
41  const camelCase = (input, options) => {
42  	if (!(typeof input === 'string' || Array.isArray(input))) {
43  		throw new TypeError('Expected the input to be `string | string[]`');
44  	}
45  
46  	options = {
47  		pascalCase: false,
48  		preserveConsecutiveUppercase: false,
49  		...options
50  	};
51  
52  	if (Array.isArray(input)) {
53  		input = input.map(x => x.trim())
54  			.filter(x => x.length)
55  			.join('-');
56  	} else {
57  		input = input.trim();
58  	}
59  
60  	if (input.length === 0) {
61  		return '';
62  	}
63  
64  	if (input.length === 1) {
65  		return options.pascalCase ? input.toLocaleUpperCase(options.locale) : input.toLocaleLowerCase(options.locale);
66  	}
67  
68  	const hasUpperCase = input !== input.toLocaleLowerCase(options.locale);
69  
70  	if (hasUpperCase) {
71  		input = preserveCamelCase(input, options.locale);
72  	}
73  
74  	input = input.replace(/^[_.\- ]+/, '');
75  
76  	if (options.preserveConsecutiveUppercase) {
77  		input = preserveConsecutiveUppercase(input);
78  	} else {
79  		input = input.toLocaleLowerCase();
80  	}
81  
82  	if (options.pascalCase) {
83  		input = input.charAt(0).toLocaleUpperCase(options.locale) + input.slice(1);
84  	}
85  
86  	return postProcess(input, options);
87  };
88  
89  module.exports = camelCase;
90  // TODO: Remove this for the next major release
91  module.exports.default = camelCase;