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)
- (\|(?[^|\]]+))?
- )\]\]
- """,
- RegexOptions.Compiled
- | RegexOptions.IgnorePatternWhitespace
- | RegexOptions.ExplicitCapture
- | RegexOptions.Multiline
- );
+ ^\[\[(
+ # link, and optional anchor
+ (?[^\|\#\]]+)?(\#(?[^\|\]]+))?
+
+ # display title (optional)
+ (\|(?[^|\]]+))?
+
+ # tooltip (optional)
+ (\|(?[^|\]]+))?
+ )\]\]
+ """, RegexOptions.Multiline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.NonBacktracking)]
+ private static partial Regex InternalLinkRegex();
///
/// Initializes a new instance of the class.
@@ -49,7 +47,7 @@ public ObsidianInternalLinksParser()
}
///
- 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" }]})
{