Repository: sindresorhus/camelcase
Pull request #102 (2022-12-13 12:12:31)

Update preserveCamelCase method
**What is the PR for?**

Closes [#95](https://github.com/sindresorhus/camelcase/issues/95). It ensure that `preserveCamelCase` method doesn't ignore `preserveConsecutiveUppercase` option.
 It fixes some failing test cases which contains Consecutive upper case characters.

**Checklist**
- [x]  I have read the documentation.
- [x] I have included a pull request description of my changes.
- [x] I have included some tests.



Patch:
diff --git a/index.js b/index.js
index 6e350bd..6d80316 100644
--- a/index.js
+++ b/index.js
@@ -8,13 +8,15 @@ const LEADING_SEPARATORS = new RegExp('^' + SEPARATORS.source);
 const SEPARATORS_AND_IDENTIFIER = new RegExp(SEPARATORS.source + IDENTIFIER.source, 'gu');
 const NUMBERS_AND_IDENTIFIER = new RegExp('\\d+' + IDENTIFIER.source, 'gu');
 
-const preserveCamelCase = (string, toLowerCase, toUpperCase) => {
+const preserveCamelCase = (string, toLowerCase, toUpperCase, preserveConsecutiveUppercase) => {
 	let isLastCharLower = false;
 	let isLastCharUpper = false;
 	let isLastLastCharUpper = false;
+	let isLastLastCharPreserved = false;
 
 	for (let index = 0; index < string.length; index++) {
 		const character = string[index];
+		isLastLastCharPreserved = index > 2 ? string[index - 3] === '-' : true;
 
 		if (isLastCharLower && UPPERCASE.test(character)) {
 			string = string.slice(0, index) + '-' + string.slice(index);
@@ -22,7 +24,7 @@ const preserveCamelCase = (string, toLowerCase, toUpperCase) => {
 			isLastLastCharUpper = isLastCharUpper;
 			isLastCharUpper = true;
 			index++;
-		} else if (isLastCharUpper && isLastLastCharUpper && LOWERCASE.test(character)) {
+		} else if (isLastCharUpper && isLastLastCharUpper && LOWERCASE.test(character) && (!isLastLastCharPreserved || preserveConsecutiveUppercase)) {
 			string = string.slice(0, index - 1) + '-' + string.slice(index - 1);
 			isLastLastCharUpper = isLastCharUpper;
 			isLastCharUpper = false;
@@ -93,7 +95,7 @@ export default function camelCase(input, options) {
 	const hasUpperCase = input !== toLowerCase(input);
 
 	if (hasUpperCase) {
-		input = preserveCamelCase(input, toLowerCase, toUpperCase);
+		input = preserveCamelCase(input, toLowerCase, toUpperCase, options.preserveConsecutiveUppercase);
 	}
 
 	input = input.replace(LEADING_SEPARATORS, '');


Test patch:
diff --git a/test.js b/test.js
index d3cbc27..306b437 100644
--- a/test.js
+++ b/test.js
@@ -3,9 +3,8 @@ import camelCase from './index.js';
 
 test('camelCase', t => {
 	t.is(camelCase('foo'), 'foo');
-	/// https://github.com/sindresorhus/camelcase/issues/95
-	/// t.is(camelCase('IDs'), 'ids');
-	/// t.is(camelCase('FooIDs'), 'fooIds');
+	t.is(camelCase('IDs'), 'ids');
+	t.is(camelCase('FooIDs'), 'fooIds');
 	t.is(camelCase('foo-bar'), 'fooBar');
 	t.is(camelCase('foo-bar-baz'), 'fooBarBaz');
 	t.is(camelCase('foo--bar'), 'fooBar');
@@ -170,8 +169,7 @@ test('camelCase with preserveConsecutiveUppercase option', t => {
 	t.is(camelCase('РозовыйПушистыйFOOдинорогиf', {preserveConsecutiveUppercase: true}), 'розовыйПушистыйFOOдинорогиf');
 	t.is(camelCase('桑德在这里。', {preserveConsecutiveUppercase: true}), '桑德在这里。');
 	t.is(camelCase('桑德_在这里。', {preserveConsecutiveUppercase: true}), '桑德在这里。');
-	/// https://github.com/sindresorhus/camelcase/issues/95
-	/// t.is(camelCase('IDs', {preserveConsecutiveUppercase: true}), 'ids');
+	t.is(camelCase('IDs', {preserveConsecutiveUppercase: true}), 'iDs');
 	t.is(camelCase('FooIDs', {preserveConsecutiveUppercase: true}), 'fooIDs');
 });