/// <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>
        /// <param name="markdown"></param>
        /// <param name="startingPos"></param>
        /// <param name="maxEndingPos"></param>
        protected void ParseInlineChildren(ref string markdown, int startingPos, int maxEndingPos)
        {
            int currentParsePosition = startingPos;


            while (currentParsePosition < maxEndingPos)
            {
                int nextElemntStart = 0;
                int nextElementEnd  = 0;

                // Find the next element
                MarkdownInline element = Common.FindNextInlineElement(ref markdown, currentParsePosition, maxEndingPos, ref nextElemntStart, ref nextElementEnd);

                // If the element we found doesn't start at the position we are looking for there is text between the element and
                // the start. We need to wrap it into a Text Run
                if (nextElemntStart != currentParsePosition)
                {
                    TextRunInline textRun = new TextRunInline();
                    textRun.Parse(ref markdown, currentParsePosition, nextElemntStart);
                    Children.Add(textRun);
                }

                // Ask it to parse, it will return us the ending pos of itself.
                currentParsePosition = element.Parse(ref markdown, nextElemntStart, nextElementEnd);

                // Add it the the children
                Children.Add(element);
            }
        }
示例#2
0
        /// <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);
        }
示例#3
0
            private void RenderTextRun(TextRunInline inline, InlineCollection inlineCollection)
            {
                Run run = new Run {
                    Text = inline.Text
                };

                inlineCollection.Add(run);
            }
示例#4
0
        /// <summary>
        /// Renders a text run element.
        /// </summary>
        /// <param name="inlineCollection"> The list to add to. </param>
        /// <param name="element"> The parsed inline element to render. </param>
        /// <param name="parent"> The container element. </param>
        /// <param name="context"> Persistent state. </param>
        private void RenderTextRun(InlineCollection inlineCollection, TextRunInline element, TextElement parent, RenderContext context)
        {
            // Create the text run
            Run textRun = new Run();

            textRun.Text = CollapseWhitespace(context, element.Text);

            // Add it
            inlineCollection.Add(textRun);
        }
        /// <summary>
        /// Renders a text run element.
        /// </summary>
        /// <param name="inlineCollection"> The list to add to. </param>
        /// <param name="element"> The parsed inline element to render. </param>
        /// <param name="context"> Persistent state. </param>
        /// <returns><see cref="Run"/></returns>
        private Run RenderTextRun(InlineCollection inlineCollection, TextRunInline element, RenderContext context)
        {
            // Create the text run
            Run textRun = new Run
            {
                Text = CollapseWhitespace(context, element.Text)
            };

            // Add it
            inlineCollection.Add(textRun);

            return(textRun);
        }
示例#6
0
        /// <summary>
        /// Renders a text run element.
        /// </summary>
        /// <param name="inlineCollection"> The list to add to. </param>
        /// <param name="element"> The parsed inline element to render. </param>
        /// <param name="context"> Persistent state. </param>
        private void RenderTextRun(InlineCollection inlineCollection, TextRunInline element, RenderContext context, bool large)
        {
            // Create the text run
            Run textRun = new Run
            {
                Text = element.Text,
            };

            if (large)
            {
                textRun.FontSize = 28;
            }

            // Add it
            inlineCollection.Add(textRun);
        }
示例#7
0
        private Run InternalRenderTextRun(TextRunInline element, IRenderContext context)
        {
            if (!(context is InlineRenderContext localContext))
            {
                throw new RenderContextIncorrectException();
            }

            var inlineCollection = localContext.InlineCollection;

            Run textRun = new Run
            {
                Text = CollapseWhitespace(context, element.Text)
            };

            inlineCollection.Add(textRun);
            return(textRun);
        }
        /// <summary>
        /// Renders a text run element.
        /// </summary>
        /// <param name="element"></param>
        /// <param name="currentInlines"></param>
        /// <param name="trimTextStart">If true this element should trin the start of the text and set to fales.</param>
        private void RenderTextRun(TextRunInline element, InlineCollection currentInlines, ref bool trimTextStart)
        {
            // Create the text run
            Run textRun = new Run();

            textRun.Text = element.Text;

            // Check if we should trim the starting text. This allows us to trim the text starting a block
            // but nothing else. If we do a trim set it to false so no one else does.
            if (trimTextStart)
            {
                trimTextStart = false;
                textRun.Text  = textRun.Text.TrimStart();
            }

            // Add it
            currentInlines.Add(textRun);
        }
        protected override void RenderTextRun(TextRunInline element, IRenderContext context)
        {
            if (context.Parent is FormattedString fs)
            {
                var span = new Span
                {
                    Text = element.Text.Replace("\n\r", Environment.NewLine)
                };

                if (_headerLevel > 0)
                {
                    span.Style = _headerStyles[_headerLevel];
                }

                RenderInlineSpan(span);

                fs.Spans.Add(span);
            }
        }
示例#10
0
        protected override void RenderTextRun(TextRunInline element, IRenderContext context)
        {
            // Fetch the paragraph to add the text content to
            var renderContext = context as RenderContext;
            var paragraph     = context.Parent as XElement;

            // Fetch the content of the inline element
            var text = element.Text;

            // Check if we need to trim leading white space
            if (renderContext.TrimLeadingWhitespace)
            {
                text = text.TrimStart();
                renderContext.TrimLeadingWhitespace = false;
            }

            // No content, nothing to do
            if (string.IsNullOrWhiteSpace(text))
            {
                return;
            }

            // Add a bold italic xml tag
            if (renderContext.SetBoldRun && renderContext.SetItalicRun)
            {
                paragraph.Add(new XElement("bi", text));
                return;
            }
            // Add a bold xml tag
            if (renderContext.SetBoldRun)
            {
                paragraph.Add(new XElement("b", text));
                return;
            }
            // Add a italic xml tag
            if (renderContext.SetItalicRun)
            {
                paragraph.Add(new XElement("i", text));
                return;
            }
            // Add a normal xml tag
            paragraph.Add(new XElement("n", text));
        }
示例#11
0
        private Run InternalRenderTextRun(TextRunInline element, IRenderContext context)
        {
            var localContext = context as InlineRenderContext;

            if (localContext == null)
            {
                throw new RenderContextIncorrectException();
            }

            var inlineCollection = localContext.InlineCollection;

            // Create the text run
            Run textRun = new Run
            {
                Text = CollapseWhitespace(context, element.Text)
            };

            // Add it
            inlineCollection.Add(textRun);
            return(textRun);
        }
        /// <summary>
        /// Attempts to parse a reference e.g. "[example]: http://www.reddit.com 'title'".
        /// </summary>
        /// <param name="markdown"> The markdown text. </param>
        /// <param name="start"> The location to start parsing. </param>
        /// <param name="end"> The location to stop parsing. </param>
        /// <returns> A parsed markdown link, or <c>null</c> if this is not a markdown link. </returns>
        internal static LinkReferenceBlock Parse(string markdown, int start, int end)
        {
            // Expect a '[' character.
            if (start >= end || markdown[start] != '[')
            {
                return(null);
            }

            // Find the ']' character
            int pos = start + 1;

            while (pos < end)
            {
                if (markdown[pos] == ']')
                {
                    break;
                }

                pos++;
            }

            if (pos == end)
            {
                return(null);
            }

            // Extract the ID.
            string id = markdown.Substring(start + 1, pos - (start + 1));

            // Expect the ':' character.
            pos++;
            if (pos == end || markdown[pos] != ':')
            {
                return(null);
            }

            // Skip whitespace
            pos++;
            while (pos < end && ParseHelpers.IsMarkdownWhiteSpace(markdown[pos]))
            {
                pos++;
            }

            if (pos == end)
            {
                return(null);
            }

            // Extract the URL.
            int urlStart = pos;

            while (pos < end && !ParseHelpers.IsMarkdownWhiteSpace(markdown[pos]))
            {
                pos++;
            }

            string url = TextRunInline.ResolveEscapeSequences(markdown, urlStart, pos);

            // Ignore leading '<' and trailing '>'.
            url = url.TrimStart('<').TrimEnd('>');

            // Skip whitespace.
            pos++;
            while (pos < end && ParseHelpers.IsMarkdownWhiteSpace(markdown[pos]))
            {
                pos++;
            }

            string tooltip = null;

            if (pos < end)
            {
                // Extract the tooltip.
                char tooltipEndChar;
                switch (markdown[pos])
                {
                case '(':
                    tooltipEndChar = ')';
                    break;

                case '"':
                case '\'':
                    tooltipEndChar = markdown[pos];
                    break;

                default:
                    return(null);
                }

                pos++;
                int tooltipStart = pos;
                while (pos < end && markdown[pos] != tooltipEndChar)
                {
                    pos++;
                }

                if (pos == end)
                {
                    return(null);    // No end character.
                }

                tooltip = markdown.Substring(tooltipStart, pos - tooltipStart);

                // Check there isn't any trailing text.
                pos++;
                while (pos < end && ParseHelpers.IsMarkdownWhiteSpace(markdown[pos]))
                {
                    pos++;
                }

                if (pos < end)
                {
                    return(null);
                }
            }

            // We found something!
            var result = new LinkReferenceBlock();

            result.Id      = id;
            result.Url     = url;
            result.Tooltip = tooltip;
            return(result);
        }
示例#13
0
 /// <summary>
 /// Renders a text run element.
 /// </summary>
 /// <param name="element"> The parsed inline element to render. </param>
 /// <param name="context"> Persistent state. </param>
 protected override void RenderTextRun(TextRunInline element, IRenderContext context)
 {
     InternalRenderTextRun(element, context);
 }
示例#14
0
        /// <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));
        }
示例#15
0
 /// <summary>
 /// Renders a text run element.
 /// </summary>
 /// <param name="element"> The parsed inline element to render. </param>
 /// <param name="context"> Persistent state. </param>
 protected abstract void RenderTextRun(TextRunInline element, IRenderContext context);