Skip to content

Commit cd5159f

Browse files
committed
chore(utils): introduce helpers for ordinal numbers, precision and capitalisation
1 parent 29a01df commit cd5159f

3 files changed

Lines changed: 87 additions & 0 deletions

File tree

packages/utils/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,16 @@ export {
5555
} from './lib/reports/utils';
5656
export {
5757
CliArgsObject,
58+
capitalize,
5859
countOccurrences,
5960
distinct,
6061
factorOf,
6162
objectToCliArgs,
6263
objectToEntries,
6364
objectToKeys,
6465
toArray,
66+
toNumberPrecision,
67+
toOrdinal,
6568
toUnixPath,
6669
} from './lib/transform';
6770
export { verboseUtils } from './lib/verbose-utils';

packages/utils/src/lib/transform.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,38 @@ export function toUnixPath(
115115

116116
return unixPath;
117117
}
118+
119+
export function capitalize<T extends string>(text: T): Capitalize<T> {
120+
return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
121+
1,
122+
)}` as Capitalize<T>;
123+
}
124+
125+
export function toNumberPrecision(
126+
value: number,
127+
decimalPlaces: number,
128+
): number {
129+
return Number(
130+
`${Math.round(
131+
Number.parseFloat(`${value}e${decimalPlaces}`),
132+
)}e-${decimalPlaces}`,
133+
);
134+
}
135+
136+
/* eslint-disable no-magic-numbers */
137+
export function toOrdinal(value: number): string {
138+
if (value % 10 === 1 && value % 100 !== 11) {
139+
return `${value}st`;
140+
}
141+
142+
if (value % 10 === 2 && value % 100 !== 12) {
143+
return `${value}nd`;
144+
}
145+
146+
if (value % 10 === 3 && value % 100 !== 13) {
147+
return `${value}rd`;
148+
}
149+
150+
return `${value}th`;
151+
}
152+
/* eslint-enable no-magic-numbers */

packages/utils/src/lib/transform.unit.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, expect, it } from 'vitest';
22
import {
3+
capitalize,
34
countOccurrences,
45
deepClone,
56
distinct,
@@ -8,6 +9,8 @@ import {
89
objectToEntries,
910
objectToKeys,
1011
toArray,
12+
toNumberPrecision,
13+
toOrdinal,
1114
toUnixPath,
1215
} from './transform';
1316

@@ -187,3 +190,49 @@ describe('toUnixPath', () => {
187190
).toBe('windows/path/config.ts');
188191
});
189192
});
193+
194+
describe('capitalize', () => {
195+
it('should transform the first string letter to upper case', () => {
196+
expect(capitalize('code PushUp')).toBe('Code PushUp');
197+
});
198+
199+
it('should leave the first string letter in upper case', () => {
200+
expect(capitalize('Code PushUp')).toBe('Code PushUp');
201+
});
202+
203+
it('should accept empty string', () => {
204+
expect(capitalize('')).toBe('');
205+
});
206+
});
207+
208+
describe('toNumberPrecision', () => {
209+
it.each([
210+
[12.1, 0, 12],
211+
[12.3, 1, 12.3],
212+
[12.35, 1, 12.4],
213+
[0.001, 2, 0],
214+
])(
215+
'should round %d to %d decimal places as %d',
216+
(value, decimalPlaces, roundedValue) => {
217+
expect(toNumberPrecision(value, decimalPlaces)).toBe(roundedValue);
218+
},
219+
);
220+
});
221+
222+
describe('toOrdinal', () => {
223+
it.each([
224+
[1, '1st'],
225+
[2, '2nd'],
226+
[3, '3rd'],
227+
[5, '5th'],
228+
[10, '10th'],
229+
[11, '11th'],
230+
[12, '12th'],
231+
[13, '13th'],
232+
[171, '171st'],
233+
[172, '172nd'],
234+
[173, '173rd'],
235+
])('should covert %d to ordinal as %s', (value, ordinalValue) => {
236+
expect(toOrdinal(value)).toBe(ordinalValue);
237+
});
238+
});

0 commit comments

Comments
 (0)