mirror of
https://github.com/xoofx/markdig.git
synced 2026-02-09 05:49:12 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
800c81bb9a | ||
|
|
5653a4f7ee | ||
|
|
4f14ffe63b | ||
|
|
d57acefe56 | ||
|
|
fb61e5a8da | ||
|
|
264516bfdb | ||
|
|
6d8f8996d5 | ||
|
|
ba8557d3bf | ||
|
|
d18fd0b957 | ||
|
|
fba96774f4 | ||
|
|
0b2764ea62 | ||
|
|
64d81ed47b | ||
|
|
9a9742888b | ||
|
|
5400b30a90 | ||
|
|
673f4a4beb | ||
|
|
05a27649aa | ||
|
|
26c6b12dea | ||
|
|
9a18ca222f | ||
|
|
354f31b870 | ||
|
|
c6c2f58ec0 | ||
|
|
4a146f00f6 | ||
|
|
2c10ac59d3 | ||
|
|
9a98fb9453 | ||
|
|
1c7f843a4c | ||
|
|
fdaf301bd6 | ||
|
|
5a9f2f3afe | ||
|
|
6a1b30761a | ||
|
|
8f8b08fad6 |
@@ -2,7 +2,7 @@
|
||||
|
||||
<img align="right" width="160px" height="160px" src="img/markdig.png">
|
||||
|
||||
Markdig is a fast, powerfull, [CommonMark](http://commonmark.org/) compliant, extensible Markdown processor for .NET.
|
||||
Markdig is a fast, powerful, [CommonMark](http://commonmark.org/) compliant, extensible Markdown processor for .NET.
|
||||
|
||||
> NOTE: The repository is under construction. There will be a dedicated website and proper documentation at some point!
|
||||
|
||||
@@ -80,6 +80,10 @@ var result = Markdown.ToHtml("This is a text with some *emphasis*", pipeline);
|
||||
|
||||
You can have a look at the [MarkdownExtensions](https://github.com/lunet-io/markdig/blob/master/src/Markdig/MarkdownExtensions.cs) that describes all actionable extensions (by modifying the MarkdownPipeline)
|
||||
|
||||
## Build
|
||||
|
||||
In order to build Markdig, you need to install [.NET Core RTM](https://www.microsoft.com/net/core)
|
||||
|
||||
## License
|
||||
|
||||
This software is released under the [BSD-Clause 2 license](https://github.com/lunet-io/markdig/blob/master/license.txt).
|
||||
@@ -111,7 +115,7 @@ This is an early preview of the benchmarking against various implementations:
|
||||
### Analysis of the results:
|
||||
|
||||
- Markdig is roughly **x100 times faster than MarkdownSharp**, **30x times faster than docfx**
|
||||
- **Among the best in CPU**, Extremelly competitive and often faster than other implementations (not feature wise equivalent)
|
||||
- **Among the best in CPU**, Extremely competitive and often faster than other implementations (not feature wise equivalent)
|
||||
- **15% to 30% less allocations** and GC pressure
|
||||
|
||||
Because Marked.NET, MarkdownSharp and DocAsCode.MarkdownLite are way too slow, they are not included in the following charts:
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -85,6 +86,7 @@
|
||||
<None Include="Specs\GridTableSpecs.md" />
|
||||
<None Include="Specs\HardlineBreakSpecs.md" />
|
||||
<None Include="Specs\BootstrapSpecs.md" />
|
||||
<None Include="Specs\DiagramsSpecs.md" />
|
||||
<None Include="Specs\TaskListSpecs.md" />
|
||||
<None Include="Specs\SmartyPantsSpecs.md" />
|
||||
<None Include="Specs\MediaSpecs.md" />
|
||||
@@ -100,6 +102,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
26
src/Markdig.Tests/Specs/DiagramsSpecs.md
Normal file
26
src/Markdig.Tests/Specs/DiagramsSpecs.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Extensions
|
||||
|
||||
Adds support for diagrams extension:
|
||||
|
||||
## Mermaid diagrams
|
||||
|
||||
Using a fenced code block with the `mermaid` language info will output a `<div class='mermaid'>` instead of a `pre/code` block:
|
||||
|
||||
```````````````````````````````` example
|
||||
```mermaid
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
```
|
||||
.
|
||||
<div class="mermaid">graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
</div>
|
||||
````````````````````````````````
|
||||
|
||||
TODO: Add other text diagram languages
|
||||
@@ -70,8 +70,8 @@ A regular row can continue a previous regular row when column separator `|` are
|
||||
+---------+---------+---------+
|
||||
| Col1 | Col2 | Col3 |
|
||||
| Col1a | Col2a | Col3a |
|
||||
| Col12 | Col3b |
|
||||
| Col123 |
|
||||
| Col1b | Col3b |
|
||||
| Col1c |
|
||||
.
|
||||
<table>
|
||||
<col style="width:33.33%">
|
||||
@@ -87,11 +87,11 @@ Col2a</td>
|
||||
Col3a</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">Col12</td>
|
||||
<td></td>
|
||||
<td colspan="2">Col1b</td>
|
||||
<td>Col3b</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">Col123</td>
|
||||
<td colspan="3">Col1c</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -133,3 +133,13 @@ a | b
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
Check quotes and dash:
|
||||
|
||||
```````````````````````````````` example
|
||||
A "quote" with a ---
|
||||
.
|
||||
<p>A “quote” with a —</p>
|
||||
````````````````````````````````
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,8 @@ 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/master/spec.txt", string.Empty),
|
||||
new KeyValuePair<string, string>("https://raw.githubusercontent.com/jgm/CommonMark/91e045ca370258903ed138450373043a496ec64b/spec.txt", string.Empty), // 0.26 specs
|
||||
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"),
|
||||
@@ -57,6 +58,7 @@ SOFTWARE.
|
||||
new KeyValuePair<string, string>(Host.ResolvePath("SmartyPantsSpecs.md"), "pipetables+smartypants|advanced+smartypants"), // Check with smartypants to make sure that it doesn't break pipetables
|
||||
new KeyValuePair<string, string>(Host.ResolvePath("AutoIdentifierSpecs.md"), "autoidentifiers|advanced"),
|
||||
new KeyValuePair<string, string>(Host.ResolvePath("TaskListSpecs.md"), "tasklists|advanced"),
|
||||
new KeyValuePair<string, string>(Host.ResolvePath("DiagramsSpecs.md"), "diagrams|advanced"),
|
||||
};
|
||||
var emptyLines = false;
|
||||
var displayEmptyLines = false;
|
||||
|
||||
@@ -297,5 +297,102 @@ namespace Markdig.Tests
|
||||
Assert.False(LinkHelper.TryParseAutolink(new StringSlice(@"<ab"), out text, out isEmail));
|
||||
Assert.False(LinkHelper.TryParseAutolink(new StringSlice(@"<user@>"), out text, out isEmail));
|
||||
}
|
||||
|
||||
[TestCase("Header identifiers in HTML", "header-identifiers-in-html")]
|
||||
[TestCase("* Dogs*?--in *my* house?", "dogs-in-my-house")] // Not Pandoc equivalent: dogs--in...
|
||||
[TestCase("[HTML], [S5], or [RTF]?", "html-s5-or-rtf")]
|
||||
[TestCase("3. Applications", "applications")]
|
||||
[TestCase("33", "")]
|
||||
public void TestUrilizeNonAscii_Pandoc(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, false));
|
||||
}
|
||||
|
||||
[TestCase("abc", "abc")]
|
||||
[TestCase("a-c", "a-c")]
|
||||
[TestCase("a c", "a-c")]
|
||||
[TestCase("a_c", "a_c")]
|
||||
[TestCase("a.c", "a.c")]
|
||||
[TestCase("a,c", "ac")]
|
||||
[TestCase("a--", "a")] // Not Pandoc-equivalent: a--
|
||||
[TestCase("a__", "a")] // Not Pandoc-equivalent: a__
|
||||
[TestCase("a..", "a")] // Not Pandoc-equivalent: a..
|
||||
[TestCase("a??", "a")]
|
||||
[TestCase("a ", "a")]
|
||||
[TestCase("a--d", "a-d")]
|
||||
[TestCase("a__d", "a_d")]
|
||||
[TestCase("a??d", "ad")]
|
||||
[TestCase("a d", "a-d")]
|
||||
[TestCase("a..d", "a.d")]
|
||||
[TestCase("-bc", "bc")]
|
||||
[TestCase("_bc", "bc")]
|
||||
[TestCase(" bc", "bc")]
|
||||
[TestCase("?bc", "bc")]
|
||||
[TestCase(".bc", "bc")]
|
||||
[TestCase("a-.-", "a")] // Not Pandoc equivalent: a-.-
|
||||
public void TestUrilizeOnlyAscii_Simple(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, true));
|
||||
}
|
||||
|
||||
[TestCase("bær", "br")]
|
||||
[TestCase("bør", "br")]
|
||||
[TestCase("bΘr", "br")]
|
||||
[TestCase("四五", "")]
|
||||
public void TestUrilizeOnlyAscii_NonAscii(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, true));
|
||||
}
|
||||
|
||||
[TestCase("bár", "bar")]
|
||||
[TestCase("àrrivé", "arrive")]
|
||||
public void TestUrilizeOnlyAscii_Normalization(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, true));
|
||||
}
|
||||
|
||||
[TestCase("123", "")]
|
||||
[TestCase("1,-b", "b")]
|
||||
[TestCase("b1,-", "b1")] // Not Pandoc equivalent: b1-
|
||||
[TestCase("ab3", "ab3")]
|
||||
[TestCase("ab3de", "ab3de")]
|
||||
public void TestUrilizeOnlyAscii_Numeric(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, true));
|
||||
}
|
||||
|
||||
[TestCase("一二三四五", "一二三四五")]
|
||||
[TestCase("一,-b", "一-b")]
|
||||
public void TestUrilizeNonAscii_NonAsciiNumeric(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, false));
|
||||
}
|
||||
|
||||
[TestCase("bær", "bær")]
|
||||
[TestCase("æ5el", "æ5el")]
|
||||
[TestCase("-æ5el", "æ5el")]
|
||||
[TestCase("-frø-", "frø")]
|
||||
[TestCase("-fr-ø", "fr-ø")]
|
||||
public void TestUrilizeNonAscii_Simple(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, false));
|
||||
}
|
||||
|
||||
// Just to be sure, test for characters expressly forbidden in URI fragments:
|
||||
[TestCase("b#r", "br")]
|
||||
[TestCase("b%r", "br")] // Invalid except as an escape character
|
||||
[TestCase("b^r", "br")]
|
||||
[TestCase("b[r", "br")]
|
||||
[TestCase("b]r", "br")]
|
||||
[TestCase("b{r", "br")]
|
||||
[TestCase("b}r", "br")]
|
||||
[TestCase("b<r", "br")]
|
||||
[TestCase("b>r", "br")]
|
||||
[TestCase(@"b\r", "br")]
|
||||
[TestCase(@"b""r", "br")]
|
||||
public void TestUrilizeNonAscii_NonValidCharactersForFragments(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.Urilize(input, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,10 +293,6 @@ literal ( 0, 9) 9-9
|
||||
");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestThematicBreak()
|
||||
{
|
||||
@@ -373,12 +369,13 @@ literal ( 0, 2) 2-3
|
||||
[Test]
|
||||
public void TestHtmlEntityInline()
|
||||
{
|
||||
// 01234567
|
||||
Check("0 1", @"
|
||||
paragraph ( 0, 0) 0-7
|
||||
// 01 23456789
|
||||
Check("0\n 1", @"
|
||||
paragraph ( 0, 0) 0-9
|
||||
literal ( 0, 0) 0-0
|
||||
htmlentity ( 0, 1) 1-6
|
||||
literal ( 0, 7) 7-7
|
||||
linebreak ( 0, 1) 1-1
|
||||
htmlentity ( 1, 0) 2-7
|
||||
literal ( 1, 6) 8-9
|
||||
");
|
||||
}
|
||||
|
||||
@@ -658,7 +655,7 @@ literal ( 4, 2) 13-13
|
||||
Check("0\n\n 0\n 1\n", @"
|
||||
paragraph ( 0, 0) 0-0
|
||||
literal ( 0, 0) 0-0
|
||||
code ( 2, 4) 7-13
|
||||
code ( 2, 0) 3-13
|
||||
");
|
||||
}
|
||||
|
||||
@@ -669,7 +666,7 @@ code ( 2, 4) 7-13
|
||||
Check("0\n\n\t0\n\t1\n", @"
|
||||
paragraph ( 0, 0) 0-0
|
||||
literal ( 0, 0) 0-0
|
||||
code ( 2, 4) 4-7
|
||||
code ( 2, 0) 3-7
|
||||
");
|
||||
}
|
||||
|
||||
@@ -680,7 +677,7 @@ code ( 2, 4) 4-7
|
||||
Check("0\n\n \t0\n \t1\n", @"
|
||||
paragraph ( 0, 0) 0-0
|
||||
literal ( 0, 0) 0-0
|
||||
code ( 2, 4) 5-9
|
||||
code ( 2, 0) 3-9
|
||||
");
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"NUnit": "3.2.0"
|
||||
"NUnit": "3.2.0",
|
||||
"NUnit3TestAdapter": "3.2.0"
|
||||
}
|
||||
}
|
||||
31
src/Markdig/Extensions/Diagrams/DiagramExtension.cs
Normal file
31
src/Markdig/Extensions/Diagrams/DiagramExtension.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
// 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.Renderers.Html;
|
||||
|
||||
namespace Markdig.Extensions.Diagrams
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension to allow diagrams.
|
||||
/// </summary>
|
||||
/// <seealso cref="Markdig.IMarkdownExtension" />
|
||||
public class DiagramExtension : IMarkdownExtension
|
||||
{
|
||||
public void Setup(MarkdownPipelineBuilder pipeline)
|
||||
{
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
{
|
||||
var htmlRenderer = renderer as HtmlRenderer;
|
||||
if (htmlRenderer != null)
|
||||
{
|
||||
var codeRenderer = htmlRenderer.ObjectRenderers.FindExact<CodeBlockRenderer>();
|
||||
// TODO: Add other well known diagram languages
|
||||
codeRenderer.BlocksAsDiv.Add("mermaid");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/Markdig/Extensions/NoRefLinks/NoFollowLinksExtension.cs
Normal file
34
src/Markdig/Extensions/NoRefLinks/NoFollowLinksExtension.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
// 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.Renderers.Html.Inlines;
|
||||
|
||||
namespace Markdig.Extensions.NoRefLinks
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension to automatically render rel=nofollow to all links in an HTML output.
|
||||
/// </summary>
|
||||
public class NoFollowLinksExtension : IMarkdownExtension
|
||||
{
|
||||
public void Setup(MarkdownPipelineBuilder pipeline)
|
||||
{
|
||||
}
|
||||
|
||||
public void Setup(IMarkdownRenderer renderer)
|
||||
{
|
||||
var linkRenderer = renderer.ObjectRenderers.Find<LinkInlineRenderer>();
|
||||
if (linkRenderer != null)
|
||||
{
|
||||
linkRenderer.AutoRelNoFollow = true;
|
||||
}
|
||||
|
||||
var autolinkRenderer = renderer.ObjectRenderers.Find<AutolinkInlineRenderer>();
|
||||
if (autolinkRenderer != null)
|
||||
{
|
||||
autolinkRenderer.AutoRelNoFollow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,8 @@ namespace Markdig.Extensions.SmartyPants
|
||||
case '-':
|
||||
if (slice.NextChar() == '-')
|
||||
{
|
||||
processor.ParserStates[Index] = string.Empty;
|
||||
var quotePants = GetOrCreateState(processor);
|
||||
quotePants.HasDash = true;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -170,11 +171,8 @@ namespace Markdig.Extensions.SmartyPants
|
||||
// We will check in a post-process step for balanaced open/close quotes
|
||||
if (postProcess)
|
||||
{
|
||||
var quotePants = processor.ParserStates[Index] as List<SmartyPant>;
|
||||
if (quotePants == null)
|
||||
{
|
||||
processor.ParserStates[Index] = quotePants = new List<SmartyPant>();
|
||||
}
|
||||
var quotePants = GetOrCreateState(processor);
|
||||
|
||||
// Register only if we don't have yet any quotes
|
||||
if (quotePants.Count == 0)
|
||||
{
|
||||
@@ -187,11 +185,21 @@ namespace Markdig.Extensions.SmartyPants
|
||||
return true;
|
||||
}
|
||||
|
||||
private ListSmartyPants GetOrCreateState(InlineProcessor processor)
|
||||
{
|
||||
var quotePants = processor.ParserStates[Index] as ListSmartyPants;
|
||||
if (quotePants == null)
|
||||
{
|
||||
processor.ParserStates[Index] = quotePants = new ListSmartyPants();
|
||||
}
|
||||
return quotePants;
|
||||
}
|
||||
|
||||
private void BlockOnProcessInlinesEnd(InlineProcessor processor, Inline inline)
|
||||
{
|
||||
processor.Block.ProcessInlinesEnd -= BlockOnProcessInlinesEnd;
|
||||
|
||||
var pants = (List<SmartyPant>) processor.ParserStates[Index];
|
||||
var pants = (ListSmartyPants) processor.ParserStates[Index];
|
||||
|
||||
// We only change quote into left or right quotes if we find proper balancing
|
||||
var previousIndices = new int[3] {-1, -1, -1};
|
||||
@@ -286,7 +294,8 @@ namespace Markdig.Extensions.SmartyPants
|
||||
bool isFinalProcessing)
|
||||
{
|
||||
// Don't try to process anything if there are no dash
|
||||
if (state.ParserStates[Index] == null)
|
||||
var quotePants = state.ParserStates[Index] as ListSmartyPants;
|
||||
if (quotePants == null || !quotePants.HasDash)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -361,5 +370,11 @@ namespace Markdig.Extensions.SmartyPants
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private class ListSmartyPants : List<SmartyPant>
|
||||
{
|
||||
public bool HasDash { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,11 +131,12 @@ namespace Markdig.Extensions.Tables
|
||||
// | ------------- | ------------ | ---------------------------------------- |
|
||||
// Calculate the colspan for the new row
|
||||
int columnIndex = -1;
|
||||
foreach (var columnSlice in columns)
|
||||
for (int i = 0; i < columns.Count; i++)
|
||||
{
|
||||
var columnSlice = columns[i];
|
||||
if (line.PeekCharExtra(columnSlice.Start) == '|')
|
||||
{
|
||||
columnIndex++;
|
||||
columnIndex = i;
|
||||
}
|
||||
if (columnIndex >= 0)
|
||||
{
|
||||
@@ -301,8 +302,9 @@ namespace Markdig.Extensions.Tables
|
||||
{
|
||||
var columns = tableState.ColumnSlices;
|
||||
TableRow currentRow = null;
|
||||
foreach (var columnSlice in columns)
|
||||
for (int i = 0; i < columns.Count; i++)
|
||||
{
|
||||
var columnSlice = columns[i];
|
||||
if (columnSlice.CurrentCell != null)
|
||||
{
|
||||
if (currentRow == null)
|
||||
@@ -332,7 +334,8 @@ namespace Markdig.Extensions.Tables
|
||||
// Else we can create a new cell
|
||||
columnSlice.CurrentCell = new TableCell(this)
|
||||
{
|
||||
ColumnSpan = columnSlice.CurrentColumnSpan
|
||||
ColumnSpan = columnSlice.CurrentColumnSpan,
|
||||
ColumnIndex = i
|
||||
};
|
||||
|
||||
if (columnSlice.BlockProcessor == null)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Markdig.Renderers;
|
||||
using Markdig.Renderers.Html;
|
||||
|
||||
@@ -38,7 +39,9 @@ namespace Markdig.Extensions.Tables
|
||||
{
|
||||
foreach (var tableColumnDefinition in table.ColumnDefinitions)
|
||||
{
|
||||
renderer.WriteLine($"<col style=\"width:{Math.Round(tableColumnDefinition.Width*100)/100}%\">");
|
||||
var width = Math.Round(tableColumnDefinition.Width*100)/100;
|
||||
var widthValue = string.Format(CultureInfo.InvariantCulture, "{0:0.##}", width);
|
||||
renderer.WriteLine($"<col style=\"width:{widthValue}%\">");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,10 +81,10 @@ namespace Markdig.Extensions.Tables
|
||||
{
|
||||
renderer.Write($" colspan=\"{cell.ColumnSpan}\"");
|
||||
}
|
||||
|
||||
if (table.ColumnDefinitions != null && i < table.ColumnDefinitions.Count)
|
||||
var columnIndex = cell.ColumnIndex == -1 ? i : cell.ColumnIndex;
|
||||
if (table.ColumnDefinitions != null && columnIndex < table.ColumnDefinitions.Count)
|
||||
{
|
||||
switch (table.ColumnDefinitions[i].Alignment)
|
||||
switch (table.ColumnDefinitions[columnIndex].Alignment)
|
||||
{
|
||||
case TableColumnAlign.Center:
|
||||
renderer.Write(" style=\"text-align: center;\"");
|
||||
|
||||
@@ -27,8 +27,14 @@ namespace Markdig.Extensions.Tables
|
||||
public TableCell(BlockParser parser) : base(parser)
|
||||
{
|
||||
ColumnSpan = 1;
|
||||
ColumnIndex = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the index of the column to which this cell belongs.
|
||||
/// </summary>
|
||||
public int ColumnIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column span this cell is covering. Default is 1.
|
||||
/// </summary>
|
||||
|
||||
@@ -61,6 +61,11 @@ namespace Markdig.Helpers
|
||||
}
|
||||
previousIsSpace = false;
|
||||
}
|
||||
else if (c.IsDigit())
|
||||
{
|
||||
headingBuffer.Append(c);
|
||||
previousIsSpace = false;
|
||||
}
|
||||
else if (!previousIsSpace && c.IsWhitespace())
|
||||
{
|
||||
var pc = headingBuffer[headingBuffer.Length - 1];
|
||||
|
||||
@@ -9,6 +9,7 @@ using Markdig.Extensions.Bootstrap;
|
||||
using Markdig.Extensions.Citations;
|
||||
using Markdig.Extensions.CustomContainers;
|
||||
using Markdig.Extensions.DefinitionLists;
|
||||
using Markdig.Extensions.Diagrams;
|
||||
using Markdig.Extensions.Emoji;
|
||||
using Markdig.Extensions.EmphasisExtras;
|
||||
using Markdig.Extensions.Figures;
|
||||
@@ -19,6 +20,7 @@ using Markdig.Extensions.Hardlines;
|
||||
using Markdig.Extensions.ListExtras;
|
||||
using Markdig.Extensions.Mathematics;
|
||||
using Markdig.Extensions.MediaLinks;
|
||||
using Markdig.Extensions.NoRefLinks;
|
||||
using Markdig.Extensions.PragmaLines;
|
||||
using Markdig.Extensions.SelfPipeline;
|
||||
using Markdig.Extensions.SmartyPants;
|
||||
@@ -57,6 +59,7 @@ namespace Markdig
|
||||
.UsePipeTables()
|
||||
.UseListExtras()
|
||||
.UseTaskLists()
|
||||
.UseDiagrams()
|
||||
.UseGenericAttributes(); // Must be last as it is one parser that is modifying other parsers
|
||||
}
|
||||
|
||||
@@ -89,6 +92,17 @@ namespace Markdig
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses the diagrams extension
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline.</param>
|
||||
/// <returns>The modified pipeline</returns>
|
||||
public static MarkdownPipelineBuilder UseDiagrams(this MarkdownPipelineBuilder pipeline)
|
||||
{
|
||||
pipeline.Extensions.AddIfNotAlready<DiagramExtension>();
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses precise source code location (useful for syntax highlighting).
|
||||
/// </summary>
|
||||
@@ -353,6 +367,17 @@ namespace Markdig
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add rel=nofollow to all links rendered to HTML.
|
||||
/// </summary>
|
||||
/// <param name="pipeline"></param>
|
||||
/// <returns></returns>
|
||||
public static MarkdownPipelineBuilder UseNoFollowLinks(this MarkdownPipelineBuilder pipeline)
|
||||
{
|
||||
pipeline.Extensions.AddIfNotAlready<NoFollowLinksExtension>();
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will disable the HTML support in the markdown processor (for constraint/safe parsing).
|
||||
/// </summary>
|
||||
@@ -456,6 +481,12 @@ namespace Markdig
|
||||
case "tasklists":
|
||||
pipeline.UseTaskLists();
|
||||
break;
|
||||
case "diagrams":
|
||||
pipeline.UseDiagrams();
|
||||
break;
|
||||
case "nofollowlinks":
|
||||
pipeline.UseNoFollowLinks();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Invalid extension `{extension}` from `{extensions}`", nameof(extensions));
|
||||
}
|
||||
|
||||
@@ -12,13 +12,15 @@ namespace Markdig.Parsers
|
||||
/// <seealso cref="Markdig.Parsers.BlockParser" />
|
||||
public class FencedCodeBlockParser : FencedBlockParserBase<FencedCodeBlock>
|
||||
{
|
||||
public const string DefaultInfoPrefix = "language-";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FencedCodeBlockParser"/> class.
|
||||
/// </summary>
|
||||
public FencedCodeBlockParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'`', '~'};
|
||||
InfoPrefix = "language-";
|
||||
InfoPrefix = DefaultInfoPrefix;
|
||||
}
|
||||
|
||||
protected override FencedCodeBlock CreateFencedBlock(BlockProcessor processor)
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Markdig.Parsers
|
||||
}
|
||||
|
||||
// A space is required after leading #
|
||||
if (leadingCount > 0 && leadingCount <= 6 && (c.IsSpace() || c == '\0'))
|
||||
if (leadingCount > 0 && leadingCount <= 6 && (c.IsSpaceOrTab() || c == '\0'))
|
||||
{
|
||||
// Move to the content
|
||||
var headingBlock = new HeadingBlock(this)
|
||||
@@ -89,7 +89,7 @@ namespace Markdig.Parsers
|
||||
c = processor.Line.Text[i];
|
||||
if (endState == 0)
|
||||
{
|
||||
if (c.IsSpace()) // TODO: Not clear if it is a space or space+tab in the specs
|
||||
if (c.IsSpaceOrTab())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ namespace Markdig.Parsers
|
||||
|
||||
if (countClosingTags > 0)
|
||||
{
|
||||
if (c.IsSpace())
|
||||
if (c.IsSpaceOrTab())
|
||||
{
|
||||
processor.Line.End = i - 1;
|
||||
}
|
||||
|
||||
@@ -18,13 +18,14 @@ namespace Markdig.Parsers
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
{
|
||||
var startPosition = processor.Line.Start;
|
||||
var startColumn = processor.ColumnBeforeIndent;
|
||||
var startPosition = processor.StartBeforeIndent;
|
||||
var result = TryContinue(processor, null);
|
||||
if (result == BlockState.Continue)
|
||||
{
|
||||
processor.NewBlocks.Push(new CodeBlock(this)
|
||||
{
|
||||
Column = processor.Column,
|
||||
Column = startColumn,
|
||||
Span = new SourceSpan(startPosition, processor.Line.End)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -45,14 +45,14 @@ namespace Markdig.Parsers.Inlines
|
||||
if (literal != null)
|
||||
{
|
||||
var matched = slice;
|
||||
matched.End = match - 1;
|
||||
matched.End = slice.Start + match - 1;
|
||||
int line;
|
||||
int column;
|
||||
processor.Inline = new HtmlEntityInline()
|
||||
{
|
||||
Original = matched,
|
||||
Transcoded = new StringSlice(literal),
|
||||
Span = new SourceSpan(processor.GetSourcePosition(startPosition, out line, out column), processor.GetSourcePosition(matched.End + 1)),
|
||||
Span = new SourceSpan(processor.GetSourcePosition(startPosition, out line, out column), processor.GetSourcePosition(matched.End)),
|
||||
Line = line,
|
||||
Column = column
|
||||
};
|
||||
|
||||
@@ -138,11 +138,6 @@ namespace Markdig.Parsers
|
||||
list.CountBlankLinesReset++;
|
||||
}
|
||||
|
||||
if (list.CountBlankLinesReset > 1)
|
||||
{
|
||||
return BlockState.BreakDiscard;
|
||||
}
|
||||
|
||||
if (list.CountBlankLinesReset == 1 && listItem.ColumnWidth < 0)
|
||||
{
|
||||
state.Close(listItem);
|
||||
@@ -254,6 +249,16 @@ namespace Markdig.Parsers
|
||||
columnWidth = (state.IsBlankLine ? columnBeforeIndent : state.Column) - initColumnBeforeIndent;
|
||||
}
|
||||
|
||||
// Starts/continue the list unless:
|
||||
// - an empty list item follows a paragraph
|
||||
// - an ordered list is not starting by '1'
|
||||
var isPreviousParagraph = (block ?? state.LastBlock) is ParagraphBlock;
|
||||
if (isPreviousParagraph && (state.IsBlankLine || (listInfo.BulletType == '1' && listInfo.OrderedStart != "1")))
|
||||
{
|
||||
state.GoToColumn(initColumn);
|
||||
return BlockState.None;
|
||||
}
|
||||
|
||||
var newListItem = new ListItemBlock(this)
|
||||
{
|
||||
Column = initColumn,
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Markdig.Parsers
|
||||
|
||||
breakCharCount++;
|
||||
}
|
||||
else if (c.IsSpace())
|
||||
else if (c.IsSpaceOrTab())
|
||||
{
|
||||
hasSpacesSinceLastMatch = true;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,6 @@ namespace Markdig
|
||||
{
|
||||
public static partial class Markdown
|
||||
{
|
||||
public const string Version = "0.6.2";
|
||||
public const string Version = "0.7.2";
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
// 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.Parsers;
|
||||
using Markdig.Syntax;
|
||||
|
||||
namespace Markdig.Renderers.Html
|
||||
@@ -11,24 +15,57 @@ namespace Markdig.Renderers.Html
|
||||
/// <seealso cref="Markdig.Renderers.Html.HtmlObjectRenderer{Markdig.Syntax.CodeBlock}" />
|
||||
public class CodeBlockRenderer : HtmlObjectRenderer<CodeBlock>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CodeBlockRenderer"/> class.
|
||||
/// </summary>
|
||||
public CodeBlockRenderer()
|
||||
{
|
||||
BlocksAsDiv = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public bool OutputAttributesOnPre { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a map of fenced code block infos that should be rendered as div blocks instead of pre/code blocks.
|
||||
/// </summary>
|
||||
public HashSet<string> BlocksAsDiv { get; }
|
||||
|
||||
protected override void Write(HtmlRenderer renderer, CodeBlock obj)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
renderer.Write("<pre");
|
||||
if (OutputAttributesOnPre)
|
||||
|
||||
var fencedCodeBlock = obj as FencedCodeBlock;
|
||||
if (fencedCodeBlock?.Info != null && BlocksAsDiv.Contains(fencedCodeBlock.Info))
|
||||
{
|
||||
renderer.WriteAttributes(obj);
|
||||
var infoPrefix = (obj.Parser as FencedCodeBlockParser)?.InfoPrefix ??
|
||||
FencedCodeBlockParser.DefaultInfoPrefix;
|
||||
|
||||
// We are replacing the HTML attribute `language-mylang` by `mylang` only for a div block
|
||||
// NOTE that we are allocating a closure here
|
||||
renderer.Write("<div")
|
||||
.WriteAttributes(obj.TryGetAttributes(),
|
||||
cls => cls.StartsWith(infoPrefix) ? cls.Substring(infoPrefix.Length) : cls)
|
||||
.Write(">");
|
||||
renderer.WriteLeafRawLines(obj, true, true, true);
|
||||
renderer.WriteLine("</div>");
|
||||
|
||||
}
|
||||
renderer.Write("><code");
|
||||
if (!OutputAttributesOnPre)
|
||||
else
|
||||
{
|
||||
renderer.WriteAttributes(obj);
|
||||
renderer.Write("<pre");
|
||||
if (OutputAttributesOnPre)
|
||||
{
|
||||
renderer.WriteAttributes(obj);
|
||||
}
|
||||
renderer.Write("><code");
|
||||
if (!OutputAttributesOnPre)
|
||||
{
|
||||
renderer.WriteAttributes(obj);
|
||||
}
|
||||
renderer.Write(">");
|
||||
renderer.WriteLeafRawLines(obj, true, true);
|
||||
renderer.WriteLine("</code></pre>");
|
||||
}
|
||||
renderer.Write(">");
|
||||
renderer.WriteLeafRawLines(obj, true, true);
|
||||
renderer.WriteLine("</code></pre>");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,11 @@ namespace Markdig.Renderers.Html.Inlines
|
||||
/// <seealso cref="Markdig.Renderers.Html.HtmlObjectRenderer{Markdig.Syntax.Inlines.AutolinkInline}" />
|
||||
public class AutolinkInlineRenderer : HtmlObjectRenderer<AutolinkInline>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to always add rel="nofollow" for links or not.
|
||||
/// </summary>
|
||||
public bool AutoRelNoFollow { get; set; }
|
||||
|
||||
protected override void Write(HtmlRenderer renderer, AutolinkInline obj)
|
||||
{
|
||||
if (renderer.EnableHtmlForInline)
|
||||
@@ -22,6 +27,12 @@ namespace Markdig.Renderers.Html.Inlines
|
||||
}
|
||||
renderer.WriteEscapeUrl(obj.Url);
|
||||
renderer.WriteAttributes(obj);
|
||||
|
||||
if (!obj.IsEmail && AutoRelNoFollow)
|
||||
{
|
||||
renderer.Write(" rel=\"nofollow\"");
|
||||
}
|
||||
|
||||
renderer.Write("\">");
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ namespace Markdig.Renderers.Html.Inlines
|
||||
/// <seealso cref="Markdig.Renderers.Html.HtmlObjectRenderer{Markdig.Syntax.Inlines.LinkInline}" />
|
||||
public class LinkInlineRenderer : HtmlObjectRenderer<LinkInline>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to always add rel="nofollow" for links or not.
|
||||
/// </summary>
|
||||
public bool AutoRelNoFollow { get; set; }
|
||||
|
||||
protected override void Write(HtmlRenderer renderer, LinkInline link)
|
||||
{
|
||||
if (renderer.EnableHtmlForInline)
|
||||
@@ -54,6 +59,10 @@ namespace Markdig.Renderers.Html.Inlines
|
||||
{
|
||||
if (renderer.EnableHtmlForInline)
|
||||
{
|
||||
if (AutoRelNoFollow)
|
||||
{
|
||||
renderer.Write(" rel=\"nofollow\"");
|
||||
}
|
||||
renderer.Write(">");
|
||||
}
|
||||
renderer.WriteChildren(link);
|
||||
|
||||
@@ -83,26 +83,28 @@ namespace Markdig.Renderers
|
||||
/// Writes the content escaped for HTML.
|
||||
/// </summary>
|
||||
/// <param name="slice">The slice.</param>
|
||||
/// <param name="softEscape">Only escape < and &</param>
|
||||
/// <returns>This instance</returns>
|
||||
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
||||
public HtmlRenderer WriteEscape(ref StringSlice slice)
|
||||
public HtmlRenderer WriteEscape(ref StringSlice slice, bool softEscape = false)
|
||||
{
|
||||
if (slice.Start > slice.End)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
return WriteEscape(slice.Text, slice.Start, slice.Length);
|
||||
return WriteEscape(slice.Text, slice.Start, slice.Length, softEscape);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the content escaped for HTML.
|
||||
/// </summary>
|
||||
/// <param name="slice">The slice.</param>
|
||||
/// <param name="softEscape">Only escape < and &</param>
|
||||
/// <returns>This instance</returns>
|
||||
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
||||
public HtmlRenderer WriteEscape(StringSlice slice)
|
||||
public HtmlRenderer WriteEscape(StringSlice slice, bool softEscape = false)
|
||||
{
|
||||
return WriteEscape(ref slice);
|
||||
return WriteEscape(ref slice, softEscape);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -111,8 +113,9 @@ namespace Markdig.Renderers
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <param name="length">The length.</param>
|
||||
/// <param name="softEscape">Only escape < and &</param>
|
||||
/// <returns>This instance</returns>
|
||||
public HtmlRenderer WriteEscape(string content, int offset, int length)
|
||||
public HtmlRenderer WriteEscape(string content, int offset, int length, bool softEscape = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(content) || length == 0)
|
||||
return this;
|
||||
@@ -132,12 +135,15 @@ namespace Markdig.Renderers
|
||||
previousOffset = offset + 1;
|
||||
break;
|
||||
case '>':
|
||||
Write(content, previousOffset, offset - previousOffset);
|
||||
if (EnableHtmlEscape)
|
||||
if (!softEscape)
|
||||
{
|
||||
Write(">");
|
||||
Write(content, previousOffset, offset - previousOffset);
|
||||
if (EnableHtmlEscape)
|
||||
{
|
||||
Write(">");
|
||||
}
|
||||
previousOffset = offset + 1;
|
||||
}
|
||||
previousOffset = offset + 1;
|
||||
break;
|
||||
case '&':
|
||||
Write(content, previousOffset, offset - previousOffset);
|
||||
@@ -148,12 +154,15 @@ namespace Markdig.Renderers
|
||||
previousOffset = offset + 1;
|
||||
break;
|
||||
case '"':
|
||||
Write(content, previousOffset, offset - previousOffset);
|
||||
if (EnableHtmlEscape)
|
||||
if (!softEscape)
|
||||
{
|
||||
Write(""");
|
||||
Write(content, previousOffset, offset - previousOffset);
|
||||
if (EnableHtmlEscape)
|
||||
{
|
||||
Write(""");
|
||||
}
|
||||
previousOffset = offset + 1;
|
||||
}
|
||||
previousOffset = offset + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -233,8 +242,9 @@ namespace Markdig.Renderers
|
||||
/// Writes the specified <see cref="HtmlAttributes"/>.
|
||||
/// </summary>
|
||||
/// <param name="attributes">The attributes to render.</param>
|
||||
/// <param name="classFilter">A class filter used to transform a class into another class at writing time</param>
|
||||
/// <returns>This instance</returns>
|
||||
public HtmlRenderer WriteAttributes(HtmlAttributes attributes)
|
||||
public HtmlRenderer WriteAttributes(HtmlAttributes attributes, Func<string, string> classFilter = null)
|
||||
{
|
||||
if (attributes == null)
|
||||
{
|
||||
@@ -256,7 +266,7 @@ namespace Markdig.Renderers
|
||||
{
|
||||
Write(" ");
|
||||
}
|
||||
WriteEscape(cssClass);
|
||||
WriteEscape(classFilter != null ? classFilter(cssClass) : cssClass);
|
||||
}
|
||||
Write("\"");
|
||||
}
|
||||
@@ -284,8 +294,9 @@ namespace Markdig.Renderers
|
||||
/// <param name="leafBlock">The leaf block.</param>
|
||||
/// <param name="writeEndOfLines">if set to <c>true</c> write end of lines.</param>
|
||||
/// <param name="escape">if set to <c>true</c> escape the content for HTML</param>
|
||||
/// <param name="softEscape">Only escape < and &</param>
|
||||
/// <returns>This instance</returns>
|
||||
public HtmlRenderer WriteLeafRawLines(LeafBlock leafBlock, bool writeEndOfLines, bool escape)
|
||||
public HtmlRenderer WriteLeafRawLines(LeafBlock leafBlock, bool writeEndOfLines, bool escape, bool softEscape = false)
|
||||
{
|
||||
if (leafBlock == null) throw new ArgumentNullException(nameof(leafBlock));
|
||||
if (leafBlock.Lines.Lines != null)
|
||||
@@ -300,7 +311,7 @@ namespace Markdig.Renderers
|
||||
}
|
||||
if (escape)
|
||||
{
|
||||
WriteEscape(ref slices[i].Slice);
|
||||
WriteEscape(ref slices[i].Slice, softEscape);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"title": "Markdig",
|
||||
"version": "0.6.2",
|
||||
"version": "0.7.2",
|
||||
"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.6.2\n- Handle latest CommonMark specs for corner cases for emphasis (See https://talk.commonmark.org/t/emphasis-strong-emphasis-corner-cases/2123/1 )\n> 0.6.1:\n- Fix issue with autoidentifier extension overriding manual HTML attributes id on headings\n> 0.6.0\n- Fix conflicts between PipeTables and SmartyPants extensions\n- Add SelfPipeline extension\n",
|
||||
"releaseNotes": "> 0.7.2\n- Fix rendering of table colspan with non english locale\n- Fix grid table colspan parsing\n- Add nofollow extension for links\n> 0.7.1\n- Fix issue in smarty pants which could lead to an InvalidCastException\n- Update parsers to latest CommonMark specs\n>0.7.0\n- Update to latest NETStandard.Library 1.6.0\n- Fix issue with digits in auto-identifier extension\n- Fix incorrect start of span calculated for code indented blocks",
|
||||
"tags": [ "Markdown CommonMark md html md2html" ]
|
||||
},
|
||||
"configurations": {
|
||||
@@ -60,10 +60,7 @@
|
||||
},
|
||||
"netstandard1.1": {
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-24027",
|
||||
"System.Threading": "4.0.11-rc2-24027",
|
||||
"System.Threading.Tasks": "4.0.11-rc2-24027",
|
||||
"System.Threading.Tasks.Parallel": "4.0.1-rc2-24027"
|
||||
"NETStandard.Library": "1.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user