index.js 2.5 KB

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