Skip to content

Commit 5b7e075

Browse files
authored
✨ feature: Code Case Extensions (#57)
* Create common code case extensions * Create ToCamelCase Extension * Create ToKebabCase Extension * Create ToSnakeCase Extension * Create ToPascalCase Extension * Create ToTrainCase Extension * Global usings * Create Tests for ToCase Extensions
1 parent 35396b5 commit 5b7e075

12 files changed

+232
-4
lines changed

TJC.StringExtensions.Tests/Cases/CamelCaseExtensionsTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,18 @@ public void SplitCamelCase_FirstLetterUppercase_SplitsWithSpace()
4646
// Assert
4747
Assert.AreEqual(expected, result);
4848
}
49+
50+
[TestMethod]
51+
public void ToCamelCaseTest()
52+
{
53+
// Arrange
54+
var input = "Camel Case Extensions";
55+
var expected = "camelCaseExtensions";
56+
57+
// Act
58+
var result = input.ToCamelCase();
59+
60+
// Assert
61+
Assert.AreEqual(expected, result);
62+
}
4963
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using TJC.StringExtensions.Cases;
2+
3+
namespace TJC.StringExtensions.Tests.Cases;
4+
5+
[TestClass]
6+
public class KebabCaseExtensionsTests
7+
{
8+
[TestMethod]
9+
public void ToKebabCaseTest()
10+
{
11+
// Arrange
12+
var input = "Kebab Case Extensions";
13+
var expected = "kebab-case-extensions";
14+
15+
// Act
16+
var result = input.ToKebabCase();
17+
18+
// Assert
19+
Assert.AreEqual(expected, result);
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using TJC.StringExtensions.Cases;
2+
3+
namespace TJC.StringExtensions.Tests.Cases;
4+
5+
[TestClass]
6+
public class PascalCaseExtensionsTests
7+
{
8+
[TestMethod]
9+
public void ToPascalCaseTest()
10+
{
11+
// Arrange
12+
var input = "Pascal Case Extensions";
13+
var expected = "PascalCaseExtensions";
14+
15+
// Act
16+
var result = input.ToPascalCase();
17+
18+
// Assert
19+
Assert.AreEqual(expected, result);
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using TJC.StringExtensions.Cases;
2+
3+
namespace TJC.StringExtensions.Tests.Cases;
4+
5+
[TestClass]
6+
public class SnakeCaseExtensionsTests
7+
{
8+
[TestMethod]
9+
public void ToSnakeCaseTest()
10+
{
11+
// Arrange
12+
var input = "Snake Case Extensions";
13+
var expected = "snake_case_extensions";
14+
15+
// Act
16+
var result = input.ToSnakeCase();
17+
18+
// Assert
19+
Assert.AreEqual(expected, result);
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using TJC.StringExtensions.Cases;
2+
3+
namespace TJC.StringExtensions.Tests.Cases;
4+
5+
[TestClass]
6+
public class TrainCaseExtensionsTests
7+
{
8+
[TestMethod]
9+
public void ToTrainCaseTest()
10+
{
11+
// Arrange
12+
var input = "Train Case Extensions";
13+
var expected = "Train-Case-Extensions";
14+
15+
// Act
16+
var result = input.ToTrainCase();
17+
18+
// Assert
19+
Assert.AreEqual(expected, result);
20+
}
21+
}

TJC.StringExtensions/Cases/CamelCaseExtensions.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,28 @@ public static class CamelCaseExtensions
99
{
1010
/// <summary>
1111
/// Split camel case with a separator (typically a space).
12-
/// <para></para>
13-
/// Example: "camelCaseExtensions" becomes "camel Case Extensions"
1412
/// </summary>
1513
/// <param name="input"></param>
1614
/// <param name="separator"></param>
17-
/// <returns></returns>
15+
/// <returns>"camelCaseExtensions" becomes "camel Case Extensions"</returns>
1816
public static string SplitCamelCase(this string? input, string separator = " ")
1917
{
2018
if (string.IsNullOrEmpty(input))
2119
return string.Empty;
2220
return string.Concat(input.Select((x, i) => i > 0 && char.IsUpper(x) ? $"{separator}{x}" : x.ToString()));
2321
}
22+
23+
/// <summary>
24+
/// Convert any case format to camel case.
25+
/// </summary>
26+
/// <param name="input"></param>
27+
/// <returns>camelCase</returns>
28+
public static string ToCamelCase(this string input)
29+
{
30+
var words = input.CodeCaseToWords();
31+
var result = new StringBuilder(words[0].ToLower());
32+
for (int i = 1; i < words.Length; i++)
33+
result.Append(char.ToUpper(words[i][0]) + words[i][1..].ToLower());
34+
return result.ToString();
35+
}
2436
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace TJC.StringExtensions.Cases;
2+
3+
/// <summary>
4+
/// Case extensions for strings.
5+
/// </summary>
6+
public static partial class CodeCaseExtensions
7+
{
8+
private static readonly char[] _separator = [' ', '_', '-'];
9+
10+
/// <summary>
11+
/// Splits any code case format with a separator.
12+
/// </summary>
13+
/// <param name="input"></param>
14+
/// <param name="separator"></param>
15+
/// <returns></returns>
16+
public static string SplitCodeCase(this string input, string separator = " ")
17+
{
18+
if (string.IsNullOrEmpty(input))
19+
return string.Empty;
20+
return string.Join(separator, input.CodeCaseToWords());
21+
}
22+
23+
/// <summary>
24+
/// Convert any code case format to words array.
25+
/// </summary>
26+
/// <param name="input"></param>
27+
/// <returns></returns>
28+
public static string[] CodeCaseToWords(this string input)
29+
{
30+
if (string.IsNullOrWhiteSpace(input))
31+
return [];
32+
// Add spaces around transitions (camelCase, PascalCase) and split by space, hyphen, or underscore
33+
var spaced = CaseWordSplitter.Replace(input, " ");
34+
return spaced.Split(_separator, StringSplitOptions.RemoveEmptyEntries);
35+
}
36+
37+
private static readonly Regex CaseWordSplitter = CaseWordSplitterRegex();
38+
39+
[GeneratedRegex(@"[a-z][A-Z]|[_\- ]", RegexOptions.Compiled)]
40+
private static partial Regex CaseWordSplitterRegex();
41+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace TJC.StringExtensions.Cases;
2+
3+
/// <summary>
4+
/// Kebab case extensions for strings.
5+
/// <para></para>
6+
/// Example of kebab case: "kebab-case-extensions"
7+
/// </summary>
8+
public static class KebabCaseExtensions
9+
{
10+
/// <summary>
11+
/// Convert any case format to kebab case.
12+
/// </summary>
13+
/// <param name="input"></param>
14+
/// <returns>kebab-case</returns>
15+
public static string ToKebabCase(this string input) =>
16+
string.Join("-", input.CodeCaseToWords()).ToLower();
17+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace TJC.StringExtensions.Cases;
2+
3+
/// <summary>
4+
/// Pascal case extensions for strings.
5+
/// <para></para>
6+
/// Example of pascal case: "PascalCaseExtensions"
7+
/// </summary>
8+
public static class PascalCaseExtensions
9+
{
10+
/// <summary>
11+
/// Convert any case format to pascal case.
12+
/// </summary>
13+
/// <param name="input"></param>
14+
/// <returns>PascalCase</returns>
15+
public static string ToPascalCase(this string input)
16+
{
17+
var words = input.CodeCaseToWords();
18+
var result = new StringBuilder();
19+
foreach (var word in words)
20+
result.Append(char.ToUpper(word[0]) + word[1..].ToLower());
21+
return result.ToString();
22+
}
23+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace TJC.StringExtensions.Cases;
2+
3+
/// <summary>
4+
/// Snake case extensions for strings.
5+
/// <para></para>
6+
/// Example of snake case: "snake-case-extensions"
7+
/// </summary>
8+
public static class SnakeCaseExtensions
9+
{
10+
/// <summary>
11+
/// Convert any case format to snake case.
12+
/// </summary>
13+
/// <param name="input"></param>
14+
/// <returns>snake_case</returns>
15+
public static string ToSnakeCase(this string input) =>
16+
string.Join("_", input.CodeCaseToWords()).ToLower();
17+
}

0 commit comments

Comments
 (0)