126 lines
4.1 KiB
C#
126 lines
4.1 KiB
C#
using System.IO;
|
|
|
|
using Markdig.Syntax.Inlines;
|
|
|
|
namespace MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines
|
|
{
|
|
/// <summary>
|
|
/// A Gemtext renderer for a <see cref="LinkInline" />.
|
|
/// </summary>
|
|
/// <seealso cref="GemtextObjectRenderer{LinkInline}" />
|
|
public class LinkInlineRenderer : GemtextObjectRenderer<LinkInline>
|
|
{
|
|
/// <summary>
|
|
/// Writes out any gathered links in a block.
|
|
/// </summary>
|
|
/// <param name="renderer">The renderer being used.</param>
|
|
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 (string? 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;
|
|
}
|
|
}
|
|
}
|