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); }
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); }
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); }
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); }
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 })); }
public override Node parse(BlockParser parser) { parser.encounteredBlankLine = true; parser.advance(); return(null); }
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 })); } }
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"))); }
/// 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 })); } }
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"))); }
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 })); }
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)); }
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); }
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)); } }
public override Node parse(BlockParser parser) { parser.advance(); return(Element.empty("hr")); }