@danielhaim/titlecaser 1.2.56 → 1.2.58
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 +48 -26
- package/package.json +3 -3
- package/src/TitleCaser.js +267 -231
- package/src/TitleCaserConsts.js +134 -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/README.md
CHANGED
|
@@ -292,43 +292,65 @@ $ npm run test
|
|
|
292
292
|
```
|
|
293
293
|
|
|
294
294
|
```bash
|
|
295
|
+
Testing Acronym/Pronoun of Alpha2/3 Country Codes
|
|
296
|
+
✓ Capitalizes country code "US" correctly in a geopolitical context (4 ms)
|
|
297
|
+
✓ Does not capitalize "us" when used as a pronoun (2 ms)
|
|
298
|
+
✓ Capitalizes country code "UK" with preceding indicator and trailing comma (2 ms)
|
|
299
|
+
✓ Handles multiple instances of country codes and pronouns (2 ms)
|
|
300
|
+
✓ Does not capitalize "us" when used in common phrases (2 ms)
|
|
301
|
+
✓ Capitalizes "USA" in a formal context (1 ms)
|
|
302
|
+
✓ Capitalizes "US" before a government-related word (1 ms)
|
|
303
|
+
✓ Does not capitalize "us" before a government-related word (1 ms)
|
|
304
|
+
✓ Capitalizes "UK" with preceding indicator before a government-related word (2 ms)
|
|
305
|
+
✓ Handles multiple instances of country codes and pronouns before government-related words (1 ms)
|
|
306
|
+
✓ Capitalizes "US" before a military-related word (1 ms)
|
|
307
|
+
✓ Does not capitalize "us" before a military-related word (1 ms)
|
|
308
|
+
✓ Capitalizes "UK" with preceding indicator before a territory-related word (2 ms)
|
|
309
|
+
✓ Handles multiple instances of country codes and pronouns before talks-related words (3 ms)
|
|
310
|
+
✓ Does not capitalize "us" before a talks-related word (1 ms)
|
|
311
|
+
✓ Capitalizes "USA" in a formal context before a bill-related word (1 ms)
|
|
312
|
+
✓ Handles multiple instances of country codes and pronouns before a bill-related word (2 ms)
|
|
313
|
+
|
|
295
314
|
Test Basic Options
|
|
296
315
|
✓ Default title case conversion
|
|
297
|
-
✓ Customized title case conversion
|
|
298
|
-
✓ AP-style title case conversion with replacements
|
|
299
|
-
✓
|
|
300
|
-
✓
|
|
316
|
+
✓ Customized title case conversion (1 ms)
|
|
317
|
+
✓ AP-style title case conversion with replacements (3 ms)
|
|
318
|
+
✓ Testing Word Replacement (Kellogs -> Kellogg\'s)
|
|
319
|
+
✓ AP-style title case conversion with replacements (1 ms)
|
|
320
|
+
✓ Capitalize suffix word in sentence (1 ms)
|
|
301
321
|
|
|
302
322
|
Test Methods
|
|
303
|
-
✓ removeReplaceTerm
|
|
304
|
-
✓ setReplaceTerms
|
|
323
|
+
✓ removeReplaceTerm (1 ms)
|
|
324
|
+
✓ setReplaceTerms (1 ms)
|
|
305
325
|
|
|
306
326
|
Test Variation Stability
|
|
307
|
-
✓ Hyphenated, colon, and short word replacements
|
|
308
327
|
✓ Capitalization and word replacements
|
|
309
|
-
✓ AP-style title case with possessive and colon
|
|
328
|
+
✓ AP-style title case with possessive and colon (1 ms)
|
|
310
329
|
✓ AP-style title case with lowercase back/front-end terms
|
|
311
|
-
✓ Chicago style title case with comparison and colon
|
|
312
|
-
✓ APA style title case with colon
|
|
313
|
-
✓ Wikipedia style title case with acronym and hyphen
|
|
314
|
-
✓
|
|
330
|
+
✓ Chicago style title case with comparison and colon (1 ms)
|
|
331
|
+
✓ APA style title case with colon (2 ms)
|
|
332
|
+
✓ Wikipedia style title case with acronym and hyphen (1 ms)
|
|
333
|
+
✓ Hyphenated, colon, and short word replacements (2 ms)
|
|
334
|
+
✓ I Love Connecting with My Online Friends, but Sometimes I Prefer to Hang Out with My Friends IRL (2 ms)
|
|
335
|
+
✓ Test Smart Quotes (1 ms)
|
|
336
|
+
✓ Wikipedia style capitalization test with special term and colon (1 ms)
|
|
337
|
+
✓ APA style title case with colon and apostrophe (2 ms)
|
|
315
338
|
✓ Chicago style title case with custom term replacements
|
|
316
|
-
✓ AP-style capitalization test with special terms and colon
|
|
317
|
-
✓ NYT-style capitalization test with special terms and colon
|
|
318
|
-
✓ APA style capitalization test with short conjunction terms and colon
|
|
319
|
-
✓ Correct phrase casing list testing
|
|
320
|
-
✓ Wikipedia style capitalization test with special term and colon
|
|
339
|
+
✓ AP-style capitalization test with special terms and colon (1 ms)
|
|
340
|
+
✓ NYT-style capitalization test with special terms and colon (1 ms)
|
|
341
|
+
✓ APA style capitalization test with short conjunction terms and colon (2 ms)
|
|
342
|
+
✓ Correct phrase casing list testing (1 ms)
|
|
321
343
|
|
|
322
344
|
Test Reserved Words
|
|
323
|
-
✓
|
|
324
|
-
✓
|
|
325
|
-
✓
|
|
326
|
-
✓
|
|
327
|
-
✓
|
|
328
|
-
✓
|
|
329
|
-
✓ HTML line break nl2br
|
|
330
|
-
✓ HTML line break nl2br
|
|
331
|
-
✓ Ampersand in a sentence should return & and not &Amp;
|
|
345
|
+
✓ Title case transformation for a single reserved word
|
|
346
|
+
✓ Title case transformation for a sentence with a reserved word and colon (1 ms)
|
|
347
|
+
✓ Title case transformation for a reserved word with a possessive form (1 ms)
|
|
348
|
+
✓ Title case transformation for specific brand names
|
|
349
|
+
✓ Title case transformation for a sentence with HTML line break (nl2br) using <br> tag (1 ms)
|
|
350
|
+
✓ Title case transformation for a sentence with untrimmed white spaces
|
|
351
|
+
✓ Title case transformation for a sentence with HTML line break (nl2br) using <br> tag (1 ms)
|
|
352
|
+
✓ Title case transformation for a sentence with HTML line break (nl2br) without space after colon using <br> tag (1 ms)
|
|
353
|
+
✓ Ampersand in a sentence should return & and not &Amp; (1 ms)
|
|
332
354
|
✓ Untrimmed white spaces
|
|
333
355
|
```
|
|
334
356
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielhaim/titlecaser",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.58",
|
|
4
4
|
"description": "Converts a string to title case with multiple style options, ability to ignore certain words, and handle acronyms",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"title case",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"jest-environment-jsdom": "^29.5.0",
|
|
68
68
|
"jest-environment-puppeteer": "^9.0.0",
|
|
69
69
|
"jest-puppeteer": "^9.0.0",
|
|
70
|
-
"puppeteer": "^
|
|
71
|
-
"puppeteer-core": "^
|
|
70
|
+
"puppeteer": "^21.5.2",
|
|
71
|
+
"puppeteer-core": "^21.5.2",
|
|
72
72
|
"terser-webpack-plugin": "^5.3.9",
|
|
73
73
|
"webpack": "^5.86.0",
|
|
74
74
|
"webpack-cli": "^5.1.4",
|
package/src/TitleCaser.js
CHANGED
|
@@ -1,236 +1,272 @@
|
|
|
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
|
+
}
|
|
15
|
+
|
|
16
|
+
toTitleCase(str) {
|
|
17
|
+
try {
|
|
18
|
+
// If input is empty, throw an error.
|
|
19
|
+
if (str.trim().length === 0) throw new TypeError("Invalid input: input must not be empty.");
|
|
20
|
+
|
|
21
|
+
// If input is not a string, throw an error.
|
|
22
|
+
if (typeof str !== "string") throw new TypeError("Invalid input: input must be a string.");
|
|
23
|
+
|
|
24
|
+
// If options is not an object, throw an error.
|
|
25
|
+
if (typeof this.options !== "undefined" && typeof this.options !== "object")
|
|
26
|
+
throw new TypeError("Invalid options: options must be an object.");
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
style = "ap",
|
|
30
|
+
neverCapitalize = [],
|
|
31
|
+
replaceTermList = this.wordReplacementsList,
|
|
32
|
+
smartQuotes = false, // Set to false by default
|
|
33
|
+
} = this.options;
|
|
34
|
+
|
|
35
|
+
const ignoreList = ["nl2br", ...neverCapitalize];
|
|
36
|
+
const {
|
|
37
|
+
articlesList,
|
|
38
|
+
shortConjunctionsList,
|
|
39
|
+
shortPrepositionsList,
|
|
40
|
+
neverCapitalizedList,
|
|
41
|
+
replaceTerms,
|
|
42
|
+
smartQuotes: mergedSmartQuotes, // Rename for clarity
|
|
43
|
+
} = TitleCaserUtils.getTitleCaseOptions(this.options, commonAbbreviationList, wordReplacementsList);
|
|
44
|
+
|
|
45
|
+
// Prerocess the replaceTerms array to make it easier to search for.
|
|
46
|
+
const replaceTermsArray = replaceTermList.map((term) => Object.keys(term)[0].toLowerCase());
|
|
47
|
+
// Create an object from the replaceTerms array to make it easier to search for.
|
|
48
|
+
const replaceTermObj = Object.fromEntries(
|
|
49
|
+
replaceTermList.map((term) => [Object.keys(term)[0].toLowerCase(), Object.values(term)[0]]),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const map = {
|
|
53
|
+
"&": "&",
|
|
54
|
+
"<": "<",
|
|
55
|
+
">": ">",
|
|
56
|
+
// '\u2018': '\u2019', // Smart single quote
|
|
57
|
+
// '\u201C': '\u201D', // Smart double quote
|
|
58
|
+
'"': """,
|
|
59
|
+
"'": "'",
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Remove extra spaces and replace <br> tags with a placeholder.
|
|
63
|
+
let inputString = str.trim();
|
|
64
|
+
|
|
65
|
+
// Replace <br> and <br /> tags with a placeholder.
|
|
66
|
+
inputString = inputString.replace(/<\s*br\s*\/?\s*>/gi, " nl2br ");
|
|
67
|
+
|
|
68
|
+
// Remove extra spaces and replace <br> tags with a placeholder.
|
|
69
|
+
inputString = inputString.replace(/ {2,}/g, (match) => match.slice(0, 1));
|
|
70
|
+
|
|
71
|
+
// Split the string into an array of words.
|
|
72
|
+
const words = inputString.split(" ");
|
|
73
|
+
|
|
74
|
+
const wordsInTitleCase = words.map((word, i) => {
|
|
75
|
+
switch (true) {
|
|
76
|
+
case TitleCaserUtils.isWordAmpersand(word):
|
|
77
|
+
// if the word is an ampersand, return it as is.
|
|
78
|
+
return word;
|
|
79
|
+
case TitleCaserUtils.hasHtmlBreak(word):
|
|
80
|
+
// If the word is a <br> tag, return it as is.
|
|
81
|
+
return word;
|
|
82
|
+
case TitleCaserUtils.isWordIgnored(word, ignoreList):
|
|
83
|
+
// If the word is in the ignore list, return it as is.
|
|
84
|
+
return word;
|
|
85
|
+
case replaceTermsArray.includes(word.toLowerCase()):
|
|
86
|
+
// If the word is in the replaceTerms array, return the replacement.
|
|
87
|
+
return replaceTermObj[word.toLowerCase()];
|
|
88
|
+
case TitleCaserUtils.isWordInArray(word, correctTitleCasingList):
|
|
89
|
+
// If the word is in the correctTitleCasingList array, return the correct casing.
|
|
90
|
+
return TitleCaserUtils.correctTerm(word, correctTitleCasingList);
|
|
91
|
+
case TitleCaserUtils.hasHyphen(word):
|
|
92
|
+
return TitleCaserUtils.correctTermHyphenated(word, style);
|
|
93
|
+
case TitleCaserUtils.hasSuffix(word, style):
|
|
94
|
+
// If the word has a suffix, return the correct casing.
|
|
95
|
+
return TitleCaserUtils.correctSuffix(word, correctTitleCasingList);
|
|
96
|
+
case TitleCaserUtils.hasUppercaseIntentional(word):
|
|
97
|
+
// If the word has an intentional uppercase letter, return the correct casing.
|
|
98
|
+
return word;
|
|
99
|
+
case TitleCaserUtils.isShortWord(word, style) && i !== 0:
|
|
100
|
+
// If the word is a short word, return the correct casing.
|
|
101
|
+
return i > 0 && TitleCaserUtils.endsWithSymbol(words[i - 1], [":", "?", "!", "."])
|
|
102
|
+
? word.charAt(0).toUpperCase() + word.slice(1)
|
|
103
|
+
: word.toLowerCase();
|
|
104
|
+
case TitleCaserUtils.endsWithSymbol(word):
|
|
105
|
+
// If the word ends with a symbol, return the correct casing.
|
|
106
|
+
const splitWord = word.split(/([.,\/#!$%\^&\*;:{}=\-_`~()])/g);
|
|
107
|
+
const processedWords = splitWord.map((splitWord, j) => {
|
|
108
|
+
// If the word is in the correctTitleCasingList array, return the correct casing.
|
|
109
|
+
if (TitleCaserUtils.isWordInArray(splitWord, correctTitleCasingList))
|
|
110
|
+
return TitleCaserUtils.correctTerm(splitWord, correctTitleCasingList);
|
|
111
|
+
// Else return the word with the correct casing.
|
|
112
|
+
else
|
|
113
|
+
return j > 0 && TitleCaserUtils.endsWithSymbol(splitWord)
|
|
114
|
+
? splitWord.charAt(0).toUpperCase() + splitWord.slice(1)
|
|
115
|
+
: splitWord.charAt(0).toUpperCase() + splitWord.slice(1);
|
|
116
|
+
});
|
|
117
|
+
// Join the processed words and return them.
|
|
118
|
+
return processedWords.join("");
|
|
119
|
+
case TitleCaserUtils.startsWithSymbol(word):
|
|
120
|
+
// If the word starts with a symbol, return the correct casing.
|
|
121
|
+
return !TitleCaserUtils.isWordInArray(word, correctTitleCasingList)
|
|
122
|
+
? word
|
|
123
|
+
: TitleCaserUtils.correctTerm(word);
|
|
124
|
+
case TitleCaserUtils.hasRomanNumeral(word):
|
|
125
|
+
// If the word has a roman numeral, return the correct casing.
|
|
126
|
+
return word.toUpperCase();
|
|
127
|
+
case TitleCaserUtils.hasNumbers(word):
|
|
128
|
+
// If the word has numbers, return the correct casing.
|
|
129
|
+
return word;
|
|
130
|
+
default:
|
|
131
|
+
// Default to returning the word with the correct casing.
|
|
132
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Join the words in the array into a string.
|
|
137
|
+
inputString = wordsInTitleCase.join(" ");
|
|
138
|
+
|
|
139
|
+
for (const phrase of correctPhraseCasingList) {
|
|
140
|
+
// If the phrase is in the input string, replace it with the correct casing.
|
|
141
|
+
if (inputString.toLowerCase().includes(phrase.toLowerCase())) {
|
|
142
|
+
inputString = inputString.replace(new RegExp(phrase, "gi"), phrase);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Replace the nl2br placeholder with <br> tags.
|
|
147
|
+
inputString = inputString.replace(/nl2br/gi, "<br>");
|
|
148
|
+
|
|
149
|
+
// Convert quotation marks to smart quotes if enabled
|
|
150
|
+
// Refer to: https://github.com/danielhaim1/TitleCaser/issues/4
|
|
151
|
+
if (smartQuotes) {
|
|
152
|
+
inputString = TitleCaserUtils.convertQuotesToCurly(inputString);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const newWords = inputString.split(" ");
|
|
156
|
+
|
|
157
|
+
for (let i = 0; i < newWords.length; i++) {
|
|
158
|
+
const prevWord = i > 0 ? newWords[i - 1] : null;
|
|
159
|
+
let currentWord = newWords[i];
|
|
160
|
+
const nextWord = i < newWords.length - 1 ? newWords[i + 1] : null;
|
|
161
|
+
|
|
162
|
+
// Capture punctuation at the end of the word
|
|
163
|
+
const punctuationMatch = currentWord.match(/[.,!?;:]+$/);
|
|
164
|
+
let punctuation = "";
|
|
165
|
+
|
|
166
|
+
if (punctuationMatch) {
|
|
167
|
+
punctuation = punctuationMatch[0];
|
|
168
|
+
currentWord = currentWord.replace(/[.,!?;:]+$/, ""); // Remove punctuation at the end
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
let cleanCurrentWord = currentWord.replace(/[.,!?;:]/g, "");
|
|
172
|
+
let cleanNextWord = nextWord ? nextWord.replace(/[.,!?;:]/g, "") : nextWord;
|
|
173
|
+
|
|
174
|
+
if (cleanCurrentWord === "Us") {
|
|
175
|
+
if (TitleCaserUtils.isAcronym(currentWord, prevWord, nextWord)) {
|
|
176
|
+
if (punctuation === "") {
|
|
177
|
+
newWords[i] = "US";
|
|
178
|
+
} else {
|
|
179
|
+
newWords[i] = "US" + punctuation;
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
if (punctuation === "") {
|
|
183
|
+
newWords[i] = "Us";
|
|
184
|
+
} else {
|
|
185
|
+
newWords[i] = "Us" + punctuation;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
inputString = newWords.join(" ");
|
|
192
|
+
|
|
193
|
+
return inputString;
|
|
194
|
+
} catch (error) {
|
|
195
|
+
throw new Error(error);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
setReplaceTerms(terms) {
|
|
200
|
+
if (typeof terms !== "object") {
|
|
201
|
+
throw new TypeError("Invalid argument: replace terms must be an object.");
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Add the new replace terms to the wordReplacementsList array
|
|
205
|
+
Object.entries(terms).forEach(([term, replacement]) => {
|
|
206
|
+
const index = wordReplacementsList.findIndex((obj) => obj[term]);
|
|
207
|
+
if (index !== -1) {
|
|
208
|
+
// If the term already exists in the array, update the replacement value
|
|
209
|
+
wordReplacementsList[index][term] = replacement;
|
|
210
|
+
} else {
|
|
211
|
+
// If the term doesn't exist in the array, add a new object with the term and replacement
|
|
212
|
+
wordReplacementsList.push({ [term]: replacement });
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Log the updated wordReplacementsList array
|
|
217
|
+
// console.log(wordReplacementsList);
|
|
218
|
+
|
|
219
|
+
// Update the replace terms option
|
|
220
|
+
this.options.wordReplacementsList = wordReplacementsList;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
addReplaceTerm(term, replacement) {
|
|
224
|
+
if (typeof term !== "string" || typeof replacement !== "string") {
|
|
225
|
+
throw new TypeError("Invalid argument: term and replacement must be strings.");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const index = this.wordReplacementsList.findIndex((obj) => obj[term]);
|
|
229
|
+
|
|
230
|
+
if (index !== -1) {
|
|
231
|
+
// If the term already exists in the array, update the replacement value
|
|
232
|
+
this.wordReplacementsList[index][term] = replacement;
|
|
233
|
+
} else {
|
|
234
|
+
// If the term doesn't exist in the array, add a new object with the term and replacement
|
|
235
|
+
this.wordReplacementsList.push({ [term]: replacement });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Update the replace terms option
|
|
239
|
+
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
removeReplaceTerm(term) {
|
|
243
|
+
if (typeof term !== "string") {
|
|
244
|
+
throw new TypeError("Invalid argument: term must be a string.");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Find the index of the term in the wordReplacementsList array
|
|
248
|
+
const index = this.wordReplacementsList.findIndex((obj) => Object.keys(obj)[0] === term);
|
|
249
|
+
|
|
250
|
+
// If the term is not found in the array, throw an error
|
|
251
|
+
if (index === -1) {
|
|
252
|
+
throw new Error(`Term '${term}' not found in word replacements list.`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Remove the term from the array
|
|
256
|
+
this.wordReplacementsList.splice(index, 1);
|
|
257
|
+
|
|
258
|
+
// Log the updated wordReplacementsList array
|
|
259
|
+
// console.log(this.wordReplacementsList);
|
|
260
|
+
|
|
261
|
+
// Update the replace terms option
|
|
262
|
+
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
setStyle(style) {
|
|
266
|
+
if (typeof style !== "string") {
|
|
267
|
+
throw new TypeError("Invalid argument: style must be a string.");
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
this.options.style = style;
|
|
271
|
+
}
|
|
272
|
+
}
|