Beispiel #1
0
        public override List <string> parseChildLines(BlockParser parser)
        {
            var childLines = new List <string>();

            while (!parser.isDone)
            {
                var match = pattern.Match(parser.current);
                if (match.Success)
                {
                    childLines.Add(match.Groups[1].Value);
                    parser.advance();
                }
                else
                {
                    // If there's a codeblock, then a newline, then a codeblock, keep the
                    // code blocks together.
                    var nextMatch =
                        parser.next != null?pattern.Match(parser.next) : null;

                    if (parser.current.Trim() == "" && nextMatch != null)
                    {
                        childLines.Add("");
                        childLines.Add(nextMatch.Groups[1].Value);
                        parser.advance();
                        parser.advance();
                    }
                    else
                    {
                        break;
                    }
                }
            }

            return(childLines);
        }
Beispiel #2
0
        List <String> parseChildLines(BlockParser parser, String endBlock = "")
        {
            if (endBlock == null)
            {
                endBlock = "";
            }

            var childLines = new List <string>();

            parser.advance();

            while (!parser.isDone)
            {
                var match = pattern.Match(parser.current);
                if (!match.Success || !match.Groups[1].Value.StartsWith(endBlock))
                {
                    childLines.Add(parser.current);
                    parser.advance();
                }
                else
                {
                    parser.advance();
                    break;
                }
            }

            return(childLines);
        }
Beispiel #3
0
        public override List <string> parseChildLines(BlockParser parser)
        {
            var childLines = new List <string>();

            while (!parser.isDone)
            {
                var match = this.pattern.Match(parser.current);
                if (match.Success)
                {
                    childLines.Add(match.Groups[1].Value);
                    parser.advance();
                    continue;
                }

                if (parser.blockSyntaxes.First(s => s.canParse(parser)) is ParagraphSyntax)
                {
                    childLines.Add(parser.current);
                    parser.advance();
                }
                else
                {
                    break;
                }
            }

            return(childLines);
        }
Beispiel #4
0
        public override List <string> parseChildLines(BlockParser parser)
        {
            // Grab all of the lines that form the blockquote, stripping off the ">".
            var childLines = new List <string>();

            while (!parser.isDone)
            {
                var match = pattern.Match(parser.current);
                if (match.Success)
                {
                    childLines.Add(match.Groups[1].Value);
                    parser.advance();
                    continue;
                }

                // A paragraph continuation is OK. This is content that cannot be parsed
                // as any other syntax except Paragraph, and it doesn't match the bar in
                // a Setext header.
                if (parser.blockSyntaxes.First(s => s.canParse(parser)) is ParagraphSyntax)
                {
                    childLines.Add(parser.current);
                    parser.advance();
                }
                else
                {
                    break;
                }
            }

            return(childLines);
        }
Beispiel #5
0
        public override Node parse(BlockParser parser)
        {
            var    lines = new List <string>();
            string tag   = string.Empty;

            while (!parser.isDone)
            {
                var match = BlockParser._setextPattern.Match(parser.current);
                if (!match.Success)
                {
                    lines.Add(parser.current);
                    parser.advance();
                    continue;
                }
                else
                {
                    tag = match.Groups[1].Value[0] == '=' ? "h1" : "h2";
                    parser.advance();
                    break;
                }
            }


            var contents = new UnparsedContent(lines.join('\n'));

            return(new Element(tag, new List <Node>()
            {
                contents
            }));
        }
Beispiel #6
0
        public override Node parse(BlockParser parser)
        {
            parser.encounteredBlankLine = true;
            parser.advance();

            return(null);
        }
Beispiel #7
0
        public override Node parse(BlockParser parser)
        {
            var childLines = new List <string>();

            // Eat until we hit something that ends a paragraph.
            while (!BlockSyntax.isAtBlockEnd(parser))
            {
                childLines.Add(parser.current);
                parser.advance();
            }

            var paragraphLines = _extractReflinkDefinitions(parser, childLines);

            if (paragraphLines == null)
            {
                // Paragraph consisted solely of reference link definitions.
                return(new TextNode(""));
            }
            else
            {
                var contents = new UnparsedContent(paragraphLines.join('\n'));
                return(new Element("p", new List <Node>()
                {
                    contents
                }));
            }
        }
Beispiel #8
0
        public override Node parse(BlockParser parser)
        {
            var childLines = new List <string>();

            // Eat until we hit [endPattern].
            while (!parser.isDone)
            {
                childLines.Add(parser.current);
                if (parser.matches(_endPattern))
                {
                    break;
                }
                parser.advance();
            }

            parser.advance();
            return(new TextNode(childLines.join("\n")));
        }
Beispiel #9
0
        /// Parses a table into its three parts:
        ///
        /// * a head row of head cells (`<th>` cells)
        /// * a divider of hyphens and pipes (not rendered)
        /// * many body rows of body cells (`<td>` cells)
        public override Node parse(BlockParser parser)
        {
            var alignments  = parseAlignments(parser.next);
            var columnCount = alignments.Count;
            var headRow     = parseRow(parser, alignments, "th");

            if (headRow.children.Count != columnCount)
            {
                return(null);
            }

            var head = new Element("thead", new List <Node>()
            {
                headRow
            });

            // Advance past the divider of hyphens.
            parser.advance();

            var rows = new List <Element>()
            {
            };

            while (!parser.isDone && !BlockSyntax.isAtBlockEnd(parser))
            {
                var row = parseRow(parser, alignments, "td");
                while (row.children.Count < columnCount)
                {
                    // Insert synthetic empty cells.
                    row.children.Add(Element.empty("td"));
                }

                while (row.children.Count > columnCount)
                {
                    row.children.removeLast();
                }

                rows.Add(row);
            }

            if (rows.isEmpty())
            {
                return(new Element("table", new List <Node>()
                {
                    head
                }));
            }
            else
            {
                var body = new Element("tbody", rows);

                return(new Element("table", new List <Node>()
                {
                    head, body
                }));
            }
        }
Beispiel #10
0
        public override Node parse(BlockParser parser)
        {
            var childLines = new List <string>();

            // Eat until we hit a blank line.
            while (!parser.isDone && !parser.matches(BlockParser._emptyPattern))
            {
                childLines.Add(parser.current);
                parser.advance();
            }

            return(new TextNode(childLines.join("\n")));
        }
Beispiel #11
0
        public override Node parse(BlockParser parser)
        {
            var match = pattern.Match(parser.current);

            parser.advance();
            var level    = match.Groups[1].Length;
            var contents = new UnparsedContent(match.Groups[2].Value.Trim());

            return(new Element("h" + level, new List <Node>()
            {
                contents
            }));
        }
Beispiel #12
0
        Element parseRow(
            BlockParser parser, List <string> alignments, string cellType)
        {
            var line = parser.current
                       .replaceFirst(_openingPipe, "")
                       .replaceFirst(_closingPipe, "");
            var cells = line.split(_pipePattern);

            parser.advance();
            var    row     = new List <Node>();
            string preCell = string.Empty;

            for (var index = 0; index < cells.Length; index++)
            {
                var cell = cells[index];
                if (preCell != null)
                {
                    cell    = preCell + cell;
                    preCell = null;
                }

                if (cell.EndsWith("\\"))
                {
                    preCell = cell.Substring(0, cell.Length - 1) + '|';
                    continue;
                }

                var contents = new UnparsedContent(cell);
                row.Add(new Element(cellType, new List <Node>()
                {
                    contents
                }));
            }

            for (var i = 0; i < row.Count && i < alignments.Count; i++)
            {
                if (alignments[i] == null)
                {
                    continue;
                }

                ((Element)row[i]).attributes["style"] = "text-align: " + alignments[i] + ';';
            }

            return(new Element("tr", row));
        }
Beispiel #13
0
        public virtual List <string> parseChildLines(BlockParser parser)
        {
            var childLines = new List <string>();

            while (!parser.isDone)
            {
                var match = pattern.Match(parser.current);
                if (!match.Success)
                {
                    break;
                }

                childLines.Add(match.Groups[1].Value);

                parser.advance();
            }

            return(childLines);
        }
Beispiel #14
0
        public override Node parse(BlockParser parser)
        {
            var items      = new List <ListItem>();
            var childLines = new List <string>();


            Match match = null;


            string listMarker = null;
            string indent     = null;
            // In case the first number in an ordered list is not 1, use it as the
            // "start".
            int startNumber = 0;

            while (!parser.isDone)
            {
                var leadingSpace             = _whitespaceRe.matchAsPrefix(parser.current).Groups[0].Value;
                var leadingExpandedTabLength = _expandedTabLength(leadingSpace);
                if (tryMatch(BlockParser._emptyPattern, parser, ref match))
                {
                    if (BlockParser._emptyPattern.Match(parser.next ?? "").Success)
                    {
                        // Two blank lines ends a list.
                        break;
                    }

                    // Add a blank line to the current list item.
                    childLines.Add("");
                }
                else if (!string.IsNullOrEmpty(indent) && indent.Length <= leadingExpandedTabLength)
                {
                    // Strip off indent and add to current item.
                    var line = parser.current
                               .replaceFirst(leadingSpace, new string(' ', leadingExpandedTabLength))
                               .replaceFirst(indent, "");
                    childLines.Add(line);
                }
                else if (tryMatch(BlockParser._hrPattern, parser, ref match))
                {
                    // Horizontal rule takes precedence to a new list item.
                    break;
                }
                else if (tryMatch(BlockParser._ulPattern, parser, ref match) ||
                         tryMatch(BlockParser._olPattern, parser, ref match))
                {
                    var precedingWhitespace = match.Groups[1].Value;
                    var digits = match.Groups[2].Value ?? "";
                    if (startNumber == 0 && digits.isNotEmpty())
                    {
                        startNumber = int.Parse(digits);
                    }

                    var marker          = match.Groups[3];
                    var firstWhitespace = match.Groups[5].Value ?? "";
                    var restWhitespace  = match.Groups[6].Value ?? "";
                    var content         = match.Groups[7].Value ?? "";
                    var isBlank         = content.isEmpty();
                    if (listMarker != null && listMarker != marker.Value)
                    {
                        // Changing the bullet or ordered list delimiter starts a new list.
                        break;
                    }

                    listMarker = marker.Value;
                    var markerAsSpaces = new string(' ', digits.Length + marker.Length);
                    if (isBlank)
                    {
                        // See http://spec.commonmark.org/0.28/#list-items under "3. Item
                        // starting with a blank line."
                        //
                        // If the list item starts with a blank line, the final piece of the
                        // indentation is just a single space.
                        indent = precedingWhitespace + markerAsSpaces + ' ';
                    }
                    else if (restWhitespace.Length >= 4)
                    {
                        // See http://spec.commonmark.org/0.28/#list-items under "2. Item
                        // starting with indented code."
                        //
                        // If the list item starts with indented code, we need to _not_ count
                        // any indentation past the required whitespace character.
                        indent = precedingWhitespace + markerAsSpaces + firstWhitespace;
                    }
                    else
                    {
                        indent = precedingWhitespace +
                                 markerAsSpaces +
                                 firstWhitespace +
                                 restWhitespace;
                    }

                    // End the current list item and start a new one.
                    endItem(ref childLines, items);
                    childLines.Add(restWhitespace + content);
                }
                else if (BlockSyntax.isAtBlockEnd(parser))
                {
                    // Done with the list.
                    break;
                }
                else
                {
                    // If the previous item is a blank line, this means we're done with the
                    // list and are starting a new top-level paragraph.
                    if ((childLines.isNotEmpty()) && (childLines.last() == ""))
                    {
                        parser.encounteredBlankLine = true;
                        break;
                    }

                    // Anything else is paragraph continuation text.
                    childLines.Add(parser.current);
                }

                parser.advance();
            }

            endItem(ref childLines, items);
            var itemNodes = new List <Element>();

            items.ForEach(removeLeadingEmptyLine);
            var anyEmptyLines = removeTrailingEmptyLines(items);
            var anyEmptyLinesBetweenBlocks = false;

            foreach (var item in items)
            {
                var itemParser = new BlockParser(item.lines, parser.document);
                var children   = itemParser.parseLines();
                itemNodes.Add(new Element("li", children));
                anyEmptyLinesBetweenBlocks =
                    anyEmptyLinesBetweenBlocks || itemParser.encounteredBlankLine;
            }

            // Must strip paragraph tags if the list is "tight".
            // http://spec.commonmark.org/0.28/#lists
            var listIsTight = !anyEmptyLines && !anyEmptyLinesBetweenBlocks;

            if (listIsTight)
            {
                // We must post-process the list items, converting any top-level paragraph
                // elements to just text elements.
                foreach (var item in itemNodes)
                {
                    for (var i = 0; i < item.children.Count; i++)
                    {
                        var child = item.children[i];
                        var ele   = child as Element;
                        if (ele != null && ele.tag == "p")
                        {
                            item.children.RemoveAt(i);
                            item.children.InsertRange(i, ele.children);
                        }
                    }
                }
            }

            if (listTag == "ol" && startNumber != 1)
            {
                var element = new Element(listTag, itemNodes);
                element.attributes["start"] = startNumber.ToString();
                return(element);
            }
            else
            {
                return(new Element(listTag, itemNodes));
            }
        }
Beispiel #15
0
 public override Node parse(BlockParser parser)
 {
     parser.advance();
     return(Element.empty("hr"));
 }