From 0d6343b421734d15d71fc4b48c7e780fc085d3d7 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Mon, 14 Apr 2025 22:02:21 +0200 Subject: [PATCH] Make AlertBlock parsing a bit cheaper --- src/Markdig/Extensions/Alerts/AlertBlock.cs | 2 +- .../Extensions/Alerts/AlertInlineParser.cs | 39 +++++++++++-------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/Markdig/Extensions/Alerts/AlertBlock.cs b/src/Markdig/Extensions/Alerts/AlertBlock.cs index 4e5ff529..43869c05 100644 --- a/src/Markdig/Extensions/Alerts/AlertBlock.cs +++ b/src/Markdig/Extensions/Alerts/AlertBlock.cs @@ -22,7 +22,7 @@ public class AlertBlock : QuoteBlock } /// - /// Gets or sets the kind of the alert block (e.g `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`) + /// Gets or sets the kind of the alert block (e.g `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`). /// public StringSlice Kind { get; set; } diff --git a/src/Markdig/Extensions/Alerts/AlertInlineParser.cs b/src/Markdig/Extensions/Alerts/AlertInlineParser.cs index 04fd97a6..7d609e5b 100644 --- a/src/Markdig/Extensions/Alerts/AlertInlineParser.cs +++ b/src/Markdig/Extensions/Alerts/AlertInlineParser.cs @@ -15,6 +15,9 @@ namespace Markdig.Extensions.Alerts; /// public class AlertInlineParser : InlineParser { + private static readonly TransformedStringCache s_alertTypeClassCache = new( + type => $"markdown-alert-{type.ToLowerInvariant()}"); + /// /// Initializes a new instance of the class. /// @@ -25,27 +28,30 @@ public class AlertInlineParser : InlineParser public override bool Match(InlineProcessor processor, ref StringSlice slice) { + if (slice.PeekChar() != '!') + { + return false; + } + // We expect the alert to be the first child of a quote block. Example: // > [!NOTE] // > This is a note - if (processor.Block is not ParagraphBlock paragraphBlock || paragraphBlock.Parent is not QuoteBlock quoteBlock || paragraphBlock.Inline?.FirstChild != null - || quoteBlock is AlertBlock || quoteBlock.Parent is not MarkdownDocument) + if (processor.Block is not ParagraphBlock paragraphBlock || + paragraphBlock.Parent is not QuoteBlock quoteBlock || + paragraphBlock.Inline?.FirstChild != null || + quoteBlock is AlertBlock || + quoteBlock.Parent is not MarkdownDocument) { return false; } - var saved = slice; - var c = slice.NextChar(); - if (c != '!') - { - slice = saved; - return false; - } + StringSlice saved = slice; - c = slice.NextChar(); // Skip ! + slice.SkipChar(); // Skip [ + char c = slice.NextChar(); // Skip ! - var start = slice.Start; - var end = start; + int start = slice.Start; + int end = start; while (c.IsAlpha()) { end = slice.Start; @@ -76,13 +82,13 @@ public class AlertInlineParser : InlineParser end = slice.Start; if (c == '\n') { - slice.NextChar(); // Skip \n + slice.SkipChar(); // Skip \n } } } else if (c == '\n') { - slice.NextChar(); // Skip \n + slice.SkipChar(); // Skip \n } break; } @@ -103,8 +109,9 @@ public class AlertInlineParser : InlineParser Column = quoteBlock.Column, }; - alertBlock.GetAttributes().AddClass("markdown-alert"); - alertBlock.GetAttributes().AddClass($"markdown-alert-{alertType.ToString().ToLowerInvariant()}"); + HtmlAttributes attributes = alertBlock.GetAttributes(); + attributes.AddClass("markdown-alert"); + attributes.AddClass(s_alertTypeClassCache.Get(alertType.AsSpan())); // Replace the quote block with the alert block var parentQuoteBlock = quoteBlock.Parent!;