From 90b8cf40dc8396ffddd02ec9e5a15c78903c4e69 Mon Sep 17 00:00:00 2001 From: Steven Giesel Date: Thu, 4 Jul 2024 21:54:19 +0200 Subject: [PATCH] Fix: Process even deeply nested versions --- .../Features/MarkdownConverter.cs | 51 ++++++++++++++----- .../Components/TableOfContentsTests.cs | 1 + 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/LinkDotNet.Blog.Web/Features/MarkdownConverter.cs b/src/LinkDotNet.Blog.Web/Features/MarkdownConverter.cs index 0b1c6e8d..d1cee624 100644 --- a/src/LinkDotNet.Blog.Web/Features/MarkdownConverter.cs +++ b/src/LinkDotNet.Blog.Web/Features/MarkdownConverter.cs @@ -4,6 +4,7 @@ using Markdig; using Markdig.Extensions.AutoIdentifiers; using Markdig.Helpers; +using Markdig.Parsers; using Markdig.Renderers.Html; using Markdig.Syntax; using Markdig.Syntax.Inlines; @@ -42,30 +43,54 @@ public static IReadOnlyCollection GenerateToc(string markdownContent) return document .Descendants() .Where(h => h.Inline?.FirstChild is not null) - .Select(heading => new TocItem { Level = heading.Level, Text = InlineToString(heading.Inline), Id = heading.GetAttributes().Id }) + .Select(heading => new TocItem + { + Level = heading.Level, Text = InlineToString(heading.Inline), Id = heading.GetAttributes().Id + }) .ToArray(); } private static string InlineToString(ContainerInline inline) { var sb = new StringBuilder(); - var current = inline.FirstChild; - while (current is not null) + ProcessInlineDelegate(inline, sb); + return sb.ToString(); + + static void ProcessInlineDelegate(Inline inline, StringBuilder stringBuilder) { - var text = current switch + if (inline is null) { - CodeInline cd => cd.Content, - LinkInline link => link.FirstChild?.ToString(), - EmphasisInline em => em.FirstChild?.ToString(), - _ => current.ToString() - }; + return; + } - sb.Append(text); + var current = inline; + while (current is not null) + { + switch (current) + { + case CodeInline cd: + stringBuilder.Append(cd.Content); + break; + case LinkInline link: + ProcessInlineDelegate(link.FirstChild, stringBuilder); + break; + case EmphasisInline em: + ProcessInlineDelegate(em.FirstChild, stringBuilder); + break; + case LiteralInline literal: + stringBuilder.Append(literal.Content); + break; + case ContainerInline container: + ProcessInlineDelegate(container.FirstChild, stringBuilder); + break; + default: + stringBuilder.Append(current); + break; + } - current = current.NextSibling; + current = current.NextSibling; + } } - - return sb.ToString(); } } diff --git a/tests/LinkDotNet.Blog.UnitTests/Web/Features/ShowBlogPost/Components/TableOfContentsTests.cs b/tests/LinkDotNet.Blog.UnitTests/Web/Features/ShowBlogPost/Components/TableOfContentsTests.cs index 3ce947dd..1b47e88a 100644 --- a/tests/LinkDotNet.Blog.UnitTests/Web/Features/ShowBlogPost/Components/TableOfContentsTests.cs +++ b/tests/LinkDotNet.Blog.UnitTests/Web/Features/ShowBlogPost/Components/TableOfContentsTests.cs @@ -57,6 +57,7 @@ public void ShouldSetAnchorLinkCorrectWhenAlreadyAnchorInUrl() [InlineData("# This is `Header` 1", "This is Header 1")] [InlineData("# [This is a link](https://link.com)", "This is a link")] [InlineData("# **What** *if*", "What if")] + [InlineData("# *[Link](link)*", "Link")] public void ShouldCreateCorrectToc(string markdown, string expectedToc) { var cut = Render(p => p