nhb-toolbox 4.25.1 → 4.25.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ All notable changes to the package will be documented here.
6
6
 
7
7
  ---
8
8
 
9
+ ## [4.25.10] - 2025-11-06
10
+
11
+ - **Fixed** *pluralization issues* in the methods of `Converter` classes.
12
+
13
+ ## [4.25.1-4] - 2025-11-05
14
+
15
+ - **Added** *alias* for `Chronos` *static method* `use`: `register`.
16
+ - **Updated** *tsdoc* for `Chronos` *static methods* `use` and `register`.
17
+
9
18
  ## [4.25.0] - 2025-11-03
10
19
 
11
20
  - **Added** new `Chronos` method `durationString(...)` and **Fixed** issues with internal *duration normalization logic*.
package/README.md CHANGED
@@ -39,6 +39,7 @@
39
39
  <img src="https://img.shields.io/github/issues-pr/nazmul-nhb/nhb-toolbox?style=flat&label=PRs&logo=github" alt="Pull Requests" />
40
40
  </a>
41
41
 
42
+ <!-- License Info -->
42
43
  <a href="https://www.npmjs.com/package/nhb-toolbox" aria-label="License">
43
44
  <img src="https://img.shields.io/npm/l/nhb-toolbox.svg?label=LICENSE&style=flat&color=orange&logo=open-source-initiative" alt="License" />
44
45
  </a>
@@ -213,7 +214,7 @@ See [Changelog](CHANGELOG.md) for recent updates.
213
214
 
214
215
  **`Chronos`** - The ultimate date/time manipulation class with 100+ methods for parsing, formatting, calculating, and comparing dates. Handles all edge cases and timezones safely.
215
216
 
216
- > 🧩 **Note**: Some methods in `Chronos` are available only through the [plugin system](https://toolbox.nazmul-nhb.dev/docs/classes/Chronos/plugins#-official-plugins). This modular design ensures the core bundle stays lightweight — plugins are loaded only when needed, reducing unnecessary code in your final build.
217
+ > 🧩 **Note**: Some methods in `Chronos` are available only through the [**plugin system**](https://toolbox.nazmul-nhb.dev/docs/classes/Chronos/plugins#-official-plugins). This modular design ensures the core bundle stays lightweight — plugins are loaded only when needed, reducing unnecessary code in your final build.
217
218
 
218
219
  ```typescript
219
220
  new Chronos('2025-01-01').addDays(3).format('YYYY-MM-DD'); // "2025-01-04"
@@ -12,13 +12,28 @@ class $BaseConverter {
12
12
  $withPluralUnit(value, unit) {
13
13
  const abs = Math.abs(value ?? this.value);
14
14
  const u = unit ?? this.unit;
15
- const pluralized = abs <= 1 ? u
16
- : u ?
17
- u?.endsWith('foot') ?
18
- u.replace(/foot$/, 'feet')
19
- : `${u}s`
20
- : '';
21
- return `${abs} ${pluralized}`.trim();
15
+ if (!u)
16
+ return String(abs);
17
+ let pluralized;
18
+ if (abs === 1) {
19
+ pluralized = u;
20
+ }
21
+ else if (constants_1.IRREGULAR_PLURALS?.[u]) {
22
+ pluralized = constants_1.IRREGULAR_PLURALS[u];
23
+ }
24
+ else if (constants_1.INVARIANT_UNITS.has(u)) {
25
+ pluralized = u;
26
+ }
27
+ else if (u.endsWith('foot')) {
28
+ pluralized = u.replace(/foot$/, 'feet');
29
+ }
30
+ else if (u.endsWith('inch')) {
31
+ pluralized = u.replace(/inch$/, 'inches');
32
+ }
33
+ else {
34
+ pluralized = constants_1.Y_TO_IES.has(u) ? u.replace(/y$/, 'ies') : `${u}s`;
35
+ }
36
+ return `${abs} ${pluralized}`;
22
37
  }
23
38
  $round(value, decimals = 2) {
24
39
  const factor = 10 ** decimals;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UNITS = void 0;
3
+ exports.Y_TO_IES = exports.INVARIANT_UNITS = exports.IRREGULAR_PLURALS = exports.UNITS = void 0;
4
4
  exports.UNITS = Object.freeze({
5
5
  time: [
6
6
  'nanosecond',
@@ -100,3 +100,13 @@ exports.UNITS = Object.freeze({
100
100
  'long-ton',
101
101
  ],
102
102
  });
103
+ exports.IRREGULAR_PLURALS = {
104
+ millennium: 'millennia',
105
+ century: 'centuries',
106
+ };
107
+ exports.INVARIANT_UNITS = new Set([
108
+ 'celsius',
109
+ 'fahrenheit',
110
+ 'kelvin',
111
+ ]);
112
+ exports.Y_TO_IES = new Set(['century']);
@@ -8,3 +8,6 @@ export declare const UNITS: Readonly<{
8
8
  readonly volume: readonly ["cubic-millimeter", "cubic-centimeter", "cubic-meter", "cubic-kilometer", "cubic-millimetre", "cubic-centimetre", "cubic-metre", "cubic-kilometre", "cubic-inch", "cubic-foot", "cubic-yard", "liter", "litre", "milliliter", "millilitre", "gallon", "quart", "pint", "cup", "tablespoon", "teaspoon"];
9
9
  readonly mass: readonly ["microgram", "milligram", "gram", "kilogram", "tonne", "ounce", "pound", "stone", "short-ton", "long-ton"];
10
10
  }>;
11
+ export declare const IRREGULAR_PLURALS: Record<string, string>;
12
+ export declare const INVARIANT_UNITS: Set<string>;
13
+ export declare const Y_TO_IES: Set<string>;
@@ -771,7 +771,7 @@ export declare class Chronos {
771
771
  * @param plugin The plugin to inject.
772
772
  *
773
773
  * @remarks
774
- * - Using {@link use} method on in `React` projects may trigger *linter error* like `"React Hooks must be called in a React function component or a custom React Hook function."`
774
+ * - Using this (`use`) method in `React` projects may trigger *linter error* like `"React Hooks must be called in a React function component or a custom React Hook function."`
775
775
  * - To prevent this incorrect *linter error* in `React` projects, prefer using {@link register} method (alias `use` method).
776
776
  *
777
777
  * - **NOTE:** *Once a plugin is injected, all the registered methods for that plugin will be available for the whole project.*
@@ -784,7 +784,7 @@ export declare class Chronos {
784
784
  *
785
785
  * @remarks
786
786
  * - This is just an alias for {@link use} method.
787
- * - Using {@link use} method on in `React` projects may trigger *linter error* like `"React Hooks must be called in a React function component or a custom React Hook function."`
787
+ * - Using {@link use} method in `React` projects may trigger *linter error* like `"React Hooks must be called in a React function component or a custom React Hook function."`
788
788
  * - To prevent this incorrect *linter error* in `React` projects, prefer using this (`register`) method over {@link use} method.
789
789
  *
790
790
  * - **NOTE:** *Once a plugin is injected, all the registered methods for that plugin will be available for the whole project.*
@@ -88,7 +88,7 @@ export interface ChronosStatics {
88
88
  * @param plugin The plugin to inject.
89
89
  *
90
90
  * @remarks
91
- * - Using {@link use} method on in `React` projects may trigger *linter error* like `"React Hooks must be called in a React function component or a custom React Hook function."`
91
+ * - Using this (`use`) method in `React` projects may trigger *linter error* like `"React Hooks must be called in a React function component or a custom React Hook function."`
92
92
  * - To prevent this incorrect *linter error* in `React` projects, prefer using {@link register} method (alias `use` method).
93
93
  *
94
94
  * - **NOTE:** *Once a plugin is injected, all the registered methods for that plugin will be available for the whole project.*
@@ -101,7 +101,7 @@ export interface ChronosStatics {
101
101
  *
102
102
  * @remarks
103
103
  * - This is just an alias for {@link use} method.
104
- * - Using {@link use} method on in `React` projects may trigger *linter error* like `"React Hooks must be called in a React function component or a custom React Hook function."`
104
+ * - Using {@link use} method in `React` projects may trigger *linter error* like `"React Hooks must be called in a React function component or a custom React Hook function."`
105
105
  * - To prevent this incorrect *linter error* in `React` projects, prefer using this (`register`) method over {@link use} method.
106
106
  *
107
107
  * - **NOTE:** *Once a plugin is injected, all the registered methods for that plugin will be available for the whole project.*
@@ -1,4 +1,4 @@
1
- import { UNITS } from './constants.js';
1
+ import { INVARIANT_UNITS, IRREGULAR_PLURALS, UNITS, Y_TO_IES } from './constants.js';
2
2
  export class $BaseConverter {
3
3
  value;
4
4
  unit;
@@ -9,13 +9,28 @@ export class $BaseConverter {
9
9
  $withPluralUnit(value, unit) {
10
10
  const abs = Math.abs(value ?? this.value);
11
11
  const u = unit ?? this.unit;
12
- const pluralized = abs <= 1 ? u
13
- : u ?
14
- u?.endsWith('foot') ?
15
- u.replace(/foot$/, 'feet')
16
- : `${u}s`
17
- : '';
18
- return `${abs} ${pluralized}`.trim();
12
+ if (!u)
13
+ return String(abs);
14
+ let pluralized;
15
+ if (abs === 1) {
16
+ pluralized = u;
17
+ }
18
+ else if (IRREGULAR_PLURALS?.[u]) {
19
+ pluralized = IRREGULAR_PLURALS[u];
20
+ }
21
+ else if (INVARIANT_UNITS.has(u)) {
22
+ pluralized = u;
23
+ }
24
+ else if (u.endsWith('foot')) {
25
+ pluralized = u.replace(/foot$/, 'feet');
26
+ }
27
+ else if (u.endsWith('inch')) {
28
+ pluralized = u.replace(/inch$/, 'inches');
29
+ }
30
+ else {
31
+ pluralized = Y_TO_IES.has(u) ? u.replace(/y$/, 'ies') : `${u}s`;
32
+ }
33
+ return `${abs} ${pluralized}`;
19
34
  }
20
35
  $round(value, decimals = 2) {
21
36
  const factor = 10 ** decimals;
@@ -97,3 +97,13 @@ export const UNITS = Object.freeze({
97
97
  'long-ton',
98
98
  ],
99
99
  });
100
+ export const IRREGULAR_PLURALS = {
101
+ millennium: 'millennia',
102
+ century: 'centuries',
103
+ };
104
+ export const INVARIANT_UNITS = new Set([
105
+ 'celsius',
106
+ 'fahrenheit',
107
+ 'kelvin',
108
+ ]);
109
+ export const Y_TO_IES = new Set(['century']);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nhb-toolbox",
3
- "version": "4.25.1",
3
+ "version": "4.25.10",
4
4
  "description": "A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",