diff --git a/.editorconfig b/.editorconfig index 3848020..bdd4559 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,7 +5,7 @@ indent_style = tab indent_size = 4 tab_width = 4 end_of_line = lf -insert_final_newline = false +insert_final_newline = true trim_trailing_whitespace = true max_line_length = 120 @@ -14,22 +14,20 @@ indent_size = 2 indent_style = space trim_trailing_whitespace = false -[*.{csproj,props,targets,slnx}] +[*.{csproj,props,targets,slnx,config}] indent_size = 2 indent_style = space -[nuget.config] -indent_size = 2 -indent_style = space +[*.{cs,vb}] +#### code style rule default severity #### +dotnet_analyzer_diagnostic.category-style.severity = warning #### .NET Coding Conventions #### [*.{cs,vb}] - # Organize usings file_header_template = Copyright (c) The Geekeey Authors\nSPDX-License-Identifier: EUPL-1.2 dotnet_separate_import_directive_groups = true dotnet_sort_system_directives_first = true -dotnet_diagnostic.IDE0005.severity = suggestion # https://github.com/dotnet/roslyn/issues/41640 # this. and Me. preferences dotnet_style_qualification_for_event = false @@ -51,9 +49,8 @@ dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity dotnet_style_require_accessibility_modifiers = for_non_interface_members # Expression-level preferences - dotnet_diagnostic.IDE0270.severity = none -dotnet_style_coalesce_expression = true # IDE0029,IDE0030,IDE0270 +dotnet_style_coalesce_expression = true dotnet_style_collection_initializer = true dotnet_style_explicit_tuple_names = true @@ -64,16 +61,17 @@ dotnet_style_prefer_auto_properties = true dotnet_style_prefer_compound_assignment = true dotnet_diagnostic.IDE0045.severity = suggestion -dotnet_style_prefer_conditional_expression_over_assignment = true # IDE0045 +dotnet_style_prefer_conditional_expression_over_assignment = true + dotnet_diagnostic.IDE0046.severity = suggestion -dotnet_style_prefer_conditional_expression_over_return = true # IDE0046 +dotnet_style_prefer_conditional_expression_over_return = true dotnet_style_prefer_inferred_anonymous_type_member_names = true dotnet_style_prefer_inferred_tuple_names = true dotnet_style_prefer_is_null_check_over_reference_equality_method = true dotnet_style_prefer_simplified_boolean_expressions = true dotnet_style_prefer_simplified_interpolation = true -dotnet_style_namespace_match_folder = false # resharper: resharper_check_namespace_highlighting +dotnet_style_namespace_match_folder = false # Field preferences dotnet_style_readonly_field = true @@ -81,11 +79,6 @@ dotnet_style_readonly_field = true # Suppression preferences dotnet_remove_unnecessary_suppression_exclusions = none -# ReSharper preferences -resharper_wrap_object_and_collection_initializer_style = chop_always -resharper_check_namespace_highlighting = none -resharper_csharp_wrap_lines = false - #### C# Coding Conventions #### [*.cs] @@ -121,6 +114,7 @@ csharp_preferred_modifier_order = public, private, protected, internal, static, # Code-block preferences csharp_prefer_braces = true csharp_prefer_simple_using_statement = true +csharp_style_prefer_top_level_statements = false # Expression-level preferences csharp_prefer_simple_default_expression = true @@ -132,8 +126,8 @@ csharp_style_prefer_range_operator = true csharp_style_throw_expression = true dotnet_diagnostic.IDE0058.severity = suggestion -csharp_style_unused_value_assignment_preference = discard_variable # IDE0058 -csharp_style_unused_value_expression_statement_preference = discard_variable # IDE0058 +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable # 'using' directive preferences csharp_using_directive_placement = outside_namespace @@ -401,19 +395,3 @@ dotnet_naming_style.s_camelcase.required_prefix = s_ dotnet_naming_style.s_camelcase.required_suffix = dotnet_naming_style.s_camelcase.word_separator = dotnet_naming_style.s_camelcase.capitalization = camel_case - -[*.{cs,vb}] -dotnet_analyzer_diagnostic.category-style.severity = warning -dotnet_analyzer_diagnostic.category-design.severity = warning -dotnet_analyzer_diagnostic.category-globalization.severity = notice -dotnet_analyzer_diagnostic.category-naming.severity = warning -dotnet_analyzer_diagnostic.category-performance.severity = warning -dotnet_analyzer_diagnostic.category-reliability.severity = warning -dotnet_analyzer_diagnostic.category-security.severity = warning -dotnet_analyzer_diagnostic.category-usage.severity = warning -dotnet_analyzer_diagnostic.category-maintainability.severity = warning - -dotnet_diagnostic.CA1716.severity = none # Identifiers should not match keywords -dotnet_diagnostic.CA1816.severity = suggestion # Dispose methods should call SuppressFinalize -dotnet_diagnostic.CA1848.severity = none # Use the LoggerMessage delegates -dotnet_diagnostic.IDE0210.severity = none # Use top-level statements diff --git a/CHANGELOG.md b/CHANGELOG.md index 81779d4..1ba22dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.0.0] - 2026-01-22 +## [1.0.0] - 2026-05-21 ### Added @@ -19,4 +19,4 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Removed [1.0.0]: https://code.geekeey.de/geekeey/semver/releases/tag/1.0.0 -[Unreleased]: https://code.geekeey.de/geekeey/semver/compare/1.0.0...HEAD \ No newline at end of file +[Unreleased]: https://code.geekeey.de/geekeey/semver/compare/1.0.0...HEAD diff --git a/README.md b/README.md index 335f284..25709ac 100644 --- a/README.md +++ b/README.md @@ -24,4 +24,59 @@ You may need to add our NuGet feed to your `nuget.config` this can be done by ru dotnet nuget add source -n geekeey https://code.geekeey.de/api/packages/geekeey/nuget/index.json ``` -### Usage \ No newline at end of file +### Usage + +```csharp +using Geekeey.SemVer; + +var version = SemanticVersion.Parse("1.2.3-beta+build.7"); +var next = new SemanticVersion(1, 3, 0); + +Console.WriteLine(version); +Console.WriteLine(version.Major); +Console.WriteLine(version.Prerelease); +Console.WriteLine(version.Metadata); +Console.WriteLine(version < next); +``` + +You can also use `TryParse` when you need to handle invalid input without exceptions. + +```csharp +using Geekeey.SemVer; + +if (SemanticVersion.TryParse("1.2.3-alpha", out var parsed)) +{ + Console.WriteLine(parsed); +} +``` + +Version ranges support npm-style and Maven-style syntax. + +```csharp +using Geekeey.SemVer; + +var npmRange = SemanticVersionRange.Parse("^1.2.3"); +var mavenRange = SemanticVersionRange.Parse("[1.2.3,2.0.0)"); +var candidate = SemanticVersion.Parse("1.4.2"); + +Console.WriteLine(npmRange.Contains(candidate)); +Console.WriteLine(mavenRange.Contains(candidate)); +Console.WriteLine(npmRange.ToString("m", null)); +Console.WriteLine(mavenRange.ToString("ns", null)); +``` + +Both `SemanticVersion` and `SemanticVersionRange` integrate with `System.Text.Json`. + +```csharp +using System.Text.Json; +using Geekeey.SemVer; + +var version = SemanticVersion.Parse("1.2.3-beta+build.7"); +var range = SemanticVersionRange.Parse("^1.2.3"); + +var versionJson = JsonSerializer.Serialize(version); +var rangeJson = JsonSerializer.Serialize(range); + +var roundTrippedVersion = JsonSerializer.Deserialize(versionJson); +var roundTrippedRange = JsonSerializer.Deserialize(rangeJson); +``` diff --git a/src/semver.tests/.editorconfig b/src/semver.tests/.editorconfig new file mode 100644 index 0000000..9de929c --- /dev/null +++ b/src/semver.tests/.editorconfig @@ -0,0 +1,15 @@ + +[*.{cs,vb}] +# disable CA1822: Mark members as static +# -> TUnit requiring instance methods for test cases +dotnet_diagnostic.CA1822.severity = none +# disable CA1707: Identifiers should not contain underscores +dotnet_diagnostic.CA1707.severity = none +# disable IDE0060: Remove unused parameter +dotnet_diagnostic.IDE0060.severity = none +# disable IDE0005: Unnecessary using directive +dotnet_diagnostic.IDE0005.severity = none +# disable IDE0390: Method can be made synchronous +dotnet_diagnostic.IDE0390.severity = none +# disable IDE0391: Method can be made synchronous +dotnet_diagnostic.IDE0391.severity = none diff --git a/src/semver.tests/SemanticVersionComparerTests.cs b/src/semver.tests/SemanticVersionComparerTests.cs index de52204..94c9887 100644 --- a/src/semver.tests/SemanticVersionComparerTests.cs +++ b/src/semver.tests/SemanticVersionComparerTests.cs @@ -112,4 +112,4 @@ internal sealed class SemanticVersionComparerTests await Assert.That(SemanticVersionComparer.Priority.Equals(v1, v2)).IsFalse(); await Assert.That(SemanticVersionComparer.SortOrder.Equals(v1, v2)).IsFalse(); } -} \ No newline at end of file +} diff --git a/src/semver.tests/SemanticVersionRangeTests.cs b/src/semver.tests/SemanticVersionRangeTests.cs index 715efb1..2fb4c13 100644 --- a/src/semver.tests/SemanticVersionRangeTests.cs +++ b/src/semver.tests/SemanticVersionRangeTests.cs @@ -258,4 +258,4 @@ internal sealed class SemanticVersionRangeTests await Assert.That(success).IsFalse(); await Assert.That(charsWritten).IsEqualTo(0); } -} \ No newline at end of file +} diff --git a/src/semver.tests/SemanticVersionTests.cs b/src/semver.tests/SemanticVersionTests.cs index 0749384..fe09dd8 100644 --- a/src/semver.tests/SemanticVersionTests.cs +++ b/src/semver.tests/SemanticVersionTests.cs @@ -1,7 +1,6 @@ // Copyright (c) The Geekeey Authors // SPDX-License-Identifier: EUPL-1.2 -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; @@ -223,4 +222,4 @@ internal sealed class SemanticVersionTests await Assert.That(() => JsonSerializer.Deserialize(json)) .Throws(); } -} \ No newline at end of file +} diff --git a/src/semver/SemanticVersion.Comparison.cs b/src/semver/SemanticVersion.Comparison.cs index 48ccfeb..6e2a43b 100644 --- a/src/semver/SemanticVersion.Comparison.cs +++ b/src/semver/SemanticVersion.Comparison.cs @@ -48,4 +48,4 @@ public readonly partial record struct SemanticVersion : IComparable, IComparable { return left.CompareTo(right) >= 0; } -} \ No newline at end of file +} diff --git a/src/semver/SemanticVersion.Formatting.cs b/src/semver/SemanticVersion.Formatting.cs index dc6b34b..890a35d 100644 --- a/src/semver/SemanticVersion.Formatting.cs +++ b/src/semver/SemanticVersion.Formatting.cs @@ -109,4 +109,4 @@ public readonly partial record struct SemanticVersion : ISpanFormattable } #endregion -} \ No newline at end of file +} diff --git a/src/semver/SemanticVersion.JsonConverter.cs b/src/semver/SemanticVersion.JsonConverter.cs index d08c40a..a0c200c 100644 --- a/src/semver/SemanticVersion.JsonConverter.cs +++ b/src/semver/SemanticVersion.JsonConverter.cs @@ -38,4 +38,4 @@ public readonly partial record struct SemanticVersion writer.WriteStringValue(value.ToString("f", null)); } } -} \ No newline at end of file +} diff --git a/src/semver/SemanticVersion.Parsing.cs b/src/semver/SemanticVersion.Parsing.cs index b3725b5..cb311aa 100644 --- a/src/semver/SemanticVersion.Parsing.cs +++ b/src/semver/SemanticVersion.Parsing.cs @@ -152,4 +152,4 @@ public readonly partial record struct SemanticVersion : ISpanParsable public string? Metadata { get; } -} \ No newline at end of file +} diff --git a/src/semver/SemanticVersionComparer.cs b/src/semver/SemanticVersionComparer.cs index c9e0dfa..a177492 100644 --- a/src/semver/SemanticVersionComparer.cs +++ b/src/semver/SemanticVersionComparer.cs @@ -304,4 +304,4 @@ public abstract class SemanticVersionComparer : IEqualityComparer buffer) Written += n; return true; } -} \ No newline at end of file +} diff --git a/src/semver/package-icon.png b/src/semver/package-icon.png new file mode 100644 index 0000000..35f4099 Binary files /dev/null and b/src/semver/package-icon.png differ diff --git a/src/semver/package-readme.md b/src/semver/package-readme.md new file mode 100644 index 0000000..de6be3b --- /dev/null +++ b/src/semver/package-readme.md @@ -0,0 +1,70 @@ +SemVer is a .NET library for parsing, comparing, formatting, and serializing semantic versions and version ranges. + +## Features + +- **Parsing:** parse semantic version strings into structured objects. +- **Comparison:** compare versions with operators or `CompareTo`. +- **Ranges:** evaluate npm-style and Maven-style version ranges. +- **Serialization:** use `System.Text.Json` converters for versions and ranges. + +## Getting Started + +### Install the NuGet package: + +```shell +dotnet add package Geekeey.SemVer +``` + +You may need to add our NuGet feed to your `nuget.config` this can be done by running the following command: + +```shell +dotnet nuget add source -n geekeey https://code.geekeey.de/api/packages/geekeey/nuget/index.json +``` + +### Usage + +```csharp +using Geekeey.SemVer; + +var version = SemanticVersion.Parse("1.2.3-beta+build.7"); +var next = new SemanticVersion(1, 3, 0); + +Console.WriteLine(version); +Console.WriteLine(version.Major); +Console.WriteLine(version.Prerelease); +Console.WriteLine(version.Metadata); +Console.WriteLine(version < next); + +if (SemanticVersion.TryParse("1.2.3-alpha", out var parsed)) +{ + Console.WriteLine(parsed); +} +``` + +Version ranges support npm-style and Maven-style syntax. + +```csharp +using Geekeey.SemVer; + +var npmRange = SemanticVersionRange.Parse("^1.2.3"); +var mavenRange = SemanticVersionRange.Parse("[1.2.3,2.0.0)"); +var candidate = SemanticVersion.Parse("1.4.2"); + +Console.WriteLine(npmRange.Contains(candidate)); +Console.WriteLine(mavenRange.Contains(candidate)); +Console.WriteLine(npmRange.ToString("m", null)); +Console.WriteLine(mavenRange.ToString("ns", null)); +``` + +Both `SemanticVersion` and `SemanticVersionRange` integrate with `System.Text.Json`. + +```csharp +using System.Text.Json; +using Geekeey.SemVer; + +var versionJson = JsonSerializer.Serialize(SemanticVersion.Parse("1.2.3-beta+build.7")); +var rangeJson = JsonSerializer.Serialize(SemanticVersionRange.Parse("^1.2.3")); + +var roundTrippedVersion = JsonSerializer.Deserialize(versionJson); +var roundTrippedRange = JsonSerializer.Deserialize(rangeJson); +```