Compare commits

...

16 Commits

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

View File

@@ -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]
@@ -20115,4 +20115,147 @@ namespace Markdig.Tests
TestParser.TestSpec("----\nthis: is a frontmatter\n----\nThis is a text", "<hr />\n<h2>this: is a frontmatter</h2>\n<p>This is a text</p>", "yaml");
}
}
// # Extensions
//
// This section describes the different extensions supported:
//
// ## AutoLinks
//
// Autolinks will format as a HTML link any string that starts by:
//
// - `http://` or `https://`
// - `ftp://`
// - `mailto:`
// - `www.`
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example001()
{
// Example 1
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is a http://www.google.com URL and https://www.google.com
// This is a ftp://test.com
// And a mailto:email@toto.com
// And a plain www.google.com
//
// Should be rendered as:
// <p>This is a <a href="http://www.google.com">http://www.google.com</a> URL and <a href="https://www.google.com">https://www.google.com</a>
// This is a <a href="ftp://test.com">ftp://test.com</a>
// And a <a href="mailto:email@toto.com">mailto:email@toto.com</a>
// And a plain <a href="http://www.google.com">www.google.com</a></p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 1, "Extensions AutoLinks");
TestParser.TestSpec("This is a http://www.google.com URL and https://www.google.com\nThis is a ftp://test.com\nAnd a mailto:email@toto.com\nAnd a plain www.google.com", "<p>This is a <a href=\"http://www.google.com\">http://www.google.com</a> URL and <a href=\"https://www.google.com\">https://www.google.com</a>\nThis is a <a href=\"ftp://test.com\">ftp://test.com</a>\nAnd a <a href=\"mailto:email@toto.com\">mailto:email@toto.com</a>\nAnd a plain <a href=\"http://www.google.com\">www.google.com</a></p>", "autolinks|advanced");
}
}
// But incomplete links will not be matched:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example002()
{
// Example 2
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is not a http:/www.google.com URL and https:/www.google.com
// This is not a ftp:/test.com
// And not a mailto:emailtoto.com
// And not a plain www. or a www.x
//
// Should be rendered as:
// <p>This is not a http:/www.google.com URL and https:/www.google.com
// This is not a ftp:/test.com
// And not a mailto:emailtoto.com
// And not a plain www. or a www.x</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 2, "Extensions AutoLinks");
TestParser.TestSpec("This is not a http:/www.google.com URL and https:/www.google.com\nThis is not a ftp:/test.com\nAnd not a mailto:emailtoto.com\nAnd not a plain www. or a www.x ", "<p>This is not a http:/www.google.com URL and https:/www.google.com\nThis is not a ftp:/test.com\nAnd not a mailto:emailtoto.com\nAnd not a plain www. or a www.x</p>", "autolinks|advanced");
}
}
// Previous character must be a punctuation or a valid space (tab, space, new line):
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example003()
{
// Example 3
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is not a nhttp://www.google.com URL but this is (https://www.google.com)
//
// Should be rendered as:
// <p>This is not a nhttp://www.google.com URL but this is (<a href="https://www.google.com">https://www.google.com</a>)</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 3, "Extensions AutoLinks");
TestParser.TestSpec("This is not a nhttp://www.google.com URL but this is (https://www.google.com)", "<p>This is not a nhttp://www.google.com URL but this is (<a href=\"https://www.google.com\">https://www.google.com</a>)</p>", "autolinks|advanced");
}
}
// An autolink should not interfere with an `<a>` HTML inline:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example004()
{
// Example 4
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is an HTML <a href="http://www.google.com">http://www.google.com</a> link
//
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com">http://www.google.com</a> link</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 4, "Extensions AutoLinks");
TestParser.TestSpec("This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link", "<p>This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link</p>", "autolinks|advanced");
}
}
// or even within emphasis:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example005()
{
// Example 5
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is an HTML <a href="http://www.google.com"> **http://www.google.com** </a> link
//
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com"> <strong>http://www.google.com</strong> </a> link</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 5, "Extensions AutoLinks");
TestParser.TestSpec("This is an HTML <a href=\"http://www.google.com\"> **http://www.google.com** </a> link", "<p>This is an HTML <a href=\"http://www.google.com\"> <strong>http://www.google.com</strong> </a> link</p>", "autolinks|advanced");
}
}
// An autolink should not interfere with a markdown link:
[TestFixture]
public partial class TestExtensionsAutoLinks
{
[Test]
public void Example006()
{
// Example 6
// Section: Extensions AutoLinks
//
// The following CommonMark:
// This is an HTML [http://www.google.com](http://www.google.com) link
//
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com">http://www.google.com</a> link</p>
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 6, "Extensions AutoLinks");
TestParser.TestSpec("This is an HTML [http://www.google.com](http://www.google.com) link", "<p>This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link</p>", "autolinks|advanced");
}
}
}

View File

@@ -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

@@ -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

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

View File

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

View File

@@ -0,0 +1,29 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.
using Markdig.Renderers;
using Markdig.Syntax.Inlines;
namespace Markdig.Extensions.AutoLinks
{
/// <summary>
/// Extension to automatically create <see cref="LinkInline"/> when a link url http: or mailto: is found.
/// </summary>
/// <seealso cref="Markdig.IMarkdownExtension" />
public class AutoLinkExtension : IMarkdownExtension
{
public void Setup(MarkdownPipelineBuilder pipeline)
{
if (!pipeline.InlineParsers.Contains<AutoLinkParser>())
{
// Insert the parser before any other parsers
pipeline.InlineParsers.Insert(0, new AutoLinkParser());
}
}
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);
}

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

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

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.5",
"version": "0.10.3",
"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.5\n- Allow to force table column alignment to left\n> 0.8.4\n- Fix issue when calculating the span of an indented code block within a list. Make sure to include first whitespace on the line\n> 0.8.3\n- fix NullReferenceException with Gridtables extension when a single `+` is entered on a line\n> 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.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": {
@@ -34,7 +34,7 @@
"frameworks": {
"net35": {
"buildOptions": {
"define": [ "SUPPORT_NORMALIZE", "SUPPORT_FIXED_STRING" ]
"define": [ "SUPPORT_FIXED_STRING" ]
},
"frameworkAssemblies": {
"mscorlib": "",
@@ -44,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