Example #1
0
        /// <summary>
        /// Inline processing
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        protected string ProcessInline(MarkdownInline i)
        {
            string para = string.Empty;

            switch (i.Type)
            {
            //case MarkdownInlineType.Comment:
            //    break;
            //case MarkdownInlineType.TextRun:
            //    break;
            case MarkdownInlineType.Bold:
                para += ANSI.WriteMode(ANSICodes.Modes.Bold) +
                        i.ToString().Trim('*') + ANSI.WriteMode();
                break;

            //case MarkdownInlineType.Italic:
            //    break;
            case MarkdownInlineType.MarkdownLink:
                MarkdownLinkInline mitLink = (MarkdownLinkInline)i;
                if (mitLink.Url.ToLower().EndsWith(".md"))
                {
                    actionsCount++;
                    para += $"{mitLink.Inlines[0]}[{actionsCount}]";
                    Data.Actions.Add(actionsCount.ToString(),
                                     new BBSCodeResult.Action()
                    {
                        module = "MarkdownScreen",
                        data   = (mitLink.Url.StartsWith("http") ? "" : basePath) + mitLink.Url
                    });
                }
                else
                {
                    para += mitLink.ToString();
                }
                break;

            //case MarkdownInlineType.RawHyperlink:
            //    break;
            //case MarkdownInlineType.RawSubreddit:
            //    break;
            //case MarkdownInlineType.Strikethrough:
            //    break;
            //case MarkdownInlineType.Superscript:
            //    break;
            //case MarkdownInlineType.Subscript:
            //    break;
            //case MarkdownInlineType.Code:
            //    break;
            //case MarkdownInlineType.Image:
            //    break;
            //case MarkdownInlineType.Emoji:
            //    break;
            //case MarkdownInlineType.LinkReference:
            //    break;
            default:
                para += i.ToString();
                break;
            }
            return(para);
        }
Example #2
0
        /// <summary>
        /// Renders a link 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 RenderMarkdownLink(InlineCollection inlineCollection, MarkdownLinkInline element, TextElement parent, RenderContext context)
        {
            // Avoid crash when link text is empty.
            if (element.Inlines.Count == 0)
            {
                return;
            }

            // Attempt to resolve references.
            element.ResolveReference(_document);
            if (element.Url == null)
            {
                // The element couldn't be resolved, just render it as text.
                RenderInlineChildren(inlineCollection, element.Inlines, parent, context);
                return;
            }

            // HACK: Superscript is not allowed within a hyperlink.  But if we switch it around, so
            // that the superscript is outside the hyperlink, then it will render correctly.
            // This assumes that the entire hyperlink is to be rendered as superscript.
            if (AllTextIsSuperscript(element) == false)
            {
                // Regular ol' hyperlink.
                var link = new Hyperlink();

                // Register the link
                _linkRegister.RegisterNewHyperLink(link, element.Url);

                // Remove superscripts.
                RemoveSuperscriptRuns(element, insertCaret: true);

                // Render the children into the link inline.
                var childContext = context.Clone();
                childContext.WithinHyperlink = true;
                RenderInlineChildren(link.Inlines, element.Inlines, link, childContext);
                context.TrimLeadingWhitespace = childContext.TrimLeadingWhitespace;

                // Add it to the current inlines
                inlineCollection.Add(link);
            }
            else
            {
                // THE HACK IS ON!

                // Create a fake superscript element.
                var fakeSuperscript = new SuperscriptTextInline
                {
                    Inlines = new List <MarkdownInline>
                    {
                        element
                    }
                };

                // Remove superscripts.
                RemoveSuperscriptRuns(element, insertCaret: false);

                // Now render it.
                RenderSuperscriptRun(inlineCollection, fakeSuperscript, parent, context);
            }
        }
        /// <summary>
        /// Verifies if the link is valid, before processing into a link, or plain text.
        /// </summary>
        /// <param name="element"> The parsed inline element to render. </param>
        /// <param name="context"> Persistent state. </param>
        protected void CheckRenderMarkdownLink(MarkdownLinkInline element, IRenderContext context)
        {
            // Avoid processing when link text is empty.
            if (element.Inlines.Count == 0)
            {
                return;
            }

            // Attempt to resolve references.
            element.ResolveReference(Document);
            if (element.Url == null)
            {
                // The element couldn't be resolved, just render it as text.
                RenderInlineChildren(element.Inlines, context);
                return;
            }

            foreach (MarkdownInline inline in element.Inlines)
            {
                if (inline is ImageInline imageInline)
                {
                    // this is an image, create Image.
                    if (!string.IsNullOrEmpty(imageInline.ReferenceId))
                    {
                        imageInline.ResolveReference(Document);
                    }

                    imageInline.Url = element.Url;
                    RenderImage(imageInline, context);
                    return;
                }
            }

            RenderMarkdownLink(element, context);
        }
Example #4
0
        /// <summary>
        /// Renders a link element
        /// </summary>
        /// <param name="element"> The parsed inline element to render. </param>
        /// <param name="context"> Persistent state. </param>
        protected override void RenderMarkdownLink(MarkdownLinkInline element, IRenderContext context)
        {
            if (!(context is InlineRenderContext localContext))
            {
                throw new RenderContextIncorrectException();
            }

            // HACK: Superscript is not allowed within a hyperlink.  But if we switch it around, so
            // that the superscript is outside the hyperlink, then it will render correctly.
            // This assumes that the entire hyperlink is to be rendered as superscript.
            if (AllTextIsSuperscript(element) == false)
            {
                var link = new Hyperlink();

                LinkRegister.RegisterNewHyperLink(link, element.Url);

                RemoveSuperscriptRuns(element, insertCaret: true);

                var childContext = new InlineRenderContext(link.Inlines, context)
                {
                    Parent          = link,
                    WithinHyperlink = true
                };

                if (localContext.OverrideForeground)
                {
                    link.Foreground = localContext.Foreground;
                }
                else if (LinkForeground != null)
                {
                    link.Foreground = LinkForeground;
                }

                RenderInlineChildren(element.Inlines, childContext);
                context.TrimLeadingWhitespace = childContext.TrimLeadingWhitespace;

                ToolTipService.SetToolTip(link, element.Tooltip ?? element.Url);

                localContext.InlineCollection.Add(link);
            }
            else
            {
                // THE HACK IS ON!

                // Create a fake superscript element.
                var fakeSuperscript = new SuperscriptTextInline
                {
                    Inlines = new List <MarkdownInline>
                    {
                        element
                    }
                };

                RemoveSuperscriptRuns(element, insertCaret: false);

                RenderSuperscriptRun(fakeSuperscript, context);
            }
        }
        private static Hyperlink CreateHyperlink(MarkdownLinkInline markdownLinkInline)
        {
            var hyperlink = new Hyperlink()
            {
                NavigateUri = new Uri(markdownLinkInline.Url, UriKind.Absolute)
            };

            hyperlink.Inlines.AddRange(CreateInlines(markdownLinkInline.Inlines));
            hyperlink.RequestNavigate += NavigateFromHyperlink;
            return(hyperlink);
        }
Example #6
0
        static Common()
        {
            BoldTextInline.AddTripChars(_triggerList);
            ItalicTextInline.AddTripChars(_triggerList);
            MarkdownLinkInline.AddTripChars(_triggerList);
            HyperlinkInline.AddTripChars(_triggerList);
            StrikethroughTextInline.AddTripChars(_triggerList);
            SuperscriptTextInline.AddTripChars(_triggerList);
            CodeInline.AddTripChars(_triggerList);

            // Create an array of characters to search against using IndexOfAny.
            _tripCharacters = _triggerList.Select(trigger => trigger.FirstChar).Distinct().ToArray();
        }
        /// <summary>
        /// Renders a link 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 RenderMarkdownLink(MarkdownLinkInline element, InlineCollection currentInlines, ref bool trimTextStart)
        {
            // Create the text run
            Hyperlink link = new Hyperlink();

            // Register the link
            m_linkRegister.RegisterNewHyperLink(link, element.Url);

            // Render the children into the link inline.
            RenderInlineChildren(element, link.Inlines, ref trimTextStart);

            // Add it to the current inlines
            currentInlines.Add(link);
        }
Example #8
0
 /// <summary>
 /// Returns a list of trip chars for all of the inlines. These are used to detect the
 /// possible beginning of an inline.
 /// </summary>
 /// <returns></returns>
 public static List <InlineTripCharHelper> GetTripCharsList()
 {
     lock (s_tripCharList)
     {
         if (s_tripCharList.Count == 0)
         {
             s_tripCharList.Add(BoldTextElement.GetTripChars());
             s_tripCharList.Add(ItalicTextElement.GetTripChars());
             s_tripCharList.Add(MarkdownLinkInline.GetTripChars());
             s_tripCharList.Add(RawHyperlinkInline.GetTripChars());
             s_tripCharList.Add(RawSubredditInline.GetTripChars());
             // Text run doesn't have one.
         }
     }
     return(s_tripCharList);
 }
Example #9
0
        static Common()
        {
            BoldItalicTextInline.AddTripChars(_triggerList);
            UnderlineTextInline.AddTripChars(_triggerList);
            BoldTextInline.AddTripChars(_triggerList);
            ItalicTextInline.AddTripChars(_triggerList);
            MarkdownLinkInline.AddTripChars(_triggerList);
            HyperlinkInline.AddTripChars(_triggerList);
            StrikethroughTextInline.AddTripChars(_triggerList);
            CodeInline.AddTripChars(_triggerList);
            ImageInline.AddTripChars(_triggerList);
            EmojiInline.AddTripChars(_triggerList);
            LinkAnchorInline.AddTripChars(_triggerList);
            DiscordInline.AddTripChars(_triggerList);
            SpoilerTextInline.AddTripChars(_triggerList);

            // Create an array of characters to search against using IndexOfAny.
            _tripCharacters = _triggerList.Select(trigger => trigger.FirstChar).Distinct().ToArray();
        }
        /// <summary>
        /// Verifies if the link is valid, before processing into a link, or plain text.
        /// </summary>
        /// <param name="element"> The parsed inline element to render. </param>
        /// <param name="context"> Persistent state. </param>
        protected void CheckRenderMarkdownLink(MarkdownLinkInline element, IRenderContext context)
        {
            // Avoid processing when link text is empty.
            if (element.Inlines.Count == 0)
            {
                return;
            }

            // Attempt to resolve references.
            element.ResolveReference(Document);
            if (element.Url == null)
            {
                // The element couldn't be resolved, just render it as text.
                RenderInlineChildren(element.Inlines, context);
            }
            else
            {
                // Url is valid, create Link.
                RenderMarkdownLink(element, context);
            }
        }
Example #11
0
        /// <summary>
        /// Renders a link 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 RenderMarkdownLink(InlineCollection inlineCollection, MarkdownLinkInline element, TextElement parent, RenderContext context)
        {
            // Avoid crash when link text is empty.
            if (element.Inlines.Count == 0)
            {
                return;
            }

            // Attempt to resolve references.
            element.ResolveReference(_document);
            if (element.Url == null || _document.EnableHiddenLinks == false)
            {
                // The element couldn't be resolved, just render it as text.
                RenderInlineChildren(inlineCollection, element.Inlines, parent, context);
                return;
            }

            // Regular ol' hyperlink.
            var link = new Hyperlink();

            // Register the link
            _linkRegister.RegisterNewHyperLink(link, element.Url);

            // Render the children into the link inline.
            var childContext = context.Clone();

            childContext.WithinHyperlink = true;

            if (LinkForeground != null)
            {
                link.Foreground = LinkForeground;
            }

            RenderInlineChildren(link.Inlines, element.Inlines, link, childContext);
            context.TrimLeadingWhitespace = childContext.TrimLeadingWhitespace;

            // Add it to the current inlines
            inlineCollection.Add(link);
        }
Example #12
0
        /// <summary>
        /// Renders a link element
        /// </summary>
        /// <param name="element"> The parsed inline element to render. </param>
        /// <param name="context"> Persistent state. </param>
        protected override void RenderMarkdownLink(MarkdownLinkInline element, IRenderContext context)
        {
            if (!(context is InlineRenderContext localContext))
            {
                throw new RenderContextIncorrectException();
            }

            // Regular ol' hyperlink.
            var link = new Hyperlink();

            // Register the link
            LinkRegister.RegisterNewHyperLink(link, element.Url);

            // Render the children into the link inline.
            var childContext = new InlineRenderContext(link.Inlines, context)
            {
                Parent          = link,
                WithinHyperlink = true
            };

            if (localContext.OverrideForeground)
            {
                link.Foreground = localContext.Foreground;
            }
            else if (LinkForeground != null)
            {
                link.Foreground = LinkForeground;
            }

            RenderInlineChildren(element.Inlines, childContext);
            context.TrimLeadingWhitespace = childContext.TrimLeadingWhitespace;

            ToolTipService.SetToolTip(link, element.Tooltip ?? element.Url);

            // Add it to the current inlines
            localContext.InlineCollection.Add(link);
        }
        protected override void RenderMarkdownLink(MarkdownLinkInline element, IRenderContext context)
        {
            var text = string.Join(string.Empty, element.Inlines);

            RenderLink(text, element.Url, context);
        }
Example #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));
        }
Example #15
0
 protected override void RenderMarkdownLink(MarkdownLinkInline element, IRenderContext context)
 {
 }
Example #16
0
 /// <summary>
 /// Renders a link element
 /// </summary>
 /// <param name="element"> The parsed inline element to render. </param>
 /// <param name="context"> Persistent state. </param>
 protected abstract void RenderMarkdownLink(MarkdownLinkInline element, IRenderContext context);
Example #17
0
        /// <summary>
        /// Finds the next inline element by matching trip chars and verifying the match.
        /// </summary>
        /// <returns></returns>
        public static MarkdownInline FindNextInlineElement(ref string markdown, int startingPos, int endingPos, ref int nextElementStart, ref int nextElementEnd)
        {
            // Get the list of trip chars
            List <InlineTripCharHelper> tripChars = GetTripCharsList();

            // Loop though all of the chars in this run and look for a trip char.
            for (int i = startingPos; i < endingPos; i++)
            {
                char currentChar = Char.ToLower(markdown[i]);

                // Try to match each trip char to the char
                foreach (InlineTripCharHelper currentTripChar in tripChars)
                {
                    // Check if our current char matches the sufex char.
                    if (currentChar == currentTripChar.FirstChar)
                    {
                        // We have a match! See if there is a suffix and if so if it matches.
                        if (currentTripChar.FirstCharSuffix != null)
                        {
                            // We need to loop through the sufex and see if it matches the next n chars in the markdown.
                            int  suffexCharCounter = i + 1;
                            bool suffexFound       = true;
                            foreach (char suffexChar in currentTripChar.FirstCharSuffix)
                            {
                                char test = Char.ToLower(markdown[suffexCharCounter]);
                                if (suffexCharCounter >= endingPos || suffexChar != Char.ToLower(markdown[suffexCharCounter]))
                                {
                                    suffexFound = false;
                                    break;
                                }
                                suffexCharCounter++;
                            }
                            // If the suffex didn't match this isn't a possibility.
                            if (!suffexFound)
                            {
                                continue;
                            }
                        }

                        // If we are here we have a possible match. Call into the inline class to verify.
                        // Note! The order of bold and italic here is important because they both start with *
                        // otherwise italic will consume bold's opening tag.
                        switch (currentTripChar.Type)
                        {
                        case MarkdownInlineType.Bold:
                            if (BoldTextElement.VerifyMatch(ref markdown, i, endingPos, ref nextElementStart, ref nextElementEnd))
                            {
                                return(new BoldTextElement());
                            }
                            break;

                        case MarkdownInlineType.Italic:
                            if (ItalicTextElement.VerifyMatch(ref markdown, i, endingPos, ref nextElementStart, ref nextElementEnd))
                            {
                                return(new ItalicTextElement());
                            }
                            break;

                        case MarkdownInlineType.MarkdownLink:
                            if (MarkdownLinkInline.VerifyMatch(ref markdown, i, endingPos, ref nextElementStart, ref nextElementEnd))
                            {
                                return(new MarkdownLinkInline());
                            }
                            break;

                        case MarkdownInlineType.RawHyperlink:
                            if (RawHyperlinkInline.VerifyMatch(ref markdown, i, endingPos, ref nextElementStart, ref nextElementEnd))
                            {
                                return(new RawHyperlinkInline());
                            }
                            break;

                        case MarkdownInlineType.RawSubreddit:
                            if (RawSubredditInline.VerifyMatch(ref markdown, i, endingPos, ref nextElementStart, ref nextElementEnd))
                            {
                                return(new RawSubredditInline());
                            }
                            break;
                        }
                    }
                }
            }

            // If we didn't find any elements we have a normal text block.
            // Let is consume the entire range.
            nextElementStart = startingPos;
            nextElementEnd   = endingPos;
            return(new TextRunInline());
        }