Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions TJC.StringExtensions.Tests/Cases/CamelCaseExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,18 @@ public void SplitCamelCase_FirstLetterUppercase_SplitsWithSpace()
// Assert
Assert.AreEqual(expected, result);
}

[TestMethod]
public void ToCamelCaseTest()
{
// Arrange
var input = "Camel Case Extensions";
var expected = "camelCaseExtensions";

// Act
var result = input.ToCamelCase();

// Assert
Assert.AreEqual(expected, result);
}
}
21 changes: 21 additions & 0 deletions TJC.StringExtensions.Tests/Cases/KebabCaseExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using TJC.StringExtensions.Cases;

namespace TJC.StringExtensions.Tests.Cases;

[TestClass]
public class KebabCaseExtensionsTests
{
[TestMethod]
public void ToKebabCaseTest()
{
// Arrange
var input = "Kebab Case Extensions";
var expected = "kebab-case-extensions";

// Act
var result = input.ToKebabCase();

// Assert
Assert.AreEqual(expected, result);
}
}
21 changes: 21 additions & 0 deletions TJC.StringExtensions.Tests/Cases/PascalCaseExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using TJC.StringExtensions.Cases;

namespace TJC.StringExtensions.Tests.Cases;

[TestClass]
public class PascalCaseExtensionsTests
{
[TestMethod]
public void ToPascalCaseTest()
{
// Arrange
var input = "Pascal Case Extensions";
var expected = "PascalCaseExtensions";

// Act
var result = input.ToPascalCase();

// Assert
Assert.AreEqual(expected, result);
}
}
21 changes: 21 additions & 0 deletions TJC.StringExtensions.Tests/Cases/SnakeCaseExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using TJC.StringExtensions.Cases;

namespace TJC.StringExtensions.Tests.Cases;

[TestClass]
public class SnakeCaseExtensionsTests
{
[TestMethod]
public void ToSnakeCaseTest()
{
// Arrange
var input = "Snake Case Extensions";
var expected = "snake_case_extensions";

// Act
var result = input.ToSnakeCase();

// Assert
Assert.AreEqual(expected, result);
}
}
21 changes: 21 additions & 0 deletions TJC.StringExtensions.Tests/Cases/TrainCaseExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using TJC.StringExtensions.Cases;

namespace TJC.StringExtensions.Tests.Cases;

[TestClass]
public class TrainCaseExtensionsTests
{
[TestMethod]
public void ToTrainCaseTest()
{
// Arrange
var input = "Train Case Extensions";
var expected = "Train-Case-Extensions";

// Act
var result = input.ToTrainCase();

// Assert
Assert.AreEqual(expected, result);
}
}
18 changes: 15 additions & 3 deletions TJC.StringExtensions/Cases/CamelCaseExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,28 @@ public static class CamelCaseExtensions
{
/// <summary>
/// Split camel case with a separator (typically a space).
/// <para></para>
/// Example: "camelCaseExtensions" becomes "camel Case Extensions"
/// </summary>
/// <param name="input"></param>
/// <param name="separator"></param>
/// <returns></returns>
/// <returns>"camelCaseExtensions" becomes "camel Case Extensions"</returns>
public static string SplitCamelCase(this string? input, string separator = " ")
{
if (string.IsNullOrEmpty(input))
return string.Empty;
return string.Concat(input.Select((x, i) => i > 0 && char.IsUpper(x) ? $"{separator}{x}" : x.ToString()));
}

/// <summary>
/// Convert any case format to camel case.
/// </summary>
/// <param name="input"></param>
/// <returns>camelCase</returns>
public static string ToCamelCase(this string input)
{
var words = input.CodeCaseToWords();
var result = new StringBuilder(words[0].ToLower());
for (int i = 1; i < words.Length; i++)
result.Append(char.ToUpper(words[i][0]) + words[i][1..].ToLower());
return result.ToString();
}
}
41 changes: 41 additions & 0 deletions TJC.StringExtensions/Cases/CodeCaseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace TJC.StringExtensions.Cases;

/// <summary>
/// Case extensions for strings.
/// </summary>
public static partial class CodeCaseExtensions
{
private static readonly char[] _separator = [' ', '_', '-'];

/// <summary>
/// Splits any code case format with a separator.
/// </summary>
/// <param name="input"></param>
/// <param name="separator"></param>
/// <returns></returns>
public static string SplitCodeCase(this string input, string separator = " ")
{
if (string.IsNullOrEmpty(input))
return string.Empty;
return string.Join(separator, input.CodeCaseToWords());
}

/// <summary>
/// Convert any code case format to words array.
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string[] CodeCaseToWords(this string input)
{
if (string.IsNullOrWhiteSpace(input))
return [];
// Add spaces around transitions (camelCase, PascalCase) and split by space, hyphen, or underscore
var spaced = CaseWordSplitter.Replace(input, " ");
return spaced.Split(_separator, StringSplitOptions.RemoveEmptyEntries);
}

private static readonly Regex CaseWordSplitter = CaseWordSplitterRegex();

[GeneratedRegex(@"[a-z][A-Z]|[_\- ]", RegexOptions.Compiled)]
private static partial Regex CaseWordSplitterRegex();
}
17 changes: 17 additions & 0 deletions TJC.StringExtensions/Cases/KebabCaseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace TJC.StringExtensions.Cases;

/// <summary>
/// Kebab case extensions for strings.
/// <para></para>
/// Example of kebab case: "kebab-case-extensions"
/// </summary>
public static class KebabCaseExtensions
{
/// <summary>
/// Convert any case format to kebab case.
/// </summary>
/// <param name="input"></param>
/// <returns>kebab-case</returns>
public static string ToKebabCase(this string input) =>
string.Join("-", input.CodeCaseToWords()).ToLower();
}
23 changes: 23 additions & 0 deletions TJC.StringExtensions/Cases/PascalCaseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace TJC.StringExtensions.Cases;

/// <summary>
/// Pascal case extensions for strings.
/// <para></para>
/// Example of pascal case: "PascalCaseExtensions"
/// </summary>
public static class PascalCaseExtensions
{
/// <summary>
/// Convert any case format to pascal case.
/// </summary>
/// <param name="input"></param>
/// <returns>PascalCase</returns>
public static string ToPascalCase(this string input)
{
var words = input.CodeCaseToWords();
var result = new StringBuilder();
foreach (var word in words)
result.Append(char.ToUpper(word[0]) + word[1..].ToLower());
return result.ToString();
}
}
17 changes: 17 additions & 0 deletions TJC.StringExtensions/Cases/SnakeCaseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace TJC.StringExtensions.Cases;

/// <summary>
/// Snake case extensions for strings.
/// <para></para>
/// Example of snake case: "snake-case-extensions"
/// </summary>
public static class SnakeCaseExtensions
{
/// <summary>
/// Convert any case format to snake case.
/// </summary>
/// <param name="input"></param>
/// <returns>snake_case</returns>
public static string ToSnakeCase(this string input) =>
string.Join("_", input.CodeCaseToWords()).ToLower();
}
18 changes: 18 additions & 0 deletions TJC.StringExtensions/Cases/TrainCaseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace TJC.StringExtensions.Cases;

/// <summary>
/// Train case extensions for strings.
/// <para></para>
/// Example of train case: "Train-Case-Extensions"
/// </summary>
public static class TrainCaseExtensions
{
/// <summary>
/// Convert any case format to train case.
/// </summary>
/// <param name="input"></param>
/// <returns>Train-Case</returns>
public static string ToTrainCase(this string input) =>
string.Join("-", input.CodeCaseToWords()
.Select(word => char.ToUpper(word[0]) + word[1..].ToLower()));
}
4 changes: 3 additions & 1 deletion TJC.StringExtensions/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
global using TJC.StringExtensions.Separator;
global using System.Text;
global using System.Text.RegularExpressions;
global using TJC.StringExtensions.Separator;