mirror of
https://github.com/xoofx/markdig.git
synced 2026-02-08 21:37:02 +00:00
Compare commits
226 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64875c3dd9 | ||
|
|
4c92fe5a3b | ||
|
|
27f625f15b | ||
|
|
aca085703e | ||
|
|
8aa0948b20 | ||
|
|
8ce6f4d9ad | ||
|
|
3a47a5115a | ||
|
|
a8737e8481 | ||
|
|
f56b8e6ba7 | ||
|
|
0a0040450f | ||
|
|
fb12be5ab0 | ||
|
|
2277596e2e | ||
|
|
a10f6f6b8c | ||
|
|
203cfd6508 | ||
|
|
5fefcbb5b3 | ||
|
|
7ad7b55c48 | ||
|
|
e9ea103e32 | ||
|
|
c680910828 | ||
|
|
4526d886c8 | ||
|
|
397de86e2f | ||
|
|
f985750b82 | ||
|
|
00c175a79c | ||
|
|
6204095261 | ||
|
|
63fddf4511 | ||
|
|
c964659085 | ||
|
|
eabfe74e92 | ||
|
|
bd1dcd952c | ||
|
|
54e2514778 | ||
|
|
4b7a4d21de | ||
|
|
6b1399ba23 | ||
|
|
07467d6c30 | ||
|
|
2f9588498c | ||
|
|
80ed85e2a8 | ||
|
|
b2306db388 | ||
|
|
8db238797b | ||
|
|
780e16a9c9 | ||
|
|
8fdc0d59d7 | ||
|
|
f1cd0cb1b8 | ||
|
|
a724783e3f | ||
|
|
1c862a1e07 | ||
|
|
35d3160ad2 | ||
|
|
e0a2f9e52d | ||
|
|
c9ba236dbc | ||
|
|
0c9b5dddc9 | ||
|
|
bd2bb98631 | ||
|
|
da0ba34165 | ||
|
|
51c5bec315 | ||
|
|
13bdab4570 | ||
|
|
6b9433c7d8 | ||
|
|
eedbb494fc | ||
|
|
9d36a74312 | ||
|
|
4009c89321 | ||
|
|
6b433d9352 | ||
|
|
f6e6001d94 | ||
|
|
1474b7b29a | ||
|
|
61b29b6d41 | ||
|
|
6684c8257c | ||
|
|
247cd92926 | ||
|
|
404a94f284 | ||
|
|
1cc8a40473 | ||
|
|
dc4968d5ab | ||
|
|
b2b36038ff | ||
|
|
4a57035aec | ||
|
|
1752178631 | ||
|
|
39c05f34d1 | ||
|
|
640196a18f | ||
|
|
4f9119fc96 | ||
|
|
5eb600afc3 | ||
|
|
64ebff4012 | ||
|
|
9e5d30cd4c | ||
|
|
4324caaaea | ||
|
|
46c2d49243 | ||
|
|
80b1cf6020 | ||
|
|
264f7f2132 | ||
|
|
80ec8da7d3 | ||
|
|
1e2399669d | ||
|
|
ab53969f06 | ||
|
|
168217b4e0 | ||
|
|
a3ce1903c1 | ||
|
|
db1021a979 | ||
|
|
cbd00a45af | ||
|
|
fef4719e41 | ||
|
|
ae25a8f12c | ||
|
|
bb5403c795 | ||
|
|
325fb7158e | ||
|
|
67416e4b45 | ||
|
|
8b48accb7e | ||
|
|
bb42ee42ca | ||
|
|
d17660fe5d | ||
|
|
19e409ceca | ||
|
|
59df6d1a2e | ||
|
|
763ed32212 | ||
|
|
8aa522c4bf | ||
|
|
9031be96f8 | ||
|
|
4bc2e847d5 | ||
|
|
80d4e6f344 | ||
|
|
b6e38a0a96 | ||
|
|
1d79ad8436 | ||
|
|
383b197490 | ||
|
|
7aeee0681f | ||
|
|
e017adae84 | ||
|
|
7035aed74a | ||
|
|
21b6a3869a | ||
|
|
aa92e59b2c | ||
|
|
5f87e56651 | ||
|
|
9934c0033a | ||
|
|
5d1da2deac | ||
|
|
4e424c43fb | ||
|
|
3030b72f78 | ||
|
|
d1784676b2 | ||
|
|
47e49f0a4f | ||
|
|
0bfc456509 | ||
|
|
8e14997bc1 | ||
|
|
a8ec3c1a48 | ||
|
|
f6f617a746 | ||
|
|
3d65b9f6b6 | ||
|
|
5f7d93be52 | ||
|
|
3ec787687c | ||
|
|
9fbe5eb21d | ||
|
|
fb4abdfae3 | ||
|
|
7ab34d5cef | ||
|
|
b576b08332 | ||
|
|
9c43b802bd | ||
|
|
7dda864e4a | ||
|
|
b3953dbe23 | ||
|
|
453e8239d2 | ||
|
|
8e8b95c3bb | ||
|
|
35b64052d6 | ||
|
|
ef495da097 | ||
|
|
a6b9c9a41e | ||
|
|
5bb2d92180 | ||
|
|
929ec36c76 | ||
|
|
8e17d9c94e | ||
|
|
a11cd8c28c | ||
|
|
68d2a20d20 | ||
|
|
e3531413e1 | ||
|
|
ef534224f8 | ||
|
|
2f3e1451b8 | ||
|
|
a34e257d2c | ||
|
|
9d83631cfe | ||
|
|
61b3ffde91 | ||
|
|
bebdf0179e | ||
|
|
ab5e8ae9e2 | ||
|
|
c8da430134 | ||
|
|
0e8c312fda | ||
|
|
4814e9cea5 | ||
|
|
068a6e7af5 | ||
|
|
e4f2892a23 | ||
|
|
c2cfb05d8d | ||
|
|
813647ca10 | ||
|
|
83357dc929 | ||
|
|
420aa79a48 | ||
|
|
24be820827 | ||
|
|
694a764f96 | ||
|
|
bb1da73da2 | ||
|
|
e6b591c035 | ||
|
|
5a19cdfebb | ||
|
|
34e439f494 | ||
|
|
b0602a7bb0 | ||
|
|
d7558f0442 | ||
|
|
eac0ab3cca | ||
|
|
147cd48a8d | ||
|
|
1b44256fc0 | ||
|
|
db2856daf7 | ||
|
|
9beb0c1613 | ||
|
|
ef343158b7 | ||
|
|
de5526877d | ||
|
|
b00d75607b | ||
|
|
8c37a1bef5 | ||
|
|
7a9405ec9e | ||
|
|
6506e4594c | ||
|
|
7b20299d2b | ||
|
|
55eaadce67 | ||
|
|
87269d88b9 | ||
|
|
fb8162f5d7 | ||
|
|
a04aa8a4de | ||
|
|
352443d9cd | ||
|
|
cd798b8d95 | ||
|
|
c5b260f708 | ||
|
|
2583463ea2 | ||
|
|
777ac71bd1 | ||
|
|
810ae49cc7 | ||
|
|
225e308438 | ||
|
|
05dd543d16 | ||
|
|
c711201b34 | ||
|
|
47b3ac5d99 | ||
|
|
49aa856f52 | ||
|
|
5e15575929 | ||
|
|
c9fc608598 | ||
|
|
6ba3c3d683 | ||
|
|
d15edb79fa | ||
|
|
fa3b67342d | ||
|
|
033f156b2b | ||
|
|
f3db5e882e | ||
|
|
c9365f3551 | ||
|
|
9ecb5b9950 | ||
|
|
95fb53cbc9 | ||
|
|
9d82088e03 | ||
|
|
340b75b557 | ||
|
|
0b79389b14 | ||
|
|
111d3d3362 | ||
|
|
ac6ceb23e8 | ||
|
|
d31fa47cd1 | ||
|
|
d7f6a94f12 | ||
|
|
dbdd752b73 | ||
|
|
4c2b46e0fc | ||
|
|
68d12d0212 | ||
|
|
fa1c117011 | ||
|
|
6b1c5bc816 | ||
|
|
e2cafc6b3d | ||
|
|
aff7604b4b | ||
|
|
68530aa4e0 | ||
|
|
bfc1152b8a | ||
|
|
37af8f8ecb | ||
|
|
6792bffb5e | ||
|
|
976855a4c3 | ||
|
|
acf2ba9502 | ||
|
|
cadbc67825 | ||
|
|
0d86a93200 | ||
|
|
f78b5c83cd | ||
|
|
0234d60d74 | ||
|
|
cd18087e29 | ||
|
|
30f670bf5f | ||
|
|
c73785372b | ||
|
|
147698daab | ||
|
|
2b07e9a5b9 |
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -20,16 +20,16 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Install .NET Core
|
||||
- name: Install .NET 5.0
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '3.1.x'
|
||||
dotnet-version: '5.0.x'
|
||||
|
||||
- name: Build (Release)
|
||||
run: dotnet build src -c Release
|
||||
|
||||
|
||||
- name: SpecFileGen
|
||||
run: dotnet src/SpecFileGen/bin/Release/netcoreapp3.1/SpecFileGen.dll
|
||||
run: dotnet src/SpecFileGen/bin/Release/net5.0/SpecFileGen.dll
|
||||
|
||||
- name: Test (Release)
|
||||
run: dotnet test src -c Release
|
||||
@@ -38,14 +38,14 @@ jobs:
|
||||
run: dotnet test src -c Debug
|
||||
|
||||
- name: Coverlet
|
||||
run: dotnet test src -c Release -f netcoreapp3.1 /p:Include=\"[${{env.PROJECT_NAME}}]*\" /p:CollectCoverage=true /p:CoverletOutputFormat=lcov
|
||||
run: dotnet test src -c Release -f net5.0 /p:Include=\"[${{env.PROJECT_NAME}}]*\" /p:CollectCoverage=true /p:CoverletOutputFormat=lcov
|
||||
|
||||
- name: Coveralls Upload
|
||||
uses: coverallsapp/github-action@v1.0.1
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: src/${{env.PROJECT_NAME}}.Tests/coverage.netcoreapp3.1.info
|
||||
path-to-lcov: src/${{env.PROJECT_NAME}}.Tests/coverage.info
|
||||
|
||||
- name: Pack
|
||||
run: dotnet pack src -c Release
|
||||
|
||||
21
changelog.md
21
changelog.md
@@ -1,14 +1,27 @@
|
||||
# Changelog
|
||||
|
||||
## 0.25.0 (10 June 2021)
|
||||
- Fix regression when parsing link reference definitions (#543)
|
||||
- Make digits in JiraKey's posible ([PR #548](https://github.com/lunet-io/markdig/pull/548))
|
||||
|
||||
## 0.24.0 (20 Mar 2021)
|
||||
- Add support for roundtrip Markdown ([PR #481](https://github.com/lunet-io/markdig/pull/481))
|
||||
- Introduction of nullability ([PR #522](https://github.com/lunet-io/markdig/pull/522) [PR #524](https://github.com/lunet-io/markdig/pull/524) [PR #525](https://github.com/lunet-io/markdig/pull/525) [PR #526](https://github.com/lunet-io/markdig/pull/526) [PR #527](https://github.com/lunet-io/markdig/pull/527))
|
||||
- Various internal cleanup and small performance improvements ([PR #521](https://github.com/lunet-io/markdig/pull/521) [PR #524](https://github.com/lunet-io/markdig/pull/524) [PR #525](https://github.com/lunet-io/markdig/pull/525) [PR #529](https://github.com/lunet-io/markdig/pull/529) [PR #531](https://github.com/lunet-io/markdig/pull/531) [PR #532](https://github.com/lunet-io/markdig/pull/532))
|
||||
|
||||
## 0.23.0 (16 Jan 2021)
|
||||
- Add depth limits to avoid pathological-case parsing times/StackOverflows (#500)
|
||||
- Breaking change: rename AutolineInlineParser to AutolinkInlineParser
|
||||
|
||||
## 0.22.1 (2 Dec 2020)
|
||||
- Update logo for NuGet package
|
||||
|
||||
## 0.22.0 (05 Oct 2020)
|
||||
- Fix Setext headings in block quotes.
|
||||
- Fix tel: treated as autolink ([PR #478](https://github.com/lunet-io/markdig/pull/478)
|
||||
- Make Inline.FirstParentOfType public ([PR #474](https://github.com/lunet-io/markdig/pull/474)
|
||||
- Fix `&` to be parsed as a punctuation while it was detected as a html entity in certain cases ([PR #471](https://github.com/lunet-io/markdig/pull/471)
|
||||
- Add ParentBlock property to ContainerInline ([PR #468](https://github.com/lunet-io/markdig/pull/468)
|
||||
- Fix tel: treated as autolink ([PR #478](https://github.com/lunet-io/markdig/pull/478))
|
||||
- Make Inline.FirstParentOfType public ([PR #474](https://github.com/lunet-io/markdig/pull/474))
|
||||
- Fix `&` to be parsed as a punctuation while it was detected as a html entity in certain cases ([PR #471](https://github.com/lunet-io/markdig/pull/471))
|
||||
- Add ParentBlock property to ContainerInline ([PR #468](https://github.com/lunet-io/markdig/pull/468))
|
||||
|
||||
## 0.21.1 (17 Aug 2020)
|
||||
- Fix Markdig.Signed on GitHub Actions
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Markdig [](https://github.com/lunet-io/markdig/actions) [](https://coveralls.io/github/lunet-io/markdig?branch=master) [](https://www.nuget.org/packages/Markdig/) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
|
||||
# Markdig [](https://github.com/lunet-io/markdig/actions) [](https://coveralls.io/github/xoofx/markdig?branch=master) [](https://www.nuget.org/packages/Markdig/) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
|
||||
|
||||
<img align="right" width="160px" height="160px" src="img/markdig.png">
|
||||
|
||||
@@ -19,6 +19,7 @@ You can **try Markdig online** and compare it to other implementations on [babel
|
||||
- including **GFM fenced code blocks**.
|
||||
- **Extensible** architecture
|
||||
- Even the core Markdown/CommonMark parsing is pluggable, so it allows to disable builtin Markdown/Commonmark parsing (e.g [Disable HTML parsing](https://github.com/lunet-io/markdig/blob/7964bd0160d4c18e4155127a4c863d61ebd8944a/src/Markdig/MarkdownExtensions.cs#L306)) or change behaviour (e.g change matching `#` of a headers with `@`)
|
||||
- [**Roundtrip support**](./src/Markdig/Roundtrip.md): Parses trivia (whitespace, newlines and other characters) to support lossless parse ⭢ render roundtrip. This enables changing markdown documents without introducing undesired trivia changes.
|
||||
- Built-in with **20+ extensions**, including:
|
||||
- 2 kind of tables:
|
||||
- [**Pipe tables**](src/Markdig.Tests/Specs/PipeTableSpecs.md) (inspired from GitHub tables and [PanDoc - Pipe Tables](http://pandoc.org/README.html#extension-pipe_tables))
|
||||
|
||||
@@ -36,12 +36,12 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.10.6" />
|
||||
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.10.6" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
||||
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.12.1" />
|
||||
<PackageReference Include="CommonMark.NET" Version="0.15.1" />
|
||||
<PackageReference Include="MarkdownSharp" Version="1.13.0.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="0.8.31-beta" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="1.0.41.0" />
|
||||
<PackageReference Include="MarkdownSharp" Version="2.0.5" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.0.161401" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.62" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Markdig\Markdig.csproj" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<IsPackable>false</IsPackable>
|
||||
<StartupObject>Markdig.Tests.Program</StartupObject>
|
||||
@@ -12,7 +12,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -62,6 +62,29 @@ namespace Markdig.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[TestCase('[', 9 * 1024, true, false)]
|
||||
[TestCase('[', 11 * 1024, true, true)]
|
||||
[TestCase('[', 100, false, false)]
|
||||
[TestCase('[', 150, false, true)]
|
||||
[TestCase('>', 100, true, false)]
|
||||
[TestCase('>', 150, true, true)]
|
||||
public void GuardsAgainstHighlyNestedNodes(char c, int count, bool parseOnly, bool shouldThrow)
|
||||
{
|
||||
var markdown = new string(c, count);
|
||||
TestDelegate test = parseOnly ? () => Markdown.Parse(markdown) : () => Markdown.ToHtml(markdown);
|
||||
|
||||
if (shouldThrow)
|
||||
{
|
||||
Exception e = Assert.Throws<ArgumentException>(test);
|
||||
Assert.True(e.Message.Contains("depth limit"));
|
||||
}
|
||||
else
|
||||
{
|
||||
test();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIssue356Corrected()
|
||||
{
|
||||
|
||||
15266
src/Markdig.Tests/RoundtripSpecs/CommonMark.generated.cs
Normal file
15266
src/Markdig.Tests/RoundtripSpecs/CommonMark.generated.cs
Normal file
File diff suppressed because it is too large
Load Diff
9710
src/Markdig.Tests/RoundtripSpecs/CommonMark.md
Normal file
9710
src/Markdig.Tests/RoundtripSpecs/CommonMark.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestAutoLinkInline
|
||||
{
|
||||
[TestCase("<http://a>")]
|
||||
[TestCase(" <http://a>")]
|
||||
[TestCase("<http://a> ")]
|
||||
[TestCase(" <http://a> ")]
|
||||
[TestCase("<example@example.com>")]
|
||||
[TestCase(" <example@example.com>")]
|
||||
[TestCase("<example@example.com> ")]
|
||||
[TestCase(" <example@example.com> ")]
|
||||
[TestCase("p http://a p")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestBackslashEscapeInline
|
||||
{
|
||||
[TestCase(@"\!")]
|
||||
[TestCase(@"\""")]
|
||||
[TestCase(@"\#")]
|
||||
[TestCase(@"\$")]
|
||||
[TestCase(@"\&")]
|
||||
[TestCase(@"\'")]
|
||||
[TestCase(@"\(")]
|
||||
[TestCase(@"\)")]
|
||||
[TestCase(@"\*")]
|
||||
[TestCase(@"\+")]
|
||||
[TestCase(@"\,")]
|
||||
[TestCase(@"\-")]
|
||||
[TestCase(@"\.")]
|
||||
[TestCase(@"\/")]
|
||||
[TestCase(@"\:")]
|
||||
[TestCase(@"\;")]
|
||||
[TestCase(@"\<")]
|
||||
[TestCase(@"\=")]
|
||||
[TestCase(@"\>")]
|
||||
[TestCase(@"\?")]
|
||||
[TestCase(@"\@")]
|
||||
[TestCase(@"\[")]
|
||||
[TestCase(@"\\")]
|
||||
[TestCase(@"\]")]
|
||||
[TestCase(@"\^")]
|
||||
[TestCase(@"\_")]
|
||||
[TestCase(@"\`")]
|
||||
[TestCase(@"\{")]
|
||||
[TestCase(@"\|")]
|
||||
[TestCase(@"\}")]
|
||||
[TestCase(@"\~")]
|
||||
|
||||
// below test breaks visual studio
|
||||
//[TestCase(@"\!\""\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase(@"# \#\#h1")]
|
||||
[TestCase(@"# \#\#h1\#")]
|
||||
public void TestHeading(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase(@"`\``")]
|
||||
[TestCase(@"` \``")]
|
||||
[TestCase(@"`\` `")]
|
||||
[TestCase(@"` \` `")]
|
||||
[TestCase(@" ` \` `")]
|
||||
[TestCase(@"` \` ` ")]
|
||||
[TestCase(@" ` \` ` ")]
|
||||
public void TestCodeSpanInline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
77
src/Markdig.Tests/RoundtripSpecs/Inlines/TestCodeInline.cs
Normal file
77
src/Markdig.Tests/RoundtripSpecs/Inlines/TestCodeInline.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCodeInline
|
||||
{
|
||||
[TestCase("``")]
|
||||
[TestCase(" ``")]
|
||||
[TestCase("`` ")]
|
||||
[TestCase(" `` ")]
|
||||
|
||||
[TestCase("`c`")]
|
||||
[TestCase(" `c`")]
|
||||
[TestCase("`c` ")]
|
||||
[TestCase(" `c` ")]
|
||||
|
||||
[TestCase("` c`")]
|
||||
[TestCase(" ` c`")]
|
||||
[TestCase("` c` ")]
|
||||
[TestCase(" ` c` ")]
|
||||
|
||||
[TestCase("`c `")]
|
||||
[TestCase(" `c `")]
|
||||
[TestCase("`c ` ")]
|
||||
[TestCase(" `c ` ")]
|
||||
|
||||
[TestCase("`c``")] // 1, 2
|
||||
[TestCase("``c`")] // 2, 1
|
||||
[TestCase("``c``")] // 2, 2
|
||||
|
||||
[TestCase("```c``")] // 2, 3
|
||||
[TestCase("``c```")] // 3, 2
|
||||
[TestCase("```c```")] // 3, 3
|
||||
|
||||
[TestCase("```c````")] // 3, 4
|
||||
[TestCase("````c```")] // 4, 3
|
||||
[TestCase("````c````")] // 4, 4
|
||||
|
||||
[TestCase("```a``` p")]
|
||||
[TestCase("```a`b`c```")]
|
||||
[TestCase("```a``` p\n```a``` p")]
|
||||
|
||||
[TestCase("` a `")]
|
||||
[TestCase(" ` a `")]
|
||||
[TestCase("` a ` ")]
|
||||
[TestCase(" ` a ` ")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("p `a` p")]
|
||||
[TestCase("p ``a`` p")]
|
||||
[TestCase("p ```a``` p")]
|
||||
[TestCase("p\n\n```a``` p")]
|
||||
public void TestParagraph(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("`\na\n`")]
|
||||
[TestCase("`\na\r`")]
|
||||
[TestCase("`\na\r\n`")]
|
||||
[TestCase("`\ra\r`")]
|
||||
[TestCase("`\ra\n`")]
|
||||
[TestCase("`\ra\r\n`")]
|
||||
[TestCase("`\r\na\n`")]
|
||||
[TestCase("`\r\na\r`")]
|
||||
[TestCase("`\r\na\r\n`")]
|
||||
public void Test_Newlines(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
132
src/Markdig.Tests/RoundtripSpecs/Inlines/TestEmphasisInline.cs
Normal file
132
src/Markdig.Tests/RoundtripSpecs/Inlines/TestEmphasisInline.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestEmphasisInline
|
||||
{
|
||||
[TestCase("_t_")]
|
||||
[TestCase("_t_t")]
|
||||
[TestCase("t_t_")]
|
||||
[TestCase("_t t_")]
|
||||
[TestCase("_t\tt_")]
|
||||
[TestCase("*t*")]
|
||||
[TestCase("t*t*")]
|
||||
[TestCase("*t*t")]
|
||||
[TestCase("*t t*")]
|
||||
[TestCase("*t\tt*")]
|
||||
|
||||
[TestCase(" _t_")]
|
||||
[TestCase(" _t_t")]
|
||||
[TestCase(" t_t_")]
|
||||
[TestCase(" _t t_")]
|
||||
[TestCase(" _t\tt_")]
|
||||
[TestCase(" *t*")]
|
||||
[TestCase(" t*t*")]
|
||||
[TestCase(" *t*t")]
|
||||
[TestCase(" *t t*")]
|
||||
[TestCase(" *t\tt*")]
|
||||
|
||||
[TestCase("_t_")]
|
||||
[TestCase("_t_t ")]
|
||||
[TestCase("t_t_ ")]
|
||||
[TestCase("_t t_ ")]
|
||||
[TestCase("_t\tt_ ")]
|
||||
[TestCase("*t* ")]
|
||||
[TestCase("t*t* ")]
|
||||
[TestCase("*t*t ")]
|
||||
[TestCase("*t t* ")]
|
||||
[TestCase("*t\tt* ")]
|
||||
|
||||
[TestCase(" _t_")]
|
||||
[TestCase(" _t_t ")]
|
||||
[TestCase(" t_t_ ")]
|
||||
[TestCase(" _t t_ ")]
|
||||
[TestCase(" _t\tt_ ")]
|
||||
[TestCase(" *t* ")]
|
||||
[TestCase(" t*t* ")]
|
||||
[TestCase(" *t*t ")]
|
||||
[TestCase(" *t t* ")]
|
||||
[TestCase(" *t\tt* ")]
|
||||
|
||||
[TestCase("_t_\t")]
|
||||
[TestCase("_t_t\t")]
|
||||
[TestCase("t_t_\t")]
|
||||
[TestCase("_t t_\t")]
|
||||
[TestCase("_t\tt_\t")]
|
||||
[TestCase("*t*\t")]
|
||||
[TestCase("t*t*\t")]
|
||||
[TestCase("*t*t\t")]
|
||||
[TestCase("*t t*\t")]
|
||||
[TestCase("*t\tt*\t")]
|
||||
public void Test_Emphasis(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("__t__")]
|
||||
[TestCase("__t__t")]
|
||||
[TestCase("t__t__")]
|
||||
[TestCase("__t t__")]
|
||||
[TestCase("__t\tt__")]
|
||||
[TestCase("**t**")]
|
||||
[TestCase("**t**t")]
|
||||
[TestCase("t**t**")]
|
||||
[TestCase("**t\tt**")]
|
||||
|
||||
[TestCase(" __t__")]
|
||||
[TestCase(" __t__t")]
|
||||
[TestCase(" t__t__")]
|
||||
[TestCase(" __t t__")]
|
||||
[TestCase(" __t\tt__")]
|
||||
[TestCase(" **t**")]
|
||||
[TestCase(" **t**t")]
|
||||
[TestCase(" t**t**")]
|
||||
[TestCase(" **t\tt**")]
|
||||
|
||||
[TestCase("__t__ ")]
|
||||
[TestCase("__t__t ")]
|
||||
[TestCase("t__t__ ")]
|
||||
[TestCase("__t t__ ")]
|
||||
[TestCase("__t\tt__ ")]
|
||||
[TestCase("**t** ")]
|
||||
[TestCase("**t**t ")]
|
||||
[TestCase("t**t** ")]
|
||||
[TestCase("**t\tt** ")]
|
||||
|
||||
[TestCase(" __t__ ")]
|
||||
[TestCase(" __t__t ")]
|
||||
[TestCase(" t__t__ ")]
|
||||
[TestCase(" __t t__ ")]
|
||||
[TestCase(" __t\tt__ ")]
|
||||
[TestCase(" **t** ")]
|
||||
[TestCase(" **t** t")]
|
||||
[TestCase(" t**t** ")]
|
||||
[TestCase(" **t\tt** ")]
|
||||
|
||||
[TestCase("__t__\t")]
|
||||
[TestCase("__t__t\t")]
|
||||
[TestCase("t__t__\t ")]
|
||||
[TestCase("__t t__\t ")]
|
||||
[TestCase("__t\tt__\t ")]
|
||||
[TestCase("**t**\t ")]
|
||||
[TestCase("**t**t\t ")]
|
||||
[TestCase("t**t**\t ")]
|
||||
[TestCase("**t\tt**\t ")]
|
||||
|
||||
[TestCase(" __t__\t ")]
|
||||
[TestCase(" __t__t\t ")]
|
||||
[TestCase(" t__t__\t ")]
|
||||
[TestCase(" __t t__\t ")]
|
||||
[TestCase(" __t\tt__\t ")]
|
||||
[TestCase(" **t**\t ")]
|
||||
[TestCase(" **t**\t t")]
|
||||
[TestCase(" t**t**\t ")]
|
||||
[TestCase(" **t\tt**\t ")]
|
||||
public void Test_StrongEmphasis(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <seealso cref="https://spec.commonmark.org/0.29/#entity-and-numeric-character-references"/>
|
||||
[TestFixture]
|
||||
public class TestHtmlEntityInline
|
||||
{
|
||||
[TestCase(">")]
|
||||
[TestCase("<")]
|
||||
[TestCase(" ")]
|
||||
[TestCase("♥")]
|
||||
[TestCase("*")]
|
||||
[TestCase("�")]
|
||||
[TestCase("Ӓ")]
|
||||
[TestCase("ಫ")]
|
||||
|
||||
[TestCase(" >")]
|
||||
[TestCase(" <")]
|
||||
[TestCase(" ")]
|
||||
[TestCase(" ♥")]
|
||||
[TestCase(" *")]
|
||||
[TestCase(" �")]
|
||||
[TestCase(" Ӓ")]
|
||||
[TestCase(" ಫ")]
|
||||
|
||||
[TestCase("> ")]
|
||||
[TestCase("< ")]
|
||||
[TestCase(" ")]
|
||||
[TestCase("♥ ")]
|
||||
[TestCase("* ")]
|
||||
[TestCase("� ")]
|
||||
[TestCase("Ӓ ")]
|
||||
[TestCase("ಫ ")]
|
||||
|
||||
[TestCase(" > ")]
|
||||
[TestCase(" < ")]
|
||||
[TestCase(" ")]
|
||||
[TestCase(" ♥ ")]
|
||||
[TestCase(" * ")]
|
||||
[TestCase(" � ")]
|
||||
[TestCase(" Ӓ ")]
|
||||
[TestCase(" ಫ ")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/Markdig.Tests/RoundtripSpecs/Inlines/TestHtmlInline.cs
Normal file
27
src/Markdig.Tests/RoundtripSpecs/Inlines/TestHtmlInline.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestHtmlInline
|
||||
{
|
||||
[TestCase("<em>f</em>")]
|
||||
[TestCase("<em> f</em>")]
|
||||
[TestCase("<em>f </em>")]
|
||||
[TestCase("<em> f </em>")]
|
||||
[TestCase("<b>p</b>")]
|
||||
[TestCase("<b></b>")]
|
||||
[TestCase("<b> </b>")]
|
||||
[TestCase("<b> </b>")]
|
||||
[TestCase("<b> </b>")]
|
||||
[TestCase("<b>\t</b>")]
|
||||
[TestCase("<b> \t</b>")]
|
||||
[TestCase("<b>\t </b>")]
|
||||
[TestCase("<b> \t </b>")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/Markdig.Tests/RoundtripSpecs/Inlines/TestImageInline.cs
Normal file
25
src/Markdig.Tests/RoundtripSpecs/Inlines/TestImageInline.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestImageInline
|
||||
{
|
||||
[TestCase("")]
|
||||
[TestCase(" ")]
|
||||
[TestCase(" ")]
|
||||
[TestCase("  ")]
|
||||
[TestCase(" ")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("paragraph ")]
|
||||
public void TestParagraph(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestLineBreakInline
|
||||
{
|
||||
[TestCase("p\n")]
|
||||
[TestCase("p\r\n")]
|
||||
[TestCase("p\r")]
|
||||
[TestCase("[]() ![]() `` ` ` ` ` ![]() ![]()")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
229
src/Markdig.Tests/RoundtripSpecs/Inlines/TestLinkInline.cs
Normal file
229
src/Markdig.Tests/RoundtripSpecs/Inlines/TestLinkInline.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestLinkInline
|
||||
{
|
||||
[TestCase("[a]")] // TODO: this is not a link but a paragraph
|
||||
[TestCase("[a]()")]
|
||||
|
||||
[TestCase("[](b)")]
|
||||
[TestCase(" [](b)")]
|
||||
[TestCase("[](b) ")]
|
||||
[TestCase(" [](b) ")]
|
||||
|
||||
[TestCase("[a](b)")]
|
||||
[TestCase(" [a](b)")]
|
||||
[TestCase("[a](b) ")]
|
||||
[TestCase(" [a](b) ")]
|
||||
|
||||
[TestCase("[ a](b)")]
|
||||
[TestCase(" [ a](b)")]
|
||||
[TestCase("[ a](b) ")]
|
||||
[TestCase(" [ a](b) ")]
|
||||
|
||||
[TestCase("[a ](b)")]
|
||||
[TestCase(" [a ](b)")]
|
||||
[TestCase("[a ](b) ")]
|
||||
[TestCase(" [a ](b) ")]
|
||||
|
||||
[TestCase("[ a ](b)")]
|
||||
[TestCase(" [ a ](b)")]
|
||||
[TestCase("[ a ](b) ")]
|
||||
[TestCase(" [ a ](b) ")]
|
||||
|
||||
// below cases are required for a full roundtrip but not have low prio for impl
|
||||
[TestCase("[]( b)")]
|
||||
[TestCase(" []( b)")]
|
||||
[TestCase("[]( b) ")]
|
||||
[TestCase(" []( b) ")]
|
||||
|
||||
[TestCase("[a]( b)")]
|
||||
[TestCase(" [a]( b)")]
|
||||
[TestCase("[a]( b) ")]
|
||||
[TestCase(" [a]( b) ")]
|
||||
|
||||
[TestCase("[ a]( b)")]
|
||||
[TestCase(" [ a]( b)")]
|
||||
[TestCase("[ a]( b) ")]
|
||||
[TestCase(" [ a]( b) ")]
|
||||
|
||||
[TestCase("[a ]( b)")]
|
||||
[TestCase(" [a ]( b)")]
|
||||
[TestCase("[a ]( b) ")]
|
||||
[TestCase(" [a ]( b) ")]
|
||||
|
||||
[TestCase("[ a ]( b)")]
|
||||
[TestCase(" [ a ]( b)")]
|
||||
[TestCase("[ a ]( b) ")]
|
||||
[TestCase(" [ a ]( b) ")]
|
||||
|
||||
[TestCase("[](b )")]
|
||||
[TestCase(" [](b )")]
|
||||
[TestCase("[](b ) ")]
|
||||
[TestCase(" [](b ) ")]
|
||||
|
||||
[TestCase("[a](b )")]
|
||||
[TestCase(" [a](b )")]
|
||||
[TestCase("[a](b ) ")]
|
||||
[TestCase(" [a](b ) ")]
|
||||
|
||||
[TestCase("[ a](b )")]
|
||||
[TestCase(" [ a](b )")]
|
||||
[TestCase("[ a](b ) ")]
|
||||
[TestCase(" [ a](b ) ")]
|
||||
|
||||
[TestCase("[a ](b )")]
|
||||
[TestCase(" [a ](b )")]
|
||||
[TestCase("[a ](b ) ")]
|
||||
[TestCase(" [a ](b ) ")]
|
||||
|
||||
[TestCase("[ a ](b )")]
|
||||
[TestCase(" [ a ](b )")]
|
||||
[TestCase("[ a ](b ) ")]
|
||||
[TestCase(" [ a ](b ) ")]
|
||||
|
||||
[TestCase("[]( b )")]
|
||||
[TestCase(" []( b )")]
|
||||
[TestCase("[]( b ) ")]
|
||||
[TestCase(" []( b ) ")]
|
||||
|
||||
[TestCase("[a]( b )")]
|
||||
[TestCase(" [a]( b )")]
|
||||
[TestCase("[a]( b ) ")]
|
||||
[TestCase(" [a]( b ) ")]
|
||||
|
||||
[TestCase("[ a]( b )")]
|
||||
[TestCase(" [ a]( b )")]
|
||||
[TestCase("[ a]( b ) ")]
|
||||
[TestCase(" [ a]( b ) ")]
|
||||
|
||||
[TestCase("[a ]( b )")]
|
||||
[TestCase(" [a ]( b )")]
|
||||
[TestCase("[a ]( b ) ")]
|
||||
[TestCase(" [a ]( b ) ")]
|
||||
|
||||
[TestCase("[ a ]( b )")]
|
||||
[TestCase(" [ a ]( b )")]
|
||||
[TestCase("[ a ]( b ) ")]
|
||||
[TestCase(" [ a ]( b ) ")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[a](b \"t\") ")]
|
||||
[TestCase("[a](b \" t\") ")]
|
||||
[TestCase("[a](b \"t \") ")]
|
||||
[TestCase("[a](b \" t \") ")]
|
||||
|
||||
[TestCase("[a](b \"t\") ")]
|
||||
[TestCase("[a](b \" t\") ")]
|
||||
[TestCase("[a](b \"t \") ")]
|
||||
[TestCase("[a](b \" t \") ")]
|
||||
|
||||
[TestCase("[a](b \"t\" ) ")]
|
||||
[TestCase("[a](b \" t\" ) ")]
|
||||
[TestCase("[a](b \"t \" ) ")]
|
||||
[TestCase("[a](b \" t \" ) ")]
|
||||
|
||||
[TestCase("[a](b \"t\" ) ")]
|
||||
[TestCase("[a](b \" t\" ) ")]
|
||||
[TestCase("[a](b \"t \" ) ")]
|
||||
[TestCase("[a](b \" t \" ) ")]
|
||||
|
||||
[TestCase("[a](b 't') ")]
|
||||
[TestCase("[a](b ' t') ")]
|
||||
[TestCase("[a](b 't ') ")]
|
||||
[TestCase("[a](b ' t ') ")]
|
||||
|
||||
[TestCase("[a](b 't') ")]
|
||||
[TestCase("[a](b ' t') ")]
|
||||
[TestCase("[a](b 't ') ")]
|
||||
[TestCase("[a](b ' t ') ")]
|
||||
|
||||
[TestCase("[a](b 't' ) ")]
|
||||
[TestCase("[a](b ' t' ) ")]
|
||||
[TestCase("[a](b 't ' ) ")]
|
||||
[TestCase("[a](b ' t ' ) ")]
|
||||
|
||||
[TestCase("[a](b 't' ) ")]
|
||||
[TestCase("[a](b ' t' ) ")]
|
||||
[TestCase("[a](b 't ' ) ")]
|
||||
[TestCase("[a](b ' t ' ) ")]
|
||||
|
||||
[TestCase("[a](b (t)) ")]
|
||||
[TestCase("[a](b ( t)) ")]
|
||||
[TestCase("[a](b (t )) ")]
|
||||
[TestCase("[a](b ( t )) ")]
|
||||
|
||||
[TestCase("[a](b (t)) ")]
|
||||
[TestCase("[a](b ( t)) ")]
|
||||
[TestCase("[a](b (t )) ")]
|
||||
[TestCase("[a](b ( t )) ")]
|
||||
|
||||
[TestCase("[a](b (t) ) ")]
|
||||
[TestCase("[a](b ( t) ) ")]
|
||||
[TestCase("[a](b (t ) ) ")]
|
||||
[TestCase("[a](b ( t ) ) ")]
|
||||
|
||||
[TestCase("[a](b (t) ) ")]
|
||||
[TestCase("[a](b ( t) ) ")]
|
||||
[TestCase("[a](b (t ) ) ")]
|
||||
[TestCase("[a](b ( t ) ) ")]
|
||||
public void Test_Title(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[a](<>)")]
|
||||
[TestCase("[a]( <>)")]
|
||||
[TestCase("[a](<> )")]
|
||||
[TestCase("[a]( <> )")]
|
||||
|
||||
[TestCase("[a](< >)")]
|
||||
[TestCase("[a]( < >)")]
|
||||
[TestCase("[a](< > )")]
|
||||
[TestCase("[a]( < > )")]
|
||||
|
||||
[TestCase("[a](<b>)")]
|
||||
[TestCase("[a](<b >)")]
|
||||
[TestCase("[a](< b>)")]
|
||||
[TestCase("[a](< b >)")]
|
||||
|
||||
[TestCase("[a](<b b>)")]
|
||||
[TestCase("[a](<b b >)")]
|
||||
[TestCase("[a](< b b >)")]
|
||||
public void Test_PointyBrackets(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[*a*][a]")]
|
||||
[TestCase("[a][b]")]
|
||||
[TestCase("[a][]")]
|
||||
[TestCase("[a]")]
|
||||
public void Test_Inlines(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
// | [ a ]( b " t " ) |
|
||||
[TestCase(" [ a ]( b \" t \" ) ")]
|
||||
[TestCase("\v[\va\v](\vb\v\"\vt\v\"\v)\v")]
|
||||
[TestCase("\f[\fa\f](\fb\f\"\ft\f\"\f)\f")]
|
||||
[TestCase("\t[\ta\t](\tb\t\"\tt\t\"\t)\t")]
|
||||
public void Test_UncommonWhitespace(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[x]: https://example.com\r\n")]
|
||||
public void Test_LinkReferenceDefinitionWithCarriageReturnLineFeed(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Markdig.Renderers.Roundtrip;
|
||||
using Markdig.Syntax;
|
||||
using NUnit.Framework;
|
||||
using System.IO;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs.Inlines
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestNullCharacterInline
|
||||
{
|
||||
[TestCase("\0", "\uFFFD")]
|
||||
[TestCase("\0p", "\uFFFDp")]
|
||||
[TestCase("p\0", "p\uFFFD")]
|
||||
[TestCase("p\0p", "p\uFFFDp")]
|
||||
[TestCase("p\0\0p", "p\uFFFD\uFFFDp")] // I promise you, this was not intentional
|
||||
public void Test(string value, string expected)
|
||||
{
|
||||
RoundTrip(value, expected);
|
||||
}
|
||||
|
||||
// this method is copied intentionally to ensure all other tests
|
||||
// do not unintentionally use the expected parameter
|
||||
private static void RoundTrip(string markdown, string expected)
|
||||
{
|
||||
var pipelineBuilder = new MarkdownPipelineBuilder();
|
||||
pipelineBuilder.EnableTrackTrivia();
|
||||
MarkdownPipeline pipeline = pipelineBuilder.Build();
|
||||
MarkdownDocument markdownDocument = Markdown.Parse(markdown, pipeline);
|
||||
var sw = new StringWriter();
|
||||
var rr = new RoundtripRenderer(sw);
|
||||
|
||||
rr.Write(markdownDocument);
|
||||
|
||||
Assert.AreEqual(expected, sw.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/Markdig.Tests/RoundtripSpecs/TestAtxHeading.cs
Normal file
55
src/Markdig.Tests/RoundtripSpecs/TestAtxHeading.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestAtxHeading
|
||||
{
|
||||
[TestCase("# h")]
|
||||
[TestCase("# h ")]
|
||||
[TestCase("# h\n#h")]
|
||||
[TestCase("# h\n #h")]
|
||||
[TestCase("# h\n # h")]
|
||||
[TestCase("# h\n # h ")]
|
||||
[TestCase(" # h \n # h ")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("\n# h\n\np")]
|
||||
[TestCase("\n# h\n\np\n")]
|
||||
[TestCase("\n# h\n\np\n\n")]
|
||||
[TestCase("\n\n# h\n\np\n\n")]
|
||||
[TestCase("\n\n# h\np\n\n")]
|
||||
[TestCase("\n\n# h\np\n\n")]
|
||||
public void TestParagraph(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("\n# h")]
|
||||
[TestCase("\n# h\n")]
|
||||
[TestCase("\n# h\r")]
|
||||
[TestCase("\n# h\r\n")]
|
||||
|
||||
[TestCase("\r# h")]
|
||||
[TestCase("\r# h\n")]
|
||||
[TestCase("\r# h\r")]
|
||||
[TestCase("\r# h\r\n")]
|
||||
|
||||
[TestCase("\r\n# h")]
|
||||
[TestCase("\r\n# h\n")]
|
||||
[TestCase("\r\n# h\r")]
|
||||
[TestCase("\r\n# h\r\n")]
|
||||
|
||||
[TestCase("# h\n\n ")]
|
||||
[TestCase("# h\n\n ")]
|
||||
[TestCase("# h\n\n ")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
58
src/Markdig.Tests/RoundtripSpecs/TestExample.cs
Normal file
58
src/Markdig.Tests/RoundtripSpecs/TestExample.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using Markdig.Helpers;
|
||||
using Markdig.Renderers.Roundtrip;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using NUnit.Framework;
|
||||
using System.IO;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestExample
|
||||
{
|
||||
[Test]
|
||||
public void Test()
|
||||
{
|
||||
var markdown = $@"
|
||||
# Test document
|
||||
This document contains an unordered list. It uses tabs to indent. This test demonstrates
|
||||
a method of making the input markdown uniform without altering any other markdown in the
|
||||
resulting output file.
|
||||
|
||||
- item1
|
||||
|
||||
>look, ma:
|
||||
> my space is not normalized!
|
||||
";
|
||||
MarkdownDocument markdownDocument = Markdown.Parse(markdown, trackTrivia: true);
|
||||
var listBlock = markdownDocument[2] as ListBlock;
|
||||
var listItem = listBlock[0] as ListItemBlock;
|
||||
var paragraph = listItem[0] as ParagraphBlock;
|
||||
var containerInline = new ContainerInline();
|
||||
containerInline.AppendChild(new LiteralInline(" my own text!"));
|
||||
containerInline.AppendChild(new LineBreakInline { NewLine = NewLine.CarriageReturnLineFeed });
|
||||
paragraph.Inline = containerInline;
|
||||
|
||||
var sw = new StringWriter();
|
||||
var rr = new RoundtripRenderer(sw);
|
||||
rr.Write(markdownDocument);
|
||||
var outputMarkdown = sw.ToString();
|
||||
var expected = $@"
|
||||
# Test document
|
||||
This document contains an unordered list. It uses tabs to indent. This test demonstrates
|
||||
a method of making the input markdown uniform without altering any other markdown in the
|
||||
resulting output file.
|
||||
|
||||
- my own text!
|
||||
|
||||
>look, ma:
|
||||
> my space is not normalized!
|
||||
";
|
||||
|
||||
expected = expected.Replace("\r\n", "\n").Replace("\r", "\n");
|
||||
outputMarkdown = outputMarkdown.Replace("\r\n", "\n").Replace("\r", "\n");
|
||||
|
||||
Assert.AreEqual(expected, outputMarkdown);
|
||||
}
|
||||
}
|
||||
}
|
||||
107
src/Markdig.Tests/RoundtripSpecs/TestFencedCodeBlock.cs
Normal file
107
src/Markdig.Tests/RoundtripSpecs/TestFencedCodeBlock.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestFencedCodeBlock
|
||||
{
|
||||
[TestCase("```\nc\n```")]
|
||||
[TestCase("```\nc\n```\n")]
|
||||
[TestCase("\n```\nc\n```")]
|
||||
[TestCase("\n\n```\nc\n```")]
|
||||
[TestCase("```\nc\n```\n")]
|
||||
[TestCase("```\nc\n```\n\n")]
|
||||
[TestCase("\n```\nc\n```\n")]
|
||||
[TestCase("\n```\nc\n```\n\n")]
|
||||
[TestCase("\n\n```\nc\n```\n")]
|
||||
[TestCase("\n\n```\nc\n```\n\n")]
|
||||
|
||||
[TestCase(" ```\nc\n````")]
|
||||
[TestCase("```\nc\n````")]
|
||||
[TestCase("p\n\n```\nc\n```")]
|
||||
|
||||
[TestCase("```\n c\n```")]
|
||||
[TestCase("```\nc \n```")]
|
||||
[TestCase("```\n c \n```")]
|
||||
|
||||
[TestCase(" ``` \n c \n ``` ")]
|
||||
[TestCase("\t```\t\n\tc\t\n\t```\t")]
|
||||
[TestCase("\v```\v\n\vc\v\n\v```\v")]
|
||||
[TestCase("\f```\f\n\fc\f\n\f```\f")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("~~~ aa ``` ~~~\nfoo\n~~~")]
|
||||
[TestCase("~~~ aa ``` ~~~\nfoo\n~~~ ")]
|
||||
public void TestTilde(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("```\n c \n```")]
|
||||
[TestCase("```\n c \r```")]
|
||||
[TestCase("```\n c \r\n```")]
|
||||
[TestCase("```\r c \n```")]
|
||||
[TestCase("```\r c \r```")]
|
||||
[TestCase("```\r c \r\n```")]
|
||||
[TestCase("```\r\n c \n```")]
|
||||
[TestCase("```\r\n c \r```")]
|
||||
[TestCase("```\r\n c \r\n```")]
|
||||
|
||||
[TestCase("```\n c \n```\n")]
|
||||
[TestCase("```\n c \r```\n")]
|
||||
[TestCase("```\n c \r\n```\n")]
|
||||
[TestCase("```\r c \n```\n")]
|
||||
[TestCase("```\r c \r```\n")]
|
||||
[TestCase("```\r c \r\n```\n")]
|
||||
[TestCase("```\r\n c \n```\n")]
|
||||
[TestCase("```\r\n c \r```\n")]
|
||||
[TestCase("```\r\n c \r\n```\n")]
|
||||
|
||||
[TestCase("```\n c \n```\r")]
|
||||
[TestCase("```\n c \r```\r")]
|
||||
[TestCase("```\n c \r\n```\r")]
|
||||
[TestCase("```\r c \n```\r")]
|
||||
[TestCase("```\r c \r```\r")]
|
||||
[TestCase("```\r c \r\n```\r")]
|
||||
[TestCase("```\r\n c \n```\r")]
|
||||
[TestCase("```\r\n c \r```\r")]
|
||||
[TestCase("```\r\n c \r\n```\r")]
|
||||
|
||||
[TestCase("```\n c \n```\r\n")]
|
||||
[TestCase("```\n c \r```\r\n")]
|
||||
[TestCase("```\n c \r\n```\r\n")]
|
||||
[TestCase("```\r c \n```\r\n")]
|
||||
[TestCase("```\r c \r```\r\n")]
|
||||
[TestCase("```\r c \r\n```\r\n")]
|
||||
[TestCase("```\r\n c \n```\r\n")]
|
||||
[TestCase("```\r\n c \r```\r\n")]
|
||||
[TestCase("```\r\n c \r\n```\r\n")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("```i a\n```")]
|
||||
[TestCase("```i a a2\n```")]
|
||||
[TestCase("```i a a2 a3\n```")]
|
||||
[TestCase("```i a a2 a3 a4\n```")]
|
||||
|
||||
[TestCase("```i\ta\n```")]
|
||||
[TestCase("```i\ta a2\n```")]
|
||||
[TestCase("```i\ta a2 a3\n```")]
|
||||
[TestCase("```i\ta a2 a3 a4\n```")]
|
||||
|
||||
[TestCase("```i\ta \n```")]
|
||||
[TestCase("```i\ta a2 \n```")]
|
||||
[TestCase("```i\ta a2 a3 \n```")]
|
||||
[TestCase("```i\ta a2 a3 a4 \n```")]
|
||||
public void TestInfoArguments(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/Markdig.Tests/RoundtripSpecs/TestHtmlBlock.cs
Normal file
20
src/Markdig.Tests/RoundtripSpecs/TestHtmlBlock.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestHtmlBlock
|
||||
{
|
||||
[TestCase("<br>")]
|
||||
[TestCase("<br>\n")]
|
||||
[TestCase("<br>\n\n")]
|
||||
[TestCase("<div></div>\n\n# h")]
|
||||
[TestCase("p\n\n<div></div>\n")]
|
||||
[TestCase("<div></div>\n\n# h")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/Markdig.Tests/RoundtripSpecs/TestIndentedCodeBlock.cs
Normal file
86
src/Markdig.Tests/RoundtripSpecs/TestIndentedCodeBlock.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestIndentedCodeBlock
|
||||
{
|
||||
// A codeblock is indented with 4 spaces. After the 4th space, whitespace is interpreted as content.
|
||||
// l = line
|
||||
[TestCase(" l")]
|
||||
[TestCase(" l")]
|
||||
[TestCase("\tl")]
|
||||
[TestCase("\t\tl")]
|
||||
[TestCase("\tl1\n l1")]
|
||||
|
||||
[TestCase("\n l")]
|
||||
[TestCase("\n\n l")]
|
||||
[TestCase("\n l\n")]
|
||||
[TestCase("\n l\n\n")]
|
||||
[TestCase("\n\n l\n")]
|
||||
[TestCase("\n\n l\n\n")]
|
||||
|
||||
[TestCase(" l\n l")]
|
||||
[TestCase(" l\n l\n l")]
|
||||
|
||||
|
||||
// two newlines are needed for indented codeblock start after paragraph
|
||||
[TestCase("p\n\n l")]
|
||||
[TestCase("p\n\n l\n")]
|
||||
[TestCase("p\n\n l\n\n")]
|
||||
|
||||
[TestCase("p\n\n l\n l")]
|
||||
[TestCase("p\n\n l\n l")]
|
||||
|
||||
[TestCase(" l\n\np\n\n l")]
|
||||
[TestCase(" l l\n\np\n\n l l")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase(" l\n")]
|
||||
[TestCase(" l\r")]
|
||||
[TestCase(" l\r\n")]
|
||||
|
||||
[TestCase(" l\n l")]
|
||||
[TestCase(" l\n l\n")]
|
||||
[TestCase(" l\n l\r")]
|
||||
[TestCase(" l\n l\r\n")]
|
||||
|
||||
[TestCase(" l\r l")]
|
||||
[TestCase(" l\r l\n")]
|
||||
[TestCase(" l\r l\r")]
|
||||
[TestCase(" l\r l\r\n")]
|
||||
|
||||
[TestCase(" l\r\n l")]
|
||||
[TestCase(" l\r\n l\n")]
|
||||
[TestCase(" l\r\n l\r")]
|
||||
[TestCase(" l\r\n l\r\n")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase(" l\n\n l\n")]
|
||||
[TestCase(" l\n\n\n l\n")]
|
||||
public void TestNewlinesInBetweenResultInOneCodeBlock(string value)
|
||||
{
|
||||
var pipelineBuilder = new MarkdownPipelineBuilder();
|
||||
pipelineBuilder.EnableTrackTrivia();
|
||||
MarkdownPipeline pipeline = pipelineBuilder.Build();
|
||||
var markdownDocument = Markdown.Parse(value, pipeline);
|
||||
|
||||
Assert.AreEqual(1, markdownDocument.Count);
|
||||
}
|
||||
|
||||
[TestCase(" l\n\np")]
|
||||
[TestCase(" l\n\n\np")]
|
||||
[TestCase(" l\n\n\n\np")]
|
||||
public void TestParagraph(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
214
src/Markdig.Tests/RoundtripSpecs/TestLinkReferenceDefinition.cs
Normal file
214
src/Markdig.Tests/RoundtripSpecs/TestLinkReferenceDefinition.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestLinkReferenceDefinition
|
||||
{
|
||||
[TestCase(@"[a]: /r")]
|
||||
[TestCase(@" [a]: /r")]
|
||||
[TestCase(@" [a]: /r")]
|
||||
[TestCase(@" [a]: /r")]
|
||||
|
||||
[TestCase(@"[a]: /r")]
|
||||
[TestCase(@" [a]: /r")]
|
||||
[TestCase(@" [a]: /r")]
|
||||
[TestCase(@" [a]: /r")]
|
||||
|
||||
[TestCase(@"[a]: /r ")]
|
||||
[TestCase(@" [a]: /r ")]
|
||||
[TestCase(@" [a]: /r ")]
|
||||
[TestCase(@" [a]: /r ")]
|
||||
|
||||
[TestCase(@"[a]: /r ""l""")]
|
||||
[TestCase(@"[a]: /r ""l""")]
|
||||
[TestCase(@"[a]: /r ""l""")]
|
||||
[TestCase(@"[a]: /r ""l"" ")]
|
||||
[TestCase(@"[a]: /r ""l""")]
|
||||
[TestCase(@"[a]: /r ""l"" ")]
|
||||
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l"" ")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l"" ")]
|
||||
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l"" ")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l"" ")]
|
||||
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l"" ")]
|
||||
[TestCase(@" [a]: /r ""l""")]
|
||||
[TestCase(@" [a]: /r ""l"" ")]
|
||||
|
||||
[TestCase("[a]:\t/r")]
|
||||
[TestCase("[a]:\t/r\t")]
|
||||
[TestCase("[a]:\t/r\t\"l\"")]
|
||||
[TestCase("[a]:\t/r\t\"l\"\t")]
|
||||
|
||||
[TestCase("[a]: \t/r")]
|
||||
[TestCase("[a]: \t/r\t")]
|
||||
[TestCase("[a]: \t/r\t\"l\"")]
|
||||
[TestCase("[a]: \t/r\t\"l\"\t")]
|
||||
|
||||
[TestCase("[a]:\t /r")]
|
||||
[TestCase("[a]:\t /r\t")]
|
||||
[TestCase("[a]:\t /r\t\"l\"")]
|
||||
[TestCase("[a]:\t /r\t\"l\"\t")]
|
||||
|
||||
[TestCase("[a]: \t /r")]
|
||||
[TestCase("[a]: \t /r\t")]
|
||||
[TestCase("[a]: \t /r\t\"l\"")]
|
||||
[TestCase("[a]: \t /r\t\"l\"\t")]
|
||||
|
||||
[TestCase("[a]:\t/r \t")]
|
||||
[TestCase("[a]:\t/r \t\"l\"")]
|
||||
[TestCase("[a]:\t/r \t\"l\"\t")]
|
||||
|
||||
[TestCase("[a]: \t/r")]
|
||||
[TestCase("[a]: \t/r \t")]
|
||||
[TestCase("[a]: \t/r \t\"l\"")]
|
||||
[TestCase("[a]: \t/r \t\"l\"\t")]
|
||||
|
||||
[TestCase("[a]:\t /r")]
|
||||
[TestCase("[a]:\t /r \t")]
|
||||
[TestCase("[a]:\t /r \t\"l\"")]
|
||||
[TestCase("[a]:\t /r \t\"l\"\t")]
|
||||
|
||||
[TestCase("[a]: \t /r")]
|
||||
[TestCase("[a]: \t /r \t")]
|
||||
[TestCase("[a]: \t /r \t\"l\"")]
|
||||
[TestCase("[a]: \t /r \t\"l\"\t")]
|
||||
|
||||
[TestCase("[a]:\t/r\t ")]
|
||||
[TestCase("[a]:\t/r\t \"l\"")]
|
||||
[TestCase("[a]:\t/r\t \"l\"\t")]
|
||||
|
||||
[TestCase("[a]: \t/r")]
|
||||
[TestCase("[a]: \t/r\t ")]
|
||||
[TestCase("[a]: \t/r\t \"l\"")]
|
||||
[TestCase("[a]: \t/r\t \"l\"\t")]
|
||||
|
||||
[TestCase("[a]:\t /r")]
|
||||
[TestCase("[a]:\t /r\t ")]
|
||||
[TestCase("[a]:\t /r\t \"l\"")]
|
||||
[TestCase("[a]:\t /r\t \"l\"\t")]
|
||||
|
||||
[TestCase("[a]: \t /r")]
|
||||
[TestCase("[a]: \t /r\t ")]
|
||||
[TestCase("[a]: \t /r\t \"l\"")]
|
||||
[TestCase("[a]: \t /r\t \"l\"\t")]
|
||||
|
||||
[TestCase("[a]:\t/r \t ")]
|
||||
[TestCase("[a]:\t/r \t \"l\"")]
|
||||
[TestCase("[a]:\t/r \t \"l\"\t")]
|
||||
|
||||
[TestCase("[a]: \t/r")]
|
||||
[TestCase("[a]: \t/r \t ")]
|
||||
[TestCase("[a]: \t/r \t \"l\"")]
|
||||
[TestCase("[a]: \t/r \t \"l\"\t")]
|
||||
|
||||
[TestCase("[a]:\t /r")]
|
||||
[TestCase("[a]:\t /r \t ")]
|
||||
[TestCase("[a]:\t /r \t \"l\"")]
|
||||
[TestCase("[a]:\t /r \t \"l\"\t")]
|
||||
|
||||
[TestCase("[a]: \t /r")]
|
||||
[TestCase("[a]: \t /r \t ")]
|
||||
[TestCase("[a]: \t /r \t \"l\"")]
|
||||
[TestCase("[a]: \t /r \t \"l\"\t")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[a]: /r\n[b]: /r\n")]
|
||||
[TestCase("[a]: /r\n[b]: /r\n[c] /r\n")]
|
||||
public void TestMultiple(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[a]:\f/r\f\"l\"")]
|
||||
[TestCase("[a]:\v/r\v\"l\"")]
|
||||
public void TestUncommonWhitespace(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[a]:\n/r\n\"t\"")]
|
||||
[TestCase("[a]:\n/r\r\"t\"")]
|
||||
[TestCase("[a]:\n/r\r\n\"t\"")]
|
||||
|
||||
[TestCase("[a]:\r/r\n\"t\"")]
|
||||
[TestCase("[a]:\r/r\r\"t\"")]
|
||||
[TestCase("[a]:\r/r\r\n\"t\"")]
|
||||
|
||||
[TestCase("[a]:\r\n/r\n\"t\"")]
|
||||
[TestCase("[a]:\r\n/r\r\"t\"")]
|
||||
[TestCase("[a]:\r\n/r\r\n\"t\"")]
|
||||
|
||||
[TestCase("[a]:\n/r\n\"t\nt\"")]
|
||||
[TestCase("[a]:\n/r\n\"t\rt\"")]
|
||||
[TestCase("[a]:\n/r\n\"t\r\nt\"")]
|
||||
|
||||
[TestCase("[a]:\r\n /r\t \n \t \"t\r\nt\" ")]
|
||||
[TestCase("[a]:\n/r\n\n[a],")]
|
||||
[TestCase("[a]: /r\n[b]: /r\n\n[a],")]
|
||||
public void TestNewlines(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[ a]: /r")]
|
||||
[TestCase("[a ]: /r")]
|
||||
[TestCase("[ a ]: /r")]
|
||||
[TestCase("[ a]: /r")]
|
||||
[TestCase("[ a ]: /r")]
|
||||
[TestCase("[a ]: /r")]
|
||||
[TestCase("[ a ]: /r")]
|
||||
[TestCase("[ a ]: /r")]
|
||||
[TestCase("[a a]: /r")]
|
||||
[TestCase("[a\va]: /r")]
|
||||
[TestCase("[a\fa]: /r")]
|
||||
[TestCase("[a\ta]: /r")]
|
||||
[TestCase("[\va]: /r")]
|
||||
[TestCase("[\fa]: /r")]
|
||||
[TestCase("[\ta]: /r")]
|
||||
[TestCase(@"[\]]: /r")]
|
||||
public void TestLabel(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[a]: /r ()")]
|
||||
[TestCase("[a]: /r (t)")]
|
||||
[TestCase("[a]: /r ( t)")]
|
||||
[TestCase("[a]: /r (t )")]
|
||||
[TestCase("[a]: /r ( t )")]
|
||||
|
||||
[TestCase("[a]: /r ''")]
|
||||
[TestCase("[a]: /r 't'")]
|
||||
[TestCase("[a]: /r ' t'")]
|
||||
[TestCase("[a]: /r 't '")]
|
||||
[TestCase("[a]: /r ' t '")]
|
||||
public void Test_Title(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("[a]: /r\n===\n[a]")]
|
||||
public void TestSetextHeader(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/Markdig.Tests/RoundtripSpecs/TestNoBlocksFoundBlock.cs
Normal file
23
src/Markdig.Tests/RoundtripSpecs/TestNoBlocksFoundBlock.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestNoBlocksFoundBlock
|
||||
{
|
||||
[TestCase("\r")]
|
||||
[TestCase("\n")]
|
||||
[TestCase("\r\n")]
|
||||
[TestCase("\t")]
|
||||
[TestCase("\v")]
|
||||
[TestCase("\f")]
|
||||
[TestCase(" ")]
|
||||
[TestCase(" ")]
|
||||
[TestCase(" ")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
191
src/Markdig.Tests/RoundtripSpecs/TestOrderedList.cs
Normal file
191
src/Markdig.Tests/RoundtripSpecs/TestOrderedList.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestOrderedList
|
||||
{
|
||||
[TestCase("1. i")]
|
||||
[TestCase("1. i")]
|
||||
[TestCase("1. i ")]
|
||||
[TestCase("1. i ")]
|
||||
[TestCase("1. i ")]
|
||||
|
||||
[TestCase(" 1. i")]
|
||||
[TestCase(" 1. i")]
|
||||
[TestCase(" 1. i ")]
|
||||
[TestCase(" 1. i ")]
|
||||
[TestCase(" 1. i ")]
|
||||
|
||||
[TestCase(" 1. i")]
|
||||
[TestCase(" 1. i")]
|
||||
[TestCase(" 1. i ")]
|
||||
[TestCase(" 1. i ")]
|
||||
[TestCase(" 1. i ")]
|
||||
|
||||
[TestCase(" 1. i")]
|
||||
[TestCase(" 1. i")]
|
||||
[TestCase(" 1. i ")]
|
||||
[TestCase(" 1. i ")]
|
||||
[TestCase(" 1. i ")]
|
||||
|
||||
[TestCase("1. i\n")]
|
||||
[TestCase("1. i\n")]
|
||||
[TestCase("1. i \n")]
|
||||
[TestCase("1. i \n")]
|
||||
[TestCase("1. i \n")]
|
||||
|
||||
[TestCase(" 1. i\n")]
|
||||
[TestCase(" 1. i\n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
|
||||
[TestCase(" 1. i\n")]
|
||||
[TestCase(" 1. i\n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
|
||||
[TestCase(" 1. i\n")]
|
||||
[TestCase(" 1. i\n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
[TestCase(" 1. i \n")]
|
||||
|
||||
[TestCase("1. i\n2. j")]
|
||||
[TestCase("1. i\n2. j")]
|
||||
[TestCase("1. i \n2. j")]
|
||||
[TestCase("1. i \n2. j")]
|
||||
[TestCase("1. i \n2. j")]
|
||||
|
||||
[TestCase(" 1. i\n2. j")]
|
||||
[TestCase(" 1. i\n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
|
||||
[TestCase(" 1. i\n2. j")]
|
||||
[TestCase(" 1. i\n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
|
||||
[TestCase(" 1. i\n2. j")]
|
||||
[TestCase(" 1. i\n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
[TestCase(" 1. i \n2. j")]
|
||||
|
||||
[TestCase("1. i\n2. j\n")]
|
||||
[TestCase("1. i\n2. j\n")]
|
||||
[TestCase("1. i \n2. j\n")]
|
||||
[TestCase("1. i \n2. j\n")]
|
||||
[TestCase("1. i \n2. j\n")]
|
||||
|
||||
[TestCase(" 1. i\n2. j\n")]
|
||||
[TestCase(" 1. i\n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
|
||||
[TestCase(" 1. i\n2. j\n")]
|
||||
[TestCase(" 1. i\n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
|
||||
[TestCase(" 1. i\n2. j\n")]
|
||||
[TestCase(" 1. i\n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
[TestCase(" 1. i \n2. j\n")]
|
||||
|
||||
[TestCase("1. i\n2. j\n3. k")]
|
||||
[TestCase("1. i\n2. j\n3. k\n")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("10. i")]
|
||||
[TestCase("11. i")]
|
||||
[TestCase("10. i\n12. i")]
|
||||
[TestCase("2. i\n3. i")]
|
||||
public void Test_MoreThenOneStart(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
|
||||
[TestCase("\n1. i")]
|
||||
[TestCase("\r1. i")]
|
||||
[TestCase("\r\n1. i")]
|
||||
|
||||
[TestCase("\n1. i\n")]
|
||||
[TestCase("\r1. i\n")]
|
||||
[TestCase("\r\n1. i\n")]
|
||||
|
||||
[TestCase("\n1. i\r")]
|
||||
[TestCase("\r1. i\r")]
|
||||
[TestCase("\r\n1. i\r")]
|
||||
|
||||
[TestCase("\n1. i\r\n")]
|
||||
[TestCase("\r1. i\r\n")]
|
||||
[TestCase("\r\n1. i\r\n")]
|
||||
|
||||
[TestCase("1. i\n2. i")]
|
||||
[TestCase("\n1. i\n2. i")]
|
||||
[TestCase("\r1. i\n2. i")]
|
||||
[TestCase("\r\n1. i\n2. i")]
|
||||
|
||||
[TestCase("1. i\r2. i")]
|
||||
[TestCase("\n1. i\r2. i")]
|
||||
[TestCase("\r1. i\r2. i")]
|
||||
[TestCase("\r\n1. i\r2. i")]
|
||||
|
||||
[TestCase("1. i\r\n2. i")]
|
||||
[TestCase("\n1. i\r\n2. i")]
|
||||
[TestCase("\r1. i\r\n2. i")]
|
||||
[TestCase("\r\n1. i\r\n2. i")]
|
||||
|
||||
[TestCase("1. i\n2. i\n")]
|
||||
[TestCase("\n1. i\n2. i\n")]
|
||||
[TestCase("\r1. i\n2. i\n")]
|
||||
[TestCase("\r\n1. i\n2. i\n")]
|
||||
|
||||
[TestCase("1. i\r2. i\r")]
|
||||
[TestCase("\n1. i\r2. i\r")]
|
||||
[TestCase("\r1. i\r2. i\r")]
|
||||
[TestCase("\r\n1. i\r2. i\r")]
|
||||
|
||||
[TestCase("1. i\r\n2. i\r\n")]
|
||||
[TestCase("\n1. i\r\n2. i\r\n")]
|
||||
[TestCase("\r1. i\r\n2. i\r\n")]
|
||||
[TestCase("\r\n1. i\r\n2. i\r\n")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("1. i\n 1. i")]
|
||||
[TestCase("1. i\n 1. i\n")]
|
||||
[TestCase("1. i\n 1. i\n 2. i")]
|
||||
[TestCase("1. i\n 2. i\n 3. i")]
|
||||
|
||||
[TestCase("1. i\n\t1. i")]
|
||||
[TestCase("1. i\n\t1. i\n2. i")]
|
||||
public void TestMultipleLevels(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("1. c")]
|
||||
[TestCase("1. c")]
|
||||
public void Test_IndentedCodeBlock(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
247
src/Markdig.Tests/RoundtripSpecs/TestParagraph.cs
Normal file
247
src/Markdig.Tests/RoundtripSpecs/TestParagraph.cs
Normal file
@@ -0,0 +1,247 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestParagraph
|
||||
{
|
||||
[TestCase("p")]
|
||||
[TestCase(" p")]
|
||||
[TestCase("p ")]
|
||||
[TestCase(" p ")]
|
||||
|
||||
[TestCase("p\np")]
|
||||
[TestCase(" p\np")]
|
||||
[TestCase("p \np")]
|
||||
[TestCase(" p \np")]
|
||||
|
||||
[TestCase("p\n p")]
|
||||
[TestCase(" p\n p")]
|
||||
[TestCase("p \n p")]
|
||||
[TestCase(" p \n p")]
|
||||
|
||||
[TestCase("p\np ")]
|
||||
[TestCase(" p\np ")]
|
||||
[TestCase("p \np ")]
|
||||
[TestCase(" p \np ")]
|
||||
|
||||
[TestCase("p\n\n p ")]
|
||||
[TestCase(" p\n\n p ")]
|
||||
[TestCase("p \n\n p ")]
|
||||
[TestCase(" p \n\n p ")]
|
||||
|
||||
[TestCase("p\n\np")]
|
||||
[TestCase(" p\n\np")]
|
||||
[TestCase("p \n\np")]
|
||||
[TestCase(" p \n\np")]
|
||||
|
||||
[TestCase("p\n\n p")]
|
||||
[TestCase(" p\n\n p")]
|
||||
[TestCase("p \n\n p")]
|
||||
[TestCase(" p \n\n p")]
|
||||
|
||||
[TestCase("p\n\np ")]
|
||||
[TestCase(" p\n\np ")]
|
||||
[TestCase("p \n\np ")]
|
||||
[TestCase(" p \n\np ")]
|
||||
|
||||
[TestCase("p\n\n p ")]
|
||||
[TestCase(" p\n\n p ")]
|
||||
[TestCase("p \n\n p ")]
|
||||
[TestCase(" p \n\n p ")]
|
||||
|
||||
[TestCase("\np")]
|
||||
[TestCase("\n p")]
|
||||
[TestCase("\np ")]
|
||||
[TestCase("\n p ")]
|
||||
|
||||
[TestCase("\np\np")]
|
||||
[TestCase("\n p\np")]
|
||||
[TestCase("\np \np")]
|
||||
[TestCase("\n p \np")]
|
||||
|
||||
[TestCase("\np\n p")]
|
||||
[TestCase("\n p\n p")]
|
||||
[TestCase("\np \n p")]
|
||||
[TestCase("\n p \n p")]
|
||||
|
||||
[TestCase("\np\np ")]
|
||||
[TestCase("\n p\np ")]
|
||||
[TestCase("\np \np ")]
|
||||
[TestCase("\n p \np ")]
|
||||
|
||||
[TestCase("\np\n\n p ")]
|
||||
[TestCase("\n p\n\n p ")]
|
||||
[TestCase("\np \n\n p ")]
|
||||
[TestCase("\n p \n\n p ")]
|
||||
|
||||
[TestCase("\np\n\np")]
|
||||
[TestCase("\n p\n\np")]
|
||||
[TestCase("\np \n\np")]
|
||||
[TestCase("\n p \n\np")]
|
||||
|
||||
[TestCase("\np\n\n p")]
|
||||
[TestCase("\n p\n\n p")]
|
||||
[TestCase("\np \n\n p")]
|
||||
[TestCase("\n p \n\n p")]
|
||||
|
||||
[TestCase("\np\n\np ")]
|
||||
[TestCase("\n p\n\np ")]
|
||||
[TestCase("\np \n\np ")]
|
||||
[TestCase("\n p \n\np ")]
|
||||
|
||||
[TestCase("\np\n\n p ")]
|
||||
[TestCase("\n p\n\n p ")]
|
||||
[TestCase("\np \n\n p ")]
|
||||
[TestCase("\n p \n\n p ")]
|
||||
|
||||
[TestCase("p p")]
|
||||
[TestCase("p\tp")]
|
||||
[TestCase("p \tp")]
|
||||
[TestCase("p \t p")]
|
||||
[TestCase("p \tp")]
|
||||
|
||||
// special cases
|
||||
[TestCase(" p \n\n\n\n p \n\n")]
|
||||
[TestCase("\n\np")]
|
||||
[TestCase("p\n")]
|
||||
[TestCase("p\n\n")]
|
||||
[TestCase("p\np\n p")]
|
||||
[TestCase("p\np\n p\n p")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
|
||||
//[TestCase("\n")]
|
||||
//[TestCase("\r\n")]
|
||||
//[TestCase("\r")]
|
||||
|
||||
[TestCase("p\n")]
|
||||
[TestCase("p\r")]
|
||||
[TestCase("p\r\n")]
|
||||
|
||||
[TestCase("p\np")]
|
||||
[TestCase("p\rp")]
|
||||
[TestCase("p\r\np")]
|
||||
|
||||
[TestCase("p\np\n")]
|
||||
[TestCase("p\rp\n")]
|
||||
[TestCase("p\r\np\n")]
|
||||
|
||||
[TestCase("p\np\r")]
|
||||
[TestCase("p\rp\r")]
|
||||
[TestCase("p\r\np\r")]
|
||||
|
||||
[TestCase("p\np\r\n")]
|
||||
[TestCase("p\rp\r\n")]
|
||||
[TestCase("p\r\np\r\n")]
|
||||
|
||||
[TestCase("\np\n")]
|
||||
[TestCase("\np\r")]
|
||||
[TestCase("\np\r\n")]
|
||||
|
||||
[TestCase("\np\np")]
|
||||
[TestCase("\np\rp")]
|
||||
[TestCase("\np\r\np")]
|
||||
|
||||
[TestCase("\np\np\n")]
|
||||
[TestCase("\np\rp\n")]
|
||||
[TestCase("\np\r\np\n")]
|
||||
|
||||
[TestCase("\np\np\r")]
|
||||
[TestCase("\np\rp\r")]
|
||||
[TestCase("\np\r\np\r")]
|
||||
|
||||
[TestCase("\np\np\r\n")]
|
||||
[TestCase("\np\rp\r\n")]
|
||||
[TestCase("\np\r\np\r\n")]
|
||||
|
||||
[TestCase("\rp\n")]
|
||||
[TestCase("\rp\r")]
|
||||
[TestCase("\rp\r\n")]
|
||||
|
||||
[TestCase("\rp\np")]
|
||||
[TestCase("\rp\rp")]
|
||||
[TestCase("\rp\r\np")]
|
||||
|
||||
[TestCase("\rp\np\n")]
|
||||
[TestCase("\rp\rp\n")]
|
||||
[TestCase("\rp\r\np\n")]
|
||||
|
||||
[TestCase("\rp\np\r")]
|
||||
[TestCase("\rp\rp\r")]
|
||||
[TestCase("\rp\r\np\r")]
|
||||
|
||||
[TestCase("\rp\np\r\n")]
|
||||
[TestCase("\rp\rp\r\n")]
|
||||
[TestCase("\rp\r\np\r\n")]
|
||||
|
||||
[TestCase("\r\np\n")]
|
||||
[TestCase("\r\np\r")]
|
||||
[TestCase("\r\np\r\n")]
|
||||
|
||||
[TestCase("\r\np\np")]
|
||||
[TestCase("\r\np\rp")]
|
||||
[TestCase("\r\np\r\np")]
|
||||
|
||||
[TestCase("\r\np\np\n")]
|
||||
[TestCase("\r\np\rp\n")]
|
||||
[TestCase("\r\np\r\np\n")]
|
||||
|
||||
[TestCase("\r\np\np\r")]
|
||||
[TestCase("\r\np\rp\r")]
|
||||
[TestCase("\r\np\r\np\r")]
|
||||
|
||||
[TestCase("\r\np\np\r\n")]
|
||||
[TestCase("\r\np\rp\r\n")]
|
||||
[TestCase("\r\np\r\np\r\n")]
|
||||
|
||||
[TestCase("p\n")]
|
||||
[TestCase("p\n\n")]
|
||||
[TestCase("p\n\n\n")]
|
||||
[TestCase("p\n\n\n\n")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase(" \n")]
|
||||
[TestCase(" \r")]
|
||||
[TestCase(" \r\n")]
|
||||
|
||||
[TestCase(" \np")]
|
||||
[TestCase(" \rp")]
|
||||
[TestCase(" \r\np")]
|
||||
|
||||
[TestCase(" \np")]
|
||||
[TestCase(" \rp")]
|
||||
[TestCase(" \r\np")]
|
||||
|
||||
[TestCase(" \np")]
|
||||
[TestCase(" \rp")]
|
||||
[TestCase(" \r\np")]
|
||||
|
||||
[TestCase(" \n ")]
|
||||
[TestCase(" \r ")]
|
||||
[TestCase(" \r\n ")]
|
||||
|
||||
[TestCase(" \np ")]
|
||||
[TestCase(" \rp ")]
|
||||
[TestCase(" \r\np ")]
|
||||
|
||||
[TestCase(" \np ")]
|
||||
[TestCase(" \rp ")]
|
||||
[TestCase(" \r\np ")]
|
||||
|
||||
[TestCase(" \np ")]
|
||||
[TestCase(" \rp ")]
|
||||
[TestCase(" \r\np ")]
|
||||
public void Test_WhitespaceWithNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
286
src/Markdig.Tests/RoundtripSpecs/TestQuoteBlock.cs
Normal file
286
src/Markdig.Tests/RoundtripSpecs/TestQuoteBlock.cs
Normal file
@@ -0,0 +1,286 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestQuoteBlock
|
||||
{
|
||||
[TestCase(">q")]
|
||||
[TestCase(" >q")]
|
||||
[TestCase(" >q")]
|
||||
[TestCase(" >q")]
|
||||
[TestCase("> q")]
|
||||
[TestCase(" > q")]
|
||||
[TestCase(" > q")]
|
||||
[TestCase(" > q")]
|
||||
[TestCase("> q")]
|
||||
[TestCase(" > q")]
|
||||
[TestCase(" > q")]
|
||||
[TestCase(" > q")]
|
||||
|
||||
[TestCase(">q\n>q")]
|
||||
[TestCase(">q\n >q")]
|
||||
[TestCase(">q\n >q")]
|
||||
[TestCase(">q\n >q")]
|
||||
[TestCase(">q\n> q")]
|
||||
[TestCase(">q\n > q")]
|
||||
[TestCase(">q\n > q")]
|
||||
[TestCase(">q\n > q")]
|
||||
[TestCase(">q\n> q")]
|
||||
[TestCase(">q\n > q")]
|
||||
[TestCase(">q\n > q")]
|
||||
[TestCase(">q\n > q")]
|
||||
|
||||
[TestCase(" >q\n>q")]
|
||||
[TestCase(" >q\n >q")]
|
||||
[TestCase(" >q\n >q")]
|
||||
[TestCase(" >q\n >q")]
|
||||
[TestCase(" >q\n> q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n> q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
|
||||
[TestCase(" >q\n>q")]
|
||||
[TestCase(" >q\n >q")]
|
||||
[TestCase(" >q\n >q")]
|
||||
[TestCase(" >q\n >q")]
|
||||
[TestCase(" >q\n> q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n> q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
[TestCase(" >q\n > q")]
|
||||
|
||||
[TestCase("> q\n>q")]
|
||||
[TestCase("> q\n >q")]
|
||||
[TestCase("> q\n >q")]
|
||||
[TestCase("> q\n >q")]
|
||||
[TestCase("> q\n> q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n> q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n > q")]
|
||||
|
||||
[TestCase(" > q\n>q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
|
||||
[TestCase(" > q\n>q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
|
||||
[TestCase(" > q\n>q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
|
||||
[TestCase("> q\n>q")]
|
||||
[TestCase("> q\n >q")]
|
||||
[TestCase("> q\n >q")]
|
||||
[TestCase("> q\n >q")]
|
||||
[TestCase("> q\n> q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n> q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n > q")]
|
||||
[TestCase("> q\n > q")]
|
||||
|
||||
[TestCase(" > q\n>q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
|
||||
[TestCase(" > q\n>q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
|
||||
[TestCase(" > q\n>q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n >q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n> q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
[TestCase(" > q\n > q")]
|
||||
|
||||
[TestCase(">q\n>q\n>q")]
|
||||
[TestCase(">q\n>\n>q")]
|
||||
[TestCase(">q\np\n>q")]
|
||||
[TestCase(">q\n>\n>\n>q")]
|
||||
[TestCase(">q\n>\n>\n>\n>q")]
|
||||
[TestCase(">q\n>\n>q\n>\n>q")]
|
||||
[TestCase("p\n\n> **q**\n>p\n")]
|
||||
|
||||
[TestCase("> q\np\n> q")] // lazy
|
||||
[TestCase("> q\n> q\np")] // lazy
|
||||
|
||||
[TestCase(">>q")]
|
||||
[TestCase(" > > q")]
|
||||
|
||||
[TestCase("> **q**\n>p\n")]
|
||||
[TestCase("> **q**")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("> q")] // 5
|
||||
[TestCase("> q")] // 6
|
||||
[TestCase(" > q")] //5
|
||||
[TestCase(" > q")] //6
|
||||
[TestCase(" > \tq")]
|
||||
[TestCase("> q\n> q")] // 5, 5
|
||||
[TestCase("> q\n> q")] // 5, 6
|
||||
[TestCase("> q\n> q")] // 6, 5
|
||||
[TestCase("> q\n> q")] // 6, 6
|
||||
[TestCase("> q\n\n> 5")] // 5, 5
|
||||
public void TestIndentedCodeBlock(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("\n> q")]
|
||||
[TestCase("\n> q\n")]
|
||||
[TestCase("\n> q\n\n")]
|
||||
[TestCase("> q\n\np")]
|
||||
[TestCase("p\n\n> q\n\n# h")]
|
||||
|
||||
//https://github.com/lunet-io/markdig/issues/480
|
||||
//[TestCase(">\np")]
|
||||
//[TestCase(">**b**\n>\n>p\n>\np\n")]
|
||||
public void TestParagraph(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("> q\n\n# h\n")]
|
||||
public void TestAtxHeader(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase(">- i")]
|
||||
[TestCase("> - i")]
|
||||
[TestCase(">- i\n>- i")]
|
||||
[TestCase(">- >p")]
|
||||
[TestCase("> - >p")]
|
||||
[TestCase(">- i1\n>- i2\n")]
|
||||
[TestCase("> **p** p\n>- i1\n>- i2\n")]
|
||||
public void TestUnorderedList(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("> *q*\n>p\n")]
|
||||
[TestCase("> *q*")]
|
||||
public void TestEmphasis(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("> **q**\n>p\n")]
|
||||
[TestCase("> **q**")]
|
||||
public void TestStrongEmphasis(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase(">p\n")]
|
||||
[TestCase(">p\r")]
|
||||
[TestCase(">p\r\n")]
|
||||
|
||||
[TestCase(">p\n>p")]
|
||||
[TestCase(">p\r>p")]
|
||||
[TestCase(">p\r\n>p")]
|
||||
|
||||
[TestCase(">p\n>p\n")]
|
||||
[TestCase(">p\r>p\n")]
|
||||
[TestCase(">p\r\n>p\n")]
|
||||
|
||||
[TestCase(">p\n>p\r")]
|
||||
[TestCase(">p\r>p\r")]
|
||||
[TestCase(">p\r\n>p\r")]
|
||||
|
||||
[TestCase(">p\n>p\r\n")]
|
||||
[TestCase(">p\r>p\r\n")]
|
||||
[TestCase(">p\r\n>p\r\n")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase(">\n>q")]
|
||||
[TestCase(">\n>\n>q")]
|
||||
[TestCase(">q\n>\n>q")]
|
||||
[TestCase(">q\n>\n>\n>q")]
|
||||
[TestCase(">q\n> \n>q")]
|
||||
[TestCase(">q\n> \n>q")]
|
||||
[TestCase(">q\n> \n>q")]
|
||||
[TestCase(">q\n>\t\n>q")]
|
||||
[TestCase(">q\n>\v\n>q")]
|
||||
[TestCase(">q\n>\f\n>q")]
|
||||
public void TestEmptyLines(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/Markdig.Tests/RoundtripSpecs/TestSetextHeading.cs
Normal file
53
src/Markdig.Tests/RoundtripSpecs/TestSetextHeading.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSetextHeading
|
||||
{
|
||||
[TestCase("h1\n===")] //3
|
||||
[TestCase("h1\n ===")] //3
|
||||
[TestCase("h1\n ===")] //3
|
||||
[TestCase("h1\n ===")] //3
|
||||
[TestCase("h1\n=== ")] //3
|
||||
[TestCase("h1 \n===")] //3
|
||||
[TestCase("h1\\\n===")] //3
|
||||
[TestCase("h1\n === ")] //3
|
||||
[TestCase("h1\nh1 l2\n===")] //3
|
||||
[TestCase("h1\n====")] // 4
|
||||
[TestCase("h1\n ====")] // 4
|
||||
[TestCase("h1\n==== ")] // 4
|
||||
[TestCase("h1\n ==== ")] // 4
|
||||
[TestCase("h1\n===\nh1\n===")] //3
|
||||
[TestCase("\\>h1\n===")] //3
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("h1\r===")]
|
||||
[TestCase("h1\n===")]
|
||||
[TestCase("h1\r\n===")]
|
||||
|
||||
[TestCase("h1\r===\r")]
|
||||
[TestCase("h1\n===\r")]
|
||||
[TestCase("h1\r\n===\r")]
|
||||
|
||||
[TestCase("h1\r===\n")]
|
||||
[TestCase("h1\n===\n")]
|
||||
[TestCase("h1\r\n===\n")]
|
||||
|
||||
[TestCase("h1\r===\r\n")]
|
||||
[TestCase("h1\n===\r\n")]
|
||||
[TestCase("h1\r\n===\r\n")]
|
||||
|
||||
[TestCase("h1\n===\n\n\nh2---\n\n")]
|
||||
[TestCase("h1\r===\r\r\rh2---\r\r")]
|
||||
[TestCase("h1\r\n===\r\n\r\n\r\nh2---\r\n\r\n")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/Markdig.Tests/RoundtripSpecs/TestThematicBreak.cs
Normal file
53
src/Markdig.Tests/RoundtripSpecs/TestThematicBreak.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestThematicBreak
|
||||
{
|
||||
[TestCase("---")]
|
||||
[TestCase(" ---")]
|
||||
[TestCase(" ---")]
|
||||
[TestCase(" ---")]
|
||||
[TestCase("--- ")]
|
||||
[TestCase(" --- ")]
|
||||
[TestCase(" --- ")]
|
||||
[TestCase(" --- ")]
|
||||
[TestCase("- - -")]
|
||||
[TestCase(" - - -")]
|
||||
[TestCase(" - - - ")]
|
||||
[TestCase("-- -")]
|
||||
[TestCase("---\n")]
|
||||
[TestCase("---\n\n")]
|
||||
[TestCase("---\np")]
|
||||
[TestCase("---\n\np")]
|
||||
[TestCase("---\n# h")]
|
||||
[TestCase("p\n\n---")]
|
||||
// Note: "p\n---" is parsed as setext heading
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("\n---")]
|
||||
[TestCase("\r---")]
|
||||
[TestCase("\r\n---")]
|
||||
|
||||
[TestCase("\n---\n")]
|
||||
[TestCase("\r---\n")]
|
||||
[TestCase("\r\n---\n")]
|
||||
|
||||
[TestCase("\n---\r")]
|
||||
[TestCase("\r---\r")]
|
||||
[TestCase("\r\n---\r")]
|
||||
|
||||
[TestCase("\n---\r\n")]
|
||||
[TestCase("\r---\r\n")]
|
||||
[TestCase("\r\n---\r\n")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
183
src/Markdig.Tests/RoundtripSpecs/TestUnorderedList.cs
Normal file
183
src/Markdig.Tests/RoundtripSpecs/TestUnorderedList.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using NUnit.Framework;
|
||||
using static Markdig.Tests.TestRoundtrip;
|
||||
|
||||
namespace Markdig.Tests.RoundtripSpecs
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestUnorderedList
|
||||
{
|
||||
// i = item
|
||||
[TestCase("- i1")]
|
||||
[TestCase("- i1 ")]
|
||||
[TestCase("- i1\n")]
|
||||
[TestCase("- i1\n\n")]
|
||||
[TestCase("- i1\n- i2")]
|
||||
[TestCase("- i1\n - i2")]
|
||||
[TestCase("- i1\n - i1.1\n - i1.2")]
|
||||
[TestCase("- i1 \n- i2 \n")]
|
||||
[TestCase("- i1 \n- i2 \n")]
|
||||
[TestCase(" - i1")]
|
||||
[TestCase(" - i1")]
|
||||
[TestCase(" - i1")]
|
||||
[TestCase("- i1\n\n- i1")]
|
||||
[TestCase("- i1\n\n\n- i1")]
|
||||
[TestCase("- i1\n - i1.1\n - i1.1.1\n")]
|
||||
|
||||
[TestCase("-\ti1")]
|
||||
[TestCase("-\ti1\n-\ti2")]
|
||||
[TestCase("-\ti1\n- i2\n-\ti3")]
|
||||
public void Test(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("- > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase("- > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase("- > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase("- > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q")]
|
||||
[TestCase(" - > q1\n - > q2")]
|
||||
public void TestBlockQuote(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("- i1\n\np\n")] // TODO: listblock should render newline, apparently last paragraph of last listitem dont have newline
|
||||
[TestCase("- i1\n\n\np\n")]
|
||||
[TestCase("- i1\n\np")]
|
||||
[TestCase("- i1\n\np\n")]
|
||||
public void TestParagraph(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("- i1\n\n---\n")]
|
||||
[TestCase("- i1\n\n\n---\n")]
|
||||
public void TestThematicBreak(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("- c")] // 5
|
||||
[TestCase("- c\n c")] // 5, 6
|
||||
[TestCase(" - c\n c")] // 5, 6
|
||||
[TestCase(" - c\n c")] // 5, 7
|
||||
[TestCase("- c\n c")] // 6, 6
|
||||
[TestCase(" - c\n c")] // 6, 6
|
||||
[TestCase(" - c\n c")] // 6, 7
|
||||
public void TestIndentedCodeBlock(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("- ```a```")]
|
||||
[TestCase("- ```\n a\n```")]
|
||||
[TestCase("- i1\n - i1.1\n ```\n c\n ```")]
|
||||
[TestCase("- i1\n - i1.1\n ```\nc\n```")]
|
||||
[TestCase("- i1\n - i1.1\n ```\nc\n```\n")]
|
||||
public void TestFencedCodeBlock(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
|
||||
[TestCase("\n- i")]
|
||||
[TestCase("\r- i")]
|
||||
[TestCase("\r\n- i")]
|
||||
|
||||
[TestCase("\n- i\n")]
|
||||
[TestCase("\r- i\n")]
|
||||
[TestCase("\r\n- i\n")]
|
||||
|
||||
[TestCase("\n- i\r")]
|
||||
[TestCase("\r- i\r")]
|
||||
[TestCase("\r\n- i\r")]
|
||||
|
||||
[TestCase("\n- i\r\n")]
|
||||
[TestCase("\r- i\r\n")]
|
||||
[TestCase("\r\n- i\r\n")]
|
||||
|
||||
[TestCase("- i\n- j")]
|
||||
[TestCase("- i\r- j")]
|
||||
[TestCase("- i\r\n- j")]
|
||||
|
||||
[TestCase("\n- i\n- j")]
|
||||
[TestCase("\n- i\r- j")]
|
||||
[TestCase("\n- i\r\n- j")]
|
||||
|
||||
[TestCase("\r- i\n- j")]
|
||||
[TestCase("\r- i\r- j")]
|
||||
[TestCase("\r- i\r\n- j")]
|
||||
|
||||
[TestCase("\r\n- i\n- j")]
|
||||
[TestCase("\r\n- i\r- j")]
|
||||
[TestCase("\r\n- i\r\n- j")]
|
||||
|
||||
[TestCase("- i\n- j\n")]
|
||||
[TestCase("- i\r- j\n")]
|
||||
[TestCase("- i\r\n- j\n")]
|
||||
|
||||
[TestCase("\n- i\n- j\n")]
|
||||
[TestCase("\n- i\r- j\n")]
|
||||
[TestCase("\n- i\r\n- j\n")]
|
||||
|
||||
[TestCase("\r- i\n- j\n")]
|
||||
[TestCase("\r- i\r- j\n")]
|
||||
[TestCase("\r- i\r\n- j\n")]
|
||||
|
||||
[TestCase("\r\n- i\n- j\n")]
|
||||
[TestCase("\r\n- i\r- j\n")]
|
||||
[TestCase("\r\n- i\r\n- j\n")]
|
||||
|
||||
[TestCase("- i\n- j\r")]
|
||||
[TestCase("- i\r- j\r")]
|
||||
[TestCase("- i\r\n- j\r")]
|
||||
|
||||
[TestCase("\n- i\n- j\r")]
|
||||
[TestCase("\n- i\r- j\r")]
|
||||
[TestCase("\n- i\r\n- j\r")]
|
||||
|
||||
[TestCase("\r- i\n- j\r")]
|
||||
[TestCase("\r- i\r- j\r")]
|
||||
[TestCase("\r- i\r\n- j\r")]
|
||||
|
||||
[TestCase("\r\n- i\n- j\r")]
|
||||
[TestCase("\r\n- i\r- j\r")]
|
||||
[TestCase("\r\n- i\r\n- j\r")]
|
||||
|
||||
[TestCase("- i\n- j\r\n")]
|
||||
[TestCase("- i\r- j\r\n")]
|
||||
[TestCase("- i\r\n- j\r\n")]
|
||||
|
||||
[TestCase("\n- i\n- j\r\n")]
|
||||
[TestCase("\n- i\r- j\r\n")]
|
||||
[TestCase("\n- i\r\n- j\r\n")]
|
||||
|
||||
[TestCase("\r- i\n- j\r\n")]
|
||||
[TestCase("\r- i\r- j\r\n")]
|
||||
[TestCase("\r- i\r\n- j\r\n")]
|
||||
|
||||
[TestCase("\r\n- i\n- j\r\n")]
|
||||
[TestCase("\r\n- i\r- j\r\n")]
|
||||
[TestCase("\r\n- i\r\n- j\r\n")]
|
||||
|
||||
[TestCase("- i\n")]
|
||||
[TestCase("- i\n\n")]
|
||||
[TestCase("- i\n\n\n")]
|
||||
[TestCase("- i\n\n\n\n")]
|
||||
public void TestNewline(string value)
|
||||
{
|
||||
RoundTrip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
//
|
||||
// The rules for detecting a link are:
|
||||
//
|
||||
// - The project key must be composed of one or more capitalized ASCII letter `[A-Z]+`
|
||||
// - The project key must be composed of one or more capitalized ASCII letters or digits `[A-Z,0-9]+`
|
||||
// - A single hyphen `-` must separate the project key and issue number.
|
||||
// - The issue number is composed of 1 or more digits `[0, 9]+`
|
||||
// - The reference must be preceded by either `(` or whitespace or EOF.
|
||||
@@ -53,13 +53,13 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is a KIRA-1 issue
|
||||
// This is a ABC4-123 issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is a <a href="http://your.company.abc/browse/KIRA-1" target="blank">KIRA-1</a> issue</p>
|
||||
// <p>This is a <a href="http://your.company.abc/browse/ABC4-123" target="blank">ABC4-123</a> issue</p>
|
||||
|
||||
Console.WriteLine("Example 2\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is a KIRA-1 issue", "<p>This is a <a href=\"http://your.company.abc/browse/KIRA-1\" target=\"blank\">KIRA-1</a> issue</p>", "jiralinks");
|
||||
TestParser.TestSpec("This is a ABC4-123 issue", "<p>This is a <a href=\"http://your.company.abc/browse/ABC4-123\" target=\"blank\">ABC4-123</a> issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -69,16 +69,15 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is a Z-1 issue
|
||||
// This is a ABC45-123 issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is a <a href="http://your.company.abc/browse/Z-1" target="blank">Z-1</a> issue</p>
|
||||
// <p>This is a <a href="http://your.company.abc/browse/ABC45-123" target="blank">ABC45-123</a> issue</p>
|
||||
|
||||
Console.WriteLine("Example 3\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is a Z-1 issue", "<p>This is a <a href=\"http://your.company.abc/browse/Z-1\" target=\"blank\">Z-1</a> issue</p>", "jiralinks");
|
||||
TestParser.TestSpec("This is a ABC45-123 issue", "<p>This is a <a href=\"http://your.company.abc/browse/ABC45-123\" target=\"blank\">ABC45-123</a> issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
// These are also valid links with `(` and `)`:
|
||||
[Test]
|
||||
public void JiraLinks_Example004()
|
||||
{
|
||||
@@ -86,13 +85,13 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is a (ABCD-123) issue
|
||||
// This is a KIRA-1 issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is a (<a href="http://your.company.abc/browse/ABCD-123" target="blank">ABCD-123</a>) issue</p>
|
||||
// <p>This is a <a href="http://your.company.abc/browse/KIRA-1" target="blank">KIRA-1</a> issue</p>
|
||||
|
||||
Console.WriteLine("Example 4\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is a (ABCD-123) issue", "<p>This is a (<a href=\"http://your.company.abc/browse/ABCD-123\" target=\"blank\">ABCD-123</a>) issue</p>", "jiralinks");
|
||||
TestParser.TestSpec("This is a KIRA-1 issue", "<p>This is a <a href=\"http://your.company.abc/browse/KIRA-1\" target=\"blank\">KIRA-1</a> issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -102,15 +101,16 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is a (KIRA-1) issue
|
||||
// This is a Z-1 issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is a (<a href="http://your.company.abc/browse/KIRA-1" target="blank">KIRA-1</a>) issue</p>
|
||||
// <p>This is a <a href="http://your.company.abc/browse/Z-1" target="blank">Z-1</a> issue</p>
|
||||
|
||||
Console.WriteLine("Example 5\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is a (KIRA-1) issue", "<p>This is a (<a href=\"http://your.company.abc/browse/KIRA-1\" target=\"blank\">KIRA-1</a>) issue</p>", "jiralinks");
|
||||
TestParser.TestSpec("This is a Z-1 issue", "<p>This is a <a href=\"http://your.company.abc/browse/Z-1\" target=\"blank\">Z-1</a> issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
// These are also valid links with `(` and `)`:
|
||||
[Test]
|
||||
public void JiraLinks_Example006()
|
||||
{
|
||||
@@ -118,16 +118,15 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is a (Z-1) issue
|
||||
// This is a (ABCD-123) issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is a (<a href="http://your.company.abc/browse/Z-1" target="blank">Z-1</a>) issue</p>
|
||||
// <p>This is a (<a href="http://your.company.abc/browse/ABCD-123" target="blank">ABCD-123</a>) issue</p>
|
||||
|
||||
Console.WriteLine("Example 6\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is a (Z-1) issue", "<p>This is a (<a href=\"http://your.company.abc/browse/Z-1\" target=\"blank\">Z-1</a>) issue</p>", "jiralinks");
|
||||
TestParser.TestSpec("This is a (ABCD-123) issue", "<p>This is a (<a href=\"http://your.company.abc/browse/ABCD-123\" target=\"blank\">ABCD-123</a>) issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
// These are not valid links:
|
||||
[Test]
|
||||
public void JiraLinks_Example007()
|
||||
{
|
||||
@@ -135,13 +134,13 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is not aJIRA-123 issue
|
||||
// This is a (ABC4-123) issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is not aJIRA-123 issue</p>
|
||||
// <p>This is a (<a href="http://your.company.abc/browse/ABC4-123" target="blank">ABC4-123</a>) issue</p>
|
||||
|
||||
Console.WriteLine("Example 7\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is not aJIRA-123 issue", "<p>This is not aJIRA-123 issue</p>", "jiralinks");
|
||||
TestParser.TestSpec("This is a (ABC4-123) issue", "<p>This is a (<a href=\"http://your.company.abc/browse/ABC4-123\" target=\"blank\">ABC4-123</a>) issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -151,13 +150,13 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is not JIRA-123a issue
|
||||
// This is a (KIRA-1) issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is not JIRA-123a issue</p>
|
||||
// <p>This is a (<a href="http://your.company.abc/browse/KIRA-1" target="blank">KIRA-1</a>) issue</p>
|
||||
|
||||
Console.WriteLine("Example 8\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is not JIRA-123a issue", "<p>This is not JIRA-123a issue</p>", "jiralinks");
|
||||
TestParser.TestSpec("This is a (KIRA-1) issue", "<p>This is a (<a href=\"http://your.company.abc/browse/KIRA-1\" target=\"blank\">KIRA-1</a>) issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -167,13 +166,94 @@ namespace Markdig.Tests.Specs.JiraLinks
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is a (Z-1) issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is a (<a href="http://your.company.abc/browse/Z-1" target="blank">Z-1</a>) issue</p>
|
||||
|
||||
Console.WriteLine("Example 9\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is a (Z-1) issue", "<p>This is a (<a href=\"http://your.company.abc/browse/Z-1\" target=\"blank\">Z-1</a>) issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
// These are not valid links:
|
||||
[Test]
|
||||
public void JiraLinks_Example010()
|
||||
{
|
||||
// Example 10
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is not aJIRA-123 issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is not aJIRA-123 issue</p>
|
||||
|
||||
Console.WriteLine("Example 10\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is not aJIRA-123 issue", "<p>This is not aJIRA-123 issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JiraLinks_Example011()
|
||||
{
|
||||
// Example 11
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is not 4JIRA-123 issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is not 4JIRA-123 issue</p>
|
||||
|
||||
Console.WriteLine("Example 11\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is not 4JIRA-123 issue", "<p>This is not 4JIRA-123 issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JiraLinks_Example012()
|
||||
{
|
||||
// Example 12
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is not JIRA-123a issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is not JIRA-123a issue</p>
|
||||
|
||||
Console.WriteLine("Example 12\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is not JIRA-123a issue", "<p>This is not JIRA-123a issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JiraLinks_Example013()
|
||||
{
|
||||
// Example 13
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is not JIRA- issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is not JIRA- issue</p>
|
||||
|
||||
Console.WriteLine("Example 9\nSection Jira Links\n");
|
||||
Console.WriteLine("Example 13\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is not JIRA- issue", "<p>This is not JIRA- issue</p>", "jiralinks");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JiraLinks_Example014()
|
||||
{
|
||||
// Example 14
|
||||
// Section: Jira Links
|
||||
//
|
||||
// The following Markdown:
|
||||
// This is not JIR4- issue
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is not JIR4- issue</p>
|
||||
|
||||
Console.WriteLine("Example 14\nSection Jira Links\n");
|
||||
TestParser.TestSpec("This is not JIR4- issue", "<p>This is not JIR4- issue</p>", "jiralinks");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ var pipeline = new MarkdownPipelineBuilder()
|
||||
|
||||
The rules for detecting a link are:
|
||||
|
||||
- The project key must be composed of one or more capitalized ASCII letter `[A-Z]+`
|
||||
- The project key must be composed of one or more capitalized ASCII letters or digits `[A-Z,0-9]+`
|
||||
- A single hyphen `-` must separate the project key and issue number.
|
||||
- The issue number is composed of 1 or more digits `[0, 9]+`
|
||||
- The reference must be preceded by either `(` or whitespace or EOF.
|
||||
@@ -24,6 +24,18 @@ This is a ABCD-123 issue
|
||||
<p>This is a <a href="http://your.company.abc/browse/ABCD-123" target="blank">ABCD-123</a> issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is a ABC4-123 issue
|
||||
.
|
||||
<p>This is a <a href="http://your.company.abc/browse/ABC4-123" target="blank">ABC4-123</a> issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is a ABC45-123 issue
|
||||
.
|
||||
<p>This is a <a href="http://your.company.abc/browse/ABC45-123" target="blank">ABC45-123</a> issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is a KIRA-1 issue
|
||||
.
|
||||
@@ -44,6 +56,12 @@ This is a (ABCD-123) issue
|
||||
<p>This is a (<a href="http://your.company.abc/browse/ABCD-123" target="blank">ABCD-123</a>) issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is a (ABC4-123) issue
|
||||
.
|
||||
<p>This is a (<a href="http://your.company.abc/browse/ABC4-123" target="blank">ABC4-123</a>) issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is a (KIRA-1) issue
|
||||
.
|
||||
@@ -64,6 +82,12 @@ This is not aJIRA-123 issue
|
||||
<p>This is not aJIRA-123 issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is not 4JIRA-123 issue
|
||||
.
|
||||
<p>This is not 4JIRA-123 issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is not JIRA-123a issue
|
||||
.
|
||||
@@ -75,3 +99,9 @@ This is not JIRA- issue
|
||||
.
|
||||
<p>This is not JIRA- issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
This is not JIR4- issue
|
||||
.
|
||||
<p>This is not JIR4- issue</p>
|
||||
````````````````````````````````
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// 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.
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
var inputTag = "<a>";
|
||||
var text = new StringSlice(inputTag);
|
||||
Assert.True(HtmlHelper.TryParseHtmlTag(text, out string outputTag));
|
||||
Assert.True(HtmlHelper.TryParseHtmlTag(ref text, out string outputTag));
|
||||
Assert.AreEqual(inputTag, outputTag);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
var inputTag = "<a href='http://google.com'>";
|
||||
var text = new StringSlice(inputTag);
|
||||
Assert.True(HtmlHelper.TryParseHtmlTag(text, out string outputTag));
|
||||
Assert.True(HtmlHelper.TryParseHtmlTag(ref text, out string outputTag));
|
||||
Assert.AreEqual(inputTag, outputTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlSimple()
|
||||
{
|
||||
var text = new StringSlice("toto tutu");
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
Assert.AreEqual("toto", link);
|
||||
Assert.AreEqual(' ', text.CurrentChar);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlUrl()
|
||||
{
|
||||
var text = new StringSlice("http://google.com)");
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
Assert.AreEqual("http://google.com", link);
|
||||
Assert.AreEqual(')', text.CurrentChar);
|
||||
}
|
||||
@@ -35,7 +35,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlTrailingFullStop(string uri)
|
||||
{
|
||||
var text = new StringSlice(uri);
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, true));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _, true));
|
||||
Assert.AreEqual("http://google.com", link);
|
||||
Assert.AreEqual('.', text.CurrentChar);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlNestedParenthesis()
|
||||
{
|
||||
var text = new StringSlice("(toto)tutu(tata) nooo");
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
Assert.AreEqual("(toto)tutu(tata)", link);
|
||||
Assert.AreEqual(' ', text.CurrentChar);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlAlternate()
|
||||
{
|
||||
var text = new StringSlice("<toto_tata_tutu> nooo");
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
Assert.AreEqual("toto_tata_tutu", link);
|
||||
Assert.AreEqual(' ', text.CurrentChar);
|
||||
}
|
||||
@@ -62,14 +62,14 @@ namespace Markdig.Tests
|
||||
public void TestUrlAlternateInvalid()
|
||||
{
|
||||
var text = new StringSlice("<toto_tata_tutu");
|
||||
Assert.False(LinkHelper.TryParseUrl(ref text, out string link));
|
||||
Assert.False(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTitleSimple()
|
||||
{
|
||||
var text = new StringSlice(@"'tata\tutu\''");
|
||||
Assert.True(LinkHelper.TryParseTitle(ref text, out string title));
|
||||
Assert.True(LinkHelper.TryParseTitle(ref text, out string title, out _));
|
||||
Assert.AreEqual(@"tata\tutu'", title);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Markdig.Tests
|
||||
public void TestTitleSimpleAlternate()
|
||||
{
|
||||
var text = new StringSlice(@"""tata\tutu\"""" ");
|
||||
Assert.True(LinkHelper.TryParseTitle(ref text, out string title));
|
||||
Assert.True(LinkHelper.TryParseTitle(ref text, out string title, out _));
|
||||
Assert.AreEqual(@"tata\tutu""", title);
|
||||
Assert.AreEqual(' ', text.CurrentChar);
|
||||
}
|
||||
|
||||
@@ -11,11 +11,14 @@ namespace Markdig.Tests
|
||||
[Test]
|
||||
public void TestToHtml()
|
||||
{
|
||||
string html = Markdown.ToHtml("This is a text with some *emphasis*");
|
||||
Assert.AreEqual("<p>This is a text with some <em>emphasis</em></p>\n", html);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
string html = Markdown.ToHtml("This is a text with some *emphasis*");
|
||||
Assert.AreEqual("<p>This is a text with some <em>emphasis</em></p>\n", html);
|
||||
|
||||
html = Markdown.ToHtml("This is a text with a https://link.tld/");
|
||||
Assert.AreNotEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
html = Markdown.ToHtml("This is a text with a https://link.tld/");
|
||||
Assert.AreNotEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -24,49 +27,66 @@ namespace Markdig.Tests
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.Build();
|
||||
|
||||
string html = Markdown.ToHtml("This is a text with some *emphasis*", pipeline);
|
||||
Assert.AreEqual("<p>This is a text with some <em>emphasis</em></p>\n", html);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
string html = Markdown.ToHtml("This is a text with some *emphasis*", pipeline);
|
||||
Assert.AreEqual("<p>This is a text with some <em>emphasis</em></p>\n", html);
|
||||
|
||||
html = Markdown.ToHtml("This is a text with a https://link.tld/", pipeline);
|
||||
Assert.AreNotEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
html = Markdown.ToHtml("This is a text with a https://link.tld/", pipeline);
|
||||
Assert.AreNotEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
}
|
||||
|
||||
pipeline = new MarkdownPipelineBuilder()
|
||||
.UseAdvancedExtensions()
|
||||
.Build();
|
||||
|
||||
html = Markdown.ToHtml("This is a text with a https://link.tld/", pipeline);
|
||||
Assert.AreEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
string html = Markdown.ToHtml("This is a text with a https://link.tld/", pipeline);
|
||||
Assert.AreEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestToHtmlWithWriter()
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
var writer = new StringWriter();
|
||||
|
||||
_ = Markdown.ToHtml("This is a text with some *emphasis*", writer);
|
||||
string html = writer.ToString();
|
||||
Assert.AreEqual("<p>This is a text with some <em>emphasis</em></p>\n", html);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
_ = Markdown.ToHtml("This is a text with some *emphasis*", writer);
|
||||
string html = writer.ToString();
|
||||
Assert.AreEqual("<p>This is a text with some <em>emphasis</em></p>\n", html);
|
||||
writer.GetStringBuilder().Length = 0;
|
||||
}
|
||||
|
||||
writer = new StringWriter();
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.UseAdvancedExtensions()
|
||||
.Build();
|
||||
|
||||
_ = Markdown.ToHtml("This is a text with a https://link.tld/", writer, pipeline);
|
||||
html = writer.ToString();
|
||||
Assert.AreEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
_ = Markdown.ToHtml("This is a text with a https://link.tld/", writer, pipeline);
|
||||
string html = writer.ToString();
|
||||
Assert.AreEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
writer.GetStringBuilder().Length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConvert()
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
HtmlRenderer renderer = new HtmlRenderer(writer);
|
||||
var writer = new StringWriter();
|
||||
var renderer = new HtmlRenderer(writer);
|
||||
|
||||
_ = Markdown.Convert("This is a text with some *emphasis*", renderer);
|
||||
string html = writer.ToString();
|
||||
Assert.AreEqual("<p>This is a text with some <em>emphasis</em></p>\n", html);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
_ = Markdown.Convert("This is a text with some *emphasis*", renderer);
|
||||
string html = writer.ToString();
|
||||
Assert.AreEqual("<p>This is a text with some <em>emphasis</em></p>\n", html);
|
||||
writer.GetStringBuilder().Length = 0;
|
||||
}
|
||||
|
||||
writer = new StringWriter();
|
||||
renderer = new HtmlRenderer(writer);
|
||||
@@ -74,9 +94,13 @@ namespace Markdig.Tests
|
||||
.UseAdvancedExtensions()
|
||||
.Build();
|
||||
|
||||
_ = Markdown.Convert("This is a text with a https://link.tld/", renderer, pipeline);
|
||||
html = writer.ToString();
|
||||
Assert.AreEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
_ = Markdown.Convert("This is a text with a https://link.tld/", renderer, pipeline);
|
||||
string html = writer.ToString();
|
||||
Assert.AreEqual("<p>This is a text with a <a href=\"https://link.tld/\">https://link.tld/</a></p>\n", html);
|
||||
writer.GetStringBuilder().Length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -88,62 +112,77 @@ namespace Markdig.Tests
|
||||
.UsePreciseSourceLocation()
|
||||
.Build();
|
||||
|
||||
MarkdownDocument document = Markdown.Parse(markdown, pipeline);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
MarkdownDocument document = Markdown.Parse(markdown, pipeline);
|
||||
|
||||
Assert.AreEqual(1, document.LineCount);
|
||||
Assert.AreEqual(markdown.Length, document.Span.Length);
|
||||
Assert.AreEqual(1, document.LineStartIndexes.Count);
|
||||
Assert.AreEqual(0, document.LineStartIndexes[0]);
|
||||
Assert.AreEqual(1, document.LineCount);
|
||||
Assert.AreEqual(markdown.Length, document.Span.Length);
|
||||
Assert.AreEqual(1, document.LineStartIndexes.Count);
|
||||
Assert.AreEqual(0, document.LineStartIndexes[0]);
|
||||
|
||||
Assert.AreEqual(1, document.Count);
|
||||
ParagraphBlock paragraph = document[0] as ParagraphBlock;
|
||||
Assert.NotNull(paragraph);
|
||||
Assert.AreEqual(markdown.Length, paragraph.Span.Length);
|
||||
LiteralInline literal = paragraph.Inline.FirstChild as LiteralInline;
|
||||
Assert.NotNull(literal);
|
||||
Assert.AreEqual("This is a text with some ", literal.ToString());
|
||||
EmphasisInline emphasis = literal.NextSibling as EmphasisInline;
|
||||
Assert.NotNull(emphasis);
|
||||
Assert.AreEqual("*emphasis*".Length, emphasis.Span.Length);
|
||||
LiteralInline emphasisLiteral = emphasis.FirstChild as LiteralInline;
|
||||
Assert.NotNull(emphasisLiteral);
|
||||
Assert.AreEqual("emphasis", emphasisLiteral.ToString());
|
||||
Assert.Null(emphasisLiteral.NextSibling);
|
||||
Assert.Null(emphasis.NextSibling);
|
||||
Assert.AreEqual(1, document.Count);
|
||||
ParagraphBlock paragraph = document[0] as ParagraphBlock;
|
||||
Assert.NotNull(paragraph);
|
||||
Assert.AreEqual(markdown.Length, paragraph.Span.Length);
|
||||
LiteralInline literal = paragraph.Inline.FirstChild as LiteralInline;
|
||||
Assert.NotNull(literal);
|
||||
Assert.AreEqual("This is a text with some ", literal.ToString());
|
||||
EmphasisInline emphasis = literal.NextSibling as EmphasisInline;
|
||||
Assert.NotNull(emphasis);
|
||||
Assert.AreEqual("*emphasis*".Length, emphasis.Span.Length);
|
||||
LiteralInline emphasisLiteral = emphasis.FirstChild as LiteralInline;
|
||||
Assert.NotNull(emphasisLiteral);
|
||||
Assert.AreEqual("emphasis", emphasisLiteral.ToString());
|
||||
Assert.Null(emphasisLiteral.NextSibling);
|
||||
Assert.Null(emphasis.NextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNormalize()
|
||||
{
|
||||
string normalized = Markdown.Normalize("Heading\n=======");
|
||||
Assert.AreEqual("# Heading", normalized);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
string normalized = Markdown.Normalize("Heading\n=======");
|
||||
Assert.AreEqual("# Heading", normalized);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNormalizeWithWriter()
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
var writer = new StringWriter();
|
||||
|
||||
_ = Markdown.Normalize("Heading\n=======", writer);
|
||||
string normalized = writer.ToString();
|
||||
Assert.AreEqual("# Heading", normalized);
|
||||
_ = Markdown.Normalize("Heading\n=======", writer);
|
||||
string normalized = writer.ToString();
|
||||
Assert.AreEqual("# Heading", normalized);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestToPlainText()
|
||||
{
|
||||
string plainText = Markdown.ToPlainText("*Hello*, [world](http://example.com)!");
|
||||
Assert.AreEqual("Hello, world!\n", plainText);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
string plainText = Markdown.ToPlainText("*Hello*, [world](http://example.com)!");
|
||||
Assert.AreEqual("Hello, world!\n", plainText);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestToPlainTextWithWriter()
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
var writer = new StringWriter();
|
||||
|
||||
_ = Markdown.ToPlainText("*Hello*, [world](http://example.com)!", writer);
|
||||
string plainText = writer.ToString();
|
||||
Assert.AreEqual("Hello, world!\n", plainText);
|
||||
_ = Markdown.ToPlainText("*Hello*, [world](http://example.com)!", writer);
|
||||
string plainText = writer.ToString();
|
||||
Assert.AreEqual("Hello, world!\n", plainText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace Markdig.Tests
|
||||
AssertSyntax("````csharp\npublic void HelloWorld()\n{\n}\n````", new FencedCodeBlock(null)
|
||||
{
|
||||
FencedChar = '`',
|
||||
FencedCharCount = 4,
|
||||
OpeningFencedCharCount = 4,
|
||||
ClosingFencedCharCount = 4,
|
||||
Info = "csharp",
|
||||
Lines = new StringLineGroup(4)
|
||||
{
|
||||
|
||||
26
src/Markdig.Tests/TestPipeTable.cs
Normal file
26
src/Markdig.Tests/TestPipeTable.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Markdig.Extensions.Tables;
|
||||
using Markdig.Syntax;
|
||||
using NUnit.Framework;
|
||||
using System.Linq;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class TestPipeTable
|
||||
{
|
||||
[TestCase("| S | T |\r\n|---|---| \r\n| G | H |")]
|
||||
[TestCase("| S | T |\r\n|---|---|\t\r\n| G | H |")]
|
||||
[TestCase("| S | T |\r\n|---|---|\v\r\n| G | H |")]
|
||||
[TestCase("| S | T |\r\n|---|---|\f\r\n| G | H |")]
|
||||
[TestCase("| S | T |\r\n|---|---|\f\v\t \r\n| G | H |")]
|
||||
[TestCase("| S | \r\n|---|\r\n| G |\r\n\r\n| D | D |\r\n| ---| ---| \r\n| V | V |", 2)]
|
||||
public void TestTableBug(string markdown, int tableCount = 1)
|
||||
{
|
||||
MarkdownDocument document = Markdown.Parse(markdown, new MarkdownPipelineBuilder().UseAdvancedExtensions().Build());
|
||||
|
||||
Table[] tables = document.Descendants().OfType<Table>().ToArray();
|
||||
|
||||
Assert.AreEqual(tableCount, tables.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ namespace Markdig.Tests
|
||||
[TestCase(/* markdownText: */ "- foo\n- bar\n- baz", /* expected: */ "foo\nbar\nbaz\n")]
|
||||
[TestCase(/* markdownText: */ "- foo<baz", /* expected: */ "foo<baz\n")]
|
||||
[TestCase(/* markdownText: */ "- foo<baz", /* expected: */ "foo<baz\n")]
|
||||
[TestCase(/* markdownText: */ "## foo `bar::baz >`", /* expected: */ "foo bar::baz >\n")]
|
||||
public void TestPlainEnsureNewLine(string markdownText, string expected)
|
||||
{
|
||||
var actual = Markdown.ToPlainText(markdownText);
|
||||
|
||||
@@ -12,6 +12,16 @@ namespace Markdig.Tests
|
||||
[TestFixture]
|
||||
public class TestPlayParser
|
||||
{
|
||||
[Test]
|
||||
public void TestLinksWithCarriageReturn()
|
||||
{
|
||||
{
|
||||
var text = "[Link 1][link-1], [link 2][link-2].\r\n\r\n[link-1]: https://example.com\r\n[link-2]: https://example.com";
|
||||
var result = Markdown.ToHtml(text).TrimEnd();
|
||||
Assert.AreEqual("<p><a href=\"https://example.com\">Link 1</a>, <a href=\"https://example.com\">link 2</a>.</p>", result);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLink()
|
||||
{
|
||||
|
||||
@@ -37,20 +37,6 @@ namespace Markdig.Tests
|
||||
Assert.That(html, Contains.Substring($"rel=\"{expected}\""));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestLinksWithNullRel()
|
||||
{
|
||||
var markdown = "[world](http://example.com)";
|
||||
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.UseReferralLinks(null)
|
||||
.Build();
|
||||
var html = Markdown.ToHtml(markdown, pipeline);
|
||||
|
||||
Assert.That(html, !Contains.Substring("rel="));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(new[] { "noopener" }, "noopener")]
|
||||
[TestCase(new[] { "nofollow" }, "nofollow")]
|
||||
|
||||
30
src/Markdig.Tests/TestRoundtrip.cs
Normal file
30
src/Markdig.Tests/TestRoundtrip.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Markdig.Renderers.Roundtrip;
|
||||
using Markdig.Syntax;
|
||||
using NUnit.Framework;
|
||||
using System.IO;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
internal static class TestRoundtrip
|
||||
{
|
||||
internal static void TestSpec(string markdownText, string expected, string extensions)
|
||||
{
|
||||
RoundTrip(markdownText);
|
||||
}
|
||||
|
||||
internal static void RoundTrip(string markdown)
|
||||
{
|
||||
var pipelineBuilder = new MarkdownPipelineBuilder();
|
||||
pipelineBuilder.EnableTrackTrivia();
|
||||
MarkdownPipeline pipeline = pipelineBuilder.Build();
|
||||
MarkdownDocument markdownDocument = Markdown.Parse(markdown, pipeline);
|
||||
var sw = new StringWriter();
|
||||
var nr = new RoundtripRenderer(sw);
|
||||
|
||||
nr.Write(markdownDocument);
|
||||
|
||||
var result = sw.ToString();
|
||||
Assert.AreEqual(markdown, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,8 @@ namespace Markdig.Tests
|
||||
{
|
||||
var text = new StringLineGroup(4)
|
||||
{
|
||||
new StringSlice("ABC"),
|
||||
new StringSlice("E"),
|
||||
new StringSlice("ABC", NewLine.LineFeed),
|
||||
new StringSlice("E", NewLine.LineFeed),
|
||||
new StringSlice("F")
|
||||
};
|
||||
|
||||
@@ -35,8 +35,8 @@ namespace Markdig.Tests
|
||||
{
|
||||
var text = new StringLineGroup(4)
|
||||
{
|
||||
new StringSlice("XABC") { Start = 1},
|
||||
new StringSlice("YYE") { Start = 2},
|
||||
new StringSlice("XABC", NewLine.LineFeed) { Start = 1},
|
||||
new StringSlice("YYE", NewLine.LineFeed) { Start = 2},
|
||||
new StringSlice("ZZZF") { Start = 3 }
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
var text = new StringLineGroup(4)
|
||||
{
|
||||
new StringSlice("ABCD"),
|
||||
new StringSlice("ABCD", NewLine.LineFeed),
|
||||
new StringSlice("EF"),
|
||||
}.ToCharIterator();
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Markdig.Tests
|
||||
[Test]
|
||||
public void TestStringLineGroupWithModifiedStart()
|
||||
{
|
||||
var line1 = new StringSlice(" ABC");
|
||||
var line1 = new StringSlice(" ABC", NewLine.LineFeed);
|
||||
line1.NextChar();
|
||||
line1.NextChar();
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Markdig.Tests
|
||||
[Test]
|
||||
public void TestStringLineGroupWithTrim()
|
||||
{
|
||||
var line1 = new StringSlice(" ABC ");
|
||||
var line1 = new StringSlice(" ABC ", NewLine.LineFeed);
|
||||
line1.NextChar();
|
||||
line1.NextChar();
|
||||
|
||||
@@ -133,8 +133,8 @@ namespace Markdig.Tests
|
||||
{
|
||||
var iterator = new StringLineGroup(4)
|
||||
{
|
||||
new StringSlice("ABC"),
|
||||
new StringSlice("E"),
|
||||
new StringSlice("ABC", NewLine.LineFeed),
|
||||
new StringSlice("E", NewLine.LineFeed),
|
||||
new StringSlice("F")
|
||||
}.ToCharIterator();
|
||||
|
||||
@@ -153,5 +153,33 @@ namespace Markdig.Tests
|
||||
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => iterator.PeekChar(-1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestIteratorSkipChar()
|
||||
{
|
||||
var lineGroup = new StringLineGroup(4)
|
||||
{
|
||||
new StringSlice("ABC", NewLine.LineFeed),
|
||||
new StringSlice("E", NewLine.LineFeed)
|
||||
};
|
||||
|
||||
Test(lineGroup.ToCharIterator());
|
||||
|
||||
Test(new StringSlice("ABC\nE\n"));
|
||||
|
||||
Test(new StringSlice("Foo\nABC\nE\n", 4, 9));
|
||||
|
||||
static void Test<T>(T iterator) where T : ICharIterator
|
||||
{
|
||||
Assert.AreEqual('A', iterator.CurrentChar); iterator.SkipChar();
|
||||
Assert.AreEqual('B', iterator.CurrentChar); iterator.SkipChar();
|
||||
Assert.AreEqual('C', iterator.CurrentChar); iterator.SkipChar();
|
||||
Assert.AreEqual('\n', iterator.CurrentChar); iterator.SkipChar();
|
||||
Assert.AreEqual('E', iterator.CurrentChar); iterator.SkipChar();
|
||||
Assert.AreEqual('\n', iterator.CurrentChar); iterator.SkipChar();
|
||||
Assert.AreEqual('\0', iterator.CurrentChar); iterator.SkipChar();
|
||||
Assert.AreEqual('\0', iterator.CurrentChar); iterator.SkipChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<AssemblyName>Markdig.WebApp</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Markdig.WebApp</PackageId>
|
||||
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
|
||||
<ApplicationInsightsResourceId>/subscriptions/b6745039-70e7-4641-994b-5457cb220e2a/resourcegroups/Default-ApplicationInsights-EastUS/providers/microsoft.insights/components/Markdig.WebApp</ApplicationInsightsResourceId>
|
||||
<ApplicationInsightsAnnotationResourceId>/subscriptions/b6745039-70e7-4641-994b-5457cb220e2a/resourcegroups/Default-ApplicationInsights-EastUS/providers/microsoft.insights/components/Markdig.WebApp</ApplicationInsightsAnnotationResourceId>
|
||||
<IsPackable>false</IsPackable>
|
||||
<UserSecretsId>683145f2-53a7-4938-bd96-35e60ac55d95</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Views">
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</None>
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.16.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Markdig\Markdig.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.12.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Connected Services" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Markdig.WebApp
|
||||
{
|
||||
@@ -8,14 +9,14 @@ namespace Markdig.WebApp
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
[cmdletbinding(SupportsShouldProcess=$true)]
|
||||
param($publishProperties=@{}, $packOutput, $pubProfilePath, $nugetUrl)
|
||||
|
||||
# to learn more about this file visit https://go.microsoft.com/fwlink/?LinkId=524327
|
||||
$publishModuleVersion = '1.1.0'
|
||||
|
||||
function Get-PublishModulePath{
|
||||
[cmdletbinding()]
|
||||
param()
|
||||
process{
|
||||
$keysToCheck = @('hklm:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\{0}',
|
||||
'hklm:\SOFTWARE\Microsoft\VisualStudio\{0}',
|
||||
'hklm:\SOFTWARE\Wow6432Node\Microsoft\VWDExpress\{0}',
|
||||
'hklm:\SOFTWARE\Microsoft\VWDExpress\{0}'
|
||||
)
|
||||
$versions = @('14.0', '15.0')
|
||||
|
||||
[string]$publishModulePath=$null
|
||||
:outer foreach($keyToCheck in $keysToCheck){
|
||||
foreach($version in $versions){
|
||||
if(Test-Path ($keyToCheck -f $version) ){
|
||||
$vsInstallPath = (Get-itemproperty ($keyToCheck -f $version) -Name InstallDir -ErrorAction SilentlyContinue | select -ExpandProperty InstallDir -ErrorAction SilentlyContinue)
|
||||
|
||||
if($vsInstallPath){
|
||||
$installedPublishModulePath = "{0}Extensions\Microsoft\Web Tools\Publish\Scripts\{1}\" -f $vsInstallPath, $publishModuleVersion
|
||||
if(!(Test-Path $installedPublishModulePath)){
|
||||
$vsInstallPath = $vsInstallPath + 'VWDExpress'
|
||||
$installedPublishModulePath = "{0}Extensions\Microsoft\Web Tools\Publish\Scripts\{1}\" -f $vsInstallPath, $publishModuleVersion
|
||||
}
|
||||
if(Test-Path $installedPublishModulePath){
|
||||
$publishModulePath = $installedPublishModulePath
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$publishModulePath
|
||||
}
|
||||
}
|
||||
|
||||
$publishModulePath = Get-PublishModulePath
|
||||
|
||||
$defaultPublishSettings = New-Object psobject -Property @{
|
||||
LocalInstallDir = $publishModulePath
|
||||
}
|
||||
|
||||
function Enable-PackageDownloader{
|
||||
[cmdletbinding()]
|
||||
param(
|
||||
$toolsDir = "$env:LOCALAPPDATA\Microsoft\Web Tools\Publish\package-downloader-$publishModuleVersion\",
|
||||
$pkgDownloaderDownloadUrl = 'https://go.microsoft.com/fwlink/?LinkId=524325') # package-downloader.psm1
|
||||
process{
|
||||
if(get-module package-downloader){
|
||||
remove-module package-downloader | Out-Null
|
||||
}
|
||||
|
||||
if(!(get-module package-downloader)){
|
||||
if(!(Test-Path $toolsDir)){ New-Item -Path $toolsDir -ItemType Directory -WhatIf:$false }
|
||||
|
||||
$expectedPath = (Join-Path ($toolsDir) 'package-downloader.psm1')
|
||||
if(!(Test-Path $expectedPath)){
|
||||
'Downloading [{0}] to [{1}]' -f $pkgDownloaderDownloadUrl,$expectedPath | Write-Verbose
|
||||
(New-Object System.Net.WebClient).DownloadFile($pkgDownloaderDownloadUrl, $expectedPath)
|
||||
}
|
||||
|
||||
if(!$expectedPath){throw ('Unable to download package-downloader.psm1')}
|
||||
|
||||
'importing module [{0}]' -f $expectedPath | Write-Output
|
||||
Import-Module $expectedPath -DisableNameChecking -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Enable-PublishModule{
|
||||
[cmdletbinding()]
|
||||
param()
|
||||
process{
|
||||
if(get-module publish-module){
|
||||
remove-module publish-module | Out-Null
|
||||
}
|
||||
|
||||
if(!(get-module publish-module)){
|
||||
$localpublishmodulepath = Join-Path $defaultPublishSettings.LocalInstallDir 'publish-module.psm1'
|
||||
if(Test-Path $localpublishmodulepath){
|
||||
'importing module [publish-module="{0}"] from local install dir' -f $localpublishmodulepath | Write-Verbose
|
||||
Import-Module $localpublishmodulepath -DisableNameChecking -Force
|
||||
$true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try{
|
||||
|
||||
if (!(Enable-PublishModule)){
|
||||
Enable-PackageDownloader
|
||||
Enable-NuGetModule -name 'publish-module' -version $publishModuleVersion -nugetUrl $nugetUrl
|
||||
}
|
||||
|
||||
'Calling Publish-AspNet' | Write-Verbose
|
||||
# call Publish-AspNet to perform the publish operation
|
||||
Publish-AspNet -publishProperties $publishProperties -packOutput $packOutput -pubProfilePath $pubProfilePath
|
||||
}
|
||||
catch{
|
||||
"An error occurred during publish.`n{0}" -f $_.Exception.Message | Write-Error
|
||||
}
|
||||
@@ -1,28 +1,9 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:65396/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"Markdig.WebApp": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "http://localhost:5000/api/to_html?text=yes",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
"launchUrl": "api/to_html?text=test"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,19 +30,30 @@ namespace Markdig.WebApp
|
||||
// This method gets called by the runtime. Use this method to add services to the container
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllers();
|
||||
|
||||
// Add framework services.
|
||||
services.AddApplicationInsightsTelemetry(Configuration);
|
||||
|
||||
services.AddMvc();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||
{
|
||||
//loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||
//loggerFactory.AddDebug();
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseMvc();
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
}
|
||||
},
|
||||
"ApplicationInsights": {
|
||||
"InstrumentationKey": "5d12f113-76b2-41fe-a35a-db454b104bf9"
|
||||
"InstrumentationKey": "5d12f113-76b2-41fe-a35a-db454b104bf9",
|
||||
"ConnectionString": "InstrumentationKey=c00ad051-d881-4dc3-b8c1-8718f1b1c0c6;IngestionEndpoint=https://westus2-0.in.applicationinsights.azure.com/"
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<!--
|
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
|
||||
-->
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// 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.
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Markdig.Extensions.Abbreviations
|
||||
/// <summary>
|
||||
/// Gets or sets the label.
|
||||
/// </summary>
|
||||
public string Label { get; set; }
|
||||
public string? Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The text associated to this label.
|
||||
|
||||
@@ -22,12 +22,12 @@ namespace Markdig.Extensions.Abbreviations
|
||||
|
||||
public static void AddAbbreviation(this MarkdownDocument document, string label, Abbreviation abbr)
|
||||
{
|
||||
if (document == null) ThrowHelper.ArgumentNullException(nameof(document));
|
||||
if (label == null) ThrowHelper.ArgumentNullException_label();
|
||||
if (abbr == null) ThrowHelper.ArgumentNullException(nameof(abbr));
|
||||
if (document is null) ThrowHelper.ArgumentNullException(nameof(document));
|
||||
if (label is null) ThrowHelper.ArgumentNullException_label();
|
||||
if (abbr is null) ThrowHelper.ArgumentNullException(nameof(abbr));
|
||||
|
||||
var map = document.GetAbbreviations();
|
||||
if (map == null)
|
||||
if (map is null)
|
||||
{
|
||||
map = new Dictionary<string, Abbreviation>();
|
||||
document.SetData(DocumentKey, map);
|
||||
@@ -35,7 +35,7 @@ namespace Markdig.Extensions.Abbreviations
|
||||
map[label] = abbr;
|
||||
}
|
||||
|
||||
public static Dictionary<string, Abbreviation> GetAbbreviations(this MarkdownDocument document)
|
||||
public static Dictionary<string, Abbreviation>? GetAbbreviations(this MarkdownDocument document)
|
||||
{
|
||||
return document.GetData(DocumentKey) as Dictionary<string, Abbreviation>;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// 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.
|
||||
|
||||
@@ -14,13 +14,6 @@ namespace Markdig.Extensions.Abbreviations
|
||||
[DebuggerDisplay("{Abbreviation}")]
|
||||
public class AbbreviationInline : LeafInline
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbbreviationInline"/> class.
|
||||
/// </summary>
|
||||
public AbbreviationInline()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbbreviationInline"/> class.
|
||||
/// </summary>
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Markdig.Extensions.Abbreviations
|
||||
return BlockState.None;
|
||||
}
|
||||
|
||||
if (!LinkHelper.TryParseLabel(ref slice, out string label, out SourceSpan labelSpan))
|
||||
if (!LinkHelper.TryParseLabel(ref slice, out string? label, out SourceSpan labelSpan))
|
||||
{
|
||||
return BlockState.None;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace Markdig.Extensions.Abbreviations
|
||||
{
|
||||
return BlockState.None;
|
||||
}
|
||||
slice.NextChar();
|
||||
slice.SkipChar();
|
||||
|
||||
slice.Trim();
|
||||
|
||||
@@ -73,13 +73,13 @@ namespace Markdig.Extensions.Abbreviations
|
||||
return BlockState.BreakDiscard;
|
||||
}
|
||||
|
||||
private void DocumentOnProcessInlinesBegin(InlineProcessor inlineProcessor, Inline inline)
|
||||
private void DocumentOnProcessInlinesBegin(InlineProcessor inlineProcessor, Inline? inline)
|
||||
{
|
||||
inlineProcessor.Document.ProcessInlinesBegin -= DocumentOnProcessInlinesBegin;
|
||||
|
||||
var abbreviations = inlineProcessor.Document.GetAbbreviations();
|
||||
// Should not happen, but another extension could decide to remove them, so...
|
||||
if (abbreviations == null)
|
||||
if (abbreviations is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -89,10 +89,10 @@ namespace Markdig.Extensions.Abbreviations
|
||||
|
||||
inlineProcessor.LiteralInlineParser.PostMatch += (InlineProcessor processor, ref StringSlice slice) =>
|
||||
{
|
||||
var literal = (LiteralInline)processor.Inline;
|
||||
var literal = (LiteralInline)processor.Inline!;
|
||||
var originalLiteral = literal;
|
||||
|
||||
ContainerInline container = null;
|
||||
ContainerInline? container = null;
|
||||
|
||||
// This is slow, but we don't have much the choice
|
||||
var content = literal.Content;
|
||||
@@ -127,7 +127,7 @@ namespace Markdig.Extensions.Abbreviations
|
||||
var indexAfterMatch = i + match.Length;
|
||||
|
||||
// If we don't have a container, create a new one
|
||||
if (container == null)
|
||||
if (container is null)
|
||||
{
|
||||
container = literal.Parent ??
|
||||
new ContainerInline
|
||||
@@ -150,7 +150,7 @@ namespace Markdig.Extensions.Abbreviations
|
||||
abbrInline.Span.End = abbrInline.Span.Start + match.Length - 1;
|
||||
|
||||
// Append the previous literal
|
||||
if (i > content.Start && literal.Parent == null)
|
||||
if (i > content.Start && literal.Parent is null)
|
||||
{
|
||||
container.AppendChild(literal);
|
||||
}
|
||||
|
||||
@@ -74,15 +74,14 @@ namespace Markdig.Extensions.AutoIdentifiers
|
||||
|
||||
var text = headingLine.ToString();
|
||||
|
||||
var linkRef = new HeadingLinkReferenceDefinition()
|
||||
var linkRef = new HeadingLinkReferenceDefinition(headingBlock)
|
||||
{
|
||||
Heading = headingBlock,
|
||||
CreateLinkInline = CreateLinkInlineForHeading
|
||||
};
|
||||
|
||||
var doc = processor.Document;
|
||||
var dictionary = doc.GetData(this) as Dictionary<string, HeadingLinkReferenceDefinition>;
|
||||
if (dictionary == null)
|
||||
if (dictionary is null)
|
||||
{
|
||||
dictionary = new Dictionary<string, HeadingLinkReferenceDefinition>();
|
||||
doc.SetData(this, dictionary);
|
||||
@@ -95,11 +94,11 @@ namespace Markdig.Extensions.AutoIdentifiers
|
||||
headingBlock.ProcessInlinesEnd += HeadingBlock_ProcessInlinesEnd;
|
||||
}
|
||||
|
||||
private void DocumentOnProcessInlinesBegin(InlineProcessor processor, Inline inline)
|
||||
private void DocumentOnProcessInlinesBegin(InlineProcessor processor, Inline? inline)
|
||||
{
|
||||
var doc = processor.Document;
|
||||
doc.ProcessInlinesBegin -= DocumentOnProcessInlinesBegin;
|
||||
var dictionary = (Dictionary<string, HeadingLinkReferenceDefinition>)doc.GetData(this);
|
||||
var dictionary = (Dictionary<string, HeadingLinkReferenceDefinition>)doc.GetData(this)!;
|
||||
foreach (var keyPair in dictionary)
|
||||
{
|
||||
// Here we make sure that auto-identifiers will not override an existing link definition
|
||||
@@ -107,7 +106,7 @@ namespace Markdig.Extensions.AutoIdentifiers
|
||||
// If it is the case, we skip the auto identifier for the Heading
|
||||
if (!doc.TryGetLinkReferenceDefinition(keyPair.Key, out var linkDef))
|
||||
{
|
||||
doc.SetLinkReferenceDefinition(keyPair.Key, keyPair.Value);
|
||||
doc.SetLinkReferenceDefinition(keyPair.Key, keyPair.Value, true);
|
||||
}
|
||||
}
|
||||
// Once we are done, we don't need to keep the intermediate dictionary around
|
||||
@@ -118,7 +117,7 @@ namespace Markdig.Extensions.AutoIdentifiers
|
||||
/// Callback when there is a reference to found to a heading.
|
||||
/// Note that reference are only working if they are declared after.
|
||||
/// </summary>
|
||||
private Inline CreateLinkInlineForHeading(InlineProcessor inlineState, LinkReferenceDefinition linkRef, Inline child)
|
||||
private Inline CreateLinkInlineForHeading(InlineProcessor inlineState, LinkReferenceDefinition linkRef, Inline? child)
|
||||
{
|
||||
var headingRef = (HeadingLinkReferenceDefinition) linkRef;
|
||||
return new LinkInline()
|
||||
@@ -135,23 +134,23 @@ namespace Markdig.Extensions.AutoIdentifiers
|
||||
/// </summary>
|
||||
/// <param name="processor">The processor.</param>
|
||||
/// <param name="inline">The inline.</param>
|
||||
private void HeadingBlock_ProcessInlinesEnd(InlineProcessor processor, Inline inline)
|
||||
private void HeadingBlock_ProcessInlinesEnd(InlineProcessor processor, Inline? inline)
|
||||
{
|
||||
var identifiers = processor.Document.GetData(AutoIdentifierKey) as HashSet<string>;
|
||||
if (identifiers == null)
|
||||
if (identifiers is null)
|
||||
{
|
||||
identifiers = new HashSet<string>();
|
||||
processor.Document.SetData(AutoIdentifierKey, identifiers);
|
||||
}
|
||||
|
||||
var headingBlock = (HeadingBlock) processor.Block;
|
||||
if (headingBlock.Inline == null)
|
||||
var headingBlock = (HeadingBlock) processor.Block!;
|
||||
if (headingBlock.Inline is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If id is already set, don't try to modify it
|
||||
var attributes = processor.Block.GetAttributes();
|
||||
var attributes = processor.Block!.GetAttributes();
|
||||
if (attributes.Id != null)
|
||||
{
|
||||
return;
|
||||
@@ -161,7 +160,7 @@ namespace Markdig.Extensions.AutoIdentifiers
|
||||
var stripRenderer = rendererCache.Get();
|
||||
|
||||
stripRenderer.Render(headingBlock.Inline);
|
||||
var headingText = stripRenderer.Writer.ToString();
|
||||
var headingText = stripRenderer.Writer.ToString()!;
|
||||
rendererCache.Release(stripRenderer);
|
||||
|
||||
// Urilize the link
|
||||
|
||||
@@ -12,6 +12,11 @@ namespace Markdig.Extensions.AutoIdentifiers
|
||||
/// <seealso cref="LinkReferenceDefinition" />
|
||||
public class HeadingLinkReferenceDefinition : LinkReferenceDefinition
|
||||
{
|
||||
public HeadingLinkReferenceDefinition(HeadingBlock headling)
|
||||
{
|
||||
Heading = headling;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the heading related to this link reference definition.
|
||||
/// </summary>
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Markdig.Extensions.AutoLinks
|
||||
{
|
||||
public readonly AutoLinkOptions Options;
|
||||
|
||||
public AutoLinkExtension(AutoLinkOptions options)
|
||||
public AutoLinkExtension(AutoLinkOptions? options)
|
||||
{
|
||||
Options = options ?? new AutoLinkOptions();
|
||||
}
|
||||
|
||||
@@ -105,7 +105,8 @@ namespace Markdig.Extensions.AutoLinks
|
||||
break;
|
||||
}
|
||||
|
||||
if (!LinkHelper.TryParseUrl(ref slice, out string link, true))
|
||||
// Parse URL
|
||||
if (!LinkHelper.TryParseUrl(ref slice, out string? link, out _, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using Markdig.Parsers.Inlines;
|
||||
using Markdig.Renderers;
|
||||
using Markdig.Renderers.Html.Inlines;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Markdig.Extensions.Citations
|
||||
{
|
||||
@@ -40,7 +40,7 @@ namespace Markdig.Extensions.Citations
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTag(EmphasisInline emphasisInline)
|
||||
private static string? GetTag(EmphasisInline emphasisInline)
|
||||
{
|
||||
Debug.Assert(emphasisInline.DelimiterCount <= 2);
|
||||
return emphasisInline.DelimiterCount == 2 && emphasisInline.DelimiterChar == '"' ? "cite" : null;
|
||||
|
||||
@@ -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 Markdig.Helpers;
|
||||
using Markdig.Parsers;
|
||||
using Markdig.Syntax;
|
||||
|
||||
@@ -22,12 +23,40 @@ namespace Markdig.Extensions.CustomContainers
|
||||
{
|
||||
}
|
||||
|
||||
public string Info { get; set; }
|
||||
|
||||
public string Arguments { get; set; }
|
||||
|
||||
public int FencedCharCount { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public char FencedChar { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int OpeningFencedCharCount { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public StringSlice TriviaAfterFencedChar { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Info { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public StringSlice UnescapedInfo { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public StringSlice TriviaAfterInfo { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Arguments { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public StringSlice UnescapedArguments { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public StringSlice TriviaAfterArguments { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public NewLine InfoNewLine { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public StringSlice TriviaBeforeClosingFence { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int ClosingFencedCharCount { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace Markdig.Extensions.CustomContainers
|
||||
{
|
||||
protected override void Write(HtmlRenderer renderer, CustomContainerInline obj)
|
||||
{
|
||||
renderer.Write("<span").WriteAttributes(obj).Write(">");
|
||||
renderer.Write("<span").WriteAttributes(obj).Write('>');
|
||||
renderer.WriteChildren(obj);
|
||||
renderer.Write("</span>");
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Markdig.Extensions.CustomContainers
|
||||
renderer.EnsureLine();
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("<div").WriteAttributes(obj).Write(">");
|
||||
renderer.Write("<div").WriteAttributes(obj).Write('>');
|
||||
}
|
||||
// We don't escape a CustomContainer
|
||||
renderer.WriteChildren(obj);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
{
|
||||
var paragraphBlock = processor.LastBlock as ParagraphBlock;
|
||||
if (processor.IsCodeIndent || paragraphBlock == null || paragraphBlock.LastLine - processor.LineIndex > 1)
|
||||
if (processor.IsCodeIndent || paragraphBlock is null || paragraphBlock.LastLine - processor.LineIndex > 1)
|
||||
{
|
||||
return BlockState.None;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
processor.GoToColumn(column + 4);
|
||||
}
|
||||
|
||||
var previousParent = paragraphBlock.Parent;
|
||||
var previousParent = paragraphBlock.Parent!;
|
||||
var currentDefinitionList = GetCurrentDefinitionList(paragraphBlock, previousParent);
|
||||
|
||||
processor.Discard(paragraphBlock);
|
||||
@@ -61,7 +61,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
paragraphBlock.Parent.Remove(paragraphBlock);
|
||||
}
|
||||
|
||||
if (currentDefinitionList == null)
|
||||
if (currentDefinitionList is null)
|
||||
{
|
||||
currentDefinitionList = new DefinitionList(this)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
Span = new SourceSpan(paragraphBlock.Span.Start, paragraphBlock.Span.End),
|
||||
IsOpen = false
|
||||
};
|
||||
term.AppendLine(ref line.Slice, line.Column, line.Line, line.Position);
|
||||
term.AppendLine(ref line.Slice, line.Column, line.Line, line.Position, processor.TrackTrivia);
|
||||
definitionItem.Add(term);
|
||||
}
|
||||
currentDefinitionList.Add(definitionItem);
|
||||
@@ -102,7 +102,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
return BlockState.Continue;
|
||||
}
|
||||
|
||||
private static DefinitionList GetCurrentDefinitionList(ParagraphBlock paragraphBlock, ContainerBlock previousParent)
|
||||
private static DefinitionList? GetCurrentDefinitionList(ParagraphBlock paragraphBlock, ContainerBlock previousParent)
|
||||
{
|
||||
var index = previousParent.IndexOf(paragraphBlock) - 1;
|
||||
if (index < 0) return null;
|
||||
@@ -124,11 +124,11 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
return BlockState.Continue;
|
||||
}
|
||||
|
||||
var list = (DefinitionList)definitionItem.Parent;
|
||||
var list = (DefinitionList)definitionItem.Parent!;
|
||||
var lastBlankLine = definitionItem.LastChild as BlankLineBlock;
|
||||
|
||||
// Check if we have another definition list
|
||||
if (Array.IndexOf(OpeningCharacters, processor.CurrentChar) >= 0)
|
||||
if (Array.IndexOf(OpeningCharacters!, processor.CurrentChar) >= 0)
|
||||
{
|
||||
var startPosition = processor.Start;
|
||||
var column = processor.ColumnBeforeIndent;
|
||||
@@ -145,7 +145,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
definitionItem.RemoveAt(definitionItem.Count - 1);
|
||||
}
|
||||
|
||||
list.Span.End = list.LastChild.Span.End;
|
||||
list.Span.End = list.LastChild!.Span.End;
|
||||
return BlockState.None;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
var isBreakable = definitionItem.LastChild?.IsBreakable ?? true;
|
||||
if (processor.IsBlankLine)
|
||||
{
|
||||
if (lastBlankLine == null && isBreakable)
|
||||
if (lastBlankLine is null && isBreakable)
|
||||
{
|
||||
definitionItem.Add(new BlankLineBlock());
|
||||
}
|
||||
@@ -179,7 +179,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
}
|
||||
|
||||
var paragraphBlock = definitionItem.LastChild as ParagraphBlock;
|
||||
if (lastBlankLine == null && paragraphBlock != null)
|
||||
if (lastBlankLine is null && paragraphBlock != null)
|
||||
{
|
||||
return BlockState.Continue;
|
||||
}
|
||||
@@ -190,7 +190,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
definitionItem.RemoveAt(definitionItem.Count - 1);
|
||||
}
|
||||
|
||||
list.Span.End = list.LastChild.Span.End;
|
||||
list.Span.End = list.LastChild!.Span.End;
|
||||
return BlockState.Break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
protected override void Write(HtmlRenderer renderer, DefinitionList list)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
renderer.Write("<dl").WriteAttributes(list).WriteLine(">");
|
||||
renderer.Write("<dl").WriteAttributes(list).WriteLine('>');
|
||||
foreach (var item in list)
|
||||
{
|
||||
bool hasOpendd = false;
|
||||
@@ -41,7 +41,7 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
hasOpendd = false;
|
||||
countdd = 0;
|
||||
}
|
||||
renderer.Write("<dt").WriteAttributes(definitionTerm).Write(">");
|
||||
renderer.Write("<dt").WriteAttributes(definitionTerm).Write('>');
|
||||
renderer.WriteLeafInline(definitionTerm);
|
||||
renderer.WriteLine("</dt>");
|
||||
}
|
||||
@@ -49,13 +49,13 @@ namespace Markdig.Extensions.DefinitionLists
|
||||
{
|
||||
if (!hasOpendd)
|
||||
{
|
||||
renderer.Write("<dd").WriteAttributes(definitionItem).Write(">");
|
||||
renderer.Write("<dd").WriteAttributes(definitionItem).Write('>');
|
||||
countdd = 0;
|
||||
hasOpendd = true;
|
||||
}
|
||||
|
||||
var nextTerm = i + 1 < definitionItem.Count ? definitionItem[i + 1] : null;
|
||||
bool isSimpleParagraph = (nextTerm == null || nextTerm is DefinitionItem) && countdd == 0 &&
|
||||
bool isSimpleParagraph = (nextTerm is null || nextTerm is DefinitionItem) && countdd == 0 &&
|
||||
definitionTermOrContent is ParagraphBlock;
|
||||
|
||||
var saveImplicitParagraph = renderer.ImplicitParagraph;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Markdig.Extensions.Diagrams
|
||||
{
|
||||
if (renderer is HtmlRenderer htmlRenderer)
|
||||
{
|
||||
var codeRenderer = htmlRenderer.ObjectRenderers.FindExact<CodeBlockRenderer>();
|
||||
var codeRenderer = htmlRenderer.ObjectRenderers.FindExact<CodeBlockRenderer>()!;
|
||||
// TODO: Add other well known diagram languages
|
||||
codeRenderer.BlocksAsDiv.Add("mermaid");
|
||||
codeRenderer.BlocksAsDiv.Add("nomnoml");
|
||||
|
||||
@@ -34,6 +34,6 @@ namespace Markdig.Extensions.Emoji
|
||||
/// <summary>
|
||||
/// Gets or sets the original match string (either an emoji shortcode or a text smiley)
|
||||
/// </summary>
|
||||
public string Match { get; set; }
|
||||
public string? Match { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1745,10 +1745,10 @@ namespace Markdig.Extensions.Emoji
|
||||
/// </summary>
|
||||
public EmojiMapping(IDictionary<string, string> shortcodeToUnicode, IDictionary<string, string> smileyToShortcode)
|
||||
{
|
||||
if (shortcodeToUnicode == null)
|
||||
if (shortcodeToUnicode is null)
|
||||
ThrowHelper.ArgumentNullException(nameof(shortcodeToUnicode));
|
||||
|
||||
if (smileyToShortcode == null)
|
||||
if (smileyToShortcode is null)
|
||||
ThrowHelper.ArgumentNullException(nameof(smileyToShortcode));
|
||||
|
||||
// Build emojis and smileys CompactPrefixTree
|
||||
@@ -1778,7 +1778,7 @@ namespace Markdig.Extensions.Emoji
|
||||
if (string.IsNullOrEmpty(smiley.Key) || string.IsNullOrEmpty(smiley.Value))
|
||||
ThrowHelper.ArgumentException("The dictionaries cannot contain null or empty keys/values", nameof(smileyToShortcode));
|
||||
|
||||
if (!shortcodeToUnicode.TryGetValue(smiley.Value, out string unicode))
|
||||
if (!shortcodeToUnicode.TryGetValue(smiley.Value, out string? unicode))
|
||||
ThrowHelper.ArgumentException(string.Format("Invalid smiley target: {0} is not present in the emoji shortcodes dictionary", smiley.Value));
|
||||
|
||||
firstChars.Add(smiley.Key[0]);
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Markdig.Extensions.EmphasisExtras
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTag(EmphasisInline emphasisInline)
|
||||
private string? GetTag(EmphasisInline emphasisInline)
|
||||
{
|
||||
var c = emphasisInline.DelimiterChar;
|
||||
switch (c)
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Markdig.Extensions.Figures
|
||||
Column = column + line.Start - startPosition,
|
||||
IsOpen = false
|
||||
};
|
||||
caption.AppendLine(ref line, caption.Column, processor.LineIndex, processor.CurrentLineStartPosition);
|
||||
caption.AppendLine(ref line, caption.Column, processor.LineIndex, processor.CurrentLineStartPosition, processor.TrackTrivia);
|
||||
figure.Add(caption);
|
||||
}
|
||||
processor.NewBlocks.Push(figure);
|
||||
@@ -96,7 +96,7 @@ namespace Markdig.Extensions.Figures
|
||||
Column = column + line.Start - startPosition,
|
||||
IsOpen = false
|
||||
};
|
||||
caption.AppendLine(ref line, caption.Column, processor.LineIndex, processor.CurrentLineStartPosition);
|
||||
caption.AppendLine(ref line, caption.Column, processor.LineIndex, processor.CurrentLineStartPosition, processor.TrackTrivia);
|
||||
figure.Add(caption);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Markdig.Extensions.Figures
|
||||
protected override void Write(HtmlRenderer renderer, FigureCaption obj)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
renderer.Write("<figcaption").WriteAttributes(obj).Write(">");
|
||||
renderer.Write("<figcaption").WriteAttributes(obj).Write('>');
|
||||
renderer.WriteLeafInline(obj);
|
||||
renderer.WriteLine("</figcaption>");
|
||||
}
|
||||
|
||||
@@ -16,14 +16,13 @@ namespace Markdig.Extensions.Footnotes
|
||||
{
|
||||
public Footnote(BlockParser parser) : base(parser)
|
||||
{
|
||||
Links = new List<FootnoteLink>();
|
||||
Order = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the label used by this footnote.
|
||||
/// </summary>
|
||||
public string Label { get; set; }
|
||||
public string? Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the order of this footnote (determined by the order of the <see cref="FootnoteLink"/> in the document)
|
||||
@@ -33,7 +32,7 @@ namespace Markdig.Extensions.Footnotes
|
||||
/// <summary>
|
||||
/// Gets the links referencing this footnote.
|
||||
/// </summary>
|
||||
public List<FootnoteLink> Links { get; private set; }
|
||||
public List<FootnoteLink> Links { get; } = new ();
|
||||
|
||||
/// <summary>
|
||||
/// The label span
|
||||
|
||||
@@ -12,6 +12,11 @@ namespace Markdig.Extensions.Footnotes
|
||||
/// <seealso cref="Inline" />
|
||||
public class FootnoteLink : Inline
|
||||
{
|
||||
public FootnoteLink(Footnote footnote)
|
||||
{
|
||||
Footnote = footnote;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is back link (from a footnote to the link)
|
||||
/// </summary>
|
||||
|
||||
@@ -12,6 +12,11 @@ namespace Markdig.Extensions.Footnotes
|
||||
/// <seealso cref="LinkReferenceDefinition" />
|
||||
public class FootnoteLinkReferenceDefinition : LinkReferenceDefinition
|
||||
{
|
||||
public FootnoteLinkReferenceDefinition(Footnote footnote)
|
||||
{
|
||||
Footnote = footnote;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the footnote related to this link reference definition.
|
||||
/// </summary>
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Markdig.Extensions.Footnotes
|
||||
|
||||
var saved = processor.Column;
|
||||
int start = processor.Start;
|
||||
if (!LinkHelper.TryParseLabel(ref processor.Line, false, out string label, out SourceSpan labelSpan) || !label.StartsWith("^") || processor.CurrentChar != ':')
|
||||
if (!LinkHelper.TryParseLabel(ref processor.Line, false, out string? label, out SourceSpan labelSpan) || !label.StartsWith("^") || processor.CurrentChar != ':')
|
||||
{
|
||||
processor.GoToColumn(saved);
|
||||
return BlockState.None;
|
||||
@@ -70,16 +70,15 @@ namespace Markdig.Extensions.Footnotes
|
||||
}
|
||||
footnotes.Add(footnote);
|
||||
|
||||
var linkRef = new FootnoteLinkReferenceDefinition()
|
||||
var linkRef = new FootnoteLinkReferenceDefinition(footnote)
|
||||
{
|
||||
Footnote = footnote,
|
||||
CreateLinkInline = CreateLinkToFootnote,
|
||||
Line = processor.LineIndex,
|
||||
Span = new SourceSpan(start, processor.Start - 2), // account for ]:
|
||||
LabelSpan = labelSpan,
|
||||
Label = label
|
||||
};
|
||||
processor.Document.SetLinkReferenceDefinition(footnote.Label, linkRef);
|
||||
processor.Document.SetLinkReferenceDefinition(footnote.Label, linkRef, true);
|
||||
processor.NewBlocks.Push(footnote);
|
||||
return BlockState.Continue;
|
||||
}
|
||||
@@ -130,12 +129,12 @@ namespace Markdig.Extensions.Footnotes
|
||||
/// </summary>
|
||||
/// <param name="state">The processor.</param>
|
||||
/// <param name="inline">The inline.</param>
|
||||
private void Document_ProcessInlinesEnd(InlineProcessor state, Inline inline)
|
||||
private void Document_ProcessInlinesEnd(InlineProcessor state, Inline? inline)
|
||||
{
|
||||
// Unregister
|
||||
state.Document.ProcessInlinesEnd -= Document_ProcessInlinesEnd;
|
||||
|
||||
var footnotes = ((FootnoteGroup)state.Document.GetData(DocumentKey));
|
||||
var footnotes = (FootnoteGroup)state.Document.GetData(DocumentKey)!;
|
||||
// Remove the footnotes from the document and readd them at the end
|
||||
state.Document.Remove(footnotes);
|
||||
state.Document.Add(footnotes);
|
||||
@@ -166,7 +165,7 @@ namespace Markdig.Extensions.Footnotes
|
||||
|
||||
// Insert all footnote backlinks
|
||||
var paragraphBlock = footnote.LastChild as ParagraphBlock;
|
||||
if (paragraphBlock == null)
|
||||
if (paragraphBlock is null)
|
||||
{
|
||||
paragraphBlock = new ParagraphBlock();
|
||||
footnote.Add(paragraphBlock);
|
||||
@@ -180,28 +179,27 @@ namespace Markdig.Extensions.Footnotes
|
||||
{
|
||||
linkIndex++;
|
||||
link.Index = linkIndex;
|
||||
var backLink = new FootnoteLink()
|
||||
var backLink = new FootnoteLink(footnote)
|
||||
{
|
||||
Index = linkIndex,
|
||||
IsBackLink = true,
|
||||
Footnote = footnote
|
||||
IsBackLink = true
|
||||
};
|
||||
paragraphBlock.Inline.AppendChild(backLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Inline CreateLinkToFootnote(InlineProcessor state, LinkReferenceDefinition linkRef, Inline child)
|
||||
private static Inline CreateLinkToFootnote(InlineProcessor state, LinkReferenceDefinition linkRef, Inline? child)
|
||||
{
|
||||
var footnote = ((FootnoteLinkReferenceDefinition)linkRef).Footnote;
|
||||
if (footnote.Order < 0)
|
||||
{
|
||||
var footnotes = (FootnoteGroup)state.Document.GetData(DocumentKey);
|
||||
var footnotes = (FootnoteGroup)state.Document.GetData(DocumentKey)!;
|
||||
footnotes.CurrentOrder++;
|
||||
footnote.Order = footnotes.CurrentOrder;
|
||||
}
|
||||
|
||||
var link = new FootnoteLink() {Footnote = footnote};
|
||||
var link = new FootnoteLink(footnote);
|
||||
footnote.Links.Add(link);
|
||||
|
||||
return link;
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
var copy = line;
|
||||
copy.Start = indexOfAttributes;
|
||||
var startOfAttributes = copy.Start;
|
||||
if (GenericAttributesParser.TryParse(ref copy, out HtmlAttributes attributes))
|
||||
if (GenericAttributesParser.TryParse(ref copy, out HtmlAttributes? attributes))
|
||||
{
|
||||
var htmlAttributes = block.GetAttributes();
|
||||
attributes.CopyTo(htmlAttributes);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using Markdig.Helpers;
|
||||
using Markdig.Parsers;
|
||||
using Markdig.Renderers.Html;
|
||||
@@ -28,7 +30,7 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
public override bool Match(InlineProcessor processor, ref StringSlice slice)
|
||||
{
|
||||
var startPosition = slice.Start;
|
||||
if (TryParse(ref slice, out HtmlAttributes attributes))
|
||||
if (TryParse(ref slice, out HtmlAttributes? attributes))
|
||||
{
|
||||
var inline = processor.Inline;
|
||||
|
||||
@@ -45,16 +47,16 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
}
|
||||
}
|
||||
}
|
||||
var objectToAttach = inline == null || inline == processor.Root ? (MarkdownObject) processor.Block : inline;
|
||||
var objectToAttach = inline is null || inline == processor.Root ? (MarkdownObject)processor.Block! : inline;
|
||||
|
||||
// If the current block is a Paragraph, but only the HtmlAttributes is used,
|
||||
// Try to attach the attributes to the following block
|
||||
if (objectToAttach is ParagraphBlock paragraph &&
|
||||
paragraph.Inline.FirstChild == null &&
|
||||
processor.Inline == null &&
|
||||
paragraph.Inline!.FirstChild is null &&
|
||||
processor.Inline is null &&
|
||||
slice.IsEmptyOrWhitespace())
|
||||
{
|
||||
var parent = paragraph.Parent;
|
||||
var parent = paragraph.Parent!;
|
||||
var indexOfParagraph = parent.IndexOf(paragraph);
|
||||
if (indexOfParagraph + 1 < parent.Count)
|
||||
{
|
||||
@@ -86,7 +88,7 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
/// <param name="slice">The slice to parse.</param>
|
||||
/// <param name="attributes">The output attributes or null if not found or invalid</param>
|
||||
/// <returns><c>true</c> if parsing the HTML attributes was successful</returns>
|
||||
public static bool TryParse(ref StringSlice slice, out HtmlAttributes attributes)
|
||||
public static bool TryParse(ref StringSlice slice, [NotNullWhen(true)] out HtmlAttributes? attributes)
|
||||
{
|
||||
attributes = null;
|
||||
if (slice.PeekCharExtra(-1) == '{')
|
||||
@@ -96,9 +98,9 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
|
||||
var line = slice;
|
||||
|
||||
string id = null;
|
||||
List<string> classes = null;
|
||||
List<KeyValuePair<string, string>> properties = null;
|
||||
string? id = null;
|
||||
List<string>? classes = null;
|
||||
List<KeyValuePair<string, string?>>? properties = null;
|
||||
|
||||
bool isValid = false;
|
||||
var c = line.NextChar();
|
||||
@@ -107,7 +109,7 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
if (c == '}')
|
||||
{
|
||||
isValid = true;
|
||||
line.NextChar(); // skip }
|
||||
line.SkipChar(); // skip }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -135,7 +137,7 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
var text = slice.Text.Substring(start, end - start + 1);
|
||||
if (isClass)
|
||||
{
|
||||
if (classes == null)
|
||||
if (classes is null)
|
||||
{
|
||||
classes = new List<string>();
|
||||
}
|
||||
@@ -175,12 +177,10 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
// Handle boolean properties that are not followed by =
|
||||
if ((hasSpace && (c == '.' || c == '#' || IsStartAttributeName(c))) || c == '}')
|
||||
{
|
||||
if (properties == null)
|
||||
{
|
||||
properties = new List<KeyValuePair<string, string>>();
|
||||
}
|
||||
properties ??= new ();
|
||||
|
||||
// Add a null value for the property
|
||||
properties.Add(new KeyValuePair<string, string>(name, null));
|
||||
properties.Add(new KeyValuePair<string, string?>(name, null));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
}
|
||||
|
||||
// Go to next char, skip any spaces
|
||||
line.NextChar();
|
||||
line.SkipChar();
|
||||
line.TrimStart();
|
||||
|
||||
int startValue = -1;
|
||||
@@ -245,11 +245,8 @@ namespace Markdig.Extensions.GenericAttributes
|
||||
|
||||
var value = slice.Text.Substring(startValue, endValue - startValue + 1);
|
||||
|
||||
if (properties == null)
|
||||
{
|
||||
properties = new List<KeyValuePair<string, string>>();
|
||||
}
|
||||
properties.Add(new KeyValuePair<string, string>(name, value));
|
||||
properties ??= new();
|
||||
properties.Add(new KeyValuePair<string, string?>(name, value));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using Markdig.Renderers.Html;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Markdig.Extensions.Globalization
|
||||
{
|
||||
@@ -51,7 +52,7 @@ namespace Markdig.Extensions.Globalization
|
||||
|
||||
}
|
||||
|
||||
private bool ShouldBeRightToLeft(MarkdownObject item)
|
||||
private static bool ShouldBeRightToLeft(MarkdownObject item)
|
||||
{
|
||||
if (item is IEnumerable<MarkdownObject> container)
|
||||
{
|
||||
@@ -67,7 +68,7 @@ namespace Markdig.Extensions.Globalization
|
||||
}
|
||||
else if (item is LeafBlock leaf)
|
||||
{
|
||||
return ShouldBeRightToLeft(leaf.Inline);
|
||||
return ShouldBeRightToLeft(leaf.Inline!);
|
||||
}
|
||||
else if (item is LiteralInline literal)
|
||||
{
|
||||
@@ -76,7 +77,7 @@ namespace Markdig.Extensions.Globalization
|
||||
|
||||
foreach (var paragraph in item.Descendants<ParagraphBlock>())
|
||||
{
|
||||
foreach (var inline in paragraph.Inline)
|
||||
foreach (var inline in paragraph.Inline!)
|
||||
{
|
||||
if (inline is LiteralInline literal)
|
||||
{
|
||||
@@ -88,14 +89,30 @@ namespace Markdig.Extensions.Globalization
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool StartsWithRtlCharacter(StringSlice slice)
|
||||
private static bool StartsWithRtlCharacter(StringSlice slice)
|
||||
{
|
||||
foreach (var c in CharHelper.ToUtf32(slice))
|
||||
for (int i = slice.Start; i <= slice.End; i++)
|
||||
{
|
||||
if (CharHelper.IsRightToLeft(c))
|
||||
if (slice[i] < 128)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int rune;
|
||||
if (CharHelper.IsHighSurrogate(slice[i]) && i < slice.End && CharHelper.IsLowSurrogate(slice[i + 1]))
|
||||
{
|
||||
Debug.Assert(char.IsSurrogatePair(slice[i], slice[i + 1]));
|
||||
rune = char.ConvertToUtf32(slice[i], slice[i + 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
rune = slice[i];
|
||||
}
|
||||
|
||||
if (CharHelper.IsRightToLeft(rune))
|
||||
return true;
|
||||
|
||||
else if (CharHelper.IsLeftToRight(c))
|
||||
if (CharHelper.IsLeftToRight(rune))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,8 +40,14 @@ namespace Markdig.Extensions.JiraLinks
|
||||
var startKey = slice.Start;
|
||||
var endKey = slice.Start;
|
||||
|
||||
//read as many uppercase characters as required - project key
|
||||
while (current.IsAlphaUpper())
|
||||
// the first character of the key can not be a digit.
|
||||
if (current.IsDigit())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// read as many uppercase characters or digits as required - project key
|
||||
while (current.IsAlphaUpper() || current.IsDigit())
|
||||
{
|
||||
endKey = slice.Start;
|
||||
current = slice.NextChar();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using Markdig.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace Markdig.Extensions.MediaLinks
|
||||
@@ -13,12 +14,23 @@ namespace Markdig.Extensions.MediaLinks
|
||||
{
|
||||
private sealed class DelegateProvider : IHostProvider
|
||||
{
|
||||
public string HostPrefix { get; set; }
|
||||
public Func<Uri, string> Delegate { get; set; }
|
||||
public bool AllowFullScreen { get; set; } = true;
|
||||
public string Class { get; set; }
|
||||
public DelegateProvider(string hostPrefix, Func<Uri, string?> handler, bool allowFullscreen = true, string? className = null)
|
||||
{
|
||||
HostPrefix = hostPrefix;
|
||||
Delegate = handler;
|
||||
AllowFullScreen = allowFullscreen;
|
||||
Class = className;
|
||||
}
|
||||
|
||||
public bool TryHandle(Uri mediaUri, bool isSchemaRelative, out string iframeUrl)
|
||||
public string HostPrefix { get; }
|
||||
|
||||
public Func<Uri, string?> Delegate { get; }
|
||||
|
||||
public bool AllowFullScreen { get; }
|
||||
|
||||
public string? Class { get; }
|
||||
|
||||
public bool TryHandle(Uri mediaUri, bool isSchemaRelative, [NotNullWhen(true)] out string? iframeUrl)
|
||||
{
|
||||
if (!mediaUri.Host.StartsWith(HostPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -38,14 +50,14 @@ namespace Markdig.Extensions.MediaLinks
|
||||
/// <param name="allowFullScreen">Should the generated iframe has allowfullscreen attribute.</param>
|
||||
/// <param name="iframeClass">"class" attribute of generated iframe.</param>
|
||||
/// <returns>A <see cref="IHostProvider"/> with delegate handler.</returns>
|
||||
public static IHostProvider Create(string hostPrefix, Func<Uri, string> handler, bool allowFullScreen = true, string iframeClass = null)
|
||||
public static IHostProvider Create(string hostPrefix, Func<Uri, string?> handler, bool allowFullScreen = true, string? iframeClass = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hostPrefix))
|
||||
ThrowHelper.ArgumentException("hostPrefix is null or empty.", nameof(hostPrefix));
|
||||
if (handler == null)
|
||||
if (handler is null)
|
||||
ThrowHelper.ArgumentNullException(nameof(handler));
|
||||
|
||||
return new DelegateProvider { HostPrefix = hostPrefix, Delegate = handler, AllowFullScreen = allowFullScreen, Class = iframeClass };
|
||||
return new DelegateProvider(hostPrefix, handler, allowFullScreen, iframeClass);
|
||||
}
|
||||
|
||||
internal static Dictionary<string, IHostProvider> KnownHosts { get; }
|
||||
@@ -67,7 +79,7 @@ namespace Markdig.Extensions.MediaLinks
|
||||
return query.Split(SplitAnd, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
private static string YouTube(Uri uri)
|
||||
private static string? YouTube(Uri uri)
|
||||
{
|
||||
string uriPath = uri.AbsolutePath;
|
||||
if (string.Equals(uriPath, "/embed", StringComparison.OrdinalIgnoreCase) || uriPath.StartsWith("/embed/", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -80,20 +92,20 @@ namespace Markdig.Extensions.MediaLinks
|
||||
}
|
||||
var queryParams = SplitQuery(uri);
|
||||
return BuildYouTubeIframeUrl(
|
||||
queryParams.FirstOrDefault(p => p.StartsWith("v="))?.Substring(2),
|
||||
queryParams.FirstOrDefault(p => p.StartsWith("t="))?.Substring(2)
|
||||
queryParams.FirstOrDefault(p => p.StartsWith("v=", StringComparison.Ordinal))?.Substring(2),
|
||||
queryParams.FirstOrDefault(p => p.StartsWith("t=", StringComparison.Ordinal))?.Substring(2)
|
||||
);
|
||||
}
|
||||
|
||||
private static string YouTubeShortened(Uri uri)
|
||||
private static string? YouTubeShortened(Uri uri)
|
||||
{
|
||||
return BuildYouTubeIframeUrl(
|
||||
uri.AbsolutePath.Substring(1),
|
||||
SplitQuery(uri).FirstOrDefault(p => p.StartsWith("t="))?.Substring(2)
|
||||
SplitQuery(uri).FirstOrDefault(p => p.StartsWith("t=", StringComparison.Ordinal))?.Substring(2)
|
||||
);
|
||||
}
|
||||
|
||||
private static string BuildYouTubeIframeUrl(string videoId, string startTime)
|
||||
private static string? BuildYouTubeIframeUrl(string? videoId, string? startTime)
|
||||
{
|
||||
if (string.IsNullOrEmpty(videoId))
|
||||
{
|
||||
@@ -103,31 +115,27 @@ namespace Markdig.Extensions.MediaLinks
|
||||
return string.IsNullOrEmpty(startTime) ? url : $"{url}?start={startTime}";
|
||||
}
|
||||
|
||||
private static string Vimeo(Uri uri)
|
||||
private static string? Vimeo(Uri uri)
|
||||
{
|
||||
var items = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped).Split('/');
|
||||
return items.Length > 0 ? $"https://player.vimeo.com/video/{ items[items.Length - 1] }" : null;
|
||||
}
|
||||
|
||||
private static string Odnoklassniki(Uri uri)
|
||||
private static string? Odnoklassniki(Uri uri)
|
||||
{
|
||||
var items = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped).Split('/');
|
||||
return items.Length > 0 ? $"https://ok.ru/videoembed/{ items[items.Length - 1] }" : null;
|
||||
}
|
||||
|
||||
private static string Yandex(Uri uri)
|
||||
private static string? Yandex(Uri uri)
|
||||
{
|
||||
var items = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped).Split('/');
|
||||
var albumKeyword
|
||||
= items.Skip(0).FirstOrDefault();
|
||||
var albumId
|
||||
= items.Skip(1).FirstOrDefault();
|
||||
var trackKeyword
|
||||
= items.Skip(2).FirstOrDefault();
|
||||
var trackId
|
||||
= items.Skip(3).FirstOrDefault();
|
||||
string[] items = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped).Split('/');
|
||||
string? albumKeyword = items.Skip(0).FirstOrDefault();
|
||||
string? albumId = items.Skip(1).FirstOrDefault();
|
||||
string? trackKeyword = items.Skip(2).FirstOrDefault();
|
||||
string? trackId = items.Skip(3).FirstOrDefault();
|
||||
|
||||
if (albumKeyword != "album" || albumId == null || trackKeyword != "track" || trackId == null)
|
||||
if (albumKeyword != "album" || albumId is null || trackKeyword != "track" || trackId is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Markdig.Extensions.MediaLinks
|
||||
{
|
||||
@@ -14,7 +15,7 @@ namespace Markdig.Extensions.MediaLinks
|
||||
/// <summary>
|
||||
/// "class" attribute of generated iframe.
|
||||
/// </summary>
|
||||
string Class { get; }
|
||||
string? Class { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generate url for iframe.
|
||||
@@ -23,7 +24,7 @@ namespace Markdig.Extensions.MediaLinks
|
||||
/// <param name="isSchemaRelative"><see langword="true"/> if <paramref name="mediaUri"/> is a schema relative uri, i.e. uri starts with "//".</param>
|
||||
/// <param name="iframeUrl">Generated url for iframe.</param>
|
||||
/// <seealso href="https://tools.ietf.org/html/rfc3986#section-4.2"/>
|
||||
bool TryHandle(Uri mediaUri, bool isSchemaRelative, out string iframeUrl);
|
||||
bool TryHandle(Uri mediaUri, bool isSchemaRelative, [NotNullWhen(true)] out string? iframeUrl);
|
||||
|
||||
/// <summary>
|
||||
/// Should the generated iframe has allowfullscreen attribute.
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Markdig.Extensions.MediaLinks
|
||||
{
|
||||
}
|
||||
|
||||
public MediaLinkExtension(MediaOptions options)
|
||||
public MediaLinkExtension(MediaOptions? options)
|
||||
{
|
||||
Options = options ?? new MediaOptions();
|
||||
}
|
||||
@@ -46,18 +46,18 @@ namespace Markdig.Extensions.MediaLinks
|
||||
|
||||
private bool TryLinkInlineRenderer(HtmlRenderer renderer, LinkInline linkInline)
|
||||
{
|
||||
if (!linkInline.IsImage || linkInline.Url == null)
|
||||
if (!linkInline.IsImage || linkInline.Url is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSchemaRelative = false;
|
||||
// Only process absolute Uri
|
||||
if (!Uri.TryCreate(linkInline.Url, UriKind.RelativeOrAbsolute, out Uri uri) || !uri.IsAbsoluteUri)
|
||||
if (!Uri.TryCreate(linkInline.Url, UriKind.RelativeOrAbsolute, out Uri? uri) || !uri.IsAbsoluteUri)
|
||||
{
|
||||
// see https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
// since relative uri doesn't support many properties, "http" is used as a placeholder here.
|
||||
if (linkInline.Url.StartsWith("//") && Uri.TryCreate("http:" + linkInline.Url, UriKind.Absolute, out uri))
|
||||
if (linkInline.Url.StartsWith("//", StringComparison.Ordinal) && Uri.TryCreate("http:" + linkInline.Url, UriKind.Absolute, out uri))
|
||||
{
|
||||
isSchemaRelative = true;
|
||||
}
|
||||
@@ -98,10 +98,10 @@ namespace Markdig.Extensions.MediaLinks
|
||||
// Otherwise try to detect if we have an audio/video from the file extension
|
||||
var lastDot = path.LastIndexOf('.');
|
||||
if (lastDot >= 0 &&
|
||||
Options.ExtensionToMimeType.TryGetValue(path.Substring(lastDot), out string mimeType))
|
||||
Options.ExtensionToMimeType.TryGetValue(path.Substring(lastDot), out string? mimeType))
|
||||
{
|
||||
var htmlAttributes = GetHtmlAttributes(linkInline);
|
||||
var isAudio = mimeType.StartsWith("audio");
|
||||
var isAudio = mimeType.StartsWith("audio", StringComparison.Ordinal);
|
||||
var tagType = isAudio ? "audio" : "video";
|
||||
|
||||
renderer.Write($"<{tagType}");
|
||||
@@ -126,9 +126,8 @@ namespace Markdig.Extensions.MediaLinks
|
||||
|
||||
private bool TryRenderIframeFromKnownProviders(Uri uri, bool isSchemaRelative, HtmlRenderer renderer, LinkInline linkInline)
|
||||
{
|
||||
|
||||
IHostProvider foundProvider = null;
|
||||
string iframeUrl = null;
|
||||
IHostProvider? foundProvider = null;
|
||||
string? iframeUrl = null;
|
||||
foreach (var provider in Options.Hosts)
|
||||
{
|
||||
if (!provider.TryHandle(uri, isSchemaRelative, out iframeUrl))
|
||||
@@ -137,7 +136,7 @@ namespace Markdig.Extensions.MediaLinks
|
||||
break;
|
||||
}
|
||||
|
||||
if (foundProvider == null)
|
||||
if (foundProvider is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -145,7 +144,7 @@ namespace Markdig.Extensions.MediaLinks
|
||||
var htmlAttributes = GetHtmlAttributes(linkInline);
|
||||
renderer.Write("<iframe src=\"");
|
||||
renderer.WriteEscapeUrl(iframeUrl);
|
||||
renderer.Write("\"");
|
||||
renderer.Write('"');
|
||||
|
||||
if (!string.IsNullOrEmpty(Options.Width))
|
||||
htmlAttributes.AddPropertyIfNotExist("width", Options.Width);
|
||||
@@ -156,8 +155,8 @@ namespace Markdig.Extensions.MediaLinks
|
||||
if (!string.IsNullOrEmpty(Options.Class))
|
||||
htmlAttributes.AddClass(Options.Class);
|
||||
|
||||
if (!string.IsNullOrEmpty(foundProvider.Class))
|
||||
htmlAttributes.AddClass(foundProvider.Class);
|
||||
if (foundProvider.Class is { Length: > 0 } className)
|
||||
htmlAttributes.AddClass(className);
|
||||
|
||||
htmlAttributes.AddPropertyIfNotExist("frameborder", "0");
|
||||
if (foundProvider.AllowFullScreen)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// 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.
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Markdig.Extensions.PragmaLines
|
||||
{
|
||||
var attribute = block.GetAttributes();
|
||||
var pragmaId = GetPragmaId(block);
|
||||
if ( attribute.Id == null)
|
||||
if ( attribute.Id is null)
|
||||
{
|
||||
attribute.Id = pragmaId;
|
||||
}
|
||||
@@ -49,8 +49,7 @@ namespace Markdig.Extensions.PragmaLines
|
||||
var tag = $"<a id=\"{pragmaId}\"></a>";
|
||||
if (heading?.Inline?.FirstChild != null)
|
||||
{
|
||||
heading.Inline.FirstChild.InsertBefore(new HtmlInline() { Tag = tag });
|
||||
|
||||
heading.Inline.FirstChild.InsertBefore(new HtmlInline(tag));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
// 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;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Markdig.Renderers;
|
||||
using Markdig.Renderers.Html.Inlines;
|
||||
|
||||
namespace Markdig.Extensions.ReferralLinks
|
||||
{
|
||||
@@ -15,7 +14,7 @@ namespace Markdig.Extensions.ReferralLinks
|
||||
{
|
||||
public ReferralLinksExtension(string[] rels)
|
||||
{
|
||||
Rels = rels?.ToList();
|
||||
Rels = rels?.ToList() ?? throw new ArgumentNullException(nameof(rels));
|
||||
}
|
||||
|
||||
public List<string> Rels { get; }
|
||||
@@ -26,8 +25,7 @@ namespace Markdig.Extensions.ReferralLinks
|
||||
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
string relString = Rels == null? null :
|
||||
string.Join(" ", Rels.Where(r => !string.IsNullOrEmpty(r)));
|
||||
string relString = string.Join(" ", Rels.Where(r => !string.IsNullOrEmpty(r)));
|
||||
|
||||
var linkRenderer = renderer.ObjectRenderers.Find<LinkInlineRenderer>();
|
||||
if (linkRenderer != null)
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Markdig.Extensions.SelfPipeline
|
||||
/// <param name="tag">The matching start tag.</param>
|
||||
/// <param name="defaultExtensions">The default extensions.</param>
|
||||
/// <exception cref="ArgumentException">Tag cannot contain angle brackets</exception>
|
||||
public SelfPipelineExtension(string tag = null, string defaultExtensions = null)
|
||||
public SelfPipelineExtension(string? tag = null, string? defaultExtensions = null)
|
||||
{
|
||||
tag = tag?.Trim();
|
||||
tag = string.IsNullOrEmpty(tag) ? DefaultTag : tag;
|
||||
@@ -46,7 +46,7 @@ namespace Markdig.Extensions.SelfPipeline
|
||||
/// <summary>
|
||||
/// Gets the default pipeline to configure if no tag was found in the input text. Default is <c>null</c> (core pipeline).
|
||||
/// </summary>
|
||||
public string DefaultExtensions { get; }
|
||||
public string? DefaultExtensions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the self pipeline hint tag start that will be matched.
|
||||
@@ -75,10 +75,10 @@ namespace Markdig.Extensions.SelfPipeline
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public MarkdownPipeline CreatePipelineFromInput(string inputText)
|
||||
{
|
||||
if (inputText == null) ThrowHelper.ArgumentNullException(nameof(inputText));
|
||||
if (inputText is null) ThrowHelper.ArgumentNullException(nameof(inputText));
|
||||
|
||||
var builder = new MarkdownPipelineBuilder();
|
||||
string defaultConfig = DefaultExtensions;
|
||||
string? defaultConfig = DefaultExtensions;
|
||||
var indexOfSelfPipeline = inputText.IndexOf(SelfPipelineHintTagStart, StringComparison.OrdinalIgnoreCase);
|
||||
if (indexOfSelfPipeline >= 0)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ namespace Markdig.Extensions.SelfPipeline
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(defaultConfig))
|
||||
if (defaultConfig is { Length: > 0 })
|
||||
{
|
||||
builder.Configure(defaultConfig);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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.Renderers;
|
||||
using Markdig.Renderers.Html;
|
||||
@@ -22,14 +23,14 @@ namespace Markdig.Extensions.SmartyPants
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public HtmlSmartyPantRenderer(SmartyPantOptions options)
|
||||
public HtmlSmartyPantRenderer(SmartyPantOptions? options)
|
||||
{
|
||||
this.options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
protected override void Write(HtmlRenderer renderer, SmartyPant obj)
|
||||
{
|
||||
if (!options.Mapping.TryGetValue(obj.Type, out string text))
|
||||
if (!options.Mapping.TryGetValue(obj.Type, out string? text))
|
||||
{
|
||||
DefaultOptions.Mapping.TryGetValue(obj.Type, out text);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Markdig.Extensions.SmartyPants
|
||||
/// Initializes a new instance of the <see cref="SmartyPantsExtension"/> class.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
public SmartyPantsExtension(SmartyPantOptions options)
|
||||
public SmartyPantsExtension(SmartyPantOptions? options)
|
||||
{
|
||||
Options = options ?? new SmartyPantOptions();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Markdig.Extensions.SmartyPants
|
||||
type = SmartyPantType.Quote; // We will resolve them at the end of parsing all inlines
|
||||
if (slice.PeekChar() == '\'')
|
||||
{
|
||||
slice.NextChar();
|
||||
slice.SkipChar();
|
||||
type = SmartyPantType.DoubleQuote; // We will resolve them at the end of parsing all inlines
|
||||
}
|
||||
break;
|
||||
@@ -171,9 +171,9 @@ namespace Markdig.Extensions.SmartyPants
|
||||
var quotePants = GetOrCreateState(processor);
|
||||
|
||||
// Register only if we don't have yet any quotes
|
||||
if (quotePants.Count == 0)
|
||||
if (quotePants.Count is 0)
|
||||
{
|
||||
processor.Block.ProcessInlinesEnd += BlockOnProcessInlinesEnd;
|
||||
processor.Block!.ProcessInlinesEnd += BlockOnProcessInlinesEnd;
|
||||
}
|
||||
quotePants.Add(pant);
|
||||
}
|
||||
@@ -203,13 +203,13 @@ namespace Markdig.Extensions.SmartyPants
|
||||
}
|
||||
}
|
||||
|
||||
private void BlockOnProcessInlinesEnd(InlineProcessor processor, Inline inline)
|
||||
private void BlockOnProcessInlinesEnd(InlineProcessor processor, Inline? inline)
|
||||
{
|
||||
processor.Block.ProcessInlinesEnd -= BlockOnProcessInlinesEnd;
|
||||
processor.Block!.ProcessInlinesEnd -= BlockOnProcessInlinesEnd;
|
||||
|
||||
var pants = (ListSmartyPants) processor.ParserStates[Index];
|
||||
|
||||
Stack<Opener> openers = new Stack<Opener>(4);
|
||||
var openers = new Stack<Opener>(4);
|
||||
|
||||
for (int i = 0; i < pants.Count; i++)
|
||||
{
|
||||
@@ -219,17 +219,17 @@ namespace Markdig.Extensions.SmartyPants
|
||||
int type;
|
||||
bool isLeft;
|
||||
|
||||
if (quoteType == SmartyPantType.LeftQuote || quoteType == SmartyPantType.RightQuote)
|
||||
if (quoteType is SmartyPantType.LeftQuote or SmartyPantType.RightQuote)
|
||||
{
|
||||
type = 0;
|
||||
isLeft = quoteType == SmartyPantType.LeftQuote;
|
||||
}
|
||||
else if (quoteType == SmartyPantType.LeftDoubleQuote || quoteType == SmartyPantType.RightDoubleQuote)
|
||||
else if (quoteType is SmartyPantType.LeftDoubleQuote or SmartyPantType.RightDoubleQuote)
|
||||
{
|
||||
type = 1;
|
||||
isLeft = quoteType == SmartyPantType.LeftDoubleQuote;
|
||||
}
|
||||
else if (quoteType == SmartyPantType.LeftAngleQuote || quoteType == SmartyPantType.RightAngleQuote)
|
||||
else if (quoteType is SmartyPantType.LeftAngleQuote or SmartyPantType.RightAngleQuote)
|
||||
{
|
||||
type = 2;
|
||||
isLeft = quoteType == SmartyPantType.LeftAngleQuote;
|
||||
@@ -280,7 +280,11 @@ namespace Markdig.Extensions.SmartyPants
|
||||
pants.Clear();
|
||||
}
|
||||
|
||||
bool IPostInlineProcessor.PostProcess(InlineProcessor state, Inline root, Inline lastChild, int postInlineProcessorIndex,
|
||||
bool IPostInlineProcessor.PostProcess(
|
||||
InlineProcessor state,
|
||||
Inline? root,
|
||||
Inline? lastChild,
|
||||
int postInlineProcessorIndex,
|
||||
bool isFinalProcessing)
|
||||
{
|
||||
// Don't try to process anything if there are no dash
|
||||
@@ -339,9 +343,9 @@ namespace Markdig.Extensions.SmartyPants
|
||||
next = postLiteral;
|
||||
}
|
||||
}
|
||||
else if (child is ContainerInline)
|
||||
else if (child is ContainerInline childContainer)
|
||||
{
|
||||
pendingContainers.Push(((ContainerInline)child).FirstChild);
|
||||
pendingContainers.Push(childContainer.FirstChild!);
|
||||
}
|
||||
|
||||
child = next;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Markdig.Extensions.Tables
|
||||
}
|
||||
|
||||
var line = processor.Line;
|
||||
GridTableState tableState = null;
|
||||
GridTableState? tableState = null;
|
||||
|
||||
// Match the first row that should be of the minimal form: +---------------
|
||||
var c = line.CurrentChar;
|
||||
@@ -33,7 +33,7 @@ namespace Markdig.Extensions.Tables
|
||||
while (c == '+')
|
||||
{
|
||||
var columnStart = line.Start;
|
||||
line.NextChar();
|
||||
line.SkipChar();
|
||||
line.TrimStart();
|
||||
|
||||
// if we have reached the end of the line, exit
|
||||
@@ -49,13 +49,13 @@ namespace Markdig.Extensions.Tables
|
||||
return BlockState.None;
|
||||
}
|
||||
|
||||
tableState ??= new GridTableState { Start = processor.Start, ExpectRow = true };
|
||||
tableState ??= new GridTableState(start: processor.Start, expectRow: true);
|
||||
tableState.AddColumn(columnStart - lineStart, line.Start - lineStart, columnAlign);
|
||||
|
||||
c = line.CurrentChar;
|
||||
}
|
||||
|
||||
if (c != 0 || tableState == null)
|
||||
if (c != 0 || tableState is null)
|
||||
{
|
||||
return BlockState.None;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ namespace Markdig.Extensions.Tables
|
||||
|
||||
// Calculate the total width of all columns
|
||||
int totalWidth = 0;
|
||||
foreach (var columnSlice in tableState.ColumnSlices)
|
||||
foreach (var columnSlice in tableState.ColumnSlices!)
|
||||
{
|
||||
totalWidth += columnSlice.End - columnSlice.Start - 1;
|
||||
}
|
||||
@@ -91,7 +91,7 @@ namespace Markdig.Extensions.Tables
|
||||
public override BlockState TryContinue(BlockProcessor processor, Block block)
|
||||
{
|
||||
var gridTable = (Table)block;
|
||||
var tableState = (GridTableState)block.GetData(typeof(GridTableState));
|
||||
var tableState = (GridTableState)block.GetData(typeof(GridTableState))!;
|
||||
tableState.AddLine(ref processor.Line);
|
||||
if (processor.CurrentChar == '+')
|
||||
{
|
||||
@@ -113,7 +113,7 @@ namespace Markdig.Extensions.Tables
|
||||
|
||||
private BlockState HandleNewRow(BlockProcessor processor, GridTableState tableState, Table gridTable)
|
||||
{
|
||||
var columns = tableState.ColumnSlices;
|
||||
var columns = tableState.ColumnSlices!;
|
||||
SetRowSpanState(columns, processor.Line, out bool isHeaderRow, out bool hasRowSpan);
|
||||
SetColumnSpanState(columns, processor.Line);
|
||||
TerminateCurrentRow(processor, tableState, gridTable, false);
|
||||
@@ -161,44 +161,43 @@ namespace Markdig.Extensions.Tables
|
||||
|
||||
private static bool IsRowSeperator(StringSlice slice)
|
||||
{
|
||||
while (slice.Length > 0)
|
||||
char c = slice.CurrentChar;
|
||||
do
|
||||
{
|
||||
if (slice.CurrentChar != '-' && slice.CurrentChar != '=' && slice.CurrentChar != ':')
|
||||
if (c != '-' && c != '=' && c != ':')
|
||||
{
|
||||
return false;
|
||||
return c == '\0';
|
||||
}
|
||||
slice.NextChar();
|
||||
c = slice.NextChar();
|
||||
}
|
||||
return true;
|
||||
while (true);
|
||||
}
|
||||
|
||||
private static void TerminateCurrentRow(BlockProcessor processor, GridTableState tableState, Table gridTable, bool isLastRow)
|
||||
{
|
||||
var columns = tableState.ColumnSlices;
|
||||
TableRow currentRow = null;
|
||||
for (int i = 0; i < columns.Count; i++)
|
||||
TableRow? currentRow = null;
|
||||
for (int i = 0; i < columns!.Count; i++)
|
||||
{
|
||||
var columnSlice = columns[i];
|
||||
if (columnSlice.CurrentCell != null)
|
||||
{
|
||||
if (currentRow == null)
|
||||
{
|
||||
currentRow = new TableRow();
|
||||
}
|
||||
currentRow ??= new TableRow();
|
||||
|
||||
// If this cell does not already belong to a row
|
||||
if (columnSlice.CurrentCell.Parent == null)
|
||||
if (columnSlice.CurrentCell.Parent is null)
|
||||
{
|
||||
currentRow.Add(columnSlice.CurrentCell);
|
||||
}
|
||||
// If the cell is not going to span through to the next row
|
||||
if (columnSlice.CurrentCell.AllowClose)
|
||||
{
|
||||
columnSlice.BlockProcessor.Close(columnSlice.CurrentCell);
|
||||
columnSlice.BlockProcessor!.Close(columnSlice.CurrentCell);
|
||||
}
|
||||
}
|
||||
|
||||
// Renew the block parser processor (or reset it for the last row)
|
||||
if (columnSlice.BlockProcessor != null && (columnSlice.CurrentCell == null || columnSlice.CurrentCell.AllowClose))
|
||||
if (columnSlice.BlockProcessor != null && (columnSlice.CurrentCell is null || columnSlice.CurrentCell.AllowClose))
|
||||
{
|
||||
columnSlice.BlockProcessor.ReleaseChild();
|
||||
columnSlice.BlockProcessor = isLastRow ? null : processor.CreateChild();
|
||||
@@ -214,7 +213,7 @@ namespace Markdig.Extensions.Tables
|
||||
}
|
||||
}
|
||||
|
||||
if (currentRow != null && currentRow.Count > 0)
|
||||
if (currentRow is { Count: > 0 })
|
||||
{
|
||||
gridTable.Add(currentRow);
|
||||
}
|
||||
@@ -223,7 +222,7 @@ namespace Markdig.Extensions.Tables
|
||||
private BlockState HandleContents(BlockProcessor processor, GridTableState tableState, Table gridTable)
|
||||
{
|
||||
var isRowLine = processor.CurrentChar == '+';
|
||||
var columns = tableState.ColumnSlices;
|
||||
var columns = tableState.ColumnSlices!;
|
||||
var line = processor.Line;
|
||||
SetColumnSpanState(columns, line);
|
||||
if (!isRowLine && !CanContinueRow(columns))
|
||||
@@ -267,7 +266,7 @@ namespace Markdig.Extensions.Tables
|
||||
|
||||
if (!isRowLine || !IsRowSeperator(sliceForCell))
|
||||
{
|
||||
if (columnSlice.CurrentCell == null)
|
||||
if (columnSlice.CurrentCell is null)
|
||||
{
|
||||
columnSlice.CurrentCell = new TableCell(this)
|
||||
{
|
||||
@@ -275,7 +274,7 @@ namespace Markdig.Extensions.Tables
|
||||
ColumnIndex = i
|
||||
};
|
||||
|
||||
if (columnSlice.BlockProcessor == null)
|
||||
if (columnSlice.BlockProcessor is null)
|
||||
{
|
||||
columnSlice.BlockProcessor = processor.CreateChild();
|
||||
}
|
||||
@@ -284,7 +283,7 @@ namespace Markdig.Extensions.Tables
|
||||
columnSlice.BlockProcessor.Open(columnSlice.CurrentCell);
|
||||
}
|
||||
// Process the content of the cell
|
||||
columnSlice.BlockProcessor.LineIndex = processor.LineIndex;
|
||||
columnSlice.BlockProcessor!.LineIndex = processor.LineIndex;
|
||||
columnSlice.BlockProcessor.ProcessLine(sliceForCell);
|
||||
}
|
||||
|
||||
@@ -335,7 +334,7 @@ namespace Markdig.Extensions.Tables
|
||||
{
|
||||
var parser = processor.Parsers.FindExact<ParagraphBlockParser>();
|
||||
// Discard the grid table
|
||||
var parent = gridTable.Parent;
|
||||
var parent = gridTable.Parent!;
|
||||
processor.Discard(gridTable);
|
||||
var paragraphBlock = new ParagraphBlock(parser)
|
||||
{
|
||||
@@ -351,7 +350,7 @@ namespace Markdig.Extensions.Tables
|
||||
var gridTable = block as Table;
|
||||
if (gridTable != null)
|
||||
{
|
||||
var tableState = (GridTableState)block.GetData(typeof(GridTableState));
|
||||
var tableState = (GridTableState)block.GetData(typeof(GridTableState))!;
|
||||
TerminateCurrentRow(processor, tableState, gridTable, true);
|
||||
if (!gridTable.IsValid())
|
||||
{
|
||||
|
||||
@@ -13,63 +13,65 @@ namespace Markdig.Extensions.Tables
|
||||
/// </summary>
|
||||
internal sealed class GridTableState
|
||||
{
|
||||
public int Start { get; set; }
|
||||
public GridTableState(int start, bool expectRow)
|
||||
{
|
||||
Start = start;
|
||||
ExpectRow = expectRow;
|
||||
}
|
||||
|
||||
public int Start { get; }
|
||||
|
||||
public StringLineGroup Lines;
|
||||
|
||||
public List<ColumnSlice> ColumnSlices { get; private set; }
|
||||
public List<ColumnSlice>? ColumnSlices { get; private set; }
|
||||
|
||||
public bool ExpectRow { get; set; }
|
||||
public bool ExpectRow { get; }
|
||||
|
||||
public int StartRowGroup { get; set; }
|
||||
|
||||
public void AddLine(ref StringSlice line)
|
||||
{
|
||||
if (Lines.Lines == null)
|
||||
if (Lines.Lines is null)
|
||||
{
|
||||
Lines = new StringLineGroup(4);
|
||||
}
|
||||
|
||||
Lines.Add(line);
|
||||
}
|
||||
|
||||
public void AddColumn(int start, int end, TableColumnAlign? align)
|
||||
{
|
||||
if (ColumnSlices == null)
|
||||
{
|
||||
ColumnSlices = new List<ColumnSlice>();
|
||||
}
|
||||
|
||||
ColumnSlices.Add(new ColumnSlice()
|
||||
{
|
||||
Start = start,
|
||||
End = end,
|
||||
Align = align,
|
||||
});
|
||||
ColumnSlices ??= new List<ColumnSlice>();
|
||||
|
||||
ColumnSlices.Add(new ColumnSlice(start, end, align));
|
||||
}
|
||||
|
||||
public class ColumnSlice
|
||||
public sealed class ColumnSlice
|
||||
{
|
||||
public ColumnSlice()
|
||||
public ColumnSlice(int start, int end, TableColumnAlign? align)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
Align = align;
|
||||
CurrentColumnSpan = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the index position of this column (after the |)
|
||||
/// </summary>
|
||||
public int Start { get; set; }
|
||||
public int Start { get; }
|
||||
|
||||
public int End { get; set; }
|
||||
public int End { get; }
|
||||
|
||||
public TableColumnAlign? Align { get; set; }
|
||||
public TableColumnAlign? Align { get; }
|
||||
|
||||
public int CurrentColumnSpan { get; set; }
|
||||
|
||||
public int PreviousColumnSpan { get; set; }
|
||||
|
||||
public BlockProcessor BlockProcessor { get; set; }
|
||||
public BlockProcessor? BlockProcessor { get; set; }
|
||||
|
||||
public TableCell CurrentCell { get; set; }
|
||||
public TableCell? CurrentCell { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ namespace Markdig.Extensions.Tables
|
||||
protected override void Write(HtmlRenderer renderer, Table table)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
renderer.Write("<table").WriteAttributes(table).WriteLine(">");
|
||||
renderer.Write("<table").WriteAttributes(table).WriteLine('>');
|
||||
|
||||
bool hasBody = false;
|
||||
bool hasAlreadyHeader = false;
|
||||
@@ -69,7 +69,7 @@ namespace Markdig.Extensions.Tables
|
||||
renderer.WriteLine("<tbody>");
|
||||
hasBody = true;
|
||||
}
|
||||
renderer.Write("<tr").WriteAttributes(row).WriteLine(">");
|
||||
renderer.Write("<tr").WriteAttributes(row).WriteLine('>');
|
||||
for (int i = 0; i < row.Count; i++)
|
||||
{
|
||||
var cellObj = row[i];
|
||||
@@ -109,7 +109,7 @@ namespace Markdig.Extensions.Tables
|
||||
}
|
||||
}
|
||||
renderer.WriteAttributes(cell);
|
||||
renderer.Write(">");
|
||||
renderer.Write('>');
|
||||
|
||||
var previousImplicitParagraph = renderer.ImplicitParagraph;
|
||||
if (cell.Count == 1)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// 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.
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Markdig.Extensions.Tables
|
||||
{
|
||||
// Only if we have already a paragraph
|
||||
var paragraph = processor.CurrentBlock as ParagraphBlock;
|
||||
if (processor.IsCodeIndent || paragraph == null)
|
||||
if (processor.IsCodeIndent || paragraph is null)
|
||||
{
|
||||
return BlockState.None;
|
||||
}
|
||||
@@ -45,7 +45,7 @@ namespace Markdig.Extensions.Tables
|
||||
if (countPipe > 0)
|
||||
{
|
||||
// Mark the paragraph as open (important, otherwise we would have an infinite loop)
|
||||
paragraph.AppendLine(ref processor.Line, processor.Column, processor.LineIndex, processor.Line.Start);
|
||||
paragraph.AppendLine(ref processor.Line, processor.Column, processor.LineIndex, processor.Line.Start, processor.TrackTrivia);
|
||||
paragraph.IsOpen = true;
|
||||
return BlockState.BreakDiscard;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Markdig.Extensions.Tables
|
||||
/// Initializes a new instance of the <see cref="PipeTableExtension"/> class.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
public PipeTableExtension(PipeTableOptions options = null)
|
||||
public PipeTableExtension(PipeTableOptions? options = null)
|
||||
{
|
||||
Options = options ?? new PipeTableOptions();
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace Markdig.Extensions.Tables
|
||||
var lineBreakParser = pipeline.InlineParsers.FindExact<LineBreakInlineParser>();
|
||||
if (!pipeline.InlineParsers.Contains<PipeTableParser>())
|
||||
{
|
||||
pipeline.InlineParsers.InsertBefore<EmphasisInlineParser>(new PipeTableParser(lineBreakParser, Options));
|
||||
pipeline.InlineParsers.InsertBefore<EmphasisInlineParser>(new PipeTableParser(lineBreakParser!, Options));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@ namespace Markdig.Extensions.Tables
|
||||
/// </summary>
|
||||
/// <param name="lineBreakParser">The linebreak parser to use</param>
|
||||
/// <param name="options">The options.</param>
|
||||
public PipeTableParser(LineBreakInlineParser lineBreakParser, PipeTableOptions options = null)
|
||||
public PipeTableParser(LineBreakInlineParser lineBreakParser, PipeTableOptions? options = null)
|
||||
{
|
||||
this.lineBreakParser = lineBreakParser ?? throw new ArgumentNullException(nameof(lineBreakParser));
|
||||
OpeningCharacters = new[] { '|', '\n' };
|
||||
OpeningCharacters = new[] { '|', '\n', '\r' };
|
||||
Options = options ?? new PipeTableOptions();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Markdig.Extensions.Tables
|
||||
var position = processor.GetSourcePosition(slice.Start, out int globalLineIndex, out int column);
|
||||
var localLineIndex = globalLineIndex - processor.LineIndex;
|
||||
|
||||
if (tableState == null)
|
||||
if (tableState is null)
|
||||
{
|
||||
|
||||
// A table could be preceded by an empty line or a line containing an inline
|
||||
@@ -67,12 +67,12 @@ namespace Markdig.Extensions.Tables
|
||||
// start for a table. Typically, with this, we can have an attributes {...}
|
||||
// starting on the first line of a pipe table, even if the first line
|
||||
// doesn't have a pipe
|
||||
if (processor.Inline != null && (localLineIndex > 0 || c == '\n'))
|
||||
if (processor.Inline != null && (localLineIndex > 0 || c == '\n' || c == '\r'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (processor.Inline == null)
|
||||
if (processor.Inline is null)
|
||||
{
|
||||
isFirstLineEmpty = true;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ namespace Markdig.Extensions.Tables
|
||||
processor.ParserStates[Index] = tableState;
|
||||
}
|
||||
|
||||
if (c == '\n')
|
||||
if (c == '\n' || c == '\r')
|
||||
{
|
||||
if (!isFirstLineEmpty && !tableState.LineHasPipe)
|
||||
{
|
||||
@@ -92,8 +92,8 @@ namespace Markdig.Extensions.Tables
|
||||
tableState.LineIndex++;
|
||||
if (!isFirstLineEmpty)
|
||||
{
|
||||
tableState.ColumnAndLineDelimiters.Add(processor.Inline);
|
||||
tableState.EndOfLines.Add(processor.Inline);
|
||||
tableState.ColumnAndLineDelimiters.Add(processor.Inline!);
|
||||
tableState.EndOfLines.Add(processor.Inline!);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -112,16 +112,15 @@ namespace Markdig.Extensions.Tables
|
||||
}
|
||||
tableState.LineHasPipe = true;
|
||||
tableState.LineIndex = localLineIndex;
|
||||
slice.NextChar(); // Skip the `|` character
|
||||
slice.SkipChar(); // Skip the `|` character
|
||||
|
||||
tableState.ColumnAndLineDelimiters.Add(processor.Inline);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool PostProcess(InlineProcessor state, Inline root, Inline lastChild, int postInlineProcessorIndex, bool isFinalProcessing)
|
||||
public bool PostProcess(InlineProcessor state, Inline? root, Inline? lastChild, int postInlineProcessorIndex, bool isFinalProcessing)
|
||||
{
|
||||
var container = root as ContainerInline;
|
||||
var tableState = state.ParserStates[Index] as TableState;
|
||||
@@ -129,23 +128,20 @@ namespace Markdig.Extensions.Tables
|
||||
// If the delimiters are being processed by an image link, we need to transform them back to literals
|
||||
if (!isFinalProcessing)
|
||||
{
|
||||
if (container == null || tableState == null)
|
||||
if (container is null || tableState is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var child = container.LastChild;
|
||||
List<PipeTableDelimiterInline> delimitersToRemove = null;
|
||||
List<PipeTableDelimiterInline>? delimitersToRemove = null;
|
||||
|
||||
while (child != null)
|
||||
{
|
||||
var pipeDelimiter = child as PipeTableDelimiterInline;
|
||||
if (pipeDelimiter != null)
|
||||
if (child is PipeTableDelimiterInline pipeDelimiter)
|
||||
{
|
||||
if (delimitersToRemove == null)
|
||||
{
|
||||
delimitersToRemove = new List<PipeTableDelimiterInline>();
|
||||
}
|
||||
delimitersToRemove ??= new List<PipeTableDelimiterInline>();
|
||||
|
||||
delimitersToRemove.Add(pipeDelimiter);
|
||||
}
|
||||
|
||||
@@ -196,10 +192,10 @@ namespace Markdig.Extensions.Tables
|
||||
}
|
||||
|
||||
// Remove previous state
|
||||
state.ParserStates[Index] = null;
|
||||
state.ParserStates[Index] = null!;
|
||||
|
||||
// Continue
|
||||
if (tableState == null || container == null || tableState.IsInvalidTable || !tableState.LineHasPipe ) //|| tableState.LineIndex != state.LocalLineIndex)
|
||||
if (tableState is null || container is null || tableState.IsInvalidTable || !tableState.LineHasPipe ) //|| tableState.LineIndex != state.LocalLineIndex)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -209,7 +205,7 @@ namespace Markdig.Extensions.Tables
|
||||
// TODO: we could optimize this by merging FindHeaderRow and the cell loop
|
||||
var aligns = FindHeaderRow(delimiters);
|
||||
|
||||
if (Options.RequireHeaderSeparator && aligns == null)
|
||||
if (Options.RequireHeaderSeparator && aligns is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -217,7 +213,7 @@ namespace Markdig.Extensions.Tables
|
||||
var table = new Table();
|
||||
|
||||
// If the current paragraph block has any attributes attached, we can copy them
|
||||
var attributes = state.Block.TryGetAttributes();
|
||||
var attributes = state.Block!.TryGetAttributes();
|
||||
if (attributes != null)
|
||||
{
|
||||
attributes.CopyTo(table.GetAttributes());
|
||||
@@ -258,9 +254,9 @@ namespace Markdig.Extensions.Tables
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (lastElement is ContainerInline)
|
||||
if (lastElement is ContainerInline lastElementContainer)
|
||||
{
|
||||
var nextElement = ((ContainerInline) lastElement).LastChild;
|
||||
var nextElement = lastElementContainer.LastChild;
|
||||
if (nextElement != null)
|
||||
{
|
||||
lastElement = nextElement;
|
||||
@@ -287,26 +283,24 @@ namespace Markdig.Extensions.Tables
|
||||
|
||||
// Cell loop
|
||||
// Reconstruct the table from the delimiters
|
||||
TableRow row = null;
|
||||
TableRow firstRow = null;
|
||||
TableRow? row = null;
|
||||
TableRow? firstRow = null;
|
||||
for (int i = 0; i < delimiters.Count; i++)
|
||||
{
|
||||
var delimiter = delimiters[i];
|
||||
var pipeSeparator = delimiter as PipeTableDelimiterInline;
|
||||
var isLine = delimiter is LineBreakInline;
|
||||
|
||||
if (row == null)
|
||||
if (row is null)
|
||||
{
|
||||
row = new TableRow();
|
||||
if (firstRow == null)
|
||||
{
|
||||
firstRow = row;
|
||||
}
|
||||
|
||||
firstRow ??= row;
|
||||
|
||||
// If the first delimiter is a pipe and doesn't have any parent or previous sibling, for cases like:
|
||||
// 0) | a | b | \n
|
||||
// 1) | a | b \n
|
||||
if (pipeSeparator != null && (delimiter.PreviousSibling == null || delimiter.PreviousSibling is LineBreakInline))
|
||||
if (pipeSeparator != null && (delimiter.PreviousSibling is null || delimiter.PreviousSibling is LineBreakInline))
|
||||
{
|
||||
delimiter.Remove();
|
||||
continue;
|
||||
@@ -318,23 +312,23 @@ namespace Markdig.Extensions.Tables
|
||||
// x
|
||||
// 1) | a | b \n
|
||||
// 2) a | b \n
|
||||
Inline endOfCell = null;
|
||||
Inline beginOfCell = null;
|
||||
Inline? endOfCell = null;
|
||||
Inline? beginOfCell = null;
|
||||
var cellContentIt = delimiter;
|
||||
while (true)
|
||||
{
|
||||
cellContentIt = cellContentIt.PreviousSibling ?? cellContentIt.Parent;
|
||||
|
||||
if (cellContentIt == null || cellContentIt is LineBreakInline)
|
||||
if (cellContentIt is null || cellContentIt is LineBreakInline)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// The cell begins at the first effective child after a | or the top ContainerInline (which is not necessary to bring into the tree + it contains an invalid span calculation)
|
||||
if (cellContentIt is PipeTableDelimiterInline || (cellContentIt.GetType() == typeof(ContainerInline) && cellContentIt.Parent == null ))
|
||||
if (cellContentIt is PipeTableDelimiterInline || (cellContentIt.GetType() == typeof(ContainerInline) && cellContentIt.Parent is null ))
|
||||
{
|
||||
beginOfCell = ((ContainerInline)cellContentIt).FirstChild;
|
||||
if (endOfCell == null)
|
||||
if (endOfCell is null)
|
||||
{
|
||||
endOfCell = beginOfCell;
|
||||
}
|
||||
@@ -342,20 +336,19 @@ namespace Markdig.Extensions.Tables
|
||||
}
|
||||
|
||||
beginOfCell = cellContentIt;
|
||||
if (endOfCell == null)
|
||||
if (endOfCell is null)
|
||||
{
|
||||
endOfCell = beginOfCell;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the current deilimiter is a pipe `|` OR
|
||||
// the beginOfCell/endOfCell are not null and
|
||||
// either they are :
|
||||
// - different
|
||||
// - they contain a single element, but it is not a line break (\n) or an empty/whitespace Literal.
|
||||
// Then we can add a cell to the current row
|
||||
if (!isLine || (beginOfCell != null && endOfCell != null && ( beginOfCell != endOfCell || !(beginOfCell is LineBreakInline || (beginOfCell is LiteralInline && ((LiteralInline)beginOfCell).Content.IsEmptyOrWhitespace())))))
|
||||
if (!isLine || (beginOfCell != null && endOfCell != null && ( beginOfCell != endOfCell || !(beginOfCell is LineBreakInline || (beginOfCell is LiteralInline beingOfCellLiteral && beingOfCellLiteral.Content.IsEmptyOrWhitespace())))))
|
||||
{
|
||||
if (!isLine)
|
||||
{
|
||||
@@ -420,11 +413,11 @@ namespace Markdig.Extensions.Tables
|
||||
Debug.Assert(row != null);
|
||||
if (table.Span.IsEmpty)
|
||||
{
|
||||
table.Span = row.Span;
|
||||
table.Span = row!.Span;
|
||||
table.Line = row.Line;
|
||||
table.Column = row.Column;
|
||||
}
|
||||
table.Add(row);
|
||||
table.Add(row!);
|
||||
row = null;
|
||||
}
|
||||
}
|
||||
@@ -470,11 +463,11 @@ namespace Markdig.Extensions.Tables
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool ParseHeaderString(Inline inline, out TableColumnAlign? align)
|
||||
private static bool ParseHeaderString(Inline? inline, out TableColumnAlign? align)
|
||||
{
|
||||
align = 0;
|
||||
var literal = inline as LiteralInline;
|
||||
if (literal == null)
|
||||
if (literal is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -493,10 +486,10 @@ namespace Markdig.Extensions.Tables
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<TableColumnDefinition> FindHeaderRow(List<Inline> delimiters)
|
||||
private List<TableColumnDefinition>? FindHeaderRow(List<Inline> delimiters)
|
||||
{
|
||||
bool isValidRow = false;
|
||||
List<TableColumnDefinition> aligns = null;
|
||||
List<TableColumnDefinition>? aligns = null;
|
||||
for (int i = 0; i < delimiters.Count; i++)
|
||||
{
|
||||
if (!IsLine(delimiters[i]))
|
||||
@@ -518,20 +511,21 @@ namespace Markdig.Extensions.Tables
|
||||
|
||||
// Check the left side of a `|` delimiter
|
||||
TableColumnAlign? align = null;
|
||||
if (delimiter.PreviousSibling != null && !ParseHeaderString(delimiter.PreviousSibling, out align))
|
||||
if (delimiter.PreviousSibling != null &&
|
||||
!(delimiter.PreviousSibling is LiteralInline li && li.Content.IsEmptyOrWhitespace()) && // ignore parsed whitespace
|
||||
!ParseHeaderString(delimiter.PreviousSibling, out align))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Create aligns until we may have a header row
|
||||
if (aligns == null)
|
||||
{
|
||||
aligns = new List<TableColumnDefinition>();
|
||||
}
|
||||
|
||||
aligns ??= new List<TableColumnDefinition>();
|
||||
|
||||
aligns.Add(new TableColumnDefinition() { Alignment = align });
|
||||
|
||||
// If this is the last delimiter, we need to check the right side of the `|` delimiter
|
||||
if (nextDelimiter == null)
|
||||
if (nextDelimiter is null)
|
||||
{
|
||||
var nextSibling = columnDelimiter != null
|
||||
? columnDelimiter.FirstChild
|
||||
@@ -572,20 +566,20 @@ namespace Markdig.Extensions.Tables
|
||||
return inline is LineBreakInline;
|
||||
}
|
||||
|
||||
private static bool IsStartOfLineColumnDelimiter(Inline inline)
|
||||
private static bool IsStartOfLineColumnDelimiter(Inline? inline)
|
||||
{
|
||||
if (inline == null)
|
||||
if (inline is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var previous = inline.PreviousSibling;
|
||||
if (previous == null)
|
||||
if (previous is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var literal = previous as LiteralInline;
|
||||
if (literal != null)
|
||||
|
||||
if (previous is LiteralInline literal)
|
||||
{
|
||||
if (!literal.Content.IsEmptyOrWhitespace())
|
||||
{
|
||||
@@ -593,65 +587,57 @@ namespace Markdig.Extensions.Tables
|
||||
}
|
||||
previous = previous.PreviousSibling;
|
||||
}
|
||||
return previous == null || IsLine(previous);
|
||||
return previous is null || IsLine(previous);
|
||||
}
|
||||
|
||||
private static void TrimStart(Inline inline)
|
||||
private static void TrimStart(Inline? inline)
|
||||
{
|
||||
while (inline is ContainerInline && !(inline is DelimiterInline))
|
||||
{
|
||||
inline = ((ContainerInline)inline).FirstChild;
|
||||
}
|
||||
var literal = inline as LiteralInline;
|
||||
if (literal != null)
|
||||
|
||||
if (inline is LiteralInline literal)
|
||||
{
|
||||
literal.Content.TrimStart();
|
||||
}
|
||||
}
|
||||
|
||||
private static void TrimEnd(Inline inline)
|
||||
private static void TrimEnd(Inline? inline)
|
||||
{
|
||||
var literal = inline as LiteralInline;
|
||||
if (literal != null)
|
||||
if (inline is LiteralInline literal)
|
||||
{
|
||||
literal.Content.TrimEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsNullOrSpace(Inline inline)
|
||||
private static bool IsNullOrSpace(Inline? inline)
|
||||
{
|
||||
if (inline == null)
|
||||
if (inline is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var literal = inline as LiteralInline;
|
||||
if (literal != null)
|
||||
|
||||
if (inline is LiteralInline literal)
|
||||
{
|
||||
return literal.Content.IsEmptyOrWhitespace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private class TableState
|
||||
private sealed class TableState
|
||||
{
|
||||
public TableState()
|
||||
{
|
||||
ColumnAndLineDelimiters = new List<Inline>();
|
||||
Cells = new List<TableCell>();
|
||||
EndOfLines = new List<Inline>();
|
||||
}
|
||||
|
||||
public bool IsInvalidTable { get; set; }
|
||||
|
||||
public bool LineHasPipe { get; set; }
|
||||
|
||||
public int LineIndex { get; set; }
|
||||
|
||||
public List<Inline> ColumnAndLineDelimiters { get; }
|
||||
public List<Inline> ColumnAndLineDelimiters { get; } = new();
|
||||
|
||||
public List<TableCell> Cells { get; }
|
||||
public List<TableCell> Cells { get; } = new();
|
||||
|
||||
public List<Inline> EndOfLines { get; }
|
||||
public List<Inline> EndOfLines { get; } = new();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Markdig.Extensions.Tables
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Table"/> class.
|
||||
/// </summary>
|
||||
public Table() : this(null)
|
||||
public Table() : base(null)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -25,15 +25,14 @@ namespace Markdig.Extensions.Tables
|
||||
/// Initializes a new instance of the <see cref="Table"/> class.
|
||||
/// </summary>
|
||||
/// <param name="parser">The parser used to create this block.</param>
|
||||
public Table(BlockParser parser) : base(parser)
|
||||
public Table(BlockParser? parser) : base(parser)
|
||||
{
|
||||
ColumnDefinitions = new List<TableColumnDefinition>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column alignments. May be null.
|
||||
/// </summary>
|
||||
public List<TableColumnDefinition> ColumnDefinitions { get; }
|
||||
public List<TableColumnDefinition> ColumnDefinitions { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the table structure is valid.
|
||||
@@ -83,8 +82,7 @@ namespace Markdig.Extensions.Tables
|
||||
var maxColumn = 0;
|
||||
for (int i = 0; i < this.Count; i++)
|
||||
{
|
||||
var row = this[i] as TableRow;
|
||||
if (row != null && row.Count > maxColumn)
|
||||
if (this[i] is TableRow row && row.Count > maxColumn)
|
||||
{
|
||||
maxColumn = row.Count;
|
||||
}
|
||||
@@ -92,8 +90,7 @@ namespace Markdig.Extensions.Tables
|
||||
|
||||
for (int i = 0; i < this.Count; i++)
|
||||
{
|
||||
var row = this[i] as TableRow;
|
||||
if (row != null)
|
||||
if (this[i] is TableRow row)
|
||||
{
|
||||
for (int j = row.Count; j < maxColumn; j++)
|
||||
{
|
||||
@@ -124,8 +121,7 @@ namespace Markdig.Extensions.Tables
|
||||
|
||||
for (int i = 0; i < this.Count; i++)
|
||||
{
|
||||
var row = this[i] as TableRow;
|
||||
if (row != null)
|
||||
if (this[i] is TableRow row)
|
||||
{
|
||||
for (int j = row.Count; j < maxColumn; j++)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Markdig.Extensions.Tables
|
||||
/// Initializes a new instance of the <see cref="TableCell"/> class.
|
||||
/// </summary>
|
||||
/// <param name="parser">The parser used to create this block.</param>
|
||||
public TableCell(BlockParser parser) : base(parser)
|
||||
public TableCell(BlockParser? parser) : base(parser)
|
||||
{
|
||||
AllowClose = true;
|
||||
ColumnSpan = 1;
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Markdig.Extensions.Tables
|
||||
if (c == ':')
|
||||
{
|
||||
hasLeft = true;
|
||||
slice.NextChar();
|
||||
slice.SkipChar();
|
||||
}
|
||||
|
||||
slice.TrimStart();
|
||||
@@ -91,7 +91,7 @@ namespace Markdig.Extensions.Tables
|
||||
if (c == ':')
|
||||
{
|
||||
hasRight = true;
|
||||
slice.NextChar();
|
||||
slice.SkipChar();
|
||||
}
|
||||
slice.TrimStart();
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Markdig.Extensions.TaskLists
|
||||
// [ ]
|
||||
// or [x] or [X]
|
||||
|
||||
if (!(processor.Block.Parent is ListItemBlock listItemBlock))
|
||||
if (!(processor.Block!.Parent is ListItemBlock listItemBlock))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ namespace Markdig.Extensions.TaskLists
|
||||
return false;
|
||||
}
|
||||
// Skip last ]
|
||||
slice.NextChar();
|
||||
slice.SkipChar();
|
||||
|
||||
// Create the TaskList
|
||||
var taskItem = new TaskList()
|
||||
@@ -75,7 +75,7 @@ namespace Markdig.Extensions.TaskLists
|
||||
listItemBlock.GetAttributes().AddClass(ListItemClass);
|
||||
}
|
||||
|
||||
var listBlock = (ListBlock) listItemBlock.Parent;
|
||||
var listBlock = (ListBlock) listItemBlock.Parent!;
|
||||
if (!string.IsNullOrEmpty(ListClass))
|
||||
{
|
||||
listBlock.GetAttributes().AddClass(ListClass);
|
||||
|
||||
@@ -221,9 +221,9 @@ namespace Markdig.Helpers
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNewLine(this char c)
|
||||
public static bool IsNewLineOrLineFeed(this char c)
|
||||
{
|
||||
return c == '\n';
|
||||
return c == '\n' || c == '\r';
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -355,22 +355,6 @@ namespace Markdig.Helpers
|
||||
internal static bool IsInInclusiveRange(int value, uint min, uint max)
|
||||
=> ((uint)value - min) <= (max - min);
|
||||
|
||||
public static IEnumerable<int> ToUtf32(StringSlice text)
|
||||
{
|
||||
for (int i = text.Start; i <= text.End; i++)
|
||||
{
|
||||
if (IsHighSurrogate(text[i]) && i < text.End && IsLowSurrogate(text[i + 1]))
|
||||
{
|
||||
Debug.Assert(char.IsSurrogatePair(text[i], text[i + 1]));
|
||||
yield return char.ConvertToUtf32(text[i], text[i + 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return text[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsRightToLeft(int c)
|
||||
{
|
||||
// Generated from Table D.1 of RFC3454
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user