namefully 1.0.9 → 1.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.
Files changed (189) hide show
  1. package/LICENSE +21 -674
  2. package/dist/example/index.js +2734 -0
  3. package/dist/lib/config.d.ts +121 -0
  4. package/dist/lib/config.js +189 -0
  5. package/dist/lib/config.js.map +1 -0
  6. package/dist/lib/constants.d.ts +4 -0
  7. package/dist/lib/constants.js +31 -0
  8. package/dist/lib/constants.js.map +1 -0
  9. package/dist/lib/error.d.ts +172 -0
  10. package/dist/lib/error.js +210 -0
  11. package/dist/lib/error.js.map +1 -0
  12. package/dist/lib/{usecases/index.d.ts → example/example.d.ts} +0 -0
  13. package/dist/lib/full-name.d.ts +71 -0
  14. package/dist/lib/full-name.js +147 -0
  15. package/dist/lib/full-name.js.map +1 -0
  16. package/dist/lib/index.d.ts +16 -6
  17. package/dist/lib/index.js +29 -8
  18. package/dist/lib/index.js.map +1 -1
  19. package/dist/lib/name.d.ts +177 -0
  20. package/dist/lib/name.js +322 -0
  21. package/dist/lib/name.js.map +1 -0
  22. package/dist/lib/namefully.d.ts +303 -208
  23. package/dist/lib/namefully.js +603 -442
  24. package/dist/lib/namefully.js.map +1 -1
  25. package/dist/lib/parser.d.ts +46 -0
  26. package/dist/lib/parser.js +173 -0
  27. package/dist/lib/parser.js.map +1 -0
  28. package/dist/lib/src/config.d.ts +121 -0
  29. package/dist/lib/src/constants.d.ts +4 -0
  30. package/dist/lib/src/error.d.ts +172 -0
  31. package/dist/lib/src/full-name.d.ts +71 -0
  32. package/dist/lib/src/index.d.ts +16 -6
  33. package/dist/lib/src/name.d.ts +177 -0
  34. package/dist/lib/src/namefully.d.ts +303 -208
  35. package/dist/lib/src/parser.d.ts +46 -0
  36. package/dist/lib/src/types.d.ts +127 -0
  37. package/dist/lib/src/utils.d.ts +63 -0
  38. package/dist/lib/src/validator.d.ts +66 -0
  39. package/dist/lib/types.d.ts +127 -0
  40. package/dist/lib/types.js +181 -0
  41. package/dist/lib/types.js.map +1 -0
  42. package/dist/lib/utils.d.ts +63 -0
  43. package/dist/lib/utils.js +138 -0
  44. package/dist/lib/utils.js.map +1 -0
  45. package/dist/lib/validator.d.ts +66 -0
  46. package/dist/lib/validator.js +332 -0
  47. package/dist/lib/validator.js.map +1 -0
  48. package/dist/umd/namefully.js +2191 -2111
  49. package/dist/umd/namefully.js.map +1 -1
  50. package/dist/umd/namefully.min.js +1 -1
  51. package/dist/umd/namefully.min.js.LICENSE.txt +8 -20
  52. package/dist/umd/namefully.min.js.map +1 -1
  53. package/package.json +50 -53
  54. package/readme.md +151 -175
  55. package/changelog.md +0 -114
  56. package/dist/lib/core/constants.d.ts +0 -26
  57. package/dist/lib/core/constants.js +0 -42
  58. package/dist/lib/core/constants.js.map +0 -1
  59. package/dist/lib/core/index.d.ts +0 -9
  60. package/dist/lib/core/index.js +0 -13
  61. package/dist/lib/core/index.js.map +0 -1
  62. package/dist/lib/core/parsers/array-name.parser.d.ts +0 -42
  63. package/dist/lib/core/parsers/array-name.parser.js +0 -84
  64. package/dist/lib/core/parsers/array-name.parser.js.map +0 -1
  65. package/dist/lib/core/parsers/array-string.parser.d.ts +0 -48
  66. package/dist/lib/core/parsers/array-string.parser.js +0 -96
  67. package/dist/lib/core/parsers/array-string.parser.js.map +0 -1
  68. package/dist/lib/core/parsers/index.d.ts +0 -11
  69. package/dist/lib/core/parsers/index.js +0 -11
  70. package/dist/lib/core/parsers/index.js.map +0 -1
  71. package/dist/lib/core/parsers/nama.parser.d.ts +0 -34
  72. package/dist/lib/core/parsers/nama.parser.js +0 -75
  73. package/dist/lib/core/parsers/nama.parser.js.map +0 -1
  74. package/dist/lib/core/parsers/parser.d.ts +0 -29
  75. package/dist/lib/core/parsers/parser.js +0 -3
  76. package/dist/lib/core/parsers/parser.js.map +0 -1
  77. package/dist/lib/core/parsers/string.parser.d.ts +0 -61
  78. package/dist/lib/core/parsers/string.parser.js +0 -63
  79. package/dist/lib/core/parsers/string.parser.js.map +0 -1
  80. package/dist/lib/core/utils/utils.d.ts +0 -14
  81. package/dist/lib/core/utils/utils.js +0 -67
  82. package/dist/lib/core/utils/utils.js.map +0 -1
  83. package/dist/lib/models/enums.d.ts +0 -91
  84. package/dist/lib/models/enums.js +0 -98
  85. package/dist/lib/models/enums.js.map +0 -1
  86. package/dist/lib/models/firstname.d.ts +0 -41
  87. package/dist/lib/models/firstname.js +0 -59
  88. package/dist/lib/models/firstname.js.map +0 -1
  89. package/dist/lib/models/index.d.ts +0 -12
  90. package/dist/lib/models/index.js +0 -15
  91. package/dist/lib/models/index.js.map +0 -1
  92. package/dist/lib/models/lastname.d.ts +0 -44
  93. package/dist/lib/models/lastname.js +0 -86
  94. package/dist/lib/models/lastname.js.map +0 -1
  95. package/dist/lib/models/misc.d.ts +0 -80
  96. package/dist/lib/models/misc.js +0 -3
  97. package/dist/lib/models/misc.js.map +0 -1
  98. package/dist/lib/models/name.d.ts +0 -48
  99. package/dist/lib/models/name.js +0 -72
  100. package/dist/lib/models/name.js.map +0 -1
  101. package/dist/lib/models/summary.d.ts +0 -23
  102. package/dist/lib/models/summary.js +0 -60
  103. package/dist/lib/models/summary.js.map +0 -1
  104. package/dist/lib/src/core/constants.d.ts +0 -26
  105. package/dist/lib/src/core/index.d.ts +0 -9
  106. package/dist/lib/src/core/parsers/array-name.parser.d.ts +0 -42
  107. package/dist/lib/src/core/parsers/array-string.parser.d.ts +0 -48
  108. package/dist/lib/src/core/parsers/index.d.ts +0 -11
  109. package/dist/lib/src/core/parsers/nama.parser.d.ts +0 -34
  110. package/dist/lib/src/core/parsers/parser.d.ts +0 -29
  111. package/dist/lib/src/core/parsers/string.parser.d.ts +0 -61
  112. package/dist/lib/src/core/utils/utils.d.ts +0 -14
  113. package/dist/lib/src/models/enums.d.ts +0 -91
  114. package/dist/lib/src/models/firstname.d.ts +0 -41
  115. package/dist/lib/src/models/index.d.ts +0 -12
  116. package/dist/lib/src/models/lastname.d.ts +0 -44
  117. package/dist/lib/src/models/misc.d.ts +0 -80
  118. package/dist/lib/src/models/name.d.ts +0 -48
  119. package/dist/lib/src/models/summary.d.ts +0 -23
  120. package/dist/lib/src/validators/array-name.validator.d.ts +0 -25
  121. package/dist/lib/src/validators/array-string.validator.d.ts +0 -43
  122. package/dist/lib/src/validators/common/validation-error.d.ts +0 -19
  123. package/dist/lib/src/validators/common/validation-rule.d.ts +0 -69
  124. package/dist/lib/src/validators/common/validation-type.d.ts +0 -24
  125. package/dist/lib/src/validators/firstname.validator.d.ts +0 -20
  126. package/dist/lib/src/validators/fullname.validator.d.ts +0 -21
  127. package/dist/lib/src/validators/index.d.ts +0 -21
  128. package/dist/lib/src/validators/lastname.validator.d.ts +0 -20
  129. package/dist/lib/src/validators/middlename.validator.d.ts +0 -20
  130. package/dist/lib/src/validators/nama.validator.d.ts +0 -21
  131. package/dist/lib/src/validators/namon.validator.d.ts +0 -20
  132. package/dist/lib/src/validators/prefix.validator.d.ts +0 -14
  133. package/dist/lib/src/validators/string-name.validator.d.ts +0 -20
  134. package/dist/lib/src/validators/suffix.validator.d.ts +0 -14
  135. package/dist/lib/src/validators/validator.d.ts +0 -13
  136. package/dist/lib/usecases/compress.usecase.d.ts +0 -8
  137. package/dist/lib/usecases/constants.d.ts +0 -7
  138. package/dist/lib/usecases/describe.usecase.d.ts +0 -12
  139. package/dist/lib/usecases/format.usecase.d.ts +0 -6
  140. package/dist/lib/usecases/namefully.usecase.d.ts +0 -14
  141. package/dist/lib/usecases/shorten.usecase.d.ts +0 -6
  142. package/dist/lib/validators/array-name.validator.d.ts +0 -25
  143. package/dist/lib/validators/array-name.validator.js +0 -82
  144. package/dist/lib/validators/array-name.validator.js.map +0 -1
  145. package/dist/lib/validators/array-string.validator.d.ts +0 -43
  146. package/dist/lib/validators/array-string.validator.js +0 -80
  147. package/dist/lib/validators/array-string.validator.js.map +0 -1
  148. package/dist/lib/validators/common/validation-error.d.ts +0 -19
  149. package/dist/lib/validators/common/validation-error.js +0 -26
  150. package/dist/lib/validators/common/validation-error.js.map +0 -1
  151. package/dist/lib/validators/common/validation-rule.d.ts +0 -69
  152. package/dist/lib/validators/common/validation-rule.js +0 -73
  153. package/dist/lib/validators/common/validation-rule.js.map +0 -1
  154. package/dist/lib/validators/common/validation-type.d.ts +0 -24
  155. package/dist/lib/validators/common/validation-type.js +0 -28
  156. package/dist/lib/validators/common/validation-type.js.map +0 -1
  157. package/dist/lib/validators/firstname.validator.d.ts +0 -20
  158. package/dist/lib/validators/firstname.validator.js +0 -29
  159. package/dist/lib/validators/firstname.validator.js.map +0 -1
  160. package/dist/lib/validators/fullname.validator.d.ts +0 -21
  161. package/dist/lib/validators/fullname.validator.js +0 -38
  162. package/dist/lib/validators/fullname.validator.js.map +0 -1
  163. package/dist/lib/validators/index.d.ts +0 -21
  164. package/dist/lib/validators/index.js +0 -35
  165. package/dist/lib/validators/index.js.map +0 -1
  166. package/dist/lib/validators/lastname.validator.d.ts +0 -20
  167. package/dist/lib/validators/lastname.validator.js +0 -29
  168. package/dist/lib/validators/lastname.validator.js.map +0 -1
  169. package/dist/lib/validators/middlename.validator.d.ts +0 -20
  170. package/dist/lib/validators/middlename.validator.js +0 -38
  171. package/dist/lib/validators/middlename.validator.js.map +0 -1
  172. package/dist/lib/validators/nama.validator.d.ts +0 -21
  173. package/dist/lib/validators/nama.validator.js +0 -43
  174. package/dist/lib/validators/nama.validator.js.map +0 -1
  175. package/dist/lib/validators/namon.validator.d.ts +0 -20
  176. package/dist/lib/validators/namon.validator.js +0 -29
  177. package/dist/lib/validators/namon.validator.js.map +0 -1
  178. package/dist/lib/validators/prefix.validator.d.ts +0 -14
  179. package/dist/lib/validators/prefix.validator.js +0 -31
  180. package/dist/lib/validators/prefix.validator.js.map +0 -1
  181. package/dist/lib/validators/string-name.validator.d.ts +0 -20
  182. package/dist/lib/validators/string-name.validator.js +0 -29
  183. package/dist/lib/validators/string-name.validator.js.map +0 -1
  184. package/dist/lib/validators/suffix.validator.d.ts +0 -14
  185. package/dist/lib/validators/suffix.validator.js +0 -31
  186. package/dist/lib/validators/suffix.validator.js.map +0 -1
  187. package/dist/lib/validators/validator.d.ts +0 -13
  188. package/dist/lib/validators/validator.js +0 -9
  189. package/dist/lib/validators/validator.js.map +0 -1
@@ -1,562 +1,723 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Namefully = void 0;
13
+ const config_1 = require("./config");
14
+ const constants_1 = require("./constants");
15
+ const error_1 = require("./error");
16
+ const parser_1 = require("./parser");
17
+ const types_1 = require("./types");
18
+ const utils_1 = require("./utils");
3
19
  /**
4
- * `Namefully` person name handler
20
+ * A helper for organizing person names in a particular order, way, or shape.
5
21
  *
6
- * Created on March 03, 2020
7
- * @author Ralph Florent <ralflornt@gmail.com>
22
+ * Though `namefully` is easy to use, it does not magically guess which part of
23
+ * the name is what (prefix, suffix, first, last, or middle names). It relies
24
+ * actually on how the name parts are indicated (i.e., their roles) so that
25
+ * it can perform internally certain operations and saves us some extra
26
+ * calculations/processing. In addition, `Namefully` can be created using
27
+ * distinct raw data shapes. This is intended to give some flexibility to the
28
+ * developer so that he or she is not bound to a particular data format.
29
+ * By following closely the API reference to know how to harness its usability,
30
+ * this utility aims to save time in formatting names.
8
31
  *
9
- * @license GPL-3.0
10
- * @see {@link https://github.com/ralflorent/namefully|namefully} for more info.
11
- */
12
- const index_1 = require("./core/index");
13
- const index_2 = require("./models/index");
14
- const index_3 = require("./validators/index");
15
- /**
16
- * Person name handler
17
- * @class
18
- * @classdesc
19
- * `Namefully` does not magically guess which part of the name is what. It relies
20
- * actually on how the developer indicates the roles of the name parts so that
21
- * it, internally, can perform certain operations and saves the developer some
22
- * calculations/processings. Nevertheless, Namefully can be constructed using
23
- * distinct raw data shape. This is intended to give some flexibility to the
24
- * developer so that he or she is not bound to a particular data format. Please,
25
- * do follow closely the APIs to know how to properly use it in order to avoid
26
- * some errors (mainly validation's).
32
+ * `namefully` also works like a trapdoor. Once a raw data is provided and
33
+ * validated, a developer can only *access* in a vast amount of, yet effective
34
+ * ways the name info. *No editing* is possible. If the name is mistaken, a new
35
+ * instance of `Namefully` must be created. In other words, it's immutable.
36
+ * Remember, this utility's primary objective is to help manipulate a person name.
27
37
  *
28
- * `Namefully` also works like a trap door. Once a raw data is provided and
29
- * validated, a developer can only ACCESS in a vast amount of, yet effective ways
30
- * the name info. NO EDITING is possible. If the name is mistaken, a new instance
31
- * of `Namefully` must be created. Remember, this utility's primary objective is
32
- * to help to **handle** a person name.
38
+ * Note that the name standards used for the current version of this library
39
+ * are as follows:
40
+ * `[prefix] firstName [middleName] lastName [suffix]`
41
+ * The opening `[` and closing `]` symbols mean that these parts are optional.
42
+ * In other words, the most basic and typical case is a name that looks like
43
+ * this: `John Smith`, where `John` is the first name piece and `Smith`, the last
44
+ * name piece.
33
45
  *
34
- * Note that the name standards used for the current version of this library are
35
- * as follows:
36
- * [Prefix] Firstname [Middlename] Lastname [Suffix]
37
- * The opening `[` and closing `]` brackets mean that these parts are optional.
38
- * In other words, the most basic and typical case is a name that looks like this:
39
- * `John Smith`, where `John` is the first name and `Smith`, the last name.
40
46
  * @see https://departments.weber.edu/qsupport&training/Data_Standards/Name.htm
41
47
  * for more info on name standards.
42
48
  *
43
- * **IMPORTANT**: Keep in mind that the order of appearance matters and can be
44
- * altered through configured parameters, which we will be seeing later on. By
45
- * default, the order of appearance is as shown above and will be used as a basis
46
- * for future examples and use cases.
49
+ * **IMPORTANT**: Keep in mind that the order of appearance (or name order) matters
50
+ * and may be altered through configured parameters, which will be seen later.
51
+ * By default, the order of appearance is as shown above and will be used as a
52
+ * basis for future examples and use cases.
47
53
  *
48
54
  * Once imported, all that is required to do is to create an instance of
49
55
  * `Namefully` and the rest will follow.
50
56
  *
51
57
  * Some terminologies used across the library are:
52
- * - namon: piece of a name (e.g., firstname)
53
- * - nama: pieces of a name (e.g., firstname + lastname)
58
+ * - namon: 1 piece of name (e.g., first name)
59
+ * - nama: 2+ pieces of name (e.g., first name + last name)
54
60
  *
55
- * Happy naming!
61
+ * Happy name handling 😊!
56
62
  */
57
63
  class Namefully {
58
64
  /**
59
- * Constructs an instance of the utility and helps to benefit from many helpers
60
- * @param {string | string[] | Array<Name> | Nama} raw element to parse or
61
- * construct the pieces of the name
62
- * @param {Config} options to configure how to run the utility
65
+ * Creates a name with distinguishable parts from a raw string content.
66
+ * @param names element to parse.
67
+ * @param options additional settings.
68
+ *
69
+ * An optional configuration may be provided with specifics on how to treat
70
+ * a full name during its course. By default, all name parts are validated
71
+ * against some basic validation rules to avoid common runtime exceptions.
63
72
  */
64
- constructor(raw, options) {
65
- // well, first thing first
66
- this.configure(options);
67
- // let's try to parse this, baby!
68
- this.build(raw);
73
+ constructor(names, options) {
74
+ this.build(this.toParser(names), options);
69
75
  }
70
76
  /**
71
- * Gets the full name ordered as configured
72
- * @param {'firstname'|'lastname'} orderedBy force to order by first or last
73
- * name by overriding the preset configuration
74
- * @returns {string} the suffix
77
+ * Constructs a `Namefully` instance from a text.
75
78
  *
76
- * @see {format} to alter manually the order of appearance of the full name.
77
- * For example, ::format('l f m') outputs `lastname firstname middlename`.
78
- */
79
- getFullname(orderedBy) {
80
- orderedBy = orderedBy || this.config.orderedBy; // override config
81
- const { titling, ending } = this.config;
82
- const pxSep = titling === 'us' ? index_2.Separator.PERIOD : index_2.Separator.EMPTY; // Mr[.]
83
- const sxSep = ending !== index_2.Separator.SPACE ? ending : index_2.Separator.EMPTY; // [,] PhD
84
- const nama = [];
85
- if (this.fullname.prefix)
86
- nama.push(index_2.Separator.EMPTY.concat(this.fullname.prefix, pxSep));
87
- switch (orderedBy) {
88
- case 'firstname':
89
- nama.push(this.getFirstname());
90
- nama.push(...this.getMiddlenames());
91
- nama.push(index_2.Separator.EMPTY.concat(this.getLastname(), sxSep));
92
- break;
93
- case 'lastname':
94
- nama.push(this.getLastname());
95
- nama.push(this.getFirstname());
96
- nama.push(this.getMiddlenames().join(index_2.Separator.SPACE).concat(sxSep));
97
- break;
79
+ * It works like `parse` except that this function returns `null` where `parse`
80
+ * would throw a `NameError`.
81
+ */
82
+ static tryParse(text) {
83
+ try {
84
+ return new this(parser_1.Parser.build(text));
85
+ }
86
+ catch (error) {
87
+ return undefined;
98
88
  }
99
- if (this.fullname.suffix)
100
- nama.push(this.fullname.suffix);
101
- return nama.join(index_2.Separator.SPACE);
102
89
  }
103
90
  /**
104
- * Gets the first name part of the full name
105
- * @returns {string} the first name
91
+ * Constructs a `Namefully` instance from a text.
92
+ *
93
+ * It throws a `NameError` if the text cannot be parsed. Use `tryParse`
94
+ * instead if a `null` return is preferred over a throwable error.
95
+ *
96
+ * This operation is computed asynchronously, which gives more flexibility at
97
+ * the time of catching the error (and stack trace if any). The acceptable
98
+ * text format is a string composed of two or more name pieces. For instance,
99
+ * `John Lennon`, or `John Winston Ono Lennon` are parsable names and follow
100
+ * the basic name standard rules (i.e., first-middle-last).
101
+ *
102
+ * Keep in mind that prefix and suffix are not considered during the parsing
103
+ * process.
104
+ */
105
+ static parse(text) {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ return parser_1.Parser.buildAsync(text).then((parser) => new Namefully(parser));
108
+ });
109
+ }
110
+ /**
111
+ * The current configuration.
112
+ */
113
+ get config() {
114
+ return this._config;
115
+ }
116
+ /**
117
+ * The number of characters of the `birthName`, including spaces.
118
+ */
119
+ get length() {
120
+ return this.birth.length;
121
+ }
122
+ /**
123
+ * The prefix part.
124
+ */
125
+ get prefix() {
126
+ var _a;
127
+ return (_a = this._fullName.prefix) === null || _a === void 0 ? void 0 : _a.toString();
128
+ }
129
+ /**
130
+ * The firt name.
131
+ */
132
+ get first() {
133
+ return this.firstName();
134
+ }
135
+ /**
136
+ * The first middle name if any.
137
+ */
138
+ get middle() {
139
+ return this.hasMiddle ? this.middleName()[0] : undefined;
140
+ }
141
+ /**
142
+ * Returns true if any middle name has been set.
143
+ */
144
+ get hasMiddle() {
145
+ return this._fullName.has(types_1.Namon.MIDDLE_NAME);
146
+ }
147
+ /**
148
+ * The last name.
149
+ */
150
+ get last() {
151
+ return this.lastName();
152
+ }
153
+ /**
154
+ * The suffix part.
155
+ */
156
+ get suffix() {
157
+ var _a;
158
+ return (_a = this._fullName.suffix) === null || _a === void 0 ? void 0 : _a.toString();
159
+ }
160
+ /**
161
+ * The birth name.
162
+ */
163
+ get birth() {
164
+ return this.birthName();
165
+ }
166
+ /**
167
+ * The shortest version of a person name.
168
+ */
169
+ get short() {
170
+ return this.shorten();
171
+ }
172
+ /**
173
+ * The longest version of a person name.
174
+ */
175
+ get long() {
176
+ return this.birth;
177
+ }
178
+ /**
179
+ * The entire name set.
180
+ */
181
+ get full() {
182
+ return this.fullName();
183
+ }
184
+ /**
185
+ * The first name combined with the last name's initial.
186
+ */
187
+ get public() {
188
+ return this.format('f $l');
189
+ }
190
+ /**
191
+ * Returns the full name as set.
106
192
  */
107
- getFirstname() {
108
- return this.fullname.firstname.tostring();
193
+ toString() {
194
+ return this.full;
109
195
  }
110
196
  /**
111
- * Gets the last name part of the full name
112
- * @param {LastnameFormat} [format] overrides the how-to format of a surname
113
- * output, considering its subparts.
114
- * @returns {string} the last name
197
+ * Fetches the raw form of a name piece.
115
198
  */
116
- getLastname(format) {
117
- return this.fullname.lastname.tostring(format);
199
+ get(namon) {
200
+ if (namon.equal(types_1.Namon.PREFIX))
201
+ return this._fullName.prefix;
202
+ if (namon.equal(types_1.Namon.FIRST_NAME))
203
+ return this._fullName.firstName;
204
+ if (namon.equal(types_1.Namon.MIDDLE_NAME))
205
+ return this._fullName.middleName;
206
+ if (namon.equal(types_1.Namon.LAST_NAME))
207
+ return this._fullName.lastName;
208
+ if (namon.equal(types_1.Namon.SUFFIX))
209
+ return this._fullName.suffix;
210
+ return undefined;
118
211
  }
119
212
  /**
120
- * Gets the middle names part of the full name
121
- * @returns {Array<string>} the middle names
213
+ * Whether this name is equal to another one from a raw-string perspective.
122
214
  */
123
- getMiddlenames() {
124
- return this.fullname.middlename ? this.fullname.middlename.map(n => n.namon) : [];
215
+ equal(other) {
216
+ return this.toString() === other.toString();
125
217
  }
126
218
  /**
127
- * Gets the prefix part of the full name
128
- * @returns {string} the prefix
219
+ * Gets a JSON representation of the full name.
129
220
  */
130
- getPrefix() {
131
- const pxSep = this.config.titling === 'us' ? index_2.Separator.PERIOD : index_2.Separator.EMPTY;
132
- return this.fullname.prefix ?
133
- index_2.Separator.EMPTY.concat(this.fullname.prefix, pxSep) :
134
- index_2.Separator.EMPTY;
221
+ toJson() {
222
+ return {
223
+ prefix: this.prefix,
224
+ firstName: this.first,
225
+ middleName: this.middleName(),
226
+ lastName: this.last,
227
+ suffix: this.suffix,
228
+ };
135
229
  }
136
230
  /**
137
- * Gets the suffix part of the full name
138
- * @returns {string} the suffix
231
+ * Confirms that a name part has been set.
139
232
  */
140
- getSuffix() {
141
- return this.fullname.suffix || index_2.Separator.EMPTY;
233
+ has(namon) {
234
+ return this._fullName.has(namon);
142
235
  }
143
236
  /**
144
- * Gets the initials of the full name
145
- * @param {'firstname'|'lastname'} orderedBy force to order by first or last
146
- * name by overriding the preset configuration
147
- * @param {boolean} [withMid] whether to include middle names's
148
- * @returns {Array<string>} the initials
237
+ * Gets the full name ordered as configured.
149
238
  *
150
- * @example
151
- * Given the names:
152
- * - `John Smith` => ['J', 'S']
153
- * - `John Ben Smith` => ['J', 'S']
154
- * when `withMid` is set to true:
155
- * - `John Ben Smith` => ['J', 'B', 'S']
239
+ * The name order `orderedBy` forces to order by first or last name by
240
+ * overriding the preset configuration.
156
241
  *
157
- * **NOTE**:
158
- * Ordered by last name obeys the following format:
159
- * `lastname firstname [middlename]`
160
- * which means that if no middle name was set, setting `withMid` to true
161
- * will output nothing and warn the end user about it.
162
- */
163
- getInitials(orderedBy, withMid = false) {
164
- orderedBy = orderedBy || this.config.orderedBy; // override config
165
- const midInits = this.fullname.middlename ?
166
- this.fullname.middlename.map(n => n.getInitials()) : [];
167
- if (withMid && !this.fullname.middlename) {
168
- console.warn('No initials for middle names since none was set.');
242
+ * `Namefully.format` may also be used to alter manually the order of appearance
243
+ * of full name.
244
+ *
245
+ * For example:
246
+ * ```ts
247
+ * const name = new Namefully('Jon Stark Snow');
248
+ * console.log(name.fullName(NameOrder.LAST_NAME)); // "Snow Jon Stark"
249
+ * console.log(name.format('l f m')); // "Snow Jon Stark"
250
+ * ```
251
+ */
252
+ fullName(orderedBy) {
253
+ const sep = this._config.ending ? ',' : '';
254
+ const names = [];
255
+ orderedBy = orderedBy || this._config.orderedBy;
256
+ if (this.prefix)
257
+ names.push(this.prefix);
258
+ if (orderedBy === types_1.NameOrder.FIRST_NAME) {
259
+ names.push(this.first, ...this.middleName(), this.last + sep);
169
260
  }
170
- const initials = [];
171
- switch (orderedBy) {
172
- case 'firstname':
173
- initials.push(...this.fullname.firstname.getInitials());
174
- if (withMid)
175
- midInits.forEach(m => initials.push(...m));
176
- initials.push(...this.fullname.lastname.getInitials());
177
- break;
178
- case 'lastname':
179
- initials.push(...this.fullname.lastname.getInitials());
180
- initials.push(...this.fullname.firstname.getInitials());
181
- if (withMid)
182
- midInits.forEach(m => initials.push(...m));
183
- break;
261
+ else {
262
+ names.push(this.last, this.first, this.middleName().join(' ') + sep);
184
263
  }
185
- return initials;
264
+ if (this.suffix)
265
+ names.push(this.suffix);
266
+ return names.join(' ').trim();
267
+ }
268
+ /**
269
+ * Gets the birth name ordered as configured, no `prefix` or `suffix`.
270
+ *
271
+ * @param orderedBy forces to order by first or last name by overriding the
272
+ * preset configuration.
273
+ */
274
+ birthName(orderedBy) {
275
+ orderedBy = orderedBy || this._config.orderedBy;
276
+ return orderedBy === types_1.NameOrder.FIRST_NAME
277
+ ? [this.first, ...this.middleName(), this.last].join(' ')
278
+ : [this.last, this.first, ...this.middleName()].join(' ');
186
279
  }
187
280
  /**
188
- * Gives some descriptive statistics that summarize the central tendency,
189
- * dispersion and shape of the characters' distribution.
190
- * @param what which variant to use when describe a name part
191
- * @returns {string} the stats behind the full name.
281
+ * Gets the first name part of the `FullName`.
192
282
  *
193
- * Treated as a categorical dataset, the summary contains the following info:
194
- * `count` : the number of *unrestricted* characters of the name;
195
- * `frequency` : the highest frequency within the characters;
196
- * `top` : the character with the highest frequency;
197
- * `unique` : the count of unique characters of the name.
283
+ * @param withMore determines whether to include other pieces of the first
284
+ * name.
285
+ */
286
+ firstName(withMore = true) {
287
+ return this._fullName.firstName.toString(withMore);
288
+ }
289
+ /**
290
+ * Gets the middle name part of the `FullName`.
291
+ */
292
+ middleName() {
293
+ return this._fullName.middleName.map((n) => n.value);
294
+ }
295
+ /**
296
+ * Gets the last name part of the `FullName`.
198
297
  *
199
- * @example
200
- * Given the name "Thomas Alva Edison", the summary will output as follows:
298
+ * @param format overrides the how-to formatting of a surname output,
299
+ * considering its sub-parts.
300
+ */
301
+ lastName(format) {
302
+ return this._fullName.lastName.toString(format);
303
+ }
304
+ /**
305
+ * Gets the initials of the `FullName`.
201
306
  *
202
- * Descriptive statistics for "Thomas Alva Edison"
203
- * count : 16
204
- * frequency: 3
205
- * top : A
206
- * unique : 12
307
+ * @param {options.orderedBy} forces to order by first or last name by
308
+ * overriding the preset configuration.
309
+ * @param
207
310
  *
208
- * **NOTE:**
209
- * During the setup, a set of restricted characters can be defined to be removed
210
- * from the stats. By default, the only restricted character is the `space`.
211
- * That is why the `count` for the example below result in `16` instead of
212
- * `16`.
213
- * Another thing to consider is that the summary is case *insensitive*. Note
214
- * that the letter `a` has the top frequency, be it `3`.
215
- */
216
- describe(what = 'fullname') {
217
- switch (what) {
218
- case 'fullname':
219
- return this.summary;
220
- case 'firstname':
221
- return this.fullname.firstname.describe();
222
- case 'lastname':
223
- return this.fullname.lastname.describe();
224
- case 'middlename':
225
- return !this.fullname.middlename ? null :
226
- new index_2.Summary(this.fullname.middlename.map(n => n.namon).join(index_2.Separator.SPACE));
311
+ * For example, given the names:
312
+ * - `John Smith` => `['J', 'S']`
313
+ * - `John Ben Smith` => `['J', 'B', 'S']`.
314
+ */
315
+ initials(options) {
316
+ const initials = [];
317
+ const firstInits = this._fullName.firstName.initials();
318
+ const midInits = this._fullName.middleName.map((n) => n.initials()[0]);
319
+ const lastInits = this._fullName.lastName.initials();
320
+ const mergedOptions = Object.assign({ orderedBy: this._config.orderedBy, only: types_1.NameType.BIRTH_NAME }, options);
321
+ const { orderedBy, only } = mergedOptions;
322
+ if (only !== types_1.NameType.BIRTH_NAME) {
323
+ if (only === types_1.NameType.FIRST_NAME) {
324
+ initials.push(...firstInits);
325
+ }
326
+ else if (only === types_1.NameType.MIDDLE_NAME) {
327
+ initials.push(...midInits);
328
+ }
329
+ else {
330
+ initials.push(...lastInits);
331
+ }
332
+ }
333
+ else if (orderedBy === types_1.NameOrder.FIRST_NAME) {
334
+ initials.push(...firstInits, ...midInits, ...lastInits);
335
+ }
336
+ else {
337
+ initials.push(...lastInits, ...firstInits, ...midInits);
227
338
  }
339
+ return initials;
228
340
  }
229
341
  /**
230
342
  * Shortens a complex full name to a simple typical name, a combination of
231
- * first name and last name.
232
- * @param {'firstname'|'lastname'} orderedBy force to order by first or last
233
- * name by overriding the preset configuration
234
- * @returns {string} a typical name
343
+ * first and last name.
344
+ *
345
+ * @param orderedBy forces to order by first or last name by overriding the
346
+ * preset configuration.
235
347
  *
236
- * @example
237
348
  * For a given name such as `Mr Keanu Charles Reeves`, shortening this name
238
349
  * is equivalent to making it `Keanu Reeves`.
350
+ *
351
+ * As a shortened name, the namon of the first name is favored over the other
352
+ * names forming part of the entire first names, if any. Meanwhile, for
353
+ * the last name, the configured `surname` is prioritized.
354
+ *
355
+ * For a given `FirstName FatherName MotherName`, shortening this name when
356
+ * the surname is set as `mother` is equivalent to making it:
357
+ * `FirstName MotherName`.
239
358
  */
240
359
  shorten(orderedBy) {
241
- orderedBy = orderedBy || this.config.orderedBy; // override config
242
- return orderedBy === 'firstname' ?
243
- [
244
- this.fullname.firstname.namon,
245
- this.fullname.lastname.namon,
246
- ].join(index_2.Separator.SPACE) :
247
- [
248
- this.fullname.lastname.namon,
249
- this.fullname.firstname.namon,
250
- ].join(index_2.Separator.SPACE);
251
- }
252
- /**
253
- * Compresses a name by using different forms of variants
254
- * @param {number} [limit] a threshold to limit the number of characters
255
- * @param {'firstname'|'lastname'|'middlename'|'firstmid'|'midlast'} [by]
256
- * a variant to use when compressing the long name. The last two variants
257
- * represent respectively the combination of `firstname + middlename` and
258
- * `middlename + lastname`.
259
- * @param {boolean} [warning] should warn when the set limit is violated
360
+ orderedBy = orderedBy || this._config.orderedBy;
361
+ return orderedBy === types_1.NameOrder.FIRST_NAME
362
+ ? [this._fullName.firstName.value, this._fullName.lastName.toString()].join(' ')
363
+ : [this._fullName.lastName.toString(), this._fullName.firstName.value].join(' ');
364
+ }
365
+ /**
366
+ * Flattens a long name using the name types as variants.
367
+ *
368
+ * While @param limit sets a threshold as a limited number of characters
369
+ * supported to flatten a `FullName`, @param by indicates which variant
370
+ * to use when doing so. By default, a full name gets flattened by
371
+ * `Flat.MIDDLE_NAME`.
260
372
  *
261
- * @example
262
- * The compressing operation is only executed iff there is valid entry and it
263
- * surpasses the limit set. In the examples below, let us assume that the
373
+ * The flattening operation is only executed iff there is a valid entry and
374
+ * it surpasses the limit set. In the examples below, let us assume that the
264
375
  * name goes beyond the limit value.
265
376
  *
266
- * Compressing a long name refers to reducing the name to the following forms:
267
- * 1. by firstname: 'John Moe Beau Lennon' => 'J. Moe Beau Lennon'
268
- * 2. by middlename: 'John Moe Beau Lennon' => 'John M. B. Lennon'
269
- * 3. by lastname: 'John Moe Beau Lennon' => 'John Moe Beau L.'
270
- * 4. by firstmid: 'John Moe Beau Lennon' => 'J. M. B. Lennon'
271
- * 5. by midlast: 'John Moe Beau Lennon' => 'John M. B. L.'
377
+ * Flattening a long name refers to reducing the name to the following forms.
378
+ * For example, `John Winston Ono Lennon` flattened by:
379
+ * * Flat.FIRST_NAME: => 'J. Winston Ono Lennon'
380
+ * * Flat.MIDDLE_NAME: => 'John W. O. Lennon'
381
+ * * Flat.LAST_NAME: => 'John Winston Ono L.'
382
+ * * Flat.FIRST_MID: => 'J. W. O. Lennon'
383
+ * * Flat.MID_LAST: => 'John W. O. L.'
384
+ * * Flat.ALL: => 'J. W. O. L.'
272
385
  *
273
- * By default, it compresses by 'firstmid' variant: 'J. M. B. Lennon'.
274
- */
275
- compress(limit = 20, by = 'middlename', warning = true) {
276
- if (this.getFullname().length <= limit) // no need to compress
277
- return this.getFullname();
278
- const { firstname: fn, lastname: ln, middlename } = this.fullname;
279
- const mn = this.getMiddlenames().join(index_2.Separator.SPACE);
280
- const hasmid = Array.isArray(middlename) && middlename.length > 0;
281
- const sep = this.config.titling === 'us' ? index_2.Separator.PERIOD : index_2.Separator.EMPTY;
282
- const firsts = fn.getInitials().join(sep).concat(sep);
283
- const lasts = ln.getInitials().join(sep).concat(sep);
284
- const mids = hasmid ? middlename.map(n => n.getInitials()).join(sep).concat(sep) : index_2.Separator.EMPTY;
285
- let cname = '';
286
- if (this.config.orderedBy === 'firstname') {
386
+ * With the help of the @param recursive flag, the above operation can happen
387
+ * recursively in the same order if the name is still too long. For example,
388
+ * flattening `John Winston Ono Lennon` using the following params:
389
+ * `flatten({ limit: 18, by: Flat.FIRST_NAME, recursive: true })`
390
+ * will result in `John W. O. Lennon` and not `J. Winston Ono Lennon`.
391
+ *
392
+ * A shorter version of this method is `zip()`.
393
+ */
394
+ flatten(options) {
395
+ if (this.length <= options.limit)
396
+ return this.full;
397
+ const mergedOptions = Object.assign({ limit: 20, by: types_1.Flat.MIDDLE_NAME, withPeriod: true, recursive: false, withMore: false }, options);
398
+ const { by, limit, recursive, withMore, withPeriod, surname } = mergedOptions;
399
+ const sep = withPeriod ? '.' : '';
400
+ const fn = this._fullName.firstName.toString();
401
+ const mn = this.middleName().join(' ');
402
+ const ln = this._fullName.lastName.toString();
403
+ const hasMid = this.hasMiddle;
404
+ const f = this._fullName.firstName.initials(withMore).join(sep + ' ') + sep;
405
+ const l = this._fullName.lastName.initials(surname).join(sep + ' ') + sep;
406
+ const m = hasMid ? this._fullName.middleName.map((n) => n.initials()[0]).join(sep + ' ') + sep : '';
407
+ let name = [];
408
+ if (this._config.orderedBy === types_1.NameOrder.FIRST_NAME) {
287
409
  switch (by) {
288
- case 'firstname':
289
- cname = hasmid ?
290
- [firsts, mn, ln.tostring()].join(index_2.Separator.SPACE) :
291
- [firsts, ln.tostring()].join(index_2.Separator.SPACE);
410
+ case types_1.Flat.FIRST_NAME:
411
+ name = hasMid ? [f, mn, ln] : [f, ln];
292
412
  break;
293
- case 'lastname':
294
- cname = hasmid ?
295
- [fn.tostring(), mn, lasts].join(index_2.Separator.SPACE) :
296
- [fn.tostring(), lasts].join(index_2.Separator.SPACE);
413
+ case types_1.Flat.LAST_NAME:
414
+ name = hasMid ? [fn, mn, l] : [fn, l];
297
415
  break;
298
- case 'middlename':
299
- cname = hasmid ?
300
- [fn.tostring(), mids, ln.tostring()].join(index_2.Separator.SPACE) :
301
- [fn.tostring(), ln.tostring()].join(index_2.Separator.SPACE);
416
+ case types_1.Flat.MIDDLE_NAME:
417
+ name = hasMid ? [fn, m, ln] : [fn, ln];
302
418
  break;
303
- case 'firstmid':
304
- cname = hasmid ?
305
- [firsts, mids, ln.tostring()].join(index_2.Separator.SPACE) :
306
- [firsts, ln.tostring()].join(index_2.Separator.SPACE);
419
+ case types_1.Flat.FIRST_MID:
420
+ name = hasMid ? [f, m, ln] : [f, ln];
307
421
  break;
308
- case 'midlast':
309
- cname = hasmid ?
310
- [fn.tostring(), mids, lasts].join(index_2.Separator.SPACE) :
311
- [fn.tostring(), lasts].join(index_2.Separator.SPACE);
422
+ case types_1.Flat.MID_LAST:
423
+ name = hasMid ? [fn, m, l] : [fn, l];
424
+ break;
425
+ case types_1.Flat.ALL:
426
+ name = hasMid ? [f, m, l] : [f, l];
312
427
  break;
313
428
  }
314
429
  }
315
430
  else {
316
431
  switch (by) {
317
- case 'firstname':
318
- cname = hasmid ?
319
- [ln.tostring(), firsts, mn].join(index_2.Separator.SPACE) :
320
- [ln.tostring(), firsts].join(index_2.Separator.SPACE);
432
+ case types_1.Flat.FIRST_NAME:
433
+ name = hasMid ? [ln, f, mn] : [ln, f];
434
+ break;
435
+ case types_1.Flat.LAST_NAME:
436
+ name = hasMid ? [l, fn, mn] : [l, fn];
321
437
  break;
322
- case 'lastname':
323
- cname = hasmid ?
324
- [lasts, fn.tostring(), mn].join(index_2.Separator.SPACE) :
325
- [lasts, fn.tostring()].join(index_2.Separator.SPACE);
438
+ case types_1.Flat.MIDDLE_NAME:
439
+ name = hasMid ? [ln, fn, m] : [ln, fn];
326
440
  break;
327
- case 'middlename':
328
- cname = hasmid ?
329
- [ln.tostring(), fn.tostring(), mids].join(index_2.Separator.SPACE) :
330
- [ln.tostring(), fn.tostring()].join(index_2.Separator.SPACE);
441
+ case types_1.Flat.FIRST_MID:
442
+ name = hasMid ? [ln, f, m] : [ln, f];
331
443
  break;
332
- case 'firstmid':
333
- cname = hasmid ?
334
- [ln.tostring(), firsts, mids].join(index_2.Separator.SPACE) :
335
- [ln.tostring(), firsts].join(index_2.Separator.SPACE);
444
+ case types_1.Flat.MID_LAST:
445
+ name = hasMid ? [l, fn, m] : [l, fn];
336
446
  break;
337
- case 'midlast':
338
- cname = hasmid ?
339
- [lasts, fn.tostring(), mids].join(index_2.Separator.SPACE) :
340
- [lasts, fn.tostring()].join(index_2.Separator.SPACE);
447
+ case types_1.Flat.ALL:
448
+ name = hasMid ? [l, f, m] : [l, f];
341
449
  break;
342
450
  }
343
451
  }
344
- if (warning && cname.length > limit)
345
- console.warn(`The compressed name <${cname}> still surpasses the set limit ${limit}`);
346
- return cname;
347
- }
348
- /**
349
- * Zips or compresses a name by using different forms of variants
350
- * @param by a variant to use when compressing the long name. The last two
351
- * variants represent respectively the combination of `firstname + middlename`
352
- * and `middlename + lastname`.
353
- */
354
- zip(by = 'mn') {
355
- let v;
356
- if (by === 'fn' || by === 'firstname')
357
- v = 'firstname';
358
- if (by === 'mn' || by === 'middlename')
359
- v = 'middlename';
360
- if (by === 'ln' || by === 'lastname')
361
- v = 'lastname';
362
- if (by === 'fm' || by === 'firstmid')
363
- v = 'firstmid';
364
- if (by === 'ml' || by === 'midlast')
365
- v = 'midlast';
366
- return this.compress(0, v, false);
367
- }
368
- /**
369
- * Suggests possible (randomly) usernames closest to the name
370
- * @returns {Array<string>} a set of usernames
452
+ const flat = name.join(' ');
453
+ if (recursive && flat.length > limit) {
454
+ const next = by === types_1.Flat.FIRST_NAME
455
+ ? types_1.Flat.MIDDLE_NAME
456
+ : by === types_1.Flat.MIDDLE_NAME
457
+ ? types_1.Flat.LAST_NAME
458
+ : by === types_1.Flat.LAST_NAME
459
+ ? types_1.Flat.FIRST_MID
460
+ : by === types_1.Flat.FIRST_MID
461
+ ? types_1.Flat.MID_LAST
462
+ : by === types_1.Flat.MID_LAST
463
+ ? types_1.Flat.ALL
464
+ : by === types_1.Flat.ALL
465
+ ? types_1.Flat.ALL
466
+ : by;
467
+ if (next === by)
468
+ return flat;
469
+ return this.flatten(Object.assign(Object.assign({}, options), { by: next }));
470
+ }
471
+ return flat;
472
+ }
473
+ /**
474
+ * Zips or compacts a name using different forms of variants.
475
+ *
476
+ * @see `flatten()` for more details.
477
+ */
478
+ zip(by = types_1.Flat.MID_LAST, withPeriod = true) {
479
+ return this.flatten({ limit: 0, by, withPeriod });
480
+ }
481
+ /**
482
+ * Formats the full name as desired.
483
+ * @param pattern character used to format it.
371
484
  *
372
- * **NOTE**
373
- * The validity of these usernames are not checked against any social media
374
- * or web app online.
375
- */
376
- username() {
377
- const unames = [];
378
- const { firstname: f, lastname: l } = this.fullname;
379
- const p = index_2.Separator.PERIOD;
380
- // Given `John Smith`
381
- unames.push(f.lower() + l.lower()); // johnsmith
382
- unames.push(l.lower() + f.lower()); // smithjohn
383
- unames.push(f.lower()[0] + l.lower()); // jsmith
384
- unames.push(l.lower()[0] + f.lower()); // sjohn
385
- unames.push(f.lower()[0] + p + l.lower()); // j.smith
386
- unames.push(l.lower()[0] + p + f.lower()); // s.john
387
- unames.push(f.lower().slice(0, 2) + l.lower()); // josmith
388
- unames.push(l.lower().slice(0, 2) + f.lower()); // smjohn
389
- unames.push(f.lower().slice(0, 2) + p + l.lower()); // jo.smith
390
- unames.push(l.lower().slice(0, 2) + p + f.lower()); // sm.john
391
- return unames;
392
- }
393
- /**
394
- * Formats the name as desired
395
- * @param {string} how to format the full name
396
- * @returns {string} the formatted name as specified
485
+ * string format
486
+ * -------------
487
+ * - 'short': typical first + last name
488
+ * - 'long': birth name (without prefix and suffix)
489
+ * - 'public': first name combined with the last name's initial.
490
+ * - 'official': official document format
397
491
  *
398
- * How to format it?
399
- * 'f': first name
400
- * 'F': capitalized first name
401
- * 'l': last name (official)
402
- * 'L': capitalized last name
403
- * 'm': middle names
404
- * 'M': Capitalized middle names
405
- * 'O': official document format
492
+ * char format
493
+ * -----------
494
+ * - 'b': birth name
495
+ * - 'B': capitalized birth name
496
+ * - 'f': first name
497
+ * - 'F': capitalized first name
498
+ * - 'l': last name
499
+ * - 'L': capitalized last name
500
+ * - 'm': middle names
501
+ * - 'M': capitalized middle names
502
+ * - 'o': official document format
503
+ * - 'O': official document format in capital letters
504
+ * - 'p': prefix
505
+ * - 'P': capitalized prefix
506
+ * - 's': suffix
507
+ * - 'S': capitalized suffix
406
508
  *
407
- * @example
408
- * Given the name `Joe Jim Smith`, call the `format` with the how string.
509
+ * punctuations
510
+ * ------------
511
+ * - '.': period
512
+ * - ',': comma
513
+ * - ' ': space
514
+ * - '-': hyphen
515
+ * - '_': underscore
516
+ * - '$': an escape character to select only the initial of the next char.
517
+ *
518
+ * Given the name `Joe Jim Smith`, use `format` with the `pattern` string.
409
519
  * - format('l f') => 'Smith Joe'
410
520
  * - format('L, f') => 'SMITH, Joe'
411
- * - format('fml') => 'JoeJimSmith'
412
- * - format('FML') => 'JOEJIMSMITH'
413
- * - format('L, f m') => 'SMITH, Joe Jim'
414
- * - format('O') => 'SMITH, Joe Jim'
415
- */
416
- format(how) {
417
- if (!how)
418
- return this.getFullname();
521
+ * - format('short') => 'Joe Smith'
522
+ * - format() => 'SMITH, Joe Jim'
523
+ * - format(r'f $l.') => 'Joe S.'.
524
+ *
525
+ * Do note that the escape character is only valid for the birth name parts:
526
+ * first, middle, and last names.
527
+ */
528
+ format(pattern) {
529
+ var _a;
530
+ if (pattern === 'short')
531
+ return this.short;
532
+ if (pattern === 'long')
533
+ return this.long;
534
+ if (pattern === 'public')
535
+ return this.public;
536
+ if (pattern === 'official')
537
+ pattern = 'o';
538
+ let group = '';
419
539
  const formatted = [];
420
- const tokens = [
421
- '.', ',', ' ', '-', '_', 'f', 'F', 'l', 'L', 'm', 'M',
422
- 'n', 'N', 'o', 'O', 'p', 'P', 's', 'S'
423
- ];
424
- for (const c of how) {
425
- if (tokens.indexOf(c) === -1)
426
- throw new Error(`<${c}> is an invalid character for the formatting.`);
427
- formatted.push(this.map(c));
540
+ for (const char of pattern.split('')) {
541
+ if (constants_1.ALLOWED_TOKENS.indexOf(char) === -1) {
542
+ throw new error_1.NotAllowedError({
543
+ source: this.full,
544
+ operation: 'format',
545
+ message: `unsupported character <${char}> from ${pattern}.`,
546
+ });
547
+ }
548
+ group += char;
549
+ if (char === '$')
550
+ continue;
551
+ formatted.push((_a = this.map(group)) !== null && _a !== void 0 ? _a : '');
552
+ group = '';
428
553
  }
429
- return formatted.join(index_2.Separator.EMPTY).trim();
554
+ return formatted.join('').trim();
555
+ }
556
+ /**
557
+ * Flips definitely the name order from the preset/current config.
558
+ */
559
+ flip() {
560
+ if (this._config.orderedBy === types_1.NameOrder.FIRST_NAME) {
561
+ this._config.updateOrder(types_1.NameOrder.LAST_NAME);
562
+ console.log(`The name order is now changed to: ${types_1.NameOrder.LAST_NAME}`);
563
+ }
564
+ else {
565
+ this._config.updateOrder(types_1.NameOrder.FIRST_NAME);
566
+ console.log(`The name order is now changed to: ${types_1.NameOrder.FIRST_NAME}`);
567
+ }
568
+ }
569
+ /**
570
+ * Splits the name parts of a birth name.
571
+ * @param separator token for the split.
572
+ */
573
+ split(separator = /[' -]/g) {
574
+ return this.birth.replace(separator, ' ').split(' ');
430
575
  }
431
576
  /**
432
- * Configures how the setup will be working
433
- * @param {Config} options for a customized setup
577
+ * Joins the name parts of a birth name.
578
+ * @param separator token for the junction.
434
579
  */
435
- configure(options) {
436
- // consider using deepmerge if objects no longer stay shallow
437
- this.config = Object.assign(Object.assign({}, index_1.CONFIG), options); // if options, it overrides CONFIG
580
+ join(separator = '') {
581
+ return this.split().join(separator);
438
582
  }
439
583
  /**
440
- * Defines the full name by having the pieces (namon) of the names ready
441
- * @param parser customized or user-defined parser to get the full name
584
+ * Transforms a birth name into UPPERCASE
442
585
  */
443
- initialize(parser) {
444
- const { orderedBy, separator, bypass, lastnameFormat } = this.config;
445
- this.fullname = parser.parse({ orderedBy, separator, bypass, lastnameFormat });
586
+ toUpperCase() {
587
+ return this.birth.toUpperCase();
446
588
  }
447
589
  /**
448
- * Maps a character to a specific piece of the name
449
- * @param c character to be mapped
450
- * @return {string} piece of name
590
+ * Transforms a birth name into lowercase
451
591
  */
452
- map(c) {
453
- switch (c) {
592
+ toLowerCase() {
593
+ return this.birth.toLowerCase();
594
+ }
595
+ /**
596
+ * Transforms a birth name into camelCase
597
+ */
598
+ toCamelCase() {
599
+ return utils_1.decapitalize(this.toPascalCase());
600
+ }
601
+ /**
602
+ * Transforms a birth name into PascalCase
603
+ */
604
+ toPascalCase() {
605
+ return this.split()
606
+ .map((n) => utils_1.capitalize(n))
607
+ .join('');
608
+ }
609
+ /**
610
+ * Transforms a birth name into snake_case
611
+ */
612
+ toSnakeCase() {
613
+ return this.split()
614
+ .map((n) => n.toLowerCase())
615
+ .join('_');
616
+ }
617
+ /**
618
+ * Transforms a birth name into hyphen-case
619
+ */
620
+ toHyphenCase() {
621
+ return this.split()
622
+ .map((n) => n.toLowerCase())
623
+ .join('-');
624
+ }
625
+ /**
626
+ * Transforms a birth name into dot.case
627
+ */
628
+ toDotCase() {
629
+ return this.split()
630
+ .map((n) => n.toLowerCase())
631
+ .join('.');
632
+ }
633
+ /**
634
+ * Transforms a birth name into ToGgLeCaSe
635
+ */
636
+ toToggleCase() {
637
+ return utils_1.toggleCase(this.birth);
638
+ }
639
+ build(parser, options) {
640
+ this._config = config_1.Config.merge(options);
641
+ this._fullName = parser.parse(this._config);
642
+ }
643
+ toParser(raw) {
644
+ if (raw instanceof parser_1.Parser)
645
+ return raw;
646
+ if (typeof raw === 'string')
647
+ return new parser_1.StringParser(raw);
648
+ if (utils_1.isStringArray(raw))
649
+ return new parser_1.ArrayStringParser(raw);
650
+ if (utils_1.isNameArray(raw))
651
+ return new parser_1.ArrayNameParser(raw);
652
+ if (typeof raw === 'object')
653
+ return new parser_1.NamaParser(raw);
654
+ throw new error_1.InputError({
655
+ source: raw,
656
+ message: 'Cannot parse raw data. Review expected data types.',
657
+ });
658
+ }
659
+ map(char) {
660
+ var _a, _b;
661
+ switch (char) {
454
662
  case '.':
455
- return index_2.Separator.PERIOD;
456
663
  case ',':
457
- return index_2.Separator.COMMA;
458
664
  case ' ':
459
- return index_2.Separator.SPACE;
460
665
  case '-':
461
- return index_2.Separator.HYPHEN;
462
666
  case '_':
463
- return index_2.Separator.UNDERSCORE;
667
+ return char;
668
+ case 'b':
669
+ return this.birth;
670
+ case 'B':
671
+ return this.birth.toUpperCase();
464
672
  case 'f':
465
- return this.fullname.firstname.namon;
673
+ return this.first;
466
674
  case 'F':
467
- return this.fullname.firstname.upper();
675
+ return this.first.toUpperCase();
468
676
  case 'l':
469
- return this.fullname.lastname.namon;
677
+ return this.last;
470
678
  case 'L':
471
- return this.fullname.lastname.upper();
679
+ return this.last.toUpperCase();
472
680
  case 'm':
473
- return this.fullname.middlename
474
- .map(n => n.namon).join(index_2.Separator.SPACE);
475
681
  case 'M':
476
- return this.fullname.middlename
477
- .map(n => n.upper()).join(index_2.Separator.SPACE);
682
+ return char === 'm' ? this.middleName().join(' ') : this.middleName().join(' ').toUpperCase();
478
683
  case 'o':
479
684
  case 'O':
480
- const { titling, ending } = this.config;
481
- const pxSep = titling === 'us' ? index_2.Separator.PERIOD : index_2.Separator.EMPTY;
482
- const sxSep = ending !== index_2.Separator.SPACE ? ending : index_2.Separator.EMPTY;
483
- const official = [
484
- this.fullname.prefix ? index_2.Separator.EMPTY.concat(this.fullname.prefix, pxSep) : index_2.Separator.EMPTY,
485
- this.fullname.lastname.upper().concat(index_2.Separator.COMMA),
486
- this.fullname.firstname.tostring(),
487
- this.fullname.middlename.map(n => n.namon).join(index_2.Separator.SPACE).concat(sxSep),
488
- this.fullname.suffix || index_2.Separator.EMPTY,
489
- ].join(index_2.Separator.SPACE).trim();
490
- return c === 'o' ? official : official.toUpperCase();
685
+ const sep = this._config.ending ? ',' : '';
686
+ const names = [];
687
+ if (this.prefix)
688
+ names.push(this.prefix);
689
+ names.push(`${this.last},`.toUpperCase());
690
+ if (this.hasMiddle) {
691
+ names.push(this.first, this.middleName().join(' ') + sep);
692
+ }
693
+ else {
694
+ names.push(this.first + sep);
695
+ }
696
+ if (this.suffix)
697
+ names.push(this.suffix);
698
+ const nama = names.join(' ').trim();
699
+ return char === 'o' ? nama : nama.toUpperCase();
491
700
  case 'p':
492
- return this.fullname.prefix || index_2.Separator.EMPTY;
701
+ return this.prefix;
493
702
  case 'P':
494
- return this.fullname.prefix ? this.fullname.prefix.toUpperCase() : index_2.Separator.EMPTY;
703
+ return (_a = this.prefix) === null || _a === void 0 ? void 0 : _a.toUpperCase();
495
704
  case 's':
496
- return this.fullname.suffix || index_2.Separator.EMPTY;
705
+ return this.suffix;
497
706
  case 'S':
498
- return this.fullname.suffix ? this.fullname.suffix.toUpperCase() : index_2.Separator.EMPTY;
707
+ return (_b = this.suffix) === null || _b === void 0 ? void 0 : _b.toUpperCase();
708
+ case '$f':
709
+ case '$F':
710
+ return this._fullName.firstName.initials()[0];
711
+ case '$l':
712
+ case '$L':
713
+ return this._fullName.lastName.initials()[0];
714
+ case '$m':
715
+ case '$M':
716
+ return this.hasMiddle ? this.middle[0] : undefined;
499
717
  default:
500
- return index_2.Separator.EMPTY;
501
- }
502
- }
503
- /**
504
- * Builds a high qualitty of data using parsers and validators
505
- * @param {string | string[] | Array<Name> | Nama} raw data to parse or
506
- * construct the pieces of the name
507
- */
508
- build(raw) {
509
- if (this.config.parser) {
510
- this.initialize(this.config.parser);
511
- }
512
- else if (typeof raw === 'string') { // check for string type
513
- this.initialize(new index_1.StringParser(raw));
514
- }
515
- else if (Array.isArray(raw) && raw.length) { // check for Array<T>
516
- if (typeof raw[0] === 'string') { // check for Array<string>
517
- for (const key of raw)
518
- if (typeof key !== 'string')
519
- throw new Error(`Cannot parse raw data as array of 'string'`);
520
- this.initialize(new index_1.ArrayStringParser(raw));
521
- }
522
- else if (raw[0] instanceof index_2.Name) { // check for Array<Name>
523
- for (const obj of raw)
524
- if (!(obj instanceof index_2.Name))
525
- throw new Error(`Cannot parse raw data as array of '${index_2.Name.name}'`);
526
- this.initialize(new index_1.ArrayNameParser(raw));
527
- }
528
- else {
529
- // typescript should stop them, but let's be paranoid (for JS developers)
530
- throw new Error(`Cannot parse raw data as arrays that are not of '${index_2.Name.name}' or string`);
531
- }
532
- }
533
- else if (raw instanceof Object) { // check for json object
534
- for (const entry of Object.entries(raw)) { // make sure keys are correct
535
- const key = entry[0], value = entry[1];
536
- if (['firstname', 'lastname', 'middlename', 'prefix', 'suffix'].indexOf(key) === -1)
537
- throw new Error(`Cannot parse raw data as json object that does not contains keys of '${index_2.Namon}'`);
538
- if (typeof value !== 'string') // make sure the values are proper string
539
- throw new Error(`Cannot parse raw data. The key <${key}> should be a 'string' type`);
540
- }
541
- this.initialize(new index_1.NamaParser(raw));
542
- }
543
- else {
544
- // typescript should stop them, but let's be paranoid again (for JS developers)
545
- throw new Error(`Cannot parse raw data. Review the data type expected.`);
718
+ return undefined;
546
719
  }
547
- // paranoid coder mode: on :P
548
- if (!this.config.bypass)
549
- new index_3.FullnameValidator().validate(this.fullname);
550
- this.summary = new index_2.Summary(this.getFullname());
551
720
  }
552
721
  }
553
722
  exports.Namefully = Namefully;
554
- Namefully.prototype.full = Namefully.prototype.getFullname;
555
- Namefully.prototype.fn = Namefully.prototype.getFirstname;
556
- Namefully.prototype.ln = Namefully.prototype.getLastname;
557
- Namefully.prototype.mn = Namefully.prototype.getMiddlenames;
558
- Namefully.prototype.px = Namefully.prototype.getPrefix;
559
- Namefully.prototype.sx = Namefully.prototype.getSuffix;
560
- Namefully.prototype.inits = Namefully.prototype.getInitials;
561
- Namefully.prototype.stats = Namefully.prototype.describe;
562
723
  //# sourceMappingURL=namefully.js.map