From eb22c5e79ba7ce50fe332a116fa9a7f61a74a9e1 Mon Sep 17 00:00:00 2001 From: Sakura Akeno Isayeki Date: Sun, 25 Aug 2024 19:24:21 +0200 Subject: [PATCH] feat: Update regex implementations Updated all regex implementations to use .NET 7+ GeneratedRegex sourcegen-based implementations. --- .../Helpers/VaultComponentHelpers.cs | 11 +++--- .../Markdown/InternalLinks/InternalLink.cs | 7 ++-- .../ObsidianInternalLinksParser.cs | 34 +++++++++---------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/Nodsoft.MoltenObsidian.Blazor/Helpers/VaultComponentHelpers.cs b/Nodsoft.MoltenObsidian.Blazor/Helpers/VaultComponentHelpers.cs index 73c5b4f..7da0f8d 100644 --- a/Nodsoft.MoltenObsidian.Blazor/Helpers/VaultComponentHelpers.cs +++ b/Nodsoft.MoltenObsidian.Blazor/Helpers/VaultComponentHelpers.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Text.RegularExpressions; +using JetBrains.Annotations; using Microsoft.AspNetCore.Components; namespace Nodsoft.MoltenObsidian.Blazor.Helpers; @@ -7,13 +8,15 @@ namespace Nodsoft.MoltenObsidian.Blazor.Helpers; /// /// Provides helper methods for working with Vault implementation components. /// -public static class VaultComponentHelpers +[PublicAPI] +public static partial class VaultComponentHelpers { /// /// Regex for matching a slug segment at the end of a string. (e.g. "/{*slugName}") /// This is the same regex used by the Blazor Router to match slug segments. /// - private static readonly Regex SlugRegex = new(@"\/\{\*[\w\d]+\}$", RegexOptions.Compiled); + [GeneratedRegex(@"\/\{\*[\w\d]+\}$", RegexOptions.Compiled)] + private static partial Regex SlugRegex(); /// /// A dictionary containing the base vault path for a component type. @@ -56,8 +59,8 @@ private static string GetCallingBaseVaultPath(Type componentType) // Second. Does the RouteAttribute have a slug segment at the end? // If so, remove it. - string basePath = SlugRegex.IsMatch(routeAttribute.Template) - ? SlugRegex.Replace(routeAttribute.Template, string.Empty) + string basePath = SlugRegex().IsMatch(routeAttribute.Template) + ? SlugRegex().Replace(routeAttribute.Template, string.Empty) : routeAttribute.Template; // Third. Does the base path end with slashes? diff --git a/Nodsoft.MoltenObsidian/Infrastructure/Markdown/InternalLinks/InternalLink.cs b/Nodsoft.MoltenObsidian/Infrastructure/Markdown/InternalLinks/InternalLink.cs index f2acaee..3dcc57d 100644 --- a/Nodsoft.MoltenObsidian/Infrastructure/Markdown/InternalLinks/InternalLink.cs +++ b/Nodsoft.MoltenObsidian/Infrastructure/Markdown/InternalLinks/InternalLink.cs @@ -11,7 +11,7 @@ namespace Nodsoft.MoltenObsidian.Infrastructure.Markdown.InternalLinks; /// Syntax: [[link]] | [[link|display]] | [[link|display|tooltip]] /// The link can be a relative path, an absolute path, and/or a section anchor. /// -public sealed class InternalLink : LinkInline +public sealed partial class InternalLink : LinkInline { /// /// Initializes a new instance of the class. @@ -24,7 +24,8 @@ public InternalLink() /// /// Regex substitution pattern for internal link anchors, to replace spaces with dashes and remove all other invalid characters. /// - private static readonly Regex AnchorRegex = new(@"[^\w.]+", RegexOptions.Compiled); + [GeneratedRegex(@"[^\w.]+", RegexOptions.Compiled | RegexOptions.NonBacktracking)] + private static partial Regex AnchorRegex(); /// @@ -44,7 +45,7 @@ public InternalLink() /// /// The fragment of the section anchor, suitable for use in a URL. /// - public string? TargetSectionLinkFragment => TargetSection is null ? null : AnchorRegex.Replace(TargetSection, "-").Trim('-').ToLowerInvariant(); + public string? TargetSectionLinkFragment => TargetSection is null ? null : AnchorRegex().Replace(TargetSection, "-").Trim('-').ToLowerInvariant(); /// /// The display text of the internal link, if any. diff --git a/Nodsoft.MoltenObsidian/Infrastructure/Markdown/InternalLinks/ObsidianInternalLinksParser.cs b/Nodsoft.MoltenObsidian/Infrastructure/Markdown/InternalLinks/ObsidianInternalLinksParser.cs index 50784dc..2e97a95 100644 --- a/Nodsoft.MoltenObsidian/Infrastructure/Markdown/InternalLinks/ObsidianInternalLinksParser.cs +++ b/Nodsoft.MoltenObsidian/Infrastructure/Markdown/InternalLinks/ObsidianInternalLinksParser.cs @@ -10,7 +10,7 @@ namespace Nodsoft.MoltenObsidian.Infrastructure.Markdown.InternalLinks; /// Provides parsing for Obsidian internal links for Markdig. /// /// -public sealed class ObsidianInternalLinksParser : InlineParser +public sealed partial class ObsidianInternalLinksParser : InlineParser { /// /// Regex pattern with named variables for internal links. @@ -23,22 +23,20 @@ public sealed class ObsidianInternalLinksParser : InlineParser /// [[note_one|not note one]] /// [[note#section|display|tooltip]] /// - private static readonly Regex InternalLinkRegex = new( + [GeneratedRegex( """ - ^\[\[( - # link, and optional anchor - (?[^\|\#\]]+)?(\#(?[^\|\]]+))? - # display title (optional) - (\|(?[^|\]]+))? - # tooltip (optional) - (\|(?<tooltip>[^|\]]+))? - )\]\] - """, - RegexOptions.Compiled - | RegexOptions.IgnorePatternWhitespace - | RegexOptions.ExplicitCapture - | RegexOptions.Multiline - ); + ^\[\[( + # link, and optional anchor + (?<link>[^\|\#\]]+)?(\#(?<anchor>[^\|\]]+))? + + # display title (optional) + (\|(?<title>[^|\]]+))? + + # tooltip (optional) + (\|(?<tooltip>[^|\]]+))? + )\]\] + """, RegexOptions.Multiline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.NonBacktracking)] + private static partial Regex InternalLinkRegex(); /// <summary> /// Initializes a new instance of the <see cref="ObsidianInternalLinksParser"/> class. @@ -49,7 +47,7 @@ public ObsidianInternalLinksParser() } /// <inheritdoc /> - public override bool Match(InlineProcessor processor, ref StringSlice slice) + public override bool Match(InlineProcessor processor, scoped ref StringSlice slice) { // Seek to the first two opening brackets if (slice.CurrentChar is not '[' && slice.PeekChar() is not '[') @@ -58,7 +56,7 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice) } // Grab the remainder of the slice, and check if it matches the internal link pattern. - Match match = InternalLinkRegex.Match(slice.Text[slice.Start..slice.End]); + Match match = InternalLinkRegex().Match(slice.Text[slice.Start..slice.End]); if (match is { Groups: [{ Name: "0" }]}) {