mirror of
https://github.com/xoofx/markdig.git
synced 2026-02-14 13:54:55 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
266e0c8bfd | ||
|
|
f5c07dbab5 | ||
|
|
c8a28a1ad7 | ||
|
|
72cc454314 | ||
|
|
7fe2c1f939 | ||
|
|
087e7a68b6 | ||
|
|
abeabf15a1 | ||
|
|
f9bfcaab7b | ||
|
|
afa0182f02 | ||
|
|
b83de5934d | ||
|
|
c294d3bfb4 | ||
|
|
a7cdb2351a | ||
|
|
46ef21a3ed | ||
|
|
18c8d0178c | ||
|
|
ebc79dafbd | ||
|
|
a1d2467643 | ||
|
|
8220f0fa56 |
@@ -59,9 +59,11 @@
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Specs.tt</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="TestHtmlAttributes.cs" />
|
||||
<Compile Include="TestHtmlHelper.cs" />
|
||||
<Compile Include="TestLineReader.cs" />
|
||||
<Compile Include="TestLinkHelper.cs" />
|
||||
<Compile Include="TestPragmaLines.cs" />
|
||||
<Compile Include="TestSourcePosition.cs" />
|
||||
<Compile Include="TestStringSliceList.cs" />
|
||||
<Compile Include="TestPlayParser.cs" />
|
||||
|
||||
@@ -11,3 +11,11 @@ This is a test with a :) and a :angry: smiley
|
||||
.
|
||||
<p>This is a test with a 😃 and a 😠 smiley</p>
|
||||
````````````````````````````````
|
||||
|
||||
An emoji needs to be preceded by a space and followed by a space:
|
||||
|
||||
```````````````````````````````` example
|
||||
These are not:) an :)emoji with a:) x:angry:x
|
||||
.
|
||||
<p>These are not:) an :)emoji with a:) x:angry:x</p>
|
||||
````````````````````````````````
|
||||
|
||||
@@ -61,3 +61,60 @@ multi-paragraph list items.<a href="#fnref:3" class="footnote-back-ref">↩<
|
||||
</div>
|
||||
````````````````````````````````
|
||||
|
||||
Check with mulitple consecutive footnotes:
|
||||
|
||||
```````````````````````````````` example
|
||||
Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].
|
||||
|
||||
[^1]: Footnote 1 text
|
||||
|
||||
[^2]: Footnote 2 text
|
||||
|
||||
a
|
||||
|
||||
[^3]: Footnote 3 text
|
||||
|
||||
[^4]: Footnote 4 text
|
||||
.
|
||||
<p>Here is a footnote<a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a>. And another one<a id="fnref:2" href="#fn:2" class="footnote-ref"><sup>2</sup></a>. And a third one<a id="fnref:3" href="#fn:3" class="footnote-ref"><sup>3</sup></a>. And a fourth<a id="fnref:4" href="#fn:4" class="footnote-ref"><sup>4</sup></a>.</p>
|
||||
<p>a</p>
|
||||
<div class="footnotes">
|
||||
<hr />
|
||||
<ol>
|
||||
<li id="fn:1">
|
||||
<p>Footnote 1 text<a href="#fnref:1" class="footnote-back-ref">↩</a></p></li>
|
||||
<li id="fn:2">
|
||||
<p>Footnote 2 text<a href="#fnref:2" class="footnote-back-ref">↩</a></p></li>
|
||||
<li id="fn:3">
|
||||
<p>Footnote 3 text<a href="#fnref:3" class="footnote-back-ref">↩</a></p></li>
|
||||
<li id="fn:4">
|
||||
<p>Footnote 4 text<a href="#fnref:4" class="footnote-back-ref">↩</a></p></li>
|
||||
</ol>
|
||||
</div>
|
||||
````````````````````````````````
|
||||
|
||||
Another test with consecutive footnotes without a blank line separator:
|
||||
|
||||
```````````````````````````````` example
|
||||
Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].
|
||||
|
||||
[^1]: Footnote 1 text
|
||||
[^2]: Footnote 2 text
|
||||
[^3]: Footnote 3 text
|
||||
[^4]: Footnote 4 text
|
||||
.
|
||||
<p>Here is a footnote<a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a>. And another one<a id="fnref:2" href="#fn:2" class="footnote-ref"><sup>2</sup></a>. And a third one<a id="fnref:3" href="#fn:3" class="footnote-ref"><sup>3</sup></a>. And a fourth<a id="fnref:4" href="#fn:4" class="footnote-ref"><sup>4</sup></a>.</p>
|
||||
<div class="footnotes">
|
||||
<hr />
|
||||
<ol>
|
||||
<li id="fn:1">
|
||||
<p>Footnote 1 text<a href="#fnref:1" class="footnote-back-ref">↩</a></p></li>
|
||||
<li id="fn:2">
|
||||
<p>Footnote 2 text<a href="#fnref:2" class="footnote-back-ref">↩</a></p></li>
|
||||
<li id="fn:3">
|
||||
<p>Footnote 3 text<a href="#fnref:3" class="footnote-back-ref">↩</a></p></li>
|
||||
<li id="fn:4">
|
||||
<p>Footnote 4 text<a href="#fnref:4" class="footnote-back-ref">↩</a></p></li>
|
||||
</ol>
|
||||
</div>
|
||||
````````````````````````````````
|
||||
|
||||
@@ -83,29 +83,6 @@ They are' not matching 'quotes
|
||||
.
|
||||
<p>They are' not matching 'quotes</p>
|
||||
````````````````````````````````
|
||||
|
||||
Double quotes using ``` `` ``` are working if they match another `''` pair, and there is no other double quotes on the line (otherwise they would be parsed as a code span):
|
||||
|
||||
```````````````````````````````` example
|
||||
This is ``a double quote''
|
||||
.
|
||||
<p>This is “a double quote”</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is ``a code span''``
|
||||
.
|
||||
<p>This is <code>a code span''</code></p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
hello ``there```
|
||||
test
|
||||
.
|
||||
<p>hello “there”`
|
||||
test</p>
|
||||
````````````````````````````````
|
||||
|
||||
An emphasis starting inside left/right quotes will span over the right quote:
|
||||
|
||||
```````````````````````````````` example
|
||||
|
||||
@@ -3811,6 +3811,7 @@ namespace Markdig.Tests
|
||||
// main :: IO ()
|
||||
// main = print $ parseTags tags
|
||||
// </code></pre>
|
||||
// okay
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <pre language="haskell"><code>
|
||||
@@ -3819,9 +3820,10 @@ namespace Markdig.Tests
|
||||
// main :: IO ()
|
||||
// main = print $ parseTags tags
|
||||
// </code></pre>
|
||||
// <p>okay</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 134, "Leaf blocks HTML blocks");
|
||||
TestParser.TestSpec("<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>", "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>", "");
|
||||
TestParser.TestSpec("<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\nokay", "<pre language=\"haskell\"><code>\nimport Text.HTML.TagSoup\n\nmain :: IO ()\nmain = print $ parseTags tags\n</code></pre>\n<p>okay</p>", "");
|
||||
}
|
||||
}
|
||||
// A script tag (type 1):
|
||||
@@ -3840,6 +3842,7 @@ namespace Markdig.Tests
|
||||
//
|
||||
// document.getElementById("demo").innerHTML = "Hello JavaScript!";
|
||||
// </script>
|
||||
// okay
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <script type="text/javascript">
|
||||
@@ -3847,9 +3850,10 @@ namespace Markdig.Tests
|
||||
//
|
||||
// document.getElementById("demo").innerHTML = "Hello JavaScript!";
|
||||
// </script>
|
||||
// <p>okay</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 135, "Leaf blocks HTML blocks");
|
||||
TestParser.TestSpec("<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>", "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>", "");
|
||||
TestParser.TestSpec("<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\nokay", "<script type=\"text/javascript\">\n// JavaScript example\n\ndocument.getElementById(\"demo\").innerHTML = \"Hello JavaScript!\";\n</script>\n<p>okay</p>", "");
|
||||
}
|
||||
}
|
||||
// A style tag (type 1):
|
||||
@@ -3869,6 +3873,7 @@ namespace Markdig.Tests
|
||||
//
|
||||
// p {color:blue;}
|
||||
// </style>
|
||||
// okay
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <style
|
||||
@@ -3877,9 +3882,10 @@ namespace Markdig.Tests
|
||||
//
|
||||
// p {color:blue;}
|
||||
// </style>
|
||||
// <p>okay</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 136, "Leaf blocks HTML blocks");
|
||||
TestParser.TestSpec("<style\n type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>", "<style\n type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>", "");
|
||||
TestParser.TestSpec("<style\n type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\nokay", "<style\n type=\"text/css\">\nh1 {color:red;}\n\np {color:blue;}\n</style>\n<p>okay</p>", "");
|
||||
}
|
||||
}
|
||||
// If there is no matching end tag, the block will end at the
|
||||
@@ -4044,15 +4050,17 @@ namespace Markdig.Tests
|
||||
//
|
||||
// bar
|
||||
// baz -->
|
||||
// okay
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <!-- Foo
|
||||
//
|
||||
// bar
|
||||
// baz -->
|
||||
// <p>okay</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 143, "Leaf blocks HTML blocks");
|
||||
TestParser.TestSpec("<!-- Foo\n\nbar\n baz -->", "<!-- Foo\n\nbar\n baz -->", "");
|
||||
TestParser.TestSpec("<!-- Foo\n\nbar\n baz -->\nokay", "<!-- Foo\n\nbar\n baz -->\n<p>okay</p>", "");
|
||||
}
|
||||
}
|
||||
// A processing instruction (type 3):
|
||||
@@ -4071,6 +4079,7 @@ namespace Markdig.Tests
|
||||
// echo '>';
|
||||
//
|
||||
// ?>
|
||||
// okay
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <?php
|
||||
@@ -4078,9 +4087,10 @@ namespace Markdig.Tests
|
||||
// echo '>';
|
||||
//
|
||||
// ?>
|
||||
// <p>okay</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 144, "Leaf blocks HTML blocks");
|
||||
TestParser.TestSpec("<?php\n\n echo '>';\n\n?>", "<?php\n\n echo '>';\n\n?>", "");
|
||||
TestParser.TestSpec("<?php\n\n echo '>';\n\n?>\nokay", "<?php\n\n echo '>';\n\n?>\n<p>okay</p>", "");
|
||||
}
|
||||
}
|
||||
// A declaration (type 4):
|
||||
@@ -4126,6 +4136,7 @@ namespace Markdig.Tests
|
||||
// }
|
||||
// }
|
||||
// ]]>
|
||||
// okay
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <![CDATA[
|
||||
@@ -4140,9 +4151,10 @@ namespace Markdig.Tests
|
||||
// }
|
||||
// }
|
||||
// ]]>
|
||||
// <p>okay</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 146, "Leaf blocks HTML blocks");
|
||||
TestParser.TestSpec("<![CDATA[\nfunction matchwo(a,b)\n{\n if (a < b && a < 0) then {\n return 1;\n\n } else {\n\n return 0;\n }\n}\n]]>", "<![CDATA[\nfunction matchwo(a,b)\n{\n if (a < b && a < 0) then {\n return 1;\n\n } else {\n\n return 0;\n }\n}\n]]>", "");
|
||||
TestParser.TestSpec("<![CDATA[\nfunction matchwo(a,b)\n{\n if (a < b && a < 0) then {\n return 1;\n\n } else {\n\n return 0;\n }\n}\n]]>\nokay", "<![CDATA[\nfunction matchwo(a,b)\n{\n if (a < b && a < 0) then {\n return 1;\n\n } else {\n\n return 0;\n }\n}\n]]>\n<p>okay</p>", "");
|
||||
}
|
||||
}
|
||||
// The opening tag can be indented 1-3 spaces, but not 4:
|
||||
@@ -5387,8 +5399,8 @@ namespace Markdig.Tests
|
||||
TestParser.TestSpec(" > # Foo\n > bar\n > baz", "<pre><code>> # Foo\n> bar\n> baz\n</code></pre>", "");
|
||||
}
|
||||
}
|
||||
// The Laziness clause allows us to omit the `>` before a
|
||||
// paragraph continuation line:
|
||||
// The Laziness clause allows us to omit the `>` before
|
||||
// [paragraph continuation text]:
|
||||
[TestFixture]
|
||||
public partial class TestContainerblocksBlockquotes
|
||||
{
|
||||
@@ -5561,8 +5573,8 @@ namespace Markdig.Tests
|
||||
TestParser.TestSpec("> ```\nfoo\n```", "<blockquote>\n<pre><code></code></pre>\n</blockquote>\n<p>foo</p>\n<pre><code></code></pre>", "");
|
||||
}
|
||||
}
|
||||
// Note that in the following case, we have a paragraph
|
||||
// continuation line:
|
||||
// Note that in the following case, we have a [lazy
|
||||
// continuation line]:
|
||||
[TestFixture]
|
||||
public partial class TestContainerblocksBlockquotes
|
||||
{
|
||||
@@ -5595,7 +5607,7 @@ namespace Markdig.Tests
|
||||
//
|
||||
// the `- bar` is indented too far to start a list, and can't
|
||||
// be an indented code block because indented code blocks cannot
|
||||
// interrupt paragraphs, so it is a [paragraph continuation line].
|
||||
// interrupt paragraphs, so it is [paragraph continuation text].
|
||||
//
|
||||
// A block quote can be empty:
|
||||
[TestFixture]
|
||||
@@ -7286,6 +7298,7 @@ namespace Markdig.Tests
|
||||
// - foo
|
||||
// - bar
|
||||
// - baz
|
||||
// - boo
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <ul>
|
||||
@@ -7293,7 +7306,11 @@ namespace Markdig.Tests
|
||||
// <ul>
|
||||
// <li>bar
|
||||
// <ul>
|
||||
// <li>baz</li>
|
||||
// <li>baz
|
||||
// <ul>
|
||||
// <li>boo</li>
|
||||
// </ul>
|
||||
// </li>
|
||||
// </ul>
|
||||
// </li>
|
||||
// </ul>
|
||||
@@ -7301,7 +7318,7 @@ namespace Markdig.Tests
|
||||
// </ul>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 254, "Container blocks List items");
|
||||
TestParser.TestSpec("- foo\n - bar\n - baz", "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>", "");
|
||||
TestParser.TestSpec("- foo\n - bar\n - baz\n - boo", "<ul>\n<li>foo\n<ul>\n<li>bar\n<ul>\n<li>baz\n<ul>\n<li>boo</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>", "");
|
||||
}
|
||||
}
|
||||
// One is not enough:
|
||||
@@ -7318,16 +7335,18 @@ namespace Markdig.Tests
|
||||
// - foo
|
||||
// - bar
|
||||
// - baz
|
||||
// - boo
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <ul>
|
||||
// <li>foo</li>
|
||||
// <li>bar</li>
|
||||
// <li>baz</li>
|
||||
// <li>boo</li>
|
||||
// </ul>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 255, "Container blocks List items");
|
||||
TestParser.TestSpec("- foo\n - bar\n - baz", "<ul>\n<li>foo</li>\n<li>bar</li>\n<li>baz</li>\n</ul>", "");
|
||||
TestParser.TestSpec("- foo\n - bar\n - baz\n - boo", "<ul>\n<li>foo</li>\n<li>bar</li>\n<li>baz</li>\n<li>boo</li>\n</ul>", "");
|
||||
}
|
||||
}
|
||||
// Here we need four, because the list marker is wider:
|
||||
@@ -13868,7 +13887,7 @@ namespace Markdig.Tests
|
||||
// [link reference definition] elsewhere in the
|
||||
// document and is not followed by `[]` or a link label.
|
||||
// The contents of the first link label are parsed as inlines,
|
||||
// which are used as the link's text. the link's URI and title
|
||||
// which are used as the link's text. The link's URI and title
|
||||
// are provided by the matching link reference definition.
|
||||
// Thus, `[foo]` is equivalent to `[foo][]`.
|
||||
[TestFixture]
|
||||
@@ -17103,6 +17122,88 @@ namespace Markdig.Tests
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 1, "Extensions Footontes");
|
||||
TestParser.TestSpec("Here is a footnote reference,[^1] and another.[^longnote]\n\nThis is another reference to [^1]\n\n[^1]: Here is the footnote.\n\nAnd another reference to [^longnote]\n\n[^longnote]: Here's one with multiple blocks.\n\n Subsequent paragraphs are indented to show that they\nbelong to the previous footnote.\n\n > This is a block quote\n > Inside a footnote\n\n { some.code }\n\n The whole paragraph can be indented, or just the first\n line. In this way, multi-paragraph footnotes work like\n multi-paragraph list items.\n\nThis paragraph won't be part of the note, because it\nisn't indented.", "<p>Here is a footnote reference,<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a> and another.<a id=\"fnref:3\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a></p>\n<p>This is another reference to <a id=\"fnref:2\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a></p>\n<p>And another reference to <a id=\"fnref:4\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a></p>\n<p>This paragraph won't be part of the note, because it\nisn't indented.</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Here is the footnote.<a href=\"#fnref:1\" class=\"footnote-back-ref\">↩</a><a href=\"#fnref:2\" class=\"footnote-back-ref\">↩</a></p>\n</li>\n<li id=\"fn:2\">\n<p>Here's one with multiple blocks.</p>\n<p>Subsequent paragraphs are indented to show that they\nbelong to the previous footnote.</p>\n<blockquote>\n<p>This is a block quote\nInside a footnote</p>\n</blockquote>\n<pre><code>{ some.code }\n</code></pre>\n<p>The whole paragraph can be indented, or just the first\nline. In this way, multi-paragraph footnotes work like\nmulti-paragraph list items.<a href=\"#fnref:3\" class=\"footnote-back-ref\">↩</a><a href=\"#fnref:4\" class=\"footnote-back-ref\">↩</a></p>\n</li>\n</ol>\n</div>", "footnotes");
|
||||
}
|
||||
}
|
||||
// Check with mulitple consecutive footnotes:
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsFootontes
|
||||
{
|
||||
[Test]
|
||||
public void Example002()
|
||||
{
|
||||
// Example 2
|
||||
// Section: Extensions Footontes
|
||||
//
|
||||
// The following CommonMark:
|
||||
// Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].
|
||||
//
|
||||
// [^1]: Footnote 1 text
|
||||
//
|
||||
// [^2]: Footnote 2 text
|
||||
//
|
||||
// a
|
||||
//
|
||||
// [^3]: Footnote 3 text
|
||||
//
|
||||
// [^4]: Footnote 4 text
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>Here is a footnote<a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a>. And another one<a id="fnref:2" href="#fn:2" class="footnote-ref"><sup>2</sup></a>. And a third one<a id="fnref:3" href="#fn:3" class="footnote-ref"><sup>3</sup></a>. And a fourth<a id="fnref:4" href="#fn:4" class="footnote-ref"><sup>4</sup></a>.</p>
|
||||
// <p>a</p>
|
||||
// <div class="footnotes">
|
||||
// <hr />
|
||||
// <ol>
|
||||
// <li id="fn:1">
|
||||
// <p>Footnote 1 text<a href="#fnref:1" class="footnote-back-ref">↩</a></p></li>
|
||||
// <li id="fn:2">
|
||||
// <p>Footnote 2 text<a href="#fnref:2" class="footnote-back-ref">↩</a></p></li>
|
||||
// <li id="fn:3">
|
||||
// <p>Footnote 3 text<a href="#fnref:3" class="footnote-back-ref">↩</a></p></li>
|
||||
// <li id="fn:4">
|
||||
// <p>Footnote 4 text<a href="#fnref:4" class="footnote-back-ref">↩</a></p></li>
|
||||
// </ol>
|
||||
// </div>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 2, "Extensions Footontes");
|
||||
TestParser.TestSpec("Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].\n\n[^1]: Footnote 1 text\n\n[^2]: Footnote 2 text\n\na\n\n[^3]: Footnote 3 text\n\n[^4]: Footnote 4 text", "<p>Here is a footnote<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a>. And another one<a id=\"fnref:2\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a>. And a third one<a id=\"fnref:3\" href=\"#fn:3\" class=\"footnote-ref\"><sup>3</sup></a>. And a fourth<a id=\"fnref:4\" href=\"#fn:4\" class=\"footnote-ref\"><sup>4</sup></a>.</p>\n<p>a</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Footnote 1 text<a href=\"#fnref:1\" class=\"footnote-back-ref\">↩</a></p></li>\n<li id=\"fn:2\">\n<p>Footnote 2 text<a href=\"#fnref:2\" class=\"footnote-back-ref\">↩</a></p></li>\n<li id=\"fn:3\">\n<p>Footnote 3 text<a href=\"#fnref:3\" class=\"footnote-back-ref\">↩</a></p></li>\n<li id=\"fn:4\">\n<p>Footnote 4 text<a href=\"#fnref:4\" class=\"footnote-back-ref\">↩</a></p></li>\n</ol>\n</div>", "footnotes");
|
||||
}
|
||||
}
|
||||
// Another test with consecutive footnotes without a blank line separator:
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsFootontes
|
||||
{
|
||||
[Test]
|
||||
public void Example003()
|
||||
{
|
||||
// Example 3
|
||||
// Section: Extensions Footontes
|
||||
//
|
||||
// The following CommonMark:
|
||||
// Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].
|
||||
//
|
||||
// [^1]: Footnote 1 text
|
||||
// [^2]: Footnote 2 text
|
||||
// [^3]: Footnote 3 text
|
||||
// [^4]: Footnote 4 text
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>Here is a footnote<a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a>. And another one<a id="fnref:2" href="#fn:2" class="footnote-ref"><sup>2</sup></a>. And a third one<a id="fnref:3" href="#fn:3" class="footnote-ref"><sup>3</sup></a>. And a fourth<a id="fnref:4" href="#fn:4" class="footnote-ref"><sup>4</sup></a>.</p>
|
||||
// <div class="footnotes">
|
||||
// <hr />
|
||||
// <ol>
|
||||
// <li id="fn:1">
|
||||
// <p>Footnote 1 text<a href="#fnref:1" class="footnote-back-ref">↩</a></p></li>
|
||||
// <li id="fn:2">
|
||||
// <p>Footnote 2 text<a href="#fnref:2" class="footnote-back-ref">↩</a></p></li>
|
||||
// <li id="fn:3">
|
||||
// <p>Footnote 3 text<a href="#fnref:3" class="footnote-back-ref">↩</a></p></li>
|
||||
// <li id="fn:4">
|
||||
// <p>Footnote 4 text<a href="#fnref:4" class="footnote-back-ref">↩</a></p></li>
|
||||
// </ol>
|
||||
// </div>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 3, "Extensions Footontes");
|
||||
TestParser.TestSpec("Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].\n\n[^1]: Footnote 1 text\n[^2]: Footnote 2 text\n[^3]: Footnote 3 text\n[^4]: Footnote 4 text", "<p>Here is a footnote<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a>. And another one<a id=\"fnref:2\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a>. And a third one<a id=\"fnref:3\" href=\"#fn:3\" class=\"footnote-ref\"><sup>3</sup></a>. And a fourth<a id=\"fnref:4\" href=\"#fn:4\" class=\"footnote-ref\"><sup>4</sup></a>.</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Footnote 1 text<a href=\"#fnref:1\" class=\"footnote-back-ref\">↩</a></p></li>\n<li id=\"fn:2\">\n<p>Footnote 2 text<a href=\"#fnref:2\" class=\"footnote-back-ref\">↩</a></p></li>\n<li id=\"fn:3\">\n<p>Footnote 3 text<a href=\"#fnref:3\" class=\"footnote-back-ref\">↩</a></p></li>\n<li id=\"fn:4\">\n<p>Footnote 4 text<a href=\"#fnref:4\" class=\"footnote-back-ref\">↩</a></p></li>\n</ol>\n</div>", "footnotes");
|
||||
}
|
||||
}
|
||||
// # Extensions
|
||||
//
|
||||
@@ -17978,6 +18079,26 @@ namespace Markdig.Tests
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 1, "Extensions Emoji");
|
||||
TestParser.TestSpec("This is a test with a :) and a :angry: smiley", "<p>This is a test with a 😃 and a 😠 smiley</p>", "emojis");
|
||||
}
|
||||
}
|
||||
// An emoji needs to be preceded by a space and followed by a space:
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsEmoji
|
||||
{
|
||||
[Test]
|
||||
public void Example002()
|
||||
{
|
||||
// Example 2
|
||||
// Section: Extensions Emoji
|
||||
//
|
||||
// The following CommonMark:
|
||||
// These are not:) an :)emoji with a:) x:angry:x
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>These are not:) an :)emoji with a:) x:angry:x</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 2, "Extensions Emoji");
|
||||
TestParser.TestSpec("These are not:) an :)emoji with a:) x:angry:x", "<p>These are not:) an :)emoji with a:) x:angry:x</p>", "emojis");
|
||||
}
|
||||
}
|
||||
// # Extensions
|
||||
//
|
||||
@@ -18937,7 +19058,7 @@ namespace Markdig.Tests
|
||||
TestParser.TestSpec("They are' not matching 'quotes", "<p>They are' not matching 'quotes</p>", "smartypants");
|
||||
}
|
||||
}
|
||||
// Double quotes using ``` `` ``` are working if they match another `''` pair, and there is no other double quotes on the line (otherwise they would be parsed as a code span):
|
||||
// An emphasis starting inside left/right quotes will span over the right quote:
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsSmartyPantsQuotes
|
||||
{
|
||||
@@ -18948,72 +19069,12 @@ namespace Markdig.Tests
|
||||
// Section: Extensions SmartyPants Quotes
|
||||
//
|
||||
// The following CommonMark:
|
||||
// This is ``a double quote''
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is “a double quote”</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 13, "Extensions SmartyPants Quotes");
|
||||
TestParser.TestSpec("This is ``a double quote''", "<p>This is “a double quote”</p>", "smartypants");
|
||||
}
|
||||
}
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsSmartyPantsQuotes
|
||||
{
|
||||
[Test]
|
||||
public void Example014()
|
||||
{
|
||||
// Example 14
|
||||
// Section: Extensions SmartyPants Quotes
|
||||
//
|
||||
// The following CommonMark:
|
||||
// This is ``a code span''``
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is <code>a code span''</code></p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 14, "Extensions SmartyPants Quotes");
|
||||
TestParser.TestSpec("This is ``a code span''`` ", "<p>This is <code>a code span''</code></p>", "smartypants");
|
||||
}
|
||||
}
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsSmartyPantsQuotes
|
||||
{
|
||||
[Test]
|
||||
public void Example015()
|
||||
{
|
||||
// Example 15
|
||||
// Section: Extensions SmartyPants Quotes
|
||||
//
|
||||
// The following CommonMark:
|
||||
// hello ``there```
|
||||
// test
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>hello “there”`
|
||||
// test</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 15, "Extensions SmartyPants Quotes");
|
||||
TestParser.TestSpec("hello ``there```\ntest", "<p>hello “there”`\ntest</p>", "smartypants");
|
||||
}
|
||||
}
|
||||
// An emphasis starting inside left/right quotes will span over the right quote:
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsSmartyPantsQuotes
|
||||
{
|
||||
[Test]
|
||||
public void Example016()
|
||||
{
|
||||
// Example 16
|
||||
// Section: Extensions SmartyPants Quotes
|
||||
//
|
||||
// The following CommonMark:
|
||||
// This is "a *text" with an emphasis*
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is “a <em>text” with an emphasis</em></p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 16, "Extensions SmartyPants Quotes");
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 13, "Extensions SmartyPants Quotes");
|
||||
TestParser.TestSpec("This is \"a *text\" with an emphasis*", "<p>This is “a <em>text” with an emphasis</em></p>", "smartypants");
|
||||
}
|
||||
}
|
||||
@@ -19022,9 +19083,9 @@ namespace Markdig.Tests
|
||||
public partial class TestExtensionsSmartyPantsSeparators
|
||||
{
|
||||
[Test]
|
||||
public void Example017()
|
||||
public void Example014()
|
||||
{
|
||||
// Example 17
|
||||
// Example 14
|
||||
// Section: Extensions SmartyPants Separators
|
||||
//
|
||||
// The following CommonMark:
|
||||
@@ -19033,7 +19094,7 @@ namespace Markdig.Tests
|
||||
// Should be rendered as:
|
||||
// <p>This is a – text</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 17, "Extensions SmartyPants Separators");
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 14, "Extensions SmartyPants Separators");
|
||||
TestParser.TestSpec("This is a -- text", "<p>This is a – text</p>", "smartypants");
|
||||
}
|
||||
}
|
||||
@@ -19041,9 +19102,9 @@ namespace Markdig.Tests
|
||||
public partial class TestExtensionsSmartyPantsSeparators
|
||||
{
|
||||
[Test]
|
||||
public void Example018()
|
||||
public void Example015()
|
||||
{
|
||||
// Example 18
|
||||
// Example 15
|
||||
// Section: Extensions SmartyPants Separators
|
||||
//
|
||||
// The following CommonMark:
|
||||
@@ -19052,7 +19113,7 @@ namespace Markdig.Tests
|
||||
// Should be rendered as:
|
||||
// <p>This is a — text</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 18, "Extensions SmartyPants Separators");
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 15, "Extensions SmartyPants Separators");
|
||||
TestParser.TestSpec("This is a --- text", "<p>This is a — text</p>", "smartypants");
|
||||
}
|
||||
}
|
||||
@@ -19060,9 +19121,9 @@ namespace Markdig.Tests
|
||||
public partial class TestExtensionsSmartyPantsSeparators
|
||||
{
|
||||
[Test]
|
||||
public void Example019()
|
||||
public void Example016()
|
||||
{
|
||||
// Example 19
|
||||
// Example 16
|
||||
// Section: Extensions SmartyPants Separators
|
||||
//
|
||||
// The following CommonMark:
|
||||
@@ -19071,7 +19132,7 @@ namespace Markdig.Tests
|
||||
// Should be rendered as:
|
||||
// <p>This is a en ellipsis…</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 19, "Extensions SmartyPants Separators");
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 16, "Extensions SmartyPants Separators");
|
||||
TestParser.TestSpec("This is a en ellipsis...", "<p>This is a en ellipsis…</p>", "smartypants");
|
||||
}
|
||||
}
|
||||
|
||||
96
src/Markdig.Tests/TestHtmlAttributes.cs
Normal file
96
src/Markdig.Tests/TestHtmlAttributes.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
// 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.Html;
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture()]
|
||||
public class TestHtmlAttributes
|
||||
{
|
||||
[Test]
|
||||
public void TestAddClass()
|
||||
{
|
||||
var attributes = new HtmlAttributes();
|
||||
attributes.AddClass("test");
|
||||
Assert.NotNull(attributes.Classes);
|
||||
Assert.AreEqual(new List<string>() { "test" }, attributes.Classes);
|
||||
|
||||
attributes.AddClass("test");
|
||||
Assert.AreEqual(1, attributes.Classes.Count);
|
||||
|
||||
attributes.AddClass("test1");
|
||||
Assert.AreEqual(new List<string>() { "test", "test1" }, attributes.Classes);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddProperty()
|
||||
{
|
||||
var attributes = new HtmlAttributes();
|
||||
attributes.AddProperty("key1", "1");
|
||||
Assert.NotNull(attributes.Properties);
|
||||
Assert.AreEqual(new List<KeyValuePair<string, string>>() { new KeyValuePair<string, string>("key1", "1") }, attributes.Properties);
|
||||
|
||||
attributes.AddPropertyIfNotExist("key1", "1");
|
||||
Assert.NotNull(attributes.Properties);
|
||||
Assert.AreEqual(new List<KeyValuePair<string, string>>() { new KeyValuePair<string, string>("key1", "1") }, attributes.Properties);
|
||||
|
||||
attributes.AddPropertyIfNotExist("key2", "2");
|
||||
Assert.AreEqual(new List<KeyValuePair<string, string>>() { new KeyValuePair<string, string>("key1", "1"), new KeyValuePair<string, string>("key2", "2") }, attributes.Properties);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCopyTo()
|
||||
{
|
||||
var from = new HtmlAttributes();
|
||||
from.AddClass("test");
|
||||
from.AddProperty("key1", "1");
|
||||
|
||||
var to = new HtmlAttributes();
|
||||
from.CopyTo(to);
|
||||
|
||||
Assert.True(ReferenceEquals(from.Classes, to.Classes));
|
||||
Assert.True(ReferenceEquals(from.Properties, to.Properties));
|
||||
|
||||
// From: Classes From: Properties To: Classes To: Properties
|
||||
// test1: null null null null
|
||||
from = new HtmlAttributes();
|
||||
to = new HtmlAttributes();
|
||||
from.CopyTo(to, false, false);
|
||||
Assert.Null(to.Classes);
|
||||
Assert.Null(to.Properties);
|
||||
|
||||
// test2: ["test"] ["key1", "1"] null null
|
||||
from = new HtmlAttributes();
|
||||
to = new HtmlAttributes();
|
||||
from.AddClass("test");
|
||||
from.AddProperty("key1", "1");
|
||||
from.CopyTo(to, false, false);
|
||||
Assert.AreEqual(new List<string>() { "test" }, to.Classes);
|
||||
Assert.AreEqual(new List<KeyValuePair<string, string>>() { new KeyValuePair<string, string>("key1", "1")}, to.Properties);
|
||||
|
||||
// test3: null null ["test"] ["key1", "1"]
|
||||
from = new HtmlAttributes();
|
||||
to = new HtmlAttributes();
|
||||
to.AddClass("test");
|
||||
to.AddProperty("key1", "1");
|
||||
from.CopyTo(to, false, false);
|
||||
Assert.AreEqual(new List<string>() { "test" }, to.Classes);
|
||||
Assert.AreEqual(new List<KeyValuePair<string, string>>() { new KeyValuePair<string, string>("key1", "1") }, to.Properties);
|
||||
|
||||
// test4: ["test1"] ["key2", "2"] ["test"] ["key1", "1"]
|
||||
from = new HtmlAttributes();
|
||||
to = new HtmlAttributes();
|
||||
from.AddClass("test1");
|
||||
from.AddProperty("key2", "2");
|
||||
to.AddClass("test");
|
||||
to.AddProperty("key1", "1");
|
||||
from.CopyTo(to, false, false);
|
||||
Assert.AreEqual(new List<string>() { "test", "test1" }, to.Classes);
|
||||
Assert.AreEqual(new List<KeyValuePair<string, string>>() { new KeyValuePair<string, string>("key1", "1"), new KeyValuePair<string, string>("key2", "2") }, to.Properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ namespace Markdig.Tests
|
||||
private static string Compact(string html)
|
||||
{
|
||||
// Normalize the output to make it compatible with CommonMark specs
|
||||
html = html.Replace("\r", "").Trim();
|
||||
html = html.Replace("\r\n", "\n").Replace(@"\r", @"\n").Trim();
|
||||
html = Regex.Replace(html, @"\s+</li>", "</li>");
|
||||
html = Regex.Replace(html, @"<li>\s+", "<li>");
|
||||
html = html.Normalize(NormalizationForm.FormKD);
|
||||
|
||||
@@ -27,6 +27,49 @@ Later in a text we are using HTML and it becomes an abbr tag HTML
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestListBug()
|
||||
{
|
||||
// TODO: Add this test back to the CommonMark specs
|
||||
var text = @"- item1
|
||||
- item2
|
||||
- item3
|
||||
- item4";
|
||||
TestParser.TestSpec(text, @"<ul>
|
||||
<li>item1
|
||||
<ul>
|
||||
<li>item2
|
||||
<ul>
|
||||
<li>item3
|
||||
<ul>
|
||||
<li>item4</li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestHtmlBug()
|
||||
{
|
||||
TestParser.TestSpec(@" # header1
|
||||
|
||||
<pre class='copy'>
|
||||
blabla
|
||||
</pre>
|
||||
|
||||
# header2
|
||||
", @"<h1>header1</h1>
|
||||
<pre class='copy'>
|
||||
blabla
|
||||
</pre>
|
||||
<h1>header2</h1>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestBugAdvancaed()
|
||||
{
|
||||
|
||||
81
src/Markdig.Tests/TestPragmaLines.cs
Normal file
81
src/Markdig.Tests/TestPragmaLines.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
// 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;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestPragmaLines
|
||||
{
|
||||
[Test]
|
||||
public void TestFindClosest()
|
||||
{
|
||||
var doc = Markdown.Parse(
|
||||
"test1\n" + // 0
|
||||
"\n" + // 1
|
||||
"test2\n" + // 2
|
||||
"\n" + // 3
|
||||
"test3\n" + // 4
|
||||
"\n" + // 5
|
||||
"test4\n" + // 6
|
||||
"\n" + // 7
|
||||
"# Heading\n" + // 8
|
||||
"\n" + // 9
|
||||
"Long para\n" + // 10
|
||||
"on multiple\n" + // 11
|
||||
"lines\n" + // 12
|
||||
"to check that\n" + // 13
|
||||
"lines are\n" + // 14
|
||||
"correctly \n" + // 15
|
||||
"found\n" + // 16
|
||||
"\n" + // 17
|
||||
"- item1\n" + // 18
|
||||
"- item2\n" + // 19
|
||||
"- item3\n" + // 20
|
||||
"\n" + // 21
|
||||
"This is a last paragraph\n" // 22
|
||||
, new MarkdownPipelineBuilder().UsePragmaLines().Build());
|
||||
|
||||
foreach (var exact in new int[] {0, 2, 4, 6, 8, 10, 18, 19, 20, 22})
|
||||
{
|
||||
Assert.AreEqual(exact, doc.FindClosestLine(exact));
|
||||
}
|
||||
|
||||
Assert.AreEqual(22, doc.FindClosestLine(23));
|
||||
|
||||
Assert.AreEqual(10, doc.FindClosestLine(11));
|
||||
Assert.AreEqual(10, doc.FindClosestLine(12));
|
||||
Assert.AreEqual(10, doc.FindClosestLine(13));
|
||||
Assert.AreEqual(18, doc.FindClosestLine(14)); // > 50% of the paragraph, we switch to next
|
||||
Assert.AreEqual(18, doc.FindClosestLine(15));
|
||||
Assert.AreEqual(18, doc.FindClosestLine(16));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFindClosest1()
|
||||
{
|
||||
var text =
|
||||
"- item1\n" + // 0
|
||||
" - item11\n" + // 1
|
||||
" - item12\n" + // 2
|
||||
" - item121\n" + // 3
|
||||
" - item13\n" + // 4
|
||||
" - item131\n" + // 5
|
||||
" - item1311\n"; // 6
|
||||
|
||||
var pipeline = new MarkdownPipelineBuilder().UsePragmaLines().Build();
|
||||
var doc = Markdown.Parse(text, pipeline);
|
||||
|
||||
for (int exact = 0; exact < 7; exact++)
|
||||
{
|
||||
Assert.AreEqual(exact, doc.FindClosestLine(exact));
|
||||
}
|
||||
|
||||
Assert.AreEqual(6, doc.FindClosestLine(50));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,18 +67,34 @@ namespace Markdig.Extensions.Emoji
|
||||
public override bool Match(InlineProcessor processor, ref StringSlice slice)
|
||||
{
|
||||
string match;
|
||||
|
||||
// Previous char must be a space
|
||||
if (!slice.PeekCharExtra(-1).IsWhiteSpaceOrZero())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to match an existing emoji
|
||||
var startPosition = slice.Start;
|
||||
if (!textMatchHelper.TryMatch(slice.Text, slice.Start, slice.Length, out match))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Following char must be a space
|
||||
if (!slice.PeekCharExtra(match.Length).IsWhiteSpaceOrZero())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we have a smiley, we decode it to emoji
|
||||
string emoji;
|
||||
if (!SmileyToEmoji.TryGetValue(match, out emoji))
|
||||
{
|
||||
emoji = match;
|
||||
}
|
||||
|
||||
// Decode the eomji to unicode
|
||||
string unicode;
|
||||
if (!EmojiToUnicode.TryGetValue(emoji, out unicode))
|
||||
{
|
||||
|
||||
@@ -26,9 +26,14 @@ namespace Markdig.Extensions.Footnotes
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
{
|
||||
return TryOpen(processor, false);
|
||||
}
|
||||
|
||||
private BlockState TryOpen(BlockProcessor processor, bool isContinue)
|
||||
{
|
||||
// We expect footnote to appear only at document level and not indented more than a code indent block
|
||||
if (processor.IsCodeIndent || processor.CurrentContainer.GetType() != typeof(MarkdownDocument) )
|
||||
if (processor.IsCodeIndent || (!isContinue && processor.CurrentContainer.GetType() != typeof(MarkdownDocument)) || (isContinue && !(processor.CurrentContainer is Footnote)))
|
||||
{
|
||||
return BlockState.None;
|
||||
}
|
||||
@@ -42,7 +47,7 @@ namespace Markdig.Extensions.Footnotes
|
||||
processor.GoToColumn(saved);
|
||||
return BlockState.None;
|
||||
}
|
||||
|
||||
|
||||
// Advance the column
|
||||
int deltaColumn = processor.Start - start;
|
||||
processor.Column = processor.Column + deltaColumn;
|
||||
@@ -88,9 +93,23 @@ namespace Markdig.Extensions.Footnotes
|
||||
return BlockState.ContinueDiscard;
|
||||
}
|
||||
|
||||
if (footnote.IsLastLineEmpty && processor.Column == 0)
|
||||
if (processor.Column == 0)
|
||||
{
|
||||
return BlockState.Break;
|
||||
if (footnote.IsLastLineEmpty)
|
||||
{
|
||||
// Close the current footnote
|
||||
processor.Close(footnote);
|
||||
|
||||
// Parse any opening footnote
|
||||
return TryOpen(processor);
|
||||
}
|
||||
|
||||
// Make sure that consecutive footnotes without a blanklines are parsed correctly
|
||||
if (TryOpen(processor, true) == BlockState.Continue)
|
||||
{
|
||||
processor.Close(footnote);
|
||||
return BlockState.Continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
footnote.IsLastLineEmpty = false;
|
||||
|
||||
@@ -28,10 +28,10 @@ namespace Markdig.Extensions.SmartyPants
|
||||
|
||||
public void Setup(MarkdownPipelineBuilder pipeline)
|
||||
{
|
||||
if (!pipeline.InlineParsers.Contains<SmaryPantsInlineParser>())
|
||||
if (!pipeline.InlineParsers.Contains<SmartyPantsInlineParser>())
|
||||
{
|
||||
// Insert the parser after the code span parser
|
||||
pipeline.InlineParsers.InsertAfter<CodeInlineParser>(new SmaryPantsInlineParser());
|
||||
pipeline.InlineParsers.InsertAfter<CodeInlineParser>(new SmartyPantsInlineParser());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ namespace Markdig.Extensions.SmartyPants
|
||||
/// <summary>
|
||||
/// The inline parser for SmartyPants.
|
||||
/// </summary>
|
||||
public class SmaryPantsInlineParser : InlineParser
|
||||
public class SmartyPantsInlineParser : InlineParser
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SmaryPantsInlineParser"/> class.
|
||||
/// Initializes a new instance of the <see cref="SmartyPantsInlineParser"/> class.
|
||||
/// </summary>
|
||||
public SmaryPantsInlineParser()
|
||||
public SmartyPantsInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'`', '\'', '"', '<', '>', '.', '-'};
|
||||
OpeningCharacters = new[] {'\'', '"', '<', '>', '.', '-'};
|
||||
}
|
||||
|
||||
public override bool Match(InlineProcessor processor, ref StringSlice slice)
|
||||
@@ -44,13 +44,6 @@ namespace Markdig.Extensions.SmartyPants
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '`':
|
||||
if (slice.PeekChar(1) == '`')
|
||||
{
|
||||
slice.NextChar();
|
||||
type = SmartyPantType.DoubleQuote; // We will resolve them at the end of parsing all inlines
|
||||
}
|
||||
break;
|
||||
case '\'':
|
||||
type = SmartyPantType.Quote; // We will resolve them at the end of parsing all inlines
|
||||
if (slice.PeekChar(1) == '\'')
|
||||
@@ -101,19 +101,5 @@ namespace Markdig.Helpers
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ReplacyBy<TElement>(T element) where TElement : T
|
||||
{
|
||||
if (element == null) throw new ArgumentNullException(nameof(element));
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (this[i] is TElement)
|
||||
{
|
||||
this[i] = element;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,7 +249,7 @@ namespace Markdig.Helpers
|
||||
endOfIndex = 0;
|
||||
for (int i = Start; i <= end; i++)
|
||||
{
|
||||
if (MatchLowercase(text, End, i))
|
||||
if (MatchLowercase(text, End, i - Start))
|
||||
{
|
||||
endOfIndex = i + text.Length;
|
||||
return true;
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Markdig
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses the boostrap extension.
|
||||
/// Uses the bootstrap extension.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline.</param>
|
||||
/// <returns>The modified pipeline</returns>
|
||||
@@ -442,4 +442,4 @@ namespace Markdig
|
||||
return pipeline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace Markdig.Parsers
|
||||
{
|
||||
if (state.Indent > columWidth && state.IsCodeIndent)
|
||||
{
|
||||
state.GoToColumn(columWidth);
|
||||
state.GoToColumn(state.ColumnBeforeIndent + columWidth);
|
||||
}
|
||||
|
||||
// Update list-item source end position
|
||||
|
||||
@@ -25,6 +25,6 @@ namespace Markdig
|
||||
{
|
||||
public static partial class Markdown
|
||||
{
|
||||
public const string Version = "0.5.8";
|
||||
public const string Version = "0.5.12";
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ namespace Markdig.Renderers.Html
|
||||
}
|
||||
if (htmlAttributes.Classes == null)
|
||||
{
|
||||
htmlAttributes.Classes = shared ? Classes : new List<string>(Classes);
|
||||
htmlAttributes.Classes = shared ? Classes : Classes != null ? new List<string>(Classes) : null;
|
||||
}
|
||||
else if (Classes != null)
|
||||
{
|
||||
@@ -127,7 +127,7 @@ namespace Markdig.Renderers.Html
|
||||
|
||||
if (htmlAttributes.Properties == null)
|
||||
{
|
||||
htmlAttributes.Properties = shared ? Properties : new List<KeyValuePair<string, string>>(Properties);
|
||||
htmlAttributes.Properties = shared ? Properties : Properties != null ? new List<KeyValuePair<string, string>>(Properties) : null;
|
||||
}
|
||||
else if (Properties != null)
|
||||
{
|
||||
|
||||
@@ -53,10 +53,6 @@ namespace Markdig.Syntax
|
||||
|
||||
public static int FindClosestLine(this MarkdownDocument root, int line)
|
||||
{
|
||||
// Forces the preview window to scroll to the top of the document
|
||||
if (line <= 3)
|
||||
return 0;
|
||||
|
||||
var closestBlock = root.FindClosestBlock(line);
|
||||
return closestBlock?.Line ?? 0;
|
||||
}
|
||||
@@ -89,7 +85,7 @@ namespace Markdig.Syntax
|
||||
}
|
||||
|
||||
// If we are between two lines, try to find the best spot
|
||||
if (lowerIndex >= 0 && lowerIndex < blocks.Count)
|
||||
if (lowerIndex > 0 && lowerIndex < blocks.Count)
|
||||
{
|
||||
var prevBlock = blocks[lowerIndex - 1].FindClosestBlock(line) ?? blocks[lowerIndex - 1];
|
||||
var nextBlock = blocks[lowerIndex].FindClosestBlock(line) ?? blocks[lowerIndex];
|
||||
@@ -113,6 +109,18 @@ namespace Markdig.Syntax
|
||||
return middle < 0.5 ? prevBlock : nextBlock;
|
||||
}
|
||||
|
||||
if (lowerIndex == 0)
|
||||
{
|
||||
var prevBlock = blocks[lowerIndex].FindClosestBlock(line) ?? blocks[lowerIndex];
|
||||
return prevBlock;
|
||||
}
|
||||
|
||||
if (lowerIndex == blocks.Count)
|
||||
{
|
||||
var prevBlock = blocks[lowerIndex - 1].FindClosestBlock(line) ?? blocks[lowerIndex - 1];
|
||||
return prevBlock;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"title": "Markdig",
|
||||
"version": "0.5.8",
|
||||
"version": "0.5.12",
|
||||
"authors": [ "Alexandre Mutel" ],
|
||||
"description": "A fast, powerfull, CommonMark compliant, extensible Markdown processor for .NET",
|
||||
"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.5.8\n- Fix calculation of spans for nested blocks\n- Add methods for looking for a block from a position or for the closest line (typically used for syntax highlighting by MarkdownEditor)\n> 0.5.7\n- Fix issue with generic attributes extension not working properly and breaking parsing\n> 0.5.6\n- Improve pragma line output\n- Make MarkdownPipeline.Setup(renderer) public.\n> 0.5.5\n- Add same github class for task lists\n- Add pragma lines extension\n> 0.5.4:\nFix bug in HTML block parsing which could break parsing of remaining document",
|
||||
"releaseNotes": "- Fix ArgumentNullException with MediaLinks extension in HtmlAttributes.CopyTo method\n",
|
||||
"tags": [ "Markdown CommonMark md html md2html" ]
|
||||
},
|
||||
"configurations": {
|
||||
|
||||
Reference in New Issue
Block a user