namefully 2.0.2 → 2.2.0
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/cjs/builder.js +6 -3
- package/dist/cjs/config.js +10 -5
- package/dist/cjs/constants.js +4 -26
- package/dist/cjs/data.js +42 -0
- package/dist/cjs/fullname.js +75 -8
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/name.js +1 -1
- package/dist/cjs/namefully.js +80 -22
- package/dist/cjs/parser.js +30 -14
- package/dist/cjs/types.js +18 -1
- package/dist/esm/builder.d.ts +2 -2
- package/dist/esm/builder.js +6 -3
- package/dist/esm/config.d.ts +4 -10
- package/dist/esm/config.js +10 -5
- package/dist/esm/constants.d.ts +3 -2
- package/dist/esm/constants.js +3 -25
- package/dist/esm/data.d.ts +31 -0
- package/dist/esm/data.js +38 -0
- package/dist/esm/fullname.d.ts +38 -1
- package/dist/esm/fullname.js +73 -7
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/name.d.ts +13 -7
- package/dist/esm/name.js +1 -1
- package/dist/esm/namefully.d.ts +64 -26
- package/dist/esm/namefully.js +80 -22
- package/dist/esm/parser.d.ts +9 -6
- package/dist/esm/parser.js +30 -15
- package/dist/esm/types.d.ts +3 -0
- package/dist/esm/types.js +18 -1
- package/dist/namefully.js +251 -74
- package/dist/namefully.min.js +1 -1
- package/package.json +2 -2
- package/readme.md +28 -4
package/dist/esm/namefully.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Config } from './config.js';
|
|
2
|
+
import { SerializedName } from './data.js';
|
|
2
3
|
import { Name, JsonName } from './name.js';
|
|
3
|
-
import { Flat, NameOrder, NameType, Namon, Nullable, Surname } from './types.js';
|
|
4
4
|
import { NameIndex } from './utils.js';
|
|
5
|
+
import { Flat, NameOrder, NameType, Namon, Nullable, Surname, Separator, Title } from './types.js';
|
|
5
6
|
import { Parser } from './parser.js';
|
|
6
7
|
/**
|
|
7
8
|
* A utility for organizing human names in a particular order, way, or shape.
|
|
@@ -31,8 +32,8 @@ import { Parser } from './parser.js';
|
|
|
31
32
|
* this: `John Smith`, where `John` is the first name piece and `Smith`, the last
|
|
32
33
|
* name piece.
|
|
33
34
|
*
|
|
34
|
-
* @see {@link https://www.fbiic.gov/public/2008/nov/Naming_practice_guide_UK_2006.pdf}
|
|
35
|
-
*
|
|
35
|
+
* @see {@link https://www.fbiic.gov/public/2008/nov/Naming_practice_guide_UK_2006.pdf} for
|
|
36
|
+
* more info on name standards.
|
|
36
37
|
*
|
|
37
38
|
* **IMPORTANT**: Keep in mind that the order of appearance (or name order) matters
|
|
38
39
|
* and may be altered through configurable parameters, which will be seen later.
|
|
@@ -59,7 +60,7 @@ export declare class Namefully {
|
|
|
59
60
|
* name during its existence. All name parts must have at least one (1) character
|
|
60
61
|
* to proceed. That is the only requirement/validation of namefully.
|
|
61
62
|
*/
|
|
62
|
-
constructor(names: string | string[] | Name[] | JsonName | Parser, options?:
|
|
63
|
+
constructor(names: string | string[] | Name[] | JsonName | Parser, options?: NameOptions);
|
|
63
64
|
/**
|
|
64
65
|
* Constructs a `Namefully` instance from a text.
|
|
65
66
|
*
|
|
@@ -85,6 +86,8 @@ export declare class Namefully {
|
|
|
85
86
|
static parse(text: string, index?: NameIndex): Promise<Namefully>;
|
|
86
87
|
/** The configuration dictating this name's behavior. */
|
|
87
88
|
get config(): Config;
|
|
89
|
+
/** Whether the name is a single word name. */
|
|
90
|
+
get isMono(): boolean;
|
|
88
91
|
/** The number of characters of the `birthName`, including spaces. */
|
|
89
92
|
get length(): number;
|
|
90
93
|
/** The prefix part of the name set. */
|
|
@@ -111,17 +114,40 @@ export declare class Namefully {
|
|
|
111
114
|
get public(): string;
|
|
112
115
|
/** The combination of prefix and last name. */
|
|
113
116
|
get salutation(): string;
|
|
114
|
-
/**
|
|
117
|
+
/**
|
|
118
|
+
* Returns an iterable of the name components in their natural form.
|
|
119
|
+
*
|
|
120
|
+
* Regardless of the order of appearance, this method will always return the
|
|
121
|
+
* existing `Name`s according to the name standards upon which this library
|
|
122
|
+
* is based.
|
|
123
|
+
*
|
|
124
|
+
* This is useful for iterating over the name parts in a consistent manner and
|
|
125
|
+
* this automatically enables operations such as mapping, filtering, etc.
|
|
126
|
+
*/
|
|
127
|
+
get parts(): Iterable<Name>;
|
|
128
|
+
/** The number of name components. */
|
|
129
|
+
get size(): number;
|
|
130
|
+
/**
|
|
131
|
+
* Makes the name set iterable (i.e., for-of statements).
|
|
132
|
+
*
|
|
133
|
+
* This is similar to `parts` with the exception that all name components are
|
|
134
|
+
* returned as `Name` classes (instead of their natural form - e.g., `FirstName`)
|
|
135
|
+
* to maintain certain homogeneity and consistency across each name piece.
|
|
136
|
+
*/
|
|
137
|
+
[Symbol.iterator](): Iterator<Name>;
|
|
138
|
+
/** Gets a string representation of the full name. */
|
|
115
139
|
toString(): string;
|
|
116
140
|
/** Fetches the raw form of a name piece. */
|
|
117
|
-
get(
|
|
141
|
+
get(key: Namon | string): Nullable<Name | Name[]>;
|
|
118
142
|
/** Whether this name is equal to another one from a raw-string perspective. */
|
|
119
143
|
equal(other: Namefully): boolean;
|
|
144
|
+
/** Whether this name is equal to another one from a component perspective. */
|
|
145
|
+
deepEqual(other: Namefully): boolean;
|
|
120
146
|
/** Gets a JSON representation of the full name. */
|
|
121
147
|
toJson(): JsonName;
|
|
122
148
|
json: () => JsonName;
|
|
123
|
-
/** Confirms
|
|
124
|
-
has(namon: Namon): boolean;
|
|
149
|
+
/** Confirms whether a name component exists. */
|
|
150
|
+
has(namon: Namon | string): boolean;
|
|
125
151
|
/**
|
|
126
152
|
* Gets the full name ordered as configured.
|
|
127
153
|
*
|
|
@@ -129,21 +155,21 @@ export declare class Namefully {
|
|
|
129
155
|
* name, overriding the preset configuration.
|
|
130
156
|
*
|
|
131
157
|
* `Namefully.format()` may also be used to alter manually the order of appearance
|
|
132
|
-
* of full name. For example:
|
|
158
|
+
* of a full name. For example:
|
|
133
159
|
* ```ts
|
|
134
160
|
* const name = new Namefully('Jon Stark Snow');
|
|
135
161
|
* console.log(name.fullName(NameOrder.LAST_NAME)); // "Snow Jon Stark"
|
|
136
162
|
* console.log(name.format('l f m')); // "Snow Jon Stark"
|
|
137
163
|
* ```
|
|
138
164
|
*/
|
|
139
|
-
fullName(orderedBy?:
|
|
165
|
+
fullName(orderedBy?: NameOptions['orderedBy']): string;
|
|
140
166
|
/**
|
|
141
167
|
* Gets the birth name ordered as configured, no `prefix` or `suffix`.
|
|
142
168
|
*
|
|
143
169
|
* @param orderedBy forces to order by first or last name by overriding the
|
|
144
170
|
* preset configuration.
|
|
145
171
|
*/
|
|
146
|
-
birthName(orderedBy?:
|
|
172
|
+
birthName(orderedBy?: NameOptions['orderedBy']): string;
|
|
147
173
|
/**
|
|
148
174
|
* Gets the first name part of the `FullName`.
|
|
149
175
|
* @param {boolean} withMore determines whether to include other pieces of the
|
|
@@ -157,7 +183,7 @@ export declare class Namefully {
|
|
|
157
183
|
* @param {Surname} format overrides the how-to formatting of a surname output,
|
|
158
184
|
* considering its sub-parts.
|
|
159
185
|
*/
|
|
160
|
-
lastName(format?:
|
|
186
|
+
lastName(format?: NameOptions['surname']): string;
|
|
161
187
|
/**
|
|
162
188
|
* Gets the initials of the `FullName`.
|
|
163
189
|
*
|
|
@@ -172,8 +198,8 @@ export declare class Namefully {
|
|
|
172
198
|
* - `John Ben Smith` => `['J', 'B', 'S']`.
|
|
173
199
|
*/
|
|
174
200
|
initials(options?: {
|
|
175
|
-
orderedBy?:
|
|
176
|
-
only?: NameType;
|
|
201
|
+
orderedBy?: NameOptions['orderedBy'];
|
|
202
|
+
only?: NameType | 'firstName' | 'lastName' | 'middleName' | 'birthName';
|
|
177
203
|
asJson?: boolean;
|
|
178
204
|
}): string[] | Record<string, string[]>;
|
|
179
205
|
/**
|
|
@@ -193,7 +219,7 @@ export declare class Namefully {
|
|
|
193
219
|
* For a given `FirstName FatherName MotherName`, shortening this name when
|
|
194
220
|
* the surname is set as `mother` is equivalent to making it: `FirstName MotherName`.
|
|
195
221
|
*/
|
|
196
|
-
shorten(orderedBy?:
|
|
222
|
+
shorten(orderedBy?: NameOptions['orderedBy']): string;
|
|
197
223
|
/**
|
|
198
224
|
* Flattens long names using the name types as variants.
|
|
199
225
|
*
|
|
@@ -225,11 +251,11 @@ export declare class Namefully {
|
|
|
225
251
|
*/
|
|
226
252
|
flatten(options: Partial<{
|
|
227
253
|
limit: number;
|
|
228
|
-
by: Flat;
|
|
254
|
+
by: Flat | 'firstName' | 'lastName' | 'middleName' | 'birthName' | 'firstMid' | 'midLast' | 'all' | '*';
|
|
229
255
|
withPeriod: boolean;
|
|
230
256
|
recursive: boolean;
|
|
231
257
|
withMore: boolean;
|
|
232
|
-
surname:
|
|
258
|
+
surname: NameOptions['surname'];
|
|
233
259
|
}>): string;
|
|
234
260
|
/**
|
|
235
261
|
* Zips or compacts a name using different forms of variants.
|
|
@@ -263,14 +289,6 @@ export declare class Namefully {
|
|
|
263
289
|
* - 'P': capitalized prefix
|
|
264
290
|
* - 's': suffix
|
|
265
291
|
* - 'S': capitalized suffix
|
|
266
|
-
*
|
|
267
|
-
* punctuations
|
|
268
|
-
* ------------
|
|
269
|
-
* - '.': period
|
|
270
|
-
* - ',': comma
|
|
271
|
-
* - ' ': space
|
|
272
|
-
* - '-': hyphen
|
|
273
|
-
* - '_': underscore
|
|
274
292
|
* - '$': an escape character to select only the initial of the next char.
|
|
275
293
|
*
|
|
276
294
|
* Given the name `Joe Jim Smith`, use `format` with the `pattern` string.
|
|
@@ -312,11 +330,31 @@ export declare class Namefully {
|
|
|
312
330
|
toDotCase(): string;
|
|
313
331
|
/** Transforms a birth name into ToGgLeCaSe. */
|
|
314
332
|
toToggleCase(): string;
|
|
333
|
+
/**
|
|
334
|
+
* Serializes this Namefully instance to a JSON object.
|
|
335
|
+
*
|
|
336
|
+
* This includes both the name data (with full hierarchy for FirstName and LastName)
|
|
337
|
+
* and the configuration, allowing for complete reconstruction of the Namefully instance.
|
|
338
|
+
*
|
|
339
|
+
* @returns a JSON-serializable object containing name data and config.
|
|
340
|
+
*/
|
|
341
|
+
serialize(): SerializedName;
|
|
315
342
|
}
|
|
316
343
|
/**
|
|
317
344
|
* A default export for the `namefully` utility.
|
|
318
345
|
* @param names element to parse.
|
|
319
346
|
* @param options additional settings.
|
|
320
347
|
*/
|
|
321
|
-
declare const _default: (names: string | string[] | Name[] | JsonName | Parser, options?:
|
|
348
|
+
declare const _default: (names: string | string[] | Name[] | JsonName | Parser, options?: NameOptions) => Namefully;
|
|
322
349
|
export default _default;
|
|
350
|
+
/** Optional namefully parameters (@see {@linkcode Config} for more details). */
|
|
351
|
+
export type NameOptions = Partial<{
|
|
352
|
+
name: string;
|
|
353
|
+
orderedBy: NameOrder | 'firstName' | 'lastName';
|
|
354
|
+
separator: Separator;
|
|
355
|
+
title: Title | 'UK' | 'US';
|
|
356
|
+
ending: boolean;
|
|
357
|
+
bypass: boolean;
|
|
358
|
+
surname: Surname | 'father' | 'mother' | 'hyphenated' | 'all';
|
|
359
|
+
mono: boolean | Namon;
|
|
360
|
+
}>;
|
package/dist/esm/namefully.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ALLOWED_FORMAT_TOKENS } from './constants.js';
|
|
2
|
-
import { InputError, NotAllowedError } from './error.js';
|
|
3
2
|
import { isNameArray } from './name.js';
|
|
4
|
-
import {
|
|
3
|
+
import { InputError, NotAllowedError } from './error.js';
|
|
5
4
|
import { capitalize, decapitalize, isStringArray, toggleCase } from './utils.js';
|
|
5
|
+
import { Flat, NameOrder, NameType, Namon } from './types.js';
|
|
6
6
|
import { ArrayNameParser, ArrayStringParser, NamaParser, Parser, StringParser } from './parser.js';
|
|
7
7
|
export class Namefully {
|
|
8
8
|
#fullName;
|
|
@@ -23,7 +23,12 @@ export class Namefully {
|
|
|
23
23
|
get config() {
|
|
24
24
|
return this.#fullName.config;
|
|
25
25
|
}
|
|
26
|
+
get isMono() {
|
|
27
|
+
return this.#fullName.isMono;
|
|
28
|
+
}
|
|
26
29
|
get length() {
|
|
30
|
+
if (this.isMono)
|
|
31
|
+
return this.#fullName.toString().length;
|
|
27
32
|
return this.birth.length;
|
|
28
33
|
}
|
|
29
34
|
get prefix() {
|
|
@@ -62,25 +67,43 @@ export class Namefully {
|
|
|
62
67
|
get salutation() {
|
|
63
68
|
return this.format('p l');
|
|
64
69
|
}
|
|
70
|
+
get parts() {
|
|
71
|
+
return this.#fullName.toIterable();
|
|
72
|
+
}
|
|
73
|
+
get size() {
|
|
74
|
+
return Array.from(this.parts).length;
|
|
75
|
+
}
|
|
76
|
+
*[Symbol.iterator]() {
|
|
77
|
+
yield* this.#fullName.toIterable(true);
|
|
78
|
+
}
|
|
65
79
|
toString() {
|
|
66
80
|
return this.full;
|
|
67
81
|
}
|
|
68
|
-
get(
|
|
69
|
-
|
|
82
|
+
get(key) {
|
|
83
|
+
const namon = typeof key === 'string' ? Namon.cast(key) : key;
|
|
84
|
+
if (namon?.equal(Namon.PREFIX))
|
|
70
85
|
return this.#fullName.prefix;
|
|
71
|
-
if (namon
|
|
86
|
+
if (namon?.equal(Namon.FIRST_NAME))
|
|
72
87
|
return this.#fullName.firstName;
|
|
73
|
-
if (namon
|
|
88
|
+
if (namon?.equal(Namon.MIDDLE_NAME))
|
|
74
89
|
return this.#fullName.middleName;
|
|
75
|
-
if (namon
|
|
90
|
+
if (namon?.equal(Namon.LAST_NAME))
|
|
76
91
|
return this.#fullName.lastName;
|
|
77
|
-
if (namon
|
|
92
|
+
if (namon?.equal(Namon.SUFFIX))
|
|
78
93
|
return this.#fullName.suffix;
|
|
79
94
|
return undefined;
|
|
80
95
|
}
|
|
81
96
|
equal(other) {
|
|
82
97
|
return this.toString() === other.toString();
|
|
83
98
|
}
|
|
99
|
+
deepEqual(other) {
|
|
100
|
+
const others = Array.from(other.parts);
|
|
101
|
+
for (const part of this.parts) {
|
|
102
|
+
if (!others.some((name) => name.equal(part)))
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
84
107
|
toJson() {
|
|
85
108
|
return {
|
|
86
109
|
prefix: this.prefix,
|
|
@@ -95,6 +118,8 @@ export class Namefully {
|
|
|
95
118
|
return this.#fullName.has(namon);
|
|
96
119
|
}
|
|
97
120
|
fullName(orderedBy) {
|
|
121
|
+
if (this.isMono)
|
|
122
|
+
return this.#fullName.toString();
|
|
98
123
|
const sep = this.config.ending ? ',' : '';
|
|
99
124
|
const names = [];
|
|
100
125
|
if (this.prefix)
|
|
@@ -103,13 +128,21 @@ export class Namefully {
|
|
|
103
128
|
names.push(this.first, ...this.middleName(), this.last + sep);
|
|
104
129
|
}
|
|
105
130
|
else {
|
|
106
|
-
names.push(this.last
|
|
131
|
+
names.push(this.last);
|
|
132
|
+
if (this.hasMiddle) {
|
|
133
|
+
names.push(this.first, this.middleName().join(' ') + sep);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
names.push(this.first + sep);
|
|
137
|
+
}
|
|
107
138
|
}
|
|
108
139
|
if (this.suffix)
|
|
109
140
|
names.push(this.suffix);
|
|
110
141
|
return names.join(' ').trim();
|
|
111
142
|
}
|
|
112
143
|
birthName(orderedBy) {
|
|
144
|
+
if (this.isMono)
|
|
145
|
+
return this.#fullName.toString();
|
|
113
146
|
orderedBy ??= this.config.orderedBy;
|
|
114
147
|
return orderedBy === NameOrder.FIRST_NAME
|
|
115
148
|
? [this.first, ...this.middleName(), this.last].join(' ')
|
|
@@ -125,6 +158,8 @@ export class Namefully {
|
|
|
125
158
|
return this.#fullName.lastName.toString(format);
|
|
126
159
|
}
|
|
127
160
|
initials(options) {
|
|
161
|
+
if (this.isMono)
|
|
162
|
+
return [this.#fullName.toString()[0]];
|
|
128
163
|
const { orderedBy = this.config.orderedBy, only = NameType.BIRTH_NAME, asJson } = options ?? {};
|
|
129
164
|
const firstInits = this.#fullName.firstName.initials();
|
|
130
165
|
const midInits = this.#fullName.middleName.map((n) => n.value[0]);
|
|
@@ -142,6 +177,8 @@ export class Namefully {
|
|
|
142
177
|
}
|
|
143
178
|
}
|
|
144
179
|
shorten(orderedBy) {
|
|
180
|
+
if (this.isMono)
|
|
181
|
+
return this.#fullName.toString();
|
|
145
182
|
orderedBy ??= this.config.orderedBy;
|
|
146
183
|
const { firstName, lastName } = this.#fullName;
|
|
147
184
|
return orderedBy === NameOrder.FIRST_NAME
|
|
@@ -152,6 +189,8 @@ export class Namefully {
|
|
|
152
189
|
const { by = Flat.MIDDLE_NAME, limit = 20, recursive = false, withMore = false, withPeriod = true, surname, } = options;
|
|
153
190
|
if (this.length <= limit)
|
|
154
191
|
return this.full;
|
|
192
|
+
if (this.isMono)
|
|
193
|
+
return `${this.initials()}${withPeriod ? '.' : ''}`;
|
|
155
194
|
const { firstName, lastName, middleName } = this.#fullName;
|
|
156
195
|
const sep = withPeriod ? '.' : '';
|
|
157
196
|
const hasMid = this.hasMiddle;
|
|
@@ -179,7 +218,7 @@ export class Namefully {
|
|
|
179
218
|
case Flat.MID_LAST:
|
|
180
219
|
name = hasMid ? [fn, m, l] : [fn, l];
|
|
181
220
|
break;
|
|
182
|
-
|
|
221
|
+
default:
|
|
183
222
|
name = hasMid ? [f, m, l] : [f, l];
|
|
184
223
|
break;
|
|
185
224
|
}
|
|
@@ -201,7 +240,7 @@ export class Namefully {
|
|
|
201
240
|
case Flat.MID_LAST:
|
|
202
241
|
name = hasMid ? [l, fn, m] : [l, fn];
|
|
203
242
|
break;
|
|
204
|
-
|
|
243
|
+
default:
|
|
205
244
|
name = hasMid ? [l, f, m] : [l, f];
|
|
206
245
|
break;
|
|
207
246
|
}
|
|
@@ -242,7 +281,7 @@ export class Namefully {
|
|
|
242
281
|
let group = '';
|
|
243
282
|
const formatted = [];
|
|
244
283
|
for (const char of pattern) {
|
|
245
|
-
if (ALLOWED_FORMAT_TOKENS.
|
|
284
|
+
if (!ALLOWED_FORMAT_TOKENS.includes(char)) {
|
|
246
285
|
throw new NotAllowedError({
|
|
247
286
|
source: this.full,
|
|
248
287
|
operation: 'format',
|
|
@@ -299,6 +338,28 @@ export class Namefully {
|
|
|
299
338
|
toToggleCase() {
|
|
300
339
|
return toggleCase(this.birth);
|
|
301
340
|
}
|
|
341
|
+
serialize() {
|
|
342
|
+
const { config, firstName: fn, lastName: ln } = this.#fullName;
|
|
343
|
+
return {
|
|
344
|
+
names: {
|
|
345
|
+
prefix: this.prefix,
|
|
346
|
+
firstName: fn.hasMore ? { value: fn.value, more: fn.more } : fn.value,
|
|
347
|
+
middleName: this.hasMiddle ? this.middleName() : undefined,
|
|
348
|
+
lastName: ln.hasMother ? { father: ln.father, mother: ln.mother } : ln.value,
|
|
349
|
+
suffix: this.suffix,
|
|
350
|
+
},
|
|
351
|
+
config: {
|
|
352
|
+
name: config.name,
|
|
353
|
+
orderedBy: config.orderedBy,
|
|
354
|
+
separator: config.separator.token,
|
|
355
|
+
title: config.title,
|
|
356
|
+
ending: config.ending,
|
|
357
|
+
bypass: config.bypass,
|
|
358
|
+
surname: config.surname,
|
|
359
|
+
mono: config.mono instanceof Namon ? config.mono.key : config.mono,
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
}
|
|
302
363
|
#toParser(raw) {
|
|
303
364
|
if (raw instanceof Parser)
|
|
304
365
|
return raw;
|
|
@@ -314,12 +375,6 @@ export class Namefully {
|
|
|
314
375
|
}
|
|
315
376
|
#map(char) {
|
|
316
377
|
switch (char) {
|
|
317
|
-
case '.':
|
|
318
|
-
case ',':
|
|
319
|
-
case ' ':
|
|
320
|
-
case '-':
|
|
321
|
-
case '_':
|
|
322
|
-
return char;
|
|
323
378
|
case 'b':
|
|
324
379
|
return this.birth;
|
|
325
380
|
case 'B':
|
|
@@ -361,16 +416,19 @@ export class Namefully {
|
|
|
361
416
|
case 'S':
|
|
362
417
|
return this.suffix?.toUpperCase();
|
|
363
418
|
case '$f':
|
|
364
|
-
case '$F':
|
|
365
419
|
return this.#fullName.firstName.value[0];
|
|
420
|
+
case '$F':
|
|
421
|
+
return this.#fullName.firstName.initials(true).join('');
|
|
366
422
|
case '$l':
|
|
367
|
-
case '$L':
|
|
368
423
|
return this.#fullName.lastName.value[0];
|
|
424
|
+
case '$L':
|
|
425
|
+
return this.#fullName.lastName.initials().join('');
|
|
369
426
|
case '$m':
|
|
370
|
-
case '$M':
|
|
371
427
|
return this.hasMiddle ? this.middle[0] : undefined;
|
|
428
|
+
case '$M':
|
|
429
|
+
return this.hasMiddle ? this.#fullName.middleName.map((n) => n.value[0]).join('') : undefined;
|
|
372
430
|
default:
|
|
373
|
-
return undefined;
|
|
431
|
+
return ALLOWED_FORMAT_TOKENS.includes(char) ? char : undefined;
|
|
374
432
|
}
|
|
375
433
|
}
|
|
376
434
|
}
|
package/dist/esm/parser.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Config } from './config.js';
|
|
2
2
|
import { NameIndex } from './utils.js';
|
|
3
|
-
import { FullName } from './fullname.js';
|
|
3
|
+
import { FullName, Mononym } from './fullname.js';
|
|
4
4
|
import { Name, JsonName } from './name.js';
|
|
5
5
|
/**
|
|
6
6
|
* A parser signature that helps to organize the names accordingly.
|
|
@@ -12,6 +12,11 @@ export declare abstract class Parser<T = unknown> {
|
|
|
12
12
|
* @param raw data to be parsed
|
|
13
13
|
*/
|
|
14
14
|
constructor(raw: T);
|
|
15
|
+
/**
|
|
16
|
+
* Parses raw data into a `FullName` while applying some options.
|
|
17
|
+
* @param options for additional configuration to apply.
|
|
18
|
+
*/
|
|
19
|
+
abstract parse(options?: Partial<Config>): FullName;
|
|
15
20
|
/**
|
|
16
21
|
* Builds a dynamic `Parser` on the fly and throws a `NameError` when unable
|
|
17
22
|
* to do so. The built parser only knows how to operate birth names.
|
|
@@ -19,11 +24,6 @@ export declare abstract class Parser<T = unknown> {
|
|
|
19
24
|
static build(text: string, index?: NameIndex): Parser;
|
|
20
25
|
/** Builds asynchronously a dynamic `Parser`. */
|
|
21
26
|
static buildAsync(text: string, index?: NameIndex): Promise<Parser>;
|
|
22
|
-
/**
|
|
23
|
-
* Parses the raw data into a `FullName` while considering some options.
|
|
24
|
-
* @param options for additional configuration to apply.
|
|
25
|
-
*/
|
|
26
|
-
abstract parse(options?: Partial<Config>): FullName;
|
|
27
27
|
}
|
|
28
28
|
export declare class StringParser extends Parser<string> {
|
|
29
29
|
parse(options: Partial<Config>): FullName;
|
|
@@ -37,3 +37,6 @@ export declare class NamaParser extends Parser<JsonName> {
|
|
|
37
37
|
export declare class ArrayNameParser extends Parser<Name[]> {
|
|
38
38
|
parse(options: Partial<Config>): FullName;
|
|
39
39
|
}
|
|
40
|
+
export declare class MonoParser extends Parser<string | Name> {
|
|
41
|
+
parse(options: Partial<Config>): Mononym;
|
|
42
|
+
}
|
package/dist/esm/parser.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Config } from './config.js';
|
|
2
2
|
import { NameIndex } from './utils.js';
|
|
3
3
|
import { InputError } from './error.js';
|
|
4
|
-
import { FullName } from './fullname.js';
|
|
4
|
+
import { FullName, Mononym } from './fullname.js';
|
|
5
5
|
import { Namon, Separator } from './types.js';
|
|
6
6
|
import { FirstName, LastName, Name } from './name.js';
|
|
7
|
-
import { ArrayStringValidator, ArrayNameValidator,
|
|
7
|
+
import { ArrayStringValidator, ArrayNameValidator, Validators } from './validator.js';
|
|
8
8
|
export class Parser {
|
|
9
9
|
raw;
|
|
10
10
|
constructor(raw) {
|
|
@@ -20,10 +20,7 @@ export class Parser {
|
|
|
20
20
|
return new ArrayNameParser(names);
|
|
21
21
|
}
|
|
22
22
|
if (length < 2) {
|
|
23
|
-
throw new InputError({
|
|
24
|
-
source: text,
|
|
25
|
-
message: 'cannot build from invalid input',
|
|
26
|
-
});
|
|
23
|
+
throw new InputError({ source: text, message: 'expecting at least 2 name parts' });
|
|
27
24
|
}
|
|
28
25
|
else if (length === 2 || length === 3) {
|
|
29
26
|
return new StringParser(text);
|
|
@@ -47,13 +44,15 @@ export class StringParser extends Parser {
|
|
|
47
44
|
parse(options) {
|
|
48
45
|
const config = Config.merge(options);
|
|
49
46
|
const names = this.raw.split(config.separator.token);
|
|
50
|
-
return new ArrayStringParser(names).parse(
|
|
47
|
+
return new ArrayStringParser(names).parse(config);
|
|
51
48
|
}
|
|
52
49
|
}
|
|
53
50
|
export class ArrayStringParser extends Parser {
|
|
54
51
|
parse(options) {
|
|
55
52
|
const config = Config.merge(options);
|
|
56
|
-
|
|
53
|
+
if (this.raw.length === 1 && config.mono) {
|
|
54
|
+
return new MonoParser(this.raw[0]).parse(config);
|
|
55
|
+
}
|
|
57
56
|
const raw = this.raw.map((n) => n.trim());
|
|
58
57
|
const index = NameIndex.when(config.orderedBy, raw.length);
|
|
59
58
|
const validator = new ArrayStringValidator(index);
|
|
@@ -64,8 +63,9 @@ export class ArrayStringParser extends Parser {
|
|
|
64
63
|
validator.validate(raw);
|
|
65
64
|
}
|
|
66
65
|
const { firstName, lastName, middleName, prefix, suffix } = index;
|
|
67
|
-
fullName
|
|
68
|
-
|
|
66
|
+
const fullName = new FullName(config)
|
|
67
|
+
.setFirstName(new FirstName(raw[firstName]))
|
|
68
|
+
.setLastName(new LastName(raw[lastName]));
|
|
69
69
|
if (raw.length >= 3)
|
|
70
70
|
fullName.setMiddleName(raw[middleName].split(config.separator.token));
|
|
71
71
|
if (raw.length >= 4)
|
|
@@ -89,10 +89,10 @@ export class NamaParser extends Parser {
|
|
|
89
89
|
return [namon, value];
|
|
90
90
|
}));
|
|
91
91
|
if (config.bypass) {
|
|
92
|
-
|
|
92
|
+
Validators.nama.validateKeys(names);
|
|
93
93
|
}
|
|
94
94
|
else {
|
|
95
|
-
|
|
95
|
+
Validators.nama.validate(names);
|
|
96
96
|
}
|
|
97
97
|
return FullName.parse(this.raw, config);
|
|
98
98
|
}
|
|
@@ -100,8 +100,13 @@ export class NamaParser extends Parser {
|
|
|
100
100
|
export class ArrayNameParser extends Parser {
|
|
101
101
|
parse(options) {
|
|
102
102
|
const config = Config.merge(options);
|
|
103
|
+
if (this.raw.length === 1 && config.mono) {
|
|
104
|
+
return new MonoParser(this.raw[0]).parse(options);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
ArrayNameValidator.create().validate(this.raw);
|
|
108
|
+
}
|
|
103
109
|
const fullName = new FullName(config);
|
|
104
|
-
ArrayNameValidator.create().validate(this.raw);
|
|
105
110
|
for (const name of this.raw) {
|
|
106
111
|
if (name.isPrefix) {
|
|
107
112
|
fullName.setPrefix(name);
|
|
@@ -116,10 +121,20 @@ export class ArrayNameParser extends Parser {
|
|
|
116
121
|
fullName.middleName.push(name);
|
|
117
122
|
}
|
|
118
123
|
else if (name.isLastName) {
|
|
119
|
-
const
|
|
120
|
-
fullName.setLastName(
|
|
124
|
+
const mother = name instanceof LastName ? name.mother : undefined;
|
|
125
|
+
fullName.setLastName(new LastName(name.value, mother, config.surname));
|
|
121
126
|
}
|
|
122
127
|
}
|
|
123
128
|
return fullName;
|
|
124
129
|
}
|
|
125
130
|
}
|
|
131
|
+
export class MonoParser extends Parser {
|
|
132
|
+
parse(options) {
|
|
133
|
+
const config = Config.merge(options);
|
|
134
|
+
if (config.bypass)
|
|
135
|
+
Validators.namon.validate(this.raw);
|
|
136
|
+
const type = config.mono instanceof Namon ? config.mono : Namon.FIRST_NAME;
|
|
137
|
+
const name = this.raw instanceof Name ? this.raw : new Name(this.raw.trim(), type);
|
|
138
|
+
return new Mononym(name, config);
|
|
139
|
+
}
|
|
140
|
+
}
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ export declare class Namon {
|
|
|
61
61
|
static readonly values: Namon[];
|
|
62
62
|
/** All the predefined name types. */
|
|
63
63
|
static readonly all: Map<string, Namon>;
|
|
64
|
+
private static readonly aliases;
|
|
64
65
|
private constructor();
|
|
65
66
|
/** Whether this string key is part of the predefined keys. */
|
|
66
67
|
static has(key: string): boolean;
|
|
@@ -90,6 +91,8 @@ export declare class Separator {
|
|
|
90
91
|
/** All the available tokens. */
|
|
91
92
|
static readonly tokens: string[];
|
|
92
93
|
private constructor();
|
|
94
|
+
/** Makes a string key a separator type. */
|
|
95
|
+
static cast(key: string): Nullable<Separator>;
|
|
93
96
|
/** String representation of this object. */
|
|
94
97
|
toString(): string;
|
|
95
98
|
}
|
package/dist/esm/types.js
CHANGED
|
@@ -53,6 +53,13 @@ export class Namon {
|
|
|
53
53
|
[Namon.LAST_NAME.key, Namon.LAST_NAME],
|
|
54
54
|
[Namon.SUFFIX.key, Namon.SUFFIX],
|
|
55
55
|
]);
|
|
56
|
+
static aliases = {
|
|
57
|
+
[Namon.PREFIX.key]: ['prefix', 'px', 'p'],
|
|
58
|
+
[Namon.FIRST_NAME.key]: ['firstname', 'first', 'fn', 'f'],
|
|
59
|
+
[Namon.MIDDLE_NAME.key]: ['middlename', 'middle', 'mid', 'mn', 'm'],
|
|
60
|
+
[Namon.LAST_NAME.key]: ['lastname', 'last', 'ln', 'l'],
|
|
61
|
+
[Namon.SUFFIX.key]: ['suffix', 'sx', 's'],
|
|
62
|
+
};
|
|
56
63
|
constructor(index, key) {
|
|
57
64
|
this.index = index;
|
|
58
65
|
this.key = key;
|
|
@@ -61,7 +68,9 @@ export class Namon {
|
|
|
61
68
|
return Namon.all.has(key);
|
|
62
69
|
}
|
|
63
70
|
static cast(key) {
|
|
64
|
-
|
|
71
|
+
const searchValue = String(key).toLowerCase();
|
|
72
|
+
const namon = Object.entries(Namon.aliases).find(([, list]) => list.includes(searchValue))?.[0];
|
|
73
|
+
return Namon.has(namon ?? '') ? Namon.all.get(key) : undefined;
|
|
65
74
|
}
|
|
66
75
|
toString() {
|
|
67
76
|
return `Namon.${this.key}`;
|
|
@@ -100,6 +109,14 @@ export class Separator {
|
|
|
100
109
|
this.name = name;
|
|
101
110
|
this.token = token;
|
|
102
111
|
}
|
|
112
|
+
static cast(key) {
|
|
113
|
+
for (const [name, separator] of Separator.all) {
|
|
114
|
+
if (separator.token === key || name.toLowerCase() === key.toLowerCase()) {
|
|
115
|
+
return separator;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
103
120
|
toString() {
|
|
104
121
|
return `Separator.${this.name}`;
|
|
105
122
|
}
|