using System.IO; using Markdig.Syntax.Inlines; namespace MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines { /// /// A Gemtext renderer for a . /// /// public class LinkInlineRenderer : GemtextObjectRenderer { /// /// Writes out any gathered links in a block. /// /// The renderer being used. public static void WriteGatheredLinks(GemtextRenderer renderer) { // If we have no gathered links, then there is nothing to do. if (renderer.GatheredLinks.Count <= 0) { return; } // Put some space between the previous object and this one, then // write out each link which is already formatted. renderer.WriteLine(); foreach (var link in renderer.GatheredLinks) { renderer.WriteLine(); renderer.Write(link); } // Clear out the list of links. renderer.GatheredLinks.Clear(); } protected override void Write(GemtextRenderer renderer, LinkInline link) { // Figure out the various states we have. bool outside = !renderer.LinkInsideBlock; bool insert = !outside && renderer.BlockLinkHandling == BlockLinkHandling.InsertLine; bool gather = !outside && renderer.BlockLinkHandling switch { BlockLinkHandling.DocumentEnd => true, BlockLinkHandling.ParagraphEnd => true, _ => false, }; bool hasText = link.FirstChild != null; bool footnotes = renderer.EndLinkInlineFormatting == EndLinkInlineFormatting.Footnote; // Bare links and ones where we insert into the paragraph have // their own line. string? url = link.GetDynamicUrl != null ? link.GetDynamicUrl() ?? link.Url : link.Url; if (outside || insert) { // Make sure we are at the beginning of the line before // rendering the link. renderer.EnsureLine(); renderer.Write("=> "); renderer.Write(url); // If we have text, we need a space after the URL and before // the text. if (hasText) { renderer.Write(" "); } } // Render the text for the link if we have it. if (hasText) { renderer.WriteChildren(link); } // If we are gathering, then write out a footnote. if (gather) { int footnoteNumber = renderer.NextFootnoteNumber++; string linkText = footnotes ? footnoteNumber + ": " + url : GetLinkText(link); if (footnotes) { renderer.Write($"[{footnoteNumber}]"); } renderer.GatheredLinks.Add("=> " + url + " " + linkText); } // If we are inserting a line in the paragraph, we need a final // newline so the text of the paragraph continues on the next // line. if (insert) { renderer.WriteLine(); } } private static string GetLinkText(LinkInline link) { // This little bit of nasty code basically spins up a new renderer // to get the text of the link by itself. Then we return that // directly so it can be rendered as a link. StringWriter writer = new(); GemtextRenderer renderer = new(writer); renderer.WriteChildren(link); writer.Close(); string text = writer.ToString(); return text; } } }