mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-28 12:05:41 +03:00
feat(string): add snakeCase
, startCase
, lowerCase
, kebabCase
in compat layer (#517)
* Add cases function * Add benchmarks and re-export in index.ts * Revert
This commit is contained in:
parent
7aad9d6b9a
commit
31769810b8
@ -1,15 +1,30 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { kebabCase as kebabCaseToolkit } from 'es-toolkit';
|
||||
import { kebabCase as kebabCaseToolkitCompat } from 'es-toolkit/compat';
|
||||
import { kebabCase as kebabCaseLodash } from 'lodash';
|
||||
|
||||
describe('kebabCase', () => {
|
||||
bench('es-toolkit/kebabCase', () => {
|
||||
const str = 'camelCase';
|
||||
kebabCaseToolkit(str);
|
||||
kebabCaseToolkit('hello world');
|
||||
kebabCaseToolkit('--foo--bar__baz 123');
|
||||
kebabCaseToolkit('123numericValues');
|
||||
kebabCaseToolkit('XMLHttpRequest');
|
||||
kebabCaseToolkit('hello-World_of XML_httpRequest');
|
||||
});
|
||||
|
||||
bench('es-toolkit/comapt/kebabCase', () => {
|
||||
kebabCaseToolkitCompat('hello world');
|
||||
kebabCaseToolkitCompat('--foo--bar__baz 123');
|
||||
kebabCaseToolkitCompat('123numericValues');
|
||||
kebabCaseToolkitCompat('XMLHttpRequest');
|
||||
kebabCaseToolkitCompat('hello-World_of XML_httpRequest');
|
||||
});
|
||||
|
||||
bench('lodash/kebabCase', () => {
|
||||
const str = 'camelCase';
|
||||
kebabCaseLodash(str);
|
||||
kebabCaseLodash('hello world');
|
||||
kebabCaseLodash('--foo--bar__baz 123');
|
||||
kebabCaseLodash('123numericValues');
|
||||
kebabCaseLodash('XMLHttpRequest');
|
||||
kebabCaseLodash('hello-World_of XML_httpRequest');
|
||||
});
|
||||
});
|
||||
|
@ -1,28 +1,36 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { lowerCase as lowerCaseToolkit } from 'es-toolkit';
|
||||
import { lowerCase as lowerCaseToolkitCompat } from 'es-toolkit/compat';
|
||||
import { lowerCase as lowerCaseLodash } from 'lodash';
|
||||
|
||||
describe('lowerCase', () => {
|
||||
describe('short string', () => {
|
||||
describe('lowerCase - short string', () => {
|
||||
bench('es-toolkit/lowerCase', () => {
|
||||
const str = 'camelCase';
|
||||
lowerCaseToolkit(str);
|
||||
});
|
||||
|
||||
bench('es-toolkit/compat/lowerCase', () => {
|
||||
const str = 'camelCase';
|
||||
lowerCaseToolkitCompat(str);
|
||||
});
|
||||
|
||||
bench('lodash/lowerCase', () => {
|
||||
const str = 'camelCase';
|
||||
lowerCaseLodash(str);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('long string', () => {
|
||||
describe('lowerCase - long string', () => {
|
||||
const LONG_STR = 'camelCaseLongString'.repeat(1000);
|
||||
bench('es-toolkit/lowerCase', () => {
|
||||
lowerCaseToolkit(LONG_STR);
|
||||
});
|
||||
|
||||
bench('es-toolkit/compat/lowerCase', () => {
|
||||
lowerCaseToolkitCompat(LONG_STR);
|
||||
});
|
||||
|
||||
bench('lodash/lowerCase', () => {
|
||||
lowerCaseLodash(LONG_STR);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,15 +1,30 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { snakeCase as snakeCaseToolkit } from 'es-toolkit';
|
||||
import { snakeCase as snakeCaseToolkitCompat } from 'es-toolkit/compat';
|
||||
import { snakeCase as snakeCaseLodash } from 'lodash';
|
||||
|
||||
describe('snakeCase', () => {
|
||||
bench('es-toolkit/snakeCase', () => {
|
||||
const str = 'camelCase';
|
||||
snakeCaseToolkit(str);
|
||||
snakeCaseToolkit('hello world');
|
||||
snakeCaseToolkit('--foo--bar__baz 123');
|
||||
snakeCaseToolkit('123numericValues');
|
||||
snakeCaseToolkit('XMLHttpRequest');
|
||||
snakeCaseToolkit('hello-World_of XML_httpRequest');
|
||||
});
|
||||
|
||||
bench('es-toolkit/comapt/snakeCase', () => {
|
||||
snakeCaseToolkitCompat('hello world');
|
||||
snakeCaseToolkitCompat('--foo--bar__baz 123');
|
||||
snakeCaseToolkitCompat('123numericValues');
|
||||
snakeCaseToolkitCompat('XMLHttpRequest');
|
||||
snakeCaseToolkitCompat('hello-World_of XML_httpRequest');
|
||||
});
|
||||
|
||||
bench('lodash/snakeCase', () => {
|
||||
const str = 'camelCase';
|
||||
snakeCaseLodash(str);
|
||||
snakeCaseLodash('hello world');
|
||||
snakeCaseLodash('--foo--bar__baz 123');
|
||||
snakeCaseLodash('123numericValues');
|
||||
snakeCaseLodash('XMLHttpRequest');
|
||||
snakeCaseLodash('hello-World_of XML_httpRequest');
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { startCase as startCaseToolkit } from 'es-toolkit';
|
||||
import { startCase as startCaseToolkitCompat } from 'es-toolkit/compat';
|
||||
import { startCase as startCaseLodash } from 'lodash';
|
||||
import { bench, describe } from 'vitest';
|
||||
|
||||
@ -11,6 +12,14 @@ describe('startCase', () => {
|
||||
startCaseToolkit('hello-World_of XML_httpRequest');
|
||||
});
|
||||
|
||||
bench('es-toolkit/comapt/startCase', () => {
|
||||
startCaseToolkitCompat('hello world');
|
||||
startCaseToolkitCompat('--foo--bar__baz 123');
|
||||
startCaseToolkitCompat('123numericValues');
|
||||
startCaseToolkitCompat('XMLHttpRequest');
|
||||
startCaseToolkitCompat('hello-World_of XML_httpRequest');
|
||||
});
|
||||
|
||||
bench('lodash/startCase', () => {
|
||||
startCaseLodash('hello world');
|
||||
startCaseLodash('--foo--bar__baz 123');
|
||||
|
@ -83,6 +83,10 @@ export { conforms } from './predicate/conforms.ts';
|
||||
export { conformsTo } from './predicate/conformsTo.ts';
|
||||
|
||||
export { camelCase } from './string/camelCase.ts';
|
||||
export { kebabCase } from './string/kebabCase.ts';
|
||||
export { snakeCase } from './string/snakeCase.ts';
|
||||
export { startCase } from './string/startCase.ts';
|
||||
export { lowerCase } from './string/lowerCase.ts';
|
||||
export { startsWith } from './string/startsWith.ts';
|
||||
export { endsWith } from './string/endsWith.ts';
|
||||
export { padStart } from './string/padStart.ts';
|
||||
|
45
src/compat/string/kebabCase.spec.ts
Normal file
45
src/compat/string/kebabCase.spec.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { kebabCase } from './kebabCase';
|
||||
|
||||
describe('kebabCase', () => {
|
||||
const strings = ['foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 'FOO BAR', 'fooBar', '--foo-bar--', '__foo_bar__'];
|
||||
|
||||
it(`should convert \`string\``, () => {
|
||||
const actual = strings.map(string => kebabCase(string));
|
||||
|
||||
const expected = actual.map(() => 'foo-bar');
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it(`should handle double-converting strings`, () => {
|
||||
const actual = strings.map(string => kebabCase(kebabCase(string)));
|
||||
|
||||
const expected = actual.map(() => 'foo-bar');
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it(`should remove contraction apostrophes`, () => {
|
||||
const postfixes = ['d', 'll', 'm', 're', 's', 't', 've'];
|
||||
|
||||
["'", '\u2019'].forEach(apos => {
|
||||
const actual = postfixes.map(postfix => kebabCase(`a b${apos}${postfix} c`));
|
||||
|
||||
const expected = postfixes.map(postfix => `a-b${postfix}-c`);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should remove Latin mathematical operators`, () => {
|
||||
const actual = ['\xd7', '\xf7'].map(kebabCase);
|
||||
expect(actual).toEqual(['', '']);
|
||||
});
|
||||
|
||||
it(`should coerce \`string\` to a string`, () => {
|
||||
const string = 'foo bar';
|
||||
expect(kebabCase(Object(string))).toBe('foo-bar');
|
||||
expect(kebabCase({ toString: () => string })).toBe('foo-bar');
|
||||
});
|
||||
});
|
20
src/compat/string/kebabCase.ts
Normal file
20
src/compat/string/kebabCase.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { kebabCase as kebabCaseToolkit } from '../../string';
|
||||
import { normalizeForCase } from '../_internal/normalizeForCase';
|
||||
|
||||
/**
|
||||
* Converts a string to kebab case.
|
||||
*
|
||||
* Kebab case is the naming convention in which each word is written in lowercase and separated by a dash (-) character.
|
||||
*
|
||||
* @param {string} str - The string that is to be changed to kebab case.
|
||||
* @returns {string} - The converted string to kebab case.
|
||||
*
|
||||
* @example
|
||||
* const convertedStr1 = kebabCase('camelCase') // returns 'camel-case'
|
||||
* const convertedStr2 = kebabCase('some whitespace') // returns 'some-whitespace'
|
||||
* const convertedStr3 = kebabCase('hyphen-text') // returns 'hyphen-text'
|
||||
* const convertedStr4 = kebabCase('HTTPRequest') // returns 'http-request'
|
||||
*/
|
||||
export function kebabCase(str: string | object): string {
|
||||
return kebabCaseToolkit(normalizeForCase(str));
|
||||
}
|
45
src/compat/string/lowerCase.spec.ts
Normal file
45
src/compat/string/lowerCase.spec.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { lowerCase } from './lowerCase';
|
||||
|
||||
describe('lowerCase', () => {
|
||||
const strings = ['foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 'FOO BAR', 'fooBar', '--foo-bar--', '__foo_bar__'];
|
||||
|
||||
it(`should convert \`string\``, () => {
|
||||
const actual = strings.map(string => lowerCase(string));
|
||||
|
||||
const expected = actual.map(() => 'foo bar');
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it(`should handle double-converting strings`, () => {
|
||||
const actual = strings.map(string => lowerCase(lowerCase(string)));
|
||||
|
||||
const expected = actual.map(() => 'foo bar');
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it(`should remove contraction apostrophes`, () => {
|
||||
const postfixes = ['d', 'll', 'm', 're', 's', 't', 've'];
|
||||
|
||||
["'", '\u2019'].forEach(apos => {
|
||||
const actual = postfixes.map(postfix => lowerCase(`a b${apos}${postfix} c`));
|
||||
|
||||
const expected = postfixes.map(postfix => `a b${postfix} c`);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should remove Latin mathematical operators`, () => {
|
||||
const actual = ['\xd7', '\xf7'].map(lowerCase);
|
||||
expect(actual).toEqual(['', '']);
|
||||
});
|
||||
|
||||
it(`should coerce \`string\` to a string`, () => {
|
||||
const string = 'foo bar';
|
||||
expect(lowerCase(Object(string))).toBe('foo bar');
|
||||
expect(lowerCase({ toString: () => string })).toBe('foo bar');
|
||||
});
|
||||
});
|
20
src/compat/string/lowerCase.ts
Normal file
20
src/compat/string/lowerCase.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { lowerCase as lowerCaseToolkit } from '../../string/lowerCase';
|
||||
import { normalizeForCase } from '../_internal/normalizeForCase';
|
||||
|
||||
/**
|
||||
* Converts a string to lower case.
|
||||
*
|
||||
* Lower case is the naming convention in which each word is written in lowercase and separated by an space ( ) character.
|
||||
*
|
||||
* @param {string} str - The string that is to be changed to lower case.
|
||||
* @returns {string} - The converted string to lower case.
|
||||
*
|
||||
* @example
|
||||
* const convertedStr1 = lowerCase('camelCase') // returns 'camel case'
|
||||
* const convertedStr2 = lowerCase('some whitespace') // returns 'some whitespace'
|
||||
* const convertedStr3 = lowerCase('hyphen-text') // returns 'hyphen text'
|
||||
* const convertedStr4 = lowerCase('HTTPRequest') // returns 'http request'
|
||||
*/
|
||||
export function lowerCase(str: string | object): string {
|
||||
return lowerCaseToolkit(normalizeForCase(str));
|
||||
}
|
45
src/compat/string/snakeCase.spec.ts
Normal file
45
src/compat/string/snakeCase.spec.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { snakeCase } from './snakeCase';
|
||||
|
||||
describe('snakeCase', () => {
|
||||
const strings = ['foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 'FOO BAR', 'fooBar', '--foo-bar--', '__foo_bar__'];
|
||||
|
||||
it(`should convert \`string\``, () => {
|
||||
const actual = strings.map(string => snakeCase(string));
|
||||
|
||||
const expected = actual.map(() => 'foo_bar');
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it(`should handle double-converting strings`, () => {
|
||||
const actual = strings.map(string => snakeCase(snakeCase(string)));
|
||||
|
||||
const expected = actual.map(() => 'foo_bar');
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it(`should remove contraction apostrophes`, () => {
|
||||
const postfixes = ['d', 'll', 'm', 're', 's', 't', 've'];
|
||||
|
||||
["'", '\u2019'].forEach(apos => {
|
||||
const actual = postfixes.map(postfix => snakeCase(`a b${apos}${postfix} c`));
|
||||
|
||||
const expected = postfixes.map(postfix => `a_b${postfix}_c`);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should remove Latin mathematical operators`, () => {
|
||||
const actual = ['\xd7', '\xf7'].map(snakeCase);
|
||||
expect(actual).toEqual(['', '']);
|
||||
});
|
||||
|
||||
it(`should coerce \`string\` to a string`, () => {
|
||||
const string = 'foo bar';
|
||||
expect(snakeCase(Object(string))).toBe('foo_bar');
|
||||
expect(snakeCase({ toString: () => string })).toBe('foo_bar');
|
||||
});
|
||||
});
|
20
src/compat/string/snakeCase.ts
Normal file
20
src/compat/string/snakeCase.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { snakeCase as snakeCaseToolkit } from '../../string/snakeCase';
|
||||
import { normalizeForCase } from '../_internal/normalizeForCase';
|
||||
|
||||
/**
|
||||
* Converts a string to snake case.
|
||||
*
|
||||
* Snake case is the naming convention in which each word is written in lowercase and separated by an underscore (_) character.
|
||||
*
|
||||
* @param {string} str - The string that is to be changed to snake case.
|
||||
* @returns {string} - The converted string to snake case.
|
||||
*
|
||||
* @example
|
||||
* const convertedStr1 = snakeCase('camelCase') // returns 'camel_case'
|
||||
* const convertedStr2 = snakeCase('some whitespace') // returns 'some_whitespace'
|
||||
* const convertedStr3 = snakeCase('hyphen-text') // returns 'hyphen_text'
|
||||
* const convertedStr4 = snakeCase('HTTPRequest') // returns 'http_request'
|
||||
*/
|
||||
export function snakeCase(str: string | object): string {
|
||||
return snakeCaseToolkit(normalizeForCase(str));
|
||||
}
|
45
src/compat/string/startCase.spec.ts
Normal file
45
src/compat/string/startCase.spec.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { startCase } from './startCase';
|
||||
|
||||
describe('case methods', () => {
|
||||
const strings = ['foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 'FOO BAR', 'fooBar', '--foo-bar--', '__foo_bar__'];
|
||||
|
||||
it(`should convert \`string\``, () => {
|
||||
const actual = strings.map(string => startCase(string));
|
||||
|
||||
const expected = actual.map(string => (string === 'FOO BAR' ? 'FOO BAR' : 'Foo Bar'));
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it(`should handle double-converting strings`, () => {
|
||||
const actual = strings.map(string => startCase(startCase(string)));
|
||||
|
||||
const expected = actual.map(string => (string === 'FOO BAR' ? 'FOO BAR' : 'Foo Bar'));
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it(`should remove contraction apostrophes`, () => {
|
||||
const postfixes = ['d', 'll', 'm', 're', 's', 't', 've'];
|
||||
|
||||
["'", '\u2019'].forEach(apos => {
|
||||
const actual = postfixes.map(postfix => startCase(`a b${apos}${postfix} c`));
|
||||
|
||||
const expected = postfixes.map(postfix => `A B${postfix} C`);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should remove Latin mathematical operators`, () => {
|
||||
const actual = ['\xd7', '\xf7'].map(startCase);
|
||||
expect(actual).toEqual(['', '']);
|
||||
});
|
||||
|
||||
it(`should coerce \`string\` to a string`, () => {
|
||||
const string = 'foo bar';
|
||||
expect(startCase(Object(string))).toBe('Foo Bar');
|
||||
expect(startCase({ toString: () => string })).toBe('Foo Bar');
|
||||
});
|
||||
});
|
19
src/compat/string/startCase.ts
Normal file
19
src/compat/string/startCase.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { startCase as startCaseToolkit } from '../../string/startCase';
|
||||
import { normalizeForCase } from '../_internal/normalizeForCase';
|
||||
|
||||
/**
|
||||
* Converts the first character of each word in a string to uppercase and the remaining characters to lowercase.
|
||||
*
|
||||
* Start case is the naming convention in which each word is written with an initial capital letter.
|
||||
* @param {string} str - The string to convert.
|
||||
* @returns {string} The converted string.
|
||||
*
|
||||
* @example
|
||||
* const result1 = startCase('hello world'); // result will be 'Hello World'
|
||||
* const result2 = startCase('HELLO WORLD'); // result will be 'HELLO WORLD'
|
||||
* const result3 = startCase('hello-world'); // result will be 'Hello World'
|
||||
* const result4 = startCase('hello_world'); // result will be 'Hello World'
|
||||
*/
|
||||
export function startCase(str: string | object): string {
|
||||
return startCaseToolkit(normalizeForCase(str));
|
||||
}
|
@ -9,7 +9,7 @@ import { getWords } from './_internal/getWords.ts';
|
||||
*
|
||||
* @example
|
||||
* const result1 = startCase('hello world'); // result will be 'Hello World'
|
||||
* const result2 = startCase('HELLO WORLD'); // result will be 'Hello World'
|
||||
* const result2 = startCase('HELLO WORLD'); // result will be 'HELLO WORLD'
|
||||
* const result3 = startCase('hello-world'); // result will be 'Hello World'
|
||||
* const result4 = startCase('hello_world'); // result will be 'Hello World'
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user