nhb-toolbox 4.13.6 → 4.13.7
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 +5 -0
- package/dist/cjs/pluralize/Pluralizer.js +43 -15
- package/dist/cjs/pluralize/rules.js +139 -120
- package/dist/dts/pluralize/Pluralizer.d.ts.map +1 -1
- package/dist/dts/pluralize/rules.d.ts +5 -5
- package/dist/dts/pluralize/rules.d.ts.map +1 -1
- package/dist/esm/pluralize/Pluralizer.js +43 -15
- package/dist/esm/pluralize/rules.js +138 -119
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,11 @@ All notable changes to the package will be documented here.
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [4.13.7] - 2025-07-23
|
|
10
|
+
|
|
11
|
+
- **Updated** `isPlural` and `isSingular` methods in `Pluralizer` class to handle more cases.
|
|
12
|
+
- **Ran full test** on `pluralizer` and fixed some known issues.
|
|
13
|
+
|
|
9
14
|
## [4.13.3-6] - 2025-07-22
|
|
10
15
|
|
|
11
16
|
- **Reordered** rules for `pluralizer` and fixed other issues.
|
|
@@ -56,17 +56,31 @@ class Pluralizer {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
#restoreCase(original, transformed) {
|
|
59
|
+
// Exact match
|
|
60
|
+
if (original === transformed)
|
|
61
|
+
return transformed;
|
|
62
|
+
// Entire original is lowercase
|
|
63
|
+
if (original === original.toLowerCase()) {
|
|
64
|
+
return transformed.toLowerCase();
|
|
65
|
+
}
|
|
66
|
+
// Entire original is uppercase
|
|
67
|
+
if (original === original.toUpperCase()) {
|
|
68
|
+
return transformed.toUpperCase();
|
|
69
|
+
}
|
|
70
|
+
// Title case (first letter uppercase, rest lowercase)
|
|
71
|
+
if (original[0] === original[0].toUpperCase() &&
|
|
72
|
+
original.slice(1) === original.slice(1).toLowerCase()) {
|
|
73
|
+
return (transformed.charAt(0).toUpperCase() +
|
|
74
|
+
transformed.slice(1).toLowerCase());
|
|
75
|
+
}
|
|
76
|
+
// Mixed case: per-character casing
|
|
59
77
|
let result = '';
|
|
60
78
|
for (let i = 0; i < transformed.length; i++) {
|
|
61
79
|
const origChar = original[i];
|
|
62
|
-
if (origChar
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
result += transformed[i].toLowerCase();
|
|
69
|
-
}
|
|
80
|
+
if (origChar &&
|
|
81
|
+
origChar === origChar.toUpperCase() &&
|
|
82
|
+
origChar !== origChar.toLowerCase()) {
|
|
83
|
+
result += transformed[i].toUpperCase();
|
|
70
84
|
}
|
|
71
85
|
else {
|
|
72
86
|
result += transformed[i].toLowerCase();
|
|
@@ -210,11 +224,18 @@ class Pluralizer {
|
|
|
210
224
|
* pluralizer.isPlural('children'); // true
|
|
211
225
|
*/
|
|
212
226
|
isPlural(word) {
|
|
213
|
-
|
|
214
|
-
if (this.#isUncountable(word))
|
|
227
|
+
if (!(0, primitives_1.isNonEmptyString)(word))
|
|
215
228
|
return false;
|
|
216
|
-
|
|
229
|
+
const lower = word.toLowerCase();
|
|
230
|
+
// if uncountable return true
|
|
231
|
+
if (this.#isUncountable(lower))
|
|
232
|
+
return true;
|
|
233
|
+
// directly known as plural
|
|
234
|
+
if (this.#irregularPlurals[lower])
|
|
217
235
|
return true;
|
|
236
|
+
// directly known as singular
|
|
237
|
+
if (this.#irregularSingles[lower])
|
|
238
|
+
return false;
|
|
218
239
|
return this.toSingular(lower) !== lower;
|
|
219
240
|
}
|
|
220
241
|
/**
|
|
@@ -225,12 +246,19 @@ class Pluralizer {
|
|
|
225
246
|
* pluralizer.isSingular('child'); // true
|
|
226
247
|
*/
|
|
227
248
|
isSingular(word) {
|
|
228
|
-
|
|
229
|
-
if (this.#isUncountable(word))
|
|
249
|
+
if (!(0, primitives_1.isNonEmptyString)(word))
|
|
230
250
|
return false;
|
|
231
|
-
|
|
251
|
+
const lower = word.toLowerCase();
|
|
252
|
+
// if uncountable return true
|
|
253
|
+
if (this.#isUncountable(lower))
|
|
254
|
+
return true;
|
|
255
|
+
// directly known as singular
|
|
256
|
+
if (this.#irregularSingles[lower])
|
|
232
257
|
return true;
|
|
233
|
-
|
|
258
|
+
// directly known as plural
|
|
259
|
+
if (this.#irregularPlurals[lower])
|
|
260
|
+
return false;
|
|
261
|
+
return this.toSingular(lower) === lower;
|
|
234
262
|
}
|
|
235
263
|
}
|
|
236
264
|
exports.Pluralizer = Pluralizer;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
/** Irregular
|
|
3
|
+
exports.uncountables = exports.singularRules = exports.pluralRules = exports.irregularRules = void 0;
|
|
4
|
+
/** Irregular singular → plural mappings */
|
|
5
5
|
exports.irregularRules =
|
|
6
6
|
/* @__PURE__ */ Object.freeze([
|
|
7
7
|
// Pronouns
|
|
@@ -26,68 +26,79 @@ exports.irregularRules =
|
|
|
26
26
|
['his', 'their'],
|
|
27
27
|
['her', 'their'],
|
|
28
28
|
// Common irregulars
|
|
29
|
+
['analysis', 'analyses'],
|
|
30
|
+
['anathema', 'anathemata'],
|
|
31
|
+
['appendix', 'appendices'],
|
|
32
|
+
['automaton', 'automata'],
|
|
33
|
+
['basis', 'bases'],
|
|
34
|
+
['calf', 'calves'],
|
|
35
|
+
['carve', 'carves'],
|
|
29
36
|
['child', 'children'],
|
|
30
|
-
['
|
|
31
|
-
['
|
|
32
|
-
['
|
|
33
|
-
['
|
|
37
|
+
['codex', 'codices'],
|
|
38
|
+
['criterion', 'criteria'],
|
|
39
|
+
['crisis', 'crises'],
|
|
40
|
+
['datum', 'data'],
|
|
41
|
+
['diagnosis', 'diagnoses'],
|
|
42
|
+
['die', 'dice'],
|
|
43
|
+
['dogma', 'dogmata'],
|
|
44
|
+
['echo', 'echoes'],
|
|
45
|
+
['elf', 'elves'],
|
|
34
46
|
['foot', 'feet'],
|
|
35
|
-
['
|
|
47
|
+
['genus', 'genera'],
|
|
36
48
|
['goose', 'geese'],
|
|
37
|
-
['
|
|
49
|
+
['groove', 'grooves'],
|
|
50
|
+
['half', 'halves'],
|
|
51
|
+
['hedron', 'hedra'],
|
|
52
|
+
['hero', 'heroes'],
|
|
53
|
+
['hoof', 'hooves'],
|
|
54
|
+
['human', 'humans'],
|
|
55
|
+
['honey', 'honeys'],
|
|
56
|
+
['index', 'indices'],
|
|
38
57
|
['leaf', 'leaves'],
|
|
39
|
-
['
|
|
58
|
+
['lemma', 'lemmata'],
|
|
59
|
+
['loaf', 'loaves'],
|
|
60
|
+
['looey', 'looies'],
|
|
61
|
+
['man', 'men'],
|
|
62
|
+
['mango', 'mangoes'],
|
|
63
|
+
['matrix', 'matrices'],
|
|
40
64
|
['medium', 'media'],
|
|
41
|
-
['
|
|
42
|
-
['
|
|
43
|
-
['
|
|
44
|
-
['
|
|
45
|
-
['
|
|
65
|
+
['mouse', 'mice'],
|
|
66
|
+
['neurosis', 'neuroses'],
|
|
67
|
+
['noumenon', 'noumena'],
|
|
68
|
+
['organon', 'organa'],
|
|
69
|
+
['ox', 'oxen'],
|
|
70
|
+
['passerby', 'passersby'],
|
|
46
71
|
['phenomenon', 'phenomena'],
|
|
47
|
-
['
|
|
48
|
-
['
|
|
49
|
-
['
|
|
50
|
-
['vertex', 'vertices'],
|
|
51
|
-
['quiz', 'quizzes'],
|
|
52
|
-
['die', 'dice'],
|
|
53
|
-
['yes', 'yeses'],
|
|
54
|
-
['human', 'humans'],
|
|
72
|
+
['pickaxe', 'pickaxes'],
|
|
73
|
+
['potato', 'potatoes'],
|
|
74
|
+
['prolegomenon', 'prolegomena'],
|
|
55
75
|
['proof', 'proofs'],
|
|
56
|
-
['
|
|
57
|
-
['
|
|
58
|
-
['
|
|
76
|
+
['quiz', 'quizzes'],
|
|
77
|
+
['schema', 'schemata'],
|
|
78
|
+
['self', 'selves'],
|
|
79
|
+
['shelf', 'shelves'],
|
|
80
|
+
['stigma', 'stigmata'],
|
|
81
|
+
['stoma', 'stomata'],
|
|
59
82
|
['thief', 'thieves'],
|
|
60
|
-
['
|
|
61
|
-
['
|
|
62
|
-
['passerby', 'passersby'],
|
|
63
|
-
['honey', 'honeys'],
|
|
64
|
-
['virus', 'viruses'],
|
|
65
|
-
// Words ending in with a consonant and `o`.
|
|
66
|
-
['echo', 'echoes'],
|
|
67
|
-
['dingo', 'dingoes'],
|
|
68
|
-
['mango', 'mangoes'],
|
|
69
|
-
['volcano', 'volcanoes'],
|
|
70
|
-
['tornado', 'tornadoes'],
|
|
83
|
+
['tooth', 'teeth'],
|
|
84
|
+
['tomato', 'tomatoes'],
|
|
71
85
|
['torpedo', 'torpedoes'],
|
|
72
|
-
|
|
73
|
-
['
|
|
86
|
+
['tornado', 'tornadoes'],
|
|
87
|
+
['valve', 'valves'],
|
|
88
|
+
['vertex', 'vertices'],
|
|
89
|
+
['virus', 'viruses'],
|
|
74
90
|
['viscus', 'viscera'],
|
|
75
|
-
|
|
76
|
-
['
|
|
77
|
-
['
|
|
78
|
-
['
|
|
79
|
-
['lemma', 'lemmata'],
|
|
80
|
-
['schema', 'schemata'],
|
|
81
|
-
['anathema', 'anathemata'],
|
|
91
|
+
['volcano', 'volcanoes'],
|
|
92
|
+
['woman', 'women'],
|
|
93
|
+
['wolf', 'wolves'],
|
|
94
|
+
['yes', 'yeses'],
|
|
82
95
|
]);
|
|
83
|
-
/**
|
|
96
|
+
/** Pluralization rules with regex and replacements */
|
|
84
97
|
exports.pluralRules =
|
|
85
98
|
/* @__PURE__ */ Object.freeze([
|
|
86
|
-
[/s
|
|
87
|
-
[/(\P{ASCII})$/u, '$1'],
|
|
99
|
+
[/s?$/i, 's'],
|
|
88
100
|
[/(pe)(rson|ople)$/i, '$1ople'],
|
|
89
101
|
[/(child)(?:ren)?$/i, '$1ren'],
|
|
90
|
-
[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'],
|
|
91
102
|
[/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'],
|
|
92
103
|
[
|
|
93
104
|
/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,
|
|
@@ -106,7 +117,10 @@ exports.pluralRules =
|
|
|
106
117
|
[/(x|ch|ss|sh|zz)$/i, '$1es'],
|
|
107
118
|
[/(her|at|gr)o$/i, '$1oes'],
|
|
108
119
|
[/sis$/i, 'ses'],
|
|
109
|
-
[
|
|
120
|
+
[/^(chief|chef|belief|roof|cliff|reef)$/i, '$1s'],
|
|
121
|
+
[/(seraph|cherub)$/i, '$1im'],
|
|
122
|
+
[/(kni|wi|li)fe$/i, '$1ves'],
|
|
123
|
+
[/(ar|l|ea|eo|oa|hoo)f$/i, '$1ves'],
|
|
110
124
|
[/([^aeiouy]|qu)y$/i, '$1ies'],
|
|
111
125
|
[/(tive)$/i, '$1s'],
|
|
112
126
|
[/(hive)$/i, '$1s'],
|
|
@@ -118,8 +132,79 @@ exports.pluralRules =
|
|
|
118
132
|
'$1i',
|
|
119
133
|
],
|
|
120
134
|
]);
|
|
121
|
-
/**
|
|
135
|
+
/** Singularization rules with regex and replacements */
|
|
136
|
+
exports.singularRules =
|
|
137
|
+
/* @__PURE__ */ Object.freeze([
|
|
138
|
+
[/s$/i, ''],
|
|
139
|
+
[/(\P{ASCII})$/u, '$1'],
|
|
140
|
+
[/(pe)(rson|ople)$/i, '$1rson'],
|
|
141
|
+
[/(child)ren$/i, '$1'],
|
|
142
|
+
[/(eau)x?$/i, '$1'],
|
|
143
|
+
[/men$/i, 'man'],
|
|
144
|
+
[/(matr|append)ices$/i, '$1ix'],
|
|
145
|
+
[/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
|
|
146
|
+
[/(alumn|alg|vertebr)ae$/i, '$1a'],
|
|
147
|
+
[
|
|
148
|
+
/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,
|
|
149
|
+
'$1on',
|
|
150
|
+
],
|
|
151
|
+
[
|
|
152
|
+
/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,
|
|
153
|
+
'$1um',
|
|
154
|
+
],
|
|
155
|
+
[/(test)(?:is|es)$/i, '$1is'],
|
|
156
|
+
[/(movie|twelve|abuse|e[mn]u)s$/i, '$1'],
|
|
157
|
+
[
|
|
158
|
+
/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,
|
|
159
|
+
'$1sis',
|
|
160
|
+
],
|
|
161
|
+
[
|
|
162
|
+
/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,
|
|
163
|
+
'$1',
|
|
164
|
+
],
|
|
165
|
+
[/^(chief|chef|belief|roof|cliff|reef)s$/i, '$1'],
|
|
166
|
+
[/(seraph|cherub)im$/i, '$1'],
|
|
167
|
+
[/\b((?:tit)?m|l)ice$/i, '$1ouse'],
|
|
168
|
+
[/\b(mon|smil)ies$/i, '$1ey'],
|
|
169
|
+
[
|
|
170
|
+
/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,
|
|
171
|
+
'$1ie',
|
|
172
|
+
],
|
|
173
|
+
[/ies$/i, 'y'],
|
|
174
|
+
[/(kni|wi|li)ves$/i, '$1fe'],
|
|
175
|
+
[/(ar|l|ea|eo|oa|hoo)ves$/i, '$1f'],
|
|
176
|
+
[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
|
|
177
|
+
[
|
|
178
|
+
/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,
|
|
179
|
+
'$1fe',
|
|
180
|
+
],
|
|
181
|
+
[/(ss)$/i, '$1'],
|
|
182
|
+
[/(quiz)zes$/i, '$1'],
|
|
183
|
+
[/(vert|ind)ices$/i, '$1ex'],
|
|
184
|
+
[/^(ox)en$/i, '$1'],
|
|
185
|
+
[/(alias|status)es$/i, '$1'],
|
|
186
|
+
[/(octop|vir)i$/i, '$1us'],
|
|
187
|
+
[/(cris|ax|test)es$/i, '$1is'],
|
|
188
|
+
[/(shoe)s$/i, '$1'],
|
|
189
|
+
[/(her|at|gr)oes$/i, '$1o'],
|
|
190
|
+
[/oes$/i, 'o'],
|
|
191
|
+
[/(bus)es$/i, '$1'],
|
|
192
|
+
[/ices$/i, 'ex'],
|
|
193
|
+
[/(hive)s$/i, '$1'],
|
|
194
|
+
[/(tive)s$/i, '$1'],
|
|
195
|
+
[/([^f])ves$/i, '$1fe'],
|
|
196
|
+
[/([lr])ves$/i, '$1f'],
|
|
197
|
+
[/(^analy)ses$/i, '$1sis'],
|
|
198
|
+
[/([ti])a$/i, '$1um'],
|
|
199
|
+
[/(n)ews$/i, '$1ews'],
|
|
200
|
+
[
|
|
201
|
+
/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,
|
|
202
|
+
'$1us',
|
|
203
|
+
],
|
|
204
|
+
]);
|
|
205
|
+
/** Uncountable words */
|
|
122
206
|
exports.uncountables = Object.freeze(new Set([
|
|
207
|
+
// common
|
|
123
208
|
'aircraft',
|
|
124
209
|
'alcohol',
|
|
125
210
|
'ammo',
|
|
@@ -170,6 +255,7 @@ exports.uncountables = Object.freeze(new Set([
|
|
|
170
255
|
'weather',
|
|
171
256
|
'wildlife',
|
|
172
257
|
'you',
|
|
258
|
+
// abstract
|
|
173
259
|
'adulthood',
|
|
174
260
|
'advertising',
|
|
175
261
|
'anger',
|
|
@@ -181,9 +267,9 @@ exports.uncountables = Object.freeze(new Set([
|
|
|
181
267
|
'botany',
|
|
182
268
|
'carbon',
|
|
183
269
|
'chaos',
|
|
184
|
-
'coffee',
|
|
185
270
|
'cheese',
|
|
186
271
|
'childhood',
|
|
272
|
+
'coffee',
|
|
187
273
|
'compassion',
|
|
188
274
|
'cotton',
|
|
189
275
|
'dancing',
|
|
@@ -358,7 +444,7 @@ exports.uncountables = Object.freeze(new Set([
|
|
|
358
444
|
'youth',
|
|
359
445
|
'zinc',
|
|
360
446
|
'zoology',
|
|
361
|
-
//
|
|
447
|
+
// regex-based uncountables
|
|
362
448
|
/pok[eé]mon$/i,
|
|
363
449
|
/[^aeiou]ese$/i,
|
|
364
450
|
/deer$/i,
|
|
@@ -373,70 +459,3 @@ exports.uncountables = Object.freeze(new Set([
|
|
|
373
459
|
/trousers$/i,
|
|
374
460
|
/jeans$/i,
|
|
375
461
|
]));
|
|
376
|
-
/** Singular rules and replacements */
|
|
377
|
-
exports.singularRules =
|
|
378
|
-
/* @__PURE__ */ Object.freeze([
|
|
379
|
-
[/s$/i, ''],
|
|
380
|
-
[/(\P{ASCII})$/u, '$1'],
|
|
381
|
-
[/(pe)(rson|ople)$/i, '$1rson'],
|
|
382
|
-
[/(child)ren$/i, '$1'],
|
|
383
|
-
[/(eau)x?$/i, '$1'],
|
|
384
|
-
[/men$/i, 'man'],
|
|
385
|
-
[/(matr|append)ices$/i, '$1ix'],
|
|
386
|
-
[/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
|
|
387
|
-
[/(alumn|alg|vertebr)ae$/i, '$1a'],
|
|
388
|
-
[
|
|
389
|
-
/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,
|
|
390
|
-
'$1on',
|
|
391
|
-
],
|
|
392
|
-
[
|
|
393
|
-
/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,
|
|
394
|
-
'$1um',
|
|
395
|
-
],
|
|
396
|
-
[/(test)(?:is|es)$/i, '$1is'],
|
|
397
|
-
[/(movie|twelve|abuse|e[mn]u)s$/i, '$1'],
|
|
398
|
-
[
|
|
399
|
-
/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,
|
|
400
|
-
'$1sis',
|
|
401
|
-
],
|
|
402
|
-
[
|
|
403
|
-
/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,
|
|
404
|
-
'$1',
|
|
405
|
-
],
|
|
406
|
-
[/(seraph|cherub)im$/i, '$1'],
|
|
407
|
-
[/\b((?:tit)?m|l)ice$/i, '$1ouse'],
|
|
408
|
-
[/\b(mon|smil)ies$/i, '$1ey'],
|
|
409
|
-
[
|
|
410
|
-
/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,
|
|
411
|
-
'$1ie',
|
|
412
|
-
],
|
|
413
|
-
[/ies$/i, 'y'],
|
|
414
|
-
[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
|
|
415
|
-
[
|
|
416
|
-
/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,
|
|
417
|
-
'$1fe',
|
|
418
|
-
],
|
|
419
|
-
[/(ss)$/i, '$1'],
|
|
420
|
-
[/(quiz)zes$/i, '$1'],
|
|
421
|
-
[/(matr)ices$/i, '$1ix'],
|
|
422
|
-
[/(vert|ind)ices$/i, '$1ex'],
|
|
423
|
-
[/^(ox)en$/i, '$1'],
|
|
424
|
-
[/(alias|status)es$/i, '$1'],
|
|
425
|
-
[/(octop|vir)i$/i, '$1us'],
|
|
426
|
-
[/(cris|ax|test)es$/i, '$1is'],
|
|
427
|
-
[/(shoe)s$/i, '$1'],
|
|
428
|
-
[/(o)es$/i, '$1'],
|
|
429
|
-
[/(bus)es$/i, '$1'],
|
|
430
|
-
[/ices$/i, 'ex'],
|
|
431
|
-
[/(hive)s$/i, '$1'],
|
|
432
|
-
[/(tive)s$/i, '$1'],
|
|
433
|
-
[/([^f])ves$/i, '$1fe'],
|
|
434
|
-
[/([lr])ves$/i, '$1f'],
|
|
435
|
-
[/(^analy)ses$/i, '$1sis'],
|
|
436
|
-
[/([ti])a$/i, '$1um'],
|
|
437
|
-
[/(n)ews$/i, '$1ews'],
|
|
438
|
-
[
|
|
439
|
-
/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,
|
|
440
|
-
'$1us',
|
|
441
|
-
],
|
|
442
|
-
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pluralizer.d.ts","sourceRoot":"","sources":["../../../src/pluralize/Pluralizer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAgB,gBAAgB,EAAiB,MAAM,SAAS,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAU;;IAOtB;;;OAGG;;
|
|
1
|
+
{"version":3,"file":"Pluralizer.d.ts","sourceRoot":"","sources":["../../../src/pluralize/Pluralizer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAgB,gBAAgB,EAAiB,MAAM,SAAS,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAU;;IAOtB;;;OAGG;;IAuGH;;;;;;OAMG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAItD;;;;;;OAMG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAIxD;;;;;;OAMG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAM3C;;;;;;OAMG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAOlD;;;;;;;;OAQG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM;IAY/D;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAiB9B;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAiBhC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAc/B;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAajC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,UAAU,YAAmB,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { PluralizeRule } from './types';
|
|
2
|
-
/** Irregular
|
|
2
|
+
/** Irregular singular → plural mappings */
|
|
3
3
|
export declare const irregularRules: readonly [string, string][];
|
|
4
|
-
/**
|
|
4
|
+
/** Pluralization rules with regex and replacements */
|
|
5
5
|
export declare const pluralRules: readonly PluralizeRule[];
|
|
6
|
-
/**
|
|
7
|
-
export declare const uncountables: Readonly<Set<string | RegExp>>;
|
|
8
|
-
/** Singular rules and replacements */
|
|
6
|
+
/** Singularization rules with regex and replacements */
|
|
9
7
|
export declare const singularRules: readonly PluralizeRule[];
|
|
8
|
+
/** Uncountable words */
|
|
9
|
+
export declare const uncountables: Readonly<Set<string | RegExp>>;
|
|
10
10
|
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/pluralize/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/pluralize/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,2CAA2C;AAC3C,eAAO,MAAM,cAAc,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EA2FnD,CAAC;AAEJ,sDAAsD;AACtD,eAAO,MAAM,WAAW,EAAE,SAAS,aAAa,EAqC7C,CAAC;AAEJ,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,SAAS,aAAa,EAoE/C,CAAC;AAEJ,wBAAwB;AACxB,eAAO,MAAM,YAAY,gCAmQxB,CAAC"}
|
|
@@ -53,17 +53,31 @@ export class Pluralizer {
|
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
#restoreCase(original, transformed) {
|
|
56
|
+
// Exact match
|
|
57
|
+
if (original === transformed)
|
|
58
|
+
return transformed;
|
|
59
|
+
// Entire original is lowercase
|
|
60
|
+
if (original === original.toLowerCase()) {
|
|
61
|
+
return transformed.toLowerCase();
|
|
62
|
+
}
|
|
63
|
+
// Entire original is uppercase
|
|
64
|
+
if (original === original.toUpperCase()) {
|
|
65
|
+
return transformed.toUpperCase();
|
|
66
|
+
}
|
|
67
|
+
// Title case (first letter uppercase, rest lowercase)
|
|
68
|
+
if (original[0] === original[0].toUpperCase() &&
|
|
69
|
+
original.slice(1) === original.slice(1).toLowerCase()) {
|
|
70
|
+
return (transformed.charAt(0).toUpperCase() +
|
|
71
|
+
transformed.slice(1).toLowerCase());
|
|
72
|
+
}
|
|
73
|
+
// Mixed case: per-character casing
|
|
56
74
|
let result = '';
|
|
57
75
|
for (let i = 0; i < transformed.length; i++) {
|
|
58
76
|
const origChar = original[i];
|
|
59
|
-
if (origChar
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
result += transformed[i].toLowerCase();
|
|
66
|
-
}
|
|
77
|
+
if (origChar &&
|
|
78
|
+
origChar === origChar.toUpperCase() &&
|
|
79
|
+
origChar !== origChar.toLowerCase()) {
|
|
80
|
+
result += transformed[i].toUpperCase();
|
|
67
81
|
}
|
|
68
82
|
else {
|
|
69
83
|
result += transformed[i].toLowerCase();
|
|
@@ -207,11 +221,18 @@ export class Pluralizer {
|
|
|
207
221
|
* pluralizer.isPlural('children'); // true
|
|
208
222
|
*/
|
|
209
223
|
isPlural(word) {
|
|
210
|
-
|
|
211
|
-
if (this.#isUncountable(word))
|
|
224
|
+
if (!isNonEmptyString(word))
|
|
212
225
|
return false;
|
|
213
|
-
|
|
226
|
+
const lower = word.toLowerCase();
|
|
227
|
+
// if uncountable return true
|
|
228
|
+
if (this.#isUncountable(lower))
|
|
229
|
+
return true;
|
|
230
|
+
// directly known as plural
|
|
231
|
+
if (this.#irregularPlurals[lower])
|
|
214
232
|
return true;
|
|
233
|
+
// directly known as singular
|
|
234
|
+
if (this.#irregularSingles[lower])
|
|
235
|
+
return false;
|
|
215
236
|
return this.toSingular(lower) !== lower;
|
|
216
237
|
}
|
|
217
238
|
/**
|
|
@@ -222,12 +243,19 @@ export class Pluralizer {
|
|
|
222
243
|
* pluralizer.isSingular('child'); // true
|
|
223
244
|
*/
|
|
224
245
|
isSingular(word) {
|
|
225
|
-
|
|
226
|
-
if (this.#isUncountable(word))
|
|
246
|
+
if (!isNonEmptyString(word))
|
|
227
247
|
return false;
|
|
228
|
-
|
|
248
|
+
const lower = word.toLowerCase();
|
|
249
|
+
// if uncountable return true
|
|
250
|
+
if (this.#isUncountable(lower))
|
|
251
|
+
return true;
|
|
252
|
+
// directly known as singular
|
|
253
|
+
if (this.#irregularSingles[lower])
|
|
229
254
|
return true;
|
|
230
|
-
|
|
255
|
+
// directly known as plural
|
|
256
|
+
if (this.#irregularPlurals[lower])
|
|
257
|
+
return false;
|
|
258
|
+
return this.toSingular(lower) === lower;
|
|
231
259
|
}
|
|
232
260
|
}
|
|
233
261
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Irregular
|
|
1
|
+
/** Irregular singular → plural mappings */
|
|
2
2
|
export const irregularRules =
|
|
3
3
|
/* @__PURE__ */ Object.freeze([
|
|
4
4
|
// Pronouns
|
|
@@ -23,68 +23,79 @@ export const irregularRules =
|
|
|
23
23
|
['his', 'their'],
|
|
24
24
|
['her', 'their'],
|
|
25
25
|
// Common irregulars
|
|
26
|
+
['analysis', 'analyses'],
|
|
27
|
+
['anathema', 'anathemata'],
|
|
28
|
+
['appendix', 'appendices'],
|
|
29
|
+
['automaton', 'automata'],
|
|
30
|
+
['basis', 'bases'],
|
|
31
|
+
['calf', 'calves'],
|
|
32
|
+
['carve', 'carves'],
|
|
26
33
|
['child', 'children'],
|
|
27
|
-
['
|
|
28
|
-
['
|
|
29
|
-
['
|
|
30
|
-
['
|
|
34
|
+
['codex', 'codices'],
|
|
35
|
+
['criterion', 'criteria'],
|
|
36
|
+
['crisis', 'crises'],
|
|
37
|
+
['datum', 'data'],
|
|
38
|
+
['diagnosis', 'diagnoses'],
|
|
39
|
+
['die', 'dice'],
|
|
40
|
+
['dogma', 'dogmata'],
|
|
41
|
+
['echo', 'echoes'],
|
|
42
|
+
['elf', 'elves'],
|
|
31
43
|
['foot', 'feet'],
|
|
32
|
-
['
|
|
44
|
+
['genus', 'genera'],
|
|
33
45
|
['goose', 'geese'],
|
|
34
|
-
['
|
|
46
|
+
['groove', 'grooves'],
|
|
47
|
+
['half', 'halves'],
|
|
48
|
+
['hedron', 'hedra'],
|
|
49
|
+
['hero', 'heroes'],
|
|
50
|
+
['hoof', 'hooves'],
|
|
51
|
+
['human', 'humans'],
|
|
52
|
+
['honey', 'honeys'],
|
|
53
|
+
['index', 'indices'],
|
|
35
54
|
['leaf', 'leaves'],
|
|
36
|
-
['
|
|
55
|
+
['lemma', 'lemmata'],
|
|
56
|
+
['loaf', 'loaves'],
|
|
57
|
+
['looey', 'looies'],
|
|
58
|
+
['man', 'men'],
|
|
59
|
+
['mango', 'mangoes'],
|
|
60
|
+
['matrix', 'matrices'],
|
|
37
61
|
['medium', 'media'],
|
|
38
|
-
['
|
|
39
|
-
['
|
|
40
|
-
['
|
|
41
|
-
['
|
|
42
|
-
['
|
|
62
|
+
['mouse', 'mice'],
|
|
63
|
+
['neurosis', 'neuroses'],
|
|
64
|
+
['noumenon', 'noumena'],
|
|
65
|
+
['organon', 'organa'],
|
|
66
|
+
['ox', 'oxen'],
|
|
67
|
+
['passerby', 'passersby'],
|
|
43
68
|
['phenomenon', 'phenomena'],
|
|
44
|
-
['
|
|
45
|
-
['
|
|
46
|
-
['
|
|
47
|
-
['vertex', 'vertices'],
|
|
48
|
-
['quiz', 'quizzes'],
|
|
49
|
-
['die', 'dice'],
|
|
50
|
-
['yes', 'yeses'],
|
|
51
|
-
['human', 'humans'],
|
|
69
|
+
['pickaxe', 'pickaxes'],
|
|
70
|
+
['potato', 'potatoes'],
|
|
71
|
+
['prolegomenon', 'prolegomena'],
|
|
52
72
|
['proof', 'proofs'],
|
|
53
|
-
['
|
|
54
|
-
['
|
|
55
|
-
['
|
|
73
|
+
['quiz', 'quizzes'],
|
|
74
|
+
['schema', 'schemata'],
|
|
75
|
+
['self', 'selves'],
|
|
76
|
+
['shelf', 'shelves'],
|
|
77
|
+
['stigma', 'stigmata'],
|
|
78
|
+
['stoma', 'stomata'],
|
|
56
79
|
['thief', 'thieves'],
|
|
57
|
-
['
|
|
58
|
-
['
|
|
59
|
-
['passerby', 'passersby'],
|
|
60
|
-
['honey', 'honeys'],
|
|
61
|
-
['virus', 'viruses'],
|
|
62
|
-
// Words ending in with a consonant and `o`.
|
|
63
|
-
['echo', 'echoes'],
|
|
64
|
-
['dingo', 'dingoes'],
|
|
65
|
-
['mango', 'mangoes'],
|
|
66
|
-
['volcano', 'volcanoes'],
|
|
67
|
-
['tornado', 'tornadoes'],
|
|
80
|
+
['tooth', 'teeth'],
|
|
81
|
+
['tomato', 'tomatoes'],
|
|
68
82
|
['torpedo', 'torpedoes'],
|
|
69
|
-
|
|
70
|
-
['
|
|
83
|
+
['tornado', 'tornadoes'],
|
|
84
|
+
['valve', 'valves'],
|
|
85
|
+
['vertex', 'vertices'],
|
|
86
|
+
['virus', 'viruses'],
|
|
71
87
|
['viscus', 'viscera'],
|
|
72
|
-
|
|
73
|
-
['
|
|
74
|
-
['
|
|
75
|
-
['
|
|
76
|
-
['lemma', 'lemmata'],
|
|
77
|
-
['schema', 'schemata'],
|
|
78
|
-
['anathema', 'anathemata'],
|
|
88
|
+
['volcano', 'volcanoes'],
|
|
89
|
+
['woman', 'women'],
|
|
90
|
+
['wolf', 'wolves'],
|
|
91
|
+
['yes', 'yeses'],
|
|
79
92
|
]);
|
|
80
|
-
/**
|
|
93
|
+
/** Pluralization rules with regex and replacements */
|
|
81
94
|
export const pluralRules =
|
|
82
95
|
/* @__PURE__ */ Object.freeze([
|
|
83
|
-
[/s
|
|
84
|
-
[/(\P{ASCII})$/u, '$1'],
|
|
96
|
+
[/s?$/i, 's'],
|
|
85
97
|
[/(pe)(rson|ople)$/i, '$1ople'],
|
|
86
98
|
[/(child)(?:ren)?$/i, '$1ren'],
|
|
87
|
-
[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'],
|
|
88
99
|
[/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'],
|
|
89
100
|
[
|
|
90
101
|
/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,
|
|
@@ -103,7 +114,10 @@ export const pluralRules =
|
|
|
103
114
|
[/(x|ch|ss|sh|zz)$/i, '$1es'],
|
|
104
115
|
[/(her|at|gr)o$/i, '$1oes'],
|
|
105
116
|
[/sis$/i, 'ses'],
|
|
106
|
-
[
|
|
117
|
+
[/^(chief|chef|belief|roof|cliff|reef)$/i, '$1s'],
|
|
118
|
+
[/(seraph|cherub)$/i, '$1im'],
|
|
119
|
+
[/(kni|wi|li)fe$/i, '$1ves'],
|
|
120
|
+
[/(ar|l|ea|eo|oa|hoo)f$/i, '$1ves'],
|
|
107
121
|
[/([^aeiouy]|qu)y$/i, '$1ies'],
|
|
108
122
|
[/(tive)$/i, '$1s'],
|
|
109
123
|
[/(hive)$/i, '$1s'],
|
|
@@ -115,8 +129,79 @@ export const pluralRules =
|
|
|
115
129
|
'$1i',
|
|
116
130
|
],
|
|
117
131
|
]);
|
|
118
|
-
/**
|
|
132
|
+
/** Singularization rules with regex and replacements */
|
|
133
|
+
export const singularRules =
|
|
134
|
+
/* @__PURE__ */ Object.freeze([
|
|
135
|
+
[/s$/i, ''],
|
|
136
|
+
[/(\P{ASCII})$/u, '$1'],
|
|
137
|
+
[/(pe)(rson|ople)$/i, '$1rson'],
|
|
138
|
+
[/(child)ren$/i, '$1'],
|
|
139
|
+
[/(eau)x?$/i, '$1'],
|
|
140
|
+
[/men$/i, 'man'],
|
|
141
|
+
[/(matr|append)ices$/i, '$1ix'],
|
|
142
|
+
[/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
|
|
143
|
+
[/(alumn|alg|vertebr)ae$/i, '$1a'],
|
|
144
|
+
[
|
|
145
|
+
/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,
|
|
146
|
+
'$1on',
|
|
147
|
+
],
|
|
148
|
+
[
|
|
149
|
+
/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,
|
|
150
|
+
'$1um',
|
|
151
|
+
],
|
|
152
|
+
[/(test)(?:is|es)$/i, '$1is'],
|
|
153
|
+
[/(movie|twelve|abuse|e[mn]u)s$/i, '$1'],
|
|
154
|
+
[
|
|
155
|
+
/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,
|
|
156
|
+
'$1sis',
|
|
157
|
+
],
|
|
158
|
+
[
|
|
159
|
+
/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,
|
|
160
|
+
'$1',
|
|
161
|
+
],
|
|
162
|
+
[/^(chief|chef|belief|roof|cliff|reef)s$/i, '$1'],
|
|
163
|
+
[/(seraph|cherub)im$/i, '$1'],
|
|
164
|
+
[/\b((?:tit)?m|l)ice$/i, '$1ouse'],
|
|
165
|
+
[/\b(mon|smil)ies$/i, '$1ey'],
|
|
166
|
+
[
|
|
167
|
+
/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,
|
|
168
|
+
'$1ie',
|
|
169
|
+
],
|
|
170
|
+
[/ies$/i, 'y'],
|
|
171
|
+
[/(kni|wi|li)ves$/i, '$1fe'],
|
|
172
|
+
[/(ar|l|ea|eo|oa|hoo)ves$/i, '$1f'],
|
|
173
|
+
[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
|
|
174
|
+
[
|
|
175
|
+
/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,
|
|
176
|
+
'$1fe',
|
|
177
|
+
],
|
|
178
|
+
[/(ss)$/i, '$1'],
|
|
179
|
+
[/(quiz)zes$/i, '$1'],
|
|
180
|
+
[/(vert|ind)ices$/i, '$1ex'],
|
|
181
|
+
[/^(ox)en$/i, '$1'],
|
|
182
|
+
[/(alias|status)es$/i, '$1'],
|
|
183
|
+
[/(octop|vir)i$/i, '$1us'],
|
|
184
|
+
[/(cris|ax|test)es$/i, '$1is'],
|
|
185
|
+
[/(shoe)s$/i, '$1'],
|
|
186
|
+
[/(her|at|gr)oes$/i, '$1o'],
|
|
187
|
+
[/oes$/i, 'o'],
|
|
188
|
+
[/(bus)es$/i, '$1'],
|
|
189
|
+
[/ices$/i, 'ex'],
|
|
190
|
+
[/(hive)s$/i, '$1'],
|
|
191
|
+
[/(tive)s$/i, '$1'],
|
|
192
|
+
[/([^f])ves$/i, '$1fe'],
|
|
193
|
+
[/([lr])ves$/i, '$1f'],
|
|
194
|
+
[/(^analy)ses$/i, '$1sis'],
|
|
195
|
+
[/([ti])a$/i, '$1um'],
|
|
196
|
+
[/(n)ews$/i, '$1ews'],
|
|
197
|
+
[
|
|
198
|
+
/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,
|
|
199
|
+
'$1us',
|
|
200
|
+
],
|
|
201
|
+
]);
|
|
202
|
+
/** Uncountable words */
|
|
119
203
|
export const uncountables = /* @__PURE__ */ Object.freeze(new Set([
|
|
204
|
+
// common
|
|
120
205
|
'aircraft',
|
|
121
206
|
'alcohol',
|
|
122
207
|
'ammo',
|
|
@@ -167,6 +252,7 @@ export const uncountables = /* @__PURE__ */ Object.freeze(new Set([
|
|
|
167
252
|
'weather',
|
|
168
253
|
'wildlife',
|
|
169
254
|
'you',
|
|
255
|
+
// abstract
|
|
170
256
|
'adulthood',
|
|
171
257
|
'advertising',
|
|
172
258
|
'anger',
|
|
@@ -178,9 +264,9 @@ export const uncountables = /* @__PURE__ */ Object.freeze(new Set([
|
|
|
178
264
|
'botany',
|
|
179
265
|
'carbon',
|
|
180
266
|
'chaos',
|
|
181
|
-
'coffee',
|
|
182
267
|
'cheese',
|
|
183
268
|
'childhood',
|
|
269
|
+
'coffee',
|
|
184
270
|
'compassion',
|
|
185
271
|
'cotton',
|
|
186
272
|
'dancing',
|
|
@@ -355,7 +441,7 @@ export const uncountables = /* @__PURE__ */ Object.freeze(new Set([
|
|
|
355
441
|
'youth',
|
|
356
442
|
'zinc',
|
|
357
443
|
'zoology',
|
|
358
|
-
//
|
|
444
|
+
// regex-based uncountables
|
|
359
445
|
/pok[eé]mon$/i,
|
|
360
446
|
/[^aeiou]ese$/i,
|
|
361
447
|
/deer$/i,
|
|
@@ -370,70 +456,3 @@ export const uncountables = /* @__PURE__ */ Object.freeze(new Set([
|
|
|
370
456
|
/trousers$/i,
|
|
371
457
|
/jeans$/i,
|
|
372
458
|
]));
|
|
373
|
-
/** Singular rules and replacements */
|
|
374
|
-
export const singularRules =
|
|
375
|
-
/* @__PURE__ */ Object.freeze([
|
|
376
|
-
[/s$/i, ''],
|
|
377
|
-
[/(\P{ASCII})$/u, '$1'],
|
|
378
|
-
[/(pe)(rson|ople)$/i, '$1rson'],
|
|
379
|
-
[/(child)ren$/i, '$1'],
|
|
380
|
-
[/(eau)x?$/i, '$1'],
|
|
381
|
-
[/men$/i, 'man'],
|
|
382
|
-
[/(matr|append)ices$/i, '$1ix'],
|
|
383
|
-
[/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
|
|
384
|
-
[/(alumn|alg|vertebr)ae$/i, '$1a'],
|
|
385
|
-
[
|
|
386
|
-
/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,
|
|
387
|
-
'$1on',
|
|
388
|
-
],
|
|
389
|
-
[
|
|
390
|
-
/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,
|
|
391
|
-
'$1um',
|
|
392
|
-
],
|
|
393
|
-
[/(test)(?:is|es)$/i, '$1is'],
|
|
394
|
-
[/(movie|twelve|abuse|e[mn]u)s$/i, '$1'],
|
|
395
|
-
[
|
|
396
|
-
/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,
|
|
397
|
-
'$1sis',
|
|
398
|
-
],
|
|
399
|
-
[
|
|
400
|
-
/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,
|
|
401
|
-
'$1',
|
|
402
|
-
],
|
|
403
|
-
[/(seraph|cherub)im$/i, '$1'],
|
|
404
|
-
[/\b((?:tit)?m|l)ice$/i, '$1ouse'],
|
|
405
|
-
[/\b(mon|smil)ies$/i, '$1ey'],
|
|
406
|
-
[
|
|
407
|
-
/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,
|
|
408
|
-
'$1ie',
|
|
409
|
-
],
|
|
410
|
-
[/ies$/i, 'y'],
|
|
411
|
-
[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
|
|
412
|
-
[
|
|
413
|
-
/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,
|
|
414
|
-
'$1fe',
|
|
415
|
-
],
|
|
416
|
-
[/(ss)$/i, '$1'],
|
|
417
|
-
[/(quiz)zes$/i, '$1'],
|
|
418
|
-
[/(matr)ices$/i, '$1ix'],
|
|
419
|
-
[/(vert|ind)ices$/i, '$1ex'],
|
|
420
|
-
[/^(ox)en$/i, '$1'],
|
|
421
|
-
[/(alias|status)es$/i, '$1'],
|
|
422
|
-
[/(octop|vir)i$/i, '$1us'],
|
|
423
|
-
[/(cris|ax|test)es$/i, '$1is'],
|
|
424
|
-
[/(shoe)s$/i, '$1'],
|
|
425
|
-
[/(o)es$/i, '$1'],
|
|
426
|
-
[/(bus)es$/i, '$1'],
|
|
427
|
-
[/ices$/i, 'ex'],
|
|
428
|
-
[/(hive)s$/i, '$1'],
|
|
429
|
-
[/(tive)s$/i, '$1'],
|
|
430
|
-
[/([^f])ves$/i, '$1fe'],
|
|
431
|
-
[/([lr])ves$/i, '$1f'],
|
|
432
|
-
[/(^analy)ses$/i, '$1sis'],
|
|
433
|
-
[/([ti])a$/i, '$1um'],
|
|
434
|
-
[/(n)ews$/i, '$1ews'],
|
|
435
|
-
[
|
|
436
|
-
/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,
|
|
437
|
-
'$1us',
|
|
438
|
-
],
|
|
439
|
-
]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nhb-toolbox",
|
|
3
|
-
"version": "4.13.
|
|
3
|
+
"version": "4.13.7",
|
|
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",
|
|
@@ -243,6 +243,7 @@
|
|
|
243
243
|
},
|
|
244
244
|
"scripts": {
|
|
245
245
|
"test": "jest --coverage --verbose",
|
|
246
|
+
"start": "start coverage/lcov-report/index.html",
|
|
246
247
|
"format": "nhb-format",
|
|
247
248
|
"lint": "nhb-lint",
|
|
248
249
|
"fix": "nhb-fix",
|