From 77201b4835f20d9effefbbc2724c99e91e4d299b Mon Sep 17 00:00:00 2001 From: "Bruni, Ottorino" Date: Wed, 22 May 2024 18:39:51 +0200 Subject: [PATCH 1/4] Add Costant --- TextCase.UnitTests/CamelCaseConverterTest.cs | 2 + .../ConstantCaseConverterTest.cs | 25 +++++++++ TextCase.UnitTests/KebabCaseConverterTest.cs | 7 +-- TextCase/Converters/CamelCaseConverter.cs | 2 +- TextCase/Converters/ConstantCaseConverter.cs | 51 +++++++++++++++++++ TextCase/Converters/KebabCaseConverter.cs | 7 ++- 6 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 TextCase.UnitTests/ConstantCaseConverterTest.cs create mode 100644 TextCase/Converters/ConstantCaseConverter.cs diff --git a/TextCase.UnitTests/CamelCaseConverterTest.cs b/TextCase.UnitTests/CamelCaseConverterTest.cs index 500e11a..ea63a63 100644 --- a/TextCase.UnitTests/CamelCaseConverterTest.cs +++ b/TextCase.UnitTests/CamelCaseConverterTest.cs @@ -11,6 +11,7 @@ public class CamelCaseConverterTest [InlineData("hello world", "helloWorld")] [InlineData("icH bIn glückLICH", "ichBinGlücklich")] [InlineData(" che ore sono? ", "cheOreSono?")] + [InlineData("Enter \"your text here...root = true\n\n[*.{csproj,props,targets}]\"", "enter\"YourTextHere...Root=True\n\n[*.{Csproj,Props,Targets}]\"")] public void Convert_WhenCamelCase_TextShouldBeCamelCase(string input, string output) { // Setup @@ -29,6 +30,7 @@ public void Convert_WhenCamelCase_TextShouldBeCamelCase(string input, string out [InlineData("hello world", "helloWorld")] [InlineData("icH bIn glückLICH", "ichBinGlücklich")] [InlineData(" che ore sono? ", "cheOreSono?")] + [InlineData("Enter \"your text here...root = true\n\n[*.{csproj,props,targets}]\"", "enter\"YourTextHere...Root=True\n\n[*.{Csproj,Props,Targets}]\"")] public void ToCamelCase_WhenCamelCase_TextShouldBeCamelCase(string input, string output) { // Execute diff --git a/TextCase.UnitTests/ConstantCaseConverterTest.cs b/TextCase.UnitTests/ConstantCaseConverterTest.cs new file mode 100644 index 0000000..8d3189a --- /dev/null +++ b/TextCase.UnitTests/ConstantCaseConverterTest.cs @@ -0,0 +1,25 @@ +using TextCase.Converters; +using TextCase.Converters.TextCase.Converters; +using Xunit; + +namespace TextCase.UnitTests +{ + public class ConstantCaseConverterTest + { + [Theory] + [InlineData("hello world", "HELLO_WORLD")] + [InlineData("icH bIn glückLICH", "ICH_BIN_GLÜCKLICH")] + [InlineData("indent_style = space, 2-\nindent_size = 2", "INDENT_STYLE_SPACE_2\nINDENT_SIZE_2")] + public void Convert_WhenConstantCase_TextShouldBeConstantCase(string input, string expected) + { + // Setup + var service = new ConstantCaseConverter(); + + // Execute + var actual = service.Convert(input); + + // Assert + Assert.Equal(expected, actual); + } + } +} \ No newline at end of file diff --git a/TextCase.UnitTests/KebabCaseConverterTest.cs b/TextCase.UnitTests/KebabCaseConverterTest.cs index 77487ec..f7e9132 100644 --- a/TextCase.UnitTests/KebabCaseConverterTest.cs +++ b/TextCase.UnitTests/KebabCaseConverterTest.cs @@ -9,9 +9,10 @@ public class KebabCaseConverterTest [Theory] [InlineData("hello world", "hello-world")] [InlineData("icH bIn glückLICH", "ich-bin-glücklich")] - [InlineData(" che ore sono? ", "che-ore-sono")] - [InlineData("HELLO\tWORLD", "hello-world")] - [InlineData("Hello\nWorld", "hello-world")] + [InlineData("root = true\n\n[*.{csproj,props,targets}]\nindent_style = space\nindent_size = 2", "root-true\n\n[*.{csproj,props,targets}]\nindent-style-space\nindent-size-2")] + [InlineData("indent-style-space\nindent-size-2", "indent-style-space\nindent-size-2")] + [InlineData(" che ore sono? ", "che-ore-sono?")] + [InlineData("HELLO WORLD", "hello-world")] [InlineData(" Hello World ", "hello-world")] [InlineData("", "")] [InlineData(" ", "")] diff --git a/TextCase/Converters/CamelCaseConverter.cs b/TextCase/Converters/CamelCaseConverter.cs index 0e37a3e..34f04b7 100644 --- a/TextCase/Converters/CamelCaseConverter.cs +++ b/TextCase/Converters/CamelCaseConverter.cs @@ -22,7 +22,7 @@ public string Convert(string text) return string.Empty; } - var words = text.Split(new[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); + var words = text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (words.Length == 0) { diff --git a/TextCase/Converters/ConstantCaseConverter.cs b/TextCase/Converters/ConstantCaseConverter.cs new file mode 100644 index 0000000..50850f7 --- /dev/null +++ b/TextCase/Converters/ConstantCaseConverter.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TextCase.Converters +{ + using System; + using System.Text.RegularExpressions; + + namespace TextCase.Converters + { + /// + /// Represents a constant case converter + /// + public class ConstantCaseConverter : ICaseConverter + { + /// + /// Converts the specified text to constant case. + /// + /// The string to convert to constant case. + /// The specified text converted to constant case. + public string Convert(string text) + { + if (string.IsNullOrWhiteSpace(text)) + { + return string.Empty; + } + // Split by newline characters to handle each line separately + var lines = text.Split('\n'); + + for (int i = 0; i < lines.Length; i++) + { + // Remove characters that are not letters, digits, spaces, or underscores + var cleanedLine = Regex.Replace(lines[i], @"[^\w\s-]", string.Empty); + + // Replace spaces and dashes with underscores + var withUnderscores = cleanedLine.Replace(' ', '_').Replace('-', '_'); + + // Convert to uppercase + lines[i] = withUnderscores.ToUpperInvariant(); + } + + // Join the lines back with newline characters + return string.Join('\n', lines); + } + } + } + +} diff --git a/TextCase/Converters/KebabCaseConverter.cs b/TextCase/Converters/KebabCaseConverter.cs index 64d3092..dadd515 100644 --- a/TextCase/Converters/KebabCaseConverter.cs +++ b/TextCase/Converters/KebabCaseConverter.cs @@ -16,14 +16,17 @@ public class KebabCaseConverter : ICaseConverter /// The string to convert to kebab case. /// The specified text converted to kebab case. public string Convert(string text) - { + { if (string.IsNullOrWhiteSpace(text)) { return string.Empty; } - var regex = new Regex(@"[\s\W]+"); + // Replace spaces, equals signs, and underscores with hyphens + var regex = new Regex(@"[ =_]+"); var result = regex.Replace(text.Trim().ToLowerInvariant(), "-"); + + // Remove leading and trailing hyphens return result.Trim('-'); } } From 834964ca293d85bcde882e163dca99234364baec Mon Sep 17 00:00:00 2001 From: Ottorino Bruni Date: Wed, 22 May 2024 21:30:18 +0200 Subject: [PATCH 2/4] Add Cobol Case --- TextCase.UnitTests/CobolCaseConverterTest.cs | 32 +++++++++++ .../ConstantCaseConverterTest.cs | 9 ++- TextCase.UnitTests/TextCase.UnitTests.csproj | 47 +++++++-------- TextCase/Converters/CobolCaseConverter.cs | 36 ++++++++++++ TextCase/Converters/ConstantCaseConverter.cs | 57 +++++++------------ 5 files changed, 118 insertions(+), 63 deletions(-) create mode 100644 TextCase.UnitTests/CobolCaseConverterTest.cs create mode 100644 TextCase/Converters/CobolCaseConverter.cs diff --git a/TextCase.UnitTests/CobolCaseConverterTest.cs b/TextCase.UnitTests/CobolCaseConverterTest.cs new file mode 100644 index 0000000..f187ba4 --- /dev/null +++ b/TextCase.UnitTests/CobolCaseConverterTest.cs @@ -0,0 +1,32 @@ +using TextCase.Converters; +using Xunit; + +namespace TextCase.UnitTests +{ + public class CobolCaseConverterTest + { + [Theory] + [InlineData("hello world", "HELLO-WORLD")] + [InlineData("icH bIn glückLICH", "ICH-BIN-GLÜCKLICH")] + [InlineData("indent_style = space, 2-\nindent_size = 2", "INDENT-STYLE-SPACE-2\nINDENT-SIZE-2")] + [InlineData("Hello World!", "HELLO-WORLD")] + [InlineData("123 test", "123-TEST")] + [InlineData("test with multiple spaces", "TEST-WITH-MULTIPLE-SPACES")] + [InlineData("test_with_underscore", "TEST-WITH-UNDERSCORE")] + [InlineData("test-with-dash", "TEST-WITH-DASH")] + [InlineData("test.with.period", "TEST-WITH-PERIOD")] + [InlineData("test/with/slash", "TEST-WITH-SLASH")] + [InlineData("test\\with\\backslash", "TEST-WITH-BACKSLASH")] + public void Convert_WhenConstantCase_TextShouldBeConstantCase(string input, string expected) + { + // Setup + var service = new CobolCaseConverter(); + + // Execute + var actual = service.Convert(input); + + // Assert + Assert.Equal(expected, actual); + } + } +} \ No newline at end of file diff --git a/TextCase.UnitTests/ConstantCaseConverterTest.cs b/TextCase.UnitTests/ConstantCaseConverterTest.cs index 8d3189a..d972194 100644 --- a/TextCase.UnitTests/ConstantCaseConverterTest.cs +++ b/TextCase.UnitTests/ConstantCaseConverterTest.cs @@ -1,5 +1,4 @@ using TextCase.Converters; -using TextCase.Converters.TextCase.Converters; using Xunit; namespace TextCase.UnitTests @@ -10,6 +9,14 @@ public class ConstantCaseConverterTest [InlineData("hello world", "HELLO_WORLD")] [InlineData("icH bIn glückLICH", "ICH_BIN_GLÜCKLICH")] [InlineData("indent_style = space, 2-\nindent_size = 2", "INDENT_STYLE_SPACE_2\nINDENT_SIZE_2")] + [InlineData("Hello World!", "HELLO_WORLD")] + [InlineData("123 test", "123_TEST")] + [InlineData("test with multiple spaces", "TEST_WITH_MULTIPLE_SPACES")] + [InlineData("test_with_underscore", "TEST_WITH_UNDERSCORE")] + [InlineData("test-with-dash", "TEST_WITH_DASH")] + [InlineData("test.with.period", "TEST_WITH_PERIOD")] + [InlineData("test/with/slash", "TEST_WITH_SLASH")] + [InlineData("test\\with\\backslash", "TEST_WITH_BACKSLASH")] public void Convert_WhenConstantCase_TextShouldBeConstantCase(string input, string expected) { // Setup diff --git a/TextCase.UnitTests/TextCase.UnitTests.csproj b/TextCase.UnitTests/TextCase.UnitTests.csproj index ce511c3..7987c93 100644 --- a/TextCase.UnitTests/TextCase.UnitTests.csproj +++ b/TextCase.UnitTests/TextCase.UnitTests.csproj @@ -1,26 +1,21 @@ - - - - net8.0 - - false - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - + + + net8.0 + false + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + \ No newline at end of file diff --git a/TextCase/Converters/CobolCaseConverter.cs b/TextCase/Converters/CobolCaseConverter.cs new file mode 100644 index 0000000..7769dc9 --- /dev/null +++ b/TextCase/Converters/CobolCaseConverter.cs @@ -0,0 +1,36 @@ +using System.Linq; +using System.Text.RegularExpressions; + +namespace TextCase.Converters +{ + /// + /// Represents a cobol case converter + /// + public class CobolCaseConverter : ICaseConverter + { + /// + /// Converts the specified text to constant case. + /// + /// The string to convert to cobol case. + /// The specified text converted to cobol case. + public string Convert(string text) + { + if (string.IsNullOrWhiteSpace(text)) + { + return string.Empty; + } + + // Replace one or more consecutive non-alphanumeric characters (except newlines) with a single dash + var replacedPunctuation = Regex.Replace(text, @"[^\w\n]+", "-"); + + // Split the text into lines + var lines = replacedPunctuation.Split('\n'); + + // Convert each line to upper case and trim leading and trailing dashes + var processedLines = lines.Select(line => line.Trim().ToUpperInvariant().Trim('-')); + + // Join the lines back together + return string.Join("\n", processedLines); + } + } +} diff --git a/TextCase/Converters/ConstantCaseConverter.cs b/TextCase/Converters/ConstantCaseConverter.cs index 50850f7..56f0408 100644 --- a/TextCase/Converters/ConstantCaseConverter.cs +++ b/TextCase/Converters/ConstantCaseConverter.cs @@ -1,51 +1,36 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Linq; +using System.Text.RegularExpressions; namespace TextCase.Converters { - using System; - using System.Text.RegularExpressions; - - namespace TextCase.Converters + /// + /// Represents a constant case converter + /// + public class ConstantCaseConverter : ICaseConverter { /// - /// Represents a constant case converter + /// Converts the specified text to constant case. /// - public class ConstantCaseConverter : ICaseConverter + /// The string to convert to constant case. + /// The specified text converted to constant case. + public string Convert(string text) { - /// - /// Converts the specified text to constant case. - /// - /// The string to convert to constant case. - /// The specified text converted to constant case. - public string Convert(string text) + if (string.IsNullOrWhiteSpace(text)) { - if (string.IsNullOrWhiteSpace(text)) - { - return string.Empty; - } - // Split by newline characters to handle each line separately - var lines = text.Split('\n'); + return string.Empty; + } - for (int i = 0; i < lines.Length; i++) - { - // Remove characters that are not letters, digits, spaces, or underscores - var cleanedLine = Regex.Replace(lines[i], @"[^\w\s-]", string.Empty); + // Replace one or more consecutive non-alphanumeric characters (except newlines) with a single underscore + var replacedPunctuation = Regex.Replace(text, @"[^\w\n]+", "_"); - // Replace spaces and dashes with underscores - var withUnderscores = cleanedLine.Replace(' ', '_').Replace('-', '_'); + // Split the text into lines + var lines = replacedPunctuation.Split('\n'); - // Convert to uppercase - lines[i] = withUnderscores.ToUpperInvariant(); - } + // Convert each line to upper case and trim leading and trailing underscores + var processedLines = lines.Select(line => line.Trim().ToUpperInvariant().Trim('_')); - // Join the lines back with newline characters - return string.Join('\n', lines); - } + // Join the lines back together + return string.Join("\n", processedLines); } } - } From b3628082ea95857ba7cc1c6cd7d0d97bcc0c5662 Mon Sep 17 00:00:00 2001 From: "Bruni, Ottorino" Date: Thu, 23 May 2024 08:01:53 +0200 Subject: [PATCH 3/4] Add Cobol Case Converter --- TextCase/Converters/CobolCaseConverter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TextCase/Converters/CobolCaseConverter.cs b/TextCase/Converters/CobolCaseConverter.cs index 7769dc9..28511c6 100644 --- a/TextCase/Converters/CobolCaseConverter.cs +++ b/TextCase/Converters/CobolCaseConverter.cs @@ -20,8 +20,8 @@ public string Convert(string text) return string.Empty; } - // Replace one or more consecutive non-alphanumeric characters (except newlines) with a single dash - var replacedPunctuation = Regex.Replace(text, @"[^\w\n]+", "-"); + // Replace one or more consecutive non-letter, non-digit, non-newline characters with a single dash + var replacedPunctuation = Regex.Replace(text, @"[^\p{L}0-9\n]+", "-"); // Split the text into lines var lines = replacedPunctuation.Split('\n'); From 391b82bdd71e8ecb12a105075891f3e6a6b851c1 Mon Sep 17 00:00:00 2001 From: "Bruni, Ottorino" Date: Thu, 23 May 2024 08:43:59 +0200 Subject: [PATCH 4/4] Fix Tests --- README.md | 26 ++++++- .../CapitaliseCaseConverterTest.cs | 4 +- .../CapitaliseWordsCaseConverterTest.cs | 8 +-- TextCase.UnitTests/CobolCaseConverterTest.cs | 24 +++++++ .../ConstantCaseConverterTest.cs | 24 +++++++ .../HashtagCaseConverterTest.cs | 10 +-- .../InverseCaseConverterTest.cs | 44 ++++++++++++ TextCase.UnitTests/PascalCaseConverterTest.cs | 20 ++++++ TextCase.UnitTests/TrainCaseConverterTest.cs | 61 +++++++++++++++++ TextCase/Converters/HashtagCaseConverter.cs | 10 +-- TextCase/Converters/InverseCaseConverter.cs | 40 +++++++++++ TextCase/Converters/TrainCaseConverter.cs | 41 +++++++++++ TextCase/Extensions/StringExtensions.cs | 68 +++++++++++++++---- TextCase/TextCase.cs | 10 ++- TextCase/TextCase.csproj | 2 +- TextCase/TextCaseFactory.cs | 10 ++- 16 files changed, 362 insertions(+), 40 deletions(-) create mode 100644 TextCase.UnitTests/InverseCaseConverterTest.cs create mode 100644 TextCase.UnitTests/TrainCaseConverterTest.cs create mode 100644 TextCase/Converters/InverseCaseConverter.cs create mode 100644 TextCase/Converters/TrainCaseConverter.cs diff --git a/README.md b/README.md index 6dfb229..ad5bf4f 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,11 @@ There are the cases currently available: - PascalCase - KebabCase - SnackCase -- HashtagCase +- HashTagCase +- ConstantCase +- CobolCase +- InverseCase +- TrainCase It's possible to count in the text: - number of characters @@ -73,8 +77,24 @@ TextCase.Convert("You talking to me?", Case.SnackCase); "You talking to me?".ToSnackCase(); // #You #talking #to #me? -TextCase.Convert("You talking to me?", Case.HashtagCase); -"You talking to me?".ToHashtagCase(); +TextCase.Convert("You talking to me?", Case.HashTagCase); +"You talking to me?".ToHashTagCase(); + +// YOU_TALKING_TO_ME +TextCase.Convert("You talking to me?", Case.ConstantCase); +"You talking to me?".ToConstantCase(); + +// YOU-TALKING-TO-ME +TextCase.Convert("You talking to me?", Case.CobolCase); +"You talking to me?".ToCobolCase(); + +// yOu TaLkInG tO mE? +TextCase.Convert("You talking to me?", Case.InverseCase); +"You talking to me?".ToInverseCase(); + +// You-Talking-To-Me +TextCase.Convert("You talking to me?", Case.TrainCase); +"You talking to me?".ToTrainCase(); // Text Count TextCase.GetTextCount("You talking to me?"); diff --git a/TextCase.UnitTests/CapitaliseCaseConverterTest.cs b/TextCase.UnitTests/CapitaliseCaseConverterTest.cs index 4f1e89f..130c9bb 100644 --- a/TextCase.UnitTests/CapitaliseCaseConverterTest.cs +++ b/TextCase.UnitTests/CapitaliseCaseConverterTest.cs @@ -29,10 +29,10 @@ public void Convert_WhenCapitaliseCase_TextShouldBeCapitaliseCase(string input, [InlineData("Hello World", "Hello world")] [InlineData("ICH BIN GLÜCKLICH", "Ich bin glücklich")] [InlineData(" che ore SONO? ", "Che ore sono?")] - public void ToCapitaliseCase_WhenCapitaliseCase_TextShouldBeCapitaliseCase(string input, string output) + public void ToCapitalizeCase_WhenCapitalizeCase_TextShouldBeCapitalizeCase(string input, string output) { // Execute - var convertedText = input.ToCapitaliseCase(); + var convertedText = input.ToCapitalizeCase(); // Assert var expected = output; diff --git a/TextCase.UnitTests/CapitaliseWordsCaseConverterTest.cs b/TextCase.UnitTests/CapitaliseWordsCaseConverterTest.cs index ba94ebc..fb5ad99 100644 --- a/TextCase.UnitTests/CapitaliseWordsCaseConverterTest.cs +++ b/TextCase.UnitTests/CapitaliseWordsCaseConverterTest.cs @@ -5,13 +5,13 @@ namespace TextCase.UnitTests { - public class CapitaliseWordsCaseConverterTest + public class CapitalizeWordsCaseConverterTest { [Theory] [InlineData("Hello World", "Hello World")] [InlineData("ICH BIN GLÜCKLICH", "Ich Bin Glücklich")] [InlineData(" che ore SONO? ", " Che Ore Sono? ")] - public void Convert_WhenCapitaliseCase_TextShouldBeCapitaliseCase(string input, string output) + public void Convert_WhenCapitalizeCase_TextShouldBeCapitalizeCase(string input, string output) { // Setup var service = new CapitaliseWordsCaseConverter(); @@ -29,10 +29,10 @@ public void Convert_WhenCapitaliseCase_TextShouldBeCapitaliseCase(string input, [InlineData("Hello World", "Hello World")] [InlineData("ICH BIN GLÜCKLICH", "Ich Bin Glücklich")] [InlineData(" che ore SONO? ", " Che Ore Sono? ")] - public void ToCapitaliseWordsCase_WhenCapitaliseCase_TextShouldBeCapitaliseCase(string input, string output) + public void ToCapitalizeWordsCase_WhenCapitalizeCase_TextShouldBeCapitalizeCase(string input, string output) { // Execute - var convertedText = input.ToCapitaliseWordsCase(); + var convertedText = input.ToCapitalizeWordsCase(); // Assert var expected = output; diff --git a/TextCase.UnitTests/CobolCaseConverterTest.cs b/TextCase.UnitTests/CobolCaseConverterTest.cs index f187ba4..f79847f 100644 --- a/TextCase.UnitTests/CobolCaseConverterTest.cs +++ b/TextCase.UnitTests/CobolCaseConverterTest.cs @@ -1,4 +1,5 @@ using TextCase.Converters; +using TextCase.Extensions; using Xunit; namespace TextCase.UnitTests @@ -28,5 +29,28 @@ public void Convert_WhenConstantCase_TextShouldBeConstantCase(string input, stri // Assert Assert.Equal(expected, actual); } + + [Theory] + [InlineData("hello world", "HELLO-WORLD")] + [InlineData("icH bIn glückLICH", "ICH-BIN-GLÜCKLICH")] + [InlineData("indent_style = space, 2-\nindent_size = 2", "INDENT-STYLE-SPACE-2\nINDENT-SIZE-2")] + [InlineData("Hello World!", "HELLO-WORLD")] + [InlineData("123 test", "123-TEST")] + [InlineData("test with multiple spaces", "TEST-WITH-MULTIPLE-SPACES")] + [InlineData("test_with_underscore", "TEST-WITH-UNDERSCORE")] + [InlineData("test-with-dash", "TEST-WITH-DASH")] + [InlineData("test.with.period", "TEST-WITH-PERIOD")] + [InlineData("test/with/slash", "TEST-WITH-SLASH")] + [InlineData("test\\with\\backslash", "TEST-WITH-BACKSLASH")] + public void ToCobolCase_WhenCobolCase_TextShouldBeCobolCase(string input, string output) + { + // Execute + var convertedText = input.ToCobolCase(); + + // Assert + var expected = output; + var actual = convertedText; + Assert.Equal(expected, actual); + } } } \ No newline at end of file diff --git a/TextCase.UnitTests/ConstantCaseConverterTest.cs b/TextCase.UnitTests/ConstantCaseConverterTest.cs index d972194..5592c1d 100644 --- a/TextCase.UnitTests/ConstantCaseConverterTest.cs +++ b/TextCase.UnitTests/ConstantCaseConverterTest.cs @@ -1,4 +1,5 @@ using TextCase.Converters; +using TextCase.Extensions; using Xunit; namespace TextCase.UnitTests @@ -28,5 +29,28 @@ public void Convert_WhenConstantCase_TextShouldBeConstantCase(string input, stri // Assert Assert.Equal(expected, actual); } + + [Theory] + [InlineData("hello world", "HELLO_WORLD")] + [InlineData("icH bIn glückLICH", "ICH_BIN_GLÜCKLICH")] + [InlineData("indent_style = space, 2-\nindent_size = 2", "INDENT_STYLE_SPACE_2\nINDENT_SIZE_2")] + [InlineData("Hello World!", "HELLO_WORLD")] + [InlineData("123 test", "123_TEST")] + [InlineData("test with multiple spaces", "TEST_WITH_MULTIPLE_SPACES")] + [InlineData("test_with_underscore", "TEST_WITH_UNDERSCORE")] + [InlineData("test-with-dash", "TEST_WITH_DASH")] + [InlineData("test.with.period", "TEST_WITH_PERIOD")] + [InlineData("test/with/slash", "TEST_WITH_SLASH")] + [InlineData("test\\with\\backslash", "TEST_WITH_BACKSLASH")] + public void ToConstantCase_WhenConstantCase_TextShouldBeConstantCase(string input, string output) + { + // Execute + var convertedText = input.ToConstantCase(); + + // Assert + var expected = output; + var actual = convertedText; + Assert.Equal(expected, actual); + } } } \ No newline at end of file diff --git a/TextCase.UnitTests/HashtagCaseConverterTest.cs b/TextCase.UnitTests/HashtagCaseConverterTest.cs index ce0b734..38c647a 100644 --- a/TextCase.UnitTests/HashtagCaseConverterTest.cs +++ b/TextCase.UnitTests/HashtagCaseConverterTest.cs @@ -5,16 +5,16 @@ namespace TextCase.UnitTests { - public class HashtagCaseConverterTest + public class HashTagCaseConverterTest { [Theory] [InlineData("hello world", "#hello #world")] [InlineData("icH bIn glückLICH", "#icH #bIn #glückLICH")] [InlineData(" che ore sono? ", "#che #ore #sono?")] - public void Convert_WhenHashtagCase_TextShouldBeHashtagCase(string input, string output) + public void Convert_WhenHashTagCase_TextShouldBeHashTagCase(string input, string output) { // Setup - var service = new HashtagCaseConverter(); + var service = new HashTagCaseConverter(); // Execute var convertedText = service.Convert(input); @@ -29,10 +29,10 @@ public void Convert_WhenHashtagCase_TextShouldBeHashtagCase(string input, string [InlineData("hello world", "#hello #world")] [InlineData("icH bIn glückLICH", "#icH #bIn #glückLICH")] [InlineData(" che ore sono? ", "#che #ore #sono?")] - public void ToHashtagCase_WhenHashtagCase_TextShouldBeHashtagCase(string input, string output) + public void ToHashTagCase_WhenHashTagCase_TextShouldBeHashTagCase(string input, string output) { // Execute - var convertedText = input.ToHashtagCase(); + var convertedText = input.ToHashTagCase(); // Assert var expected = output; diff --git a/TextCase.UnitTests/InverseCaseConverterTest.cs b/TextCase.UnitTests/InverseCaseConverterTest.cs new file mode 100644 index 0000000..773e7a0 --- /dev/null +++ b/TextCase.UnitTests/InverseCaseConverterTest.cs @@ -0,0 +1,44 @@ +using System; +using TextCase.Converters; +using TextCase.Extensions; +using Xunit; + +namespace TextCase.UnitTests +{ + public class InverseCaseConverterTest + { + [Theory] + [InlineData("hello world", "hElLo WoRlD")] + [InlineData("icH bIn glückLICH", "iCh BiN gLüCkLiCh")] + [InlineData(" che ore sono? ", " cHe OrE sOnO? ")] + public void Convert_WhenCamelCase_TextShouldBeCamelCase(string input, string output) + { + // Setup + var service = new InverseCaseConverter(); + + // Execute + var convertedText = service.Convert(input); + + // Assert + var expected = output; + var actual = convertedText; + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("hello world", "hElLo WoRlD")] + [InlineData("icH bIn glückLICH", "iCh BiN gLüCkLiCh")] + [InlineData(" che ore sono? ", " cHe OrE sOnO? ")] + [InlineData("You talking to me?", "yOu TaLkInG tO mE?")] + public void ToInverseCase_WhenCamelCase_TextShouldBeCamelCase(string input, string output) + { + // Execute + var convertedText = input.ToInverseCase(); + + // Assert + var expected = output; + var actual = convertedText; + Assert.Equal(expected, actual); + } + } +} \ No newline at end of file diff --git a/TextCase.UnitTests/PascalCaseConverterTest.cs b/TextCase.UnitTests/PascalCaseConverterTest.cs index 587a391..9bb77af 100644 --- a/TextCase.UnitTests/PascalCaseConverterTest.cs +++ b/TextCase.UnitTests/PascalCaseConverterTest.cs @@ -1,5 +1,6 @@ using System; using TextCase.Converters; +using TextCase.Extensions; using Xunit; namespace TextCase.UnitTests @@ -27,5 +28,24 @@ public void Convert_WhenPascalCase_TextShouldBePascalCase(string input, string o var actual = convertedText; Assert.Equal(expected, actual); } + + [Theory] + [InlineData("hello world", "HelloWorld")] + [InlineData("icH bIn glückLICH", "IchBinGlücklich")] + [InlineData(" che ore sono? ", "CheOreSono?")] + [InlineData("iPhone", "Iphone")] + [InlineData(" Hello World ", "HelloWorld")] + [InlineData("hello\tworld", "HelloWorld")] + [InlineData("Hello\nWorld", "HelloWorld")] + public void ToPascalCase_WhenUpperCase_TextShouldBePascalCase(string input, string output) + { + // Execute + var convertedText = input.ToPascalCase(); + + // Assert + var expected = output; + var actual = convertedText; + Assert.Equal(expected, actual); + } } } \ No newline at end of file diff --git a/TextCase.UnitTests/TrainCaseConverterTest.cs b/TextCase.UnitTests/TrainCaseConverterTest.cs new file mode 100644 index 0000000..208d7a8 --- /dev/null +++ b/TextCase.UnitTests/TrainCaseConverterTest.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TextCase.Converters; +using TextCase.Extensions; +using Xunit; + +namespace TextCase.UnitTests +{ + public class TrainCaseConverterTest + { + [Theory] + [InlineData("hello world", "Hello-World")] + [InlineData("icH bIn glückLICH", "Ich-Bin-Glücklich")] + [InlineData("indent_style = space, 2-\nindent_size = 2", "Indent-Style-Space-2\nIndent-Size-2")] + [InlineData("Hello World!", "Hello-World")] + [InlineData("123 test", "123-Test")] + [InlineData("test with multiple spaces", "Test-With-Multiple-Spaces")] + [InlineData("test_with_underscore", "Test-With-Underscore")] + [InlineData("test-with-dash", "Test-With-Dash")] + [InlineData("test.with.period", "Test-With-Period")] + [InlineData("test/with/slash", "Test-With-Slash")] + [InlineData("test\\with\\backslash", "Test-With-Backslash")] + public void Convert_WhenTrainCase_TextShouldBeTrainCase(string input, string expected) + { + // Setup + var service = new TrainCaseConverter(); + + // Execute + var actual = service.Convert(input); + + // Assert + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("hello world", "Hello-World")] + [InlineData("icH bIn glückLICH", "Ich-Bin-Glücklich")] + [InlineData("indent_style = space, 2-\nindent_size = 2", "Indent-Style-Space-2\nIndent-Size-2")] + [InlineData("Hello World!", "Hello-World")] + [InlineData("123 test", "123-Test")] + [InlineData("test with multiple spaces", "Test-With-Multiple-Spaces")] + [InlineData("test_with_underscore", "Test-With-Underscore")] + [InlineData("test-with-dash", "Test-With-Dash")] + [InlineData("test.with.period", "Test-With-Period")] + [InlineData("test/with/slash", "Test-With-Slash")] + [InlineData("test\\with\\backslash", "Test-With-Backslash")] + public void ToTrainCase_WhenTrainCase_TextShouldBeTrainCase(string input, string output) + { + // Execute + var convertedText = input.ToTrainCase(); + + // Assert + var expected = output; + var actual = convertedText; + Assert.Equal(expected, actual); + } + } +} diff --git a/TextCase/Converters/HashtagCaseConverter.cs b/TextCase/Converters/HashtagCaseConverter.cs index e9728d6..8236093 100644 --- a/TextCase/Converters/HashtagCaseConverter.cs +++ b/TextCase/Converters/HashtagCaseConverter.cs @@ -4,15 +4,15 @@ namespace TextCase.Converters { /// - /// Represents a hashtag converter + /// Represents a hash-tag converter /// - public class HashtagCaseConverter : ICaseConverter + public class HashTagCaseConverter : ICaseConverter { /// - /// Converts the specified text to hashtag case. + /// Converts the specified text to hash-tag case. /// - /// The string to convert to hashtag case. - /// The specified text converted to hashtag case. + /// The string to convert to hash-tag case. + /// The specified text converted to hash-tag case. public string Convert(string text) { if (string.IsNullOrWhiteSpace(text)) diff --git a/TextCase/Converters/InverseCaseConverter.cs b/TextCase/Converters/InverseCaseConverter.cs new file mode 100644 index 0000000..a90fee4 --- /dev/null +++ b/TextCase/Converters/InverseCaseConverter.cs @@ -0,0 +1,40 @@ +using System; +using System.Globalization; +using System.Text; +using TextCase.Extensions; + +namespace TextCase.Converters +{ + /// + /// Represents an inverse converter + /// + public class InverseCaseConverter : ICaseConverter + { + /// + /// Converts the specified text to inverse case. + /// + /// The string to convert to inverse case. + /// The specified text converted to inverse case. + public string Convert(string text) + { + if (string.IsNullOrWhiteSpace(text)) + { + return string.Empty; + } + + var builder = new StringBuilder(); + var isUpper = false; + + foreach (var c in text) + { + builder.Append(isUpper ? char.ToUpperInvariant(c) : char.ToLowerInvariant(c)); + if (!char.IsWhiteSpace(c)) + { + isUpper = !isUpper; + } + } + + return builder.ToString(); + } + } +} diff --git a/TextCase/Converters/TrainCaseConverter.cs b/TextCase/Converters/TrainCaseConverter.cs new file mode 100644 index 0000000..29f7e6b --- /dev/null +++ b/TextCase/Converters/TrainCaseConverter.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace TextCase.Converters +{ + /// + /// Represents a train case converter + /// + public class TrainCaseConverter : ICaseConverter + { + /// + /// Converts the specified text to train case. + /// + /// The string to convert to train case. + /// The specified text converted to train case. + public string Convert(string text) + { + if (string.IsNullOrWhiteSpace(text)) + { + return string.Empty; + } + + // Replace one or more consecutive non-letter, non-digit, non-newline characters with a single dash + var replacedPunctuation = Regex.Replace(text, @"[^\p{L}0-9\n]+", "-"); + + // Split the text into lines + var lines = replacedPunctuation.Split('\n'); + + // Convert each line to title case and trim leading and trailing dashes + var processedLines = lines.Select(line => CultureInfo.InvariantCulture.TextInfo.ToTitleCase(line.ToLowerInvariant()).Trim('-')); + + // Join the lines back together + return string.Join("\n", processedLines); + } + } +} diff --git a/TextCase/Extensions/StringExtensions.cs b/TextCase/Extensions/StringExtensions.cs index 72f8c6e..20331f7 100644 --- a/TextCase/Extensions/StringExtensions.cs +++ b/TextCase/Extensions/StringExtensions.cs @@ -103,23 +103,23 @@ public static string ToTitleCase(this string value) } /// - /// Converts the specified text to capitalise case. + /// Converts the specified text to capitalize case. /// - /// The string to convert to capitalise case. - /// The specified text converted to capitalise case. - public static string ToCapitaliseCase(this string value) + /// The string to convert to capitalize case. + /// The specified text converted to capitalize case. + public static string ToCapitalizeCase(this string value) { - return TextCase.Convert(value, Case.CapitaliseCase); - } - + return TextCase.Convert(value, Case.CapitalizeCase); + } + /// - /// Converts the specified text to capitalise words case. + /// Converts the specified text to capitalize words case. /// - /// The string to convert to capitalise words case. - /// The specified text converted to capitalise words case. - public static string ToCapitaliseWordsCase(this string value) + /// The string to convert to capitalize words case. + /// The specified text converted to capitalize words case. + public static string ToCapitalizeWordsCase(this string value) { - return TextCase.Convert(value, Case.CapitaliseWordsCase); + return TextCase.Convert(value, Case.CapitalizeWordsCase); } /// @@ -187,9 +187,49 @@ public static string ToSnackCase(this string value) /// /// The string to convert to hashtag case. /// The specified text converted to hashtag case. - public static string ToHashtagCase(this string value) + public static string ToHashTagCase(this string value) + { + return TextCase.Convert(value, Case.HashTagCase); + } + + /// + /// Converts the specified text to constant case. + /// + /// The string to convert to constant case. + /// The specified text converted to constant case. + public static string ToConstantCase(this string value) + { + return TextCase.Convert(value, Case.ConstantCase); + } + + /// + /// Converts the specified text to cobol case. + /// + /// The string to convert to cobol case. + /// The specified text converted to cobol case. + public static string ToCobolCase(this string value) + { + return TextCase.Convert(value, Case.CobolCase); + } + + /// + /// Converts the specified text to inverse case. + /// + /// The string to convert to inverse case. + /// The specified text converted to inverse case. + public static string ToInverseCase(this string value) + { + return TextCase.Convert(value, Case.InverseCase); + } + + /// + /// Converts the specified text to train case. + /// + /// The string to convert to train case. + /// The specified text converted to train case. + public static string ToTrainCase(this string value) { - return TextCase.Convert(value, Case.HashtagCase); + return TextCase.Convert(value, Case.TrainCase); } } } diff --git a/TextCase/TextCase.cs b/TextCase/TextCase.cs index 281912f..b1ca174 100644 --- a/TextCase/TextCase.cs +++ b/TextCase/TextCase.cs @@ -9,15 +9,19 @@ public enum Case UpperCase, LowerCase, TitleCase, - CapitaliseCase, - CapitaliseWordsCase, + CapitalizeCase, + CapitalizeWordsCase, ReverseCase, AlternateCase, CamelCase, PascalCase, KebabCase, SnackCase, - HashtagCase + HashTagCase, + ConstantCase, + CobolCase, + TrainCase, + InverseCase } public static class TextCase diff --git a/TextCase/TextCase.csproj b/TextCase/TextCase.csproj index ef91483..acb80d8 100644 --- a/TextCase/TextCase.csproj +++ b/TextCase/TextCase.csproj @@ -2,7 +2,7 @@ net8.0 TextCase - 1.0.7 + 1.0.8 Ottorino Bruni The TextCase library for .NET helps changing the cases of existing texts. true diff --git a/TextCase/TextCaseFactory.cs b/TextCase/TextCaseFactory.cs index c2bcdf8..d68bbf2 100644 --- a/TextCase/TextCaseFactory.cs +++ b/TextCase/TextCaseFactory.cs @@ -12,15 +12,19 @@ internal static ICaseConverter GetCaseConverter(Case textCase) Case.UpperCase => new UpperCaseConverter(), Case.LowerCase => new LowerCaseConverter(), Case.TitleCase => new TitleCaseConverter(), - Case.CapitaliseCase => new CapitaliseCaseConverter(), - Case.CapitaliseWordsCase => new CapitaliseWordsCaseConverter(), + Case.CapitalizeCase => new CapitaliseCaseConverter(), + Case.CapitalizeWordsCase => new CapitaliseWordsCaseConverter(), Case.ReverseCase => new ReverseCaseConverter(), Case.AlternateCase => new AlternateCaseConverter(), Case.CamelCase => new CamelCaseConverter(), Case.PascalCase => new PascalCaseConverter(), Case.KebabCase => new KebabCaseConverter(), Case.SnackCase => new SnackCaseConverter(), - Case.HashtagCase => new HashtagCaseConverter(), + Case.HashTagCase => new HashTagCaseConverter(), + Case.ConstantCase => new ConstantCaseConverter(), + Case.CobolCase => new CobolCaseConverter(), + Case.TrainCase => new TrainCaseConverter(), + Case.InverseCase => new InverseCaseConverter(), _ => throw new ArgumentException("No valid TextCase"), }; }