Compare commits

...

27 Commits

Author SHA1 Message Date
Alexandre Mutel
1df8344576 Bump to 0.10.4 2016-12-12 11:03:48 +01:00
Alexandre Mutel
9eb84cf95e Normalize pipe tables so they contain the same number of columns for all rows 2016-12-11 19:01:49 +01:00
Alexandre Mutel
47d45b5577 Fix issue when parsing autolinks embraced by a pending emphasis (issue #78) 2016-12-11 18:08:51 +01:00
Alexandre Mutel
ebcc286df0 Bump version to 0.10.3 2016-11-29 18:02:39 +01:00
Alexandre Mutel
f11d8037ac Fix issue when the last character of a table is not a newline and there are spaces in-between (issue #73) 2016-11-29 17:43:28 +01:00
Alexandre Mutel
f668b3fe38 Bump version to 0.10.2 2016-11-26 11:20:49 +01:00
Alexandre Mutel
5ca4e31332 Fix exception when trying to Urilize an url with an unicode character outside the supported range by string.Normalize + NormD (issue #75) 2016-11-26 11:20:37 +01:00
Alexandre Mutel
a8fbe79e30 Bump to 0.10.1 2016-11-19 16:53:56 +01:00
Alexandre Mutel
bdb09b9820 Update to latest CommonMark specs 0.27 2016-11-19 16:53:44 +01:00
Alexandre Mutel
79348ebea8 Add span to LinkReferenceDefinition (issue #51) 2016-10-27 17:06:37 +02:00
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
61 changed files with 2485 additions and 163 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">
@@ -14,7 +14,7 @@ You can **try Markdig online** and compare it to other implementations on [babel
- **Abstract Syntax Tree** with precise source code location for syntax tree, useful when building a Markdown editor.
- Checkout [MarkdownEditor for Visual Studio](https://visualstudiogallery.msdn.microsoft.com/eaab33c3-437b-4918-8354-872dfe5d1bfe) powered by Markdig!
- Converter to **HTML**
- Passing more than **600+ tests** from the latest [CommonMark specs](http://spec.commonmark.org/)
- Passing more than **600+ tests** from the latest [CommonMark specs (0.27)](http://spec.commonmark.org/)
- Includes all the core elements of CommonMark:
- including **GFM fenced code blocks**.
- **Extensible** architecture
@@ -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,78 @@
# 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>
````````````````````````````````
A link embraced by pending emphasis should let the emphasis takes precedence if characters are placed at the end of the matched link:
```````````````````````````````` example
Check **http://www.a.com** or __http://www.b.com__
.
<p>Check <strong><a href="http://www.a.com">http://www.a.com</a></strong> or <strong><a href="http://www.b.com">http://www.b.com</a></strong></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

@@ -136,6 +136,7 @@ a | b
<tr>
<th>a</th>
<th>b</th>
<th></th>
</tr>
</thead>
<tbody>
@@ -147,9 +148,12 @@ a | b
<tr>
<td>3</td>
<td>4</td>
<td></td>
</tr>
<tr>
<td>5</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
@@ -346,7 +350,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 +363,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 +519,7 @@ Tests trailing spaces after pipes
```````````````````````````````` example
| abc | def |
|---|:---|
|---|---|
| cde| ddd|
| eee| fff|
| fff | fffff |
@@ -547,3 +552,31 @@ Tests trailing spaces after pipes
</tbody>
</table>
````````````````````````````````
** Normalized columns count **
The tables are normalized to the maximum number of columns found in a table
```````````````````````````````` example
a | b
-- | -
0 | 1 | 2
.
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
````````````````````````````````

View File

@@ -6,8 +6,8 @@ namespace Markdig.Tests
// ---
// title: CommonMark Spec
// author: John MacFarlane
// version: 0.26
// date: '2016-07-15'
// version: 0.27
// date: '2016-11-18'
// license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
// ...
//
@@ -6036,11 +6036,11 @@ namespace Markdig.Tests
// If the list item is ordered, then it is also assigned a start
// number, based on the ordered list marker.
//
// Exceptions: When the list item interrupts a paragraph---that
// is, when it starts on a line that would otherwise count as
// [paragraph continuation text]---then (a) the lines *Ls* must
// not begin with a blank line, and (b) if the list item is
// ordered, the start number must be 1.
// Exceptions: When the first list item in a [list] interrupts
// a paragraph---that is, when it starts on a line that would
// otherwise count as [paragraph continuation text]---then (a)
// the lines *Ls* must not begin with a blank line, and (b) if
// the list item is ordered, the start number must be 1.
//
// For example, let *Ls* be the lines
[TestFixture]
@@ -16633,6 +16633,7 @@ namespace Markdig.Tests
// <tr>
// <th>a</th>
// <th>b</th>
// <th></th>
// </tr>
// </thead>
// <tbody>
@@ -16644,15 +16645,18 @@ namespace Markdig.Tests
// <tr>
// <td>3</td>
// <td>4</td>
// <td></td>
// </tr>
// <tr>
// <td>5</td>
// <td></td>
// <td></td>
// </tr>
// </tbody>
// </table>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 7, "Extensions Pipe Table");
TestParser.TestSpec("a | b \n-- | --\n0 | 1 | 2\n3 | 4\n5 |", "<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<td>2</td>\n</tr>\n<tr>\n<td>3</td>\n<td>4</td>\n</tr>\n<tr>\n<td>5</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
TestParser.TestSpec("a | b \n-- | --\n0 | 1 | 2\n3 | 4\n5 |", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n</tr>\n<tr>\n<td>3</td>\n<td>4</td>\n<td></td>\n</tr>\n<tr>\n<td>5</td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
}
}
// **Rule #2**
@@ -16929,7 +16933,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 +16955,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 +16975,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 +17194,7 @@ namespace Markdig.Tests
//
// The following CommonMark:
// | abc | def |
// |---|:---|
// |---|---|
// | cde| ddd|
// | eee| fff|
// | fff | fffff |
@@ -17224,7 +17229,46 @@ 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");
}
}
// ** Normalized columns count **
//
// The tables are normalized to the maximum number of columns found in a table
[TestFixture]
public partial class TestExtensionsPipeTable
{
[Test]
public void Example023()
{
// Example 23
// Section: Extensions Pipe Table
//
// The following CommonMark:
// a | b
// -- | -
// 0 | 1 | 2
//
// Should be rendered as:
// <table>
// <thead>
// <tr>
// <th>a</th>
// <th>b</th>
// <th></th>
// </tr>
// </thead>
// <tbody>
// <tr>
// <td>0</td>
// <td>1</td>
// <td>2</td>
// </tr>
// </tbody>
// </table>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 23, "Extensions Pipe Table");
TestParser.TestSpec("a | b\n-- | - \n0 | 1 | 2", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
}
}
// # Extensions
@@ -17994,6 +18038,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 +20158,167 @@ 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");
}
}
// A link embraced by pending emphasis should let the emphasis takes precedence if characters are placed at the end of the matched link:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example007()
{
// Example 7
// Section: Extensions AutoLinks
//
// The following CommonMark:
// Check **http://www.a.com** or __http://www.b.com__
//
// Should be rendered as:
// <p>Check <strong><a href="http://www.a.com">http://www.a.com</a></strong> or <strong><a href="http://www.b.com">http://www.b.com</a></strong></p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 7, "Extensions AutoLinks");
TestParser.TestSpec("Check **http://www.a.com** or __http://www.b.com__", "<p>Check <strong><a href=\"http://www.a.com\">http://www.a.com</a></strong> or <strong><a href=\"http://www.b.com\">http://www.b.com</a></strong></p>", "autolinks|advanced");
}
}
}

View File

@@ -38,8 +38,7 @@ SOFTWARE.
<#@ import namespace="System.CodeDom.Compiler" #>
<#@ output extension=".cs" #><#
var specFiles = new KeyValuePair<string, string>[] {
// new KeyValuePair<string, string>("https://raw.githubusercontent.com/jgm/CommonMark/master/spec.txt", string.Empty),
new KeyValuePair<string, string>("https://raw.githubusercontent.com/jgm/CommonMark/cfc84164475d3bec8be9482c21a705adc93a54f5/spec.txt", string.Empty), // 0.26 specs
new KeyValuePair<string, string>("https://raw.githubusercontent.com/jgm/CommonMark/791b1c121f16d3d7e80837c6f52917e57bbb2f61/spec.txt", string.Empty), // 0.27
new KeyValuePair<string, string>(Host.ResolvePath("PipeTableSpecs.md"), "pipetables|advanced"),
new KeyValuePair<string, string>(Host.ResolvePath("FootnotesSpecs.md"), "footnotes|advanced"),
new KeyValuePair<string, string>(Host.ResolvePath("GenericAttributesSpecs.md"), "attributes|advanced"),
@@ -61,6 +60,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

@@ -390,6 +390,7 @@ namespace Markdig.Tests
[TestCase("b>r", "br")]
[TestCase(@"b\r", "br")]
[TestCase(@"b""r", "br")]
[TestCase(@"Requirement 😀", "requirement")]
public void TestUrilizeNonAscii_NonValidCharactersForFragments(string input, string expectedResult)
{
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, 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

@@ -118,7 +118,7 @@ blabla
[Test]
public void TestBugAdvancaed()
public void TestBugAdvanced()
{
TestParser.TestSpec(@"`https://{domain}/callbacks`
#### HEADING
@@ -126,6 +126,30 @@ Paragraph
", "<p><code>https://{domain}/callbacks</code></p>\n<h4 id=\"heading\">HEADING</h4>\n<p>Paragraph</p>", "advanced");
}
[Test]
public void TestBugPipeTables()
{
// https://github.com/lunet-io/markdig/issues/73
TestParser.TestSpec(@"| abc | def |
| --- | --- |
| 1 | ~3 |
", @"<table>
<thead>
<tr>
<th>abc</th>
<th>def</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>~3</td>
</tr>
</tbody>
</table>", "advanced");
}
[Test]
public void TestSamePipelineAllExtensions()
{

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,239 @@
// 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.Collections.Generic;
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;
}
List<char> pendingEmphasis;
// Check that an autolink is possible in the current context
if (!IsAutoLinkValidInCurrentContext(processor, out pendingEmphasis))
{
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;
}
// If we have any pending emphasis, remove any pending emphasis characters from the end of the link
if (pendingEmphasis != null)
{
for (int i = link.Length - 1; i >= 0; i--)
{
if (pendingEmphasis.Contains(link[i]))
{
slice.Start--;
}
else
{
if (i < link.Length - 1)
{
link = link.Substring(0, i + 1);
}
break;
}
}
}
// 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, out List<char> pendingEmphasis)
{
pendingEmphasis = null;
// 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--;
}
}
else
{
// Record all pending characters for emphasis
var emphasisDelimiter = currentInline as EmphasisDelimiterInline;
if (emphasisDelimiter != null)
{
if (pendingEmphasis == null)
{
// Not optimized for GC, but we don't expect this case much
pendingEmphasis = new List<char>();
}
if (!pendingEmphasis.Contains(emphasisDelimiter.DelimiterChar))
{
pendingEmphasis.Add(emphasisDelimiter.DelimiterChar);
}
}
}
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

@@ -274,7 +274,16 @@ namespace Markdig.Extensions.Tables
}
var endOfTable = new LineBreakInline();
lastElement.InsertAfter(endOfTable);
// If the last element is a container, we have to add the EOL to its child
// otherwise only next sibling
if (lastElement is ContainerInline)
{
((ContainerInline)lastElement).AppendChild(endOfTable);
}
else
{
lastElement.InsertAfter(endOfTable);
}
delimiters.Add(endOfTable);
tableState.EndOfLines.Add(endOfTable);
}
@@ -449,11 +458,14 @@ namespace Markdig.Extensions.Tables
// Clear cells when we are done
cells.Clear();
// Normalize the table
table.Normalize();
// We don't want to continue procesing delimiters, as we are already processing them here
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 +512,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

@@ -69,5 +69,33 @@ namespace Markdig.Extensions.Tables
}
return true;
}
/// <summary>
/// Normalizes the number of columns of this table by taking the maximum columns and appending empty cells.
/// </summary>
public void Normalize()
{
var maxColumn = 0;
for (int i = 0; i < this.Count; i++)
{
var row = this[i] as TableRow;
if (row != null && row.Count > maxColumn)
{
maxColumn = row.Count;
}
}
for (int i = 0; i < this.Count; i++)
{
var row = this[i] as TableRow;
if (row != null)
{
for (int j = row.Count; j < maxColumn; j++)
{
row.Add(new TableCell());
}
}
}
}
}
}

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>())
{

File diff suppressed because it is too large Load Diff

View File

@@ -20,60 +20,59 @@ namespace Markdig.Helpers
public static string Urilize(string headingText, bool allowOnlyAscii)
{
#if SUPPORT_NORMALIZE
// Normalzie the string if we don't allow UTF8
if (allowOnlyAscii)
{
headingText = headingText.Normalize(NormalizationForm.FormD);
}
#endif
var headingBuffer = StringBuilderCache.Local();
bool hasLetter = false;
bool previousIsSpace = false;
for (int i = 0; i < headingText.Length; i++)
{
var c = headingText[i];
if (char.IsLetter(c))
var normalized = allowOnlyAscii ? CharNormalizer.ConvertToAscii(c) : null;
for (int j = 0; j < (normalized?.Length ?? 1); j++)
{
#if SUPPORT_NORMALIZE
if (allowOnlyAscii && (c < ' ' || c >= 127))
if (normalized != null)
{
continue;
c = normalized[j];
}
#endif
c = char.IsUpper(c) ? char.ToLowerInvariant(c) : c;
headingBuffer.Append(c);
hasLetter = true;
previousIsSpace = false;
}
else if (hasLetter)
{
if (IsReservedPunctuation(c))
if (char.IsLetter(c))
{
if (previousIsSpace)
if (allowOnlyAscii && (c < ' ' || c >= 127))
{
headingBuffer.Length--;
continue;
}
if (headingBuffer[headingBuffer.Length - 1] != c)
c = char.IsUpper(c) ? char.ToLowerInvariant(c) : c;
headingBuffer.Append(c);
hasLetter = true;
previousIsSpace = false;
}
else if (hasLetter)
{
if (IsReservedPunctuation(c))
{
if (previousIsSpace)
{
headingBuffer.Length--;
}
if (headingBuffer[headingBuffer.Length - 1] != c)
{
headingBuffer.Append(c);
}
previousIsSpace = false;
}
else if (c.IsDigit())
{
headingBuffer.Append(c);
previousIsSpace = false;
}
previousIsSpace = false;
}
else if (c.IsDigit())
{
headingBuffer.Append(c);
previousIsSpace = false;
}
else if (!previousIsSpace && c.IsWhitespace())
{
var pc = headingBuffer[headingBuffer.Length - 1];
if (!IsReservedPunctuation(pc))
else if (!previousIsSpace && c.IsWhitespace())
{
headingBuffer.Append('-');
var pc = headingBuffer[headingBuffer.Length - 1];
if (!IsReservedPunctuation(pc))
{
headingBuffer.Append('-');
}
previousIsSpace = true;
}
previousIsSpace = true;
}
}
}

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.4";
}
}

View File

@@ -99,6 +99,8 @@ namespace Markdig.Syntax
SourceSpan urlSpan;
SourceSpan titleSpan;
var startSpan = text.Start;
if (!LinkHelper.TryParseLinkReferenceDefinition(ref text, out label, out url, out title, out labelSpan, out urlSpan, out titleSpan))
{
return false;
@@ -108,7 +110,8 @@ namespace Markdig.Syntax
{
LabelSpan = labelSpan,
UrlSpan = urlSpan,
TitleSpan = titleSpan
TitleSpan = titleSpan,
Span = new SourceSpan(startSpan, titleSpan.End > 0 ? titleSpan.End: urlSpan.End)
};
return true;
}

View File

@@ -1,6 +1,6 @@
{
"title": "Markdig",
"version": "0.8.2",
"version": "0.10.4",
"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.4\n - Fix issue with autolinks\n - Normalize number of columns for tables\n> 0.10.3\n - Fix issue with pipetables shifting a cell to a new column (issue #73)\n> 0.10.2\n - Fix exception when trying to urlize an url with an unicode character outside the supported range by NormD (issue #75)\n > 0.10.1\n- Update to latest CommonMark specs\n- Fix source span for LinkReferenceDefinition\n> 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,14 +26,15 @@
"define": [ "RELEASE", "TRACE" ],
"optimize": true,
"allowUnsafe": true,
"xmlDoc": true
"xmlDoc": true,
"nowarn": [ "CS1591" ]
}
}
},
"frameworks": {
"net35": {
"buildOptions": {
"define": [ "SUPPORT_NORMALIZE", "SUPPORT_FIXED_STRING" ]
"define": [ "SUPPORT_FIXED_STRING" ]
},
"frameworkAssemblies": {
"mscorlib": "",
@@ -43,7 +44,7 @@
},
"net40": {
"buildOptions": {
"define": [ "SUPPORT_NORMALIZE", "SUPPORT_FIXED_STRING" ]
"define": [ "SUPPORT_FIXED_STRING" ]
},
"frameworkAssemblies": {
"mscorlib": "",

View File

@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
namespace UnicodeNormDApp
{
class Program
{
static void Main(string[] args)
{
var httpClient = new WebClient();
var data = httpClient.DownloadString("http://www.unicode.org/Public/UCD/latest/ucd/NormalizationTest.txt");
var stringReader = new StringReader(data);
var sep = new char[] {';'};
var spaceSpec = new char[] {' '};
string line;
int count = 0;
int min = int.MaxValue;
int max = int.MinValue;
var values = new Dictionary<char, string>();
var builder = new StringBuilder();
while ((line = stringReader.ReadLine()) != null)
{
if (line.StartsWith("#") || line.StartsWith("@"))
{
continue;
}
var commentIndex = line.IndexOf('#');
var dataLine = commentIndex > 0 ? line.Substring(0, commentIndex) : line;
var columns = dataLine.Split(sep, StringSplitOptions.RemoveEmptyEntries);
if (columns.Length < 4)
{
continue;
}
// Skip multi code point
if (columns[0].IndexOf(' ') > 0)
{
continue;
}
var source = Convert.ToInt32(columns[0], 16);
if (source < min)
{
min = source;
}
if (source > max)
{
max = source;
}
var column4Space = columns[4].Split(spaceSpec, StringSplitOptions.RemoveEmptyEntries);
builder.Clear();
for (int i = 0; i < column4Space.Length; i++)
{
var nfdFirst = Convert.ToInt32(column4Space[i], 16);
// We support only single char codepoints
string unicodeString = char.ConvertFromUtf32(nfdFirst);
// We restrict to ascii only
if (unicodeString.Length == 1 && nfdFirst > 32 && nfdFirst < 127)
{
builder.Append(unicodeString[0]);
}
}
var str = builder.ToString();
var sourceString = char.ConvertFromUtf32(source);
// We don't keep spaces
if (sourceString.Length == 1 && str.Length > 0 && !values.ContainsKey(sourceString[0]))
{
//Trace.WriteLine(columns[0] + "/" + source + ": " + char.ConvertFromUtf32(source) + " => " + (char)nfdFirst);
count++;
values.Add(sourceString[0], str);
}
}
//var newValues = new Dictionary<int, char>(values.Count)
//{
// {15, 'a'}
//}
Trace.WriteLine($"CodeToAscii = new Dictionary<char, string>({values.Count})");
Trace.WriteLine("{");
foreach (var pair in values)
{
var escape = pair.Value.Replace("\\", @"\\").Replace("\"", "\\\"");
Trace.WriteLine($" {{'{pair.Key}',\"{escape}\"}},");
}
Trace.WriteLine("};");
//Trace.WriteLine("count: " + count);
//Trace.WriteLine("max: " + max);
//Trace.WriteLine("min: " + min);
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("UnicodeNormDApp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UnicodeNormDApp")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("33ffc0b9-0187-44f9-9424-bb5af5b4fb84")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>UnicodeNormDApp</RootNamespace>
<AssemblyName>UnicodeNormDApp</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Markdig", "Markdig\Markdig.xproj", "{8A58A7E2-627C-4F41-933F-5AC92ADFAB48}"
EndProject
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Markdig.Benchmarks", "Markd
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Markdig.WebApp", "Markdig.WebApp\Markdig.WebApp.xproj", "{3CAD9801-9976-46BE-BACA-F6D0D21FDC00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnicodeNormDApp", "UnicodeNormDApp\UnicodeNormDApp.csproj", "{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
{3CAD9801-9976-46BE-BACA-F6D0D21FDC00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3CAD9801-9976-46BE-BACA-F6D0D21FDC00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3CAD9801-9976-46BE-BACA-F6D0D21FDC00}.Release|Any CPU.Build.0 = Release|Any CPU
{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE