예제 #1
0
        private static bool CanParseDoubleLineHeading(
            ParseInput input
            )
        {
            bool isDoubleLineHeading = false;

            if (input.Lines().Count > 1)
            {
                isDoubleLineHeading = regexDoubleLineHeading.Match(input.Lines()[1]).Success;
            }
            return(isDoubleLineHeading);
        }
예제 #2
0
        private static ParseResult ParseDoubleLineHeading(
            ParseInput input
            )
        {
            ArraySegment <string> lines  = input.Lines();
            ParseResult           result = new ParseResult();
            int level;

            if (lines[1].StartsWith("="))
            {
                level = 1;
            }
            else
            {
                level = 2;
            }
            MarkdownHeading element = new MarkdownHeading(
                level,
                MarkdownParser.ParseInnerText(
                    new ParseInput(
                        input,
                        lines[0]
                        )
                    )
                );

            lines[0]       = "";
            lines[1]       = "";
            result.Success = true;
            result.AddContent(
                element
                );
            return(result);
        }
예제 #3
0
        private static void RemoveListIndicators(
            ParseInput input
            )
        {
            ArraySegment <string> lines = input.Lines();

            for (int i = 0; i < lines.Count; i++)
            {
                string truncated = lines[i];
                Match  lineOrderedContentMatch   = regexOrderedListLine.Match(lines[i]);
                Match  lineUnorderedContentMatch = regexUnorderedListLine.Match(lines[i]);
                if (
                    lineOrderedContentMatch.Success ||
                    lineUnorderedContentMatch.Success
                    )
                {
                    if (lineOrderedContentMatch.Success)
                    {
                        truncated = lineOrderedContentMatch.Groups[1].Value;
                    }
                    else if (lineUnorderedContentMatch.Success)
                    {
                        truncated = lineUnorderedContentMatch.Groups[1].Value;
                    }
                    int spaces = 0;
                    // Count spaces
                    while (
                        (spaces < truncated.Length) &&
                        (truncated[spaces] == ' ')
                        )
                    {
                        spaces++;
                    }
                    // If there are fewer than 5 spaces, remove all
                    if (spaces < 5)
                    {
                        lines[i] = truncated.Substring(spaces);
                    }
                    else
                    {
                        // More than five, just remove one space
                        lines[i] = truncated.Substring(1);
                    }
                }
                else
                {
                    lines[i] = lines[i];
                }
            }
        }
예제 #4
0
        private static ParseResult ParseSingleLineHeading(
            ParseInput input
            )
        {
            ArraySegment <string> lines  = input.Lines();
            ParseResult           result = new ParseResult();
            // Calculate heading level, (maximum 6)
            int level = 0;

            while (
                (level < 6) &&
                (lines[0][level] == '#')
                )
            {
                level++;
            }
            Match  contentMatch = regexSingleLineHeading.Match(lines[0]);
            string content      = StripLeadingCharacter(
                StripTrailingCharacter(
                    contentMatch.Groups[1].Value,
                    '#'
                    ),
                ' '
                );

            lines[0]       = "";
            result.Success = true;
            result.AddContent(
                new MarkdownHeading(
                    level,
                    MarkdownParser.ParseInnerText(
                        new ParseInput(
                            input,
                            content
                            )
                        )
                    )
                );
            return(result);
        }
예제 #5
0
        public static bool CanParseFrom(
            ParseInput input
            )
        {
            ArraySegment <string> lines = input.Lines();

            if (!regexBacktickSectionOpen.Match(lines[0]).Success)
            {
                return(false);
            }
            else
            {
                for (int i = 1; i < lines.Count; i++)
                {
                    if (regexBacktickSectionClose.Match(lines[i]).Success)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
예제 #6
0
        public static ParseResult ParseFrom(
            ParseInput input
            )
        {
            ParseResult result = new ParseResult();

            if (!CanParseFrom(input))
            {
                return(result);
            }
            ArraySegment <string> lines = input.Lines();

            lines[0] = "";
            LinkedList <IHtmlable> innerContent = new LinkedList <IHtmlable>();
            int i = 1;

            while (!regexBacktickSectionClose.Match(lines[i]).Success)
            {
                innerContent.AddLast(
                    new MarkdownText(
                        lines[i]
                        )
                    );
                lines[i] = "";
                i++;
            }
            // Remember to clear final line (closing backticks)
            lines[i] = "";
            MarkdownCodeBlock blockCodeElement = new MarkdownCodeBlock(
                Utils.LinkedListToArray(innerContent)
                );

            result.Success = true;
            result.AddContent(blockCodeElement);
            return(result);
        }
예제 #7
0
        public static ParseResult ParseFrom(
            ParseInput input
            )
        {
            ArraySegment <string> lines  = input.Lines();
            ParseResult           result = new ParseResult();

            if (!CanParseFrom(input))
            {
                return(result);
            }
            int endQuoteSection = FindEndOfQuoteSection(
                lines
                );

            string[] truncatedLines = new string[endQuoteSection];
            // Remove quote arrows and spaces, if needed
            for (int i = 0; i < endQuoteSection; i++)
            {
                string truncated = lines[i];
                if (lines[i].StartsWith(">"))
                {
                    truncated = truncated.Substring(1);
                    int spaces = 0;
                    // Count spaces
                    while (
                        (spaces < truncated.Length) &&
                        (truncated[spaces] == ' ')
                        )
                    {
                        spaces++;
                    }
                    // If there are fewer than 5 spaces, remove all
                    if (spaces < 5)
                    {
                        truncatedLines[i] = truncated.Substring(spaces);
                    }
                    else
                    {
                        // More than five, just remove one space
                        truncatedLines[i] = truncated.Substring(1);
                    }
                }
                else
                {
                    truncatedLines[i] = lines[i];
                }
                // Remove original line
                lines[i] = "";
            }

            /*
             * The truncated lines should be parsed as any other line group
             * and wrapped in a blockquote element
             */
            MarkdownParser parser = new MarkdownParser(
                truncatedLines
                );

            MarkdownQuote quoteElement = new MarkdownQuote(
                parser.ContentAsArray()
                );

            result.Success = true;
            result.AddContent(
                quoteElement
                );
            return(result);
        }
예제 #8
0
        public static ParseResult ParseFrom(
            ParseInput input
            )
        {
            ArraySegment <string> lines  = input.Lines();
            ParseResult           result = new ParseResult();

            if (!CanParseFrom(input))
            {
                return(result);
            }

            /*
             * Work out the list type from the first line
             * before we start to mangle the line contents
             */
            MarkdownElementType type;

            if (regexOrderedListLine.Match(input.FirstLine).Success)
            {
                type = MarkdownElementType.OrderedList;
            }
            else
            {
                type = MarkdownElementType.UnorderedList;
            }
            int endListSection = FindEndOfListSection(
                lines
                );
            // New array segment with only parsed content
            ArraySegment <string> listLines = new ArraySegment <string>(
                lines.Array,
                lines.Offset,
                endListSection
                );
            // Need to split into groups per list item
            int currentIndex = 0;
            // Hold the parsed list items as we go
            LinkedList <IHtmlable> listItems = new LinkedList <IHtmlable>();
            // Track whether list item contents should be in a paragraph
            bool whitespaceLineBefore = false;
            bool whitespaceLineAfter  = false;

            while (currentIndex < endListSection)
            {
                int endIndex = FindEndOfListItem(
                    listLines,
                    currentIndex
                    );

                /*
                 * There is a whitespace line between
                 * this list item and the following one
                 * and this list item isn't the final one
                 */
                whitespaceLineAfter = (
                    (endIndex < listLines.Count) &&
                    (
                        ContainsOnlyWhitespace(
                            listLines[endIndex - 1]
                            )
                    )
                    );
                // Create new parse input for this list item
                ParseInput listItemLines = new ParseInput(
                    input.Urls,
                    listLines.Array,
                    listLines.Offset + currentIndex,
                    endIndex - currentIndex
                    );
                RemoveListIndicators(
                    listItemLines
                    );
                ParseResult nextListItem = MarkdownListItem.ParseFrom(
                    listItemLines,
                    whitespaceLineBefore || whitespaceLineAfter
                    );
                foreach (
                    IHtmlable entry
                    in nextListItem.GetContent()
                    )
                {
                    listItems.AddLast(
                        entry
                        );
                }
                // Jump over lines just parsed
                currentIndex += (endIndex - currentIndex);
                // Whitespace after previous entry becomes before next entry
                whitespaceLineBefore = whitespaceLineAfter;

                /*
                 * If there's further whitespace after parsed section
                 * (for some reason) then jump over this too
                 */
                while (
                    (currentIndex < listLines.Count) &&
                    (
                        ContainsOnlyWhitespace(
                            lines[currentIndex]
                            )
                    )
                    )
                {
                    currentIndex++;
                }
            }
            result.Success = true;
            result.AddContent(
                new MarkdownList(
                    Utils.LinkedListToArray(
                        listItems
                        ),
                    type
                    )
                );
            return(result);
        }
예제 #9
0
        // Parse a plain paragraph
        public static ParseResult ParseFrom(
            ParseInput input
            )
        {
            ArraySegment <string>  lines        = input.Lines();
            ParseResult            result       = new ParseResult();
            LinkedList <IHtmlable> innerContent = new LinkedList <IHtmlable>();
            // The paragraph doesn't get parsed past the first blank line
            int endIndex = 0;

            while (
                (endIndex < lines.Count) &&
                (
                    !ContainsOnlyWhitespace(
                        lines[endIndex]
                        )
                )
                )
            {
                endIndex++;
            }
            int i = 0;

            while (i < endIndex)
            {
                lines = input.Lines();
                if (MarkdownCodeBlock.CanParseFrom(input))
                {
                    ParseResult innerResult = MarkdownCodeBlock.ParseFrom(input);
                    foreach (IHtmlable entry in innerResult.GetContent())
                    {
                        innerContent.AddLast(entry);
                    }
                }
                else
                {
                    string line = lines[0];
                    if (endsWithAtLeastTwoSpaces(line))
                    {
                        string shortened = StripTrailingWhitespace(line);
                        foreach (
                            IHtmlable entry
                            in MarkdownParser.ParseInnerText(
                                new ParseInput(
                                    input,
                                    shortened
                                    )
                                )
                            )
                        {
                            innerContent.AddLast(entry);
                        }
                        innerContent.AddLast(
                            new MarkdownLinebreak()
                            );
                    }
                    else
                    {
                        foreach (
                            IHtmlable entry
                            in MarkdownParser.ParseInnerText(
                                new ParseInput(
                                    input,
                                    line
                                    )
                                )
                            )
                        {
                            innerContent.AddLast(entry);
                        }

                        /*
                         * If this is not the last line,
                         * it doesn't end in a manual linebreak
                         * and the user hasn't added a space themselves
                         * we need to add a space at the end
                         */
                        if (
                            (i < (endIndex - 1)) &&
                            (line.Length > 0) &&
                            (line[^ 1] != ' ')