@danielhaim/titlecaser 1.2.57 → 1.2.59
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/README.md +52 -29
- package/package.json +3 -3
- package/src/TitleCaser.js +341 -231
- package/src/TitleCaserConsts.js +138 -234
- package/src/TitleCaserUtils.js +830 -601
- package/src/data/brandList.json +118 -0
- package/src/data/businessFinanceLegalTerms.json +28 -0
- package/src/data/eCommerceDigitalTerms.json +7 -0
- package/src/data/globalGeography.json +49 -0
- package/src/data/marketingMediaTerms.json +19 -0
- package/src/data/miscSpecializedTerms.json +6 -0
- package/src/data/techComputingConcepts.json +36 -0
- package/src/data/timeAcademicTerms.json +10 -0
package/src/TitleCaser.js
CHANGED
|
@@ -1,236 +1,346 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
from "./TitleCaserConsts.js";
|
|
2
|
+
commonAbbreviationList,
|
|
3
|
+
correctTitleCasingList,
|
|
4
|
+
correctPhraseCasingList,
|
|
5
|
+
wordReplacementsList,
|
|
6
|
+
} from "./TitleCaserConsts.js";
|
|
8
7
|
|
|
9
8
|
import { TitleCaserUtils } from "./TitleCaserUtils.js";
|
|
10
9
|
|
|
11
10
|
export class TitleCaser {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.wordReplacementsList = wordReplacementsList;
|
|
14
|
+
this.correctPhraseCasingList = correctPhraseCasingList;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
toTitleCase(str) {
|
|
18
|
+
try {
|
|
19
|
+
// If input is empty, throw an error.
|
|
20
|
+
if (str.trim().length === 0) throw new TypeError("Invalid input: input must not be empty.");
|
|
21
|
+
|
|
22
|
+
// If input is not a string, throw an error.
|
|
23
|
+
if (typeof str !== "string") throw new TypeError("Invalid input: input must be a string.");
|
|
24
|
+
|
|
25
|
+
// If options is not an object, throw an error.
|
|
26
|
+
if (typeof this.options !== "undefined" && typeof this.options !== "object")
|
|
27
|
+
throw new TypeError("Invalid options: options must be an object.");
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
style = "ap",
|
|
31
|
+
neverCapitalize = [],
|
|
32
|
+
replaceTermList = this.wordReplacementsList,
|
|
33
|
+
smartQuotes = false, // Set to false by default
|
|
34
|
+
} = this.options;
|
|
35
|
+
|
|
36
|
+
const ignoreList = ["nl2br", ...neverCapitalize];
|
|
37
|
+
const {
|
|
38
|
+
articlesList,
|
|
39
|
+
shortConjunctionsList,
|
|
40
|
+
shortPrepositionsList,
|
|
41
|
+
neverCapitalizedList,
|
|
42
|
+
replaceTerms,
|
|
43
|
+
smartQuotes: mergedSmartQuotes, // Rename for clarity
|
|
44
|
+
} = TitleCaserUtils.getTitleCaseOptions(this.options, commonAbbreviationList, wordReplacementsList);
|
|
45
|
+
|
|
46
|
+
// Prerocess the replaceTerms array to make it easier to search for.
|
|
47
|
+
const replaceTermsArray = replaceTermList.map((term) => Object.keys(term)[0].toLowerCase());
|
|
48
|
+
// Create an object from the replaceTerms array to make it easier to search for.
|
|
49
|
+
const replaceTermObj = Object.fromEntries(
|
|
50
|
+
replaceTermList.map((term) => [Object.keys(term)[0].toLowerCase(), Object.values(term)[0]]),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// console.log(replaceTermsArray);
|
|
54
|
+
// console.log(this.wordReplacementsList);
|
|
55
|
+
|
|
56
|
+
const map = {
|
|
57
|
+
"&": "&",
|
|
58
|
+
"<": "<",
|
|
59
|
+
">": ">",
|
|
60
|
+
// '\u2018': '\u2019', // Smart single quote
|
|
61
|
+
// '\u201C': '\u201D', // Smart double quote
|
|
62
|
+
'"': """,
|
|
63
|
+
"'": "'",
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Remove extra spaces and replace <br> tags with a placeholder.
|
|
67
|
+
let inputString = str.trim();
|
|
68
|
+
|
|
69
|
+
// Replace <br> and <br /> tags with a placeholder.
|
|
70
|
+
inputString = inputString.replace(/<\s*br\s*\/?\s*>/gi, " nl2br ");
|
|
71
|
+
|
|
72
|
+
// Remove extra spaces and replace <br> tags with a placeholder.
|
|
73
|
+
inputString = inputString.replace(/ {2,}/g, (match) => match.slice(0, 1));
|
|
74
|
+
|
|
75
|
+
// Split the string into an array of words.
|
|
76
|
+
const words = inputString.split(" ");
|
|
77
|
+
|
|
78
|
+
const wordsInTitleCase = words.map((word, i) => {
|
|
79
|
+
switch (true) {
|
|
80
|
+
case TitleCaserUtils.isWordAmpersand(word):
|
|
81
|
+
// if the word is an ampersand, return it as is.
|
|
82
|
+
return word;
|
|
83
|
+
case TitleCaserUtils.hasHtmlBreak(word):
|
|
84
|
+
// If the word is a <br> tag, return it as is.
|
|
85
|
+
return word;
|
|
86
|
+
case TitleCaserUtils.isWordIgnored(word, ignoreList):
|
|
87
|
+
// If the word is in the ignore list, return it as is.
|
|
88
|
+
return word;
|
|
89
|
+
case replaceTermsArray.includes(word.toLowerCase()):
|
|
90
|
+
// If the word is in the replaceTerms array, return the replacement.
|
|
91
|
+
return replaceTermObj[word.toLowerCase()];
|
|
92
|
+
case TitleCaserUtils.isWordInArray(word, correctTitleCasingList):
|
|
93
|
+
// If the word is in the correctTitleCasingList array, return the correct casing.
|
|
94
|
+
return TitleCaserUtils.correctTerm(word, correctTitleCasingList);
|
|
95
|
+
case TitleCaserUtils.hasHyphen(word):
|
|
96
|
+
// Separate the base word from any trailing punctuation
|
|
97
|
+
const baseWord = word.replace(/[\W_]+$/, "");
|
|
98
|
+
const trailingPunctuation = word.slice(baseWord.length);
|
|
99
|
+
|
|
100
|
+
// Split the base word at the hyphen and process each part
|
|
101
|
+
const parts = baseWord.split("-");
|
|
102
|
+
const replacedParts = parts.map((part) => {
|
|
103
|
+
const lowerCasePart = part.toLowerCase();
|
|
104
|
+
if (replaceTermsArray.includes(lowerCasePart)) {
|
|
105
|
+
return replaceTermObj[lowerCasePart];
|
|
106
|
+
}
|
|
107
|
+
return part;
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Determine if any part was replaced
|
|
111
|
+
const isReplaced = !replacedParts.every((part, index) => part === parts[index]);
|
|
112
|
+
|
|
113
|
+
// Reassemble the word with the hyphen, reattach trailing punctuation, and return
|
|
114
|
+
return (
|
|
115
|
+
(isReplaced ? replacedParts.join("-") : TitleCaserUtils.correctTermHyphenated(word, style)) +
|
|
116
|
+
trailingPunctuation
|
|
117
|
+
);
|
|
118
|
+
case TitleCaserUtils.hasSuffix(word, style):
|
|
119
|
+
// If the word has a suffix, return the correct casing.
|
|
120
|
+
return TitleCaserUtils.correctSuffix(word, correctTitleCasingList);
|
|
121
|
+
case TitleCaserUtils.hasUppercaseIntentional(word):
|
|
122
|
+
// If the word has an intentional uppercase letter, return the correct casing.
|
|
123
|
+
return word;
|
|
124
|
+
case TitleCaserUtils.isShortWord(word, style) && i !== 0:
|
|
125
|
+
// If the word is a short word, return the correct casing.
|
|
126
|
+
return i > 0 && TitleCaserUtils.endsWithSymbol(words[i - 1], [":", "?", "!", "."])
|
|
127
|
+
? word.charAt(0).toUpperCase() + word.slice(1)
|
|
128
|
+
: word.toLowerCase();
|
|
129
|
+
case TitleCaserUtils.endsWithSymbol(word):
|
|
130
|
+
// console.log("ends with symbol: ", word);
|
|
131
|
+
// If the word ends with a symbol, return the correct casing.
|
|
132
|
+
const splitWord = word.split(/([.,\/#!$%\^&\*;:{}=\-_`~()?])/g);
|
|
133
|
+
// console.log(splitWord);
|
|
134
|
+
// Process each part for correct casing
|
|
135
|
+
const processedWords = splitWord.map((part) => {
|
|
136
|
+
// Check if part is a symbol
|
|
137
|
+
if (TitleCaserUtils.endsWithSymbol(part)) {
|
|
138
|
+
// console.log(part);
|
|
139
|
+
return part;
|
|
140
|
+
} else {
|
|
141
|
+
// If it's a word, process it for correct casing
|
|
142
|
+
if (TitleCaserUtils.isWordInArray(part, correctTitleCasingList)) {
|
|
143
|
+
return TitleCaserUtils.correctTerm(part, correctTitleCasingList);
|
|
144
|
+
} else if (replaceTermsArray.includes(part)) {
|
|
145
|
+
return replaceTermObj[part];
|
|
146
|
+
} else {
|
|
147
|
+
// Apply the correct casing for words not in the list
|
|
148
|
+
return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Join the processed words and return them.
|
|
154
|
+
return processedWords.join("");
|
|
155
|
+
case TitleCaserUtils.startsWithSymbol(word):
|
|
156
|
+
// If the word starts with a symbol, return the correct casing.
|
|
157
|
+
return !TitleCaserUtils.isWordInArray(word, correctTitleCasingList)
|
|
158
|
+
? word
|
|
159
|
+
: TitleCaserUtils.correctTerm(word);
|
|
160
|
+
case TitleCaserUtils.hasRomanNumeral(word):
|
|
161
|
+
// If the word has a roman numeral, return the correct casing.
|
|
162
|
+
return word.toUpperCase();
|
|
163
|
+
case TitleCaserUtils.hasNumbers(word):
|
|
164
|
+
// If the word has numbers, return the correct casing.
|
|
165
|
+
return word;
|
|
166
|
+
default:
|
|
167
|
+
// Default to returning the word with the correct casing.
|
|
168
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Join the words in the array into a string.
|
|
173
|
+
inputString = wordsInTitleCase.join(" ");
|
|
174
|
+
|
|
175
|
+
for (const [phrase, replacement] of Object.entries(this.correctPhraseCasingList)) {
|
|
176
|
+
// Create a regular expression for case-insensitive matching of the phrase
|
|
177
|
+
const regex = new RegExp(phrase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
178
|
+
|
|
179
|
+
// Replace the phrase in the input string with its corresponding replacement
|
|
180
|
+
inputString = inputString.replace(regex, replacement);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Replace the nl2br placeholder with <br> tags.
|
|
184
|
+
inputString = inputString.replace(/nl2br/gi, "<br>");
|
|
185
|
+
|
|
186
|
+
// Convert quotation marks to smart quotes if enabled
|
|
187
|
+
// Refer to: https://github.com/danielhaim1/TitleCaser/issues/4
|
|
188
|
+
if (smartQuotes) {
|
|
189
|
+
inputString = TitleCaserUtils.convertQuotesToCurly(inputString);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const newWords = inputString.split(" ");
|
|
193
|
+
|
|
194
|
+
for (let i = 0; i < newWords.length; i++) {
|
|
195
|
+
const prevWord = i > 0 ? newWords[i - 1] : null;
|
|
196
|
+
let currentWord = newWords[i];
|
|
197
|
+
const nextWord = i < newWords.length - 1 ? newWords[i + 1] : null;
|
|
198
|
+
|
|
199
|
+
// Capture punctuation at the end of the word
|
|
200
|
+
const punctuationMatch = currentWord.match(/[.,!?;:]+$/);
|
|
201
|
+
let punctuation = "";
|
|
202
|
+
|
|
203
|
+
if (punctuationMatch) {
|
|
204
|
+
punctuation = punctuationMatch[0];
|
|
205
|
+
currentWord = currentWord.replace(/[.,!?;:]+$/, ""); // Remove punctuation at the end
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
let cleanCurrentWord = currentWord.replace(/[.,!?;:]/g, "");
|
|
209
|
+
let cleanNextWord = nextWord ? nextWord.replace(/[.,!?;:]/g, "") : nextWord;
|
|
210
|
+
|
|
211
|
+
if (cleanCurrentWord === "Us") {
|
|
212
|
+
if (TitleCaserUtils.isAcronym(currentWord, prevWord, nextWord)) {
|
|
213
|
+
if (punctuation === "") {
|
|
214
|
+
newWords[i] = "US";
|
|
215
|
+
} else {
|
|
216
|
+
newWords[i] = "US" + punctuation;
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
if (punctuation === "") {
|
|
220
|
+
newWords[i] = "Us";
|
|
221
|
+
} else {
|
|
222
|
+
newWords[i] = "Us" + punctuation;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
inputString = newWords.join(" ");
|
|
229
|
+
|
|
230
|
+
return inputString;
|
|
231
|
+
} catch (error) {
|
|
232
|
+
throw new Error(error);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
setReplaceTerms(terms) {
|
|
237
|
+
if (!Array.isArray(terms)) {
|
|
238
|
+
throw new TypeError("Invalid argument: setReplaceTerms must be an array of objects.");
|
|
239
|
+
}
|
|
240
|
+
// Iterate over each term-replacement object in the array
|
|
241
|
+
terms.forEach((termObject) => {
|
|
242
|
+
if (termObject && typeof termObject === "object") {
|
|
243
|
+
const [term, replacement] = Object.entries(termObject)[0];
|
|
244
|
+
const index = this.wordReplacementsList.findIndex((obj) => obj.hasOwnProperty(term));
|
|
245
|
+
if (index !== -1) {
|
|
246
|
+
// Update the existing term
|
|
247
|
+
this.wordReplacementsList[index][term] = replacement;
|
|
248
|
+
} else {
|
|
249
|
+
// Add the new term
|
|
250
|
+
this.wordReplacementsList.push({ [term]: replacement });
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
// Handle non-object entries in the array, if required
|
|
254
|
+
console.warn("Invalid entry in terms array:", termObject);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
259
|
+
|
|
260
|
+
// Log the updated wordReplacementsList array
|
|
261
|
+
// console.log(this.wordReplacementsList);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
addReplaceTerm(term, replacement) {
|
|
265
|
+
if (typeof term !== "string" || typeof replacement !== "string") {
|
|
266
|
+
throw new TypeError("Invalid argument: term and replacement must be strings.");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (index !== -1) {
|
|
270
|
+
// If the term already exists in the array, update the replacement value
|
|
271
|
+
this.wordReplacementsList[index][term] = replacement;
|
|
272
|
+
} else {
|
|
273
|
+
// If the term doesn't exist in the array, add a new object with the term and replacement
|
|
274
|
+
this.wordReplacementsList.push({ [term]: replacement });
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Update the replace terms option
|
|
278
|
+
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
removeReplaceTerm(term) {
|
|
282
|
+
if (typeof term !== "string") {
|
|
283
|
+
throw new TypeError("Invalid argument: term must be a string.");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Find the index of the term in the wordReplacementsList array
|
|
287
|
+
const index = this.wordReplacementsList.findIndex((obj) => Object.keys(obj)[0] === term);
|
|
288
|
+
|
|
289
|
+
// If the term is not found in the array, throw an error
|
|
290
|
+
if (index === -1) {
|
|
291
|
+
throw new Error(`Term '${term}' not found in word replacements list.`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Remove the term from the array
|
|
295
|
+
this.wordReplacementsList.splice(index, 1);
|
|
296
|
+
|
|
297
|
+
// Update the replace terms option
|
|
298
|
+
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
299
|
+
|
|
300
|
+
// Log the updated wordReplacementsList array
|
|
301
|
+
// console.log(this.wordReplacementsList);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
addExactPhraseReplacements(newPhrases) {
|
|
305
|
+
if (!Array.isArray(newPhrases)) {
|
|
306
|
+
throw new TypeError("Invalid argument: newPhrases must be an array.");
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
newPhrases.forEach((item) => {
|
|
310
|
+
// If the item is an object with a single key-value pair
|
|
311
|
+
if (typeof item === "object" && !Array.isArray(item) && Object.keys(item).length === 1) {
|
|
312
|
+
const key = Object.keys(item)[0];
|
|
313
|
+
const value = item[key];
|
|
314
|
+
if (typeof key === "string" && typeof value === "string") {
|
|
315
|
+
this.correctPhraseCasingList[key] = value;
|
|
316
|
+
} else {
|
|
317
|
+
throw new TypeError("Invalid argument: Each key-value pair must contain strings.");
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
// If the item is already a key-value pair
|
|
321
|
+
else if (typeof item === "object" && !Array.isArray(item)) {
|
|
322
|
+
Object.entries(item).forEach(([key, value]) => {
|
|
323
|
+
if (typeof key === "string" && typeof value === "string") {
|
|
324
|
+
this.correctPhraseCasingList[key] = value;
|
|
325
|
+
} else {
|
|
326
|
+
throw new TypeError("Invalid argument: Each key-value pair must contain strings.");
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
// Invalid format
|
|
331
|
+
else {
|
|
332
|
+
throw new TypeError("Invalid argument: Each item must be an object with a single key-value pair.");
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// console.log(this.correctPhraseCasingList);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
setStyle(style) {
|
|
340
|
+
if (typeof style !== "string") {
|
|
341
|
+
throw new TypeError("Invalid argument: style must be a string.");
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
this.options.style = style;
|
|
345
|
+
}
|
|
346
|
+
}
|