using HtmlAgilityPack; using Humanizer; using Markdig; using Markdig.Renderers; using Markdig.Renderers.Html; namespace OliverBooth.Extensions.Markdig.Markdown.Callout; /// /// Represents an HTML renderer which renders a . /// internal sealed class CalloutRenderer : HtmlObjectRenderer { private readonly MarkdownPipeline _pipeline; private static readonly Dictionary CalloutTypes = new() { ["NOTE"] = "pencil", ["ABSTRACT"] = "clipboard-list", ["INFO"] = "info", ["TODO"] = "circle-check", ["TIP"] = "flame", ["IMPORTANT"] = "flame", ["SUCCESS"] = "check", ["QUESTION"] = "circle-help", ["WARNING"] = "triangle-alert", ["FAILURE"] = "x", ["DANGER"] = "zap", ["BUG"] = "bug", ["EXAMPLE"] = "list", ["CITE"] = "quote", ["UPDATE"] = "calendar-check", }; public CalloutRenderer(MarkdownPipeline pipeline) { _pipeline = pipeline; } /// protected override void Write(HtmlRenderer renderer, CalloutBlock block) { renderer.EnsureLine(); if (renderer.EnableHtmlForBlock) { RenderAsHtml(renderer, block, _pipeline); } else { RenderAsText(renderer, block); } renderer.EnsureLine(); } private static void RenderAsHtml(HtmlRenderer renderer, CalloutBlock block, MarkdownPipeline pipeline) { string title = block.Title.Text; ReadOnlySpan type = block.Type.AsSpan(); Span upperType = stackalloc char[type.Length]; type.ToUpperInvariant(upperType); if (!CalloutTypes.TryGetValue(upperType.ToString(), out string? lucideClass)) { lucideClass = "pencil"; } var typeString = type.ToString().ToLowerInvariant(); renderer.Write($"
'); renderer.Write("
"); string calloutTitle = title.Length == 0 ? typeString.Humanize(LetterCasing.Sentence) : title; WriteTitle(renderer, pipeline, calloutTitle); if (block.Foldable) { renderer.Write(""); } renderer.WriteLine("
"); renderer.Write("
"); renderer.WriteChildren(block); renderer.WriteLine("
"); renderer.WriteLine("
"); renderer.EnsureLine(); } private static void WriteTitle(TextRendererBase renderer, MarkdownPipeline pipeline, string calloutTitle) { string html = global::Markdig.Markdown.ToHtml(calloutTitle, pipeline); var document = new HtmlDocument(); document.LoadHtml(html); if (document.DocumentNode.FirstChild is { Name: "p" } child) { // ugly hack to remove

tag generated by Markdig document.DocumentNode.InnerHtml = child.InnerHtml; } document.Save(renderer.Writer); } private static void RenderAsText(HtmlRenderer renderer, CalloutBlock block) { string title = block.Title.Text; ReadOnlySpan type = block.Type.AsSpan(); renderer.WriteLine(title.Length == 0 ? type.ToString().ToUpperInvariant() : title.ToUpperInvariant()); renderer.WriteChildren(block); renderer.EnsureLine(); } }