@bccampus/utils 0.2.2 → 0.2.3
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/dist/array/index.d.ts +2 -1
- package/dist/date/index.d.ts +3 -1
- package/dist/duration/index.d.ts +4 -3
- package/dist/format/index.d.ts +5 -3
- package/dist/index.cjs +0 -3
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -4
- package/dist/object/index.d.ts +6 -5
- package/dist/path/index.d.ts +4 -2
- package/dist/set/index.d.ts +6 -5
- package/dist/string/index.d.ts +8 -6
- package/dist/value/index.d.ts +2 -1
- package/package.json +6 -1
- package/eslint.config.js +0 -19
- package/src/array/chunk.ts +0 -6
- package/src/array/index.ts +0 -1
- package/src/date/index.ts +0 -1
- package/src/date/iso-date-time.ts +0 -356
- package/src/duration/add-durations.ts +0 -16
- package/src/duration/index.ts +0 -3
- package/src/duration/is-duration.ts +0 -5
- package/src/duration/to-number.ts +0 -18
- package/src/format/formatter.ts +0 -37
- package/src/format/index.ts +0 -3
- package/src/format/stringify.ts +0 -87
- package/src/format/template.ts +0 -48
- package/src/index.ts +0 -1
- package/src/object/get.ts +0 -9
- package/src/object/index.ts +0 -5
- package/src/object/is-object.ts +0 -2
- package/src/object/omit.ts +0 -21
- package/src/object/pick.ts +0 -10
- package/src/object/set.ts +0 -15
- package/src/path/file-url-to-path.ts +0 -12
- package/src/path/index.ts +0 -2
- package/src/path/normalize.ts +0 -72
- package/src/set/difference.ts +0 -9
- package/src/set/index.ts +0 -5
- package/src/set/intersection.ts +0 -12
- package/src/set/is-superset.ts +0 -12
- package/src/set/symmetric-difference.ts +0 -12
- package/src/set/union.ts +0 -8
- package/src/string/capitalize.ts +0 -2
- package/src/string/index.ts +0 -6
- package/src/string/normalize.ts +0 -7
- package/src/string/pluralize/index.ts +0 -7
- package/src/string/pluralize/pluralize.ts +0 -296
- package/src/string/pluralize/rules/index.ts +0 -4
- package/src/string/pluralize/rules/irregular.ts +0 -59
- package/src/string/pluralize/rules/pluralization.ts +0 -40
- package/src/string/pluralize/rules/singularization.ts +0 -46
- package/src/string/pluralize/rules/uncountable.ts +0 -107
- package/src/string/pluralize/types.ts +0 -4
- package/src/string/slugify/index.ts +0 -3
- package/src/string/strip-html-tags.ts +0 -4
- package/src/string/to-int.ts +0 -20
- package/src/string/to-sentence-case.ts +0 -6
- package/src/string/trim.ts +0 -11
- package/src/string/truncate.ts +0 -44
- package/src/value/index.ts +0 -1
- package/src/value/is-empty.ts +0 -31
- package/tsconfig.json +0 -18
- package/tsconfig.lib.json +0 -37
- package/tsconfig.node.json +0 -25
- package/vite.config.ts +0 -76
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Typscript version of [pluralize](https://github.com/plurals/pluralize)
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Rule, RuleKey, RuleValue } from "./types";
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
IRREGULAR_WORDS,
|
|
9
|
-
PLURALIZATION_RULES,
|
|
10
|
-
SINGULARIZATION_RULES,
|
|
11
|
-
UNCOUNTABLE_WORDS,
|
|
12
|
-
} from "./rules";
|
|
13
|
-
|
|
14
|
-
const TagIndexRegExp = /\$(\d{1,2})/g;
|
|
15
|
-
|
|
16
|
-
export class Pluralize {
|
|
17
|
-
// Rule storage - pluralize and singularize need to be run sequentially,
|
|
18
|
-
// while other rules can be optimized using an object for instant lookups.
|
|
19
|
-
private pluralRules: Rule[] = [];
|
|
20
|
-
private singularRules: Rule[] = [];
|
|
21
|
-
private uncountables: Record<string, boolean> = {};
|
|
22
|
-
private irregularPlurals: Record<string, string> = {};
|
|
23
|
-
private irregularSingles: Record<string, string> = {};
|
|
24
|
-
|
|
25
|
-
constructor() {
|
|
26
|
-
for (let index = 0; index < IRREGULAR_WORDS.length; index += 1) {
|
|
27
|
-
this.addIrregularRule(
|
|
28
|
-
IRREGULAR_WORDS[index][0],
|
|
29
|
-
IRREGULAR_WORDS[index][1],
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
for (let index = 0; index < PLURALIZATION_RULES.length; index += 1) {
|
|
34
|
-
this.addPluralRule(
|
|
35
|
-
PLURALIZATION_RULES[index][0],
|
|
36
|
-
PLURALIZATION_RULES[index][1],
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
for (let index = 0; index < SINGULARIZATION_RULES.length; index += 1) {
|
|
41
|
-
this.addSingularRule(
|
|
42
|
-
SINGULARIZATION_RULES[index][0],
|
|
43
|
-
SINGULARIZATION_RULES[index][1],
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
for (let index = 0; index < UNCOUNTABLE_WORDS.length; index += 1) {
|
|
48
|
-
this.addUncountableRule(UNCOUNTABLE_WORDS[index]);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Add a pluralization rule to the collection.
|
|
54
|
-
*/
|
|
55
|
-
addPluralRule(rule: RuleKey, replacement: RuleValue) {
|
|
56
|
-
this.pluralRules.push([this.sanitizeRule(rule), replacement]);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Add a singularization rule to the collection.
|
|
61
|
-
*/
|
|
62
|
-
addSingularRule(rule: RuleKey, replacement: RuleValue) {
|
|
63
|
-
this.singularRules.push([this.sanitizeRule(rule), replacement]);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Add an uncountable word rule.
|
|
68
|
-
*/
|
|
69
|
-
addUncountableRule(word: RuleKey) {
|
|
70
|
-
if (typeof word === "string") {
|
|
71
|
-
this.uncountables[word.toLowerCase()] = true;
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Set singular and plural references for the word.
|
|
76
|
-
this.addPluralRule(word, "$0");
|
|
77
|
-
this.addSingularRule(word, "$0");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Add an irregular word definition.
|
|
82
|
-
*
|
|
83
|
-
* @param {string} single
|
|
84
|
-
* @param {string} plural
|
|
85
|
-
*/
|
|
86
|
-
addIrregularRule(single: string, plural: string) {
|
|
87
|
-
plural = plural.toLowerCase();
|
|
88
|
-
single = single.toLowerCase();
|
|
89
|
-
|
|
90
|
-
this.irregularSingles[single] = plural;
|
|
91
|
-
this.irregularPlurals[plural] = single;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Sanitize a pluralization rule to a usable regular expression.
|
|
96
|
-
*/
|
|
97
|
-
sanitizeRule(rule: RuleKey) {
|
|
98
|
-
if (typeof rule === "string") {
|
|
99
|
-
return new RegExp(`^${rule}$`, "i");
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return rule;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Pass in a word token to produce a function that can replicate the case on
|
|
107
|
-
* another word.
|
|
108
|
-
*/
|
|
109
|
-
restoreCase(word: string, token: string) {
|
|
110
|
-
// Tokens are an exact match.
|
|
111
|
-
if (word === token) return token;
|
|
112
|
-
|
|
113
|
-
// Lower cased words. E.g. "hello".
|
|
114
|
-
if (word === word.toLowerCase()) return token.toLowerCase();
|
|
115
|
-
|
|
116
|
-
// Upper cased words. E.g. "WHISKY".
|
|
117
|
-
if (word === word.toUpperCase()) return token.toUpperCase();
|
|
118
|
-
|
|
119
|
-
// Title cased words. E.g. "Title".
|
|
120
|
-
if (word[0] === word[0].toUpperCase()) {
|
|
121
|
-
return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Lower cased words. E.g. "test".
|
|
125
|
-
return token.toLowerCase();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Interpolate a regexp string.
|
|
130
|
-
*
|
|
131
|
-
* @param {string} str
|
|
132
|
-
* @param {Array} args
|
|
133
|
-
* @return {string}
|
|
134
|
-
*/
|
|
135
|
-
interpolate(str: string, args: string[]) {
|
|
136
|
-
return str.replace(TagIndexRegExp, (match, index) => {
|
|
137
|
-
return args[index] || "";
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Replace a word using a rule.
|
|
143
|
-
*/
|
|
144
|
-
replace(word: string, rule: Rule) {
|
|
145
|
-
return word.replace(rule[0], (match, index, ...args) => {
|
|
146
|
-
const result = this.interpolate(rule[1], args);
|
|
147
|
-
|
|
148
|
-
if (match === "") {
|
|
149
|
-
return this.restoreCase(word[index - 1], result);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return this.restoreCase(match, result);
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Sanitize a word by passing in the word and sanitization rules.
|
|
158
|
-
*/
|
|
159
|
-
sanitizeWord(token: string, word: string, rules: Rule[]) {
|
|
160
|
-
// Empty string or doesn't need fixing.
|
|
161
|
-
if (!token.length || this.uncountables[token]) {
|
|
162
|
-
return word;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
let len = rules.length;
|
|
166
|
-
|
|
167
|
-
// Iterate over the sanitization rules and use the first one to match.
|
|
168
|
-
while (len--) {
|
|
169
|
-
const rule = rules[len];
|
|
170
|
-
|
|
171
|
-
if (typeof rule[0] === "string" || rule[0].test(word))
|
|
172
|
-
return this.replace(word, rule);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return word;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Replace a word with the updated word.
|
|
180
|
-
*/
|
|
181
|
-
old_replaceWord(
|
|
182
|
-
replaceMap: Record<string, string>,
|
|
183
|
-
keepMap: Record<string, string>,
|
|
184
|
-
rules: Rule[],
|
|
185
|
-
) {
|
|
186
|
-
return (word: string) => {
|
|
187
|
-
// Get the correct token and case restoration functions.
|
|
188
|
-
const token = word.toLowerCase();
|
|
189
|
-
|
|
190
|
-
// Check against the keep object map.
|
|
191
|
-
if (keepMap[token]) {
|
|
192
|
-
return this.restoreCase(word, token);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Check against the replacement map for a direct word replacement.
|
|
196
|
-
if (replaceMap[token]) {
|
|
197
|
-
return this.restoreCase(word, replaceMap[token]);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Run all the rules against the word.
|
|
201
|
-
return this.sanitizeWord(token, word, rules);
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Replace a word with the updated word.
|
|
207
|
-
*/
|
|
208
|
-
private replaceWord(
|
|
209
|
-
word: string,
|
|
210
|
-
direction: "SingularToPlural" | "PluralToSingular",
|
|
211
|
-
) {
|
|
212
|
-
const replaceMap =
|
|
213
|
-
direction === "SingularToPlural"
|
|
214
|
-
? this.irregularSingles
|
|
215
|
-
: this.irregularPlurals;
|
|
216
|
-
const keepMap =
|
|
217
|
-
direction === "SingularToPlural"
|
|
218
|
-
? this.irregularPlurals
|
|
219
|
-
: this.irregularSingles;
|
|
220
|
-
const rules =
|
|
221
|
-
direction === "SingularToPlural" ? this.pluralRules : this.singularRules;
|
|
222
|
-
|
|
223
|
-
// Get the correct token and case restoration functions.
|
|
224
|
-
const token = word.toLowerCase();
|
|
225
|
-
|
|
226
|
-
// Check against the keep object map.
|
|
227
|
-
if (keepMap[token]) {
|
|
228
|
-
return this.restoreCase(word, token);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Check against the replacement map for a direct word replacement.
|
|
232
|
-
if (replaceMap[token]) {
|
|
233
|
-
return this.restoreCase(word, replaceMap[token]);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Run all the rules against the word.
|
|
237
|
-
return this.sanitizeWord(token, word, rules);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Check if a word is part of the map.
|
|
242
|
-
*/
|
|
243
|
-
private checkWord(word: string, reason: "Singularity" | "Plurality") {
|
|
244
|
-
const replaceMap =
|
|
245
|
-
reason === "Plurality" ? this.irregularSingles : this.irregularPlurals;
|
|
246
|
-
const keepMap =
|
|
247
|
-
reason === "Plurality" ? this.irregularPlurals : this.irregularSingles;
|
|
248
|
-
const rules =
|
|
249
|
-
reason === "Singularity" ? this.pluralRules : this.singularRules;
|
|
250
|
-
|
|
251
|
-
const token = word.toLowerCase();
|
|
252
|
-
|
|
253
|
-
if (keepMap[token]) return true;
|
|
254
|
-
|
|
255
|
-
if (replaceMap[token]) return false;
|
|
256
|
-
|
|
257
|
-
return this.sanitizeWord(token, token, rules) === token;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Pluralize or singularize a word based on the passed in count.
|
|
262
|
-
*/
|
|
263
|
-
pluralize(word: string, count: number, inclusive: boolean) {
|
|
264
|
-
const pluralized = count === 1 ? this.singular(word) : this.plural(word);
|
|
265
|
-
|
|
266
|
-
return (inclusive ? `${count} ` : "") + pluralized;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Pluralize a word.
|
|
271
|
-
*/
|
|
272
|
-
plural(singularWord: string) {
|
|
273
|
-
return this.replaceWord(singularWord, "SingularToPlural");
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Check if a word is plural.
|
|
278
|
-
*/
|
|
279
|
-
isPlural(word: string) {
|
|
280
|
-
this.checkWord(word, "Plurality");
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Singularize a word.
|
|
285
|
-
*/
|
|
286
|
-
singular(pluralWord: string) {
|
|
287
|
-
return this.replaceWord(pluralWord, "PluralToSingular");
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Check if a word is singular.
|
|
292
|
-
*/
|
|
293
|
-
isSingular(word: string) {
|
|
294
|
-
this.checkWord(word, "Singularity");
|
|
295
|
-
}
|
|
296
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
export const IRREGULAR_WORDS: [string, string][] = [
|
|
2
|
-
// Pronouns.
|
|
3
|
-
['I', 'we'],
|
|
4
|
-
['me', 'us'],
|
|
5
|
-
['he', 'they'],
|
|
6
|
-
['she', 'they'],
|
|
7
|
-
['them', 'them'],
|
|
8
|
-
['myself', 'ourselves'],
|
|
9
|
-
['yourself', 'yourselves'],
|
|
10
|
-
['itself', 'themselves'],
|
|
11
|
-
['herself', 'themselves'],
|
|
12
|
-
['himself', 'themselves'],
|
|
13
|
-
['themself', 'themselves'],
|
|
14
|
-
['is', 'are'],
|
|
15
|
-
['was', 'were'],
|
|
16
|
-
['has', 'have'],
|
|
17
|
-
['this', 'these'],
|
|
18
|
-
['that', 'those'],
|
|
19
|
-
['my', 'our'],
|
|
20
|
-
['its', 'their'],
|
|
21
|
-
['his', 'their'],
|
|
22
|
-
['her', 'their'],
|
|
23
|
-
// Words ending in with a consonant and `o`.
|
|
24
|
-
['echo', 'echoes'],
|
|
25
|
-
['dingo', 'dingoes'],
|
|
26
|
-
['volcano', 'volcanoes'],
|
|
27
|
-
['tornado', 'tornadoes'],
|
|
28
|
-
['torpedo', 'torpedoes'],
|
|
29
|
-
// Ends with `us`.
|
|
30
|
-
['genus', 'genera'],
|
|
31
|
-
['viscus', 'viscera'],
|
|
32
|
-
// Ends with `ma`.
|
|
33
|
-
['stigma', 'stigmata'],
|
|
34
|
-
['stoma', 'stomata'],
|
|
35
|
-
['dogma', 'dogmata'],
|
|
36
|
-
['lemma', 'lemmata'],
|
|
37
|
-
['schema', 'schemata'],
|
|
38
|
-
['anathema', 'anathemata'],
|
|
39
|
-
// Other irregular rules.
|
|
40
|
-
['ox', 'oxen'],
|
|
41
|
-
['axe', 'axes'],
|
|
42
|
-
['die', 'dice'],
|
|
43
|
-
['yes', 'yeses'],
|
|
44
|
-
['foot', 'feet'],
|
|
45
|
-
['eave', 'eaves'],
|
|
46
|
-
['goose', 'geese'],
|
|
47
|
-
['tooth', 'teeth'],
|
|
48
|
-
['quiz', 'quizzes'],
|
|
49
|
-
['human', 'humans'],
|
|
50
|
-
['proof', 'proofs'],
|
|
51
|
-
['carve', 'carves'],
|
|
52
|
-
['valve', 'valves'],
|
|
53
|
-
['looey', 'looies'],
|
|
54
|
-
['thief', 'thieves'],
|
|
55
|
-
['groove', 'grooves'],
|
|
56
|
-
['pickaxe', 'pickaxes'],
|
|
57
|
-
['passerby', 'passersby'],
|
|
58
|
-
['canvas', 'canvases'],
|
|
59
|
-
];
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-control-regex */
|
|
2
|
-
|
|
3
|
-
import type { Rule } from "../types";
|
|
4
|
-
|
|
5
|
-
export const PLURALIZATION_RULES: Rule[] = [
|
|
6
|
-
[/s?$/i, "s"],
|
|
7
|
-
[/[^\u0000-\u007F]$/, "$0"],
|
|
8
|
-
[/([^aeiou]ese)$/i, "$1"],
|
|
9
|
-
[/(ax|test)is$/i, "$1es"],
|
|
10
|
-
[/(alias|[^aou]us|t[lm]as|gas|ris)$/i, "$1es"],
|
|
11
|
-
[/(e[mn]u)s?$/i, "$1s"],
|
|
12
|
-
[/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, "$1"],
|
|
13
|
-
[
|
|
14
|
-
/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,
|
|
15
|
-
"$1i",
|
|
16
|
-
],
|
|
17
|
-
[/(alumn|alg|vertebr)(?:a|ae)$/i, "$1ae"],
|
|
18
|
-
[/(seraph|cherub)(?:im)?$/i, "$1im"],
|
|
19
|
-
[/(her|at|gr)o$/i, "$1oes"],
|
|
20
|
-
[
|
|
21
|
-
/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i,
|
|
22
|
-
"$1a",
|
|
23
|
-
],
|
|
24
|
-
[
|
|
25
|
-
/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i,
|
|
26
|
-
"$1a",
|
|
27
|
-
],
|
|
28
|
-
[/sis$/i, "ses"],
|
|
29
|
-
[/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, "$1$2ves"],
|
|
30
|
-
[/([^aeiouy]|qu)y$/i, "$1ies"],
|
|
31
|
-
[/([^ch][ieo][ln])ey$/i, "$1ies"],
|
|
32
|
-
[/(x|ch|ss|sh|zz)$/i, "$1es"],
|
|
33
|
-
[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, "$1ices"],
|
|
34
|
-
[/\b((?:tit)?m|l)(?:ice|ouse)$/i, "$1ice"],
|
|
35
|
-
[/(pe)(?:rson|ople)$/i, "$1ople"],
|
|
36
|
-
[/(child)(?:ren)?$/i, "$1ren"],
|
|
37
|
-
[/eaux$/i, "$0"],
|
|
38
|
-
[/m[ae]n$/i, "men"],
|
|
39
|
-
["thou", "you"],
|
|
40
|
-
];
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { Rule } from "../types";
|
|
2
|
-
|
|
3
|
-
export const SINGULARIZATION_RULES: Rule[] = [
|
|
4
|
-
[/s$/i, ""],
|
|
5
|
-
[/(ss)$/i, "$1"],
|
|
6
|
-
[/(wi|kni|(?:after|half|high|low|mid|non|night|\W|^)li)ves$/i, "$1fe"],
|
|
7
|
-
[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, "$1f"],
|
|
8
|
-
[/ies$/i, "y"],
|
|
9
|
-
[/(dg|ss|ois|lk|ok|wn|mb|th|ch|ec|oal|is|ck|ix|sser|ts|wb)ies$/i, "$1ie"],
|
|
10
|
-
[
|
|
11
|
-
/\b(l|(?:neck|cross|hog|aun)?t|coll|faer|food|gen|goon|group|hipp|junk|vegg|(?:pork)?p|charl|calor|cut)ies$/i,
|
|
12
|
-
"$1ie",
|
|
13
|
-
],
|
|
14
|
-
[/\b(mon|smil)ies$/i, "$1ey"],
|
|
15
|
-
[/\b((?:tit)?m|l)ice$/i, "$1ouse"],
|
|
16
|
-
[/(seraph|cherub)im$/i, "$1"],
|
|
17
|
-
[
|
|
18
|
-
/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,
|
|
19
|
-
"$1",
|
|
20
|
-
],
|
|
21
|
-
[
|
|
22
|
-
/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,
|
|
23
|
-
"$1sis",
|
|
24
|
-
],
|
|
25
|
-
[/(movie|twelve|abuse|e[mn]u)s$/i, "$1"],
|
|
26
|
-
[/(test)(?:is|es)$/i, "$1is"],
|
|
27
|
-
[
|
|
28
|
-
/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,
|
|
29
|
-
"$1us",
|
|
30
|
-
],
|
|
31
|
-
[
|
|
32
|
-
/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,
|
|
33
|
-
"$1um",
|
|
34
|
-
],
|
|
35
|
-
[
|
|
36
|
-
/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,
|
|
37
|
-
"$1on",
|
|
38
|
-
],
|
|
39
|
-
[/(alumn|alg|vertebr)ae$/i, "$1a"],
|
|
40
|
-
[/(cod|mur|sil|vert|ind)ices$/i, "$1ex"],
|
|
41
|
-
[/(matr|append)ices$/i, "$1ix"],
|
|
42
|
-
[/(pe)(rson|ople)$/i, "$1rson"],
|
|
43
|
-
[/(child)ren$/i, "$1"],
|
|
44
|
-
[/(eau)x?$/i, "$1"],
|
|
45
|
-
[/men$/i, "man"],
|
|
46
|
-
];
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import type { RuleKey } from '../types';
|
|
2
|
-
|
|
3
|
-
export const UNCOUNTABLE_WORDS: RuleKey[] = [
|
|
4
|
-
// Singular words with no plurals.
|
|
5
|
-
'adulthood',
|
|
6
|
-
'advice',
|
|
7
|
-
'agenda',
|
|
8
|
-
'aid',
|
|
9
|
-
'aircraft',
|
|
10
|
-
'alcohol',
|
|
11
|
-
'ammo',
|
|
12
|
-
'analytics',
|
|
13
|
-
'anime',
|
|
14
|
-
'athletics',
|
|
15
|
-
'audio',
|
|
16
|
-
'bison',
|
|
17
|
-
'blood',
|
|
18
|
-
'bream',
|
|
19
|
-
'buffalo',
|
|
20
|
-
'butter',
|
|
21
|
-
'carp',
|
|
22
|
-
'cash',
|
|
23
|
-
'chassis',
|
|
24
|
-
'chess',
|
|
25
|
-
'clothing',
|
|
26
|
-
'cod',
|
|
27
|
-
'commerce',
|
|
28
|
-
'cooperation',
|
|
29
|
-
'corps',
|
|
30
|
-
'debris',
|
|
31
|
-
'diabetes',
|
|
32
|
-
'digestion',
|
|
33
|
-
'elk',
|
|
34
|
-
'energy',
|
|
35
|
-
'equipment',
|
|
36
|
-
'excretion',
|
|
37
|
-
'expertise',
|
|
38
|
-
'firmware',
|
|
39
|
-
'flounder',
|
|
40
|
-
'fun',
|
|
41
|
-
'gallows',
|
|
42
|
-
'garbage',
|
|
43
|
-
'graffiti',
|
|
44
|
-
'hardware',
|
|
45
|
-
'headquarters',
|
|
46
|
-
'health',
|
|
47
|
-
'herpes',
|
|
48
|
-
'highjinks',
|
|
49
|
-
'homework',
|
|
50
|
-
'housework',
|
|
51
|
-
'information',
|
|
52
|
-
'jeans',
|
|
53
|
-
'justice',
|
|
54
|
-
'kudos',
|
|
55
|
-
'labour',
|
|
56
|
-
'literature',
|
|
57
|
-
'machinery',
|
|
58
|
-
'mackerel',
|
|
59
|
-
'mail',
|
|
60
|
-
'media',
|
|
61
|
-
'mews',
|
|
62
|
-
'moose',
|
|
63
|
-
'music',
|
|
64
|
-
'mud',
|
|
65
|
-
'manga',
|
|
66
|
-
'news',
|
|
67
|
-
'only',
|
|
68
|
-
'personnel',
|
|
69
|
-
'pike',
|
|
70
|
-
'plankton',
|
|
71
|
-
'pliers',
|
|
72
|
-
'police',
|
|
73
|
-
'pollution',
|
|
74
|
-
'premises',
|
|
75
|
-
'rain',
|
|
76
|
-
'research',
|
|
77
|
-
'rice',
|
|
78
|
-
'salmon',
|
|
79
|
-
'scissors',
|
|
80
|
-
'series',
|
|
81
|
-
'sewage',
|
|
82
|
-
'shambles',
|
|
83
|
-
'shrimp',
|
|
84
|
-
'software',
|
|
85
|
-
'staff',
|
|
86
|
-
'swine',
|
|
87
|
-
'tennis',
|
|
88
|
-
'traffic',
|
|
89
|
-
'transportation',
|
|
90
|
-
'trout',
|
|
91
|
-
'tuna',
|
|
92
|
-
'wealth',
|
|
93
|
-
'welfare',
|
|
94
|
-
'whiting',
|
|
95
|
-
'wildebeest',
|
|
96
|
-
'wildlife',
|
|
97
|
-
'you',
|
|
98
|
-
/pok[eé]mon$/i,
|
|
99
|
-
// Regexes.
|
|
100
|
-
/[^aeiou]ese$/i, // "chinese", "japanese"
|
|
101
|
-
/deer$/i, // "deer", "reindeer"
|
|
102
|
-
/fish$/i, // "fish", "blowfish", "angelfish"
|
|
103
|
-
/measles$/i,
|
|
104
|
-
/o[iu]s$/i, // "carnivorous"
|
|
105
|
-
/pox$/i, // "chickpox", "smallpox"
|
|
106
|
-
/sheep$/i,
|
|
107
|
-
];
|
package/src/string/to-int.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts a string (or a number) into a number.
|
|
3
|
-
* If the input can not be successfully converted, it will return the fallback.
|
|
4
|
-
* It will not return NaN.
|
|
5
|
-
* @param value - The value to convert
|
|
6
|
-
* @param fallback - The value to fallback to. Defaults to 0
|
|
7
|
-
* @returns number
|
|
8
|
-
*/
|
|
9
|
-
export function stringToInt(
|
|
10
|
-
value: string | number,
|
|
11
|
-
fallback: number = 0,
|
|
12
|
-
): number {
|
|
13
|
-
let returnValue = value;
|
|
14
|
-
if (typeof returnValue === "string")
|
|
15
|
-
returnValue = Number.parseInt(returnValue);
|
|
16
|
-
|
|
17
|
-
if (Number.isNaN(returnValue)) returnValue = fallback;
|
|
18
|
-
|
|
19
|
-
return returnValue;
|
|
20
|
-
}
|
package/src/string/trim.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export function trim(text: string, chars: string | string[] = " ") {
|
|
2
|
-
let start = 0;
|
|
3
|
-
let end = text.length;
|
|
4
|
-
|
|
5
|
-
if (!Array.isArray(chars)) chars = [chars];
|
|
6
|
-
|
|
7
|
-
while (start < end && chars.includes(text[start])) start += 1;
|
|
8
|
-
while (end > start && chars.includes(text[end - 1])) end -= 1;
|
|
9
|
-
|
|
10
|
-
return start > 0 || end < text.length ? text.substring(start, end) : text;
|
|
11
|
-
}
|
package/src/string/truncate.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
export interface TruncateOptions {
|
|
2
|
-
/**
|
|
3
|
-
* The maximum number of character allowed in the text before truncating it
|
|
4
|
-
*
|
|
5
|
-
* @default 100
|
|
6
|
-
*/
|
|
7
|
-
maxlength?: number;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The string to use at the end of the truncated text
|
|
11
|
-
*
|
|
12
|
-
* @default "..."
|
|
13
|
-
*/
|
|
14
|
-
ending?: string;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* If true, truncates the text at the next space char,
|
|
18
|
-
* so the returned string can exceed the specified `maxLength`
|
|
19
|
-
*
|
|
20
|
-
* @default false
|
|
21
|
-
*/
|
|
22
|
-
noWordBreak?: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const defaultOptions: Required<TruncateOptions> = {
|
|
26
|
-
ending: "...",
|
|
27
|
-
maxlength: 100,
|
|
28
|
-
noWordBreak: false,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export function truncate(text: string, options?: TruncateOptions) {
|
|
32
|
-
const conf = { ...defaultOptions, ...options };
|
|
33
|
-
text = text.trim();
|
|
34
|
-
if (conf.noWordBreak) {
|
|
35
|
-
const lastSpaceIndex = text.indexOf(" ", conf.maxlength);
|
|
36
|
-
|
|
37
|
-
if (lastSpaceIndex >= conf.maxlength)
|
|
38
|
-
return text.substring(0, lastSpaceIndex) + conf.ending;
|
|
39
|
-
} else if (text.length > conf.maxlength + conf.ending.length) {
|
|
40
|
-
return text.substring(0, conf.maxlength) + conf.ending;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return text;
|
|
44
|
-
}
|
package/src/value/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./is-empty";
|
package/src/value/is-empty.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checks if the value is `empty`
|
|
3
|
-
*
|
|
4
|
-
* returns `true`, if the value
|
|
5
|
-
*
|
|
6
|
-
* - `undefined`
|
|
7
|
-
* - `null`
|
|
8
|
-
* - `string` and there is no character in the string or all white space
|
|
9
|
-
* - `array` and there is no item in the array
|
|
10
|
-
* - `map` and there is no item in the map
|
|
11
|
-
* - `set` and there is no item in the set
|
|
12
|
-
* - `object` and there is no property in the object
|
|
13
|
-
*
|
|
14
|
-
* otherwise, false
|
|
15
|
-
*
|
|
16
|
-
*/
|
|
17
|
-
export const isEmpty = (value: unknown) => {
|
|
18
|
-
if (value === undefined) return true;
|
|
19
|
-
if (value === null) return true;
|
|
20
|
-
|
|
21
|
-
if (typeof value === "string") return value.trim() === "";
|
|
22
|
-
if (typeof value === "object") {
|
|
23
|
-
if (Array.isArray(value) && value.length === 0) return true;
|
|
24
|
-
|
|
25
|
-
if (value instanceof Map || value instanceof Set) return value.size === 0;
|
|
26
|
-
|
|
27
|
-
return Object.keys(value).length === 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return false;
|
|
31
|
-
};
|