Skip to content

Commit

Permalink
Require Node.js 14 and move to ESM
Browse files Browse the repository at this point in the history
Closes #83
  • Loading branch information
sindresorhus committed Jun 6, 2022
1 parent 6f12d6d commit 1d2e9e1
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 90 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ jobs:
- 18
- 16
- 14
- 12
- 10
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
Expand Down
89 changes: 44 additions & 45 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,44 @@
declare namespace camelcase {
interface Options {
/**
Uppercase the first character: `foo-bar` → `FooBar`.
@default false
*/
readonly pascalCase?: boolean;

/**
Preserve the consecutive uppercase characters: `foo-BAR` → `FooBAR`.
@default false
*/
readonly preserveConsecutiveUppercase?: boolean;

/**
The locale parameter indicates the locale to be used to convert to upper/lower case according to any locale-specific case mappings. If multiple locales are given in an array, the best available locale is used.
Setting `locale: false` ignores the platform locale and uses the [Unicode Default Case Conversion](https://unicode-org.github.io/icu/userguide/transforms/casemappings.html#simple-single-character-case-mapping) algorithm.
Default: The host environment’s current locale.
@example
```
import camelCase = require('camelcase');
camelCase('lorem-ipsum', {locale: 'en-US'});
//=> 'loremIpsum'
camelCase('lorem-ipsum', {locale: 'tr-TR'});
//=> 'loremİpsum'
camelCase('lorem-ipsum', {locale: ['en-US', 'en-GB']});
//=> 'loremIpsum'
camelCase('lorem-ipsum', {locale: ['tr', 'TR', 'tr-TR']});
//=> 'loremİpsum'
```
*/
readonly locale?: false | string | readonly string[];
}
}
export type Options = {
/**
Uppercase the first character: `foo-bar` → `FooBar`.
@default false
*/
readonly pascalCase?: boolean;

/**
Preserve consecutive uppercase characters: `foo-BAR` → `FooBAR`.
@default false
*/
readonly preserveConsecutiveUppercase?: boolean;

/**
The locale parameter indicates the locale to be used to convert to upper/lower case according to any locale-specific case mappings. If multiple locales are given in an array, the best available locale is used.
Setting `locale: false` ignores the platform locale and uses the [Unicode Default Case Conversion](https://unicode-org.github.io/icu/userguide/transforms/casemappings.html#simple-single-character-case-mapping) algorithm.
Default: The host environment’s current locale.
@example
```
import camelCase from 'camelcase';
camelCase('lorem-ipsum', {locale: 'en-US'});
//=> 'loremIpsum'
camelCase('lorem-ipsum', {locale: 'tr-TR'});
//=> 'loremİpsum'
camelCase('lorem-ipsum', {locale: ['en-US', 'en-GB']});
//=> 'loremIpsum'
camelCase('lorem-ipsum', {locale: ['tr', 'TR', 'tr-TR']});
//=> 'loremİpsum'
```
*/
readonly locale?: false | string | readonly string[];
};

/**
Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`.
Expand All @@ -48,7 +49,7 @@ Correctly handles Unicode strings.
@example
```
import camelCase = require('camelcase');
import camelCase from 'camelcase';
camelCase('foo-bar');
//=> 'fooBar'
Expand Down Expand Up @@ -95,9 +96,7 @@ camelCase('lorem-ipsum', {locale: 'en-US'});
//=> 'loremIpsum'
```
*/
declare function camelcase(
export default function camelcase(
input: string | readonly string[],
options?: camelcase.Options
options?: Options
): string;

export = camelcase;
42 changes: 16 additions & 26 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

const UPPERCASE = /[\p{Lu}]/u;
const LOWERCASE = /[\p{Ll}]/u;
const LEADING_CAPITAL = /^[\p{Lu}](?![\p{Lu}])/gu;
Expand All @@ -15,17 +13,17 @@ const preserveCamelCase = (string, toLowerCase, toUpperCase) => {
let isLastCharUpper = false;
let isLastLastCharUpper = false;

for (let i = 0; i < string.length; i++) {
const character = string[i];
for (let index = 0; index < string.length; index++) {
const character = string[index];

if (isLastCharLower && UPPERCASE.test(character)) {
string = string.slice(0, i) + '-' + string.slice(i);
string = string.slice(0, index) + '-' + string.slice(index);
isLastCharLower = false;
isLastLastCharUpper = isLastCharUpper;
isLastCharUpper = true;
i++;
index++;
} else if (isLastCharUpper && isLastLastCharUpper && LOWERCASE.test(character)) {
string = string.slice(0, i - 1) + '-' + string.slice(i - 1);
string = string.slice(0, index - 1) + '-' + string.slice(index - 1);
isLastLastCharUpper = isLastCharUpper;
isLastCharUpper = false;
isLastCharLower = true;
Expand Down Expand Up @@ -53,15 +51,15 @@ const postProcess = (input, toUpperCase) => {
.replace(NUMBERS_AND_IDENTIFIER, m => toUpperCase(m));
};

const camelCase = (input, options) => {
export default function camelCase(input, options) {
if (!(typeof input === 'string' || Array.isArray(input))) {
throw new TypeError('Expected the input to be `string | string[]`');
}

options = {
pascalCase: false,
preserveConsecutiveUppercase: false,
...options
...options,
};

if (Array.isArray(input)) {
Expand All @@ -76,12 +74,13 @@ const camelCase = (input, options) => {
return '';
}

const toLowerCase = options.locale === false ?
string => string.toLowerCase() :
string => string.toLocaleLowerCase(options.locale);
const toUpperCase = options.locale === false ?
string => string.toUpperCase() :
string => string.toLocaleUpperCase(options.locale);
const toLowerCase = options.locale === false
? string => string.toLowerCase()
: string => string.toLocaleLowerCase(options.locale);

const toUpperCase = options.locale === false
? string => string.toUpperCase()
: string => string.toLocaleUpperCase(options.locale);

if (input.length === 1) {
if (SEPARATORS.test(input)) {
Expand All @@ -98,20 +97,11 @@ const camelCase = (input, options) => {
}

input = input.replace(LEADING_SEPARATORS, '');

if (options.preserveConsecutiveUppercase) {
input = preserveConsecutiveUppercase(input, toLowerCase);
} else {
input = toLowerCase(input);
}
input = options.preserveConsecutiveUppercase ? preserveConsecutiveUppercase(input, toLowerCase) : toLowerCase(input);

if (options.pascalCase) {
input = toUpperCase(input.charAt(0)) + input.slice(1);
}

return postProcess(input, toUpperCase);
};

module.exports = camelCase;
// TODO: Remove this for the next major release
module.exports.default = camelCase;
}
2 changes: 1 addition & 1 deletion index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {expectType} from 'tsd';
import camelCase = require('.');
import camelCase from './index.js';

expectType<string>(camelCase('foo-bar'));
expectType<string>(camelCase('розовый_пушистый_единороги'));
Expand Down
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": "./index.js",
"types": "./index.d.ts",
"engines": {
"node": ">=10"
"node": ">=14.16"
},
"scripts": {
"test": "xo && ava && tsd"
Expand All @@ -37,8 +40,8 @@
"pascal-case"
],
"devDependencies": {
"ava": "^1.4.1",
"tsd": "^0.11.0",
"xo": "^0.28.3"
"ava": "^4.3.0",
"tsd": "^0.20.0",
"xo": "^0.49.0"
}
}
14 changes: 6 additions & 8 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ If you use this on untrusted user input, don't forget to limit the length to som

## Install

```sh
npm install camelcase
```
$ npm install camelcase
```

*If you need to support Firefox < 78, stay on version 5 as version 6 uses regex features not available in Firefox < 78.*

## Usage

```js
const camelCase = require('camelcase');
import camelCase from 'camelcase';

camelCase('foo-bar');
//=> 'fooBar'
Expand Down Expand Up @@ -90,7 +88,7 @@ Uppercase the first character: `foo-bar` → `FooBar`
Type: `boolean`\
Default: `false`

Preserve the consecutive uppercase characters: `foo-BAR``FooBAR`.
Preserve consecutive uppercase characters: `foo-BAR``FooBAR`.

##### locale

Expand All @@ -100,7 +98,7 @@ Default: The host environment’s current locale.
The locale parameter indicates the locale to be used to convert to upper/lower case according to any locale-specific case mappings. If multiple locales are given in an array, the best available locale is used.

```js
const camelCase = require('camelcase');
import camelCase from 'camelcase';

camelCase('lorem-ipsum', {locale: 'en-US'});
//=> 'loremIpsum'
Expand All @@ -118,7 +116,7 @@ camelCase('lorem-ipsum', {locale: ['tr', 'TR', 'tr-TR']});
Setting `locale: false` ignores the platform locale and uses the [Unicode Default Case Conversion](https://unicode-org.github.io/icu/userguide/transforms/casemappings.html#simple-single-character-case-mapping) algorithm:

```js
const camelCase = require('camelcase');
import camelCase from 'camelcase';

// On a platform with 'tr-TR'

Expand Down
10 changes: 6 additions & 4 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava';
import camelCase from '.';
import camelCase from './index.js';

test('camelCase', t => {
t.is(camelCase('foo'), 'foo');
Expand Down Expand Up @@ -228,7 +228,9 @@ test('camelCase with disabled locale', t => {
test('invalid input', t => {
t.throws(() => {
camelCase(1);
}, /Expected the input to be/);
}, {
message: /Expected the input to be/,
});
});

/* eslint-disable no-extend-native */
Expand All @@ -242,11 +244,11 @@ const withLocaleCaseFunctionsMocked = fn => {

Object.defineProperty(String.prototype, 'toLocaleUpperCase', {
...toLocaleUpperCase,
value: throwWhenBeingCalled
value: throwWhenBeingCalled,
});
Object.defineProperty(String.prototype, 'toLocaleLowerCase', {
...toLocaleLowerCase,
value: throwWhenBeingCalled
value: throwWhenBeingCalled,
});

try {
Expand Down

0 comments on commit 1d2e9e1

Please sign in to comment.