/// <summary> /// This function can be called by any element parsing. Given a start and stopping point this will /// parse all found elements out of the range. /// </summary> /// <returns> A list of parsed inlines. </returns> public static List <MarkdownInline> ParseInlineChildren(string markdown, int startingPos, int maxEndingPos, bool ignoreLinks = false) { int currentParsePosition = startingPos; var inlines = new List <MarkdownInline>(); while (currentParsePosition < maxEndingPos) { // Find the next inline element. var parseResult = FindNextInlineElement(markdown, currentParsePosition, maxEndingPos, ignoreLinks); // If the element we found doesn't start at the position we are looking for there // is text between the element and the start of the parsed element. We need to wrap // it into a text run. if (parseResult.Start != currentParsePosition) { var textRun = TextRunInline.Parse(markdown, currentParsePosition, parseResult.Start); inlines.Add(textRun); } // Add the parsed element. inlines.Add(parseResult.ParsedElement); // Update the current position. currentParsePosition = parseResult.End; } return(inlines); }
/// <summary> /// Finds the next inline element by matching trip chars and verifying the match. /// </summary> /// <param name="markdown"> The markdown text to parse. </param> /// <param name="start"> The position to start parsing. </param> /// <param name="end"> The position to stop parsing. </param> /// <param name="ignoreLinks"> Indicates whether to parse links. </param> /// <returns>Returns the next element</returns> private static InlineParseResult FindNextInlineElement(string markdown, int start, int end, bool ignoreLinks) { // Search for the next inline sequence. for (int pos = start; pos < end; pos++) { // IndexOfAny should be the fastest way to skip characters we don't care about. pos = markdown.IndexOfAny(_tripCharacters, pos, end - pos); if (pos < 0) { break; } // Find the trigger(s) that matched. char currentChar = markdown[pos]; foreach (InlineTripCharHelper currentTripChar in _triggerList) { // Check if our current char matches the suffix char. if (currentChar == currentTripChar.FirstChar) { // Don't match if the previous character was a backslash. if (pos > start && markdown[pos - 1] == '\\') { continue; } // If we are here we have a possible match. Call into the inline class to verify. InlineParseResult parseResult = null; switch (currentTripChar.Method) { case InlineParseMethod.BoldItalic: parseResult = BoldItalicTextInline.Parse(markdown, pos, end); break; case InlineParseMethod.Comment: parseResult = CommentInline.Parse(markdown, pos, end); break; case InlineParseMethod.LinkReference: parseResult = LinkAnchorInline.Parse(markdown, pos, end); break; case InlineParseMethod.Bold: parseResult = BoldTextInline.Parse(markdown, pos, end); break; case InlineParseMethod.Italic: parseResult = ItalicTextInline.Parse(markdown, pos, end); break; case InlineParseMethod.MarkdownLink: if (!ignoreLinks) { parseResult = MarkdownLinkInline.Parse(markdown, pos, end); } break; case InlineParseMethod.AngleBracketLink: if (!ignoreLinks) { parseResult = HyperlinkInline.ParseAngleBracketLink(markdown, pos, end); } break; case InlineParseMethod.Url: if (!ignoreLinks) { parseResult = HyperlinkInline.ParseUrl(markdown, pos, end); } break; case InlineParseMethod.RedditLink: if (!ignoreLinks) { parseResult = HyperlinkInline.ParseRedditLink(markdown, pos, end); } break; case InlineParseMethod.PartialLink: if (!ignoreLinks) { parseResult = HyperlinkInline.ParsePartialLink(markdown, pos, end); } break; case InlineParseMethod.Email: if (!ignoreLinks) { parseResult = HyperlinkInline.ParseEmailAddress(markdown, start, pos, end); } break; case InlineParseMethod.Strikethrough: parseResult = StrikethroughTextInline.Parse(markdown, pos, end); break; case InlineParseMethod.Superscript: parseResult = SuperscriptTextInline.Parse(markdown, pos, end); break; case InlineParseMethod.Subscript: parseResult = SubscriptTextInline.Parse(markdown, pos, end); break; case InlineParseMethod.Code: parseResult = CodeInline.Parse(markdown, pos, end); break; case InlineParseMethod.Image: parseResult = ImageInline.Parse(markdown, pos, end); break; case InlineParseMethod.Emoji: parseResult = EmojiInline.Parse(markdown, pos, end); break; } if (parseResult != null) { return(parseResult); } } } } // If we didn't find any elements we have a normal text block. // Let us consume the entire range. return(new InlineParseResult(TextRunInline.Parse(markdown, start, end), start, end)); }