From 0fec5e4722a6f684be92c0ee774dd97817a6d61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borys=20=C5=BBmuda?= Date: Sat, 7 Sep 2024 10:05:23 +0200 Subject: [PATCH] feat(#41): Added convertCase --- docs/functions.md | 11 ++++++++++ docs/methods.md | 11 ++++++++++ docs/statics.md | 11 ++++++++++ src/Str.ts | 2 ++ src/Stringable.ts | 7 ++++++ src/methods.ts | 33 ++++++++++++++++++++++++++-- src/types/case.ts | 10 +++++++++ tests/convertCase.test.js | 46 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/types/case.ts create mode 100644 tests/convertCase.test.js diff --git a/docs/functions.md b/docs/functions.md index 6fe7025..9ae4ca9 100644 --- a/docs/functions.md +++ b/docs/functions.md @@ -78,6 +78,17 @@ containsAll('This is my name', ['my', 'name']); // true ``` + +### convertCase + +The `convertCase` function converts the given string to given mode: + +```js +convertCase('HeLLo WoRLD', MB_CASE_LOWER); + +// 'hello world' +``` + ### endsWith The `endsWith` function determines if the given string ends with the given value: ```js diff --git a/docs/methods.md b/docs/methods.md index 3a2a903..5047cfa 100644 --- a/docs/methods.md +++ b/docs/methods.md @@ -124,6 +124,17 @@ Stringable.of('This is my name').containsAll(['my', 'name']); // true ``` + +### convertCase + +The `convertCase` method converts the given string to given mode: + +```js +Stringable.of('HeLLo WoRLD').convertCase(MB_CASE_LOWER); + +// 'hello world' +``` + ### dirname The `dirname` method returns the parent directory portion of the given string: ```js diff --git a/docs/statics.md b/docs/statics.md index 4bfad90..a2f5086 100644 --- a/docs/statics.md +++ b/docs/statics.md @@ -92,6 +92,17 @@ Str.containsAll('This is my name', ['my', 'name']); // true ``` + +### convertCase + +The `convertCase` function converts the given string to given mode: + +```js +Str.convertCase('HeLLo WoRLD', MB_CASE_LOWER); + +// 'hello world' +``` + ### endsWith The `endsWith` function determines if the given string ends with the given value: ```js diff --git a/src/Str.ts b/src/Str.ts index b80e814..cfb5019 100644 --- a/src/Str.ts +++ b/src/Str.ts @@ -9,6 +9,7 @@ import { charAt, contains, containsAll, + convertCase, endsWith, excerpt, explode, @@ -107,6 +108,7 @@ export const Str = { }, contains, containsAll, + convertCase, endsWith, excerpt, explode, diff --git a/src/Stringable.ts b/src/Stringable.ts index c377902..9b35536 100644 --- a/src/Stringable.ts +++ b/src/Stringable.ts @@ -1,5 +1,6 @@ import Str, {ExcerptOptions} from './Str'; import {MarkdownConfiguration, defaultConfiguration} from './types/markdown'; +import {CASE_MODE, MB_CASE_FOLD} from './types/case'; type Closure = Function | null | string | { (callback: Stringable, value: string): Stringable }; @@ -117,6 +118,12 @@ export class Stringable { return Str.containsAll(this._value, needles, ignoreCase); } + public convertCase = (mode: CASE_MODE = MB_CASE_FOLD): this => { + this._value = Str.convertCase(this._value, mode); + + return this; + } + public dirname = (levels: number = 1): this => { const components = this.explode('/', levels * -1); diff --git a/src/methods.ts b/src/methods.ts index 80a9945..a675371 100644 --- a/src/methods.ts +++ b/src/methods.ts @@ -1,3 +1,13 @@ +import { + CASE_MODE, + MB_CASE_FOLD, MB_CASE_FOLD_SIMPLE, + MB_CASE_LOWER, + MB_CASE_LOWER_SIMPLE, + MB_CASE_TITLE, MB_CASE_TITLE_SIMPLE, + MB_CASE_UPPER, + MB_CASE_UPPER_SIMPLE +} from './types/case'; + export type ExcerptOptions = { radius?: number, omission?: string, @@ -89,6 +99,22 @@ export const containsAll = (haystack: string, needles: string[], ignoreCase: boo return needles.every(needle => haystack.includes(needle)); } +export const convertCase = (string: string, mode: CASE_MODE = MB_CASE_FOLD): string => { + if ([MB_CASE_UPPER, MB_CASE_UPPER_SIMPLE].includes(mode)) { + return upper(string); + } + + if ([MB_CASE_FOLD, MB_CASE_LOWER, MB_CASE_LOWER_SIMPLE, MB_CASE_FOLD_SIMPLE].includes(mode)) { + return lower(string); + } + + if ([MB_CASE_TITLE, MB_CASE_TITLE_SIMPLE].includes(mode)) { + return title(string); + } + + throw new Error(`Unsupported mode.`); +} + export const endsWith = (haystack: string, needles: null | string | number | string[]): boolean => { if (needles === null || needles === '') { return false; @@ -99,7 +125,10 @@ export const endsWith = (haystack: string, needles: null | string | number | str return values.some(needle => haystack.endsWith(String(needle))); } -export const excerpt = (text: string, phrase: string = '', {radius = 100, omission = '...'}: ExcerptOptions = {radius: 100, omission: '...'}): string => { +export const excerpt = (text: string, phrase: string = '', { + radius = 100, + omission = '...' +}: ExcerptOptions = {radius: 100, omission: '...'}): string => { if (text === phrase) { return text; } @@ -394,7 +423,7 @@ export const parseCallback = (callback: string, method: string | null = null): A : [callback, method]; } -export const position = (haystack: string, needle: string, offset: number = 0): number|boolean => { +export const position = (haystack: string, needle: string, offset: number = 0): number | boolean => { const index = haystack.indexOf(needle, offset); return index < 0 ? false : index; diff --git a/src/types/case.ts b/src/types/case.ts new file mode 100644 index 0000000..1f8cb21 --- /dev/null +++ b/src/types/case.ts @@ -0,0 +1,10 @@ +export type CASE_MODE = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; + +export const MB_CASE_UPPER = 0; +export const MB_CASE_LOWER = 1; +export const MB_CASE_TITLE = 2; +export const MB_CASE_FOLD = 3; +export const MB_CASE_UPPER_SIMPLE = 4; +export const MB_CASE_LOWER_SIMPLE = 5; +export const MB_CASE_TITLE_SIMPLE = 6; +export const MB_CASE_FOLD_SIMPLE = 7; diff --git a/tests/convertCase.test.js b/tests/convertCase.test.js new file mode 100644 index 0000000..7fde936 --- /dev/null +++ b/tests/convertCase.test.js @@ -0,0 +1,46 @@ +'use strict'; + +const {Stringable} = require('../src/Stringable'); +const {Str} = require('../src/Str'); +const {convertCase} = require('../src/methods'); +const {MB_CASE_UPPER, MB_CASE_LOWER, MB_CASE_FOLD, MB_CASE_TITLE} = require('../src/types/case'); + +it('converts the case of a string', () => { + expect(Stringable.of('hello').convertCase(MB_CASE_UPPER).toString()) + .toBe('HELLO'); + + expect(Stringable.of('WORLD').convertCase(MB_CASE_UPPER).toString()) + .toBe('WORLD'); + + expect(Stringable.of('HeLLo').convertCase(MB_CASE_LOWER).toString()) + .toBe('hello'); + + expect(Stringable.of('WoRLD').convertCase(MB_CASE_LOWER).toString()) + .toBe('world'); + + expect(Stringable.of('HeLLo WoRLD').convertCase(MB_CASE_TITLE).toString()) + .toBe('Hello World'); + + expect(Stringable.of('HeLLo').convertCase(MB_CASE_FOLD).toString()) + .toBe('hello'); + + expect(Stringable.of('WoRLD').convertCase(MB_CASE_FOLD).toString()) + .toBe('world'); + + expect(Stringable.of('üöä').convertCase(MB_CASE_UPPER).toString()) + .toBe('ÜÖÄ'); + + expect(Stringable.of('ÜÖÄ').convertCase(MB_CASE_LOWER).toString()) + .toBe('üöä'); + + expect(Str.convertCase('hello', MB_CASE_UPPER).toString()) + .toBe('HELLO'); + + expect(convertCase('hello', MB_CASE_UPPER).toString()) + .toBe('HELLO'); +}); + +it('returns error on unsupported mode', () => { + expect(() => Str.convertCase('Hello', -1).toString()) + .toThrowError('Unsupported mode.'); +});