@danielhaim/titlecaser 1.5.0 → 1.6.1
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/package.json +2 -2
- package/src/TitleCaser.js +14 -15
- package/src/TitleCaserConsts.js +2 -1
- package/src/TitleCaserUtils.js +7 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielhaim/titlecaser",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
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",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"package.json"
|
|
44
44
|
],
|
|
45
45
|
"scripts": {
|
|
46
|
-
"build-docs": "cd docs && bundle install && bundle exec jekyll build",
|
|
47
46
|
"build": "npx webpack --mode production && cp -R dist/ docs/assets/js",
|
|
47
|
+
"build-docs": "cd docs && bundle install && bundle exec jekyll build",
|
|
48
48
|
"release": "npm version patch && npm run build && git add -A && git commit -m 'Release: v$(node -p \"require('./package.json').version\")' && git push && npm publish",
|
|
49
49
|
"release-major": "npm version major && npm run build && git add -A && git commit -m 'Major Release: v$(node -p \"require('./package.json').version\")' && git push && npm publish",
|
|
50
50
|
"release-minor": "npm version minor && npm run build && git add -A && git commit -m 'Minor Release: v$(node -p \"require('./package.json').version\")' && git push && npm publish",
|
package/src/TitleCaser.js
CHANGED
|
@@ -15,13 +15,12 @@ export class TitleCaser {
|
|
|
15
15
|
this.correctPhraseCasingList = correctPhraseCasingList;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
logWarning(message) {
|
|
19
19
|
if (this.debug) {
|
|
20
20
|
console.warn(`Warning: ${message}`);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
24
|
toTitleCase(str) {
|
|
26
25
|
try {
|
|
27
26
|
// If input is empty, throw an error.
|
|
@@ -58,8 +57,8 @@ export class TitleCaser {
|
|
|
58
57
|
replaceTermList.map((term) => [Object.keys(term)[0].toLowerCase(), Object.values(term)[0]]),
|
|
59
58
|
);
|
|
60
59
|
|
|
61
|
-
this.
|
|
62
|
-
this.
|
|
60
|
+
this.logWarning(`replaceTermsArray: ${replaceTermsArray}`);
|
|
61
|
+
this.logWarning(`this.wordReplacementsList: ${this.wordReplacementsList}`);
|
|
63
62
|
|
|
64
63
|
const map = {
|
|
65
64
|
"&": "&",
|
|
@@ -133,31 +132,31 @@ export class TitleCaser {
|
|
|
133
132
|
? word.charAt(0).toUpperCase() + word.slice(1)
|
|
134
133
|
: word.toLowerCase();
|
|
135
134
|
case TitleCaserUtils.endsWithSymbol(word):
|
|
136
|
-
this.
|
|
135
|
+
this.logWarning(`Check if the word ends with a symbol: ${word}`);
|
|
137
136
|
// If the word ends with a symbol, return the correct casing.
|
|
138
137
|
const splitWord = word.split(/([.,\/#!$%\^&\*;:{}=\-_`~()?])/g);
|
|
139
|
-
this.
|
|
138
|
+
this.logWarning(`Splitting word at symbols, result: ${splitWord}`);
|
|
140
139
|
// Process each part for correct casing
|
|
141
140
|
const processedWords = splitWord.map((part) => {
|
|
142
|
-
this.
|
|
141
|
+
this.logWarning(`Processing part: ${part}`);
|
|
143
142
|
// Check if part is a symbol
|
|
144
143
|
if (TitleCaserUtils.endsWithSymbol(part)) {
|
|
145
|
-
this.
|
|
144
|
+
this.logWarning(`Part is a symbol: ${part}`);
|
|
146
145
|
return part;
|
|
147
146
|
} else {
|
|
148
|
-
this.
|
|
147
|
+
this.logWarning(`Part is a word: ${part}`);
|
|
149
148
|
// If it's a word, process it for correct casing
|
|
150
149
|
if (TitleCaserUtils.isWordInArray(part, correctTitleCasingList)) {
|
|
151
150
|
const correctedTerm = TitleCaserUtils.correctTerm(part, correctTitleCasingList);
|
|
152
|
-
this.
|
|
151
|
+
this.logWarning(`Word is in correctTitleCasingList, corrected term: ${correctedTerm}`);
|
|
153
152
|
return correctedTerm;
|
|
154
153
|
} else if (replaceTermsArray.includes(part)) {
|
|
155
154
|
const replacement = replaceTermObj[part];
|
|
156
|
-
this.
|
|
155
|
+
this.logWarning(`Word is in replaceTermsArray, replacement: ${replacement}`);
|
|
157
156
|
return replacement;
|
|
158
157
|
} else {
|
|
159
158
|
const titledWord = part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
|
160
|
-
this.
|
|
159
|
+
this.logWarning(`Applying title casing to word: ${titledWord}`);
|
|
161
160
|
return titledWord;
|
|
162
161
|
}
|
|
163
162
|
}
|
|
@@ -270,7 +269,7 @@ export class TitleCaser {
|
|
|
270
269
|
|
|
271
270
|
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
272
271
|
|
|
273
|
-
this.
|
|
272
|
+
this.logWarning(`Log the updated this.wordReplacementsList: ${this.wordReplacementsList}`);
|
|
274
273
|
}
|
|
275
274
|
|
|
276
275
|
addReplaceTerm(term, replacement) {
|
|
@@ -308,7 +307,7 @@ export class TitleCaser {
|
|
|
308
307
|
// Update the replace terms option
|
|
309
308
|
this.options.wordReplacementsList = this.wordReplacementsList;
|
|
310
309
|
|
|
311
|
-
this.
|
|
310
|
+
this.logWarning(`Log the updated this.wordReplacementsList: ${this.wordReplacementsList}`);
|
|
312
311
|
}
|
|
313
312
|
|
|
314
313
|
addExactPhraseReplacements(newPhrases) {
|
|
@@ -343,7 +342,7 @@ export class TitleCaser {
|
|
|
343
342
|
}
|
|
344
343
|
});
|
|
345
344
|
|
|
346
|
-
this.
|
|
345
|
+
this.logWarning(`Log the this.correctPhraseCasingList: ${this.correctPhraseCasingList}`);
|
|
347
346
|
}
|
|
348
347
|
|
|
349
348
|
setStyle(style) {
|
package/src/TitleCaserConsts.js
CHANGED
|
@@ -68,6 +68,7 @@ export const wordReplacementsList = [
|
|
|
68
68
|
{ "a.s.a.p": "ASAP" },
|
|
69
69
|
{ "f.a.q": "FAQ" },
|
|
70
70
|
{ "f.a.q.s": "FAQs" },
|
|
71
|
+
{ "FAQS": "FAQs" },
|
|
71
72
|
{ "f.y.i": "FYI" },
|
|
72
73
|
{ "d.i.y": "DIY" },
|
|
73
74
|
{ "t.b.d": "TBD" },
|
|
@@ -80,7 +81,7 @@ export const wordReplacementsList = [
|
|
|
80
81
|
{ "reactjs": "React" },
|
|
81
82
|
{ "react.js": "React" },
|
|
82
83
|
{ "cyber-security": "Cybersecurity" },
|
|
83
|
-
// { 'twitter': '𝕏' }
|
|
84
|
+
// { 'twitter': 'Twitter, formerly known as 𝕏' }
|
|
84
85
|
];
|
|
85
86
|
|
|
86
87
|
export const titleCaseStylesList = Object.freeze({
|
package/src/TitleCaserUtils.js
CHANGED
|
@@ -219,9 +219,14 @@ export class TitleCaserUtils {
|
|
|
219
219
|
return /[A-Z]/.test(word.slice(1));
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
const hasUppercase = /[A-Z]/.test(word.slice(1));
|
|
223
|
+
const hasLowercase = /[a-z]/.test(word.slice(1));
|
|
224
|
+
|
|
225
|
+
return hasUppercase && hasLowercase;
|
|
223
226
|
}
|
|
224
227
|
|
|
228
|
+
// Check if a word is an acronym
|
|
229
|
+
// (i.e. 'the', 'to', 'within')
|
|
225
230
|
static isAcronym(word, prevWord, nextWord) {
|
|
226
231
|
try {
|
|
227
232
|
if (typeof word !== "string") {
|
|
@@ -539,6 +544,7 @@ export class TitleCaserUtils {
|
|
|
539
544
|
});
|
|
540
545
|
}
|
|
541
546
|
|
|
547
|
+
// Check if there's an unescaped special character
|
|
542
548
|
static unescapeSpecialCharacters(str) {
|
|
543
549
|
return str.replace(/&|<|>|"|'/g, function (match) {
|
|
544
550
|
switch (match) {
|