using System.Linq; using Markdig.Helpers; using Markdig.Parsers; using Markdig.Syntax.Inlines; namespace MfGames.Markdown.Extensions; public class WikiLinkInlineParser : InlineParser { private readonly WikiLinkOptions options; public WikiLinkInlineParser(WikiLinkOptions options) { this.options = options; this.OpeningCharacters = new[] { '[' }; } /// public override bool Match( InlineProcessor processor, ref StringSlice slice) { // We are looking for the `[[` opening for the tag and that the first // one isn't escaped. if (IsNotDelimiter(slice, '[')) { return false; } // We need to loop over the entire link, including the `[[` and `]]` // while keeping track since we'll swallow additional characters beyond // the link. int linkStart = slice.Start; int linkEnd = slice.Start; slice.Start += 2; // Our content starts after the double '[['. int contentStart = slice.Start; // We need to find the end of the link (the `]]`). while (IsNotDelimiter(slice, ']')) { slice.NextChar(); linkEnd = slice.Start; } // Pull out the components before we adjust for the ']]' for the end. int contentEnd = linkEnd; // Finish skipping over the `]]`. slice.NextChar(); slice.NextChar(); // Format the label and the URL. string content = slice.Text.Substring( contentStart, contentEnd - contentStart); string[] contentParts = content.Split('|', 2); string label = contentParts.Last(); string url = this.options.GetUrl(contentParts.First()); // Add in any trailing components. This merges the `'s` from // `[[Dale]]'s` into the label. while (this.options.IsTrailingLink(slice.CurrentChar)) { label += slice.CurrentChar; slice.NextChar(); linkEnd++; } // Create the link that we're replacing. WikiLink link = new() { Span = { Start = processor.GetSourcePosition( linkStart, out int line, out int column), }, Line = line, Column = column, Url = url, IsClosed = true, }; link.AppendChild( new LiteralInline() { Line = line, Column = column, Content = new StringSlice(label), IsClosed = true, }); // Replace the inline and then indicate we have a match. processor.Inline = link; return true; } private static bool IsNotDelimiter( StringSlice slice, char delimiter) { return slice.CurrentChar != delimiter || slice.PeekChar() != delimiter || slice.PeekCharExtra(-1) == '\\'; } }