mirror of
https://github.com/xoofx/markdig.git
synced 2026-02-13 05:45:31 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1df8344576 | ||
|
|
9eb84cf95e | ||
|
|
47d45b5577 | ||
|
|
ebcc286df0 | ||
|
|
f11d8037ac | ||
|
|
f668b3fe38 | ||
|
|
5ca4e31332 | ||
|
|
a8fbe79e30 | ||
|
|
bdb09b9820 | ||
|
|
79348ebea8 | ||
|
|
b366c1a5e3 | ||
|
|
a5e53b014f | ||
|
|
c2f21e21c8 | ||
|
|
81b8dce7a8 | ||
|
|
e6223f86d8 | ||
|
|
2054c16662 | ||
|
|
95641e562f | ||
|
|
e4953931c7 | ||
|
|
93b5b7a091 | ||
|
|
4f52e893ee | ||
|
|
23ede077a1 | ||
|
|
d5e6f17683 | ||
|
|
4d5980a485 | ||
|
|
19dd902519 | ||
|
|
f046a46275 | ||
|
|
25e9eafa8b | ||
|
|
f4ff981008 |
11
readme.md
11
readme.md
@@ -1,4 +1,4 @@
|
||||
# Markdig [](https://ci.appveyor.com/project/xoofx/markdig) [](https://www.nuget.org/packages/Markdig/)
|
||||
# Markdig [](https://ci.appveyor.com/project/xoofx/markdig) [](https://www.nuget.org/packages/Markdig/) [](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!
|
||||
|
||||
[](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!
|
||||
|
||||
@@ -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" />
|
||||
|
||||
78
src/Markdig.Tests/Specs/AutoLinks.md
Normal file
78
src/Markdig.Tests/Specs/AutoLinks.md
Normal 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>
|
||||
````````````````````````````````
|
||||
@@ -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>
|
||||
````````````````````````````````
|
||||
|
||||
@@ -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>
|
||||
````````````````````````````````
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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>())
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Markdig.Extensions.AutoIdentifiers
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
29
src/Markdig/Extensions/AutoLinks/AutoLinkExtension.cs
Normal file
29
src/Markdig/Extensions/AutoLinks/AutoLinkExtension.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
239
src/Markdig/Extensions/AutoLinks/AutoLinkParser.cs
Normal file
239
src/Markdig/Extensions/AutoLinks/AutoLinkParser.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace Markdig.Extensions.Bootstrap
|
||||
pipeline.DocumentProcessed += PipelineOnDocumentProcessed;
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Markdig.Extensions.Emoji
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Markdig.Extensions.Hardlines
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Markdig.Extensions.ListExtras
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Markdig.Extensions.PragmaLines
|
||||
pipeline.DocumentProcessed += PipelineOnDocumentProcessed;
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Markdig.Extensions.SelfPipeline
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>())
|
||||
{
|
||||
|
||||
1304
src/Markdig/Helpers/CharNormalizer.cs
Normal file
1304
src/Markdig/Helpers/CharNormalizer.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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": "",
|
||||
|
||||
104
src/UnicodeNormDApp/Program.cs
Normal file
104
src/UnicodeNormDApp/Program.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
36
src/UnicodeNormDApp/Properties/AssemblyInfo.cs
Normal file
36
src/UnicodeNormDApp/Properties/AssemblyInfo.cs
Normal 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")]
|
||||
56
src/UnicodeNormDApp/UnicodeNormDApp.csproj
Normal file
56
src/UnicodeNormDApp/UnicodeNormDApp.csproj
Normal 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>
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user