Skip to content

Commit

Permalink
Move to ESM (#33)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
LitoMore and sindresorhus committed Oct 1, 2021
1 parent 0586fe4 commit 2597adb
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 94 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ jobs:
fail-fast: false
matrix:
node-version:
- 16
- 14
- 12
- 10
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
61 changes: 29 additions & 32 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,39 @@
declare namespace decamelize {
interface Options {
/**
Character or string inserted to separate words in `string`.
export interface Options {
/**
Character or string inserted to separate words in `string`.
@default '_'
@default '_'
@example
```
import decamelize = require('decamelize');
@example
```
import decamelize from 'decamelize';
decamelize('unicornRainbow');
//=> 'unicorn_rainbow'
decamelize('unicornRainbow');
//=> 'unicorn_rainbow'
decamelize('unicornRainbow', {separator: '-'});
//=> 'unicorn-rainbow'
```
*/
readonly separator?: string;
decamelize('unicornRainbow', {separator: '-'});
//=> 'unicorn-rainbow'
```
*/
readonly separator?: string;

/**
Preserve sequences of uppercase characters.
/**
Preserve sequences of uppercase characters.
@default false
@default false
@example
```
import decamelize = require('decamelize');
@example
```
import decamelize from 'decamelize';
decamelize('testGUILabel');
//=> 'test_gui_label'
decamelize('testGUILabel');
//=> 'test_gui_label'
decamelize('testGUILabel', {preserveConsecutiveUppercase: true});
//=> 'test_GUI_label'
```
*/
readonly preserveConsecutiveUppercase?: boolean;
}
decamelize('testGUILabel', {preserveConsecutiveUppercase: true});
//=> 'test_GUI_label'
```
*/
readonly preserveConsecutiveUppercase?: boolean;
}

/**
Expand All @@ -45,7 +43,7 @@ Convert a camelized string into a lowercased one with a custom separator: `unico
@example
```
import decamelize = require('decamelize');
import decamelize from 'decamelize';
decamelize('unicornRainbow');
//=> 'unicorn_rainbow'
Expand All @@ -54,6 +52,5 @@ decamelize('unicornRainbow', {separator: '-'});
//=> 'unicorn-rainbow'
```
*/
declare function decamelize(string: string, options?: decamelize.Options): string;
export default function decamelize(string: string, options?: Options): string;

export = decamelize;
26 changes: 10 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
'use strict';

const handlePreserveConsecutiveUppercase = (decamelized, separator) => {
// Lowercase all single uppercase characters. As we
// want to preserve uppercase sequences, we cannot
// simply lowercase the separated string at the end.
// `data_For_USACounties` → `data_for_USACounties`
decamelized = decamelized.replace(
/((?<![\p{Uppercase_Letter}\d])[\p{Uppercase_Letter}\d](?![\p{Uppercase_Letter}\d]))/gu,
$0 => {
return $0.toLowerCase();
}
$0 => $0.toLowerCase(),
);

// Remaining uppercase sequences will be separated from lowercase sequences.
// `data_For_USACounties` → `data_for_USA_counties`
return decamelized.replace(
/(\p{Uppercase_Letter}+)(\p{Uppercase_Letter}\p{Lowercase_Letter}+)/gu,
(_, $1, $2) => {
return $1 + separator + $2.toLowerCase();
}
(_, $1, $2) => $1 + separator + $2.toLowerCase(),
);
};

module.exports = (
export default function decamelize(
text,
{
separator = '_',
preserveConsecutiveUppercase = false
} = {}
) => {
preserveConsecutiveUppercase = false,
} = {},
) {
if (!(typeof text === 'string' && typeof separator === 'string')) {
throw new TypeError(
'The `text` and `separator` arguments should be of type `string`'
'The `text` and `separator` arguments should be of type `string`',
);
}

Expand All @@ -47,7 +41,7 @@ module.exports = (
// `myURLstring → `my_URLstring`
const decamelized = text.replace(
/([\p{Lowercase_Letter}\d])(\p{Uppercase_Letter})/gu,
replacement
replacement,
);

if (preserveConsecutiveUppercase) {
Expand All @@ -59,7 +53,7 @@ module.exports = (
return decamelized
.replace(
/(\p{Uppercase_Letter})(\p{Uppercase_Letter}\p{Lowercase_Letter}+)/gu,
replacement
replacement,
)
.toLowerCase();
};
}
4 changes: 2 additions & 2 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {expectType} from 'tsd';
import decamelize = require('.');
import decamelize from './index.js';

expectType<string>(decamelize('unicornRainbow'));
expectType<string>(decamelize('unicornRainbow', {separator: '-'}));
expectType<string>(decamelize('unicornRainbow', {
separator: '-',
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}));
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">=10"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"scripts": {
"test": "xo && ava && tsd"
Expand All @@ -33,8 +35,9 @@
"convert"
],
"devDependencies": {
"ava": "^2.4.0",
"tsd": "^0.11.0",
"xo": "^0.24.0"
"ava": "^3.15.0",
"tsd": "^0.17.0",
"typescript": "^4.4.3",
"xo": "^0.44.0"
}
}
10 changes: 5 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ If you use this on untrusted user input, don't forget to limit the length to som

## Install

```
$ npm install decamelize
```sh
npm install decamelize
```

## Usage

```js
const decamelize = require('decamelize');
import decamelize from 'decamelize';

decamelize('unicornRainbow');
//=> 'unicorn_rainbow'
Expand Down Expand Up @@ -49,7 +49,7 @@ Default: `'_'`
Character or string inserted to separate words in `string`.

```js
cosnt decamelize = require('decamelize');
import decamelize from 'decamelize';

decamelize('unicornRainbow');
//=> 'unicorn_rainbow'
Expand All @@ -66,7 +66,7 @@ Default: `false`
Preserve sequences of uppercase characters.

```js
const decamelize = require('decamelize');
import decamelize from 'decamelize';

decamelize('testGUILabel');
//=> 'test_gui_label'
Expand Down
66 changes: 33 additions & 33 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava';
import decamelize from '.';
import decamelize from './index.js';

test('decamelize', t => {
t.is(decamelize(''), '');
Expand All @@ -19,7 +19,7 @@ test('decamelize', t => {
t.is(decamelize('unicornRainbow', {separator: '-'}), 'unicorn-rainbow');
t.is(
decamelize('thisHasSpecialCharactersLikeČandŠ', {separator: ' '}),
'this has special characters like čand š'
'this has special characters like čand š',
);
});

Expand All @@ -39,101 +39,101 @@ test('separator and options passed', t => {
t.is(
decamelize('testGUILabel', {
separator: '!',
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'test!GUI!label'
'test!GUI!label',
);
});

test('keeping blocks of consecutive uppercase characters but split the last if lowercase characters follow', t => {
t.is(
decamelize('A', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'A'
'A',
);
t.is(
decamelize('myURLString', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'my_URL_string'
'my_URL_string',
);
t.is(
decamelize('URLString', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'URL_string'
'URL_string',
);
t.is(
decamelize('oxygenO2Level', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'oxygen_O2_level'
'oxygen_O2_level',
);
t.is(
decamelize('StringURL', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'string_URL'
'string_URL',
);
t.is(
decamelize('STringURL', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'S_tring_URL'
'S_tring_URL',
);
t.is(
decamelize('numberOfDataForUSA', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'number_of_data_for_USA'
'number_of_data_for_USA',
);
t.is(
decamelize('testGUILabel', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'test_GUI_label'
'test_GUI_label',
);
t.is(
decamelize('CAPLOCKED1', {
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
'CAPLOCKED1'
'CAPLOCKED1',
);
});

test('long strings', t => {
// Factor to increase the test string
const times = 100;
const longString = 'Lb8SvAARMshcNvfxjgGCgfot3AZAzysuxRpG9XfpLCz89TeWqAd3TUo64K45VH2MfjLYhztt4LQYzrEbTpx7gGcG4T8ueKPm6VraXKtULJdncFQhEQfCRwWGNscdFe6UTEAvN7Nze4Qy4hvZuKLX5YiohGpvNZUtLGen3WP2jot8VeprzyXQmiKdxdxrEResSRgSWENCzXZPSerYuEfApVbjuDJZ9kGMRXFRZQVyBDDGfY9ERqtxHQxPw65TtEo3dgwhcuhvC3dMyRJ6jWaonKB3Pqtv27vRv5MgYb5mgvCE55oCTBG9yASPaw2KqYVz3amBge9HggEzXJGhwSXjkL7jUYk3WjQUbwVnZNHkH3P9MpvM98DtTnGAYfK5TjD8Y5oXPRJmdCHzhByboaW2oRJ2Ft7dxGKXLs2s7qsQs8FsJHVcYrmVHRa6th5CizHSXK7vr5D3KYsfsnr92AmtR4LERam7CV9emBBuykQJMejLGFsvgTrBKmmUqijxSgY'.repeat(
100
100,
);

t.is(
decamelize(longString),
new Array(times)
Array.from({length: times})
.fill(
'lb8_sv_aar_mshc_nvfxjg_g_cgfot3_az_azysux_rp_g9_xfp_l_cz89_te_wq_ad3_t_uo64_k45_vh2_mfj_l_yhztt4_lq_yzr_eb_tpx7g_gc_g4_t8ue_k_pm6_vra_x_kt_ul_jdnc_f_qh_e_qf_c_rw_wg_nscd_fe6_ute_av_n7_nze4_qy4hv_zu_klx5_yioh_gpv_nz_ut_l_gen3_wp2jot8_veprzy_x_qmi_kdxdxr_e_res_s_rg_swen_cz_xzp_ser_yu_ef_ap_vbju_djz9k_gmrxfrzq_vy_bdd_gf_y9_e_rqtx_h_qx_pw65_tt_eo3dgwhcuhv_c3d_my_rj6j_waon_kb3_pqtv27v_rv5_mg_yb5mgv_ce55o_ctbg9y_as_paw2_kq_y_vz3am_bge9_hgg_ez_xj_ghw_s_xjk_l7j_u_yk3_wj_q_ubw_vn_zn_hk_h3_p9_mpv_m98_dt_tn_ga_yf_k5_tj_d8_y5o_xpr_jmd_c_hzh_byboa_w2o_rj2_ft7dx_gkx_ls2s7qs_qs8_fs_jh_vc_yrm_vh_ra6th5_ciz_hsxk7vr5_d3_k_ysfsnr92_amt_r4_le_ram7_cv9em_b_buyk_qj_mej_lg_fsvg_tr_b_kmm_uqijx_sg_y'
'lb8_sv_aar_mshc_nvfxjg_g_cgfot3_az_azysux_rp_g9_xfp_l_cz89_te_wq_ad3_t_uo64_k45_vh2_mfj_l_yhztt4_lq_yzr_eb_tpx7g_gc_g4_t8ue_k_pm6_vra_x_kt_ul_jdnc_f_qh_e_qf_c_rw_wg_nscd_fe6_ute_av_n7_nze4_qy4hv_zu_klx5_yioh_gpv_nz_ut_l_gen3_wp2jot8_veprzy_x_qmi_kdxdxr_e_res_s_rg_swen_cz_xzp_ser_yu_ef_ap_vbju_djz9k_gmrxfrzq_vy_bdd_gf_y9_e_rqtx_h_qx_pw65_tt_eo3dgwhcuhv_c3d_my_rj6j_waon_kb3_pqtv27v_rv5_mg_yb5mgv_ce55o_ctbg9y_as_paw2_kq_y_vz3am_bge9_hgg_ez_xj_ghw_s_xjk_l7j_u_yk3_wj_q_ubw_vn_zn_hk_h3_p9_mpv_m98_dt_tn_ga_yf_k5_tj_d8_y5o_xpr_jmd_c_hzh_byboa_w2o_rj2_ft7dx_gkx_ls2s7qs_qs8_fs_jh_vc_yrm_vh_ra6th5_ciz_hsxk7vr5_d3_k_ysfsnr92_amt_r4_le_ram7_cv9em_b_buyk_qj_mej_lg_fsvg_tr_b_kmm_uqijx_sg_y',
)
.join('_')
.join('_'),
);
t.is(
decamelize(longString, {separator: '!'}),
new Array(times)
Array.from({length: times})
.fill(
'lb8!sv!aar!mshc!nvfxjg!g!cgfot3!az!azysux!rp!g9!xfp!l!cz89!te!wq!ad3!t!uo64!k45!vh2!mfj!l!yhztt4!lq!yzr!eb!tpx7g!gc!g4!t8ue!k!pm6!vra!x!kt!ul!jdnc!f!qh!e!qf!c!rw!wg!nscd!fe6!ute!av!n7!nze4!qy4hv!zu!klx5!yioh!gpv!nz!ut!l!gen3!wp2jot8!veprzy!x!qmi!kdxdxr!e!res!s!rg!swen!cz!xzp!ser!yu!ef!ap!vbju!djz9k!gmrxfrzq!vy!bdd!gf!y9!e!rqtx!h!qx!pw65!tt!eo3dgwhcuhv!c3d!my!rj6j!waon!kb3!pqtv27v!rv5!mg!yb5mgv!ce55o!ctbg9y!as!paw2!kq!y!vz3am!bge9!hgg!ez!xj!ghw!s!xjk!l7j!u!yk3!wj!q!ubw!vn!zn!hk!h3!p9!mpv!m98!dt!tn!ga!yf!k5!tj!d8!y5o!xpr!jmd!c!hzh!byboa!w2o!rj2!ft7dx!gkx!ls2s7qs!qs8!fs!jh!vc!yrm!vh!ra6th5!ciz!hsxk7vr5!d3!k!ysfsnr92!amt!r4!le!ram7!cv9em!b!buyk!qj!mej!lg!fsvg!tr!b!kmm!uqijx!sg!y'
'lb8!sv!aar!mshc!nvfxjg!g!cgfot3!az!azysux!rp!g9!xfp!l!cz89!te!wq!ad3!t!uo64!k45!vh2!mfj!l!yhztt4!lq!yzr!eb!tpx7g!gc!g4!t8ue!k!pm6!vra!x!kt!ul!jdnc!f!qh!e!qf!c!rw!wg!nscd!fe6!ute!av!n7!nze4!qy4hv!zu!klx5!yioh!gpv!nz!ut!l!gen3!wp2jot8!veprzy!x!qmi!kdxdxr!e!res!s!rg!swen!cz!xzp!ser!yu!ef!ap!vbju!djz9k!gmrxfrzq!vy!bdd!gf!y9!e!rqtx!h!qx!pw65!tt!eo3dgwhcuhv!c3d!my!rj6j!waon!kb3!pqtv27v!rv5!mg!yb5mgv!ce55o!ctbg9y!as!paw2!kq!y!vz3am!bge9!hgg!ez!xj!ghw!s!xjk!l7j!u!yk3!wj!q!ubw!vn!zn!hk!h3!p9!mpv!m98!dt!tn!ga!yf!k5!tj!d8!y5o!xpr!jmd!c!hzh!byboa!w2o!rj2!ft7dx!gkx!ls2s7qs!qs8!fs!jh!vc!yrm!vh!ra6th5!ciz!hsxk7vr5!d3!k!ysfsnr92!amt!r4!le!ram7!cv9em!b!buyk!qj!mej!lg!fsvg!tr!b!kmm!uqijx!sg!y',
)
.join('!')
.join('!'),
);
t.is(
decamelize(longString, {
separator: '!',
preserveConsecutiveUppercase: true
preserveConsecutiveUppercase: true,
}),
new Array(times)
Array.from({length: times})
.fill(
'lb8!sv!AAR!mshc!nvfxjg!G!cgfot3!AZ!azysux!rp!G9!xfp!L!cz89!te!wq!ad3!T!uo64!K45!VH2!mfj!L!yhztt4!LQ!yzr!eb!tpx7g!gc!G4!T8ue!K!pm6!vra!X!kt!UL!jdnc!F!qh!E!qf!C!rw!WG!nscd!fe6!UTE!av!N7!nze4!qy4hv!zu!KLX5!yioh!gpv!NZ!ut!L!gen3!WP2jot8!veprzy!X!qmi!kdxdxr!E!res!S!rg!SWEN!cz!XZP!ser!yu!ef!ap!vbju!DJZ9k!GMRXFRZQ!vy!BDD!gf!Y9!E!rqtx!H!qx!pw65!tt!eo3dgwhcuhv!C3d!my!RJ6j!waon!KB3!pqtv27v!rv5!mg!yb5mgv!CE55o!CTBG9y!AS!paw2!kq!Y!vz3am!bge9!hgg!ez!XJ!ghw!S!xjk!L7j!U!yk3!wj!Q!ubw!vn!ZN!hk!H3!P9!mpv!M98!dt!tn!GA!yf!K5!tj!D8!Y5o!XPR!jmd!C!hzh!byboa!W2o!RJ2!ft7dx!GKX!ls2s7qs!qs8!fs!JH!vc!yrm!VH!ra6th5!ciz!HSXK7vr5!D3!K!ysfsnr92!amt!R4!LE!ram7!CV9em!B!buyk!QJ!mej!LG!fsvg!tr!B!kmm!uqijx!sg!'
'lb8!sv!AAR!mshc!nvfxjg!G!cgfot3!AZ!azysux!rp!G9!xfp!L!cz89!te!wq!ad3!T!uo64!K45!VH2!mfj!L!yhztt4!LQ!yzr!eb!tpx7g!gc!G4!T8ue!K!pm6!vra!X!kt!UL!jdnc!F!qh!E!qf!C!rw!WG!nscd!fe6!UTE!av!N7!nze4!qy4hv!zu!KLX5!yioh!gpv!NZ!ut!L!gen3!WP2jot8!veprzy!X!qmi!kdxdxr!E!res!S!rg!SWEN!cz!XZP!ser!yu!ef!ap!vbju!DJZ9k!GMRXFRZQ!vy!BDD!gf!Y9!E!rqtx!H!qx!pw65!tt!eo3dgwhcuhv!C3d!my!RJ6j!waon!KB3!pqtv27v!rv5!mg!yb5mgv!CE55o!CTBG9y!AS!paw2!kq!Y!vz3am!bge9!hgg!ez!XJ!ghw!S!xjk!L7j!U!yk3!wj!Q!ubw!vn!ZN!hk!H3!P9!mpv!M98!dt!tn!GA!yf!K5!tj!D8!Y5o!XPR!jmd!C!hzh!byboa!W2o!RJ2!ft7dx!GKX!ls2s7qs!qs8!fs!JH!vc!yrm!VH!ra6th5!ciz!HSXK7vr5!D3!K!ysfsnr92!amt!R4!LE!ram7!CV9em!B!buyk!QJ!mej!LG!fsvg!tr!B!kmm!uqijx!sg!',
)
.join('Y!') + 'y'
.join('Y!') + 'y',
);
});

0 comments on commit 2597adb

Please sign in to comment.