Skip to content

Commit aadc0f0

Browse files
committed
don't rely on regex
1 parent eba5273 commit aadc0f0

7 files changed

Lines changed: 100 additions & 42 deletions

File tree

packages/utils/source/camel-case.test.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

packages/utils/source/camel-case.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/utils/source/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
export * from "./assert.js";
22
export * from "./byte-buffer.js";
3-
export * from "./camel-case.js";
43
export * from "./chunk.js";
54
export * from "./dot-env.js";
65
export * from "./expand-tilde.js";
@@ -26,7 +25,6 @@ export * from "./map.js";
2625
export * from "./merge.js";
2726
export * from "./min-by.js";
2827
export * from "./order-by.js";
29-
export * from "./pascal-case.js";
3028
export * from "./pluralize.js";
3129
export * from "./pretty-bytes.js";
3230
export * from "./pretty-time.js";
@@ -36,6 +34,7 @@ export * from "./set-timeout-async.js";
3634
export * from "./set.js";
3735
export * from "./shuffle.js";
3836
export * from "./sleep.js";
37+
export * from "./string-case.js";
3938
export * from "./take.js";
4039
export * from "./unset.js";
4140
export * from "./validator-set-pack.js";

packages/utils/source/pascal-case.test.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

packages/utils/source/pascal-case.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { describe } from "@mainsail/test-runner";
2+
import { camelCase, pascalCase } from "./string-case";
3+
4+
describe("#stringCase", ({ it, assert }) => {
5+
it("should turn any string into camel case", () => {
6+
assert.equal(camelCase("string"), "string");
7+
assert.equal(camelCase("camelCase"), "camelCase");
8+
assert.equal(camelCase("param-case"), "paramCase");
9+
assert.equal(camelCase("PascalCase"), "pascalCase");
10+
assert.equal(camelCase("UPPER_CASE"), "upperCase");
11+
assert.equal(camelCase("snake_case"), "snakeCase");
12+
assert.equal(camelCase("sentence case"), "sentenceCase");
13+
assert.equal(camelCase("Title Case"), "titleCase");
14+
assert.equal(camelCase("dot.case"), "dotCase");
15+
});
16+
17+
it("should turn any string into pascal case", () => {
18+
assert.is(pascalCase("string"), "String");
19+
assert.is(pascalCase("camelCase"), "CamelCase");
20+
assert.is(pascalCase("param-case"), "ParamCase");
21+
assert.is(pascalCase("PascalCase"), "PascalCase");
22+
assert.is(pascalCase("UPPER_CASE"), "UpperCase");
23+
assert.is(pascalCase("snake_case"), "SnakeCase");
24+
assert.is(pascalCase("sentence case"), "SentenceCase");
25+
assert.is(pascalCase("Title Case"), "TitleCase");
26+
assert.is(pascalCase("dot.case"), "DotCase");
27+
});
28+
});
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const isSeparator = (char: string): boolean => char === "-" || char === "_" || char === "." || char.trim() === "";
2+
3+
const isUpper = (char: string): boolean => char >= "A" && char <= "Z";
4+
5+
const isLower = (char: string): boolean => char >= "a" && char <= "z";
6+
7+
const capitalizeWord = (word: string): string => {
8+
const first = word.at(0);
9+
10+
if (first === undefined) {
11+
return "";
12+
}
13+
14+
return first.toUpperCase() + word.slice(1).toLowerCase();
15+
};
16+
17+
const splitWords = (value: string): string[] => {
18+
const words: string[] = [];
19+
let word = "";
20+
21+
for (let index = 0; index < value.length; index++) {
22+
const char = value.at(index);
23+
24+
if (char === undefined) {
25+
continue;
26+
}
27+
28+
if (isSeparator(char)) {
29+
if (word.length > 0) {
30+
words.push(word);
31+
word = "";
32+
}
33+
34+
continue;
35+
}
36+
37+
const previous = word.at(-1);
38+
const next = value.at(index + 1);
39+
40+
const startsCamelWord =
41+
word.length > 0 &&
42+
previous !== undefined &&
43+
isUpper(char) &&
44+
(isLower(previous) || (isUpper(previous) && next !== undefined && isLower(next)));
45+
46+
if (startsCamelWord) {
47+
words.push(word);
48+
word = char;
49+
continue;
50+
}
51+
52+
word += char;
53+
}
54+
55+
if (word.length > 0) {
56+
words.push(word);
57+
}
58+
59+
return words;
60+
};
61+
62+
export const camelCase = (value: string): string => {
63+
const words = splitWords(value);
64+
65+
return words.map((word, index) => (index === 0 ? word.toLowerCase() : capitalizeWord(word))).join("");
66+
};
67+
68+
export const pascalCase = (value: string): string =>
69+
splitWords(value)
70+
.map((element) => capitalizeWord(element))
71+
.join("");

0 commit comments

Comments
 (0)