From 61d05861d4174d25336a0ba203d9a083f6b1b8fa Mon Sep 17 00:00:00 2001 From: Pedram Rezaei Date: Sat, 12 Sep 2026 15:00:14 -0700 Subject: [PATCH 1/3] Update to .NET 10 and latest NuGet packages --- .github/workflows/build.yml | 4 +- .github/workflows/publish.yml | 4 +- Directory.Build.props | 20 ++++---- README.md | 2 +- .../Cloudtoid.UrlPattern.csproj | 2 +- .../PatternParserTests.cs | 50 +++++++++---------- 6 files changed, 39 insertions(+), 43 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fc6ffc1..f46e70b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,9 +18,7 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 3.1.x - 6.0.x - 7.0.x + 10.0.x - name: Build - Release run: dotnet build -c Release UrlPattern.sln diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index da273b8..58c1334 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,9 +17,7 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 3.1.x - 6.0.x - 7.0.x + 10.0.x - name: Build and Test run: dotnet test -c Release UrlPattern.sln diff --git a/Directory.Build.props b/Directory.Build.props index 4ea3bbb..7fdde89 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,8 +7,8 @@ - net7.0;net6.0;netcoreapp3.1 - 11.0 + net10.0 + 14.0 enable true true @@ -16,18 +16,18 @@ - 1.0.* - 1.0.* - 6.0.* + 1.0.121 + 1.0.24 + 10.0.12 - 17.4.* - 3.0.* - 4.4.* - 6.9.* - 3.2.* + 18.10.0 + 4.4.0 + 6.2.0 + 8.10.0 + 10.0.1 diff --git a/README.md b/README.md index 4d6cafe..3bd4d6f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ We all know regular expressions are not the most user-friendly programming const Cloudtoid's URL Pattern Matcher library is optimized for speed. It compiles the new patterns and caches the compiled version for future use. The pattern matcher component is tuned to pattern match without the need for backtracking. -This library supports `.netcore3.1+`, `.net6.0` and `.net7.0` and is optimized for [.net dependency injection][DI] but can also be used without DI. +This library supports `.NET 10` and is optimized for [.net dependency injection][DI] but can also be used without DI. ```csharp var engine = new PatternEngine(); diff --git a/src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj b/src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj index ec2f78c..074477e 100644 --- a/src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj +++ b/src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj @@ -1,7 +1,7 @@  - + diff --git a/tests/Cloudtoid.UrlPattern.UnitTests/PatternParserTests.cs b/tests/Cloudtoid.UrlPattern.UnitTests/PatternParserTests.cs index 04d82fc..e353154 100644 --- a/tests/Cloudtoid.UrlPattern.UnitTests/PatternParserTests.cs +++ b/tests/Cloudtoid.UrlPattern.UnitTests/PatternParserTests.cs @@ -19,7 +19,7 @@ public void TryParse_WhenValidSingleCharMatchRoute_ReturnsMatchNodeAndNoError() var pattern = ParseAndValidate("a"); pattern.Should().BeEquivalentTo( new MatchNode("a"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -28,7 +28,7 @@ public void TryParse_WhenValidLongMatchRoute_ReturnsMatchNodeAndNoError() var pattern = ParseAndValidate("valid-value"); pattern.Should().BeEquivalentTo( new MatchNode("valid-value"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -37,7 +37,7 @@ public void TryParse_WhenSegmentChar_ReturnsSegmentNode() var pattern = ParseAndValidate("/"); pattern.Should().BeEquivalentTo( SegmentStartNode.Instance, - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -46,7 +46,7 @@ public void TryParse_WhenWildcardChar_ReturnsWildcardNode() var pattern = ParseAndValidate("*"); pattern.Should().BeEquivalentTo( WildcardNode.Instance, - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -55,7 +55,7 @@ public void TryParse_WhenOptionalMatch_ReturnsOptionalWithMatchNode() var pattern = ParseAndValidate("(value)"); pattern.Should().BeEquivalentTo( new OptionalNode(new MatchNode("value")), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -64,7 +64,7 @@ public void TryParse_WhenOptionalWild_ReturnsOptionalWithWildNode() var pattern = ParseAndValidate("(*)"); pattern.Should().BeEquivalentTo( new OptionalNode(WildcardNode.Instance), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -103,7 +103,7 @@ public void TryParse_WhenSimpleVariable_ReturnsVariableNode() var pattern = ParseAndValidate(":variable"); pattern.Should().BeEquivalentTo( new VariableNode("variable"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -112,7 +112,7 @@ public void TryParse_WhenVariableWithNumber_ReturnsVariableNode() var pattern = ParseAndValidate(":variable0"); pattern.Should().BeEquivalentTo( new VariableNode("variable0"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -121,7 +121,7 @@ public void TryParse_WhenVariableNameStops_ReturnsVariableNodeAndMatch() var pattern = ParseAndValidate(":variable-placeholder"); pattern.Should().BeEquivalentTo( new VariableNode("variable") + new MatchNode("-placeholder"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -143,7 +143,7 @@ public void TryParse_WhenSegmentIsVariable_Success() new MatchNode("v"), new VariableNode("version"), SegmentStartNode.Instance), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); pattern.Should().BeEquivalentTo( SegmentStartNode.Instance @@ -152,7 +152,7 @@ public void TryParse_WhenSegmentIsVariable_Success() + new MatchNode("v") + new VariableNode("version") + SegmentStartNode.Instance, - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -167,7 +167,7 @@ public void TryParse_WhenSegmentIsVariableExtended_Success() SegmentStartNode.Instance, new MatchNode("v"), new VariableNode("version")), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); pattern.Should().BeEquivalentTo( SegmentStartNode.Instance @@ -175,7 +175,7 @@ public void TryParse_WhenSegmentIsVariableExtended_Success() + SegmentStartNode.Instance + new MatchNode("v") + new VariableNode("version"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -194,7 +194,7 @@ public void TryParse_WhenMultipleVariables_Success() + SegmentStartNode.Instance + new VariableNode("id") + SegmentStartNode.Instance, - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -212,7 +212,7 @@ public void TryParse_WhenMultipleVariablesExtended_Success() + new MatchNode("product") + SegmentStartNode.Instance + new VariableNode("id"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -228,7 +228,7 @@ public void TryParse_WhenOptionalSegment_Success() + new MatchNode("product") + SegmentStartNode.Instance + new VariableNode("id"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -243,7 +243,7 @@ public void TryParse_WhenMultipleOptionlSegmentsWithVariables_Success() + SegmentStartNode.Instance + new MatchNode("product") + new OptionalNode((SegmentStartNode.Instance + new VariableNode("id"))!), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -259,7 +259,7 @@ public void TryParse_WhenMultipleOptionlSegmentsWithVariablesExtended_Success() + new MatchNode("product") + SegmentStartNode.Instance + new OptionalNode(new VariableNode("id")), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -277,7 +277,7 @@ public void TryParse_WhenComplexOptional_Success() + SegmentStartNode.Instance)!) + new MatchNode("product") + SegmentStartNode.Instance, - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -350,7 +350,7 @@ public void TryParse_WhenUsingEscapeCharButNotFollowedByEscapableChar_EscapeChar private static void ExpectMatch(string value) { var pattern = ParseAndValidate(value); - pattern.Should().BeEquivalentTo(new MatchNode(value), o => o.RespectingRuntimeTypes()); + pattern.Should().BeEquivalentTo(new MatchNode(value), o => o.PreferringRuntimeMemberTypes()); } private static void ExpectVariableAndMatch(string value) @@ -359,7 +359,7 @@ private static void ExpectVariableAndMatch(string value) pattern.Should() .BeEquivalentTo( new VariableNode("variable") + new MatchNode(value.ReplaceOrdinal(":variable", string.Empty)), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } private static void ExpectEndVariableAndMatch(string value) @@ -368,7 +368,7 @@ private static void ExpectEndVariableAndMatch(string value) pattern.Should() .BeEquivalentTo( new MatchNode(value.ReplaceOrdinal(":variable", string.Empty)) + new VariableNode("variable"), - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -392,7 +392,7 @@ public void TryParse_WhenEscapedAtBegining_SpecialCharIsEscaped() private static void ExpectEscapedAtBeginingMatch(string value) { var pattern = ParseAndValidate(value); - pattern.Should().BeEquivalentTo(new MatchNode(value.Substring(2)), o => o.RespectingRuntimeTypes()); + pattern.Should().BeEquivalentTo(new MatchNode(value.Substring(2)), o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -416,7 +416,7 @@ public void TryParse_WhenEscapedInMiddle_SpecialCharIsEscaped() private static void ExpectEscapedInMiddleMatch(string value) { var pattern = ParseAndValidate(value); - pattern.Should().BeEquivalentTo(new MatchNode("a") + new MatchNode(value.Substring(3)), o => o.RespectingRuntimeTypes()); + pattern.Should().BeEquivalentTo(new MatchNode("a") + new MatchNode(value.Substring(3)), o => o.PreferringRuntimeMemberTypes()); } [TestMethod] @@ -428,7 +428,7 @@ public void TryParse_WhenWildcardPlusMatchPlusVariableVariableNameStops_Success( + new MatchNode("placeholder") + new VariableNode("variable") + SegmentStartNode.Instance, - o => o.RespectingRuntimeTypes()); + o => o.PreferringRuntimeMemberTypes()); } private static PatternNode ParseAndValidate(string pattern) From 8418d4e4c9020816c0189a1227b6dec633e941b9 Mon Sep 17 00:00:00 2001 From: Pedram Rezaei Date: Sat, 12 Sep 2026 15:04:55 -0700 Subject: [PATCH 2/3] Update GitHub Actions to Node.js 24 releases --- .github/workflows/build.yml | 4 ++-- .github/workflows/publish.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f46e70b..9836c3e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,10 +12,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v7 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v6 with: dotnet-version: | 10.0.x diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 58c1334..63c7846 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,10 +11,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v7 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v6 with: dotnet-version: | 10.0.x From 1c7c264338e1a10b9fd95ff8eb873bc5e6172791 Mon Sep 17 00:00:00 2001 From: Pedram Rezaei Date: Sat, 12 Sep 2026 15:15:32 -0700 Subject: [PATCH 3/3] Use NuGet trusted publishing and include package README --- .github/workflows/publish.yml | 11 ++++++++++- src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj | 5 +++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 63c7846..98447f1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,6 +6,9 @@ on: jobs: build: + permissions: + contents: read + id-token: write runs-on: ubuntu-latest @@ -25,5 +28,11 @@ jobs: - name: Pack run: dotnet pack -c Release --no-build --output . --version-suffix ${{github.run_number}} src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj + - name: NuGet login + uses: NuGet/login@v1 + id: nuget-login + with: + user: pedramr + - name: Push - run: dotnet nuget push Cloudtoid.UrlPattern.*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.nuget_org_api_key }} \ No newline at end of file + run: dotnet nuget push Cloudtoid.UrlPattern.*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }} \ No newline at end of file diff --git a/src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj b/src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj index 074477e..d45f8ec 100644 --- a/src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj +++ b/src/Cloudtoid.UrlPattern/Cloudtoid.UrlPattern.csproj @@ -6,6 +6,7 @@ + README.md Cloudtoid.UrlPattern Cloudtoid.UrlPattern pedram@rezaei.us @@ -21,4 +22,8 @@ 1.0.$(VersionSuffix) + + + +