@danielhaim/titlecaser 1.2.58 → 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 +4 -3
- package/package.json +1 -1
- package/src/TitleCaser.js +109 -35
- package/src/TitleCaserConsts.js +5 -1
package/README.md
CHANGED
|
@@ -145,9 +145,10 @@ The `{options}` parameter is an object that contains the settings for the conver
|
|
|
145
145
|
|
|
146
146
|
## Methods
|
|
147
147
|
|
|
148
|
-
- `setReplaceTerms(terms
|
|
149
|
-
- `removeReplaceTerm(term
|
|
150
|
-
- `addReplaceTerm(term
|
|
148
|
+
- `setReplaceTerms(terms)`: Updates the `wordReplacementsList` with new term-replacement pairs. It accepts an array of objects, each containing a single key-value pair representing the term and its replacement.
|
|
149
|
+
- `removeReplaceTerm(term)`: Removes a replaced term from the `wordReplacementsList` array in the option object of the `TitleCaser` instance. Throws an error if the term is not found in the array, otherwise removes it from the array and updates the option object.
|
|
150
|
+
- `addReplaceTerm(term, replacement)`: Adds a single term-replacement pair to the `wordReplacementsList`. If the term already exists, it updates the replacement value.
|
|
151
|
+
- `addExactPhraseReplacements(newPhrases)` - This method allows adding an array of exact phrase replacements to the `TitleCaser` class. Each item in the array should be an object with a single key-value pair, where the key is the phrase to be replaced and the value is the desired replacement.
|
|
151
152
|
- `setStyle(style: string)`: Sets the style option in the object of the TitleCaser instance. The method takes a string argument style that specifies the style to use for the title casing. If the argument is not a string, the method throws a TypeError. Otherwise, it updates the style option in the object.
|
|
152
153
|
- `smartQuotes(smartQuotes: boolean)`: Specifies whether to replace straight quotes with smart quotes during title casing. Provide a boolean argument smartQuotes to enable or disable this feature.
|
|
153
154
|
|
package/package.json
CHANGED
package/src/TitleCaser.js
CHANGED
|
@@ -11,6 +11,7 @@ export class TitleCaser {
|
|
|
11
11
|
constructor(options = {}) {
|
|
12
12
|
this.options = options;
|
|
13
13
|
this.wordReplacementsList = wordReplacementsList;
|
|
14
|
+
this.correctPhraseCasingList = correctPhraseCasingList;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
toTitleCase(str) {
|
|
@@ -49,6 +50,9 @@ export class TitleCaser {
|
|
|
49
50
|
replaceTermList.map((term) => [Object.keys(term)[0].toLowerCase(), Object.values(term)[0]]),
|
|
50
51
|
);
|
|
51
52
|
|
|
53
|
+
// console.log(replaceTermsArray);
|
|
54
|
+
// console.log(this.wordReplacementsList);
|
|
55
|
+
|
|
52
56
|
const map = {
|
|
53
57
|
"&": "&",
|
|
54
58
|
"<": "<",
|
|
@@ -89,7 +93,28 @@ export class TitleCaser {
|
|
|
89
93
|
// If the word is in the correctTitleCasingList array, return the correct casing.
|
|
90
94
|
return TitleCaserUtils.correctTerm(word, correctTitleCasingList);
|
|
91
95
|
case TitleCaserUtils.hasHyphen(word):
|
|
92
|
-
|
|
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
|
+
);
|
|
93
118
|
case TitleCaserUtils.hasSuffix(word, style):
|
|
94
119
|
// If the word has a suffix, return the correct casing.
|
|
95
120
|
return TitleCaserUtils.correctSuffix(word, correctTitleCasingList);
|
|
@@ -102,18 +127,29 @@ export class TitleCaser {
|
|
|
102
127
|
? word.charAt(0).toUpperCase() + word.slice(1)
|
|
103
128
|
: word.toLowerCase();
|
|
104
129
|
case TitleCaserUtils.endsWithSymbol(word):
|
|
130
|
+
// console.log("ends with symbol: ", word);
|
|
105
131
|
// If the word ends with a symbol, return the correct casing.
|
|
106
|
-
const splitWord = word.split(/([.,\/#!$%\^&\*;:{}=\-_`~()])/g);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return
|
|
114
|
-
|
|
115
|
-
|
|
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
|
+
}
|
|
116
151
|
});
|
|
152
|
+
|
|
117
153
|
// Join the processed words and return them.
|
|
118
154
|
return processedWords.join("");
|
|
119
155
|
case TitleCaserUtils.startsWithSymbol(word):
|
|
@@ -136,11 +172,12 @@ export class TitleCaser {
|
|
|
136
172
|
// Join the words in the array into a string.
|
|
137
173
|
inputString = wordsInTitleCase.join(" ");
|
|
138
174
|
|
|
139
|
-
for (const phrase of correctPhraseCasingList) {
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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);
|
|
144
181
|
}
|
|
145
182
|
|
|
146
183
|
// Replace the nl2br placeholder with <br> tags.
|
|
@@ -197,27 +234,31 @@ export class TitleCaser {
|
|
|
197
234
|
}
|
|
198
235
|
|
|
199
236
|
setReplaceTerms(terms) {
|
|
200
|
-
if (
|
|
201
|
-
throw new TypeError("Invalid argument:
|
|
237
|
+
if (!Array.isArray(terms)) {
|
|
238
|
+
throw new TypeError("Invalid argument: setReplaceTerms must be an array of objects.");
|
|
202
239
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
+
}
|
|
210
252
|
} else {
|
|
211
|
-
//
|
|
212
|
-
|
|
253
|
+
// Handle non-object entries in the array, if required
|
|
254
|
+
console.warn("Invalid entry in terms array:", termObject);
|
|
213
255
|
}
|
|
214
256
|
});
|
|
215
257
|
|
|
216
|
-
|
|
217
|
-
// console.log(wordReplacementsList);
|
|
258
|
+
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
218
259
|
|
|
219
|
-
//
|
|
220
|
-
this.
|
|
260
|
+
// Log the updated wordReplacementsList array
|
|
261
|
+
// console.log(this.wordReplacementsList);
|
|
221
262
|
}
|
|
222
263
|
|
|
223
264
|
addReplaceTerm(term, replacement) {
|
|
@@ -225,8 +266,6 @@ export class TitleCaser {
|
|
|
225
266
|
throw new TypeError("Invalid argument: term and replacement must be strings.");
|
|
226
267
|
}
|
|
227
268
|
|
|
228
|
-
const index = this.wordReplacementsList.findIndex((obj) => obj[term]);
|
|
229
|
-
|
|
230
269
|
if (index !== -1) {
|
|
231
270
|
// If the term already exists in the array, update the replacement value
|
|
232
271
|
this.wordReplacementsList[index][term] = replacement;
|
|
@@ -255,11 +294,46 @@ export class TitleCaser {
|
|
|
255
294
|
// Remove the term from the array
|
|
256
295
|
this.wordReplacementsList.splice(index, 1);
|
|
257
296
|
|
|
297
|
+
// Update the replace terms option
|
|
298
|
+
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
299
|
+
|
|
258
300
|
// Log the updated wordReplacementsList array
|
|
259
301
|
// console.log(this.wordReplacementsList);
|
|
302
|
+
}
|
|
260
303
|
|
|
261
|
-
|
|
262
|
-
|
|
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);
|
|
263
337
|
}
|
|
264
338
|
|
|
265
339
|
setStyle(style) {
|
package/src/TitleCaserConsts.js
CHANGED
|
@@ -145,4 +145,8 @@ export const titleCaseDefaultOptionsList = Object.freeze({
|
|
|
145
145
|
});
|
|
146
146
|
|
|
147
147
|
export const ignoredWordList = [];
|
|
148
|
-
export const correctPhraseCasingList =
|
|
148
|
+
export const correctPhraseCasingList = {
|
|
149
|
+
'the cybersmile foundation': 'The Cybersmile Foundation',
|
|
150
|
+
'co. by colgate': 'CO. by Colgate'
|
|
151
|
+
};
|
|
152
|
+
|