Exemplo n.º 1
0
        /// <summary>
        /// Called when the object should parse it's goods out of the markdown. The markdown, start, and stop are given.
        /// The start and stop are what is returned from the FindNext function below. The object should do it's parsing and
        /// return up to the last pos it used. This can be shorter than what is given to the function in endingPos.
        /// </summary>
        /// <param name="markdown">The markdown</param>
        /// <param name="startingPos">Where the parse should start</param>
        /// <param name="endingPos">Where the parse should end</param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int endingPos)
        {
            int italicStart = Common.IndexOf(ref markdown, '*', startingPos, endingPos);

            // These should always be =
            if (italicStart != startingPos)
            {
                DebuggingReporter.ReportCriticalError("italic parse didn't find * in at the starting pos");
            }
            italicStart++;

            // Find the ending
            int italicEnd = Common.IndexOf(ref markdown, '*', italicStart, endingPos, true);

            if (italicEnd + 1 != endingPos)
            {
                DebuggingReporter.ReportCriticalError("italic parse didn't find * in at the end pos");
            }

            // Make sure there is something to parse, and not just dead space
            if (italicEnd > italicStart)
            {
                // Parse any children of this bold element
                ParseInlineChildren(ref markdown, italicStart, italicEnd);
            }

            // Return the point after the *
            return(italicEnd + 1);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Called when the object should parse it's goods out of the markdown. The markdown, start, and stop are given.
        /// The start and stop are what is returned from the FindNext function below. The object should do it's parsing and
        /// return up to the last pos it used. This can be shorter than what is given to the function in endingPos.
        /// </summary>
        /// <param name="markdown">The markdown</param>
        /// <param name="startingPos">Where the parse should start</param>
        /// <param name="endingPos">Where the parse should end</param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int endingPos)
        {
            int boldStart = Common.IndexOf(ref markdown, "**", startingPos, endingPos);

            // These should always be =
            if (boldStart != startingPos)
            {
                DebuggingReporter.ReportCriticalError("bold parse didn't find ** in at the starting pos");
            }
            boldStart += 2;

            // Find the ending
            int boldEnding = Common.IndexOf(ref markdown, "**", boldStart, endingPos, true);

            if (boldEnding + 2 != endingPos)
            {
                DebuggingReporter.ReportCriticalError("bold parse didn't find ** in at the end pos");
            }

            // Make sure there is something to parse, and not just dead space
            if (boldEnding > boldStart)
            {
                // Parse any children of this bold element
                ParseInlineChildren(ref markdown, boldStart, boldEnding);
            }

            // Return the point after the **
            return(boldEnding + 2);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Fired when the markdown is changed.
        /// </summary>
        /// <param name="newMarkdown"></param>
        private void OnMarkdownChanged(string newMarkdown)
        {
            OnMarkdownReadyArgs args = new OnMarkdownReadyArgs();

            // Clear the current content
            CleanUpTextBlock();

            // Make sure we have something to parse.
            if (!String.IsNullOrWhiteSpace(newMarkdown))
            {
                try
                {
                    // Try to parse the markdown.
                    Markdown markdown = new Markdown();
                    markdown.Parse(newMarkdown);

                    // Now try to display it
                    RenderToRichTextBlock rendner = new RenderToRichTextBlock(ui_richTextBox, this);
                    rendner.Render(markdown);
                }
                catch (Exception e)
                {
                    DebuggingReporter.ReportCriticalError("Error while parsing and rendering: " + e.Message);
                    args.WasError  = true;
                    args.Exception = e;
                }
            }

            // #todo indicate if ready
            m_onMarkdownReady.Raise(this, args);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Called when the object should parse it's goods out of the markdown. The markdown, start, and stop are given.
        /// The start and stop are what is returned from the FindNext function below. The object should do it's parsing and
        /// return up to the last pos it used. This can be shorter than what is given to the function in endingPos.
        /// </summary>
        /// <param name="markdown">The markdown</param>
        /// <param name="startingPos">Where the parse should start</param>
        /// <param name="endingPos">Where the parse should end</param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int endingPos)
        {
            int httpStart  = Common.IndexOf(ref markdown, "http://", startingPos, endingPos);
            int httpsStart = Common.IndexOf(ref markdown, "https://", startingPos, endingPos);

            // Make -1 huge.
            httpStart  = httpStart == -1 ? int.MaxValue : httpStart;
            httpsStart = httpsStart == -1 ? int.MaxValue : httpsStart;

            // Figure out the pos of the link
            int linkStart = Math.Min(httpStart, httpsStart);
            int linkEnd   = Common.FindNextWhiteSpace(ref markdown, linkStart, endingPos, true);

            // These should always be =
            if (linkStart != startingPos)
            {
                DebuggingReporter.ReportCriticalError("raw link parse didn't find http in at the starting pos");
            }
            if (linkEnd != endingPos)
            {
                DebuggingReporter.ReportCriticalError("raw link parse didn't find the same ending pos");
            }

            // Special cases for links, they can't end in a special char like . ? or !
            if (Char.IsPunctuation(markdown[linkEnd - 1]))
            {
                linkEnd--;
            }

            // Grab the link text
            Url = markdown.Substring(linkStart, linkEnd - linkStart);

            // Return the point after the end
            return(linkEnd);
        }
        /// <summary>
        /// Called when this block type should parse out the goods. Given the markdown, a starting point, and a max ending point
        /// the block should find the start of the block, find the end and parse out the middle. The end most of the time will not be
        /// the max ending pos, but it sometimes can be. The function will return where it ended parsing the block in the markdown.
        /// </summary>
        /// <param name="markdown"></param>
        /// <param name="startingPos"></param>
        /// <param name="maxEndingPos"></param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int maxEndingPos)
        {
            // Figure out what char we are processing.
            int  horzStart = startingPos;
            char ruleChar  = '*';

            if (markdown[horzStart] == '*')
            {
                ruleChar = '*';
            }
            else if (markdown[horzStart] == '-')
            {
                ruleChar = '-';
            }
            else if (markdown[horzStart] == '=')
            {
                ruleChar = '=';
            }
            else if (markdown[horzStart] == '_')
            {
                ruleChar = '_';
            }
            else
            {
                DebuggingReporter.ReportCriticalError("Tried parse horizontal rule but didn't find a * or -");
                return(maxEndingPos);
            }

            // Find the end of the line
            int horzEnd = horzStart;

            while (horzEnd < markdown.Length && horzEnd < maxEndingPos)
            {
                if (markdown[horzEnd] != ruleChar)
                {
                    break;
                }
                horzEnd++;
            }

            // Trim off any extra line endings, except ' ' otherwise we can't do code blocks
            while (horzEnd < markdown.Length && horzEnd < maxEndingPos && Char.IsWhiteSpace(markdown[horzEnd]) && markdown[horzEnd] != ' ')
            {
                horzEnd++;
            }

            // Return where we ended.
            return(horzEnd);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Called when this block type should parse out the goods. Given the markdown, a starting point, and a max ending point
        /// the block should find the start of the block, find the end and parse out the middle. The end most of the time will not be
        /// the max ending pos, but it sometimes can be. The function will return where it ended parsing the block in the markdown.
        /// </summary>
        /// <param name="markdown"></param>
        /// <param name="startingPos"></param>
        /// <param name="maxEndingPos"></param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int maxEndingPos)
        {
            // Do a quick check
            int headerStart = startingPos;

            if (markdown[headerStart] != '#')
            {
                DebuggingReporter.ReportCriticalError("Tried to parse a header but # wasn't found");
            }

            // Find the end of header, note that headers break with a single new line no matter what.
            int headerEnd = Common.FindNextSingleNewLine(ref markdown, headerStart, maxEndingPos);

            if (headerEnd == -1)
            {
                DebuggingReporter.ReportCriticalError("Tried to parse header that didn't have an end");
                headerEnd = maxEndingPos;
            }

            // Find how many are in a row
            while (headerStart < markdown.Length && headerStart < maxEndingPos && markdown[headerStart] == '#')
            {
                HeaderLevel++;
                headerStart++;

                // To match reddit's formatting if there are more than 6 we should start showing them.
                if (HeaderLevel > 5)
                {
                    break;
                }
            }

            // Make sure there is something to parse, and not just dead space
            if (headerEnd > headerStart)
            {
                // Parse the children of this quote
                ParseInlineChildren(ref markdown, headerStart, headerEnd);
            }

            // Trim off any extra line endings, except ' ' otherwise we can't do code blocks
            while (headerEnd < markdown.Length && headerEnd < maxEndingPos && Char.IsWhiteSpace(markdown[headerEnd]) && markdown[headerEnd] != ' ')
            {
                headerEnd++;
            }

            // Return where we ended.
            return(headerEnd);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Called when this block type should parse out the goods. Given the markdown, a starting point, and a max ending point
        /// the block should find the start of the block, find the end and parse out the middle. The end most of the time will not be
        /// the max ending pos, but it sometimes can be. The function will return where it ended parsing the block in the markdown.
        /// </summary>
        /// <param name="markdown"></param>
        /// <param name="startingPos"></param>
        /// <param name="maxEndingPos"></param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int maxEndingPos)
        {
            // Do a quick check.
            int quoteStart = startingPos + 1;

            if (markdown[startingPos] != '>')
            {
                DebuggingReporter.ReportCriticalError("Tried to parse quote that didn't exist");
            }

            // Find the end of quote, we always break on a double return no matter what.
            int quoteEnd = Common.FindNextDoubleNewLine(ref markdown, quoteStart, maxEndingPos);

            if (quoteEnd == -1)
            {
                DebuggingReporter.ReportCriticalError("Tried to parse quote that didn't have an end");
                quoteEnd = maxEndingPos;
            }

            // Find how many indents we have, we have to count backwards from the starting pos. Start with one
            // so if we have no spaces we at least get that.
            QuoteIndent = 1;
            int currentBackCount = startingPos - 1;

            while (currentBackCount >= 0 && markdown[currentBackCount] != '\n' && markdown[currentBackCount] != '\r')
            {
                QuoteIndent++;
                currentBackCount--;
            }

            // Make sure there is something to parse, and not just dead space
            if (quoteEnd > quoteStart)
            {
                // Parse the children of this quote
                ParseInlineChildren(ref markdown, quoteStart, quoteEnd);
            }

            // Trim off any extra line endings, except ' ' otherwise we can't do code blocks
            while (quoteEnd < markdown.Length && quoteEnd < maxEndingPos && Char.IsWhiteSpace(markdown[quoteEnd]) && markdown[quoteEnd] != ' ')
            {
                quoteEnd++;
            }

            // Return where we ended.
            return(quoteEnd);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Called when this block type should parse out the goods. Given the markdown, a starting point, and a max ending point
        /// the block should find the start of the block, find the end and parse out the middle. The end most of the time will not be
        /// the max ending pos, but it sometimes can be. The function will return where it ended parsing the block in the markdown.
        /// </summary>
        /// <param name="markdown"></param>
        /// <param name="startingPos"></param>
        /// <param name="maxEndingPos"></param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int maxEndingPos)
        {
            // Get the end.
            int nbspEnd = TryToFindNbsp(ref markdown, startingPos, maxEndingPos);

            // Sanity check
            if (nbspEnd == -1)
            {
                DebuggingReporter.ReportCriticalError("Tried parse line break find a &nbps;");
                return(maxEndingPos);
            }

            // Trim off any extra line endings, except ' ' otherwise we can't do code blocks
            while (nbspEnd < markdown.Length && nbspEnd < maxEndingPos && Char.IsWhiteSpace(markdown[nbspEnd]) && markdown[nbspEnd] != ' ')
            {
                nbspEnd++;
            }

            // Return where we ended.
            return(nbspEnd);
        }
        /// <summary>
        /// Called when the object should parse it's goods out of the markdown. The markdown, start, and stop are given.
        /// The start and stop are what is returned from the FindNext function below. The object should do it's parsing and
        /// return up to the last pos it used. This can be shorter than what is given to the function in endingPos.
        /// </summary>
        /// <param name="markdown">The markdown</param>
        /// <param name="startingPos">Where the parse should start</param>
        /// <param name="endingPos">Where the parse should end</param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int endingPos)
        {
            // Do a sanity check.
            if ((Char.ToLower(markdown[startingPos]) != 'r' || markdown[startingPos + 1] != '/') &&
                (markdown[startingPos] != '/' || Char.ToLower(markdown[startingPos + 1]) != 'r' || markdown[startingPos + 2] != '/'))
            {
                DebuggingReporter.ReportCriticalError("Trying to parse a subreddit link but didn't find a subreddit");
                return(endingPos);
            }
            int subredditStart = startingPos;

            // Grab where to begin looking for the end.
            int subredditEnd       = subredditStart + 2;
            int subredditTextStart = subredditStart + 2;

            // If we start with a / we need to +1 to the end.
            if (markdown[subredditStart] == '/')
            {
                subredditEnd++;
            }

            // While we didn't hit the end && (it is a char or digit or _ )
            subredditEnd = Common.FindNextNonLetterDigitOrUnderscore(ref markdown, subredditEnd, endingPos, true);

            // Validate
            if (subredditEnd != endingPos)
            {
                DebuggingReporter.ReportCriticalError("Raw subreddit ending didn't match endingPos");
            }

            // Grab the text
            Text = markdown.Substring(subredditStart, subredditEnd - subredditStart);

            // Return what we consumed
            return(subredditEnd);
        }
        /// <summary>
        /// Called to preform a render of the current Markdown.
        /// </summary>
        private void RenderMarkdown()
        {
            // Make sure we have something to parse.
            if (string.IsNullOrWhiteSpace(Text))
            {
                return;
            }

            // Leave if we don't have our root yet.
            if (_rootElement == null)
            {
                return;
            }

            // Disconnect from OnClick handlers.
            UnhookListeners();

            MarkdownRenderedEventArgs markdownRenderedArgs = new MarkdownRenderedEventArgs(null);

            try
            {
                // Try to parse the markdown.
                MarkdownDocument markdown = new MarkdownDocument();
                markdown.Parse(Text);

                // Now try to display it
                var renderer = new XamlRenderer(markdown, this, this)
                {
                    Background             = Background,
                    BorderBrush            = BorderBrush,
                    BorderThickness        = BorderThickness,
                    CharacterSpacing       = CharacterSpacing,
                    FontFamily             = FontFamily,
                    FontSize               = FontSize,
                    FontStretch            = FontStretch,
                    FontStyle              = FontStyle,
                    FontWeight             = FontWeight,
                    Foreground             = Foreground,
                    IsTextSelectionEnabled = IsTextSelectionEnabled,
                    Padding                 = Padding,
                    CodeBackground          = CodeBackground,
                    CodeBorderBrush         = CodeBorderBrush,
                    CodeBorderThickness     = CodeBorderThickness,
                    CodeForeground          = CodeForeground,
                    CodeFontFamily          = CodeFontFamily,
                    CodePadding             = CodePadding,
                    CodeMargin              = CodeMargin,
                    Header1FontSize         = Header1FontSize,
                    Header1FontWeight       = Header1FontWeight,
                    Header1Margin           = Header1Margin,
                    Header1Foreground       = Header1Foreground,
                    Header2FontSize         = Header2FontSize,
                    Header2FontWeight       = Header2FontWeight,
                    Header2Margin           = Header2Margin,
                    Header2Foreground       = Header2Foreground,
                    Header3FontSize         = Header3FontSize,
                    Header3FontWeight       = Header3FontWeight,
                    Header3Margin           = Header3Margin,
                    Header3Foreground       = Header3Foreground,
                    Header4FontSize         = Header4FontSize,
                    Header4FontWeight       = Header4FontWeight,
                    Header4Margin           = Header4Margin,
                    Header4Foreground       = Header4Foreground,
                    Header5FontSize         = Header5FontSize,
                    Header5FontWeight       = Header5FontWeight,
                    Header5Margin           = Header5Margin,
                    Header5Foreground       = Header5Foreground,
                    Header6FontSize         = Header6FontSize,
                    Header6FontWeight       = Header6FontWeight,
                    Header6Margin           = Header6Margin,
                    Header6Foreground       = Header6Foreground,
                    HorizontalRuleBrush     = HorizontalRuleBrush,
                    HorizontalRuleMargin    = HorizontalRuleMargin,
                    HorizontalRuleThickness = HorizontalRuleThickness,
                    ListMargin              = ListMargin,
                    ListGutterWidth         = ListGutterWidth,
                    ListBulletSpacing       = ListBulletSpacing,
                    ParagraphMargin         = ParagraphMargin,
                    QuoteBackground         = QuoteBackground,
                    QuoteBorderBrush        = QuoteBorderBrush,
                    QuoteBorderThickness    = QuoteBorderThickness,
                    QuoteForeground         = QuoteForeground,
                    QuoteMargin             = QuoteMargin,
                    QuotePadding            = QuotePadding,
                    TableBorderBrush        = TableBorderBrush,
                    TableBorderThickness    = TableBorderThickness,
                    TableCellPadding        = TableCellPadding,
                    TableMargin             = TableMargin,
                    TextWrapping            = TextWrapping,
                    LinkForeground          = LinkForeground,
                    ImageStretch            = ImageStretch
                };
                _rootElement.Child = renderer.Render();
            }
            catch (Exception ex)
            {
                DebuggingReporter.ReportCriticalError("Error while parsing and rendering: " + ex.Message);
                markdownRenderedArgs = new MarkdownRenderedEventArgs(ex);
            }

            // Indicate that the parse is done.
            MarkdownRendered?.Invoke(this, markdownRenderedArgs);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Called when this block type should parse out the goods. Given the markdown, a starting point, and a max ending point
        /// the block should find the start of the block, find the end and parse out the middle. The end most of the time will not be
        /// the max ending pos, but it sometimes can be. The function will return where it ended parsing the block in the markdown.
        /// </summary>
        /// <param name="markdown"></param>
        /// <param name="startingPos"></param>
        /// <param name="maxEndingPos"></param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int maxEndingPos)
        {
            // Find where the code begins, since we are given the line after the last space we actually need
            // to go backwards.
            int spaceCountStart = startingPos - 1;
            int spaceCount      = 0;

            while (spaceCountStart >= 0)
            {
                // If we found a space count it
                if (markdown[spaceCountStart] == ' ')
                {
                    spaceCount++;
                }
                else
                {
                    if (spaceCount > 3)
                    {
                        // We found the next char after the code begin
                        break;
                    }
                    else
                    {
                        // We found a char that broke the space count
                        spaceCount = 0;
                    }
                }
                spaceCountStart--;
            }

            if (spaceCount == 0)
            {
                DebuggingReporter.ReportCriticalError("Tried to code but found no space row > 3");
            }

            // Find the end of code, note code breaks with a single new line no matter what.
            int codeEnd = Common.FindNextSingleNewLine(ref markdown, startingPos, maxEndingPos);

            if (codeEnd == -1)
            {
                DebuggingReporter.ReportCriticalError("Tried to code quote that didn't have an end");
                codeEnd = maxEndingPos;
            }

            // For every 4 spaces we want to add an indent
            CodeIndent = (int)Math.Floor(spaceCount / 4.0);

            // Make sure there is something to parse, and not just dead space
            if (codeEnd > startingPos)
            {
                // Parse the children of this quote
                ParseInlineChildren(ref markdown, startingPos, codeEnd);
            }

            // Trim off any extra line endings, except ' ' otherwise we can't do code blocks
            while (codeEnd < markdown.Length && codeEnd < maxEndingPos && Char.IsWhiteSpace(markdown[codeEnd]) && markdown[codeEnd] != ' ')
            {
                codeEnd++;
            }

            // Return where we ended.
            return(codeEnd);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Called when this block type should parse out the goods. Given the markdown, a starting point, and a max ending point
        /// the block should find the start of the block, find the end and parse out the middle. The end most of the time will not be
        /// the max ending pos, but it sometimes can be. The function will return where it ended parsing the block in the markdown.
        /// </summary>
        /// <param name="markdown"></param>
        /// <param name="startingPos"></param>
        /// <param name="maxEndingPos"></param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int maxEndingPos)
        {
            // Find out what the list is and where it begins.
            int listStart = startingPos;

            while (listStart < markdown.Length && listStart < maxEndingPos)
            {
                // We have a bullet list
                if (markdown[listStart] == '*' || markdown[listStart] == '-')
                {
                    ListBullet = "•";
                    // +1 to move past the ' '
                    listStart++;
                    break;
                }
                // We have a letter or digit list, start grabbing the bullet
                else if (Char.IsLetterOrDigit(markdown[listStart]))
                {
                    // Grab the list letter, but keep going to get the rest.
                    ListBullet += markdown[listStart];
                }
                // We finished the letter list.
                else if (markdown[listStart] == '.')
                {
                    ListBullet += '.';
                    break;
                }
                listStart++;
            }

            // Now figure out how many spaces come before this list, we have to count backwards from the starting pos.
            ListIndent = 0;
            int currentBackCount = startingPos - 1;

            while (currentBackCount >= 0 && markdown[currentBackCount] != '\n' && markdown[currentBackCount] != '\r')
            {
                ListIndent++;
                currentBackCount--;
            }

            // A list should only single newline break if it is that start of another element in the list.
            // So we need to loop to check for them.
            // This is hard becasue of all of our list types. For * and - we just check if the next two chars
            // are * or and a ' ' if so we matched. For letters and digits, once we find one we keep looping until
            // we find a '.'. If we find a . we get a match, if anything else we fail.
            int nextDoubleBreak    = Common.FindNextDoubleNewLine(ref markdown, listStart, maxEndingPos);
            int nextSingleBreak    = Common.FindNextSingleNewLine(ref markdown, listStart, maxEndingPos);
            int potentialListStart = -1;
            int listEnd            = nextDoubleBreak;

            while (nextSingleBreak < nextDoubleBreak && nextSingleBreak + 2 < maxEndingPos)
            {
                // Ignore spaces unless we are tracking a potential list start
                if (potentialListStart == -1 && markdown[nextSingleBreak + 1] == ' ')
                {
                    nextSingleBreak++;
                }
                // Check for a * or a - followed by a space
                else if ((markdown[nextSingleBreak + 1] == '*' || markdown[nextSingleBreak + 1] == '-') && markdown[nextSingleBreak + 2] == ' ')
                {
                    // This is our line break
                    listEnd = nextSingleBreak;
                    break;
                }
                // If this is a char we might have a new list start. Note the position and loop.
                else if (Char.IsLetterOrDigit(markdown[nextSingleBreak + 1]))
                {
                    if (potentialListStart == -1)
                    {
                        potentialListStart = nextSingleBreak;
                    }
                    nextSingleBreak++;
                }
                // If we find a . and we have a potential list start then we matched.
                else if (potentialListStart != -1 && markdown[nextSingleBreak + 1] == '.')
                {
                    // This is our line break
                    listEnd = potentialListStart;
                    break;
                }
                else
                {
                    // We failed with this new line, try to get the next one.
                    nextSingleBreak    = Common.FindNextSingleNewLine(ref markdown, nextSingleBreak + 1, maxEndingPos);
                    potentialListStart = -1;
                }
            }

            if (listEnd == -1)
            {
                DebuggingReporter.ReportCriticalError("Tried to parse list that didn't have an end");
                listEnd = maxEndingPos;
            }

            // Remove one indent from the list. This doesn't work exactly like reddit's
            // but it is close enough
            ListIndent = Math.Max(1, ListIndent - 1);

            // Jump past the *
            listStart++;

            // Make sure there is something to parse, and not just dead space
            if (listEnd > listStart)
            {
                // Parse the children of this list
                ParseInlineChildren(ref markdown, listStart, listEnd);
            }

            // Trim off any extra line endings, except ' ' otherwise we can't do code blocks
            while (listEnd < markdown.Length && listEnd < maxEndingPos && Char.IsWhiteSpace(markdown[listEnd]) && markdown[listEnd] != ' ')
            {
                listEnd++;
            }

            // Return where we ended.
            return(listEnd);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Called when the object should parse it's goods out of the markdown. The markdown, start, and stop are given.
        /// The start and stop are what is returned from the FindNext function below. The object should do it's parsing and
        /// return up to the last pos it used. This can be shorter than what is given to the function in endingPos.
        /// </summary>
        /// <param name="markdown">The markdown</param>
        /// <param name="startingPos">Where the parse should start</param>
        /// <param name="endingPos">Where the parse should end</param>
        /// <returns></returns>
        internal override int Parse(ref string markdown, int startingPos, int endingPos)
        {
            // Find all of the link parts
            int linkTextOpen  = Common.IndexOf(ref markdown, '[', startingPos, endingPos);
            int linkTextClose = Common.IndexOf(ref markdown, ']', linkTextOpen, endingPos);
            int linkOpen      = Common.IndexOf(ref markdown, '(', linkTextClose, endingPos);
            int linkClose     = Common.IndexOf(ref markdown, ')', linkOpen, endingPos);

            // These should always be =
            if (linkTextOpen != startingPos)
            {
                DebuggingReporter.ReportCriticalError("link parse didn't find [ in at the starting pos");
            }
            if (linkClose + 1 != endingPos)
            {
                DebuggingReporter.ReportCriticalError("link parse didn't find ] in at the end pos");
            }

            // Make sure there is something to parse, and not just dead space
            linkTextOpen++;
            if (linkTextClose > linkTextOpen)
            {
                // Parse any children of this link element
                ParseInlineChildren(ref markdown, linkTextOpen, linkTextClose);
            }

            // We can't render links in links. So if anything in the children of this is a link
            // we have to remove it
            for (int count = 0; count < Children.Count; count++)
            {
                // Look through the children for a link, if found grab the text
                MarkdownInlineType type        = ((MarkdownInline)Children[count]).Type;
                string             replaceText = null;
                if (type == MarkdownInlineType.MarkdownLink)
                {
                    // If it is a link just grab the URL. Ideally we would grab the text
                    // but that is too hard and this will never happen.
                    replaceText = ((MarkdownLinkInline)Children[count]).Url;
                }
                else if (type == MarkdownInlineType.RawHyperlink)
                {
                    replaceText = ((RawHyperlinkInline)Children[count]).Url;
                }
                else if (type == MarkdownInlineType.RawSubreddit)
                {
                    replaceText = ((RawSubredditInline)Children[count]).Text;
                }

                // If we found text to replace add a new text element as the text.
                if (replaceText != null)
                {
                    TextRunInline textRun = new TextRunInline();
                    textRun.Text    = replaceText;
                    Children[count] = textRun;
                }
            }

            // Grab the link
            linkOpen++;
            Url = markdown.Substring(linkOpen, linkClose - linkOpen);

            // Return the point after the )
            return(linkClose + 1);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Fired when the value of a DependencyProperty is changed.
        /// </summary>
        /// <param name="d"></param>
        /// <param name="prop"></param>
        private void OnPropertyChanged(DependencyObject d, DependencyProperty prop)
        {
            // Make sure we have something to parse.
            if (Markdown == null)
            {
                return;
            }

            // Disconnect from OnClick handlers.
            UnhookListeners();

            var args = new OnMarkdownReadyArgs();

            try
            {
                // Try to parse the markdown.
                MarkdownDocument markdown = new MarkdownDocument();
                markdown.Parse(Markdown);

                // Now try to display it
                var renderer = new XamlRenderer(markdown, this);
                renderer.Background             = Background;
                renderer.BorderBrush            = BorderBrush;
                renderer.BorderThickness        = BorderThickness;
                renderer.CharacterSpacing       = CharacterSpacing;
                renderer.FontFamily             = FontFamily;
                renderer.FontSize               = FontSize;
                renderer.FontStretch            = FontStretch;
                renderer.FontStyle              = FontStyle;
                renderer.FontWeight             = FontWeight;
                renderer.Foreground             = Foreground;
                renderer.IsTextSelectionEnabled = IsTextSelectionEnabled;
                renderer.Padding                 = Padding;
                renderer.CodeBackground          = CodeBackground;
                renderer.CodeBorderBrush         = CodeBorderBrush;
                renderer.CodeBorderThickness     = CodeBorderThickness;
                renderer.CodeForeground          = CodeForeground;
                renderer.CodeFontFamily          = CodeFontFamily;
                renderer.CodePadding             = CodePadding;
                renderer.CodeMargin              = CodeMargin;
                renderer.Header1FontSize         = Header1FontSize;
                renderer.Header1FontWeight       = Header1FontWeight;
                renderer.Header1Margin           = Header1Margin;
                renderer.Header2FontSize         = Header2FontSize;
                renderer.Header2FontWeight       = Header2FontWeight;
                renderer.Header2Margin           = Header2Margin;
                renderer.Header3FontSize         = Header3FontSize;
                renderer.Header3FontWeight       = Header3FontWeight;
                renderer.Header3Margin           = Header3Margin;
                renderer.Header4FontSize         = Header4FontSize;
                renderer.Header4FontWeight       = Header4FontWeight;
                renderer.Header4Margin           = Header4Margin;
                renderer.Header5FontSize         = Header5FontSize;
                renderer.Header5FontWeight       = Header5FontWeight;
                renderer.Header5Margin           = Header5Margin;
                renderer.Header6FontSize         = Header6FontSize;
                renderer.Header6FontWeight       = Header6FontWeight;
                renderer.Header6Margin           = Header6Margin;
                renderer.HorizontalRuleBrush     = HorizontalRuleBrush;
                renderer.HorizontalRuleMargin    = HorizontalRuleMargin;
                renderer.HorizontalRuleThickness = HorizontalRuleThickness;
                renderer.ListMargin              = ListMargin;
                renderer.ListGutterWidth         = ListGutterWidth;
                renderer.ListBulletSpacing       = ListBulletSpacing;
                renderer.ParagraphMargin         = ParagraphMargin;
                renderer.QuoteBackground         = QuoteBackground;
                renderer.QuoteBorderBrush        = QuoteBorderBrush;
                renderer.QuoteBorderThickness    = QuoteBorderThickness;
                renderer.QuoteForeground         = QuoteForeground;
                renderer.QuoteMargin             = QuoteMargin;
                renderer.QuotePadding            = QuotePadding;
                renderer.TableBorderBrush        = TableBorderBrush;
                renderer.TableBorderThickness    = TableBorderThickness;
                renderer.TableCellPadding        = TableCellPadding;
                renderer.TableMargin             = TableMargin;
                renderer.TextWrapping            = TextWrapping;
                Content = renderer.Render();
            }
            catch (Exception ex)
            {
                DebuggingReporter.ReportCriticalError("Error while parsing and rendering: " + ex.Message);
                args.WasError  = true;
                args.Exception = ex;
            }

            // #todo indicate if ready
            m_onMarkdownReady.Raise(this, args);
        }