Compare commits

...

17 Commits

Author SHA1 Message Date
Alexandre Mutel
b366c1a5e3 Bump to 0.10.0 2016-10-16 21:30:55 +02:00
Alexandre Mutel
a5e53b014f Add better support to discover active extensions when setup renderer (issue #66) 2016-10-16 21:30:38 +02:00
Alexandre Mutel
c2f21e21c8 Bump to 0.9.1 2016-10-11 14:45:03 +02:00
Alexandre Mutel
81b8dce7a8 Fix regression between autolink extension with html inline link a /regular or regular markdown links (issue #65) 2016-10-11 14:44:50 +02:00
Alexandre Mutel
e6223f86d8 Update readme with autolink extension 2016-10-11 13:15:10 +02:00
Alexandre Mutel
2054c16662 Bump to 0.9.0 2016-10-11 13:10:25 +02:00
Alexandre Mutel
95641e562f Add support for the autolink extension (issue #64) 2016-10-11 13:10:06 +02:00
Alexandre Mutel
e4953931c7 Update donation logo 2016-09-29 20:00:08 +02:00
Alexandre Mutel
93b5b7a091 Add donation button 2016-09-29 18:23:30 +02:00
Alexandre Mutel
4f52e893ee Disable warning for comments as it slows down build on appveyor 2016-09-23 14:01:01 +02:00
Alexandre Mutel
23ede077a1 Bump version to 0.8.5 2016-09-23 13:48:15 +02:00
Alexandre Mutel
d5e6f17683 Allow to force table alignment to left (issue #62) 2016-09-23 13:43:49 +02:00
Alexandre Mutel
4d5980a485 Bump version to 0.8.4 2016-09-22 21:48:58 +02:00
Alexandre Mutel
19dd902519 Fix issue when calculating the span of an indented code block within a list. Make sure to include first whitespace on the line 2016-09-22 21:48:15 +02:00
Alexandre Mutel
f046a46275 Bump version to 0.8.3 2016-09-22 16:26:54 +02:00
Alexandre Mutel
25e9eafa8b Allow to pass a manual pipeline to TestParser.TestSpec 2016-09-22 16:25:46 +02:00
Alexandre Mutel
f4ff981008 Fix NullReferenceException with GridTable extension when a single + is entered on a line 2016-09-22 16:25:13 +02:00
51 changed files with 714 additions and 109 deletions

View File

@@ -1,4 +1,4 @@
# Markdig [![Build status](https://ci.appveyor.com/api/projects/status/hk391x8jcskxt1u8?svg=true)](https://ci.appveyor.com/project/xoofx/markdig) [![NuGet](https://img.shields.io/nuget/v/Markdig.svg)](https://www.nuget.org/packages/Markdig/)
# Markdig [![Build status](https://ci.appveyor.com/api/projects/status/hk391x8jcskxt1u8?svg=true)](https://ci.appveyor.com/project/xoofx/markdig) [![NuGet](https://img.shields.io/nuget/v/Markdig.svg)](https://www.nuget.org/packages/Markdig/) [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
<img align="right" width="160px" height="160px" src="img/markdig.png">
@@ -33,6 +33,7 @@ You can **try Markdig online** and compare it to other implementations on [babel
- **Definition lists** (inspired from [PHP Markdown Extra - Definitions Lists](https://michelf.ca/projects/php-markdown/extra/#def-list))
- **Footnotes** (inspired from [PHP Markdown Extra - Footnotes](https://michelf.ca/projects/php-markdown/extra/#footnotes))
- **Auto-identifiers** for headings (similar to [Pandoc - Auto Identifiers](http://pandoc.org/README.html#extension-auto_identifiers))
- **Auto-links** generates links if a text starts with `http://` or `https://` or `ftp://` or `mailto:` or `www.xxx.yyy`
- **Task Lists** inspired from [Github Task lists](https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments).
- **Extra bullet lists**, supporting alpha bullet `a.` `b.` and roman bullet (`i`, `ii`...etc.)
- **Media support** for media url (youtube, vimeo, mp4...etc.) (inspired from this [CommonMark discussion](https://talk.commonmark.org/t/embedded-audio-and-video/441))
@@ -175,6 +176,12 @@ WarmupCount=2 TargetCount=10
TestMarkdownDeep | 7.4076 ms | 0.0617 ms | 318.00 | 186.00 | 84.00 | 2,576,728.69 |
```
## Donate
If you are using this library and find it useful for your project, please consider a donation for it!
[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
## Credits
Thanks to the fantastic work done by [John Mac Farlane](http://johnmacfarlane.net/) for the CommonMark specs and all the people involved in making Markdown a better standard!

View File

@@ -75,6 +75,7 @@
<ItemGroup>
<None Include="App.config" />
<None Include="project.json" />
<None Include="Specs\AutoLinks.md" />
<None Include="Specs\AutoIdentifierSpecs.md" />
<None Include="Specs\AbbreviationSpecs.md" />
<None Include="Specs\FigureFooterAndCiteSpecs.md" />

View File

@@ -0,0 +1,70 @@
# Extensions
This section describes the different extensions supported:
## AutoLinks
Autolinks will format as a HTML link any string that starts by:
- `http://` or `https://`
- `ftp://`
- `mailto:`
- `www.`
```````````````````````````````` example
This is a http://www.google.com URL and https://www.google.com
This is a ftp://test.com
And a mailto:email@toto.com
And a plain www.google.com
.
<p>This is a <a href="http://www.google.com">http://www.google.com</a> URL and <a href="https://www.google.com">https://www.google.com</a>
This is a <a href="ftp://test.com">ftp://test.com</a>
And a <a href="mailto:email@toto.com">mailto:email@toto.com</a>
And a plain <a href="http://www.google.com">www.google.com</a></p>
````````````````````````````````
But incomplete links will not be matched:
```````````````````````````````` example
This is not a http:/www.google.com URL and https:/www.google.com
This is not a ftp:/test.com
And not a mailto:emailtoto.com
And not a plain www. or a www.x
.
<p>This is not a http:/www.google.com URL and https:/www.google.com
This is not a ftp:/test.com
And not a mailto:emailtoto.com
And not a plain www. or a www.x</p>
````````````````````````````````
Previous character must be a punctuation or a valid space (tab, space, new line):
```````````````````````````````` example
This is not a nhttp://www.google.com URL but this is (https://www.google.com)
.
<p>This is not a nhttp://www.google.com URL but this is (<a href="https://www.google.com">https://www.google.com</a>)</p>
````````````````````````````````
An autolink should not interfere with an `<a>` HTML inline:
```````````````````````````````` example
This is an HTML <a href="http://www.google.com">http://www.google.com</a> link
.
<p>This is an HTML <a href="http://www.google.com">http://www.google.com</a> link</p>
````````````````````````````````
or even within emphasis:
```````````````````````````````` example
This is an HTML <a href="http://www.google.com"> **http://www.google.com** </a> link
.
<p>This is an HTML <a href="http://www.google.com"> <strong>http://www.google.com</strong> </a> link</p>
````````````````````````````````
An autolink should not interfere with a markdown link:
```````````````````````````````` example
This is an HTML [http://www.google.com](http://www.google.com) link
.
<p>This is an HTML <a href="http://www.google.com">http://www.google.com</a> link</p>
````````````````````````````````

View File

@@ -272,4 +272,15 @@ A grid table may not have irregularly shaped cells:
+---+---+---+
| DDDDD | E |
+---+---+---+</p>
````````````````````````````````
````````````````````````````````
An empty `+` on a line should result in a simple empty list output:
```````````````````````````````` example
+
.
<ul>
<li></li>
</ul>
````````````````````````````````

View File

@@ -346,7 +346,8 @@ The first row is considered as a **header row** if it is separated from the regu
</table>
````````````````````````````````
The text alignment is defined by default to be left.
The text alignment is defined by default to be center for header and left for cells. If the left alignment is applied, it will force the column heading to be left aligned.
There is no way to define a different alignment for heading and cells (apart from the default).
The text alignment can be changed by using the character `:` with the header column separator:
```````````````````````````````` example
@@ -358,19 +359,19 @@ The text alignment can be changed by using the character `:` with the header col
<table>
<thead>
<tr>
<th>a</th>
<th style="text-align: left;">a</th>
<th style="text-align: center;">b</th>
<th style="text-align: right;">c</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td style="text-align: left;">0</td>
<td style="text-align: center;">1</td>
<td style="text-align: right;">2</td>
</tr>
<tr>
<td>3</td>
<td style="text-align: left;">3</td>
<td style="text-align: center;">4</td>
<td style="text-align: right;">5</td>
</tr>
@@ -514,7 +515,7 @@ Tests trailing spaces after pipes
```````````````````````````````` example
| abc | def |
|---|:---|
|---|---|
| cde| ddd|
| eee| fff|
| fff | fffff |

View File

@@ -16929,7 +16929,8 @@ namespace Markdig.Tests
TestParser.TestSpec(" a | b \n-------|-------\n 0 | 1 \n 2 | 3 ", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n<tr>\n<td>2</td>\n<td>3</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
}
}
// The text alignment is defined by default to be left.
// The text alignment is defined by default to be center for header and left for cells. If the left alignment is applied, it will force the column heading to be left aligned.
// There is no way to define a different alignment for heading and cells (apart from the default).
// The text alignment can be changed by using the character `:` with the header column separator:
[TestFixture]
public partial class TestExtensionsPipeTable
@@ -16950,19 +16951,19 @@ namespace Markdig.Tests
// <table>
// <thead>
// <tr>
// <th>a</th>
// <th style="text-align: left;">a</th>
// <th style="text-align: center;">b</th>
// <th style="text-align: right;">c</th>
// </tr>
// </thead>
// <tbody>
// <tr>
// <td>0</td>
// <td style="text-align: left;">0</td>
// <td style="text-align: center;">1</td>
// <td style="text-align: right;">2</td>
// </tr>
// <tr>
// <td>3</td>
// <td style="text-align: left;">3</td>
// <td style="text-align: center;">4</td>
// <td style="text-align: right;">5</td>
// </tr>
@@ -16970,7 +16971,7 @@ namespace Markdig.Tests
// </table>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 15, "Extensions Pipe Table");
TestParser.TestSpec(" a | b | c \n:------|:-------:| ----:\n 0 | 1 | 2 \n 3 | 4 | 5 ", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th style=\"text-align: center;\">b</th>\n<th style=\"text-align: right;\">c</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: right;\">2</td>\n</tr>\n<tr>\n<td>3</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: right;\">5</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
TestParser.TestSpec(" a | b | c \n:------|:-------:| ----:\n 0 | 1 | 2 \n 3 | 4 | 5 ", "<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">a</th>\n<th style=\"text-align: center;\">b</th>\n<th style=\"text-align: right;\">c</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\">0</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: right;\">2</td>\n</tr>\n<tr>\n<td style=\"text-align: left;\">3</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: right;\">5</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
}
}
// Test alignment with starting and ending pipes:
@@ -17189,7 +17190,7 @@ namespace Markdig.Tests
//
// The following CommonMark:
// | abc | def |
// |---|:---|
// |---|---|
// | cde| ddd|
// | eee| fff|
// | fff | fffff |
@@ -17224,7 +17225,7 @@ namespace Markdig.Tests
// </table>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 22, "Extensions Pipe Table");
TestParser.TestSpec("| abc | def | \n|---|:---|\n| cde| ddd| \n| eee| fff|\n| fff | fffff | \n|gggg | ffff | ", "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>cde</td>\n<td>ddd</td>\n</tr>\n<tr>\n<td>eee</td>\n<td>fff</td>\n</tr>\n<tr>\n<td>fff</td>\n<td>fffff</td>\n</tr>\n<tr>\n<td>gggg</td>\n<td>ffff</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
TestParser.TestSpec("| abc | def | \n|---|---|\n| cde| ddd| \n| eee| fff|\n| fff | fffff | \n|gggg | ffff | ", "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>cde</td>\n<td>ddd</td>\n</tr>\n<tr>\n<td>eee</td>\n<td>fff</td>\n</tr>\n<tr>\n<td>fff</td>\n<td>fffff</td>\n</tr>\n<tr>\n<td>gggg</td>\n<td>ffff</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
}
}
// # Extensions
@@ -17994,6 +17995,28 @@ namespace Markdig.Tests
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 10, "Extensions Grid Table");
TestParser.TestSpec("+---+---+---+\n| AAAAA | B |\n+ A +---+ B +\n| A | C | B |\n+---+---+---+\n| DDDDD | E |\n+---+---+---+", "<p>+---+---+---+\n| AAAAA | B |\n+ A +---+ B +\n| A | C | B |\n+---+---+---+\n| DDDDD | E |\n+---+---+---+</p>", "gridtables|advanced");
}
}
// An empty `+` on a line should result in a simple empty list output:
[TestFixture]
public partial class TestExtensionsGridTable
{
[Test]
public void Example011()
{
// Example 11
// Section: Extensions Grid Table
//
// The following CommonMark:
// +
//
// Should be rendered as:
// <ul>
// <li></li>
// </ul>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 11, "Extensions Grid Table");
TestParser.TestSpec("+", "<ul>\n<li></li>\n</ul>", "gridtables|advanced");
}
}
// # Extensions
//
@@ -20092,4 +20115,147 @@ namespace Markdig.Tests
TestParser.TestSpec("----\nthis: is a frontmatter\n----\nThis is a text", "<hr />\n<h2>this: is a frontmatter</h2>\n<p>This is a text</p>", "yaml");
}
}
// # Extensions
//
// This section describes the different extensions supported:
//
// ## AutoLinks
//
// Autolinks will format as a HTML link any string that starts by:
//
// - `http://` or `https://`
// - `ftp://`
// - `mailto:`
// - `www.`
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example001()
{
// Example 1
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is a http://www.google.com URL and https://www.google.com
// This is a ftp://test.com
// And a mailto:email@toto.com
// And a plain www.google.com
//
// Should be rendered as:
// <p>This is a <a href="http://www.google.com">http://www.google.com</a> URL and <a href="https://www.google.com">https://www.google.com</a>
// This is a <a href="ftp://test.com">ftp://test.com</a>
// And a <a href="mailto:email@toto.com">mailto:email@toto.com</a>
// And a plain <a href="http://www.google.com">www.google.com</a></p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 1, "Extensions AutoLinks");
TestParser.TestSpec("This is a http://www.google.com URL and https://www.google.com\nThis is a ftp://test.com\nAnd a mailto:email@toto.com\nAnd a plain www.google.com", "<p>This is a <a href=\"http://www.google.com\">http://www.google.com</a> URL and <a href=\"https://www.google.com\">https://www.google.com</a>\nThis is a <a href=\"ftp://test.com\">ftp://test.com</a>\nAnd a <a href=\"mailto:email@toto.com\">mailto:email@toto.com</a>\nAnd a plain <a href=\"http://www.google.com\">www.google.com</a></p>", "autolinks|advanced");
}
}
// But incomplete links will not be matched:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example002()
{
// Example 2
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is not a http:/www.google.com URL and https:/www.google.com
// This is not a ftp:/test.com
// And not a mailto:emailtoto.com
// And not a plain www. or a www.x
//
// Should be rendered as:
// <p>This is not a http:/www.google.com URL and https:/www.google.com
// This is not a ftp:/test.com
// And not a mailto:emailtoto.com
// And not a plain www. or a www.x</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 2, "Extensions AutoLinks");
TestParser.TestSpec("This is not a http:/www.google.com URL and https:/www.google.com\nThis is not a ftp:/test.com\nAnd not a mailto:emailtoto.com\nAnd not a plain www. or a www.x ", "<p>This is not a http:/www.google.com URL and https:/www.google.com\nThis is not a ftp:/test.com\nAnd not a mailto:emailtoto.com\nAnd not a plain www. or a www.x</p>", "autolinks|advanced");
}
}
// Previous character must be a punctuation or a valid space (tab, space, new line):
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example003()
{
// Example 3
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is not a nhttp://www.google.com URL but this is (https://www.google.com)
//
// Should be rendered as:
// <p>This is not a nhttp://www.google.com URL but this is (<a href="https://www.google.com">https://www.google.com</a>)</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 3, "Extensions AutoLinks");
TestParser.TestSpec("This is not a nhttp://www.google.com URL but this is (https://www.google.com)", "<p>This is not a nhttp://www.google.com URL but this is (<a href=\"https://www.google.com\">https://www.google.com</a>)</p>", "autolinks|advanced");
}
}
// An autolink should not interfere with an `<a>` HTML inline:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example004()
{
// Example 4
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is an HTML <a href="http://www.google.com">http://www.google.com</a> link
//
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com">http://www.google.com</a> link</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 4, "Extensions AutoLinks");
TestParser.TestSpec("This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link", "<p>This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link</p>", "autolinks|advanced");
}
}
// or even within emphasis:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example005()
{
// Example 5
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is an HTML <a href="http://www.google.com"> **http://www.google.com** </a> link
//
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com"> <strong>http://www.google.com</strong> </a> link</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 5, "Extensions AutoLinks");
TestParser.TestSpec("This is an HTML <a href=\"http://www.google.com\"> **http://www.google.com** </a> link", "<p>This is an HTML <a href=\"http://www.google.com\"> <strong>http://www.google.com</strong> </a> link</p>", "autolinks|advanced");
}
}
// An autolink should not interfere with a markdown link:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example006()
{
// Example 6
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is an HTML [http://www.google.com](http://www.google.com) link
//
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com">http://www.google.com</a> link</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 6, "Extensions AutoLinks");
TestParser.TestSpec("This is an HTML [http://www.google.com](http://www.google.com) link", "<p>This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link</p>", "autolinks|advanced");
}
}
}

View File

@@ -61,6 +61,7 @@ SOFTWARE.
new KeyValuePair<string, string>(Host.ResolvePath("DiagramsSpecs.md"), "diagrams|advanced"),
new KeyValuePair<string, string>(Host.ResolvePath("NoHtmlSpecs.md"), "nohtml"),
new KeyValuePair<string, string>(Host.ResolvePath("YamlSpecs.md"), "yaml"),
new KeyValuePair<string, string>(Host.ResolvePath("AutoLinks.md"), "autolinks|advanced"),
};
var emptyLines = false;
var displayEmptyLines = false;

View File

@@ -15,25 +15,30 @@ namespace Markdig.Tests
foreach (var pipeline in GetPipeline(extensions))
{
Console.WriteLine($"Pipeline configured with extensions: {pipeline.Key}");
// Uncomment this line to get more debug information for process inlines.
//pipeline.DebugLog = Console.Out;
var result = Markdown.ToHtml(inputText, pipeline.Value);
result = Compact(result);
expectedOutputText = Compact(expectedOutputText);
Console.WriteLine("```````````````````Source");
Console.WriteLine(DisplaySpaceAndTabs(inputText));
Console.WriteLine("```````````````````Result");
Console.WriteLine(DisplaySpaceAndTabs(result));
Console.WriteLine("```````````````````Expected");
Console.WriteLine(DisplaySpaceAndTabs(expectedOutputText));
Console.WriteLine("```````````````````");
Console.WriteLine();
TextAssert.AreEqual(expectedOutputText, result);
TestSpec(inputText, expectedOutputText, pipeline.Value);
}
}
public static void TestSpec(string inputText, string expectedOutputText, MarkdownPipeline pipeline)
{
// Uncomment this line to get more debug information for process inlines.
//pipeline.DebugLog = Console.Out;
var result = Markdown.ToHtml(inputText, pipeline);
result = Compact(result);
expectedOutputText = Compact(expectedOutputText);
Console.WriteLine("```````````````````Source");
Console.WriteLine(DisplaySpaceAndTabs(inputText));
Console.WriteLine("```````````````````Result");
Console.WriteLine(DisplaySpaceAndTabs(result));
Console.WriteLine("```````````````````Expected");
Console.WriteLine(DisplaySpaceAndTabs(expectedOutputText));
Console.WriteLine("```````````````````");
Console.WriteLine();
TextAssert.AreEqual(expectedOutputText, result);
}
private static IEnumerable<KeyValuePair<string, MarkdownPipeline>> GetPipeline(string extensionsGroupText)
{
// For the standard case, we make sure that both the CommmonMark core and Extra/Advanced are CommonMark compliant!

View File

@@ -659,6 +659,20 @@ code ( 2, 0) 3-13
");
}
[Test]
public void TestIndentedCodeAfterList()
{
// 0 1 2 3 4 5
// 012345678901234567 8 901234567890123456 789012345678901234 56789
Check("1) Some list item\n\n some code\n more code\n", @"
list ( 0, 0) 0-53
listitem ( 0, 0) 0-53
paragraph ( 0, 3) 3-16
literal ( 0, 3) 3-16
code ( 2, 0) 19-53
");
}
[Test]
public void TestIndentedCodeWithTabs()
{

View File

@@ -17,7 +17,7 @@ namespace Markdig.Extensions.Abbreviations
pipeline.BlockParsers.AddIfNotAlready<AbbreviationParser>();
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null && !htmlRenderer.ObjectRenderers.Contains<HtmlAbbreviationRenderer>())

View File

@@ -59,7 +59,7 @@ namespace Markdig.Extensions.AutoIdentifiers
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}

View File

@@ -0,0 +1,29 @@
// 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;
using Markdig.Syntax.Inlines;
namespace Markdig.Extensions.AutoLinks
{
/// <summary>
/// Extension to automatically create <see cref="LinkInline"/> when a link url http: or mailto: is found.
/// </summary>
/// <seealso cref="Markdig.IMarkdownExtension" />
public class AutoLinkExtension : IMarkdownExtension
{
public void Setup(MarkdownPipelineBuilder pipeline)
{
if (!pipeline.InlineParsers.Contains<AutoLinkParser>())
{
// Insert the parser before any other parsers
pipeline.InlineParsers.Insert(0, new AutoLinkParser());
}
}
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}
}
}

View File

@@ -0,0 +1,197 @@
// 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 Markdig.Helpers;
using Markdig.Parsers;
using Markdig.Syntax.Inlines;
namespace Markdig.Extensions.AutoLinks
{
/// <summary>
/// The inline parser used to for autolinks.
/// </summary>
/// <seealso cref="Markdig.Parsers.InlineParser" />
public class AutoLinkParser : InlineParser
{
/// <summary>
/// Initializes a new instance of the <see cref="AutoLinkParser"/> class.
/// </summary>
public AutoLinkParser()
{
OpeningCharacters = new char[]
{
'h', // for http:// and https://
'f', // for ftp://
'm', // for mailto:
'w', // for www.
};
}
public override bool Match(InlineProcessor processor, ref StringSlice slice)
{
// Previous char must be a whitespace or a punctuation
var previousChar = slice.PeekCharExtra(-1);
if (!previousChar.IsAsciiPunctuation() && !previousChar.IsWhiteSpaceOrZero())
{
return false;
}
// Check that an autolink is possible in the current context
if (!IsAutoLinkValidInCurrentContext(processor))
{
return false;
}
var startPosition = slice.Start;
var c = slice.CurrentChar;
// Precheck URL
switch (c)
{
case 'h':
if (!slice.MatchLowercase("ttp://", 1) && !slice.MatchLowercase("ttps://", 1))
{
return false;
}
break;
case 'f':
if (!slice.MatchLowercase("tp://", 1))
{
return false;
}
break;
case 'm':
if (!slice.MatchLowercase("ailto:", 1))
{
return false;
}
break;
case 'w':
if (!slice.MatchLowercase("ww.", 1) || previousChar == '/') // We won't match http:/www. or /www.xxx
{
return false;
}
break;
}
// Parse URL
string link;
if (!LinkHelper.TryParseUrl(ref slice, out link))
{
return false;
}
// Post-check URL
switch (c)
{
case 'h':
if (string.Equals(link, "http://", StringComparison.OrdinalIgnoreCase) ||
string.Equals(link, "https://", StringComparison.OrdinalIgnoreCase))
{
return false;
}
break;
case 'f':
if (string.Equals(link, "ftp://", StringComparison.OrdinalIgnoreCase))
{
return false;
}
break;
case 'm':
if (string.Equals(link, "mailto:", StringComparison.OrdinalIgnoreCase) || !link.Contains("@"))
{
return false;
}
break;
case 'w':
// We require at least two .
if (link.Length <= "www.x.y".Length || link.IndexOf(".", 4, StringComparison.Ordinal) < 0)
{
return false;
}
break;
}
int line;
int column;
var inline = new LinkInline()
{
Span =
{
Start = processor.GetSourcePosition(startPosition, out line, out column),
},
Line = line,
Column = column,
Url = c == 'w' ? "http://" + link : link,
IsClosed = true,
};
inline.Span.End = inline.Span.Start + link.Length - 1;
inline.UrlSpan = inline.Span;
inline.AppendChild(new LiteralInline()
{
Span = inline.Span,
Line = line,
Column = column,
Content = new StringSlice(slice.Text, startPosition, startPosition + link.Length - 1),
IsClosed = true
});
processor.Inline = inline;
return true;
}
private bool IsAutoLinkValidInCurrentContext(InlineProcessor processor)
{
// Case where there is a pending HtmlInline <a>
var currentInline = processor.Inline;
while (currentInline != null)
{
var htmlInline = currentInline as HtmlInline;
if (htmlInline != null)
{
// If we have a </a> we don't expect nested <a>
if (htmlInline.Tag.StartsWith("</a", StringComparison.OrdinalIgnoreCase))
{
break;
}
// If there is a pending <a>, we can't allow a link
if (htmlInline.Tag.StartsWith("<a", StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
// Check previous sibling and parents in the tree
currentInline = currentInline.PreviousSibling ?? currentInline.Parent;
}
// Check that we don't have any pending brackets opened (where we could have a possible markdown link)
// NOTE: This assume that [ and ] are used for links, otherwise autolink will not work properly
currentInline = processor.Inline;
int countBrackets = 0;
while (currentInline != null)
{
var linkDelimiterInline = currentInline as LinkDelimiterInline;
if (linkDelimiterInline != null && linkDelimiterInline.IsActive)
{
if (linkDelimiterInline.Type == DelimiterType.Open)
{
countBrackets++;
}
else if (linkDelimiterInline.Type == DelimiterType.Close)
{
countBrackets--;
}
}
currentInline = currentInline.Parent;
}
return countBrackets <= 0;
}
}
}

View File

@@ -22,7 +22,7 @@ namespace Markdig.Extensions.Bootstrap
pipeline.DocumentProcessed += PipelineOnDocumentProcessed;
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}

View File

@@ -24,7 +24,7 @@ namespace Markdig.Extensions.Citations
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -38,7 +38,7 @@ namespace Markdig.Extensions.CustomContainers
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -20,7 +20,7 @@ namespace Markdig.Extensions.DefinitionLists
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -17,7 +17,7 @@ namespace Markdig.Extensions.Diagrams
{
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -21,7 +21,7 @@ namespace Markdig.Extensions.Emoji
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}
}

View File

@@ -85,7 +85,7 @@ namespace Markdig.Extensions.EmphasisExtras
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -29,7 +29,7 @@ namespace Markdig.Extensions.Figures
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -29,7 +29,7 @@ namespace Markdig.Extensions.Footers
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -20,7 +20,7 @@ namespace Markdig.Extensions.Footnotes
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -37,7 +37,7 @@ namespace Markdig.Extensions.GenericAttributes
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}

View File

@@ -24,7 +24,7 @@ namespace Markdig.Extensions.Hardlines
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}
}

View File

@@ -22,7 +22,7 @@ namespace Markdig.Extensions.ListExtras
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}
}

View File

@@ -29,7 +29,7 @@ namespace Markdig.Extensions.Mathematics
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -31,7 +31,7 @@ namespace Markdig.Extensions.MediaLinks
{
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -16,7 +16,7 @@ namespace Markdig.Extensions.NoRefLinks
{
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var linkRenderer = renderer.ObjectRenderers.Find<LinkInlineRenderer>();
if (linkRenderer != null)

View File

@@ -15,7 +15,7 @@ namespace Markdig.Extensions.NonAsciiNoEscape
{
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -23,7 +23,7 @@ namespace Markdig.Extensions.PragmaLines
pipeline.DocumentProcessed += PipelineOnDocumentProcessed;
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}

View File

@@ -62,7 +62,7 @@ namespace Markdig.Extensions.SelfPipeline
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}

View File

@@ -35,7 +35,7 @@ namespace Markdig.Extensions.SmartyPants
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -19,7 +19,7 @@ namespace Markdig.Extensions.Tables
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null && !htmlRenderer.ObjectRenderers.Contains<HtmlTableRenderer>())

View File

@@ -27,32 +27,36 @@ namespace Markdig.Extensions.Tables
var line = processor.Line;
GridTableState tableState = null;
// Match the first row that should be of the minimal form: +---------------
var c = line.CurrentChar;
var lineStart = line.Start;
int startPosition = -1;
bool hasLeft = false,
hasRight = false;
while (line.Length > 0)
while (c == '+')
{
if (c == '+')
var columnStart = line.Start;
line.NextChar();
line.TrimStart();
// if we have reached the end of the line, exit
c = line.CurrentChar;
if (c == 0)
{
tableState = tableState ?? new GridTableState { Start = processor.Start, ExpectRow = true };
if (startPosition != -1)
{
hasRight = line.PeekCharAbsolute(line.Start - 1) == ':';
tableState.AddColumn(startPosition - lineStart, line.Start - lineStart, GetAlignment(hasLeft, hasRight));
}
hasLeft = line.PeekChar(1) == ':';
startPosition = line.Start;
break;
}
else if (c != ':' && c != '-')
// Parse a column alignment
TableColumnAlign? columnAlign;
if (!TableHelper.ParseColumnHeader(ref line, '-', out columnAlign))
{
return BlockState.None;
}
c = line.NextChar();
tableState = tableState ?? new GridTableState { Start = processor.Start, ExpectRow = true };
tableState.AddColumn(columnStart - lineStart, line.Start - lineStart, columnAlign);
c = line.CurrentChar;
}
if (tableState == null || tableState.ColumnSlices.Count == (processor.Line.Length - 1))
if (c != 0 || tableState == null)
{
return BlockState.None;
}
@@ -85,13 +89,6 @@ namespace Markdig.Extensions.Tables
return BlockState.ContinueDiscard;
}
private static TableColumnAlign GetAlignment(bool hasLeft, bool hasRight)
{
return hasLeft && hasRight
? TableColumnAlign.Center
: hasRight ? TableColumnAlign.Right : TableColumnAlign.Left;
}
public override BlockState TryContinue(BlockProcessor processor, Block block)
{
var gridTable = (Table)block;

View File

@@ -31,7 +31,7 @@ namespace Markdig.Extensions.Tables
Lines.Add(line);
}
public void AddColumn(int start, int end, TableColumnAlign align)
public void AddColumn(int start, int end, TableColumnAlign? align)
{
if (ColumnSlices == null)
{
@@ -60,7 +60,7 @@ namespace Markdig.Extensions.Tables
public int End { get; set; }
public TableColumnAlign Align { get; set; }
public TableColumnAlign? Align { get; set; }
public int CurrentColumnSpan { get; set; }

View File

@@ -91,14 +91,21 @@ namespace Markdig.Extensions.Tables
? i
: cell.ColumnIndex;
columnIndex = columnIndex >= table.ColumnDefinitions.Count ? table.ColumnDefinitions.Count - 1 : columnIndex;
switch (table.ColumnDefinitions[columnIndex].Alignment)
var alignment = table.ColumnDefinitions[columnIndex].Alignment;
if (alignment.HasValue)
{
case TableColumnAlign.Center:
renderer.Write(" style=\"text-align: center;\"");
break;
case TableColumnAlign.Right:
renderer.Write(" style=\"text-align: right;\"");
break;
switch (alignment)
{
case TableColumnAlign.Center:
renderer.Write(" style=\"text-align: center;\"");
break;
case TableColumnAlign.Right:
renderer.Write(" style=\"text-align: right;\"");
break;
case TableColumnAlign.Left:
renderer.Write(" style=\"text-align: left;\"");
break;
}
}
}
renderer.WriteAttributes(cell);

View File

@@ -41,7 +41,7 @@ namespace Markdig.Extensions.Tables
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null && !htmlRenderer.ObjectRenderers.Contains<HtmlTableRenderer>())

View File

@@ -453,7 +453,7 @@ namespace Markdig.Extensions.Tables
return false;
}
private static bool ParseHeaderString(Inline inline, out TableColumnAlign align)
private static bool ParseHeaderString(Inline inline, out TableColumnAlign? align)
{
align = 0;
var literal = inline as LiteralInline;
@@ -500,7 +500,7 @@ namespace Markdig.Extensions.Tables
}
// Check the left side of a `|` delimiter
TableColumnAlign align = TableColumnAlign.Left;
TableColumnAlign? align = null;
if (delimiter.PreviousSibling != null && !ParseHeaderString(delimiter.PreviousSibling, out align))
{
break;

View File

@@ -17,6 +17,6 @@ namespace Markdig.Extensions.Tables
/// <summary>
/// Gets or sets the column alignment.
/// </summary>
public TableColumnAlign Alignment { get; set; }
public TableColumnAlign? Alignment { get; set; }
}
}

View File

@@ -20,7 +20,7 @@ namespace Markdig.Extensions.Tables
/// <returns>
/// <c>true</c> if parsing was successfull
/// </returns>
public static bool ParseColumnHeader(ref StringSlice slice, char delimiterChar, out TableColumnAlign align)
public static bool ParseColumnHeader(ref StringSlice slice, char delimiterChar, out TableColumnAlign? align)
{
return ParseColumnHeaderDetect(ref slice, ref delimiterChar, out align);
}
@@ -34,7 +34,7 @@ namespace Markdig.Extensions.Tables
/// <returns>
/// <c>true</c> if parsing was successfull
/// </returns>
public static bool ParseColumnHeaderAuto(ref StringSlice slice, out char delimiterChar, out TableColumnAlign align)
public static bool ParseColumnHeaderAuto(ref StringSlice slice, out char delimiterChar, out TableColumnAlign? align)
{
delimiterChar = '\0';
return ParseColumnHeaderDetect(ref slice, ref delimiterChar, out align);
@@ -49,11 +49,10 @@ namespace Markdig.Extensions.Tables
/// <returns>
/// <c>true</c> if parsing was successfull
/// </returns>
public static bool ParseColumnHeaderDetect(ref StringSlice slice, ref char delimiterChar, out TableColumnAlign align)
public static bool ParseColumnHeaderDetect(ref StringSlice slice, ref char delimiterChar, out TableColumnAlign? align)
{
align = TableColumnAlign.Left;
align = null;
// Work on a copy of the slice
slice.TrimStart();
var c = slice.CurrentChar;
bool hasLeft = false;
@@ -87,6 +86,7 @@ namespace Markdig.Extensions.Tables
count++;
}
// We expect at least one `-` delimiter char
if (count == 0)
{
return false;
@@ -104,7 +104,7 @@ namespace Markdig.Extensions.Tables
align = hasLeft && hasRight
? TableColumnAlign.Center
: hasRight ? TableColumnAlign.Right : TableColumnAlign.Left;
: hasRight ? TableColumnAlign.Right : hasLeft ? TableColumnAlign.Left : (TableColumnAlign?) null;
return true;
}

View File

@@ -21,7 +21,7 @@ namespace Markdig.Extensions.TaskLists
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)

View File

@@ -22,7 +22,7 @@ namespace Markdig.Extensions.Yaml
}
}
public void Setup(IMarkdownRenderer renderer)
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
if (!renderer.ObjectRenderers.Contains<YamlFrontMatterRenderer>())
{

View File

@@ -168,6 +168,17 @@ namespace Markdig.Helpers
return i == text.Length;
}
/// <summary>
/// Matches the specified text using lowercase comparison.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="offset">The offset.</param>
/// <returns><c>true</c> if the text matches; <c>false</c> otherwise</returns>
public bool MatchLowercase(string text, int offset = 0)
{
return MatchLowercase(text, End, offset);
}
/// <summary>
/// Matches the specified text using lowercase comparison.
/// </summary>

View File

@@ -20,7 +20,8 @@ namespace Markdig
/// <summary>
/// Setups this extension for the specified renderer.
/// </summary>
/// <param name="pipeline">The pipeline used to parse the document.</param>
/// <param name="renderer">The renderer.</param>
void Setup(IMarkdownRenderer renderer);
void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer);
}
}

View File

@@ -5,6 +5,7 @@
using System;
using Markdig.Extensions.Abbreviations;
using Markdig.Extensions.AutoIdentifiers;
using Markdig.Extensions.AutoLinks;
using Markdig.Extensions.Bootstrap;
using Markdig.Extensions.Citations;
using Markdig.Extensions.CustomContainers;
@@ -62,9 +63,22 @@ namespace Markdig
.UseListExtras()
.UseTaskLists()
.UseDiagrams()
.UseAutoLinks()
.UseGenericAttributes(); // Must be last as it is one parser that is modifying other parsers
}
/// <summary>
/// Uses this extension to enable autolinks from text `http://`, `https://`, `ftp://`, `mailto:`, `www.xxx.yyy`
/// </summary>
/// <param name="pipeline">The pipeline.</param>
/// <returns>The modified pipeline</returns>
public static MarkdownPipelineBuilder UseAutoLinks(this MarkdownPipelineBuilder pipeline)
{
pipeline.Extensions.AddIfNotAlready<AutoLinkExtension>();
return pipeline;
}
/// <summary>
/// Uses this extension to disable URI escape with % characters for non-US-ASCII characters in order to workaround a bug under IE/Edge with local file links containing non US-ASCII chars. DO NOT USE OTHERWISE.
/// </summary>
@@ -522,6 +536,9 @@ namespace Markdig
case "nonascii-noescape":
pipeline.UseNonAsciiNoEscape();
break;
case "autolinks":
pipeline.UseAutoLinks();
break;
default:
throw new ArgumentException($"Invalid extension `{extension}` from `{extensions}`", nameof(extensions));
}

View File

@@ -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.ObjectModel;
using System.IO;
using Markdig.Helpers;
using Markdig.Parsers;
@@ -34,7 +35,10 @@ namespace Markdig
internal bool PreciseSourceLocation { get; set; }
internal OrderedList<IMarkdownExtension> Extensions { get; }
/// <summary>
/// The read-only list of extensions used to build this pipeline.
/// </summary>
public OrderedList<IMarkdownExtension> Extensions { get; }
internal BlockParserList BlockParsers { get; }
@@ -56,7 +60,7 @@ namespace Markdig
if (renderer == null) throw new ArgumentNullException(nameof(renderer));
foreach (var extension in Extensions)
{
extension.Setup(renderer);
extension.Setup(this, renderer);
}
}
}

View File

@@ -304,6 +304,64 @@ namespace Markdig.Parsers
}
}
/// <summary>
/// Unwind any previous indent from the current character back to the first space.
/// </summary>
public void UnwindAllIndents()
{
// Find the previous first space on the current line
var previousStart = Line.Start;
for (; Line.Start > originalLineStart; Line.Start--)
{
var c = Line.PeekCharAbsolute(Line.Start - 1);
if (c == 0)
{
break;
}
if (!c.IsSpaceOrTab())
{
break;
}
}
var targetStart = Line.Start;
// Nothing changed? Early exit
if (previousStart == targetStart)
{
return;
}
// TODO: factorize the following code with what is done with GoToColumn
// If we have found the first space, we need to recalculate the correct column
Line.Start = originalLineStart;
Column = 0;
ColumnBeforeIndent = 0;
StartBeforeIndent = originalLineStart;
for (; Line.Start < targetStart; Line.Start++)
{
var c = Line.Text[Line.Start];
if (c == '\t')
{
Column = CharHelper.AddTab(Column);
}
else
{
if (!c.IsSpaceOrTab())
{
ColumnBeforeIndent = Column + 1;
StartBeforeIndent = Line.Start + 1;
}
Column++;
}
}
// Reset the indent
ColumnBeforeIndent = Column;
StartBeforeIndent = Start;
}
/// <summary>
/// Moves to the position to the code indent (<see cref="ColumnBeforeIndent"/> + 4 spaces).
/// </summary>

View File

@@ -18,16 +18,23 @@ namespace Markdig.Parsers
public override BlockState TryOpen(BlockProcessor processor)
{
var startColumn = processor.ColumnBeforeIndent;
var startPosition = processor.StartBeforeIndent;
var result = TryContinue(processor, null);
if (result == BlockState.Continue)
{
// Save the column where we need to go back
var column = processor.Column;
// Unwind all indents all spaces before in order to calculate correct span
processor.UnwindAllIndents();
processor.NewBlocks.Push(new CodeBlock(this)
{
Column = startColumn,
Span = new SourceSpan(startPosition, processor.Line.End)
Column = processor.Column,
Span = new SourceSpan(processor.Start, processor.Line.End)
});
// Go back to the correct column
processor.GoToColumn(column);
}
return result;
}

View File

@@ -25,6 +25,6 @@ namespace Markdig
{
public static partial class Markdown
{
public const string Version = "0.8.2";
public const string Version = "0.10.0";
}
}

View File

@@ -1,6 +1,6 @@
{
"title": "Markdig",
"version": "0.8.2",
"version": "0.10.0",
"authors": [ "Alexandre Mutel" ],
"description": "A fast, powerfull, CommonMark compliant, extensible Markdown processor for .NET with 20+ builtin extensions (pipetables, footnotes, definition lists... etc.)",
"copyright": "Alexandre Mutel",
@@ -11,7 +11,7 @@
"projectUrl": "https://github.com/lunet-io/markdig",
"iconUrl": "https://raw.githubusercontent.com/lunet-io/markdig/master/img/markdig.png",
"requireLicenseAcceptance": false,
"releaseNotes": "> 0.8.2\n- fix potential cast exception with Abreviation extension and empty literals\n> 0.8.1\n- new extension to disable URI escaping for non-US-ASCII characters to workaround a bug in Edge/IE\n- Fix an issue with abbreviations with left/right multiple non-punctuation/space characters\n> 0.8.0\n- Update to latest CommonMark specs\n- Fix empty literal\n- Add YAML frontmatter extension\n",
"releaseNotes": "> 0.10.0\n- Breaking change of the IMarkdownExtension to allow to receive the MarkdownPipeline for the renderers setup\n",
"tags": [ "Markdown CommonMark md html md2html" ]
},
"configurations": {
@@ -26,7 +26,8 @@
"define": [ "RELEASE", "TRACE" ],
"optimize": true,
"allowUnsafe": true,
"xmlDoc": true
"xmlDoc": true,
"nowarn": [ "CS1591" ]
}
}
},