private static void BlocksToHtmlInner(HtmlTextWriter writer, Block block, CommonMarkSettings settings) { var stack = new Stack <BlockStackEntry>(); var inlineStack = new Stack <InlineStackEntry>(); bool visitChildren; string stackLiteral = null; bool stackTight = false; bool tight = false; bool trackPositions = settings.TrackSourcePosition; int x; while (block != null) { visitChildren = false; switch (block.Tag) { case BlockTag.Document: stackLiteral = null; stackTight = false; visitChildren = true; break; case BlockTag.Paragraph: if (tight) { InlinesToHtml(writer, block.InlineContent, settings, inlineStack); } else { writer.EnsureLine(); writer.WriteConstant("<p"); if (trackPositions) { PrintPosition(writer, block); } writer.Write('>'); InlinesToHtml(writer, block.InlineContent, settings, inlineStack); writer.WriteLineConstant("</p>"); } break; case BlockTag.BlockQuote: writer.EnsureLine(); writer.WriteConstant("<blockquote"); if (trackPositions) { PrintPosition(writer, block); } writer.WriteLine('>'); stackLiteral = "</blockquote>"; stackTight = false; visitChildren = true; break; case BlockTag.ListItem: writer.EnsureLine(); writer.WriteConstant("<li"); if (trackPositions) { PrintPosition(writer, block); } writer.Write('>'); stackLiteral = "</li>"; stackTight = tight; visitChildren = true; break; case BlockTag.List: // make sure a list starts at the beginning of the line: writer.EnsureLine(); var data = block.ListData; writer.WriteConstant(data.ListType == ListType.Bullet ? "<ul" : "<ol"); if (data.Start != 1) { writer.WriteConstant(" start=\""); writer.WriteConstant(data.Start.ToString(CultureInfo.InvariantCulture)); writer.Write('\"'); } if (trackPositions) { PrintPosition(writer, block); } writer.WriteLine('>'); stackLiteral = data.ListType == ListType.Bullet ? "</ul>" : "</ol>"; stackTight = data.IsTight; visitChildren = true; break; case BlockTag.AtxHeading: case BlockTag.SetextHeading: writer.EnsureLine(); x = block.Heading.Level; if (trackPositions) { writer.WriteConstant("<h" + x.ToString(CultureInfo.InvariantCulture)); PrintPosition(writer, block); writer.Write('>'); InlinesToHtml(writer, block.InlineContent, settings, inlineStack); writer.WriteLineConstant(x > 0 && x < 7 ? HeadingCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">"); } else { writer.WriteConstant(x > 0 && x < 7 ? HeadingOpenerTags[x - 1] : "<h" + x.ToString(CultureInfo.InvariantCulture) + ">"); InlinesToHtml(writer, block.InlineContent, settings, inlineStack); writer.WriteLineConstant(x > 0 && x < 7 ? HeadingCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">"); } break; case BlockTag.IndentedCode: case BlockTag.FencedCode: writer.EnsureLine(); writer.WriteConstant("<pre><code"); if (trackPositions) { PrintPosition(writer, block); } var info = block.FencedCodeData == null ? null : block.FencedCodeData.Info; if (info != null && info.Length > 0) { x = info.IndexOf(' '); if (x == -1) { x = info.Length; } writer.WriteConstant(" class=\"language-"); EscapeHtml(new StringPart(info, 0, x), writer); writer.Write('\"'); } writer.Write('>'); EscapeHtml(block.StringContent, writer); writer.WriteLineConstant("</code></pre>"); break; case BlockTag.HtmlBlock: // cannot output source position for HTML blocks block.StringContent.WriteTo(writer); break; case BlockTag.ThematicBreak: if (trackPositions) { writer.WriteConstant("<hr"); PrintPosition(writer, block); writer.WriteLine(); } else { writer.WriteLineConstant("<hr />"); } break; case BlockTag.ReferenceDefinition: break; default: throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block); } if (visitChildren) { stack.Push(new BlockStackEntry(stackLiteral, block.NextSibling, tight)); tight = stackTight; block = block.FirstChild; } else if (block.NextSibling != null) { block = block.NextSibling; } else { block = null; } while (block == null && stack.Count > 0) { var entry = stack.Pop(); writer.WriteLineConstant(entry.Literal); tight = entry.IsTight; block = entry.Target; } } }
/// <summary> /// Ensures that the output ends with a newline. This means that newline character will be written /// only if the writer does not currently end with a newline. /// </summary> protected void EnsureNewLine() { _target.EnsureLine(); }
private static void BlocksToHtmlInner(HtmlTextWriter writer, Block block, CommonMarkSettings settings) { var stack = new Stack<BlockStackEntry>(); var inlineStack = new Stack<InlineStackEntry>(); bool visitChildren; string stackLiteral = null; bool stackTight = false; bool tight = false; bool trackPositions = settings.TrackSourcePosition; int x; while (block != null) { visitChildren = false; switch (block.Tag) { case BlockTag.Document: stackLiteral = null; stackTight = false; visitChildren = true; break; case BlockTag.Paragraph: if (tight) { InlinesToHtml(writer, block.InlineContent, settings, inlineStack); } else { writer.EnsureLine(); writer.WriteConstant("<p"); if (trackPositions) PrintPosition(writer, block); writer.Write('>'); InlinesToHtml(writer, block.InlineContent, settings, inlineStack); writer.WriteLineConstant("</p>"); } break; case BlockTag.BlockQuote: writer.EnsureLine(); writer.WriteConstant("<blockquote"); if (trackPositions) PrintPosition(writer, block); writer.WriteLine('>'); stackLiteral = "</blockquote>"; stackTight = false; visitChildren = true; break; case BlockTag.ListItem: writer.EnsureLine(); writer.WriteConstant("<li"); if (trackPositions) PrintPosition(writer, block); writer.Write('>'); stackLiteral = "</li>"; stackTight = tight; visitChildren = true; break; case BlockTag.List: // make sure a list starts at the beginning of the line: writer.EnsureLine(); var data = block.ListData; writer.WriteConstant(data.ListType == ListType.Bullet ? "<ul" : "<ol"); if (data.Start != 1) { writer.WriteConstant(" start=\""); writer.WriteConstant(data.Start.ToString(CultureInfo.InvariantCulture)); writer.Write('\"'); } if (trackPositions) PrintPosition(writer, block); writer.WriteLine('>'); stackLiteral = data.ListType == ListType.Bullet ? "</ul>" : "</ol>"; stackTight = data.IsTight; visitChildren = true; break; case BlockTag.AtxHeader: case BlockTag.SETextHeader: writer.EnsureLine(); x = block.HeaderLevel; if (trackPositions) { writer.WriteConstant("<h" + x.ToString(CultureInfo.InvariantCulture)); PrintPosition(writer, block); writer.Write('>'); InlinesToHtml(writer, block.InlineContent, settings, inlineStack); writer.WriteLineConstant(x > 0 && x < 7 ? HeaderCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">"); } else { writer.WriteConstant(x > 0 && x < 7 ? HeaderOpenerTags[x - 1] : "<h" + x.ToString(CultureInfo.InvariantCulture) + ">"); InlinesToHtml(writer, block.InlineContent, settings, inlineStack); writer.WriteLineConstant(x > 0 && x < 7 ? HeaderCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">"); } break; case BlockTag.IndentedCode: case BlockTag.FencedCode: writer.EnsureLine(); writer.WriteConstant("<pre><code"); if (trackPositions) PrintPosition(writer, block); var info = block.FencedCodeData == null ? null : block.FencedCodeData.Info; if (info != null && info.Length > 0) { x = info.IndexOf(' '); if (x == -1) x = info.Length; writer.WriteConstant(" class=\"language-"); EscapeHtml(new StringPart(info, 0, x), writer); writer.Write('\"'); } writer.Write('>'); EscapeHtml(block.StringContent, writer); writer.WriteLineConstant("</code></pre>"); break; case BlockTag.HtmlBlock: // cannot output source position for HTML blocks block.StringContent.WriteTo(writer); break; case BlockTag.HorizontalRuler: if (trackPositions) { writer.WriteConstant("<hr"); PrintPosition(writer, block); writer.WriteLine(); } else { writer.WriteLineConstant("<hr />"); } break; case BlockTag.ReferenceDefinition: break; default: throw new CommonMarkException("Block type " + block.Tag + " is not supported.", block); } if (visitChildren) { stack.Push(new BlockStackEntry(stackLiteral, block.NextSibling, tight)); tight = stackTight; block = block.FirstChild; } else if (block.NextSibling != null) { block = block.NextSibling; } else { block = null; } while (block == null && stack.Count > 0) { var entry = stack.Pop(); writer.WriteLineConstant(entry.Literal); tight = entry.IsTight; block = entry.Target; } } }