nhb-toolbox 4.20.30 → 4.20.40
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 +10 -0
- package/dist/cjs/verbalizer/Verbalizer.js +7 -4
- package/dist/cjs/verbalizer/rules.js +8 -1
- package/dist/dts/types/index.d.ts +61 -4
- package/dist/dts/utils/types.d.ts +80 -2
- package/dist/dts/verbalizer/Verbalizer.d.ts +7 -7
- package/dist/esm/verbalizer/Verbalizer.js +7 -4
- package/dist/esm/verbalizer/rules.js +8 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,16 @@ All notable changes to the package will be documented here.
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [4.20.40] - 2025-09-18
|
|
10
|
+
|
|
11
|
+
- **Added** new **utility types**: `DeepPartialAll`, `Join`,`Split` along with `ValidArray`, `List` and _more_.
|
|
12
|
+
|
|
13
|
+
## [4.20.32] - 2025-09-17
|
|
14
|
+
|
|
15
|
+
- **Renamed** `isPastParticiple()` method to `isParticiple()` in `Verbalizer/verbalizer`.
|
|
16
|
+
- **Optimized** _internal logic_ for `toPast()` and `toParticiple()` methods in `Verbalizer/verbalizer`.
|
|
17
|
+
- **Updated** all the _rules_ for `Verbalizer/verbalizer`.
|
|
18
|
+
|
|
9
19
|
## [4.20.30] - 2025-09-17
|
|
10
20
|
|
|
11
21
|
- **Reduced** _unpacked size_ by **removing** _tsdoc comments_ from js (both `cjs` and `esm`) outputs.
|
|
@@ -52,6 +52,9 @@ class Verbalizer {
|
|
|
52
52
|
}
|
|
53
53
|
return result;
|
|
54
54
|
}
|
|
55
|
+
#applyBaseRule(verb) {
|
|
56
|
+
return this.#applyRules(verb, this.#baseRules);
|
|
57
|
+
}
|
|
55
58
|
#applyRules(verb, rules) {
|
|
56
59
|
if (!(0, primitives_1.isNonEmptyString)(verb))
|
|
57
60
|
return '';
|
|
@@ -96,7 +99,7 @@ class Verbalizer {
|
|
|
96
99
|
if (irregularEntry) {
|
|
97
100
|
return this.#restoreCase(verb, irregularEntry.past);
|
|
98
101
|
}
|
|
99
|
-
return this.#restoreCase(verb, this.#applyRules(this
|
|
102
|
+
return this.#restoreCase(verb, this.#applyRules(this.#applyBaseRule(lower), this.#pastRules));
|
|
100
103
|
}
|
|
101
104
|
toParticiple(verb) {
|
|
102
105
|
if (!(0, primitives_1.isNonEmptyString)(verb))
|
|
@@ -106,7 +109,7 @@ class Verbalizer {
|
|
|
106
109
|
if (irregularEntry) {
|
|
107
110
|
return this.#restoreCase(verb, irregularEntry.participle);
|
|
108
111
|
}
|
|
109
|
-
return this.#restoreCase(verb, this.#applyRules(this
|
|
112
|
+
return this.#restoreCase(verb, this.#applyRules(this.#applyBaseRule(lower), this.#participleRules));
|
|
110
113
|
}
|
|
111
114
|
toBase(verb) {
|
|
112
115
|
if (!(0, primitives_1.isNonEmptyString)(verb))
|
|
@@ -116,7 +119,7 @@ class Verbalizer {
|
|
|
116
119
|
if (irregularEntry) {
|
|
117
120
|
return this.#restoreCase(verb, irregularEntry.base);
|
|
118
121
|
}
|
|
119
|
-
return this.#restoreCase(verb, this.#
|
|
122
|
+
return this.#restoreCase(verb, this.#applyBaseRule(lower));
|
|
120
123
|
}
|
|
121
124
|
isPast(verb) {
|
|
122
125
|
if (!(0, primitives_1.isNonEmptyString)(verb))
|
|
@@ -124,7 +127,7 @@ class Verbalizer {
|
|
|
124
127
|
const lower = verb?.trim()?.toLowerCase();
|
|
125
128
|
return this.toPast(lower) === lower;
|
|
126
129
|
}
|
|
127
|
-
|
|
130
|
+
isParticiple(verb) {
|
|
128
131
|
if (!(0, primitives_1.isNonEmptyString)(verb))
|
|
129
132
|
return false;
|
|
130
133
|
const lower = verb?.trim()?.toLowerCase();
|
|
@@ -79,7 +79,6 @@ exports.irregularVerbs = Object.freeze([
|
|
|
79
79
|
['leave', 'left', 'left'],
|
|
80
80
|
['lend', 'lent', 'lent'],
|
|
81
81
|
['lie', 'lay', 'lain'],
|
|
82
|
-
['lie', 'lied', 'lied'],
|
|
83
82
|
['light', 'lit', 'lit'],
|
|
84
83
|
['lose', 'lost', 'lost'],
|
|
85
84
|
['make', 'made', 'made'],
|
|
@@ -150,6 +149,7 @@ exports.pastRules = Object.freeze([
|
|
|
150
149
|
[/e$/i, 'ed'],
|
|
151
150
|
[/([aeiou])lf$/i, '$1lved'],
|
|
152
151
|
[/([^aeiou])y$/i, '$1ied'],
|
|
152
|
+
[/([^aeiou])ic$/i, '$1icked'],
|
|
153
153
|
[/([^aeiou])([aeiou])([^aeiou])$/i, '$1$2$3$3ed'],
|
|
154
154
|
[/$/i, 'ed'],
|
|
155
155
|
]);
|
|
@@ -158,13 +158,20 @@ exports.pastParticipleRules = Object.freeze([
|
|
|
158
158
|
[/e$/i, 'ed'],
|
|
159
159
|
[/([aeiou])lf$/i, '$1lved'],
|
|
160
160
|
[/([^aeiou])y$/i, '$1ied'],
|
|
161
|
+
[/([^aeiou])ic$/i, '$1icked'],
|
|
161
162
|
[/([^aeiou])([aeiou])([^aeiou])$/i, '$1$2$3$3ed'],
|
|
162
163
|
[/$/i, 'ed'],
|
|
163
164
|
]);
|
|
164
165
|
exports.baseRules = Object.freeze([
|
|
165
166
|
[/([aeiou])yed$/i, '$1y'],
|
|
167
|
+
[/^([^aeiouwy])ied$/i, '$1ie'],
|
|
166
168
|
[/ied$/i, 'y'],
|
|
167
169
|
[/([aeiou])lved$/i, '$1lf'],
|
|
170
|
+
[/([^aeiou])icked$/i, '$1ic'],
|
|
168
171
|
[/([bcdfghjklmnpqrstvwxyz])\1ed$/i, '$1'],
|
|
172
|
+
[/([aeiou])ked$/i, '$1ke'],
|
|
173
|
+
[/ined$/i, 'ine'],
|
|
174
|
+
[/eted$/i, 'ete'],
|
|
175
|
+
[/gued$/i, 'gue'],
|
|
169
176
|
[/ed$/i, ''],
|
|
170
177
|
]);
|
|
@@ -38,17 +38,17 @@ export type NonNullishPrimitiveKey<T> = {
|
|
|
38
38
|
/** Falsy primitive type */
|
|
39
39
|
export type FalsyPrimitive = false | 0 | '' | null | undefined;
|
|
40
40
|
/** A generic class constructor */
|
|
41
|
-
export type Constructor = new (...args: any
|
|
41
|
+
export type Constructor = new (...args: any) => any;
|
|
42
42
|
/** Generic function type */
|
|
43
|
-
export type GenericFn = (...args:
|
|
43
|
+
export type GenericFn = (...args: any) => any;
|
|
44
44
|
/** Generic function type that returns `void` */
|
|
45
|
-
export type VoidFunction = (...args: any
|
|
45
|
+
export type VoidFunction = (...args: any) => void;
|
|
46
46
|
/** Debounced function type after certain delay */
|
|
47
47
|
export type DelayedFn<T extends VoidFunction> = (...args: Parameters<T>) => void;
|
|
48
48
|
/** Throttled function type after specific delay */
|
|
49
49
|
export type ThrottledFn<T extends VoidFunction> = (...args: Parameters<T>) => void;
|
|
50
50
|
/** Asynchronous function type */
|
|
51
|
-
export type AsyncFunction<T> = (...args:
|
|
51
|
+
export type AsyncFunction<T> = (...args: any) => Promise<T>;
|
|
52
52
|
/** Advanced types to exclude from counting as object key */
|
|
53
53
|
export type AdvancedTypes = Array<unknown> | File | FileList | Chronos | DateLike | Blob | Date | RegExp | WeakMap<WeakKey, unknown> | WeakSet<WeakKey> | Map<unknown, unknown> | Set<unknown> | Function | GenericFn | VoidFunction | AsyncFunction<unknown> | Promise<unknown> | Error | EvalError | RangeError | ReferenceError | SyntaxError | TypeError | URIError | bigint | symbol;
|
|
54
54
|
/** Helper to detect if a type has methods */
|
|
@@ -76,4 +76,61 @@ export interface ClassDetails {
|
|
|
76
76
|
}
|
|
77
77
|
/** Literal type for `partial` and `required` */
|
|
78
78
|
export type PartialOrRequired = 'partial' | 'required';
|
|
79
|
+
/**
|
|
80
|
+
* - Utility type to assert that a given type condition evaluates to `true`.
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* - This type is mainly used in **type-level tests** to enforce that a condition (usually produced by {@link Equal}) is satisfied.
|
|
84
|
+
* - If the condition is not `true`, TypeScript will raise an error at compile time.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* // Passes ✅
|
|
88
|
+
* type Test1 = Expect<true>;
|
|
89
|
+
*
|
|
90
|
+
* // Fails ❌ - will cause a type error
|
|
91
|
+
* type Test2 = Expect<false>;
|
|
92
|
+
*/
|
|
93
|
+
export type Expect<T extends true> = T;
|
|
94
|
+
/**
|
|
95
|
+
* * Utility type that checks whether two types `X` and `Y` are strictly equal.
|
|
96
|
+
*
|
|
97
|
+
* @remarks
|
|
98
|
+
* - This type uses conditional types and generic inference tricks to compare whether two types are identical.
|
|
99
|
+
* - It resolves to `true` if `X` and `Y` are the same type, otherwise `false`.
|
|
100
|
+
*
|
|
101
|
+
* _Typically used together with {@link Expect} for type-level assertions in tests._
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* type Test1 = Equal<string, string>; // true
|
|
105
|
+
* type Test2 = Equal<string, number>; // false
|
|
106
|
+
*
|
|
107
|
+
* // Example with Expect
|
|
108
|
+
* type Check = Expect<Equal<'a', 'a'>>; // ✅ Compiles
|
|
109
|
+
* type Fail = Expect<Equal<'a', 'b'>>; // ❌ Type error
|
|
110
|
+
*/
|
|
111
|
+
export type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
|
|
112
|
+
/**
|
|
113
|
+
* * Ensures that an array has **at least one element**.
|
|
114
|
+
*
|
|
115
|
+
* @remarks
|
|
116
|
+
* - This type enforces non-empty arrays by requiring the first element `T`, followed by zero or more additional `T`s.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* type NonEmpty = ValidArray<number>; // [number, ...number[]]
|
|
120
|
+
* const arr1: NonEmpty = [1]; // ✅ OK
|
|
121
|
+
* const arr2: NonEmpty = []; // ❌ Error (empty array not allowed)
|
|
122
|
+
*/
|
|
123
|
+
export type ValidArray<T> = [T, ...Array<T>];
|
|
124
|
+
/**
|
|
125
|
+
* * A readonly array of elements of type `T`.
|
|
126
|
+
*
|
|
127
|
+
* @remarks
|
|
128
|
+
* - Shorthand for `ReadonlyArray<T>`. Used to represent immutable lists.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* type Numbers = List<number>; // readonly number[]
|
|
132
|
+
* const arr: Numbers = [1, 2, 3]; // ✅ OK
|
|
133
|
+
* arr.push(4); // ❌ Error (readonly)
|
|
134
|
+
*/
|
|
135
|
+
export type List<T = any> = ReadonlyArray<T>;
|
|
79
136
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GenericObject, NestedPrimitiveKey } from '../object/types';
|
|
2
|
-
import type { AdvancedTypes, Numeric } from '../types/index';
|
|
2
|
+
import type { AdvancedTypes, List, NormalPrimitive, Numeric } from '../types/index';
|
|
3
3
|
/** Options to initialize Paginator */
|
|
4
4
|
export interface PaginatorOptions {
|
|
5
5
|
/** The total number of items. */
|
|
@@ -72,7 +72,11 @@ export type ValueOf<T> = T[keyof T];
|
|
|
72
72
|
*/
|
|
73
73
|
export type KeysOfUnion<T> = T extends T ? keyof T : never;
|
|
74
74
|
/**
|
|
75
|
-
* * Recursively makes all
|
|
75
|
+
* * Recursively makes all potential standard js object properties optional.
|
|
76
|
+
*
|
|
77
|
+
* @remarks
|
|
78
|
+
* - It excludes complex types like `Array`, `Map`, `File`, `Date`, `Chronos` etc. from being recursively partial.
|
|
79
|
+
* - Please, refer to {@link AdvancedTypes} to learn more about these complex types.
|
|
76
80
|
*
|
|
77
81
|
* @example
|
|
78
82
|
* type Config = { a: string; nested: { b: number } };
|
|
@@ -82,6 +86,17 @@ export type KeysOfUnion<T> = T extends T ? keyof T : never;
|
|
|
82
86
|
export type DeepPartial<T> = {
|
|
83
87
|
[K in keyof T]?: T[K] extends AdvancedTypes ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
84
88
|
};
|
|
89
|
+
/**
|
|
90
|
+
* * Recursively makes all properties in any object or array type optional.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* type Config = { a: string; nested: { b: number } };
|
|
94
|
+
* type PartialConfig = DeepPartial<Config>;
|
|
95
|
+
* // { a?: string; nested?: { b?: number } }
|
|
96
|
+
*/
|
|
97
|
+
export type DeepPartialAll<T> = T extends Array<infer El> ? Array<DeepPartialAll<El>> : {
|
|
98
|
+
[K in keyof T]?: DeepPartialAll<T[K]>;
|
|
99
|
+
};
|
|
85
100
|
/**
|
|
86
101
|
* * Removes `readonly` modifiers from all properties of an object type.
|
|
87
102
|
*
|
|
@@ -444,4 +459,67 @@ export type RequireExactly<T extends GenericObject, N extends number> = {
|
|
|
444
459
|
* const s4: OneOrTwo = {}; // ❌ (0 keys)
|
|
445
460
|
*/
|
|
446
461
|
export type RequireBetween<T extends GenericObject, Min extends number, Max extends number, C extends unknown[] = BuildTuple<Max>, Acc extends unknown[] = BuildTuple<Min>> = RequireExactly<T, Acc['length']> | (Acc['length'] extends Max ? never : RequireBetween<T, Min, Max, C, [...Acc, unknown]>);
|
|
462
|
+
/**
|
|
463
|
+
* * Cast one type to another while preserving compatibility.
|
|
464
|
+
*
|
|
465
|
+
* @remarks
|
|
466
|
+
* - Ensures that `A1` extends `A2`. If not, falls back to `A2`.
|
|
467
|
+
* - Useful for enforcing constraints on generics or parameters.
|
|
468
|
+
*
|
|
469
|
+
* @param A1 - Type to check.
|
|
470
|
+
* @param A2 - Type to cast to.
|
|
471
|
+
* @returns `A1` if it extends `A2`, otherwise `A2`.
|
|
472
|
+
*
|
|
473
|
+
* @example
|
|
474
|
+
* type T0 = Cast<'42', string>; // '42'
|
|
475
|
+
* type T1 = Cast<'42', number>; // number
|
|
476
|
+
* type T2 = Cast<42, number>; // 42
|
|
477
|
+
*/
|
|
478
|
+
export type Cast<A1, A2> = A1 extends A2 ? A1 : A2;
|
|
479
|
+
/**
|
|
480
|
+
* * Remove the last element of a list (array).
|
|
481
|
+
*
|
|
482
|
+
* @remarks Produces a new tuple/list type with the last element removed.
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* type T0 = Pop<[1, 2, 3]>; // [1, 2]
|
|
486
|
+
* type T1 = Pop<[]>; // []
|
|
487
|
+
* type T2 = Pop<['a']>; // []
|
|
488
|
+
*/
|
|
489
|
+
export type Pop<L extends List> = L extends readonly [...infer El, any] | readonly [...infer El, any?] ? El : L;
|
|
490
|
+
type __Split<S extends string, D extends string, T extends string[] = []> = S extends `${infer BS}${D}${infer AS}` ? __Split<AS, D, [...T, BS]> : [...T, S];
|
|
491
|
+
type _Split<S extends string, D extends string = ''> = D extends '' ? Pop<__Split<S, D>> : __Split<S, D>;
|
|
492
|
+
/**
|
|
493
|
+
* ✂️ Split a string literal by a given delimiter into a list of strings.
|
|
494
|
+
*
|
|
495
|
+
* @remarks
|
|
496
|
+
* Produces a tuple of substrings by splitting `S` at each occurrence of `D`.
|
|
497
|
+
*
|
|
498
|
+
* @param S - String literal to split.
|
|
499
|
+
* @param D - Delimiter to split on (default: empty string, i.e., character split).
|
|
500
|
+
* @returns A list of string literals.
|
|
501
|
+
*
|
|
502
|
+
* @example
|
|
503
|
+
* type T0 = Split<'a,b,c', ','>; // ['a', 'b', 'c']
|
|
504
|
+
* type T1 = Split<'hello', ''>; // ['h', 'e', 'l', 'l', 'o']
|
|
505
|
+
* type T2 = Split<'foo-bar', '-'>; // ['foo', 'bar']
|
|
506
|
+
*/
|
|
507
|
+
export type Split<S extends string, D extends string = ''> = _Split<S, D> extends infer X ? Cast<X, string[]> : never;
|
|
508
|
+
type _Join<T extends List, D extends string> = T extends [] ? '' : T extends [NormalPrimitive] ? `${T[0]}` : T extends [NormalPrimitive, ...infer R] ? `${T[0]}${D}${_Join<R, D>}` : string;
|
|
509
|
+
/**
|
|
510
|
+
* * Join a list of string/number/boolean literals into a single string.
|
|
511
|
+
*
|
|
512
|
+
* @remarks
|
|
513
|
+
* Concatenates elements of `T` into a single string, separated by delimiter `D`.
|
|
514
|
+
*
|
|
515
|
+
* @param T - List of string/number/boolean literals.
|
|
516
|
+
* @param D - Delimiter to insert between elements (default: space `" "`).
|
|
517
|
+
* @returns A concatenated string literal.
|
|
518
|
+
*
|
|
519
|
+
* @example
|
|
520
|
+
* type T0 = Join<['a', 'b', 'c'], ','>; // "a,b,c"
|
|
521
|
+
* type T1 = Join<['2025', '09', '18'], '-'>; // "2025-09-18"
|
|
522
|
+
* type T2 = Join<['hello', 'world']>; // "hello world"
|
|
523
|
+
*/
|
|
524
|
+
export type Join<T extends List<NormalPrimitive>, D extends string = ' '> = _Join<T, D> extends infer X ? Cast<X, string> : never;
|
|
447
525
|
export {};
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
* For ready to use instance, please refer to {@link https://toolbox.nazmul-nhb.dev/docs/utilities/string/verbalizer verbalizer} instead.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
|
-
* const
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* const myVerbalizer = new Verbalizer();
|
|
16
|
+
* myVerbalizer.toPast('run'); // "ran"
|
|
17
|
+
* myVerbalizer.toParticiple('go'); // "gone"
|
|
18
|
+
* myVerbalizer.toBase('went'); // "go"
|
|
19
19
|
*/
|
|
20
20
|
export declare class Verbalizer {
|
|
21
21
|
#private;
|
|
@@ -98,10 +98,10 @@ export declare class Verbalizer {
|
|
|
98
98
|
* @param verb Verb to check.
|
|
99
99
|
* @returns True if the verb is in past participle form, otherwise false.
|
|
100
100
|
* @example
|
|
101
|
-
* verbalizer.
|
|
102
|
-
* verbalizer.
|
|
101
|
+
* verbalizer.isParticiple('gone'); // true
|
|
102
|
+
* verbalizer.isParticiple('go'); // false
|
|
103
103
|
*/
|
|
104
|
-
|
|
104
|
+
isParticiple(verb: string): boolean;
|
|
105
105
|
/**
|
|
106
106
|
* * Check if a given verb is in its base form.
|
|
107
107
|
* @param verb Verb to check.
|
|
@@ -49,6 +49,9 @@ export class Verbalizer {
|
|
|
49
49
|
}
|
|
50
50
|
return result;
|
|
51
51
|
}
|
|
52
|
+
#applyBaseRule(verb) {
|
|
53
|
+
return this.#applyRules(verb, this.#baseRules);
|
|
54
|
+
}
|
|
52
55
|
#applyRules(verb, rules) {
|
|
53
56
|
if (!isNonEmptyString(verb))
|
|
54
57
|
return '';
|
|
@@ -93,7 +96,7 @@ export class Verbalizer {
|
|
|
93
96
|
if (irregularEntry) {
|
|
94
97
|
return this.#restoreCase(verb, irregularEntry.past);
|
|
95
98
|
}
|
|
96
|
-
return this.#restoreCase(verb, this.#applyRules(this
|
|
99
|
+
return this.#restoreCase(verb, this.#applyRules(this.#applyBaseRule(lower), this.#pastRules));
|
|
97
100
|
}
|
|
98
101
|
toParticiple(verb) {
|
|
99
102
|
if (!isNonEmptyString(verb))
|
|
@@ -103,7 +106,7 @@ export class Verbalizer {
|
|
|
103
106
|
if (irregularEntry) {
|
|
104
107
|
return this.#restoreCase(verb, irregularEntry.participle);
|
|
105
108
|
}
|
|
106
|
-
return this.#restoreCase(verb, this.#applyRules(this
|
|
109
|
+
return this.#restoreCase(verb, this.#applyRules(this.#applyBaseRule(lower), this.#participleRules));
|
|
107
110
|
}
|
|
108
111
|
toBase(verb) {
|
|
109
112
|
if (!isNonEmptyString(verb))
|
|
@@ -113,7 +116,7 @@ export class Verbalizer {
|
|
|
113
116
|
if (irregularEntry) {
|
|
114
117
|
return this.#restoreCase(verb, irregularEntry.base);
|
|
115
118
|
}
|
|
116
|
-
return this.#restoreCase(verb, this.#
|
|
119
|
+
return this.#restoreCase(verb, this.#applyBaseRule(lower));
|
|
117
120
|
}
|
|
118
121
|
isPast(verb) {
|
|
119
122
|
if (!isNonEmptyString(verb))
|
|
@@ -121,7 +124,7 @@ export class Verbalizer {
|
|
|
121
124
|
const lower = verb?.trim()?.toLowerCase();
|
|
122
125
|
return this.toPast(lower) === lower;
|
|
123
126
|
}
|
|
124
|
-
|
|
127
|
+
isParticiple(verb) {
|
|
125
128
|
if (!isNonEmptyString(verb))
|
|
126
129
|
return false;
|
|
127
130
|
const lower = verb?.trim()?.toLowerCase();
|
|
@@ -76,7 +76,6 @@ export const irregularVerbs = Object.freeze([
|
|
|
76
76
|
['leave', 'left', 'left'],
|
|
77
77
|
['lend', 'lent', 'lent'],
|
|
78
78
|
['lie', 'lay', 'lain'],
|
|
79
|
-
['lie', 'lied', 'lied'],
|
|
80
79
|
['light', 'lit', 'lit'],
|
|
81
80
|
['lose', 'lost', 'lost'],
|
|
82
81
|
['make', 'made', 'made'],
|
|
@@ -147,6 +146,7 @@ export const pastRules = Object.freeze([
|
|
|
147
146
|
[/e$/i, 'ed'],
|
|
148
147
|
[/([aeiou])lf$/i, '$1lved'],
|
|
149
148
|
[/([^aeiou])y$/i, '$1ied'],
|
|
149
|
+
[/([^aeiou])ic$/i, '$1icked'],
|
|
150
150
|
[/([^aeiou])([aeiou])([^aeiou])$/i, '$1$2$3$3ed'],
|
|
151
151
|
[/$/i, 'ed'],
|
|
152
152
|
]);
|
|
@@ -155,13 +155,20 @@ export const pastParticipleRules = Object.freeze([
|
|
|
155
155
|
[/e$/i, 'ed'],
|
|
156
156
|
[/([aeiou])lf$/i, '$1lved'],
|
|
157
157
|
[/([^aeiou])y$/i, '$1ied'],
|
|
158
|
+
[/([^aeiou])ic$/i, '$1icked'],
|
|
158
159
|
[/([^aeiou])([aeiou])([^aeiou])$/i, '$1$2$3$3ed'],
|
|
159
160
|
[/$/i, 'ed'],
|
|
160
161
|
]);
|
|
161
162
|
export const baseRules = Object.freeze([
|
|
162
163
|
[/([aeiou])yed$/i, '$1y'],
|
|
164
|
+
[/^([^aeiouwy])ied$/i, '$1ie'],
|
|
163
165
|
[/ied$/i, 'y'],
|
|
164
166
|
[/([aeiou])lved$/i, '$1lf'],
|
|
167
|
+
[/([^aeiou])icked$/i, '$1ic'],
|
|
165
168
|
[/([bcdfghjklmnpqrstvwxyz])\1ed$/i, '$1'],
|
|
169
|
+
[/([aeiou])ked$/i, '$1ke'],
|
|
170
|
+
[/ined$/i, 'ine'],
|
|
171
|
+
[/eted$/i, 'ete'],
|
|
172
|
+
[/gued$/i, 'gue'],
|
|
166
173
|
[/ed$/i, ''],
|
|
167
174
|
]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nhb-toolbox",
|
|
3
|
-
"version": "4.20.
|
|
3
|
+
"version": "4.20.40",
|
|
4
4
|
"description": "A versatile collection of smart, efficient, and reusable utility functions and classes for everyday development needs.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|