mirror of
https://github.com/xoofx/markdig.git
synced 2026-02-15 14:05:39 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f4e958ab2 | ||
|
|
26beaa81da | ||
|
|
de5ed11963 | ||
|
|
b557d51276 | ||
|
|
27a8345943 | ||
|
|
131163ff9a | ||
|
|
241f674b99 | ||
|
|
194edee243 | ||
|
|
0995fa0cec | ||
|
|
6717be5210 | ||
|
|
e15745f346 | ||
|
|
a513b0c587 | ||
|
|
72adb963e8 | ||
|
|
aac7df6b87 | ||
|
|
4cf4bfb58f | ||
|
|
59630aec8e | ||
|
|
70c4f6deda | ||
|
|
e2b3f812cb | ||
|
|
fc8adc70e0 | ||
|
|
72c2c06fcb | ||
|
|
7174e32b7a | ||
|
|
600219529c | ||
|
|
c63392657d | ||
|
|
34579b51a1 | ||
|
|
1bb35c5fc1 | ||
|
|
0c408951b8 | ||
|
|
218a094f0d | ||
|
|
3cc405b05b | ||
|
|
d58db530bb | ||
|
|
48866a2609 | ||
|
|
b20b111385 | ||
|
|
6ac2429e2a | ||
|
|
9d52732f18 |
@@ -61,7 +61,9 @@
|
||||
<Compile Include="TestHtmlHelper.cs" />
|
||||
<Compile Include="TestLineReader.cs" />
|
||||
<Compile Include="TestLinkHelper.cs" />
|
||||
<Compile Include="TestNormalize.cs" />
|
||||
<Compile Include="TestOrderedList.cs" />
|
||||
<Compile Include="TestPlainText.cs" />
|
||||
<Compile Include="TestPragmaLines.cs" />
|
||||
<Compile Include="TestSourcePosition.cs" />
|
||||
<Compile Include="TestStringSliceList.cs" />
|
||||
|
||||
434
src/Markdig.Tests/TestNormalize.cs
Normal file
434
src/Markdig.Tests/TestNormalize.cs
Normal file
@@ -0,0 +1,434 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using System.IO;
|
||||
using Markdig.Renderers.Normalize;
|
||||
using Markdig.Helpers;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestNormalize
|
||||
{
|
||||
[Test]
|
||||
public void SyntaxCodeBlock()
|
||||
{
|
||||
AssertSyntax("````csharp\npublic void HelloWorld()\n{\n}\n````", new FencedCodeBlock(null)
|
||||
{
|
||||
FencedChar = '`',
|
||||
FencedCharCount = 4,
|
||||
Info = "csharp",
|
||||
Lines = new StringLineGroup(4)
|
||||
{
|
||||
new StringSlice("public void HelloWorld()"),
|
||||
new StringSlice("{"),
|
||||
new StringSlice("}"),
|
||||
}
|
||||
});
|
||||
|
||||
AssertSyntax(" public void HelloWorld()\n {\n }", new CodeBlock(null)
|
||||
{
|
||||
Lines = new StringLineGroup(4)
|
||||
{
|
||||
new StringSlice("public void HelloWorld()"),
|
||||
new StringSlice("{"),
|
||||
new StringSlice("}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SyntaxHeadline()
|
||||
{
|
||||
AssertSyntax("## Headline", new HeadingBlock(null)
|
||||
{
|
||||
HeaderChar = '#',
|
||||
Level = 2,
|
||||
Inline = new ContainerInline().AppendChild(new LiteralInline("Headline")),
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SyntaxParagraph()
|
||||
{
|
||||
AssertSyntax("This is a normal paragraph", new ParagraphBlock()
|
||||
{
|
||||
Inline = new ContainerInline()
|
||||
.AppendChild(new LiteralInline("This is a normal paragraph")),
|
||||
});
|
||||
|
||||
AssertSyntax("This is a\nnormal\nparagraph", new ParagraphBlock()
|
||||
{
|
||||
Inline = new ContainerInline()
|
||||
.AppendChild(new LiteralInline("This is a"))
|
||||
.AppendChild(new LineBreakInline())
|
||||
.AppendChild(new LiteralInline("normal"))
|
||||
.AppendChild(new LineBreakInline())
|
||||
.AppendChild(new LiteralInline("paragraph")),
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CodeBlock()
|
||||
{
|
||||
AssertNormalizeNoTrim(" public void HelloWorld();\n {\n }");
|
||||
AssertNormalizeNoTrim(" public void HelloWorld();\n {\n }\n\ntext after two newlines");
|
||||
AssertNormalizeNoTrim("````\npublic void HelloWorld();\n{\n}\n````\n\ntext after two newlines");
|
||||
AssertNormalizeNoTrim("````csharp\npublic void HelloWorld();\n{\n}\n````");
|
||||
AssertNormalizeNoTrim("````csharp hideNewKeyword=true\npublic void HelloWorld();\n{\n}\n````");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Heading()
|
||||
{
|
||||
AssertNormalizeNoTrim("# Heading");
|
||||
AssertNormalizeNoTrim("## Heading");
|
||||
AssertNormalizeNoTrim("### Heading");
|
||||
AssertNormalizeNoTrim("#### Heading");
|
||||
AssertNormalizeNoTrim("##### Heading");
|
||||
AssertNormalizeNoTrim("###### Heading");
|
||||
AssertNormalizeNoTrim("###### Heading\n\ntext after two newlines");
|
||||
AssertNormalizeNoTrim("# Heading\nAnd Text1\n\nAndText2", options: new NormalizeOptions() { EmptyLineAfterHeading = false });
|
||||
|
||||
AssertNormalizeNoTrim("Heading\n=======\n\ntext after two newlines", "# Heading\n\ntext after two newlines");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Backslash()
|
||||
{
|
||||
AssertNormalizeNoTrim("This is a hardline \nAnd this is another hardline\\\nThis is standard newline");
|
||||
AssertNormalizeNoTrim("This is a line\nWith another line\nAnd a last line");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HtmlBlock()
|
||||
{
|
||||
/*AssertNormalizeNoTrim(@"<div id=""foo"" class=""bar
|
||||
baz"">
|
||||
</ div >");*/ // TODO: Bug: Throws Exception during emit
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Paragraph()
|
||||
{
|
||||
AssertNormalizeNoTrim("This is a plain paragraph");
|
||||
AssertNormalizeNoTrim(@"This
|
||||
is
|
||||
a
|
||||
plain
|
||||
paragraph");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParagraphMulti()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"line1
|
||||
|
||||
line2
|
||||
|
||||
line3");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListUnordered()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"- a
|
||||
- b
|
||||
- c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListUnorderedLoose()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"- a
|
||||
|
||||
- b
|
||||
|
||||
- c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListOrderedLooseAndCodeBlock()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"1. ```
|
||||
foo
|
||||
```
|
||||
|
||||
bar");
|
||||
}
|
||||
|
||||
[Test, Ignore("Not sure this is the correct normalize for this one. Need to check the specs")]
|
||||
public void ListUnorderedLooseTop()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"* foo
|
||||
* bar
|
||||
|
||||
baz", options: new NormalizeOptions() { DefaultListItemCharacter = '*' });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListUnorderedLooseMultiParagraph()
|
||||
{
|
||||
AssertNormalizeNoTrim(
|
||||
@"- a
|
||||
|
||||
And another paragraph a
|
||||
|
||||
- b
|
||||
|
||||
And another paragraph b
|
||||
|
||||
- c");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ListOrdered()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"1. a
|
||||
2. b
|
||||
3. c");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ListOrderedAndIntended()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"1. a
|
||||
2. b
|
||||
- foo
|
||||
- bar
|
||||
a) 1234
|
||||
b) 1324
|
||||
3. c
|
||||
4. c
|
||||
5. c
|
||||
6. c
|
||||
7. c
|
||||
8. c
|
||||
9. c
|
||||
10. c
|
||||
- Foo
|
||||
- Bar
|
||||
11. c
|
||||
12. c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HeaderAndParagraph()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"# heading
|
||||
|
||||
paragraph
|
||||
|
||||
paragraph2 without newlines");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void QuoteBlock()
|
||||
{
|
||||
AssertNormalizeNoTrim(@"> test1
|
||||
>
|
||||
> test2");
|
||||
|
||||
AssertNormalizeNoTrim(@"> test1
|
||||
This is a continuation
|
||||
> test2",
|
||||
@"> test1
|
||||
> This is a continuation
|
||||
> test2"
|
||||
);
|
||||
|
||||
AssertNormalizeNoTrim(@"> test1
|
||||
> -foobar
|
||||
|
||||
asdf
|
||||
|
||||
> test2
|
||||
> -foobar sen.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThematicBreak()
|
||||
{
|
||||
AssertNormalizeNoTrim("***\n");
|
||||
|
||||
AssertNormalizeNoTrim("* * *\n", "***\n");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AutolinkInline()
|
||||
{
|
||||
AssertNormalizeNoTrim("This has a <auto.link.com>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CodeInline()
|
||||
{
|
||||
AssertNormalizeNoTrim("This has a `HelloWorld()` in it");
|
||||
AssertNormalizeNoTrim(@"This has a ``Hello`World()`` in it");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmphasisInline()
|
||||
{
|
||||
AssertNormalizeNoTrim("This is a plain **paragraph**");
|
||||
AssertNormalizeNoTrim("This is a plain *paragraph*");
|
||||
AssertNormalizeNoTrim("This is a plain _paragraph_");
|
||||
AssertNormalizeNoTrim("This is a plain __paragraph__");
|
||||
AssertNormalizeNoTrim("This is a pl*ai*n **paragraph**");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LineBreakInline()
|
||||
{
|
||||
AssertNormalizeNoTrim("normal\nline break");
|
||||
AssertNormalizeNoTrim("hard \nline break");
|
||||
AssertNormalizeNoTrim("This is a hardline \nAnd this is another hardline\\\nThis is standard newline");
|
||||
AssertNormalizeNoTrim("This is a line\nWith another line\nAnd a last line");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LinkInline()
|
||||
{
|
||||
AssertNormalizeNoTrim("This is a [link](http://company.com)");
|
||||
AssertNormalizeNoTrim("This is an ");
|
||||
|
||||
AssertNormalizeNoTrim(@"This is a [link](http://company.com ""Crazy Company"")");
|
||||
AssertNormalizeNoTrim(@"This is a [link](http://company.com ""Crazy \"" Company"")");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EscapeInline()
|
||||
{
|
||||
AssertNormalizeNoTrim("This is an escape \\* with another \\[");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HtmlEntityInline()
|
||||
{
|
||||
AssertNormalizeNoTrim("This is a ä blank");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HtmlInline()
|
||||
{
|
||||
AssertNormalizeNoTrim("foo <hr/> bar");
|
||||
AssertNormalizeNoTrim(@"foo <hr foo=""bar""/> bar");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void SpaceBetweenNodes()
|
||||
{
|
||||
AssertNormalizeNoTrim("# Hello World\nFoobar is a better bar.",
|
||||
"# Hello World\n\nFoobar is a better bar.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SpaceBetweenNodesEvenForHeadlines()
|
||||
{
|
||||
AssertNormalizeNoTrim("# Hello World\n## Chapter 1\nFoobar is a better bar.",
|
||||
"# Hello World\n\n## Chapter 1\n\nFoobar is a better bar.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SpaceRemoveAtStartAndEnd()
|
||||
{
|
||||
AssertNormalizeNoTrim("\n\n# Hello World\n## Chapter 1\nFoobar is a better bar.\n\n",
|
||||
"# Hello World\n\n## Chapter 1\n\nFoobar is a better bar.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SpaceShortenBetweenNodes()
|
||||
{
|
||||
AssertNormalizeNoTrim("# Hello World\n\n\n\nFoobar is a better bar.",
|
||||
"# Hello World\n\nFoobar is a better bar.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BiggerSample()
|
||||
{
|
||||
var input = @"# Heading 1
|
||||
|
||||
This is a paragraph
|
||||
|
||||
This is another paragraph
|
||||
|
||||
- This is a list item 1
|
||||
- This is a list item 2
|
||||
- This is a list item 3
|
||||
|
||||
```C#
|
||||
This is a code block
|
||||
```
|
||||
|
||||
> This is a quote block
|
||||
|
||||
This is an indented code block
|
||||
line 2 of indented
|
||||
|
||||
This is a last line";
|
||||
AssertNormalizeNoTrim(input);
|
||||
}
|
||||
|
||||
private static void AssertSyntax(string expected, MarkdownObject syntax)
|
||||
{
|
||||
var writer = new StringWriter();
|
||||
var normalizer = new NormalizeRenderer(writer);
|
||||
var document = new MarkdownDocument();
|
||||
if (syntax is Block)
|
||||
{
|
||||
document.Add(syntax as Block);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
normalizer.Render(document);
|
||||
|
||||
var actual = writer.ToString();
|
||||
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
public void AssertNormalizeNoTrim(string input, string expected = null, NormalizeOptions options = null)
|
||||
=> AssertNormalize(input, expected, false, options);
|
||||
|
||||
public void AssertNormalize(string input, string expected = null, bool trim = true, NormalizeOptions options = null)
|
||||
{
|
||||
expected = expected ?? input;
|
||||
input = NormText(input, trim);
|
||||
expected = NormText(expected, trim);
|
||||
|
||||
var result = Markdown.Normalize(input, options);
|
||||
result = NormText(result, trim);
|
||||
|
||||
Console.WriteLine("```````````````````Source");
|
||||
Console.WriteLine(TestParser.DisplaySpaceAndTabs(input));
|
||||
Console.WriteLine("```````````````````Result");
|
||||
Console.WriteLine(TestParser.DisplaySpaceAndTabs(result));
|
||||
Console.WriteLine("```````````````````Expected");
|
||||
Console.WriteLine(TestParser.DisplaySpaceAndTabs(expected));
|
||||
Console.WriteLine("```````````````````");
|
||||
Console.WriteLine();
|
||||
|
||||
TextAssert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
private static string NormText(string text, bool trim)
|
||||
{
|
||||
if (trim)
|
||||
{
|
||||
text = text.Trim();
|
||||
}
|
||||
return text.Replace("\r\n", "\n").Replace('\r', '\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/Markdig.Tests/TestPlainText.cs
Normal file
17
src/Markdig.Tests/TestPlainText.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestPlainText
|
||||
{
|
||||
[Test]
|
||||
public void TestPlain()
|
||||
{
|
||||
var markdownText = "*Hello*, [world](http://example.com)!";
|
||||
var expected = "Hello, world!";
|
||||
var actual = Markdown.ToPlainText(markdownText);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using System;
|
||||
@@ -86,7 +86,7 @@ namespace Markdig.Tests
|
||||
//output.WriteLine();
|
||||
}
|
||||
|
||||
Assert.True(string.CompareOrdinal(expectedValue, actualValue) == 0, "strings are differing");
|
||||
Assert.AreEqual(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
private static string ToSafeString(this char c)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<Copyright>Alexandre Mutel</Copyright>
|
||||
<AssemblyTitle>Markdig</AssemblyTitle>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.13.4</VersionPrefix>
|
||||
<VersionPrefix>0.14.0</VersionPrefix>
|
||||
<Authors>Alexandre Mutel</Authors>
|
||||
<TargetFrameworks>net35;net40;portable40-net40+sl5+win8+wp8+wpa81;netstandard1.1;uap10.0</TargetFrameworks>
|
||||
<AssemblyName>Markdig</AssemblyName>
|
||||
@@ -13,17 +13,13 @@
|
||||
<PackageId Condition="'$(SignAssembly)' == 'true'">Markdig.Signed</PackageId>
|
||||
<PackageTags>Markdown CommonMark md html md2html</PackageTags>
|
||||
<PackageReleaseNotes>
|
||||
> 0.14.0
|
||||
- Add Markdown.ToPlainText, Add option HtmlRenderer.EnableHtmlForBlock.
|
||||
- Add Markdown.Normalize, to allow to normalize a markdown document. Add NormalizeRenderer, to render a MarkdownDocument back to markdown.
|
||||
-
|
||||
> 0.13.4
|
||||
- Add support for single table header row without a table body rows (#141)
|
||||
- ADd support for `nomnoml` diagrams
|
||||
> 0.13.3
|
||||
- Add support for Pandoc YAML frontmatter (#138)
|
||||
> 0.13.2
|
||||
- Add support for UAP10.0 (#137)
|
||||
> 0.13.1
|
||||
- Fix indenting issue after a double digit list block using a tab (#134)
|
||||
> 0.13.0
|
||||
- Update to latest CommonMark specs 0.28
|
||||
</PackageReleaseNotes>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/lunet-io/markdig/master/img/markdig.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://github.com/lunet-io/markdig</PackageProjectUrl>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using System;
|
||||
@@ -7,6 +7,7 @@ using System.Reflection;
|
||||
using Markdig.Extensions.SelfPipeline;
|
||||
using Markdig.Parsers;
|
||||
using Markdig.Renderers;
|
||||
using Markdig.Renderers.Normalize;
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig
|
||||
@@ -22,6 +23,44 @@ namespace Markdig
|
||||
public static readonly string Version = ((AssemblyFileVersionAttribute) typeof(Markdown).Assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)[0]).Version;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes the specified markdown to a normalized markdown text.
|
||||
/// </summary>
|
||||
/// <param name="markdown">The markdown.</param>
|
||||
/// <param name="options">The normalize options</param>
|
||||
/// <param name="pipeline">The pipeline.</param>
|
||||
/// <returns>A normalized markdown text.</returns>
|
||||
public static string Normalize(string markdown, NormalizeOptions options = null, MarkdownPipeline pipeline = null)
|
||||
{
|
||||
var writer = new StringWriter();
|
||||
Normalize(markdown, writer, options, pipeline);
|
||||
return writer.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes the specified markdown to a normalized markdown text.
|
||||
/// </summary>
|
||||
/// <param name="markdown">The markdown.</param>
|
||||
/// <param name="writer">The destination <see cref="TextWriter"/> that will receive the result of the conversion.</param>
|
||||
/// <param name="options">The normalize options</param>
|
||||
/// <param name="pipeline">The pipeline.</param>
|
||||
/// <returns>A normalized markdown text.</returns>
|
||||
public static MarkdownDocument Normalize(string markdown, TextWriter writer, NormalizeOptions options = null, MarkdownPipeline pipeline = null)
|
||||
{
|
||||
pipeline = pipeline ?? new MarkdownPipelineBuilder().Build();
|
||||
pipeline = CheckForSelfPipeline(pipeline, markdown);
|
||||
|
||||
// We override the renderer with our own writer
|
||||
var renderer = new NormalizeRenderer(writer, options);
|
||||
pipeline.Setup(renderer);
|
||||
|
||||
var document = Parse(markdown, pipeline);
|
||||
renderer.Render(document);
|
||||
writer.Flush();
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Markdown string to HTML.
|
||||
/// </summary>
|
||||
@@ -119,5 +158,50 @@ namespace Markdig
|
||||
}
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Markdown string to Plain text and output to the specified writer.
|
||||
/// </summary>
|
||||
/// <param name="markdown">A Markdown text.</param>
|
||||
/// <param name="writer">The destination <see cref="TextWriter"/> that will receive the result of the conversion.</param>
|
||||
/// <param name="pipeline">The pipeline used for the conversion.</param>
|
||||
/// <returns>The Markdown document that has been parsed</returns>
|
||||
/// <exception cref="System.ArgumentNullException">if reader or writer variable are null</exception>
|
||||
public static MarkdownDocument ToPlainText(string markdown, TextWriter writer, MarkdownPipeline pipeline = null)
|
||||
{
|
||||
if (markdown == null) throw new ArgumentNullException(nameof(markdown));
|
||||
if (writer == null) throw new ArgumentNullException(nameof(writer));
|
||||
pipeline = pipeline ?? new MarkdownPipelineBuilder().Build();
|
||||
pipeline = CheckForSelfPipeline(pipeline, markdown);
|
||||
|
||||
// We override the renderer with our own writer
|
||||
var renderer = new HtmlRenderer(writer)
|
||||
{
|
||||
EnableHtmlForBlock = false,
|
||||
EnableHtmlForInline = false
|
||||
};
|
||||
pipeline.Setup(renderer);
|
||||
|
||||
var document = Parse(markdown, pipeline);
|
||||
renderer.Render(document);
|
||||
writer.Flush();
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Markdown string to HTML.
|
||||
/// </summary>
|
||||
/// <param name="markdown">A Markdown text.</param>
|
||||
/// <param name="pipeline">The pipeline used for the conversion.</param>
|
||||
/// <returns>The result of the conversion</returns>
|
||||
/// <exception cref="System.ArgumentNullException">if markdown variable is null</exception>
|
||||
public static string ToPlainText(string markdown, MarkdownPipeline pipeline = null)
|
||||
{
|
||||
if (markdown == null) throw new ArgumentNullException(nameof(markdown));
|
||||
var writer = new StringWriter();
|
||||
ToPlainText(markdown, writer, pipeline);
|
||||
return writer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,11 @@ namespace Markdig.Parsers.Inlines
|
||||
{
|
||||
processor.Inline = new LiteralInline()
|
||||
{
|
||||
Content = new StringSlice(new string(c, 1)),
|
||||
Content = new StringSlice(slice.Text, slice.Start, slice.Start),
|
||||
Span = { Start = processor.GetSourcePosition(startPosition, out line, out column) },
|
||||
Line = line,
|
||||
Column = column
|
||||
Column = column,
|
||||
IsFirstCharacterEscaped = true,
|
||||
};
|
||||
processor.Inline.Span.End = processor.Inline.Span.Start + 1;
|
||||
slice.NextChar();
|
||||
@@ -44,6 +45,7 @@ namespace Markdig.Parsers.Inlines
|
||||
processor.Inline = new LineBreakInline()
|
||||
{
|
||||
IsHard = true,
|
||||
IsBackslash = true,
|
||||
Span = { Start = processor.GetSourcePosition(startPosition, out line, out column) },
|
||||
Line = line,
|
||||
Column = column
|
||||
|
||||
@@ -88,7 +88,9 @@ namespace Markdig.Parsers
|
||||
processor.NewBlocks.Push(new ThematicBreakBlock(this)
|
||||
{
|
||||
Column = processor.Column,
|
||||
Span = new SourceSpan(startPosition, line.End)
|
||||
Span = new SourceSpan(startPosition, line.End),
|
||||
ThematicChar = breakChar,
|
||||
ThematicCharCount = breakCharCount
|
||||
});
|
||||
return BlockState.BreakDiscard;
|
||||
}
|
||||
|
||||
@@ -42,29 +42,50 @@ namespace Markdig.Renderers.Html
|
||||
|
||||
// We are replacing the HTML attribute `language-mylang` by `mylang` only for a div block
|
||||
// NOTE that we are allocating a closure here
|
||||
renderer.Write("<div")
|
||||
.WriteAttributes(obj.TryGetAttributes(),
|
||||
cls => cls.StartsWith(infoPrefix) ? cls.Substring(infoPrefix.Length) : cls)
|
||||
.Write(">");
|
||||
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("<div")
|
||||
.WriteAttributes(obj.TryGetAttributes(),
|
||||
cls => cls.StartsWith(infoPrefix) ? cls.Substring(infoPrefix.Length) : cls)
|
||||
.Write(">");
|
||||
}
|
||||
|
||||
renderer.WriteLeafRawLines(obj, true, true, true);
|
||||
renderer.WriteLine("</div>");
|
||||
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.WriteLine("</div>");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.Write("<pre");
|
||||
if (OutputAttributesOnPre)
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.WriteAttributes(obj);
|
||||
renderer.Write("<pre");
|
||||
|
||||
if (OutputAttributesOnPre)
|
||||
{
|
||||
renderer.WriteAttributes(obj);
|
||||
}
|
||||
|
||||
renderer.Write("><code");
|
||||
|
||||
if (!OutputAttributesOnPre)
|
||||
{
|
||||
renderer.WriteAttributes(obj);
|
||||
}
|
||||
|
||||
renderer.Write(">");
|
||||
}
|
||||
renderer.Write("><code");
|
||||
if (!OutputAttributesOnPre)
|
||||
{
|
||||
renderer.WriteAttributes(obj);
|
||||
}
|
||||
renderer.Write(">");
|
||||
|
||||
renderer.WriteLeafRawLines(obj, true, true);
|
||||
renderer.WriteLine("</code></pre>");
|
||||
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.WriteLine("</code></pre>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,17 @@ namespace Markdig.Renderers.Html
|
||||
? HeadingTexts[obj.Level - 1]
|
||||
: "<h" + obj.Level.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
renderer.Write("<").Write(headingText).WriteAttributes(obj).Write(">");
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("<").Write(headingText).WriteAttributes(obj).Write(">");
|
||||
}
|
||||
|
||||
renderer.WriteLeafInline(obj);
|
||||
renderer.Write("</").Write(headingText).WriteLine(">");
|
||||
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("</").Write(headingText).WriteLine(">");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,27 +15,31 @@ namespace Markdig.Renderers.Html
|
||||
protected override void Write(HtmlRenderer renderer, ListBlock listBlock)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
if (listBlock.IsOrdered)
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("<ol");
|
||||
if (listBlock.BulletType != '1')
|
||||
if (listBlock.IsOrdered)
|
||||
{
|
||||
renderer.Write(" type=\"").Write(listBlock.BulletType).Write("\"");
|
||||
}
|
||||
renderer.Write("<ol");
|
||||
if (listBlock.BulletType != '1')
|
||||
{
|
||||
renderer.Write(" type=\"").Write(listBlock.BulletType).Write("\"");
|
||||
}
|
||||
|
||||
if (listBlock.OrderedStart != null && (listBlock.OrderedStart != "1"))
|
||||
{
|
||||
renderer.Write(" start=\"").Write(listBlock.OrderedStart).Write("\"");
|
||||
if (listBlock.OrderedStart != null && (listBlock.OrderedStart != "1"))
|
||||
{
|
||||
renderer.Write(" start=\"").Write(listBlock.OrderedStart).Write("\"");
|
||||
}
|
||||
renderer.WriteAttributes(listBlock);
|
||||
renderer.WriteLine(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.Write("<ul");
|
||||
renderer.WriteAttributes(listBlock);
|
||||
renderer.WriteLine(">");
|
||||
}
|
||||
renderer.WriteAttributes(listBlock);
|
||||
renderer.WriteLine(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.Write("<ul");
|
||||
renderer.WriteAttributes(listBlock);
|
||||
renderer.WriteLine(">");
|
||||
}
|
||||
|
||||
foreach (var item in listBlock)
|
||||
{
|
||||
var listItem = (ListItemBlock)item;
|
||||
@@ -43,13 +47,25 @@ namespace Markdig.Renderers.Html
|
||||
renderer.ImplicitParagraph = !listBlock.IsLoose;
|
||||
|
||||
renderer.EnsureLine();
|
||||
renderer.Write("<li").WriteAttributes(listItem).Write(">");
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("<li").WriteAttributes(listItem).Write(">");
|
||||
}
|
||||
|
||||
renderer.WriteChildren(listItem);
|
||||
renderer.WriteLine("</li>");
|
||||
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.WriteLine("</li>");
|
||||
}
|
||||
|
||||
renderer.ImplicitParagraph = previousImplicit;
|
||||
}
|
||||
renderer.WriteLine(listBlock.IsOrdered ? "</ol>" : "</ul>");
|
||||
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.WriteLine(listBlock.IsOrdered ? "</ol>" : "</ul>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,16 +13,17 @@ namespace Markdig.Renderers.Html
|
||||
{
|
||||
protected override void Write(HtmlRenderer renderer, ParagraphBlock obj)
|
||||
{
|
||||
if (!renderer.ImplicitParagraph)
|
||||
if (!renderer.ImplicitParagraph && renderer.EnableHtmlForBlock)
|
||||
{
|
||||
if (!renderer.IsFirstInContainer)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
}
|
||||
|
||||
renderer.Write("<p").WriteAttributes(obj).Write(">");
|
||||
}
|
||||
renderer.WriteLeafInline(obj);
|
||||
if (!renderer.ImplicitParagraph)
|
||||
if (!renderer.ImplicitParagraph && renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.WriteLine("</p>");
|
||||
}
|
||||
|
||||
@@ -14,12 +14,18 @@ namespace Markdig.Renderers.Html
|
||||
protected override void Write(HtmlRenderer renderer, QuoteBlock obj)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
renderer.Write("<blockquote").WriteAttributes(obj).WriteLine(">");
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("<blockquote").WriteAttributes(obj).WriteLine(">");
|
||||
}
|
||||
var savedImplicitParagraph = renderer.ImplicitParagraph;
|
||||
renderer.ImplicitParagraph = false;
|
||||
renderer.WriteChildren(obj);
|
||||
renderer.ImplicitParagraph = savedImplicitParagraph;
|
||||
renderer.WriteLine("</blockquote>");
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.WriteLine("</blockquote>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,10 @@ namespace Markdig.Renderers.Html
|
||||
{
|
||||
protected override void Write(HtmlRenderer renderer, ThematicBreakBlock obj)
|
||||
{
|
||||
renderer.Write("<hr").WriteAttributes(obj).WriteLine(" />");
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("<hr").WriteAttributes(obj).WriteLine(" />");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,18 +45,27 @@ namespace Markdig.Renderers
|
||||
ObjectRenderers.Add(new LinkInlineRenderer());
|
||||
ObjectRenderers.Add(new LiteralInlineRenderer());
|
||||
|
||||
EnableHtmlForBlock = true;
|
||||
EnableHtmlForInline = true;
|
||||
EnableHtmlEscape = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to ouput HTML tags when rendering. See remarks.
|
||||
/// Gets or sets a value indicating whether to output HTML tags when rendering. See remarks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used by some renderers to disable HTML tags when rendering some inlines (for image links).
|
||||
/// This is used by some renderers to disable HTML tags when rendering some inline elements (for image links).
|
||||
/// </remarks>
|
||||
public bool EnableHtmlForInline { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to output HTML tags when rendering. See remarks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used by some renderers to disable HTML tags when rendering some block elements (for image links).
|
||||
/// </remarks>
|
||||
public bool EnableHtmlForBlock { get; set; }
|
||||
|
||||
public bool EnableHtmlEscape { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
55
src/Markdig/Renderers/Normalize/CodeBlockRenderer.cs
Normal file
55
src/Markdig/Renderers/Normalize/CodeBlockRenderer.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using Markdig.Renderers.Html;
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// An Normalize renderer for a <see cref="CodeBlock"/> and <see cref="FencedCodeBlock"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.CodeBlock}" />
|
||||
public class CodeBlockRenderer : NormalizeObjectRenderer<CodeBlock>
|
||||
{
|
||||
public bool OutputAttributesOnPre { get; set; }
|
||||
|
||||
protected override void Write(NormalizeRenderer renderer, CodeBlock obj)
|
||||
{
|
||||
var fencedCodeBlock = obj as FencedCodeBlock;
|
||||
if (fencedCodeBlock != null)
|
||||
{
|
||||
var opening = new string(fencedCodeBlock.FencedChar, fencedCodeBlock.FencedCharCount);
|
||||
renderer.Write(opening);
|
||||
if (fencedCodeBlock.Info != null)
|
||||
{
|
||||
renderer.Write(fencedCodeBlock.Info);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(fencedCodeBlock.Arguments))
|
||||
{
|
||||
renderer.Write(" ").Write(fencedCodeBlock.Arguments);
|
||||
}
|
||||
|
||||
/* TODO do we need this causes a empty space and would render html attributes to markdown.
|
||||
var attributes = obj.TryGetAttributes();
|
||||
if (attributes != null)
|
||||
{
|
||||
renderer.Write(" ");
|
||||
renderer.Write(attributes);
|
||||
}
|
||||
*/
|
||||
renderer.WriteLine();
|
||||
|
||||
renderer.WriteLeafRawLines(obj, true);
|
||||
renderer.Write(opening);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.WriteLeafRawLines(obj, false, true);
|
||||
}
|
||||
|
||||
renderer.FinishBlock(renderer.Options.EmptyLineAfterCodeBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/Markdig/Renderers/Normalize/HeadingRenderer.cs
Normal file
36
src/Markdig/Renderers/Normalize/HeadingRenderer.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using System.Globalization;
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// An Normalize renderer for a <see cref="HeadingBlock"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.HeadingBlock}" />
|
||||
public class HeadingRenderer : NormalizeObjectRenderer<HeadingBlock>
|
||||
{
|
||||
private static readonly string[] HeadingTexts = {
|
||||
"#",
|
||||
"##",
|
||||
"###",
|
||||
"####",
|
||||
"#####",
|
||||
"######",
|
||||
};
|
||||
|
||||
protected override void Write(NormalizeRenderer renderer, HeadingBlock obj)
|
||||
{
|
||||
var headingText = obj.Level > 0 && obj.Level <= 6
|
||||
? HeadingTexts[obj.Level - 1]
|
||||
: new string('#', obj.Level);
|
||||
|
||||
renderer.Write(headingText).Write(' ');
|
||||
renderer.WriteLeafInline(obj);
|
||||
|
||||
renderer.FinishBlock(renderer.Options.EmptyLineAfterHeading);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for an <see cref="AutolinkInline"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.Inlines.AutolinkInline}" />
|
||||
public class AutolinkInlineRenderer : NormalizeObjectRenderer<AutolinkInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, AutolinkInline obj)
|
||||
{
|
||||
renderer.Write('<').Write(obj.Url).Write('>');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="CodeInline"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.Inlines.CodeInline}" />
|
||||
public class CodeInlineRenderer : NormalizeObjectRenderer<CodeInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, CodeInline obj)
|
||||
{
|
||||
var delimiter = obj.Content.Contains(obj.Delimiter + "") ? new string(obj.Delimiter, 2) : obj.Delimiter + "";
|
||||
|
||||
renderer.Write(delimiter);
|
||||
renderer.Write(obj.Content);
|
||||
renderer.Write(delimiter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="DelimiterInline"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.Inlines.DelimiterInline}" />
|
||||
public class DelimiterInlineRenderer : NormalizeObjectRenderer<DelimiterInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, DelimiterInline obj)
|
||||
{
|
||||
renderer.Write(obj.ToLiteral());
|
||||
renderer.WriteChildren(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for an <see cref="EmphasisInline"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.Inlines.EmphasisInline}" />
|
||||
public class EmphasisInlineRenderer : NormalizeObjectRenderer<EmphasisInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, EmphasisInline obj)
|
||||
{
|
||||
var emphasisText = new string(obj.DelimiterChar, obj.IsDouble ? 2 : 1);
|
||||
renderer.Write(emphasisText);
|
||||
renderer.WriteChildren(obj);
|
||||
renderer.Write(emphasisText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="LineBreakInline"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.Inlines.LineBreakInline}" />
|
||||
public class LineBreakInlineRenderer : NormalizeObjectRenderer<LineBreakInline>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to render this softline break as a Normalize hardline break tag (<br />)
|
||||
/// </summary>
|
||||
public bool RenderAsHardlineBreak { get; set; }
|
||||
|
||||
protected override void Write(NormalizeRenderer renderer, LineBreakInline obj)
|
||||
{
|
||||
if (obj.IsHard)
|
||||
{
|
||||
renderer.Write(obj.IsBackslash ? "\\" : " ");
|
||||
}
|
||||
renderer.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="LinkInline"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.Inlines.LinkInline}" />
|
||||
public class LinkInlineRenderer : NormalizeObjectRenderer<LinkInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, LinkInline link)
|
||||
{
|
||||
if (link.IsImage)
|
||||
{
|
||||
renderer.Write('!');
|
||||
}
|
||||
renderer.Write('[');
|
||||
renderer.WriteChildren(link);
|
||||
renderer.Write(']');
|
||||
if (!string.IsNullOrEmpty(link.Url))
|
||||
{
|
||||
renderer.Write('(').Write(link.Url);
|
||||
|
||||
if (!string.IsNullOrEmpty(link.Title))
|
||||
{
|
||||
renderer.Write(" \"");
|
||||
renderer.Write(link.Title.Replace(@"""", @"\"""));
|
||||
renderer.Write("\"");
|
||||
}
|
||||
|
||||
renderer.Write(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using Markdig.Helpers;
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="LiteralInline"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.Inlines.LiteralInline}" />
|
||||
public class LiteralInlineRenderer : NormalizeObjectRenderer<LiteralInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, LiteralInline obj)
|
||||
{
|
||||
if (obj.IsFirstCharacterEscaped && obj.Content.Length > 0 && obj.Content[obj.Content.Start].IsAsciiPunctuation())
|
||||
{
|
||||
renderer.Write('\\');
|
||||
}
|
||||
renderer.Write(ref obj.Content);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="HtmlEntityInline"/>.
|
||||
/// </summary>
|
||||
public class NormalizeHtmlEntityInlineRenderer : NormalizeObjectRenderer<HtmlEntityInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, HtmlEntityInline obj)
|
||||
{
|
||||
renderer.Write(obj.Original);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="HtmlInline"/>.
|
||||
/// </summary>
|
||||
public class NormalizeHtmlInlineRenderer : NormalizeObjectRenderer<HtmlInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, HtmlInline obj)
|
||||
{
|
||||
renderer.Write(obj.Tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
93
src/Markdig/Renderers/Normalize/ListRenderer.cs
Normal file
93
src/Markdig/Renderers/Normalize/ListRenderer.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using System.Globalization;
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="ListBlock"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.ListBlock}" />
|
||||
public class ListRenderer : NormalizeObjectRenderer<ListBlock>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, ListBlock listBlock)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
var compact = renderer.CompactParagraph;
|
||||
renderer.CompactParagraph = !listBlock.IsLoose;
|
||||
if (listBlock.IsOrdered)
|
||||
{
|
||||
int index = 0;
|
||||
if (listBlock.OrderedStart != null)
|
||||
{
|
||||
switch (listBlock.BulletType)
|
||||
{
|
||||
case '1':
|
||||
int.TryParse(listBlock.OrderedStart, out index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < listBlock.Count; i++)
|
||||
{
|
||||
var item = listBlock[i];
|
||||
var listItem = (ListItemBlock) item;
|
||||
renderer.EnsureLine();
|
||||
|
||||
renderer.Write(index.ToString(CultureInfo.InvariantCulture));
|
||||
renderer.Write(listBlock.OrderedDelimiter);
|
||||
renderer.Write(' ');
|
||||
renderer.PushIndent(new string(' ', IntLog10Fast(index) + 3));
|
||||
renderer.WriteChildren(listItem);
|
||||
renderer.PopIndent();
|
||||
switch (listBlock.BulletType)
|
||||
{
|
||||
case '1':
|
||||
index++;
|
||||
break;
|
||||
}
|
||||
if (i + 1 < listBlock.Count && listBlock.IsLoose)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
renderer.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < listBlock.Count; i++)
|
||||
{
|
||||
var item = listBlock[i];
|
||||
var listItem = (ListItemBlock) item;
|
||||
renderer.EnsureLine();
|
||||
renderer.Write(renderer.Options.DefaultListItemCharacter);
|
||||
renderer.Write(' ');
|
||||
renderer.PushIndent(" ");
|
||||
renderer.WriteChildren(listItem);
|
||||
renderer.PopIndent();
|
||||
if (i + 1 < listBlock.Count && listBlock.IsLoose)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
renderer.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
renderer.CompactParagraph = compact;
|
||||
|
||||
renderer.FinishBlock(true);
|
||||
}
|
||||
|
||||
|
||||
private static int IntLog10Fast(int input) =>
|
||||
(input < 10) ? 0 :
|
||||
(input < 100) ? 1 :
|
||||
(input < 1000) ? 2 :
|
||||
(input < 10000) ? 3 :
|
||||
(input < 100000) ? 4 :
|
||||
(input < 1000000) ? 5 :
|
||||
(input < 10000000) ? 6 :
|
||||
(input < 100000000) ? 7 :
|
||||
(input < 1000000000) ? 8 : 9;
|
||||
}
|
||||
}
|
||||
16
src/Markdig/Renderers/Normalize/NormalizeObjectRenderer.cs
Normal file
16
src/Markdig/Renderers/Normalize/NormalizeObjectRenderer.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for Normalize rendering <see cref="Block"/> and <see cref="Markdig.Syntax.Inlines.Inline"/> Markdown objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">The type of the object.</typeparam>
|
||||
/// <seealso cref="Markdig.Renderers.IMarkdownObjectRenderer" />
|
||||
public abstract class NormalizeObjectRenderer<TObject> : MarkdownObjectRenderer<NormalizeRenderer, TObject> where TObject : MarkdownObject
|
||||
{
|
||||
}
|
||||
}
|
||||
48
src/Markdig/Renderers/Normalize/NormalizeOptions.cs
Normal file
48
src/Markdig/Renderers/Normalize/NormalizeOptions.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the options used by <see cref="NormalizeRenderer"/>
|
||||
/// </summary>
|
||||
public class NormalizeOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize a new instance of <see cref="NormalizeOptions"/>
|
||||
/// </summary>
|
||||
public NormalizeOptions()
|
||||
{
|
||||
SpaceAfterQuoteBlock = true;
|
||||
EmptyLineAfterCodeBlock = true;
|
||||
EmptyLineAfterHeading = true;
|
||||
EmptyLineAfterThematicBreak = true;
|
||||
DefaultListItemCharacter = '-';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a space after a QuoteBlock >. Default is <c>true</c>
|
||||
/// </summary>
|
||||
public bool SpaceAfterQuoteBlock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds an empty line after a code block (fenced and tabbed). Default is <c>true</c>
|
||||
/// </summary>
|
||||
public bool EmptyLineAfterCodeBlock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds an empty line after an heading. Default is <c>true</c>
|
||||
/// </summary>
|
||||
public bool EmptyLineAfterHeading { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds an empty line after an thematic break. Default is <c>true</c>
|
||||
/// </summary>
|
||||
public bool EmptyLineAfterThematicBreak { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The bullet character used for list items. Default is <c>-</c>
|
||||
/// </summary>
|
||||
public char DefaultListItemCharacter { get; set; }
|
||||
}
|
||||
}
|
||||
163
src/Markdig/Renderers/Normalize/NormalizeRenderer.cs
Normal file
163
src/Markdig/Renderers/Normalize/NormalizeRenderer.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Markdig.Helpers;
|
||||
using Markdig.Renderers.Html;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Renderers.Normalize.Inlines;
|
||||
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// Default HTML renderer for a Markdown <see cref="MarkdownDocument"/> object.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.TextRendererBase{Markdig.Renderers.Normalize.NormalizeRenderer}" />
|
||||
public class NormalizeRenderer : TextRendererBase<NormalizeRenderer>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NormalizeRenderer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="writer">The writer.</param>
|
||||
/// <param name="options">The normalize options</param>
|
||||
public NormalizeRenderer(TextWriter writer, NormalizeOptions options = null) : base(writer)
|
||||
{
|
||||
Options = options ?? new NormalizeOptions();
|
||||
// Default block renderers
|
||||
ObjectRenderers.Add(new CodeBlockRenderer());
|
||||
ObjectRenderers.Add(new ListRenderer());
|
||||
ObjectRenderers.Add(new HeadingRenderer());
|
||||
ObjectRenderers.Add(new HtmlBlockRenderer());
|
||||
ObjectRenderers.Add(new ParagraphRenderer());
|
||||
ObjectRenderers.Add(new QuoteBlockRenderer());
|
||||
ObjectRenderers.Add(new ThematicBreakRenderer());
|
||||
|
||||
// Default inline renderers
|
||||
ObjectRenderers.Add(new AutolinkInlineRenderer());
|
||||
ObjectRenderers.Add(new CodeInlineRenderer());
|
||||
ObjectRenderers.Add(new DelimiterInlineRenderer());
|
||||
ObjectRenderers.Add(new EmphasisInlineRenderer());
|
||||
ObjectRenderers.Add(new LineBreakInlineRenderer());
|
||||
ObjectRenderers.Add(new NormalizeHtmlInlineRenderer());
|
||||
ObjectRenderers.Add(new NormalizeHtmlEntityInlineRenderer());
|
||||
ObjectRenderers.Add(new LinkInlineRenderer());
|
||||
ObjectRenderers.Add(new LiteralInlineRenderer());
|
||||
}
|
||||
|
||||
public NormalizeOptions Options { get; }
|
||||
|
||||
public bool CompactParagraph { get; set; }
|
||||
|
||||
public void FinishBlock(bool emptyLine)
|
||||
{
|
||||
if (!IsLastInContainer)
|
||||
{
|
||||
WriteLine();
|
||||
if (emptyLine)
|
||||
{
|
||||
WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Writes the attached <see cref="HtmlAttributes"/> on the specified <see cref="MarkdownObject"/>.
|
||||
///// </summary>
|
||||
///// <param name="obj">The object.</param>
|
||||
///// <returns></returns>
|
||||
//public NormalizeRenderer WriteAttributes(MarkdownObject obj)
|
||||
//{
|
||||
// if (obj == null) throw new ArgumentNullException(nameof(obj));
|
||||
// return WriteAttributes(obj.TryGetAttributes());
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// Writes the specified <see cref="HtmlAttributes"/>.
|
||||
///// </summary>
|
||||
///// <param name="attributes">The attributes to render.</param>
|
||||
///// <returns>This instance</returns>
|
||||
//public NormalizeRenderer WriteAttributes(HtmlAttributes attributes)
|
||||
//{
|
||||
// if (attributes == null)
|
||||
// {
|
||||
// return this;
|
||||
// }
|
||||
|
||||
// if (attributes.Id != null)
|
||||
// {
|
||||
// Write(" id=\"").WriteEscape(attributes.Id).Write("\"");
|
||||
// }
|
||||
|
||||
// if (attributes.Classes != null && attributes.Classes.Count > 0)
|
||||
// {
|
||||
// Write(" class=\"");
|
||||
// for (int i = 0; i < attributes.Classes.Count; i++)
|
||||
// {
|
||||
// var cssClass = attributes.Classes[i];
|
||||
// if (i > 0)
|
||||
// {
|
||||
// Write(" ");
|
||||
// }
|
||||
// WriteEscape(cssClass);
|
||||
// }
|
||||
// Write("\"");
|
||||
// }
|
||||
|
||||
// if (attributes.Properties != null && attributes.Properties.Count > 0)
|
||||
// {
|
||||
// foreach (var property in attributes.Properties)
|
||||
// {
|
||||
// Write(" ").Write(property.Key);
|
||||
// if (property.Value != null)
|
||||
// {
|
||||
// Write("=").Write("\"");
|
||||
// WriteEscape(property.Value);
|
||||
// Write("\"");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return this;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the lines of a <see cref="LeafBlock"/>
|
||||
/// </summary>
|
||||
/// <param name="leafBlock">The leaf block.</param>
|
||||
/// <param name="writeEndOfLines">if set to <c>true</c> write end of lines.</param>
|
||||
/// <returns>This instance</returns>
|
||||
public NormalizeRenderer WriteLeafRawLines(LeafBlock leafBlock, bool writeEndOfLines, bool indent = false)
|
||||
{
|
||||
if (leafBlock == null) throw new ArgumentNullException(nameof(leafBlock));
|
||||
if (leafBlock.Lines.Lines != null)
|
||||
{
|
||||
var lines = leafBlock.Lines;
|
||||
var slices = lines.Lines;
|
||||
for (int i = 0; i < lines.Count; i++)
|
||||
{
|
||||
if (!writeEndOfLines && i > 0)
|
||||
{
|
||||
WriteLine();
|
||||
}
|
||||
|
||||
if (indent)
|
||||
{
|
||||
Write(" ");
|
||||
}
|
||||
|
||||
Write(ref slices[i].Slice);
|
||||
|
||||
if (writeEndOfLines)
|
||||
{
|
||||
WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/Markdig/Renderers/Normalize/ParagraphRenderer.cs
Normal file
20
src/Markdig/Renderers/Normalize/ParagraphRenderer.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="ParagraphBlock"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.ParagraphBlock}" />
|
||||
public class ParagraphRenderer : NormalizeObjectRenderer<ParagraphBlock>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, ParagraphBlock obj)
|
||||
{
|
||||
renderer.WriteLeafInline(obj);
|
||||
renderer.FinishBlock(!renderer.CompactParagraph);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/Markdig/Renderers/Normalize/QuoteBlockRenderer.cs
Normal file
24
src/Markdig/Renderers/Normalize/QuoteBlockRenderer.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="QuoteBlock"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.QuoteBlock}" />
|
||||
public class QuoteBlockRenderer : NormalizeObjectRenderer<QuoteBlock>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, QuoteBlock obj)
|
||||
{
|
||||
var quoteIndent = renderer.Options.SpaceAfterQuoteBlock ? obj.QuoteChar + " " : obj.QuoteChar.ToString();
|
||||
renderer.PushIndent(quoteIndent);
|
||||
renderer.WriteChildren(obj);
|
||||
renderer.PopIndent();
|
||||
|
||||
renderer.FinishBlock(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/Markdig/Renderers/Normalize/ThematicBreakRenderer.cs
Normal file
21
src/Markdig/Renderers/Normalize/ThematicBreakRenderer.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig.Renderers.Normalize
|
||||
{
|
||||
/// <summary>
|
||||
/// A Normalize renderer for a <see cref="ThematicBreakBlock"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.Renderers.Normalize.NormalizeObjectRenderer{Markdig.Syntax.ThematicBreakBlock}" />
|
||||
public class ThematicBreakRenderer : NormalizeObjectRenderer<ThematicBreakBlock>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, ThematicBreakBlock obj)
|
||||
{
|
||||
renderer.WriteLine(new string(obj.ThematicChar, obj.ThematicCharCount));
|
||||
|
||||
renderer.FinishBlock(renderer.Options.EmptyLineAfterThematicBreak);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Markdig.Helpers;
|
||||
@@ -70,6 +71,7 @@ namespace Markdig.Renderers
|
||||
{
|
||||
private bool previousWasLine;
|
||||
private char[] buffer;
|
||||
private readonly List<string> indents;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TextRendererBase{T}"/> class.
|
||||
@@ -80,6 +82,7 @@ namespace Markdig.Renderers
|
||||
buffer = new char[1024];
|
||||
// We assume that we are starting as if we had previously a newline
|
||||
previousWasLine = true;
|
||||
indents = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -95,6 +98,31 @@ namespace Markdig.Renderers
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
public void PushIndent(string indent)
|
||||
{
|
||||
if (indent == null) throw new ArgumentNullException(nameof(indent));
|
||||
indents.Add(indent);
|
||||
}
|
||||
|
||||
public void PopIndent()
|
||||
{
|
||||
// TODO: Check
|
||||
indents.RemoveAt(indents.Count - 1);
|
||||
}
|
||||
|
||||
private void WriteIndent()
|
||||
{
|
||||
if (previousWasLine)
|
||||
{
|
||||
previousWasLine = false;
|
||||
for (int i = 0; i < indents.Count; i++)
|
||||
{
|
||||
Writer.Write(indents[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified content.
|
||||
/// </summary>
|
||||
@@ -103,6 +131,7 @@ namespace Markdig.Renderers
|
||||
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
||||
public T Write(string content)
|
||||
{
|
||||
WriteIndent();
|
||||
previousWasLine = false;
|
||||
Writer.Write(content);
|
||||
return (T) this;
|
||||
@@ -142,6 +171,7 @@ namespace Markdig.Renderers
|
||||
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
||||
public T Write(char content)
|
||||
{
|
||||
WriteIndent();
|
||||
previousWasLine = content == '\n';
|
||||
Writer.Write(content);
|
||||
return (T) this;
|
||||
@@ -161,6 +191,7 @@ namespace Markdig.Renderers
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
WriteIndent();
|
||||
previousWasLine = false;
|
||||
if (offset == 0 && content.Length == length)
|
||||
{
|
||||
@@ -189,6 +220,7 @@ namespace Markdig.Renderers
|
||||
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
||||
public T WriteLine()
|
||||
{
|
||||
WriteIndent();
|
||||
Writer.WriteLine();
|
||||
previousWasLine = true;
|
||||
return (T) this;
|
||||
@@ -202,6 +234,7 @@ namespace Markdig.Renderers
|
||||
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
||||
public T WriteLine(string content)
|
||||
{
|
||||
WriteIndent();
|
||||
previousWasLine = true;
|
||||
Writer.WriteLine(content);
|
||||
return (T) this;
|
||||
|
||||
@@ -10,5 +10,7 @@ namespace Markdig.Syntax.Inlines
|
||||
public class LineBreakInline : LeafInline
|
||||
{
|
||||
public bool IsHard { get; set; }
|
||||
|
||||
public bool IsBackslash { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,11 @@ namespace Markdig.Syntax.Inlines
|
||||
/// </summary>
|
||||
public StringSlice Content;
|
||||
|
||||
/// <summary>
|
||||
/// A boolean indicating whether the first character of this literal is escaped by `\`.
|
||||
/// </summary>
|
||||
public bool IsFirstCharacterEscaped { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Content.ToString();
|
||||
|
||||
@@ -17,5 +17,9 @@ namespace Markdig.Syntax
|
||||
public ThematicBreakBlock(BlockParser parser) : base(parser)
|
||||
{
|
||||
}
|
||||
|
||||
public char ThematicChar { get; set; }
|
||||
|
||||
public int ThematicCharCount { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user