Skip to content

Commit f53ad5c

Browse files
Normalize title casing with reserved word replacements and add corresponding unit tests
1 parent 6a11c70 commit f53ad5c

File tree

4 files changed

+196
-2
lines changed

4 files changed

+196
-2
lines changed

src/libs/words.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const reservedWords = [
2+
"GitHub",
3+
"BitBucket",
4+
"GitLab",
5+
"JSON",
6+
"via",
7+
"by",
8+
"with",
9+
"for",
10+
"a",
11+
"at",
12+
];

src/utils/strings.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
1+
import { reservedWords } from "../libs/words";
2+
3+
const normalizeWords = (value: string): string => {
4+
for (const word of reservedWords) {
5+
value = value.replace(new RegExp(`\\b${word}\\b`, "i"), word);
6+
}
7+
8+
return value;
9+
};
10+
111
export const titleCase = (title: string | undefined) => {
212
if (title === "" || title === undefined) {
313
return "";
414
}
515

6-
return title
16+
title = title
717
.replace(/([A-Z])/g, "$1")
818
.toLowerCase()
919
.replace(/(^|\s|-|_)\S/g, (match: string) => match.toUpperCase())
10-
.replace(/[-_]/g, " ");
20+
.replace(/[-_]/g, " ")
21+
.trim();
22+
23+
const normalized = normalizeWords(title);
24+
25+
return normalized.charAt(0).toUpperCase() + normalized.slice(1);
1126
};
1227

1328
export const removeImages = (content: string): string =>
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`words 1`] = `
4+
[
5+
"GitHub Bar",
6+
"Foo GitHub Bar",
7+
"Foo GitHub",
8+
"GitHub Bar",
9+
"Foo GitHub Bar",
10+
"Foo GitHub",
11+
"GitHub Bar",
12+
"Foo GitHub Bar",
13+
"Foo GitHub",
14+
]
15+
`;
16+
17+
exports[`words 2`] = `
18+
[
19+
"BitBucket Bar",
20+
"Foo BitBucket Bar",
21+
"Foo BitBucket",
22+
"BitBucket Bar",
23+
"Foo BitBucket Bar",
24+
"Foo BitBucket",
25+
"BitBucket Bar",
26+
"Foo BitBucket Bar",
27+
"Foo BitBucket",
28+
]
29+
`;
30+
31+
exports[`words 3`] = `
32+
[
33+
"GitLab Bar",
34+
"Foo GitLab Bar",
35+
"Foo GitLab",
36+
"GitLab Bar",
37+
"Foo GitLab Bar",
38+
"Foo GitLab",
39+
"GitLab Bar",
40+
"Foo GitLab Bar",
41+
"Foo GitLab",
42+
]
43+
`;
44+
45+
exports[`words 4`] = `
46+
[
47+
"JSON Bar",
48+
"Foo JSON Bar",
49+
"Foo JSON",
50+
"JSON Bar",
51+
"Foo JSON Bar",
52+
"Foo JSON",
53+
"JSON Bar",
54+
"Foo JSON Bar",
55+
"Foo JSON",
56+
]
57+
`;
58+
59+
exports[`words 5`] = `
60+
[
61+
"Via Bar",
62+
"Foo via Bar",
63+
"Foo via",
64+
"Via Bar",
65+
"Foo via Bar",
66+
"Foo via",
67+
"Via Bar",
68+
"Foo via Bar",
69+
"Foo via",
70+
]
71+
`;
72+
73+
exports[`words 6`] = `
74+
[
75+
"By Bar",
76+
"Foo by Bar",
77+
"Foo by",
78+
"By Bar",
79+
"Foo by Bar",
80+
"Foo by",
81+
"By Bar",
82+
"Foo by Bar",
83+
"Foo by",
84+
]
85+
`;
86+
87+
exports[`words 7`] = `
88+
[
89+
"With Bar",
90+
"Foo with Bar",
91+
"Foo with",
92+
"With Bar",
93+
"Foo with Bar",
94+
"Foo with",
95+
"With Bar",
96+
"Foo with Bar",
97+
"Foo with",
98+
]
99+
`;
100+
101+
exports[`words 8`] = `
102+
[
103+
"For Bar",
104+
"Foo for Bar",
105+
"Foo for",
106+
"For Bar",
107+
"Foo for Bar",
108+
"Foo for",
109+
"For Bar",
110+
"Foo for Bar",
111+
"Foo for",
112+
]
113+
`;
114+
115+
exports[`words 9`] = `
116+
[
117+
"A Bar",
118+
"Foo a Bar",
119+
"Foo a",
120+
"A Bar",
121+
"Foo a Bar",
122+
"Foo a",
123+
"A Bar",
124+
"Foo a Bar",
125+
"Foo a",
126+
]
127+
`;
128+
129+
exports[`words 10`] = `
130+
[
131+
"At Bar",
132+
"Foo at Bar",
133+
"Foo at",
134+
"At Bar",
135+
"Foo at Bar",
136+
"Foo at",
137+
"At Bar",
138+
"Foo at Bar",
139+
"Foo at",
140+
]
141+
`;

tests/unit/strings.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { reservedWords } from "../../src/libs/words";
2+
import { titleCase } from "../../src/utils/strings";
3+
4+
test("words", () => {
5+
for (const word of reservedWords) {
6+
const lower = word.toLowerCase();
7+
const upper = word.toUpperCase();
8+
9+
const items = [
10+
// Base
11+
`${word}_bar`,
12+
`foo ${word}-bar`,
13+
`foo ${word}_`,
14+
// Lower
15+
`${lower}_bar`,
16+
`foo ${lower}-bar`,
17+
`foo ${lower}_`,
18+
// Upper
19+
`${upper}_bar`,
20+
`foo ${upper}-bar`,
21+
`foo ${upper}_`,
22+
];
23+
24+
expect(items.map((item: string) => titleCase(item))).toMatchSnapshot();
25+
}
26+
});

0 commit comments

Comments
 (0)