Skip to content

Commit 1877a13

Browse files
authored
Added StringExtensions.Humanize method. (#207)
1 parent 6178ed4 commit 1877a13

File tree

4 files changed

+58
-4
lines changed

4 files changed

+58
-4
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
Nothing yet.
1111

12+
## [1.20.4] - 2025-04-16
13+
14+
### Added
15+
16+
- Method `StringExtensions.Humanize`.
17+
1218
## [1.20.3] - 2025-04-16
1319

1420
### Fixed
@@ -281,7 +287,8 @@ Nothing yet.
281287

282288
- Implemented StringExtensions.
283289

284-
[unreleased]: https://github.com/Logitar/Logitar.NET/compare/v1.20.3...HEAD
290+
[unreleased]: https://github.com/Logitar/Logitar.NET/compare/v1.20.4...HEAD
291+
[1.20.4]: https://github.com/Logitar/Logitar.NET/compare/v1.20.3...v1.20.4
285292
[1.20.3]: https://github.com/Logitar/Logitar.NET/compare/v1.20.2...v1.20.3
286293
[1.20.2]: https://github.com/Logitar/Logitar.NET/compare/v1.20.1...v1.20.2
287294
[1.20.1]: https://github.com/Logitar/Logitar.NET/compare/v1.20.0...v1.20.1

src/Logitar/Logitar.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
<PackageReadmeFile>README.md</PackageReadmeFile>
1616
<RepositoryType>git</RepositoryType>
1717
<RepositoryUrl>https://github.com/Logitar/Logitar.NET</RepositoryUrl>
18-
<AssemblyVersion>7.0.0.0</AssemblyVersion>
18+
<AssemblyVersion>7.1.0.0</AssemblyVersion>
1919
<FileVersion>$(AssemblyVersion)</FileVersion>
2020
<PackageLicenseFile>LICENSE</PackageLicenseFile>
2121
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
22-
<Version>7.0.0</Version>
22+
<Version>7.1.0</Version>
2323
<NeutralLanguage>en-CA</NeutralLanguage>
2424
<GenerateDocumentationFile>True</GenerateDocumentationFile>
25-
<PackageReleaseNotes>Removed `ExceptionDetail` and dependency from `System.Text.Json`.</PackageReleaseNotes>
25+
<PackageReleaseNotes>Added `StringExtensions.Humanize` method.</PackageReleaseNotes>
2626
<PackageTags>logitar net framework</PackageTags>
2727
<PackageProjectUrl>https://github.com/Logitar/Logitar.NET/tree/dev/src/Logitar</PackageProjectUrl>
2828
</PropertyGroup>
@@ -53,6 +53,7 @@
5353
<ItemGroup>
5454
<Using Include="System.Collections" />
5555
<Using Include="System.Globalization" />
56+
<Using Include="System.Text" />
5657
</ItemGroup>
5758

5859
</Project>

src/Logitar/StringExtensions.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,41 @@ public static string FromUriSafeBase64(this string s)
3333
/// <returns>The Uri-safe base6 version of the string.</returns>
3434
public static string ToUriSafeBase64(this string s) => s.Replace('+', '-').Replace('/', '_').TrimEnd('=');
3535

36+
/// <summary>
37+
/// Humanizes the specified string by inserting spaces between words. Words are separated by case-change, such as in camelCase and PascalCase.
38+
/// </summary>
39+
/// <param name="s">The camelCase or PascalCase string.</param>
40+
/// <returns>The humanized string.</returns>
41+
public static string Humanize(this string s)
42+
{
43+
List<string> words = new(capacity: s.Length);
44+
45+
StringBuilder word = new();
46+
for (int i = 0; i < s.Length; i++)
47+
{
48+
char? previous = (i > 0) ? s[i - 1] : null;
49+
char current = s[i];
50+
char? next = (i < s.Length - 1) ? s[i + 1] : null;
51+
52+
if (char.IsUpper(current) && ((previous.HasValue && char.IsLower(previous.Value)) || (next.HasValue && char.IsLower(next.Value))))
53+
{
54+
if (word.Length > 0)
55+
{
56+
words.Add(word.ToString());
57+
word.Clear();
58+
}
59+
}
60+
61+
word.Append(current);
62+
}
63+
if (word.Length > 0)
64+
{
65+
words.Add(word.ToString());
66+
}
67+
68+
return string.Join(' ', words);
69+
}
70+
3671
/// <summary>
3772
/// Returns a new string where every character of the specified string has been replaced by the specified mask character (defaults to '*').
3873
/// </summary>

tests/Logitar.UnitTests/StringExtensionsTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ public void FromUriSafeBase64_uri_safe_base64_is_correctly_parsed(string base64)
3131
Assert.Equal(bytes, other);
3232
}
3333

34+
[Theory(DisplayName = "Humanize: it should return the correct humanized string.")]
35+
[InlineData("", "")]
36+
[InlineData(" ", " ")]
37+
[InlineData("helloWorld", "hello World")]
38+
[InlineData("HelloWorld1!", "Hello World1!")]
39+
[InlineData("UserID", "User ID")]
40+
public void Humanize_it_returns_the_correct_humanized_string(string input, string expected)
41+
{
42+
Assert.Equal(expected, input.Humanize());
43+
}
44+
3445
[Theory(DisplayName = "Mask: it returns the correct masked string.")]
3546
[InlineData(" ")]
3647
[InlineData("P@s$W0rD", '-')]

0 commit comments

Comments
 (0)