Skip to content

Commit c1bb0da

Browse files
committed
feat(pkg:string): added name casing detection APIs
1 parent 18d98f5 commit c1bb0da

File tree

3 files changed

+181
-0
lines changed

3 files changed

+181
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import * as NodeTest from 'node:test';
2+
import * as NodeAssert from 'node:assert';
3+
import * as NameCases from './NameCase';
4+
5+
NodeTest.describe('Function String.isUpperSnakeCase', () => {
6+
7+
NodeTest.it('Should return true for valid Upper Snake Case strings', () => {
8+
NodeAssert.strictEqual(NameCases.isUpperSnakeCase('UPPER_SNAKE_CASE'), true);
9+
NodeAssert.strictEqual(NameCases.isUpperSnakeCase('A1_B2_C3'), true);
10+
});
11+
12+
NodeTest.it('Should return false for invalid Upper Snake Case strings', () => {
13+
NodeAssert.strictEqual(NameCases.isUpperSnakeCase('lower_snake_case'), false);
14+
NodeAssert.strictEqual(NameCases.isUpperSnakeCase('Upper_Snake_Case'), false);
15+
NodeAssert.strictEqual(NameCases.isUpperSnakeCase('1A_B2'), false);
16+
NodeAssert.strictEqual(NameCases.isUpperSnakeCase('IsUpperSnakeCase'), false);
17+
NodeAssert.strictEqual(NameCases.isUpperSnakeCase('isLowerSnakeCase'), false);
18+
NodeAssert.strictEqual(NameCases.isUpperSnakeCase(''), false);
19+
});
20+
});
21+
22+
NodeTest.describe('Function String.isLowerSnakeCase', () => {
23+
24+
NodeTest.it('Should return true for valid Lower Snake Case strings', () => {
25+
NodeAssert.strictEqual(NameCases.isLowerSnakeCase('lower_snake_case'), true);
26+
NodeAssert.strictEqual(NameCases.isLowerSnakeCase('a1_b2_c3'), true);
27+
});
28+
29+
NodeTest.it('Should return false for invalid Lower Snake Case strings', () => {
30+
NodeAssert.strictEqual(NameCases.isLowerSnakeCase('UPPER_SNAKE_CASE'), false);
31+
NodeAssert.strictEqual(NameCases.isLowerSnakeCase('Upper_Snake_Case'), false);
32+
NodeAssert.strictEqual(NameCases.isLowerSnakeCase('1a_b2'), false);
33+
NodeAssert.strictEqual(NameCases.isLowerSnakeCase('IsLowerSnakeCase'), false);
34+
NodeAssert.strictEqual(NameCases.isLowerSnakeCase('isLowerSnakeCase'), false);
35+
NodeAssert.strictEqual(NameCases.isLowerSnakeCase(''), false);
36+
});
37+
});
38+
39+
NodeTest.describe('Function String.isLowerCamelCase', () => {
40+
41+
NodeTest.it('Should return true for valid Lower Camel Case strings', () => {
42+
NodeAssert.strictEqual(NameCases.isLowerCamelCase('lowerCamelCase'), true);
43+
NodeAssert.strictEqual(NameCases.isLowerCamelCase('a1b2c3'), true);
44+
});
45+
46+
NodeTest.it('Should return false for invalid Lower Camel Case strings', () => {
47+
NodeAssert.strictEqual(NameCases.isLowerCamelCase('UpperCamelCase'), false);
48+
NodeAssert.strictEqual(NameCases.isLowerCamelCase('1aB2'), false);
49+
NodeAssert.strictEqual(NameCases.isLowerCamelCase('IsLowerCamelCase'), false);
50+
NodeAssert.strictEqual(NameCases.isLowerCamelCase(''), false);
51+
});
52+
});
53+
54+
NodeTest.describe('Function String.isUpperCamelCase', () => {
55+
56+
NodeTest.it('Should return true for valid Upper Camel Case strings', () => {
57+
NodeAssert.strictEqual(NameCases.isUpperCamelCase('UpperCamelCase'), true);
58+
NodeAssert.strictEqual(NameCases.isUpperCamelCase('A1B2C3'), true);
59+
});
60+
61+
NodeTest.it('Should return false for invalid Upper Camel Case strings', () => {
62+
NodeAssert.strictEqual(NameCases.isUpperCamelCase('lowerCamelCase'), false);
63+
NodeAssert.strictEqual(NameCases.isUpperCamelCase('1AB2'), false);
64+
NodeAssert.strictEqual(NameCases.isUpperCamelCase('isUpperCamelCase'), false);
65+
NodeAssert.strictEqual(NameCases.isUpperCamelCase(''), false);
66+
});
67+
});
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/**
2+
* Copyright 2025 Angus.Fenying <[email protected]>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
const REGEX_LOWER_SNAKE_CASE = /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/;
18+
const REGEX_UPPER_SNAKE_CASE = /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/;
19+
20+
/**
21+
* Check if a string is in Upper Snake Case format (e.g. `UPPER_SNAKE_CASE`, `A1_B2_C3`).
22+
*
23+
* @param text The string to check.
24+
*
25+
* @returns `true` if the string is in Upper Snake Case format, otherwise `false`.
26+
*
27+
* @example `isUpperSnakeCase('UPPER_SNAKE_CASE') -> true`
28+
* @example `isUpperSnakeCase('lower_snake_case') -> false`
29+
* @example `isUpperSnakeCase('A1_B2_C3') -> true`
30+
* @example `isUpperSnakeCase('1A_B2') -> false`
31+
* @example `isUpperSnakeCase('') -> false`
32+
*/
33+
export function isUpperSnakeCase(text: string): boolean {
34+
35+
return REGEX_UPPER_SNAKE_CASE.test(text);
36+
}
37+
38+
/**
39+
* Check if a string is in Lower Snake Case format (e.g. `lower_snake_case`, `a1_b2_c3`).
40+
*
41+
* @param text The string to check.
42+
*
43+
* @returns `true` if the string is in Lower Snake Case format, otherwise `false`.
44+
*
45+
* @example `isLowerSnakeCase('lower_snake_case') -> true`
46+
* @example `isLowerSnakeCase('UPPER_SNAKE_CASE') -> false`
47+
* @example `isLowerSnakeCase('a1_b2_c3') -> true`
48+
* @example `isLowerSnakeCase('1a_b2') -> false`
49+
* @example `isLowerSnakeCase('') -> false`
50+
*/
51+
export function isLowerSnakeCase(text: string): boolean {
52+
53+
return REGEX_LOWER_SNAKE_CASE.test(text);
54+
}
55+
56+
const REGEX_LOWER_CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
57+
const REGEX_UPPER_CAMEL_CASE = /^[A-Z][a-zA-Z0-9]*$/;
58+
59+
/**
60+
* Check if a string is in Lower Camel Case format (e.g. `lowerCamelCase`, `a1b2c3`).
61+
*
62+
* @param text The string to check.
63+
*
64+
* @returns `true` if the string is in Lower Camel Case format, otherwise `false`.
65+
*
66+
* @example `isLowerCamelCase('lowerCamelCase') -> true`
67+
* @example `isLowerCamelCase('UpperCamelCase') -> false`
68+
* @example `isLowerCamelCase('a1b2c3') -> true`
69+
* @example `isLowerCamelCase('1aB2') -> false`
70+
* @example `isLowerCamelCase('') -> false`
71+
*/
72+
export function isLowerCamelCase(text: string): boolean {
73+
74+
return REGEX_LOWER_CAMEL_CASE.test(text);
75+
}
76+
77+
/**
78+
* Check if a string is in Upper Camel Case format (e.g. `UpperCamelCase`, `A1B2C3`).
79+
*
80+
* @param text The string to check.
81+
*
82+
* @returns `true` if the string is in Upper Camel Case format, otherwise `false`.
83+
*
84+
* @example `isUpperCamelCase('UpperCamelCase') -> true`
85+
* @example `isUpperCamelCase('lowerCamelCase') -> false`
86+
* @example `isUpperCamelCase('A1B2C3') -> true`
87+
* @example `isUpperCamelCase('1A2B') -> false`
88+
* @example `isUpperCamelCase('') -> false`
89+
*
90+
* @alias isPascalCase
91+
* @see {@link isPascalCase}
92+
*/
93+
export function isUpperCamelCase(text: string): boolean {
94+
95+
return REGEX_UPPER_CAMEL_CASE.test(text);
96+
}
97+
98+
/**
99+
* Check if a string is in Pascal Case format (same as Upper Camel Case).
100+
*
101+
* @param text The string to check.
102+
*
103+
* @returns `true` if the string is in Pascal Case format, otherwise `false`.
104+
*
105+
* @example `isPascalCase('PascalCase') -> true`
106+
* @example `isPascalCase('pascalCase') -> false`
107+
* @example `isPascalCase('Pascal_Case') -> false`
108+
* @example `isPascalCase('') -> false`
109+
*
110+
* @alias isUpperCamelCase
111+
* @see {@link isUpperCamelCase}
112+
*/
113+
export const isPascalCase = isUpperCamelCase;

packages/partials/string/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ export * from './Functions/Random';
2020
export * from './Functions/RegexpEscape';
2121
export * from './Functions/Html';
2222
export * from './Functions/ToChunks';
23+
export * from './Functions/NameCase';
2324
export * from './Classes/UnitParser';

0 commit comments

Comments
 (0)