Compare commits
319 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0ee97a803 | ||
|
|
63ce549ea2 | ||
|
|
0faf0ef430 | ||
|
|
cdd4b40469 | ||
|
|
54d85ebac6 | ||
|
|
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 | ||
|
|
e523dfd7f4 | ||
|
|
412500158c | ||
|
|
fc942b4d01 | ||
|
|
d1d64842ca | ||
|
|
930eee383f | ||
|
|
87c45db46b | ||
|
|
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 | ||
|
|
751c79fce4 | ||
|
|
4dc8cc3977 | ||
|
|
a1891e2984 | ||
|
|
ff0637993c | ||
|
|
8b64ce456f | ||
|
|
a781ae1e5b | ||
|
|
2e5007241d | ||
|
|
cf6d98b7f8 | ||
|
|
0b79389b14 | ||
|
|
111d3d3362 | ||
|
|
ac6ceb23e8 | ||
|
|
d31fa47cd1 | ||
|
|
d7f6a94f12 | ||
|
|
dbdd752b73 | ||
|
|
ccb7e8edfa | ||
|
|
db25c1db43 | ||
|
|
5db90ede4b | ||
|
|
fef1ad3563 | ||
|
|
e9302d93bd | ||
|
|
4704c49fbf | ||
|
|
aca70e5c9a | ||
|
|
da5eff075d | ||
|
|
971207e942 | ||
|
|
4c2b46e0fc | ||
|
|
68d12d0212 | ||
|
|
fa1c117011 | ||
|
|
6b1c5bc816 | ||
|
|
e2cafc6b3d | ||
|
|
aff7604b4b | ||
|
|
68530aa4e0 | ||
|
|
bfc1152b8a | ||
|
|
37af8f8ecb | ||
|
|
6792bffb5e | ||
|
|
976855a4c3 | ||
|
|
acf2ba9502 | ||
|
|
cadbc67825 | ||
|
|
0d86a93200 | ||
|
|
f78b5c83cd | ||
|
|
fb942f9810 | ||
|
|
25a227fffd | ||
|
|
2be8cd4aa7 | ||
|
|
569b80befe | ||
|
|
0b8b14490e | ||
|
|
c59fd5c651 | ||
|
|
4893e2b177 | ||
|
|
b30b219237 | ||
|
|
d6c627aa88 | ||
|
|
a26f4298a4 | ||
|
|
d5b80f6a7b | ||
|
|
98d747c839 | ||
|
|
7dd9321a97 | ||
|
|
c22d681c20 | ||
|
|
ffe7f56bc2 | ||
|
|
16c0b6a3fa | ||
|
|
db867dee48 | ||
|
|
d35b1b82ea | ||
|
|
8b829a2dea | ||
|
|
0234d60d74 | ||
|
|
cd18087e29 | ||
|
|
30f670bf5f | ||
|
|
c73785372b | ||
|
|
147698daab | ||
|
|
2b07e9a5b9 | ||
|
|
4f7ef61303 | ||
|
|
831a529338 | ||
|
|
4f5e9cd334 | ||
|
|
cb0b3a6292 | ||
|
|
4390ff289e | ||
|
|
be53e778be | ||
|
|
0eab0a3107 | ||
|
|
8fa47427ac | ||
|
|
bca544575b | ||
|
|
0017dbffc4 | ||
|
|
569efa357a | ||
|
|
7e9df72173 | ||
|
|
b2fcb1cc37 | ||
|
|
8758ba460f | ||
|
|
477a290538 | ||
|
|
0fc112a6b8 | ||
|
|
b7aea44502 | ||
|
|
0545faa9af | ||
|
|
ea67a295b2 | ||
|
|
d53128d56d | ||
|
|
ba192ce065 | ||
|
|
42462d71ac | ||
|
|
6e0363aa91 | ||
|
|
e9be3725d6 | ||
|
|
38f4332de1 | ||
|
|
bcc123d240 | ||
|
|
144e8ad156 | ||
|
|
55a7eae4d4 | ||
|
|
d96862378d | ||
|
|
8acf5a548e | ||
|
|
222a99c7e4 | ||
|
|
ac4a75bdf9 | ||
|
|
fc2e1ab896 | ||
|
|
ef7f20482e | ||
|
|
fc50e2e2e7 | ||
|
|
4d513acf6b | ||
|
|
32b1ee7eaa | ||
|
|
3e2a498ae7 | ||
|
|
e0ac9b7ddf | ||
|
|
bbf10a7ad0 | ||
|
|
62a0992e5e | ||
|
|
b2e49d174e | ||
|
|
5e218721e7 | ||
|
|
c64cd53ac3 | ||
|
|
920ab6cb60 | ||
|
|
ae726b3796 |
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
* text=auto
|
||||
*.cs text=auto diff=csharp
|
||||
*.sln text=auto eol=crlf
|
||||
17
.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.0.100
|
||||
dotnet-version: '5.0.x'
|
||||
|
||||
- name: Build (Release)
|
||||
run: dotnet build src -c Release
|
||||
|
||||
|
||||
- name: SpecFileGen
|
||||
run: dotnet src/SpecFileGen/bin/Release/netcoreapp2.1/SpecFileGen.dll
|
||||
run: dotnet src/SpecFileGen/bin/Release/net5.0/SpecFileGen.dll
|
||||
|
||||
- name: Test (Release)
|
||||
run: dotnet test src -c Release
|
||||
@@ -38,18 +38,21 @@ jobs:
|
||||
run: dotnet test src -c Debug
|
||||
|
||||
- name: Coverlet
|
||||
run: dotnet test src -c Release -f netcoreapp2.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'
|
||||
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.netcoreapp2.1.info
|
||||
path-to-lcov: src/${{env.PROJECT_NAME}}.Tests/coverage.info
|
||||
|
||||
- name: Pack
|
||||
run: dotnet pack src -c Release
|
||||
|
||||
- name: Pack Signed
|
||||
run: dotnet pack -c Release src/${{env.PROJECT_NAME}}.Signed/${{env.PROJECT_NAME}}.Signed.csproj
|
||||
|
||||
- name: Publish
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
|
||||
25
.gitignore
vendored
@@ -138,7 +138,7 @@ publish/
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
@@ -216,3 +216,26 @@ FakesAssemblies/
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Common IntelliJ Platform excludes
|
||||
|
||||
# User specific
|
||||
**/.idea/**/workspace.xml
|
||||
**/.idea/**/tasks.xml
|
||||
**/.idea/shelf/*
|
||||
**/.idea/dictionaries
|
||||
**/.idea/httpRequests/
|
||||
|
||||
# Sensitive or high-churn files
|
||||
**/.idea/**/dataSources/
|
||||
**/.idea/**/dataSources.ids
|
||||
**/.idea/**/dataSources.xml
|
||||
**/.idea/**/dataSources.local.xml
|
||||
**/.idea/**/sqlDataSources.xml
|
||||
**/.idea/**/dynamic.xml
|
||||
|
||||
# Rider
|
||||
# Rider auto-generates .iml files, and contentModel.xml
|
||||
**/.idea/**/*.iml
|
||||
**/.idea/**/contentModel.xml
|
||||
**/.idea/**/modules.xml
|
||||
|
||||
468
changelog.md
@@ -1,213 +1,255 @@
|
||||
# Changelog
|
||||
|
||||
## 0.20.0 (18 Apr 2020)
|
||||
- Markdig is now compatible only with `NETStandard 2.0`, `NETStandard 2.1`, `NETCoreApp 2.1` and `NETCoreApp 3.1`.
|
||||
- Many performance improvements from [PR #416](https://github.com/lunet-io/markdig/pull/416)
|
||||
[PR #417](https://github.com/lunet-io/markdig/pull/417)
|
||||
[PR #418](https://github.com/lunet-io/markdig/pull/418)
|
||||
[PR #421](https://github.com/lunet-io/markdig/pull/421)
|
||||
[PR #422](https://github.com/lunet-io/markdig/pull/422)
|
||||
[PR #410](https://github.com/lunet-io/markdig/pull/410)
|
||||
|
||||
## 0.18.3 (8 Mar 2020)
|
||||
- Publish NuGet Symbol packages
|
||||
|
||||
## 0.18.2 (8 Mar 2020)
|
||||
- Optimize LineReader.ReadLine in [PR #393](https://github.com/lunet-io/markdig/pull/393)
|
||||
- Use HashSet<T> instead of Dictionary<TKey, TValue> in CharacterMap<T> in [PR #394](https://github.com/lunet-io/markdig/pull/394)
|
||||
- Use BitVector128 in CharacterMap<T> in [PR #396](https://github.com/lunet-io/markdig/pull/396)
|
||||
- Optimizations in StringLineGroup in [PR #399](https://github.com/lunet-io/markdig/pull/399)
|
||||
- Fixed a bug in HeadingRenderer in [PR #402](https://github.com/lunet-io/markdig/pull/402)
|
||||
- Fixes issue #303 in [PR #404](https://github.com/lunet-io/markdig/pull/404)
|
||||
- Make output of HtmlTableRenderer XML wellformed in [PR #406](https://github.com/lunet-io/markdig/pull/406)
|
||||
|
||||
## 0.18.1 (21 Jan 2020)
|
||||
- Re-allow emojis and smileys customization, that was broken in [PR #308](https://github.com/lunet-io/markdig/pull/308) ([PR #386](https://github.com/lunet-io/markdig/pull/386))
|
||||
- Add `IHostProvider` for medialink customization (#337), support protocol-less url (#135) ([(PR #341)](https://github.com/lunet-io/markdig/pull/341))
|
||||
- Add missing Descendants<T> overload ([(PR #387)](https://github.com/lunet-io/markdig/pull/387))
|
||||
|
||||
## 0.18.0 (24 Oct 2019)
|
||||
- Ignore backslashes in GFM AutoLinks ([(PR #357)](https://github.com/lunet-io/markdig/pull/357))
|
||||
- Fix SmartyPants quote matching ([(PR #360)](https://github.com/lunet-io/markdig/pull/360))
|
||||
- Fix generic attributes with values of length 1 ([(PR #361)](https://github.com/lunet-io/markdig/pull/361))
|
||||
- Fix link text balanced bracket matching ([(PR #375)](https://github.com/lunet-io/markdig/pull/375))
|
||||
- Improve overall performance and substantially reduce allocations ([(PR #377)](https://github.com/lunet-io/markdig/pull/377))
|
||||
|
||||
## 0.17.1 (04 July 2019)
|
||||
- Fix regression when escaping HTML characters ([(PR #340)](https://github.com/lunet-io/markdig/pull/340))
|
||||
- Update Emoji Dictionary ([(PR #346)](https://github.com/lunet-io/markdig/pull/346))
|
||||
|
||||
## 0.17.0 (10 May 2019)
|
||||
- Update to latest CommonMark specs 0.29 ([(PR #327)](https://github.com/lunet-io/markdig/pull/327))
|
||||
- Add `AutoLinkOptions` with `OpenInNewWindow`, `UseHttpsForWWWLinks` ([(PR #327)](https://github.com/lunet-io/markdig/pull/327))
|
||||
- Add `DisableHeadings` extension method to `MarkdownPipelineBuilder` ([(PR #327)](https://github.com/lunet-io/markdig/pull/327))
|
||||
- Drop support for netstandard1.1 and Portable Class Libraries ([(PR #319)](https://github.com/lunet-io/markdig/pull/319))
|
||||
- Allow non-ASCII characters in url domain names ([(PR #319)](https://github.com/lunet-io/markdig/pull/319))
|
||||
- Add better support for youtu.be link ([(PR #336)](https://github.com/lunet-io/markdig/pull/336))
|
||||
- Fix backsticks in Markdown.Normalize ([(PR #334)](https://github.com/lunet-io/markdig/pull/334))
|
||||
|
||||
## 0.16.0 (25 Feb 2019)
|
||||
- Improve performance of emoji-abbreviation parser ([(PR #305)](https://github.com/lunet-io/markdig/pull/305))
|
||||
- Change output for math extension to use a rendering more compatible with existing Math JS libraries ([(PR #311)](https://github.com/lunet-io/markdig/pull/311))
|
||||
- Improve emphasis parser to allow to match more than 2 characters ([(PR #301)](https://github.com/lunet-io/markdig/pull/301))
|
||||
- Output attached attributes to a `<tr>` from a table row ([(PR #300)](https://github.com/lunet-io/markdig/pull/300))
|
||||
- Improve MarkdownObject.Descendants() search ([(PR #288)](https://github.com/lunet-io/markdig/pull/288))
|
||||
- Allow to pass a `MarkdownParserContext` ([(PR #285)](https://github.com/lunet-io/markdig/pull/285))
|
||||
|
||||
## 0.15.7 (11 Jan 2019)
|
||||
- Add configurable leading count for ATX headers ([(PR #282)](https://github.com/lunet-io/markdig/pull/282))
|
||||
- Render XML well-formed boolean attribute ([(PR #281)](https://github.com/lunet-io/markdig/pull/281))
|
||||
|
||||
## 0.15.6 (28 Dec 2018)
|
||||
- Fix potential hang when parsing LinkReferenceDefinition #278
|
||||
- Fix parsing of an invalid html entity (#277)
|
||||
- Fix IndexOutOfRangeException while parsing fenced code block with a single trailing space (#276)
|
||||
- Add tests for checking that ArgumentOutOfRangeException doesn't occur on invalid input md string (#275)
|
||||
|
||||
## 0.15.5 (11 Dec 2018)
|
||||
- Empty image alt text for link reference definitions ([(PR #254)](https://github.com/lunet-io/markdig/pull/254))
|
||||
- Fix AutoLink Match links without slash after domain ([(PR #260)](https://github.com/lunet-io/markdig/pull/260))
|
||||
- Make AutoLink ValidPreviousCharacters configurable ([(PR #264)](https://github.com/lunet-io/markdig/pull/264))
|
||||
- Ensuring line breaks when renderer does not have html enabled ([(PR #270)](https://github.com/lunet-io/markdig/pull/270))
|
||||
|
||||
## 0.15.4 (07 Oct 2018)
|
||||
- Add autolink domain GFM validation ([(PR #253)](https://github.com/lunet-io/markdig/pull/253))
|
||||
|
||||
## 0.15.3 (15 Sep 2018)
|
||||
- Add support for RTL ([(PR #239)](https://github.com/lunet-io/markdig/pull/239))
|
||||
- Add MarkdownDocument.LineCount ([(PR #241)](https://github.com/lunet-io/markdig/pull/241))
|
||||
- Fix source positions for link definitions ([(PR #243)](https://github.com/lunet-io/markdig/pull/243))
|
||||
- Add ListItemBlock.Order ([(PR #244)](https://github.com/lunet-io/markdig/pull/244))
|
||||
- Add MarkdownDocument.LineStartIndexes ([(PR #247)](https://github.com/lunet-io/markdig/pull/247))
|
||||
|
||||
## 0.15.2 (21 Aug 2018)
|
||||
- Fix footnotes parsing when they are defined after a container that has been closed in the meantime (#223)
|
||||
|
||||
## 0.15.1 (10 July 2018)
|
||||
- Add support for `netstandard2.0`
|
||||
- Make AutoIdentifierExtension thread safe
|
||||
|
||||
## 0.15.0 (4 Apr 2018)
|
||||
- Add `ConfigureNewLine` extension method to `MarkdownPipelineBuilder` ([(PR #214)](https://github.com/lunet-io/markdig/pull/214))
|
||||
- Add alternative `Use` extension method to `MarkdownPipelineBuilder` that receives an object instance ([(PR #213)](https://github.com/lunet-io/markdig/pull/213))
|
||||
- Added class attribute to media link extension ([(PR #203)](https://github.com/lunet-io/markdig/pull/203))
|
||||
- Optional link rewriter func for HtmlRenderer #143 ([(PR #201)](https://github.com/lunet-io/markdig/pull/201))
|
||||
- Upgrade NUnit3TestAdapter from 3.2 to 3.9 to address Resharper test runner problems ([(PR #199)](https://github.com/lunet-io/markdig/pull/199))
|
||||
- HTML renderer supports converting relative URLs on links and images to absolute #143 ([(PR #197)](https://github.com/lunet-io/markdig/pull/197))
|
||||
|
||||
## 0.14.9 (15 Jan 2018)
|
||||
- AutoLinkParser should to remove mailto: in outputted text ([(PR #195)](https://github.com/lunet-io/markdig/pull/195))
|
||||
- Add support for `music.yandex.ru` and `ok.ru` for MediaLinks extension ([(PR #193)](https://github.com/lunet-io/markdig/pull/193))
|
||||
## 0.14.8 (05 Dec 2017)
|
||||
- Fix potential StackOverflow exception when processing deep nested `|` delimiters (#179)
|
||||
## 0.14.7 (25 Nov 2017)
|
||||
- Fix autolink attached attributes not being displayed properly (#175)
|
||||
## 0.14.6 (21 Nov 2017)
|
||||
- Fix yaml frontmatter issue when ending with a empty line (#170)
|
||||
## 0.14.5 (18 Nov 2017)
|
||||
- Fix changelog link from nuget package
|
||||
## 0.14.4 (18 Nov 2017)
|
||||
- Add changelog.md
|
||||
- Fix bug when a thematic break is inside a fenced code block inside a pending list (#164)
|
||||
- Add support for GFM autolinks (#165, #169)
|
||||
- Better handle YAML frontmatter in case the opening `---` is never actually closed (#160)
|
||||
- Fix link conflict between a link to an image definition and heading auto-identifiers (#159)
|
||||
## 0.14.3
|
||||
- Make EmojiExtension.EnableSmiley public
|
||||
## 0.14.2
|
||||
- Fix issue with emphasis preceded/followed by an HTML entity (#157)
|
||||
- Add support for link reference definitions for Normalize renderer (#155)
|
||||
- Add option to disable smiley parsing in EmojiAndSmiley extension
|
||||
## 0.14.1
|
||||
- Fix crash in Markdown.Normalize to handle HtmlBlock correctly
|
||||
- Add better handling of bullet character for lists in Markdown.Normalize
|
||||
## 0.14.0
|
||||
- Add Markdown.ToPlainText, Add option HtmlRenderer.EnableHtmlForBlock.
|
||||
- Add Markdown.Normalize, to allow to normalize a markdown document. Add NormalizeRenderer, to render a MarkdownDocument back to markdown.
|
||||
## 0.13.4
|
||||
- Add support for single table header row without a table body rows (#141)
|
||||
- ADd support for `nomnoml` diagrams
|
||||
## 0.13.3
|
||||
- Add support for Pandoc YAML frontmatter (#138)
|
||||
## 0.13.2
|
||||
- Add support for UAP10.0 (#137)
|
||||
## 0.13.1
|
||||
- Fix indenting issue after a double digit list block using a tab (#134)
|
||||
## 0.13.0
|
||||
- Update to latest CommonMark specs 0.28
|
||||
## 0.12.3
|
||||
- Fix issue with HTML blocks for heading h2,h3,h4,h5,h6 that were not correctly identified as HTML blocks as per CommonMark spec
|
||||
## 0.12.2
|
||||
- Fix issue with generic attributes used just before a pipe table (issue #121)
|
||||
## 0.12.1
|
||||
- Fix issue with media links extension when a URL to video is used, an unexpected closing `</iframe>` was inserted (issue #119)
|
||||
## 0.12.0
|
||||
- Add new extension JiraLink support (thanks to @clarkd)
|
||||
- Fix issue in html attributes not parsing correctly properties (thanks to @meziantou)
|
||||
- Fix issues detected by an automatic static code analysis tool
|
||||
## 0.11.0
|
||||
- Fix issue with math extension and $$ block parsing not handling correctly beginning of a $$ as a inline math instead (issue #107)
|
||||
- Fix issue with custom attributes for emphasis
|
||||
- Add support for new special custom arrows emoji (`->` `<-` `<->` `<=` `=>` `<==>`)
|
||||
## 0.10.7
|
||||
- Fix issue when an url ends by a dot `.`
|
||||
## 0.10.6
|
||||
- Fix emphasis with HTML entities
|
||||
## 0.10.5
|
||||
- Several minor fixes
|
||||
## 0.10.4
|
||||
- Fix issue with autolinks
|
||||
- Normalize number of columns for tables
|
||||
## 0.10.3
|
||||
- Fix issue with pipetables shifting a cell to a new column (issue #73)
|
||||
## 0.10.2
|
||||
- Fix exception when trying to urlize an url with an unicode character outside the supported range by NormD (issue #75)
|
||||
## 0.10.1
|
||||
- Update to latest CommonMark specs
|
||||
- Fix source span for LinkReferenceDefinition
|
||||
## 0.10.0
|
||||
- Breaking change of the IMarkdownExtension to allow to receive the MarkdownPipeline for the renderers setup
|
||||
## 0.9.1
|
||||
- Fix regression bug with conflicts between autolink extension and html inline/regular links
|
||||
## 0.9.0
|
||||
- Add new Autolink extension
|
||||
## 0.8.5
|
||||
- Allow to force table column alignment to left
|
||||
## 0.8.4
|
||||
- Fix issue when calculating the span of an indented code block within a list. Make sure to include first whitespace on the line
|
||||
## 0.8.3
|
||||
- fix NullReferenceException with Gridtables extension when a single `+` is entered on a line
|
||||
## 0.8.2
|
||||
- fix potential cast exception with Abbreviation extension and empty literals
|
||||
## 0.8.1
|
||||
- new extension to disable URI escaping for non-US-ASCII characters to workaround a bug in Edge/IE
|
||||
- Fix an issue with abbreviations with left/right multiple non-punctuation/space characters
|
||||
## 0.8.0
|
||||
- Update to latest CommonMark specs
|
||||
- Fix empty literal
|
||||
- Add YAML frontmatter extension
|
||||
## 0.7.5
|
||||
- several bug fixes (pipe tables, disable HTML, special attributes, inline maths, abbreviations...)
|
||||
- add support for rowspan in grid tables
|
||||
## 0.7.4
|
||||
- Fix bug with strong emphasis starting at the beginning of a line
|
||||
## 0.7.3
|
||||
- Fix threading issue with pipeline
|
||||
## 0.7.2
|
||||
- Fix rendering of table colspan with non english locale
|
||||
- Fix grid table colspan parsing
|
||||
- Add nofollow extension for links
|
||||
## 0.7.1
|
||||
- Fix issue in smarty pants which could lead to an InvalidCastException
|
||||
- Update parsers to latest CommonMark specs
|
||||
## 0.7.0
|
||||
- Update to latest NETStandard.Library 1.6.0
|
||||
- Fix issue with digits in auto-identifier extension
|
||||
- Fix incorrect start of span calculated for code indented blocks
|
||||
## 0.6.2
|
||||
- Handle latest CommonMark specs for corner cases for emphasis (See https://talk.commonmark.org/t/emphasis-strong-emphasis-corner-cases/2123/1 )
|
||||
## 0.6.1:
|
||||
- Fix issue with autoidentifier extension overriding manual HTML attributes id on headings
|
||||
## 0.6.0
|
||||
- Fix conflicts between PipeTables and SmartyPants extensions
|
||||
- Add SelfPipeline extension
|
||||
# Changelog
|
||||
|
||||
## 0.26.0 (27 Aug 2021)
|
||||
- Fix rendering diff between line endings ([PR #560](https://github.com/lunet-io/markdig/pull/560))
|
||||
- Make Mathematics extension respect EnableHtml* options ([PR #570](https://github.com/lunet-io/markdig/pull/570))
|
||||
|
||||
## 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))
|
||||
|
||||
## 0.21.1 (17 Aug 2020)
|
||||
- Fix Markdig.Signed on GitHub Actions
|
||||
|
||||
## 0.21.0 (17 Aug 2020)
|
||||
- Restore support for .NET 4.5 (#)
|
||||
- Add IReadonlyList interface to ContainerBlock to unify and simplify enumeration (#425)
|
||||
- Fix relative uri detection to be cross-platform compatible (#430)
|
||||
- Escape URLs scheme (#431)
|
||||
- Fix media links (#435)
|
||||
- Fix parsing math blocks with no leading or trailing whitespace (#452)
|
||||
- Add support for autolink `tel:` uri (#453)
|
||||
- Fallback to non-punycode encoding for invalid IDN urls (#449)
|
||||
- Pipe Tables: Normalize using header column count (#455)
|
||||
- Expose IndentCount of FencedCodeBlock (#464)
|
||||
|
||||
## 0.20.0 (18 Apr 2020)
|
||||
- Markdig is now compatible only with `NETStandard 2.0`, `NETStandard 2.1`, `NETCoreApp 2.1` and `NETCoreApp 3.1`.
|
||||
- Many performance improvements from [PR #416](https://github.com/lunet-io/markdig/pull/416)
|
||||
[PR #417](https://github.com/lunet-io/markdig/pull/417)
|
||||
[PR #418](https://github.com/lunet-io/markdig/pull/418)
|
||||
[PR #421](https://github.com/lunet-io/markdig/pull/421)
|
||||
[PR #422](https://github.com/lunet-io/markdig/pull/422)
|
||||
[PR #410](https://github.com/lunet-io/markdig/pull/410)
|
||||
|
||||
## 0.18.3 (8 Mar 2020)
|
||||
- Publish NuGet Symbol packages
|
||||
|
||||
## 0.18.2 (8 Mar 2020)
|
||||
- Optimize LineReader.ReadLine in [PR #393](https://github.com/lunet-io/markdig/pull/393)
|
||||
- Use HashSet<T> instead of Dictionary<TKey, TValue> in CharacterMap<T> in [PR #394](https://github.com/lunet-io/markdig/pull/394)
|
||||
- Use BitVector128 in CharacterMap<T> in [PR #396](https://github.com/lunet-io/markdig/pull/396)
|
||||
- Optimizations in StringLineGroup in [PR #399](https://github.com/lunet-io/markdig/pull/399)
|
||||
- Fixed a bug in HeadingRenderer in [PR #402](https://github.com/lunet-io/markdig/pull/402)
|
||||
- Fixes issue #303 in [PR #404](https://github.com/lunet-io/markdig/pull/404)
|
||||
- Make output of HtmlTableRenderer XML wellformed in [PR #406](https://github.com/lunet-io/markdig/pull/406)
|
||||
|
||||
## 0.18.1 (21 Jan 2020)
|
||||
- Re-allow emojis and smileys customization, that was broken in [PR #308](https://github.com/lunet-io/markdig/pull/308) ([PR #386](https://github.com/lunet-io/markdig/pull/386))
|
||||
- Add `IHostProvider` for medialink customization (#337), support protocol-less url (#135) ([(PR #341)](https://github.com/lunet-io/markdig/pull/341))
|
||||
- Add missing Descendants<T> overload ([(PR #387)](https://github.com/lunet-io/markdig/pull/387))
|
||||
|
||||
## 0.18.0 (24 Oct 2019)
|
||||
- Ignore backslashes in GFM AutoLinks ([(PR #357)](https://github.com/lunet-io/markdig/pull/357))
|
||||
- Fix SmartyPants quote matching ([(PR #360)](https://github.com/lunet-io/markdig/pull/360))
|
||||
- Fix generic attributes with values of length 1 ([(PR #361)](https://github.com/lunet-io/markdig/pull/361))
|
||||
- Fix link text balanced bracket matching ([(PR #375)](https://github.com/lunet-io/markdig/pull/375))
|
||||
- Improve overall performance and substantially reduce allocations ([(PR #377)](https://github.com/lunet-io/markdig/pull/377))
|
||||
|
||||
## 0.17.1 (04 July 2019)
|
||||
- Fix regression when escaping HTML characters ([(PR #340)](https://github.com/lunet-io/markdig/pull/340))
|
||||
- Update Emoji Dictionary ([(PR #346)](https://github.com/lunet-io/markdig/pull/346))
|
||||
|
||||
## 0.17.0 (10 May 2019)
|
||||
- Update to latest CommonMark specs 0.29 ([(PR #327)](https://github.com/lunet-io/markdig/pull/327))
|
||||
- Add `AutoLinkOptions` with `OpenInNewWindow`, `UseHttpsForWWWLinks` ([(PR #327)](https://github.com/lunet-io/markdig/pull/327))
|
||||
- Add `DisableHeadings` extension method to `MarkdownPipelineBuilder` ([(PR #327)](https://github.com/lunet-io/markdig/pull/327))
|
||||
- Drop support for netstandard1.1 and Portable Class Libraries ([(PR #319)](https://github.com/lunet-io/markdig/pull/319))
|
||||
- Allow non-ASCII characters in url domain names ([(PR #319)](https://github.com/lunet-io/markdig/pull/319))
|
||||
- Add better support for youtu.be link ([(PR #336)](https://github.com/lunet-io/markdig/pull/336))
|
||||
- Fix backsticks in Markdown.Normalize ([(PR #334)](https://github.com/lunet-io/markdig/pull/334))
|
||||
|
||||
## 0.16.0 (25 Feb 2019)
|
||||
- Improve performance of emoji-abbreviation parser ([(PR #305)](https://github.com/lunet-io/markdig/pull/305))
|
||||
- Change output for math extension to use a rendering more compatible with existing Math JS libraries ([(PR #311)](https://github.com/lunet-io/markdig/pull/311))
|
||||
- Improve emphasis parser to allow to match more than 2 characters ([(PR #301)](https://github.com/lunet-io/markdig/pull/301))
|
||||
- Output attached attributes to a `<tr>` from a table row ([(PR #300)](https://github.com/lunet-io/markdig/pull/300))
|
||||
- Improve MarkdownObject.Descendants() search ([(PR #288)](https://github.com/lunet-io/markdig/pull/288))
|
||||
- Allow to pass a `MarkdownParserContext` ([(PR #285)](https://github.com/lunet-io/markdig/pull/285))
|
||||
|
||||
## 0.15.7 (11 Jan 2019)
|
||||
- Add configurable leading count for ATX headers ([(PR #282)](https://github.com/lunet-io/markdig/pull/282))
|
||||
- Render XML well-formed boolean attribute ([(PR #281)](https://github.com/lunet-io/markdig/pull/281))
|
||||
|
||||
## 0.15.6 (28 Dec 2018)
|
||||
- Fix potential hang when parsing LinkReferenceDefinition #278
|
||||
- Fix parsing of an invalid html entity (#277)
|
||||
- Fix IndexOutOfRangeException while parsing fenced code block with a single trailing space (#276)
|
||||
- Add tests for checking that ArgumentOutOfRangeException doesn't occur on invalid input md string (#275)
|
||||
|
||||
## 0.15.5 (11 Dec 2018)
|
||||
- Empty image alt text for link reference definitions ([(PR #254)](https://github.com/lunet-io/markdig/pull/254))
|
||||
- Fix AutoLink Match links without slash after domain ([(PR #260)](https://github.com/lunet-io/markdig/pull/260))
|
||||
- Make AutoLink ValidPreviousCharacters configurable ([(PR #264)](https://github.com/lunet-io/markdig/pull/264))
|
||||
- Ensuring line breaks when renderer does not have html enabled ([(PR #270)](https://github.com/lunet-io/markdig/pull/270))
|
||||
|
||||
## 0.15.4 (07 Oct 2018)
|
||||
- Add autolink domain GFM validation ([(PR #253)](https://github.com/lunet-io/markdig/pull/253))
|
||||
|
||||
## 0.15.3 (15 Sep 2018)
|
||||
- Add support for RTL ([(PR #239)](https://github.com/lunet-io/markdig/pull/239))
|
||||
- Add MarkdownDocument.LineCount ([(PR #241)](https://github.com/lunet-io/markdig/pull/241))
|
||||
- Fix source positions for link definitions ([(PR #243)](https://github.com/lunet-io/markdig/pull/243))
|
||||
- Add ListItemBlock.Order ([(PR #244)](https://github.com/lunet-io/markdig/pull/244))
|
||||
- Add MarkdownDocument.LineStartIndexes ([(PR #247)](https://github.com/lunet-io/markdig/pull/247))
|
||||
|
||||
## 0.15.2 (21 Aug 2018)
|
||||
- Fix footnotes parsing when they are defined after a container that has been closed in the meantime (#223)
|
||||
|
||||
## 0.15.1 (10 July 2018)
|
||||
- Add support for `netstandard2.0`
|
||||
- Make AutoIdentifierExtension thread safe
|
||||
|
||||
## 0.15.0 (4 Apr 2018)
|
||||
- Add `ConfigureNewLine` extension method to `MarkdownPipelineBuilder` ([(PR #214)](https://github.com/lunet-io/markdig/pull/214))
|
||||
- Add alternative `Use` extension method to `MarkdownPipelineBuilder` that receives an object instance ([(PR #213)](https://github.com/lunet-io/markdig/pull/213))
|
||||
- Added class attribute to media link extension ([(PR #203)](https://github.com/lunet-io/markdig/pull/203))
|
||||
- Optional link rewriter func for HtmlRenderer #143 ([(PR #201)](https://github.com/lunet-io/markdig/pull/201))
|
||||
- Upgrade NUnit3TestAdapter from 3.2 to 3.9 to address Resharper test runner problems ([(PR #199)](https://github.com/lunet-io/markdig/pull/199))
|
||||
- HTML renderer supports converting relative URLs on links and images to absolute #143 ([(PR #197)](https://github.com/lunet-io/markdig/pull/197))
|
||||
|
||||
## 0.14.9 (15 Jan 2018)
|
||||
- AutoLinkParser should to remove mailto: in outputted text ([(PR #195)](https://github.com/lunet-io/markdig/pull/195))
|
||||
- Add support for `music.yandex.ru` and `ok.ru` for MediaLinks extension ([(PR #193)](https://github.com/lunet-io/markdig/pull/193))
|
||||
## 0.14.8 (05 Dec 2017)
|
||||
- Fix potential StackOverflow exception when processing deep nested `|` delimiters (#179)
|
||||
## 0.14.7 (25 Nov 2017)
|
||||
- Fix autolink attached attributes not being displayed properly (#175)
|
||||
## 0.14.6 (21 Nov 2017)
|
||||
- Fix yaml frontmatter issue when ending with a empty line (#170)
|
||||
## 0.14.5 (18 Nov 2017)
|
||||
- Fix changelog link from nuget package
|
||||
## 0.14.4 (18 Nov 2017)
|
||||
- Add changelog.md
|
||||
- Fix bug when a thematic break is inside a fenced code block inside a pending list (#164)
|
||||
- Add support for GFM autolinks (#165, #169)
|
||||
- Better handle YAML frontmatter in case the opening `---` is never actually closed (#160)
|
||||
- Fix link conflict between a link to an image definition and heading auto-identifiers (#159)
|
||||
## 0.14.3
|
||||
- Make EmojiExtension.EnableSmiley public
|
||||
## 0.14.2
|
||||
- Fix issue with emphasis preceded/followed by an HTML entity (#157)
|
||||
- Add support for link reference definitions for Normalize renderer (#155)
|
||||
- Add option to disable smiley parsing in EmojiAndSmiley extension
|
||||
## 0.14.1
|
||||
- Fix crash in Markdown.Normalize to handle HtmlBlock correctly
|
||||
- Add better handling of bullet character for lists in Markdown.Normalize
|
||||
## 0.14.0
|
||||
- Add Markdown.ToPlainText, Add option HtmlRenderer.EnableHtmlForBlock.
|
||||
- Add Markdown.Normalize, to allow to normalize a markdown document. Add NormalizeRenderer, to render a MarkdownDocument back to markdown.
|
||||
## 0.13.4
|
||||
- Add support for single table header row without a table body rows (#141)
|
||||
- ADd support for `nomnoml` diagrams
|
||||
## 0.13.3
|
||||
- Add support for Pandoc YAML frontmatter (#138)
|
||||
## 0.13.2
|
||||
- Add support for UAP10.0 (#137)
|
||||
## 0.13.1
|
||||
- Fix indenting issue after a double digit list block using a tab (#134)
|
||||
## 0.13.0
|
||||
- Update to latest CommonMark specs 0.28
|
||||
## 0.12.3
|
||||
- Fix issue with HTML blocks for heading h2,h3,h4,h5,h6 that were not correctly identified as HTML blocks as per CommonMark spec
|
||||
## 0.12.2
|
||||
- Fix issue with generic attributes used just before a pipe table (issue #121)
|
||||
## 0.12.1
|
||||
- Fix issue with media links extension when a URL to video is used, an unexpected closing `</iframe>` was inserted (issue #119)
|
||||
## 0.12.0
|
||||
- Add new extension JiraLink support (thanks to @clarkd)
|
||||
- Fix issue in html attributes not parsing correctly properties (thanks to @meziantou)
|
||||
- Fix issues detected by an automatic static code analysis tool
|
||||
## 0.11.0
|
||||
- Fix issue with math extension and $$ block parsing not handling correctly beginning of a $$ as a inline math instead (issue #107)
|
||||
- Fix issue with custom attributes for emphasis
|
||||
- Add support for new special custom arrows emoji (`->` `<-` `<->` `<=` `=>` `<==>`)
|
||||
## 0.10.7
|
||||
- Fix issue when an url ends by a dot `.`
|
||||
## 0.10.6
|
||||
- Fix emphasis with HTML entities
|
||||
## 0.10.5
|
||||
- Several minor fixes
|
||||
## 0.10.4
|
||||
- Fix issue with autolinks
|
||||
- Normalize number of columns for tables
|
||||
## 0.10.3
|
||||
- Fix issue with pipetables shifting a cell to a new column (issue #73)
|
||||
## 0.10.2
|
||||
- Fix exception when trying to urlize an url with an unicode character outside the supported range by NormD (issue #75)
|
||||
## 0.10.1
|
||||
- Update to latest CommonMark specs
|
||||
- Fix source span for LinkReferenceDefinition
|
||||
## 0.10.0
|
||||
- Breaking change of the IMarkdownExtension to allow to receive the MarkdownPipeline for the renderers setup
|
||||
## 0.9.1
|
||||
- Fix regression bug with conflicts between autolink extension and html inline/regular links
|
||||
## 0.9.0
|
||||
- Add new Autolink extension
|
||||
## 0.8.5
|
||||
- Allow to force table column alignment to left
|
||||
## 0.8.4
|
||||
- Fix issue when calculating the span of an indented code block within a list. Make sure to include first whitespace on the line
|
||||
## 0.8.3
|
||||
- fix NullReferenceException with Gridtables extension when a single `+` is entered on a line
|
||||
## 0.8.2
|
||||
- fix potential cast exception with Abbreviation extension and empty literals
|
||||
## 0.8.1
|
||||
- new extension to disable URI escaping for non-US-ASCII characters to workaround a bug in Edge/IE
|
||||
- Fix an issue with abbreviations with left/right multiple non-punctuation/space characters
|
||||
## 0.8.0
|
||||
- Update to latest CommonMark specs
|
||||
- Fix empty literal
|
||||
- Add YAML frontmatter extension
|
||||
## 0.7.5
|
||||
- several bug fixes (pipe tables, disable HTML, special attributes, inline maths, abbreviations...)
|
||||
- add support for rowspan in grid tables
|
||||
## 0.7.4
|
||||
- Fix bug with strong emphasis starting at the beginning of a line
|
||||
## 0.7.3
|
||||
- Fix threading issue with pipeline
|
||||
## 0.7.2
|
||||
- Fix rendering of table colspan with non english locale
|
||||
- Fix grid table colspan parsing
|
||||
- Add nofollow extension for links
|
||||
## 0.7.1
|
||||
- Fix issue in smarty pants which could lead to an InvalidCastException
|
||||
- Update parsers to latest CommonMark specs
|
||||
## 0.7.0
|
||||
- Update to latest NETStandard.Library 1.6.0
|
||||
- Fix issue with digits in auto-identifier extension
|
||||
- Fix incorrect start of span calculated for code indented blocks
|
||||
## 0.6.2
|
||||
- Handle latest CommonMark specs for corner cases for emphasis (See https://talk.commonmark.org/t/emphasis-strong-emphasis-corner-cases/2123/1 )
|
||||
## 0.6.1:
|
||||
- Fix issue with autoidentifier extension overriding manual HTML attributes id on headings
|
||||
## 0.6.0
|
||||
- Fix conflicts between PipeTables and SmartyPants extensions
|
||||
- Add SelfPipeline extension
|
||||
|
||||
BIN
img/markdig.png
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 16 KiB |
@@ -14,11 +14,11 @@
|
||||
viewBox="0 0 192 192"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="markdig.svg"
|
||||
inkscape:export-filename="C:\Code\lunet-io\markdig\markdig.png"
|
||||
inkscape:export-xdpi="93.400002"
|
||||
inkscape:export-ydpi="93.400002">
|
||||
inkscape:export-filename="C:\code\lunet\markdig\img\markdig.png"
|
||||
inkscape:export-xdpi="256"
|
||||
inkscape:export-ydpi="256">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
@@ -28,16 +28,16 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.4374889"
|
||||
inkscape:cx="174.14769"
|
||||
inkscape:cy="93.189838"
|
||||
inkscape:zoom="6.275557"
|
||||
inkscape:cx="81.620292"
|
||||
inkscape:cy="119.68434"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2066"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
units="px" />
|
||||
<metadata
|
||||
@@ -48,7 +48,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -59,13 +59,8 @@
|
||||
style="display:inline"
|
||||
transform="translate(0,-860.36216)">
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="M 75.009766 60.486328 L 34.648438 122.74414 C 33.793918 123.59769 37.647081 134.96384 37.052734 136.09766 L 4.0234375 177.69727 C 2.4142291 180.39677 3.2900484 182.21846 4.8730469 183.84766 C 5.9214414 184.93636 6.6591287 186.06887 8.3828125 185.67188 C 9.0750612 185.50987 10.104893 185.27338 10.875 184.76758 L 52.806641 151.81445 C 53.912466 151.23195 64.44071 154.77813 65.289062 153.92383 L 126.45312 111.46875 L 75.009766 60.486328 z M 89.632812 84.769531 L 103.77539 98.912109 L 79.027344 123.66016 L 86.238281 130.87109 L 48.621094 139.92383 L 57.435547 102.30859 L 64.884766 109.51758 L 89.632812 84.769531 z "
|
||||
transform="translate(0,860.36216)"
|
||||
id="path4140" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
d="m 111.18463,862.06984 c -1.98231,0 -3.96282,0.78454 -5.54759,2.38445 L 88.200894,881.94537 75.123368,868.82653 c -3.169466,-3.18017 -7.92567,-3.18017 -11.095213,0 -3.169466,3.18017 -3.169466,7.95108 0,11.13109 l 13.077526,13.11885 -11.095212,10.73223 82.031621,81.49227 11.09525,-11.13109 13.87084,13.51554 c 1.57915,1.59105 3.56724,2.38445 5.54759,2.38445 1.98231,0 3.96285,-0.78453 5.54762,-2.38445 3.16947,-3.18017 3.16947,-7.95111 0,-11.13109 l -13.87083,-13.11884 17.43611,-17.09442 c 1.17983,-1.59105 1.98231,-3.5788 1.98231,-5.96329 0,-1.98351 -0.79863,-3.97554 -2.37816,-5.56446 l -70.54053,-70.35856 c -1.57914,-1.59105 -3.56724,-2.38446 -5.54758,-2.38446 z m 15.86949,20.75826 9.50139,9.5291 -4.04453,23.11372 23.04691,-4.05619 9.50138,9.5291 -36.8437,36.95052 -9.50135,-9.5291 21.13082,-21.19197 -23.04672,4.05619 4.04453,-23.11396 -21.131009,21.19198 -9.501383,-9.5291 36.843662,-36.95048 z"
|
||||
style="fill:#006680;fill-opacity:1;stroke-width:1.09204066"
|
||||
d="m 34.5307,873.24547 c -1.506145,1.5557 -2.414834,3.72567 -2.403331,6.22497 l 0.04173,27.41047 -19.903814,-0.0324 c -4.824408,-0.009 -8.4381391,3.7242 -8.4300642,8.70738 0.00817,4.98312 3.6330369,8.72727 8.4573232,8.73554 l 19.903821,0.0324 -0.275791,17.12991 124.244306,-0.42328 -0.0273,-17.44297 20.80798,-0.27883 c 2.4087,0.009 4.52205,-0.92824 6.02671,-2.48239 1.50614,-1.55569 2.41486,-3.72569 2.40336,-6.225 -0.009,-4.98311 -3.63306,-8.7273 -8.45733,-8.73554 l -20.50656,0.59015 0.25961,-27.09914 c -0.31244,-2.17456 -1.213,-4.36429 -3.02472,-6.23561 -1.50705,-1.55665 -3.62738,-2.49321 -6.03475,-2.50058 l -107.054134,0.14282 c -2.408688,-0.009 -4.522059,0.92823 -6.026707,2.48237 z m 27.829505,3.83665 14.459233,0.0217 14.488635,21.31347 14.429017,-21.27019 14.45922,0.0217 0.0811,57.91281 -14.4592,-0.0217 -0.0464,-33.21443 -14.428869,21.27005 -14.488819,-21.31366 0.04632,33.21458 -14.459226,-0.0218 -0.08116,-57.91275 z"
|
||||
id="path4142"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
@@ -95,7 +90,7 @@
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot4797"
|
||||
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="font-style:normal;font-weight:normal;line-height:0.01%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
transform="matrix(0.1746417,0,0,0.1459084,499.69318,366.39614)"><flowRegion
|
||||
id="flowRegion4799"><rect
|
||||
id="rect4801"
|
||||
@@ -103,7 +98,8 @@
|
||||
height="618.71844"
|
||||
x="959.01355"
|
||||
y="-976.15039" /></flowRegion><flowPara
|
||||
id="flowPara4803" /></flowRoot> <g
|
||||
id="flowPara4803"
|
||||
style="font-size:40px;line-height:1.25"> </flowPara></flowRoot> <g
|
||||
id="g4833"
|
||||
transform="matrix(0.09510056,0,0,0.09061765,496.09965,368.83934)">
|
||||
<rect
|
||||
@@ -114,18 +110,20 @@
|
||||
y="0"
|
||||
style="fill:#ffffff" />
|
||||
</g>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4886"
|
||||
d="m 111.18463,862.06984 c -1.98231,0 -3.96282,0.78454 -5.54759,2.38445 L 88.200894,881.94537 75.123368,868.82653 c -3.169466,-3.18017 -7.92567,-3.18017 -11.095213,0 -3.169466,3.18017 -3.169466,7.95108 0,11.13109 l 13.077526,13.11885 -11.095212,10.73223 82.031621,81.49227 11.09525,-11.13109 13.87084,13.51554 c 1.57915,1.59105 3.56724,2.38445 5.54759,2.38445 1.98231,0 3.96285,-0.78453 5.54762,-2.38445 3.16947,-3.18017 3.16947,-7.95111 0,-11.13109 l -13.87083,-13.11884 17.43611,-17.09442 c 1.17983,-1.59105 1.98231,-3.5788 1.98231,-5.96329 0,-1.98351 -0.79863,-3.97554 -2.37816,-5.56446 l -70.54053,-70.35856 c -1.57914,-1.59105 -3.56724,-2.38446 -5.54758,-2.38446 z m 15.86949,20.75826 9.50139,9.5291 -4.04453,23.11372 23.04691,-4.05619 9.50138,9.5291 -36.8437,36.95052 -9.50135,-9.5291 21.13082,-21.19197 -23.04672,4.05619 4.04453,-23.11396 -21.131009,21.19198 -9.501383,-9.5291 36.843662,-36.95048 z"
|
||||
style="fill:#000000;fill-opacity:1" />
|
||||
<g
|
||||
transform="translate(234.63786,787.55486)"
|
||||
id="g4170" />
|
||||
<path
|
||||
id="path4225"
|
||||
transform="translate(0,860.36216)"
|
||||
d="M 75.009766 60.486328 L 34.648438 122.74414 C 33.793918 123.59769 37.647081 134.96384 37.052734 136.09766 L 4.0234375 177.69727 C 2.4142291 180.39677 3.2900484 182.21846 4.8730469 183.84766 C 5.9214414 184.93636 6.6591287 186.06887 8.3828125 185.67188 C 9.0750612 185.50987 10.104893 185.27338 10.875 184.76758 L 52.806641 151.81445 C 53.912466 151.23195 64.44071 154.77813 65.289062 153.92383 L 126.45312 111.46875 L 75.009766 60.486328 z M 89.632812 84.769531 L 103.77539 98.912109 L 79.027344 123.66016 L 86.238281 130.87109 L 48.621094 139.92383 L 57.435547 102.30859 L 64.884766 109.51758 L 89.632812 84.769531 z "
|
||||
style="fill:#000000" />
|
||||
sodipodi:nodetypes="cccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path826"
|
||||
d="m 45.058494,943.54749 20.013843,88.87081 c -8.87e-4,1.4793 13.909884,7.9857 28.77803,7.9868 14.868153,0 27.732473,-6.0454 27.727033,-7.5199 l 17.1004,-89.73688 z m 35.561125,8.36596 h 25.853221 l 10e-6,42.86491 h 13.18189 l -26.108514,40.41734 -26.324515,-40.20925 13.397908,-0.20809 z"
|
||||
style="fill:#ff6600;stroke-width:1.2582258" />
|
||||
<path
|
||||
style="fill:#c83737;stroke-width:1.2582258"
|
||||
d="m 45.058494,943.54749 20.013843,88.87081 c -8.87e-4,1.4793 13.909884,7.9857 28.77803,7.9868 14.868153,0 27.732473,-6.0454 27.727033,-7.5199 l 17.1004,-89.73688 z m 35.561125,8.36596 h 25.853221 l 10e-6,42.86491 h 13.18189 l -26.108514,40.41734 -26.324515,-40.20925 13.397908,-0.20809 z"
|
||||
id="path828"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -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))
|
||||
@@ -59,6 +60,7 @@ If you are looking for support for an old .NET Framework 3.5 or 4.0, you can dow
|
||||
- [**WPF/XAML Markdown Renderer**: `markdig.wpf`](https://github.com/Kryptos-FR/markdig.wpf)
|
||||
- [**WPF/XAML Markdown Renderer**: `Neo.Markdig.Xaml`](https://github.com/neolithos/NeoMarkdigXaml)
|
||||
- [**Syntax highlighting**: `Markdig.SyntaxHighlighting`](https://github.com/RichardSlater/Markdig.SyntaxHighlighting)
|
||||
- [**Syntax highlighting using Prism.js**: `WebStoating.Markdig.Prism`](https://github.com/ilich/Markdig.Prism)
|
||||
- [**Embedded C# scripting**: `Markdig.Extensions.ScriptCs`](https://github.com/macaba/Markdig.Extensions.ScriptCs)
|
||||
|
||||
## Documentation
|
||||
@@ -94,6 +96,8 @@ var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
|
||||
var result = Markdown.ToHtml("This is a text with some *emphasis*", pipeline);
|
||||
```
|
||||
|
||||
[Try it online!](https://dotnetfiddle.net/GoZXyI)
|
||||
|
||||
You can have a look at the [MarkdownExtensions](https://github.com/lunet-io/markdig/blob/master/src/Markdig/MarkdownExtensions.cs) that describes all actionable extensions (by modifying the MarkdownPipeline)
|
||||
|
||||
## Build
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -5,14 +5,9 @@ extern alias newcmark;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnostics;
|
||||
using BenchmarkDotNet.Diagnostics.Windows;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Running;
|
||||
using newcmark::CommonMark.Extension;
|
||||
using Markdig;
|
||||
|
||||
|
||||
@@ -55,7 +50,7 @@ namespace Testamina.Markdig.Benchmarks
|
||||
//CommonMark.CommonMarkConverter.Parse(reader);
|
||||
//reader.Dispose();
|
||||
//var writer = new StringWriter();
|
||||
global::CommonMark.CommonMarkConverter.Convert(text);
|
||||
CommonMark.CommonMarkConverter.Convert(text);
|
||||
//writer.Flush();
|
||||
//writer.ToString();
|
||||
}
|
||||
|
||||
@@ -2,13 +2,9 @@
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Markdig.Helpers;
|
||||
|
||||
namespace Testamina.Markdig.Benchmarks
|
||||
{
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
|
||||
<OutputType>Library</OutputType>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.msbuild" Version="2.8.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Markdig\Markdig.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<IsPackable>false</IsPackable>
|
||||
<StartupObject>Markdig.Tests.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.msbuild" Version="2.9.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<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>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Markdig\Markdig.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,241 +1,288 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Markdig.Extensions.AutoLinks;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
public class MiscTests
|
||||
{
|
||||
[TestCase("link [foo [bar]]")] // https://spec.commonmark.org/0.29/#example-508
|
||||
[TestCase("link [foo][bar]")]
|
||||
[TestCase("link [][foo][bar][]")]
|
||||
[TestCase("link [][foo][bar][[]]")]
|
||||
[TestCase("link [foo] [bar]")]
|
||||
[TestCase("link [[foo] [] [bar] [[abc]def]]")]
|
||||
[TestCase("[]")]
|
||||
[TestCase("[ ]")]
|
||||
[TestCase("[bar][]")]
|
||||
[TestCase("[bar][ foo]")]
|
||||
[TestCase("[bar][foo ][]")]
|
||||
[TestCase("[bar][fo[ ]o ][][]")]
|
||||
[TestCase("[a]b[c[d[e]f]g]h")]
|
||||
[TestCase("a[b[c[d]e]f[g]h]i foo [j]k[l[m]n]o")]
|
||||
[TestCase("a[b[c[d]e]f[g]h]i[] [][foo][bar][] foo [j]k[l[m]n]o")]
|
||||
[TestCase("a[b[c[d]e]f[g]h]i foo [j]k[l[m]n]o[][]")]
|
||||
public void LinkTextMayContainBalancedBrackets(string linkText)
|
||||
{
|
||||
string markdown = $"[{linkText}](/uri)";
|
||||
string expected = $@"<p><a href=""/uri"">{linkText}</a></p>";
|
||||
|
||||
TestParser.TestSpec(markdown, expected);
|
||||
|
||||
// Make the link text unbalanced
|
||||
foreach (var bracketIndex in linkText
|
||||
.Select((c, i) => new Tuple<char, int>(c, i))
|
||||
.Where(t => t.Item1 == '[' || t.Item1 == ']')
|
||||
.Select(t => t.Item2))
|
||||
{
|
||||
string brokenLinkText = linkText.Remove(bracketIndex, 1);
|
||||
|
||||
markdown = $"[{brokenLinkText}](/uri)";
|
||||
expected = $@"<p><a href=""/uri"">{brokenLinkText}</a></p>";
|
||||
|
||||
string actual = Markdown.ToHtml(markdown);
|
||||
Assert.AreNotEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIssue356Corrected()
|
||||
{
|
||||
string input = @"https://foo.bar/path/\#m4mv5W0GYKZpGvfA.97";
|
||||
string expected = @"<p><a href=""https://foo.bar/path/%5C#m4mv5W0GYKZpGvfA.97"">https://foo.bar/path/\#m4mv5W0GYKZpGvfA.97</a></p>";
|
||||
|
||||
TestParser.TestSpec($"<{input}>", expected);
|
||||
TestParser.TestSpec(input, expected, "autolinks|advanced");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAltTextIsCorrectlyEscaped()
|
||||
{
|
||||
TestParser.TestSpec(
|
||||
@"",
|
||||
@"<p><img src=""girl.png"" alt=""This is image alt text with quotation ' and double quotation "hello" world"" /></p>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangelogPRLinksMatchDescription()
|
||||
{
|
||||
string solutionFolder = Path.GetFullPath(Path.Combine(TestParser.TestsDirectory, "../.."));
|
||||
string changelogPath = Path.Combine(solutionFolder, "changelog.md");
|
||||
string changelog = File.ReadAllText(changelogPath);
|
||||
var matches = Regex.Matches(changelog, @"\(\[\(PR #(\d+)\)\]\(.*?pull\/(\d+)\)\)");
|
||||
Assert.Greater(matches.Count, 0);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
Assert.True(int.TryParse(match.Groups[1].Value, out int textNr));
|
||||
Assert.True(int.TryParse(match.Groups[2].Value, out int linkNr));
|
||||
Assert.AreEqual(textNr, linkNr);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFixHang()
|
||||
{
|
||||
var input = File.ReadAllText(Path.Combine(TestParser.TestsDirectory, "hang.md"));
|
||||
_ = Markdown.ToHtml(input);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidHtmlEntity()
|
||||
{
|
||||
var input = "9&ddr;&*&ddr;&de<64><65>__";
|
||||
TestParser.TestSpec(input, "<p>9&ddr;&*&ddr;&de<64><65>__</p>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidCharacterHandling()
|
||||
{
|
||||
var input = File.ReadAllText(Path.Combine(TestParser.TestsDirectory, "ArgumentOutOfRangeException.md"));
|
||||
_ = Markdown.ToHtml(input);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidCodeEscape()
|
||||
{
|
||||
var input = "```**Header** ";
|
||||
_ = Markdown.ToHtml(input);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmphasisAndHtmlEntity()
|
||||
{
|
||||
var markdownText = "*Unlimited-Fun®*®";
|
||||
TestParser.TestSpec(markdownText, "<p><em>Unlimited-Fun®</em>®</p>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestThematicInsideCodeBlockInsideList()
|
||||
{
|
||||
var input = @"1. In the :
|
||||
|
||||
```
|
||||
Id DisplayName Description
|
||||
-- ----------- -----------
|
||||
62375ab9-6b52-47ed-826b-58e47e0e304b Group.Unified ...
|
||||
```";
|
||||
TestParser.TestSpec(input, @"<ol>
|
||||
<li><p>In the :</p>
|
||||
<pre><code>Id DisplayName Description
|
||||
-- ----------- -----------
|
||||
62375ab9-6b52-47ed-826b-58e47e0e304b Group.Unified ...
|
||||
</code></pre></li>
|
||||
</ol>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VisualizeMathExpressions()
|
||||
{
|
||||
string math = @"Math expressions
|
||||
|
||||
$\frac{n!}{k!(n-k)!} = \binom{n}{k}$
|
||||
|
||||
$$\frac{n!}{k!(n-k)!} = \binom{n}{k}$$
|
||||
|
||||
$$
|
||||
\frac{n!}{k!(n-k)!} = \binom{n}{k}
|
||||
$$
|
||||
|
||||
<div class=""math"">
|
||||
\begin{align}
|
||||
\sqrt{37} & = \sqrt{\frac{73^2-1}{12^2}} \\
|
||||
& = \sqrt{\frac{73^2}{12^2}\cdot\frac{73^2-1}{73^2}} \\
|
||||
& = \sqrt{\frac{73^2}{12^2}}\sqrt{\frac{73^2-1}{73^2}} \\
|
||||
& = \frac{73}{12}\sqrt{1 - \frac{1}{73^2}} \\
|
||||
& \approx \frac{73}{12}\left(1 - \frac{1}{2\cdot73^2}\right)
|
||||
\end{align}
|
||||
</div>
|
||||
";
|
||||
Console.WriteLine("Math Expressions:\n");
|
||||
|
||||
var pl = new MarkdownPipelineBuilder().UseMathematics().Build(); // UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build()
|
||||
|
||||
|
||||
var html = Markdown.ToHtml(math, pl);
|
||||
Console.WriteLine(html);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InlineMathExpression()
|
||||
{
|
||||
string math = @"Math expressions
|
||||
|
||||
$\frac{n!}{k!(n-k)!} = \binom{n}{k}$
|
||||
";
|
||||
var pl = new MarkdownPipelineBuilder().UseMathematics().Build(); // UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build()
|
||||
|
||||
var html = Markdown.ToHtml(math, pl);
|
||||
Console.WriteLine(html);
|
||||
|
||||
Assert.IsTrue(html.Contains("<p><span class=\"math\">\\("), "Leading bracket missing");
|
||||
Assert.IsTrue(html.Contains("\\)</span></p>"), "Trailing bracket missing");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BlockMathExpression()
|
||||
{
|
||||
string math = @"Math expressions
|
||||
|
||||
$$
|
||||
\frac{n!}{k!(n-k)!} = \binom{n}{k}
|
||||
$$
|
||||
";
|
||||
var pl = new MarkdownPipelineBuilder().UseMathematics().Build(); // UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build()
|
||||
|
||||
var html = Markdown.ToHtml(math, pl);
|
||||
Console.WriteLine(html);
|
||||
|
||||
Assert.IsTrue(html.Contains("<div class=\"math\">\n\\["), "Leading bracket missing");
|
||||
Assert.IsTrue(html.Contains("\\]</div>"), "Trailing bracket missing");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanDisableParsingHeadings()
|
||||
{
|
||||
var noHeadingsPipeline = new MarkdownPipelineBuilder().DisableHeadings().Build();
|
||||
|
||||
TestParser.TestSpec("Foo\n===", "<h1>Foo</h1>");
|
||||
TestParser.TestSpec("Foo\n===", "<p>Foo\n===</p>", noHeadingsPipeline);
|
||||
|
||||
TestParser.TestSpec("# Heading 1", "<h1>Heading 1</h1>");
|
||||
TestParser.TestSpec("# Heading 1", "<p># Heading 1</p>", noHeadingsPipeline);
|
||||
|
||||
// Does not also disable link reference definitions
|
||||
TestParser.TestSpec("[Foo]\n\n[Foo]: bar", "<p><a href=\"bar\">Foo</a></p>");
|
||||
TestParser.TestSpec("[Foo]\n\n[Foo]: bar", "<p><a href=\"bar\">Foo</a></p>", noHeadingsPipeline);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanOpenAutoLinksInNewWindow()
|
||||
{
|
||||
var pipeline = new MarkdownPipelineBuilder().UseAutoLinks().Build();
|
||||
var newWindowPipeline = new MarkdownPipelineBuilder().UseAutoLinks(new AutoLinkOptions() { OpenInNewWindow = true }).Build();
|
||||
|
||||
TestParser.TestSpec("www.foo.bar", "<p><a href=\"http://www.foo.bar\">www.foo.bar</a></p>", pipeline);
|
||||
TestParser.TestSpec("www.foo.bar", "<p><a href=\"http://www.foo.bar\" target=\"blank\">www.foo.bar</a></p>", newWindowPipeline);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanUseHttpsPrefixForWWWAutoLinks()
|
||||
{
|
||||
var pipeline = new MarkdownPipelineBuilder().UseAutoLinks().Build();
|
||||
var httpsPipeline = new MarkdownPipelineBuilder().UseAutoLinks(new AutoLinkOptions() { UseHttpsForWWWLinks = true }).Build();
|
||||
|
||||
TestParser.TestSpec("www.foo.bar", "<p><a href=\"http://www.foo.bar\">www.foo.bar</a></p>", pipeline);
|
||||
TestParser.TestSpec("www.foo.bar", "<p><a href=\"https://www.foo.bar\">www.foo.bar</a></p>", httpsPipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Markdig.Extensions.AutoLinks;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
public class MiscTests
|
||||
{
|
||||
[Test]
|
||||
public void LinkWithInvalidNonAsciiDomainNameIsIgnored()
|
||||
{
|
||||
// Url from https://github.com/lunet-io/markdig/issues/438
|
||||
_ = Markdown.ToHtml("[minulém díle](http://V%20minulém%20díle%20jsme%20nainstalovali%20SQL%20Server,%20který%20je%20nutný%20pro%20běh%20Configuration%20Manageru.%20Dnes%20nás%20čeká%20instalace%20WSUS,%20což%20je%20produkt,%20jež%20je%20možné%20používat%20i%20jako%20samostatnou%20funkci%20ve%20Windows%20Serveru,%20který%20se%20stará%20o%20stažení%20a%20instalaci%20aktualizací%20z%20Microsoft%20Update%20na%20klientské%20počítače.%20Stejně%20jako%20v%20předchozích%20dílech,%20tak%20i%20v%20tomto%20si%20ukážeme%20obě%20varianty%20instalace%20–%20a%20to%20jak%20instalaci%20z%20PowerShellu,%20tak%20instalaci%20pomocí%20GUI.) ");
|
||||
|
||||
// Valid IDN
|
||||
TestParser.TestSpec("[foo](http://ünicode.com)", "<p><a href=\"http://xn--nicode-2ya.com\">foo</a></p>");
|
||||
TestParser.TestSpec("[foo](http://ünicode.ünicode.com)", "<p><a href=\"http://xn--nicode-2ya.xn--nicode-2ya.com\">foo</a></p>");
|
||||
|
||||
// Invalid IDN
|
||||
TestParser.TestSpec("[foo](http://ünicode..com)", "<p><a href=\"http://%C3%BCnicode..com\">foo</a></p>");
|
||||
}
|
||||
|
||||
[TestCase("link [foo [bar]]")] // https://spec.commonmark.org/0.29/#example-508
|
||||
[TestCase("link [foo][bar]")]
|
||||
[TestCase("link [][foo][bar][]")]
|
||||
[TestCase("link [][foo][bar][[]]")]
|
||||
[TestCase("link [foo] [bar]")]
|
||||
[TestCase("link [[foo] [] [bar] [[abc]def]]")]
|
||||
[TestCase("[]")]
|
||||
[TestCase("[ ]")]
|
||||
[TestCase("[bar][]")]
|
||||
[TestCase("[bar][ foo]")]
|
||||
[TestCase("[bar][foo ][]")]
|
||||
[TestCase("[bar][fo[ ]o ][][]")]
|
||||
[TestCase("[a]b[c[d[e]f]g]h")]
|
||||
[TestCase("a[b[c[d]e]f[g]h]i foo [j]k[l[m]n]o")]
|
||||
[TestCase("a[b[c[d]e]f[g]h]i[] [][foo][bar][] foo [j]k[l[m]n]o")]
|
||||
[TestCase("a[b[c[d]e]f[g]h]i foo [j]k[l[m]n]o[][]")]
|
||||
public void LinkTextMayContainBalancedBrackets(string linkText)
|
||||
{
|
||||
string markdown = $"[{linkText}](/uri)";
|
||||
string expected = $@"<p><a href=""/uri"">{linkText}</a></p>";
|
||||
|
||||
TestParser.TestSpec(markdown, expected);
|
||||
|
||||
// Make the link text unbalanced
|
||||
foreach (var bracketIndex in linkText
|
||||
.Select((c, i) => new Tuple<char, int>(c, i))
|
||||
.Where(t => t.Item1 == '[' || t.Item1 == ']')
|
||||
.Select(t => t.Item2))
|
||||
{
|
||||
string brokenLinkText = linkText.Remove(bracketIndex, 1);
|
||||
|
||||
markdown = $"[{brokenLinkText}](/uri)";
|
||||
expected = $@"<p><a href=""/uri"">{brokenLinkText}</a></p>";
|
||||
|
||||
string actual = Markdown.ToHtml(markdown);
|
||||
Assert.AreNotEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[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()
|
||||
{
|
||||
string input = @"https://foo.bar/path/\#m4mv5W0GYKZpGvfA.97";
|
||||
string expected = @"<p><a href=""https://foo.bar/path/%5C#m4mv5W0GYKZpGvfA.97"">https://foo.bar/path/\#m4mv5W0GYKZpGvfA.97</a></p>";
|
||||
|
||||
TestParser.TestSpec($"<{input}>", expected);
|
||||
TestParser.TestSpec(input, expected, "autolinks|advanced");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIssue365Corrected()
|
||||
{
|
||||
// The scheme must be escaped too...
|
||||
string input = "";
|
||||
string expected = "<p><img src=\"%22onclick=%22alert&#40;%27click%27&#41;%22://\" alt=\"image\" /></p>";
|
||||
|
||||
TestParser.TestSpec(input, expected);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAltTextIsCorrectlyEscaped()
|
||||
{
|
||||
TestParser.TestSpec(
|
||||
@"",
|
||||
@"<p><img src=""girl.png"" alt=""This is image alt text with quotation ' and double quotation "hello" world"" /></p>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangelogPRLinksMatchDescription()
|
||||
{
|
||||
string solutionFolder = Path.GetFullPath(Path.Combine(TestParser.TestsDirectory, "../.."));
|
||||
string changelogPath = Path.Combine(solutionFolder, "changelog.md");
|
||||
string changelog = File.ReadAllText(changelogPath);
|
||||
var matches = Regex.Matches(changelog, @"\(\[\(PR #(\d+)\)\]\(.*?pull\/(\d+)\)\)");
|
||||
Assert.Greater(matches.Count, 0);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
Assert.True(int.TryParse(match.Groups[1].Value, out int textNr));
|
||||
Assert.True(int.TryParse(match.Groups[2].Value, out int linkNr));
|
||||
Assert.AreEqual(textNr, linkNr);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFixHang()
|
||||
{
|
||||
var input = File.ReadAllText(Path.Combine(TestParser.TestsDirectory, "hang.md"));
|
||||
_ = Markdown.ToHtml(input);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidHtmlEntity()
|
||||
{
|
||||
var input = "9&ddr;&*&ddr;&de<64><65>__";
|
||||
TestParser.TestSpec(input, "<p>9&ddr;&*&ddr;&de<64><65>__</p>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidCharacterHandling()
|
||||
{
|
||||
var input = File.ReadAllText(Path.Combine(TestParser.TestsDirectory, "ArgumentOutOfRangeException.md"));
|
||||
_ = Markdown.ToHtml(input);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidCodeEscape()
|
||||
{
|
||||
var input = "```**Header** ";
|
||||
_ = Markdown.ToHtml(input);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmphasisAndHtmlEntity()
|
||||
{
|
||||
var markdownText = "*Unlimited-Fun®*®";
|
||||
TestParser.TestSpec(markdownText, "<p><em>Unlimited-Fun®</em>®</p>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestThematicInsideCodeBlockInsideList()
|
||||
{
|
||||
var input = @"1. In the :
|
||||
|
||||
```
|
||||
Id DisplayName Description
|
||||
-- ----------- -----------
|
||||
62375ab9-6b52-47ed-826b-58e47e0e304b Group.Unified ...
|
||||
```";
|
||||
TestParser.TestSpec(input, @"<ol>
|
||||
<li><p>In the :</p>
|
||||
<pre><code>Id DisplayName Description
|
||||
-- ----------- -----------
|
||||
62375ab9-6b52-47ed-826b-58e47e0e304b Group.Unified ...
|
||||
</code></pre></li>
|
||||
</ol>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VisualizeMathExpressions()
|
||||
{
|
||||
string math = @"Math expressions
|
||||
|
||||
$\frac{n!}{k!(n-k)!} = \binom{n}{k}$
|
||||
|
||||
$$\frac{n!}{k!(n-k)!} = \binom{n}{k}$$
|
||||
|
||||
$$
|
||||
\frac{n!}{k!(n-k)!} = \binom{n}{k}
|
||||
$$
|
||||
|
||||
<div class=""math"">
|
||||
\begin{align}
|
||||
\sqrt{37} & = \sqrt{\frac{73^2-1}{12^2}} \\
|
||||
& = \sqrt{\frac{73^2}{12^2}\cdot\frac{73^2-1}{73^2}} \\
|
||||
& = \sqrt{\frac{73^2}{12^2}}\sqrt{\frac{73^2-1}{73^2}} \\
|
||||
& = \frac{73}{12}\sqrt{1 - \frac{1}{73^2}} \\
|
||||
& \approx \frac{73}{12}\left(1 - \frac{1}{2\cdot73^2}\right)
|
||||
\end{align}
|
||||
</div>
|
||||
";
|
||||
Console.WriteLine("Math Expressions:\n");
|
||||
|
||||
var pl = new MarkdownPipelineBuilder().UseMathematics().Build(); // UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build()
|
||||
|
||||
|
||||
var html = Markdown.ToHtml(math, pl);
|
||||
Console.WriteLine(html);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InlineMathExpression()
|
||||
{
|
||||
string math = @"Math expressions
|
||||
|
||||
$\frac{n!}{k!(n-k)!} = \binom{n}{k}$
|
||||
";
|
||||
var pl = new MarkdownPipelineBuilder().UseMathematics().Build(); // UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build()
|
||||
|
||||
var html = Markdown.ToHtml(math, pl);
|
||||
Console.WriteLine(html);
|
||||
|
||||
Assert.IsTrue(html.Contains("<p><span class=\"math\">\\("), "Leading bracket missing");
|
||||
Assert.IsTrue(html.Contains("\\)</span></p>"), "Trailing bracket missing");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BlockMathExpression()
|
||||
{
|
||||
string math = @"Math expressions
|
||||
|
||||
$$
|
||||
\frac{n!}{k!(n-k)!} = \binom{n}{k}
|
||||
$$
|
||||
";
|
||||
var pl = new MarkdownPipelineBuilder().UseMathematics().Build(); // UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build()
|
||||
|
||||
var html = Markdown.ToHtml(math, pl);
|
||||
Console.WriteLine(html);
|
||||
|
||||
Assert.IsTrue(html.Contains("<div class=\"math\">\n\\["), "Leading bracket missing");
|
||||
Assert.IsTrue(html.Contains("\\]</div>"), "Trailing bracket missing");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanDisableParsingHeadings()
|
||||
{
|
||||
var noHeadingsPipeline = new MarkdownPipelineBuilder().DisableHeadings().Build();
|
||||
|
||||
TestParser.TestSpec("Foo\n===", "<h1>Foo</h1>");
|
||||
TestParser.TestSpec("Foo\n===", "<p>Foo\n===</p>", noHeadingsPipeline);
|
||||
|
||||
TestParser.TestSpec("# Heading 1", "<h1>Heading 1</h1>");
|
||||
TestParser.TestSpec("# Heading 1", "<p># Heading 1</p>", noHeadingsPipeline);
|
||||
|
||||
// Does not also disable link reference definitions
|
||||
TestParser.TestSpec("[Foo]\n\n[Foo]: bar", "<p><a href=\"bar\">Foo</a></p>");
|
||||
TestParser.TestSpec("[Foo]\n\n[Foo]: bar", "<p><a href=\"bar\">Foo</a></p>", noHeadingsPipeline);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanOpenAutoLinksInNewWindow()
|
||||
{
|
||||
var pipeline = new MarkdownPipelineBuilder().UseAutoLinks().Build();
|
||||
var newWindowPipeline = new MarkdownPipelineBuilder().UseAutoLinks(new AutoLinkOptions() { OpenInNewWindow = true }).Build();
|
||||
|
||||
TestParser.TestSpec("www.foo.bar", "<p><a href=\"http://www.foo.bar\">www.foo.bar</a></p>", pipeline);
|
||||
TestParser.TestSpec("www.foo.bar", "<p><a href=\"http://www.foo.bar\" target=\"blank\">www.foo.bar</a></p>", newWindowPipeline);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanUseHttpsPrefixForWWWAutoLinks()
|
||||
{
|
||||
var pipeline = new MarkdownPipelineBuilder().UseAutoLinks().Build();
|
||||
var httpsPipeline = new MarkdownPipelineBuilder().UseAutoLinks(new AutoLinkOptions() { UseHttpsForWWWLinks = true }).Build();
|
||||
|
||||
TestParser.TestSpec("www.foo.bar", "<p><a href=\"http://www.foo.bar\">www.foo.bar</a></p>", pipeline);
|
||||
TestParser.TestSpec("www.foo.bar", "<p><a href=\"https://www.foo.bar\">www.foo.bar</a></p>", httpsPipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Headings
|
||||
@@ -79,15 +78,15 @@ namespace Markdig.Tests.Specs.Normalize.Headings
|
||||
// Heading
|
||||
// =======
|
||||
//
|
||||
// Text after two newlines
|
||||
// Text after two newlines 1
|
||||
//
|
||||
// Should be rendered as:
|
||||
// # Heading
|
||||
//
|
||||
// Text after two newlines
|
||||
// Text after two newlines 1
|
||||
|
||||
Console.WriteLine("Example 3\nSection Headings\n");
|
||||
TestNormalize.TestSpec("Heading\n=======\n\nText after two newlines", "# Heading\n\nText after two newlines", "");
|
||||
TestNormalize.TestSpec("Heading\n=======\n\nText after two newlines 1", "# Heading\n\nText after two newlines 1", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Headings
|
||||
|
||||
# Headings
|
||||
|
||||
```````````````````````````````` example
|
||||
# Heading 1
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
##### Heading 5
|
||||
|
||||
###### Heading 6
|
||||
````````````````````````````````
|
||||
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
###### Heading
|
||||
|
||||
@@ -34,15 +34,15 @@ Text after two newlines
|
||||
###### Heading
|
||||
|
||||
Text after two newlines
|
||||
````````````````````````````````
|
||||
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
Heading
|
||||
=======
|
||||
|
||||
Text after two newlines
|
||||
Text after two newlines 1
|
||||
.
|
||||
# Heading
|
||||
|
||||
Text after two newlines
|
||||
Text after two newlines 1
|
||||
````````````````````````````````
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Sample
|
||||
|
||||
19
src/Markdig.Tests/Program.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
// 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;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Run NUnit tests runner with this");
|
||||
// Uncomment the following line to debug a specific tests more easily
|
||||
//var tests = new Specs.CommonMarkV_0_29.TestLeafBlocksSetextHeadings();
|
||||
//tests.LeafBlocksSetextHeadings_Example063();
|
||||
}
|
||||
}
|
||||
}
|
||||
15266
src/Markdig.Tests/RoundtripSpecs/CommonMark.generated.cs
Normal file
9710
src/Markdig.Tests/RoundtripSpecs/CommonMark.md
Normal file
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-05-15 02:46:55
|
||||
|
||||
// --------------------------------
|
||||
// Abbreviations
|
||||
|
||||
@@ -112,9 +112,9 @@ A
|
||||
The longest matching abbreviation should be used
|
||||
|
||||
```````````````````````````````` example
|
||||
*[Foo]: foo
|
||||
*[Foo Bar]: foobar
|
||||
|
||||
*[Foo]: foo
|
||||
*[Foo Bar]: foobar
|
||||
|
||||
Foo B
|
||||
.
|
||||
<p><abbr title="foo">Foo</abbr> B</p>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Auto Identifiers
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Auto Links
|
||||
@@ -23,6 +22,7 @@ namespace Markdig.Tests.Specs.AutoLinks
|
||||
// - `http://` or `https://`
|
||||
// - `ftp://`
|
||||
// - `mailto:`
|
||||
// - `tel:`
|
||||
// - `www.`
|
||||
[Test]
|
||||
public void ExtensionsAutoLinks_Example001()
|
||||
@@ -34,16 +34,18 @@ namespace Markdig.Tests.Specs.AutoLinks
|
||||
// This is a http://www.google.com URL and https://www.google.com
|
||||
// This is a ftp://test.com
|
||||
// And a mailto:email@toto.com
|
||||
// And a tel:+1555123456
|
||||
// And a plain www.google.com
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is a <a href="http://www.google.com">http://www.google.com</a> URL and <a href="https://www.google.com">https://www.google.com</a>
|
||||
// This is a <a href="ftp://test.com">ftp://test.com</a>
|
||||
// And a <a href="mailto:email@toto.com">email@toto.com</a>
|
||||
// And a <a href="tel:+1555123456">+1555123456</a>
|
||||
// And a plain <a href="http://www.google.com">www.google.com</a></p>
|
||||
|
||||
Console.WriteLine("Example 1\nSection Extensions / AutoLinks\n");
|
||||
TestParser.TestSpec("This is a http://www.google.com URL and https://www.google.com\nThis is a ftp://test.com\nAnd a mailto:email@toto.com\nAnd a plain www.google.com", "<p>This is a <a href=\"http://www.google.com\">http://www.google.com</a> URL and <a href=\"https://www.google.com\">https://www.google.com</a>\nThis is a <a href=\"ftp://test.com\">ftp://test.com</a>\nAnd a <a href=\"mailto:email@toto.com\">email@toto.com</a>\nAnd a plain <a href=\"http://www.google.com\">www.google.com</a></p>", "autolinks|advanced");
|
||||
TestParser.TestSpec("This is a http://www.google.com URL and https://www.google.com\nThis is a ftp://test.com\nAnd a mailto:email@toto.com\nAnd a tel:+1555123456\nAnd a plain www.google.com", "<p>This is a <a href=\"http://www.google.com\">http://www.google.com</a> URL and <a href=\"https://www.google.com\">https://www.google.com</a>\nThis is a <a href=\"ftp://test.com\">ftp://test.com</a>\nAnd a <a href=\"mailto:email@toto.com\">email@toto.com</a>\nAnd a <a href=\"tel:+1555123456\">+1555123456</a>\nAnd a plain <a href=\"http://www.google.com\">www.google.com</a></p>", "autolinks|advanced");
|
||||
}
|
||||
|
||||
// But incomplete links will not be matched:
|
||||
@@ -58,15 +60,17 @@ namespace Markdig.Tests.Specs.AutoLinks
|
||||
// This is not a ftp:/test.com
|
||||
// And not a mailto:emailtoto.com
|
||||
// And not a plain www. or a www.x
|
||||
// And not a tel:
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>This is not a http:/www.google.com URL and https:/www.google.com
|
||||
// This is not a ftp:/test.com
|
||||
// And not a mailto:emailtoto.com
|
||||
// And not a plain www. or a www.x</p>
|
||||
// And not a plain www. or a www.x
|
||||
// And not a tel:</p>
|
||||
|
||||
Console.WriteLine("Example 2\nSection Extensions / AutoLinks\n");
|
||||
TestParser.TestSpec("This is not a http:/www.google.com URL and https:/www.google.com\nThis is not a ftp:/test.com\nAnd not a mailto:emailtoto.com\nAnd not a plain www. or a www.x ", "<p>This is not a http:/www.google.com URL and https:/www.google.com\nThis is not a ftp:/test.com\nAnd not a mailto:emailtoto.com\nAnd not a plain www. or a www.x</p>", "autolinks|advanced");
|
||||
TestParser.TestSpec("This is not a http:/www.google.com URL and https:/www.google.com\nThis is not a ftp:/test.com\nAnd not a mailto:emailtoto.com\nAnd not a plain www. or a www.x \nAnd not a tel:", "<p>This is not a http:/www.google.com URL and https:/www.google.com\nThis is not a ftp:/test.com\nAnd not a mailto:emailtoto.com\nAnd not a plain www. or a www.x\nAnd not a tel:</p>", "autolinks|advanced");
|
||||
}
|
||||
|
||||
// Previous character must be a punctuation or a valid space (tab, space, new line):
|
||||
|
||||
@@ -9,17 +9,20 @@ Autolinks will format as a HTML link any string that starts by:
|
||||
- `http://` or `https://`
|
||||
- `ftp://`
|
||||
- `mailto:`
|
||||
- `tel:`
|
||||
- `www.`
|
||||
|
||||
```````````````````````````````` example
|
||||
This is a http://www.google.com URL and https://www.google.com
|
||||
This is a ftp://test.com
|
||||
And a mailto:email@toto.com
|
||||
And a tel:+1555123456
|
||||
And a plain www.google.com
|
||||
.
|
||||
<p>This is a <a href="http://www.google.com">http://www.google.com</a> URL and <a href="https://www.google.com">https://www.google.com</a>
|
||||
This is a <a href="ftp://test.com">ftp://test.com</a>
|
||||
And a <a href="mailto:email@toto.com">email@toto.com</a>
|
||||
And a <a href="tel:+1555123456">+1555123456</a>
|
||||
And a plain <a href="http://www.google.com">www.google.com</a></p>
|
||||
````````````````````````````````
|
||||
|
||||
@@ -30,11 +33,13 @@ This is not a http:/www.google.com URL and https:/www.google.com
|
||||
This is not a ftp:/test.com
|
||||
And not a mailto:emailtoto.com
|
||||
And not a plain www. or a www.x
|
||||
And not a tel:
|
||||
.
|
||||
<p>This is not a http:/www.google.com URL and https:/www.google.com
|
||||
This is not a ftp:/test.com
|
||||
And not a mailto:emailtoto.com
|
||||
And not a plain www. or a www.x</p>
|
||||
And not a plain www. or a www.x
|
||||
And not a tel:</p>
|
||||
````````````````````````````````
|
||||
|
||||
Previous character must be a punctuation or a valid space (tab, space, new line):
|
||||
@@ -245,18 +250,18 @@ https://github.com:443
|
||||
|
||||
Links with unicode characters in the path / query / fragment are matched and url encoded
|
||||
|
||||
```````````````````````````````` example
|
||||
http://abc.net/☃
|
||||
|
||||
http://abc.net?☃
|
||||
|
||||
http://abc.net#☃
|
||||
|
||||
```````````````````````````````` example
|
||||
http://abc.net/☃
|
||||
|
||||
http://abc.net?☃
|
||||
|
||||
http://abc.net#☃
|
||||
|
||||
http://abc.net/foo#☃
|
||||
.
|
||||
<p><a href="http://abc.net/%E2%98%83">http://abc.net/☃</a></p>
|
||||
<p><a href="http://abc.net?%E2%98%83">http://abc.net?☃</a></p>
|
||||
<p><a href="http://abc.net#%E2%98%83">http://abc.net#☃</a></p>
|
||||
.
|
||||
<p><a href="http://abc.net/%E2%98%83">http://abc.net/☃</a></p>
|
||||
<p><a href="http://abc.net?%E2%98%83">http://abc.net?☃</a></p>
|
||||
<p><a href="http://abc.net#%E2%98%83">http://abc.net#☃</a></p>
|
||||
<p><a href="http://abc.net/foo#%E2%98%83">http://abc.net/foo#☃</a></p>
|
||||
````````````````````````````````
|
||||
|
||||
@@ -270,18 +275,18 @@ http://☃.net?☃
|
||||
|
||||
Same goes for regular autolinks
|
||||
|
||||
```````````````````````````````` example
|
||||
<http://abc.net/☃>
|
||||
|
||||
<http://abc.net?☃>
|
||||
|
||||
<http://abc.net#☃>
|
||||
|
||||
```````````````````````````````` example
|
||||
<http://abc.net/☃>
|
||||
|
||||
<http://abc.net?☃>
|
||||
|
||||
<http://abc.net#☃>
|
||||
|
||||
<http://abc.net/foo#☃>
|
||||
.
|
||||
<p><a href="http://abc.net/%E2%98%83">http://abc.net/☃</a></p>
|
||||
<p><a href="http://abc.net?%E2%98%83">http://abc.net?☃</a></p>
|
||||
<p><a href="http://abc.net#%E2%98%83">http://abc.net#☃</a></p>
|
||||
.
|
||||
<p><a href="http://abc.net/%E2%98%83">http://abc.net/☃</a></p>
|
||||
<p><a href="http://abc.net?%E2%98%83">http://abc.net?☃</a></p>
|
||||
<p><a href="http://abc.net#%E2%98%83">http://abc.net#☃</a></p>
|
||||
<p><a href="http://abc.net/foo#%E2%98%83">http://abc.net/foo#☃</a></p>
|
||||
````````````````````````````````
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-15 05:23:49
|
||||
|
||||
// --------------------------------
|
||||
// Bootstrap
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-12 15:26:42
|
||||
|
||||
// --------------------------------
|
||||
// CommonMark v. 0.29
|
||||
@@ -14925,6 +14924,29 @@ namespace Markdig.Tests.Specs.CommonMarkV_0_29
|
||||
Console.WriteLine("Example 649\nSection Inlines / Textual content\n");
|
||||
TestParser.TestSpec("Multiple spaces", "<p>Multiple spaces</p>", "");
|
||||
}
|
||||
|
||||
// Within a blockquote a setext heading takes precedence
|
||||
// over a thematic break:
|
||||
[Test]
|
||||
public void InlinesTextualContent_Example650()
|
||||
{
|
||||
// Example 650
|
||||
// Section: Inlines / Textual content
|
||||
//
|
||||
// The following Markdown:
|
||||
// > Foo
|
||||
// > ---
|
||||
// > bar
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <blockquote>
|
||||
// <h2>Foo</h2>
|
||||
// <p>bar</p>
|
||||
// </blockquote>
|
||||
|
||||
Console.WriteLine("Example 650\nSection Inlines / Textual content\n");
|
||||
TestParser.TestSpec("> Foo\n> ---\n> bar", "<blockquote>\n<h2>Foo</h2>\n<p>bar</p>\n</blockquote>", "");
|
||||
}
|
||||
// <!-- END TESTS -->
|
||||
//
|
||||
// # Appendix: A parsing strategy
|
||||
|
||||
@@ -9368,6 +9368,20 @@ Multiple spaces
|
||||
<p>Multiple spaces</p>
|
||||
````````````````````````````````
|
||||
|
||||
Within a blockquote a setext heading takes precedence
|
||||
over a thematic break:
|
||||
|
||||
```````````````````````````````` example
|
||||
> Foo
|
||||
> ---
|
||||
> bar
|
||||
.
|
||||
<blockquote>
|
||||
<h2>Foo</h2>
|
||||
<p>bar</p>
|
||||
</blockquote>
|
||||
````````````````````````````````
|
||||
|
||||
|
||||
<!-- END TESTS -->
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Custom Containers
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-15 05:06:35
|
||||
|
||||
// --------------------------------
|
||||
// Definition Lists
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Diagrams
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2020-01-13 21:08:58
|
||||
|
||||
// --------------------------------
|
||||
// Emoji
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Emphasis Extra
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Figures, Footers and Cites
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-15 05:33:49
|
||||
|
||||
// --------------------------------
|
||||
// Footnotes
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-08-01 13:57:17
|
||||
|
||||
// --------------------------------
|
||||
// Generic Attributes
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-15 05:25:26
|
||||
|
||||
// --------------------------------
|
||||
// Globalization
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2020-04-18 06:41:26
|
||||
|
||||
// --------------------------------
|
||||
// Grid Tables
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Hardline Breaks
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-15 05:30:00
|
||||
|
||||
// --------------------------------
|
||||
// Jira Links
|
||||
@@ -24,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.
|
||||
@@ -54,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]
|
||||
@@ -70,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()
|
||||
{
|
||||
@@ -87,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]
|
||||
@@ -103,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()
|
||||
{
|
||||
@@ -119,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()
|
||||
{
|
||||
@@ -136,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]
|
||||
@@ -152,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]
|
||||
@@ -168,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,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// List Extras
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Math
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-05-15 02:46:20
|
||||
|
||||
// --------------------------------
|
||||
// Media
|
||||
@@ -17,7 +16,7 @@ namespace Markdig.Tests.Specs.Media
|
||||
// Adds support for media links:
|
||||
//
|
||||
// ## Media links
|
||||
//
|
||||
//
|
||||
// Allows to embed audio/video links to popular website:
|
||||
[Test]
|
||||
public void ExtensionsMediaLinks_Example001()
|
||||
@@ -35,7 +34,7 @@ namespace Markdig.Tests.Specs.Media
|
||||
// 
|
||||
//
|
||||
// 
|
||||
//
|
||||
//
|
||||
// 
|
||||
//
|
||||
// 
|
||||
@@ -47,19 +46,19 @@ namespace Markdig.Tests.Specs.Media
|
||||
// 
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://player.vimeo.com/video/8607834" width="500" height="281" class="vimeo" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://player.vimeo.com/video/8607834" class="vimeo" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><video width="500" height="281" controls=""><source type="video/mp4" src="https://sample.com/video.mp4"></source></video></p>
|
||||
// <p><iframe src="https://music.yandex.ru/iframe/#track/4402274/411845/" width="500" height="281" class="yandex" frameborder="0"></iframe></p>
|
||||
// <p><iframe src="https://ok.ru/videoembed/26870090463" width="500" height="281" class="odnoklassniki" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
// <p><iframe src="https://music.yandex.ru/iframe/#track/4402274/411845/" class="yandex" width="500" height="281" frameborder="0"></iframe></p>
|
||||
// <p><iframe src="https://ok.ru/videoembed/26870090463" class="odnoklassniki" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
|
||||
Console.WriteLine("Example 1\nSection Extensions / Media links\n");
|
||||
TestParser.TestSpec("\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ?start=100\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ?start=100\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://player.vimeo.com/video/8607834\" width=\"500\" height=\"281\" class=\"vimeo\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"https://sample.com/video.mp4\"></source></video></p>\n<p><iframe src=\"https://music.yandex.ru/iframe/#track/4402274/411845/\" width=\"500\" height=\"281\" class=\"yandex\" frameborder=\"0\"></iframe></p>\n<p><iframe src=\"https://ok.ru/videoembed/26870090463\" width=\"500\" height=\"281\" class=\"odnoklassniki\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>", "medialinks|advanced+medialinks");
|
||||
TestParser.TestSpec("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ?start=100\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ?start=100\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://player.vimeo.com/video/8607834\" class=\"vimeo\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"https://sample.com/video.mp4\"></source></video></p>\n<p><iframe src=\"https://music.yandex.ru/iframe/#track/4402274/411845/\" class=\"yandex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n<p><iframe src=\"https://ok.ru/videoembed/26870090463\" class=\"odnoklassniki\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>", "medialinks|advanced+medialinks");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Adds support for media links:
|
||||
|
||||
## Media links
|
||||
|
||||
|
||||
Allows to embed audio/video links to popular website:
|
||||
|
||||
```````````````````````````````` example
|
||||
@@ -16,7 +16,7 @@ Allows to embed audio/video links to popular website:
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||

|
||||
@@ -27,14 +27,14 @@ Allows to embed audio/video links to popular website:
|
||||
|
||||

|
||||
.
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://player.vimeo.com/video/8607834" width="500" height="281" class="vimeo" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://player.vimeo.com/video/8607834" class="vimeo" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><video width="500" height="281" controls=""><source type="video/mp4" src="https://sample.com/video.mp4"></source></video></p>
|
||||
<p><iframe src="https://music.yandex.ru/iframe/#track/4402274/411845/" width="500" height="281" class="yandex" frameborder="0"></iframe></p>
|
||||
<p><iframe src="https://ok.ru/videoembed/26870090463" width="500" height="281" class="odnoklassniki" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
<p><iframe src="https://music.yandex.ru/iframe/#track/4402274/411845/" class="yandex" width="500" height="281" frameborder="0"></iframe></p>
|
||||
<p><iframe src="https://ok.ru/videoembed/26870090463" class="odnoklassniki" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
|
||||
````````````````````````````````
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// No Html
|
||||
|
||||
856
src/Markdig.Tests/Specs/PipeTableGfmSpecs.generated.cs
Normal file
@@ -0,0 +1,856 @@
|
||||
|
||||
// --------------------------------
|
||||
// GFM Pipe Tables
|
||||
// --------------------------------
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests.Specs.GFMPipeTables
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestExtensionsGfmPipeTable
|
||||
{
|
||||
// # Extensions
|
||||
//
|
||||
// This section describes the different extensions supported:
|
||||
//
|
||||
// ## Gfm Pipe Table
|
||||
//
|
||||
// This groups a certain set of behaviors that makes pipe tables adhere more strictly to the GitHub-flavored Markdown specification.
|
||||
//
|
||||
// A pipe table is detected when:
|
||||
//
|
||||
// **Rule #1**
|
||||
// - Each line of a paragraph block have to contain at least a **column delimiter** `|` that is not embedded by either a code inline (backtick \`) or a HTML inline.
|
||||
// - The second row must separate the first header row from sub-sequent rows by containing a **header column separator** for each column separated by a column delimiter. A header column separator is:
|
||||
// - starting by optional spaces
|
||||
// - followed by an optional `:` to specify left align
|
||||
// - followed by a sequence of at least one `-` character
|
||||
// - followed by an optional `:` to specify right align (or center align if left align is also defined)
|
||||
// - ending by optional spaces
|
||||
//
|
||||
// Because a list has a higher precedence than a pipe table, a table header row separator requires at least 2 dashes `--` to start a header row:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example001()
|
||||
{
|
||||
// Example 1
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -- | -
|
||||
// 0 | 1
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 1\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b\n-- | -\n0 | 1", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// The following is also considered as a table, even if the second line starts like a list:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example002()
|
||||
{
|
||||
// Example 2
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// - | -
|
||||
// 0 | 1
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 2\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b\n- | -\n0 | 1", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// A pipe table with only one header row is allowed:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example003()
|
||||
{
|
||||
// Example 3
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -- | --
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 3\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b\n-- | --", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// After a row separator header, they will be interpreted as plain column:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example004()
|
||||
{
|
||||
// Example 4
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -- | --
|
||||
// -- | --
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>--</td>
|
||||
// <td>--</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 4\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b\n-- | --\n-- | --", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>--</td>\n<td>--</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// But if a table doesn't start with a column delimiter, it is not interpreted as a table, even if following lines have a column delimiter
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example005()
|
||||
{
|
||||
// Example 5
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a b
|
||||
// c | d
|
||||
// e | f
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>a b
|
||||
// c | d
|
||||
// e | f</p>
|
||||
|
||||
Console.WriteLine("Example 5\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a b\nc | d\ne | f", "<p>a b\nc | d\ne | f</p>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// If a line doesn't have a column delimiter `|` the table is not detected
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example006()
|
||||
{
|
||||
// Example 6
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// c no d
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>a | b
|
||||
// c no d</p>
|
||||
|
||||
Console.WriteLine("Example 6\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b\nc no d", "<p>a | b\nc no d</p>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// If a row contains more columns than the header row, the extra columns will be ignored:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example007()
|
||||
{
|
||||
// Example 7
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -- | --
|
||||
// 0 | 1 | 2
|
||||
// 3 | 4
|
||||
// 5 |
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>3</td>
|
||||
// <td>4</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>5</td>
|
||||
// <td></td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 7\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b \n-- | --\n0 | 1 | 2\n3 | 4\n5 |", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n<tr>\n<td>3</td>\n<td>4</td>\n</tr>\n<tr>\n<td>5</td>\n<td></td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Rule #2**
|
||||
// A pipe table ends after a blank line or the end of the file.
|
||||
//
|
||||
// **Rule #3**
|
||||
// A cell content is trimmed (start and end) from white-spaces.
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example008()
|
||||
{
|
||||
// Example 8
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b |
|
||||
// -- | --
|
||||
// 0 | 1 |
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 8\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b |\n-- | --\n0 | 1 |", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Rule #4**
|
||||
// Column delimiters `|` at the very beginning of a line or just before a line ending with only spaces and/or terminated by a newline can be omitted
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example009()
|
||||
{
|
||||
// Example 9
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b |
|
||||
// -- | --
|
||||
// | 0 | 1
|
||||
// | 2 | 3 |
|
||||
// 4 | 5
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>2</td>
|
||||
// <td>3</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>4</td>
|
||||
// <td>5</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 9\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec(" a | b |\n-- | --\n| 0 | 1\n| 2 | 3 |\n 4 | 5 ", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n<tr>\n<td>2</td>\n<td>3</td>\n</tr>\n<tr>\n<td>4</td>\n<td>5</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// A pipe may be present at both the beginning/ending of each line:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example010()
|
||||
{
|
||||
// Example 10
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// |a|b|
|
||||
// |-|-|
|
||||
// |0|1|
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 10\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("|a|b|\n|-|-|\n|0|1|", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// Or may be omitted on one side:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example011()
|
||||
{
|
||||
// Example 11
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a|b|
|
||||
// -|-|
|
||||
// 0|1|
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 11\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a|b|\n-|-|\n0|1|", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example012()
|
||||
{
|
||||
// Example 12
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// |a|b
|
||||
// |-|-
|
||||
// |0|1
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 12\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("|a|b\n|-|-\n|0|1", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// Single column table can be declared with lines starting only by a column delimiter:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example013()
|
||||
{
|
||||
// Example 13
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// | a
|
||||
// | --
|
||||
// | b
|
||||
// | c
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>b</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>c</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 13\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("| a\n| --\n| b\n| c ", "<table>\n<thead>\n<tr>\n<th>a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>b</td>\n</tr>\n<tr>\n<td>c</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Rule #5**
|
||||
//
|
||||
// The first row is considered as a **header row** if it is separated from the regular rows by a row containing a **header column separator** for each column. A header column separator is:
|
||||
//
|
||||
// - starting by optional spaces
|
||||
// - followed by an optional `:` to specify left align
|
||||
// - followed by a sequence of at least one `-` character
|
||||
// - followed by an optional `:` to specify right align (or center align if left align is also defined)
|
||||
// - ending by optional spaces
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example014()
|
||||
{
|
||||
// Example 14
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -------|-------
|
||||
// 0 | 1
|
||||
// 2 | 3
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>2</td>
|
||||
// <td>3</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 14\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec(" a | b \n-------|-------\n 0 | 1 \n 2 | 3 ", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n<tr>\n<td>2</td>\n<td>3</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// The text alignment is defined by default to be center for header and left for cells. If the left alignment is applied, it will force the column heading to be left aligned.
|
||||
// There is no way to define a different alignment for heading and cells (apart from the default).
|
||||
// The text alignment can be changed by using the character `:` with the header column separator:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example015()
|
||||
{
|
||||
// Example 15
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b | c
|
||||
// :------|:-------:| ----:
|
||||
// 0 | 1 | 2
|
||||
// 3 | 4 | 5
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th style="text-align: left;">a</th>
|
||||
// <th style="text-align: center;">b</th>
|
||||
// <th style="text-align: right;">c</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td style="text-align: left;">0</td>
|
||||
// <td style="text-align: center;">1</td>
|
||||
// <td style="text-align: right;">2</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td style="text-align: left;">3</td>
|
||||
// <td style="text-align: center;">4</td>
|
||||
// <td style="text-align: right;">5</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 15\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec(" a | b | c \n:------|:-------:| ----:\n 0 | 1 | 2 \n 3 | 4 | 5 ", "<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">a</th>\n<th style=\"text-align: center;\">b</th>\n<th style=\"text-align: right;\">c</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\">0</td>\n<td style=\"text-align: center;\">1</td>\n<td style=\"text-align: right;\">2</td>\n</tr>\n<tr>\n<td style=\"text-align: left;\">3</td>\n<td style=\"text-align: center;\">4</td>\n<td style=\"text-align: right;\">5</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// Test alignment with starting and ending pipes:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example016()
|
||||
{
|
||||
// Example 16
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// | abc | def | ghi |
|
||||
// |:---:|-----|----:|
|
||||
// | 1 | 2 | 3 |
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th style="text-align: center;">abc</th>
|
||||
// <th>def</th>
|
||||
// <th style="text-align: right;">ghi</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td style="text-align: center;">1</td>
|
||||
// <td>2</td>
|
||||
// <td style="text-align: right;">3</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 16\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("| abc | def | ghi |\n|:---:|-----|----:|\n| 1 | 2 | 3 |", "<table>\n<thead>\n<tr>\n<th style=\"text-align: center;\">abc</th>\n<th>def</th>\n<th style=\"text-align: right;\">ghi</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align: center;\">1</td>\n<td>2</td>\n<td style=\"text-align: right;\">3</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// The following example shows a non matching header column separator:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example017()
|
||||
{
|
||||
// Example 17
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -------|---x---
|
||||
// 0 | 1
|
||||
// 2 | 3
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>a | b
|
||||
// -------|---x---
|
||||
// 0 | 1
|
||||
// 2 | 3</p>
|
||||
|
||||
Console.WriteLine("Example 17\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec(" a | b\n-------|---x---\n 0 | 1\n 2 | 3 ", "<p>a | b\n-------|---x---\n0 | 1\n2 | 3</p> ", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Rule #6**
|
||||
//
|
||||
// A column delimiter has a higher priority than emphasis delimiter
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example018()
|
||||
{
|
||||
// Example 18
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// *a* | b
|
||||
// ----- |-----
|
||||
// 0 | _1_
|
||||
// _2 | 3*
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th><em>a</em></th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td><em>1</em></td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>_2</td>
|
||||
// <td>3*</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 18\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec(" *a* | b\n----- |-----\n 0 | _1_\n _2 | 3* ", "<table>\n<thead>\n<tr>\n<th><em>a</em></th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td><em>1</em></td>\n</tr>\n<tr>\n<td>_2</td>\n<td>3*</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Rule #7**
|
||||
//
|
||||
// A backtick/code delimiter has a higher precedence than a column delimiter `|`:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example019()
|
||||
{
|
||||
// Example 19
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b `
|
||||
// 0 | `
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <p>a | b <code>0 |</code></p>
|
||||
|
||||
Console.WriteLine("Example 19\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b `\n0 | ` ", "<p>a | b <code>0 |</code></p> ", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Rule #8**
|
||||
//
|
||||
// A HTML inline has a higher precedence than a column delimiter `|`:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example020()
|
||||
{
|
||||
// Example 20
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a <a href="" title="|"></a> | b
|
||||
// -- | --
|
||||
// 0 | 1
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a <a href="" title="|"></a></th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 20\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a <a href=\"\" title=\"|\"></a> | b\n-- | --\n0 | 1", "<table>\n<thead>\n<tr>\n<th>a <a href=\"\" title=\"|\"></a></th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Rule #9**
|
||||
//
|
||||
// Links have a higher precedence than the column delimiter character `|`:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example021()
|
||||
{
|
||||
// Example 21
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -- | --
|
||||
// [This is a link with a | inside the label](http://google.com) | 1
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td><a href="http://google.com">This is a link with a | inside the label</a></td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 21\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b\n-- | --\n[This is a link with a | inside the label](http://google.com) | 1", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a href=\"http://google.com\">This is a link with a | inside the label</a></td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Rule #10**
|
||||
//
|
||||
// It is possible to have a single row header only:
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example022()
|
||||
{
|
||||
// Example 22
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -- | --
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 22\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b\n-- | --", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example023()
|
||||
{
|
||||
// Example 23
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// |a|b|c
|
||||
// |---|---|---|
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// <th>c</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 23\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("|a|b|c\n|---|---|---|", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Tests**
|
||||
//
|
||||
// Tests trailing spaces after pipes
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example024()
|
||||
{
|
||||
// Example 24
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// | abc | def |
|
||||
// |---|---|
|
||||
// | cde| ddd|
|
||||
// | eee| fff|
|
||||
// | fff | fffff |
|
||||
// |gggg | ffff |
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>abc</th>
|
||||
// <th>def</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>cde</td>
|
||||
// <td>ddd</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>eee</td>
|
||||
// <td>fff</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>fff</td>
|
||||
// <td>fffff</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>gggg</td>
|
||||
// <td>ffff</td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 24\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("| abc | def | \n|---|---|\n| cde| ddd| \n| eee| fff|\n| fff | fffff | \n|gggg | ffff | ", "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>cde</td>\n<td>ddd</td>\n</tr>\n<tr>\n<td>eee</td>\n<td>fff</td>\n</tr>\n<tr>\n<td>fff</td>\n<td>fffff</td>\n</tr>\n<tr>\n<td>gggg</td>\n<td>ffff</td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
|
||||
// **Normalized columns count**
|
||||
//
|
||||
// The tables are normalized to the number of columns found in the table header.
|
||||
// Extra columns will be ignored, missing columns will be inserted.
|
||||
[Test]
|
||||
public void ExtensionsGfmPipeTable_Example025()
|
||||
{
|
||||
// Example 25
|
||||
// Section: Extensions / Gfm Pipe Table
|
||||
//
|
||||
// The following Markdown:
|
||||
// a | b
|
||||
// -- | -
|
||||
// 0 | 1 | 2
|
||||
// 3 |
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <table>
|
||||
// <thead>
|
||||
// <tr>
|
||||
// <th>a</th>
|
||||
// <th>b</th>
|
||||
// </tr>
|
||||
// </thead>
|
||||
// <tbody>
|
||||
// <tr>
|
||||
// <td>0</td>
|
||||
// <td>1</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>3</td>
|
||||
// <td></td>
|
||||
// </tr>
|
||||
// </tbody>
|
||||
// </table>
|
||||
|
||||
Console.WriteLine("Example 25\nSection Extensions / Gfm Pipe Table\n");
|
||||
TestParser.TestSpec("a | b\n-- | - \n0 | 1 | 2\n3 |", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n<tr>\n<td>3</td>\n<td></td>\n</tr>\n</tbody>\n</table>", "gfm-pipetables");
|
||||
}
|
||||
}
|
||||
}
|
||||
617
src/Markdig.Tests/Specs/PipeTableGfmSpecs.md
Normal file
@@ -0,0 +1,617 @@
|
||||
# Extensions
|
||||
|
||||
This section describes the different extensions supported:
|
||||
|
||||
## Gfm Pipe Table
|
||||
|
||||
This groups a certain set of behaviors that makes pipe tables adhere more strictly to the GitHub-flavored Markdown specification.
|
||||
|
||||
A pipe table is detected when:
|
||||
|
||||
**Rule #1**
|
||||
- Each line of a paragraph block have to contain at least a **column delimiter** `|` that is not embedded by either a code inline (backtick \`) or a HTML inline.
|
||||
- The second row must separate the first header row from sub-sequent rows by containing a **header column separator** for each column separated by a column delimiter. A header column separator is:
|
||||
- starting by optional spaces
|
||||
- followed by an optional `:` to specify left align
|
||||
- followed by a sequence of at least one `-` character
|
||||
- followed by an optional `:` to specify right align (or center align if left align is also defined)
|
||||
- ending by optional spaces
|
||||
|
||||
Because a list has a higher precedence than a pipe table, a table header row separator requires at least 2 dashes `--` to start a header row:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-- | -
|
||||
0 | 1
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
The following is also considered as a table, even if the second line starts like a list:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
- | -
|
||||
0 | 1
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
A pipe table with only one header row is allowed:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-- | --
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
After a row separator header, they will be interpreted as plain column:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-- | --
|
||||
-- | --
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>--</td>
|
||||
<td>--</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
But if a table doesn't start with a column delimiter, it is not interpreted as a table, even if following lines have a column delimiter
|
||||
|
||||
```````````````````````````````` example
|
||||
a b
|
||||
c | d
|
||||
e | f
|
||||
.
|
||||
<p>a b
|
||||
c | d
|
||||
e | f</p>
|
||||
````````````````````````````````
|
||||
|
||||
If a line doesn't have a column delimiter `|` the table is not detected
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
c no d
|
||||
.
|
||||
<p>a | b
|
||||
c no d</p>
|
||||
````````````````````````````````
|
||||
|
||||
If a row contains more columns than the header row, the extra columns will be ignored:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-- | --
|
||||
0 | 1 | 2
|
||||
3 | 4
|
||||
5 |
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #2**
|
||||
A pipe table ends after a blank line or the end of the file.
|
||||
|
||||
**Rule #3**
|
||||
A cell content is trimmed (start and end) from white-spaces.
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b |
|
||||
-- | --
|
||||
0 | 1 |
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #4**
|
||||
Column delimiters `|` at the very beginning of a line or just before a line ending with only spaces and/or terminated by a newline can be omitted
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b |
|
||||
-- | --
|
||||
| 0 | 1
|
||||
| 2 | 3 |
|
||||
4 | 5
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
A pipe may be present at both the beginning/ending of each line:
|
||||
|
||||
```````````````````````````````` example
|
||||
|a|b|
|
||||
|-|-|
|
||||
|0|1|
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
Or may be omitted on one side:
|
||||
|
||||
```````````````````````````````` example
|
||||
a|b|
|
||||
-|-|
|
||||
0|1|
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
|a|b
|
||||
|-|-
|
||||
|0|1
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
|
||||
|
||||
Single column table can be declared with lines starting only by a column delimiter:
|
||||
|
||||
```````````````````````````````` example
|
||||
| a
|
||||
| --
|
||||
| b
|
||||
| c
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>b</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>c</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #5**
|
||||
|
||||
The first row is considered as a **header row** if it is separated from the regular rows by a row containing a **header column separator** for each column. A header column separator is:
|
||||
|
||||
- starting by optional spaces
|
||||
- followed by an optional `:` to specify left align
|
||||
- followed by a sequence of at least one `-` character
|
||||
- followed by an optional `:` to specify right align (or center align if left align is also defined)
|
||||
- ending by optional spaces
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-------|-------
|
||||
0 | 1
|
||||
2 | 3
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
The text alignment is defined by default to be center for header and left for cells. If the left alignment is applied, it will force the column heading to be left aligned.
|
||||
There is no way to define a different alignment for heading and cells (apart from the default).
|
||||
The text alignment can be changed by using the character `:` with the header column separator:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b | c
|
||||
:------|:-------:| ----:
|
||||
0 | 1 | 2
|
||||
3 | 4 | 5
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: left;">a</th>
|
||||
<th style="text-align: center;">b</th>
|
||||
<th style="text-align: right;">c</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: left;">0</td>
|
||||
<td style="text-align: center;">1</td>
|
||||
<td style="text-align: right;">2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: left;">3</td>
|
||||
<td style="text-align: center;">4</td>
|
||||
<td style="text-align: right;">5</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
Test alignment with starting and ending pipes:
|
||||
|
||||
```````````````````````````````` example
|
||||
| abc | def | ghi |
|
||||
|:---:|-----|----:|
|
||||
| 1 | 2 | 3 |
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center;">abc</th>
|
||||
<th>def</th>
|
||||
<th style="text-align: right;">ghi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;">1</td>
|
||||
<td>2</td>
|
||||
<td style="text-align: right;">3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
The following example shows a non matching header column separator:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-------|---x---
|
||||
0 | 1
|
||||
2 | 3
|
||||
.
|
||||
<p>a | b
|
||||
-------|---x---
|
||||
0 | 1
|
||||
2 | 3</p>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #6**
|
||||
|
||||
A column delimiter has a higher priority than emphasis delimiter
|
||||
|
||||
```````````````````````````````` example
|
||||
*a* | b
|
||||
----- |-----
|
||||
0 | _1_
|
||||
_2 | 3*
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><em>a</em></th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td><em>1</em></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>_2</td>
|
||||
<td>3*</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #7**
|
||||
|
||||
A backtick/code delimiter has a higher precedence than a column delimiter `|`:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b `
|
||||
0 | `
|
||||
.
|
||||
<p>a | b <code>0 |</code></p>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #8**
|
||||
|
||||
A HTML inline has a higher precedence than a column delimiter `|`:
|
||||
|
||||
```````````````````````````````` example
|
||||
a <a href="" title="|"></a> | b
|
||||
-- | --
|
||||
0 | 1
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a <a href="" title="|"></a></th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #9**
|
||||
|
||||
Links have a higher precedence than the column delimiter character `|`:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-- | --
|
||||
[This is a link with a | inside the label](http://google.com) | 1
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="http://google.com">This is a link with a | inside the label</a></td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #10**
|
||||
|
||||
It is possible to have a single row header only:
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-- | --
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example
|
||||
|a|b|c
|
||||
|---|---|---|
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
<th>c</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Tests**
|
||||
|
||||
Tests trailing spaces after pipes
|
||||
|
||||
```````````````````````````````` example
|
||||
| abc | def |
|
||||
|---|---|
|
||||
| cde| ddd|
|
||||
| eee| fff|
|
||||
| fff | fffff |
|
||||
|gggg | ffff |
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>abc</th>
|
||||
<th>def</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>cde</td>
|
||||
<td>ddd</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>eee</td>
|
||||
<td>fff</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>fff</td>
|
||||
<td>fffff</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>gggg</td>
|
||||
<td>ffff</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Normalized columns count**
|
||||
|
||||
The tables are normalized to the number of columns found in the table header.
|
||||
Extra columns will be ignored, missing columns will be inserted.
|
||||
|
||||
|
||||
```````````````````````````````` example
|
||||
a | b
|
||||
-- | -
|
||||
0 | 1 | 2
|
||||
3 |
|
||||
.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>a</th>
|
||||
<th>b</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
````````````````````````````````
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-15 05:54:35
|
||||
|
||||
// --------------------------------
|
||||
// Pipe Tables
|
||||
@@ -647,7 +646,7 @@ namespace Markdig.Tests.Specs.PipeTables
|
||||
TestParser.TestSpec("a | b `\n0 | ` ", "<p>a | b <code>0 |</code></p> ", "pipetables|advanced");
|
||||
}
|
||||
|
||||
// **Rule #7**
|
||||
// **Rule #8**
|
||||
//
|
||||
// A HTML inline has a higher precedence than a column delimiter `|`:
|
||||
[Test]
|
||||
@@ -681,7 +680,7 @@ namespace Markdig.Tests.Specs.PipeTables
|
||||
TestParser.TestSpec("a <a href=\"\" title=\"|\"></a> | b\n-- | --\n0 | 1", "<table>\n<thead>\n<tr>\n<th>a <a href=\"\" title=\"|\"></a></th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
|
||||
}
|
||||
|
||||
// **Rule #8**
|
||||
// **Rule #9**
|
||||
//
|
||||
// Links have a higher precedence than the column delimiter character `|`:
|
||||
[Test]
|
||||
@@ -715,7 +714,7 @@ namespace Markdig.Tests.Specs.PipeTables
|
||||
TestParser.TestSpec("a | b\n-- | --\n[This is a link with a | inside the label](http://google.com) | 1", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a href=\"http://google.com\">This is a link with a | inside the label</a></td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
|
||||
}
|
||||
|
||||
// ** Rule #9**
|
||||
// **Rule #10**
|
||||
//
|
||||
// It is possible to have a single row header only:
|
||||
[Test]
|
||||
@@ -767,7 +766,7 @@ namespace Markdig.Tests.Specs.PipeTables
|
||||
TestParser.TestSpec("|a|b|c\n|---|---|---|", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n</table>", "pipetables|advanced");
|
||||
}
|
||||
|
||||
// ** Tests **
|
||||
// **Tests**
|
||||
//
|
||||
// Tests trailing spaces after pipes
|
||||
[Test]
|
||||
@@ -816,7 +815,7 @@ namespace Markdig.Tests.Specs.PipeTables
|
||||
TestParser.TestSpec("| abc | def | \n|---|---|\n| cde| ddd| \n| eee| fff|\n| fff | fffff | \n|gggg | ffff | ", "<table>\n<thead>\n<tr>\n<th>abc</th>\n<th>def</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>cde</td>\n<td>ddd</td>\n</tr>\n<tr>\n<td>eee</td>\n<td>fff</td>\n</tr>\n<tr>\n<td>fff</td>\n<td>fffff</td>\n</tr>\n<tr>\n<td>gggg</td>\n<td>ffff</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
|
||||
}
|
||||
|
||||
// ** Normalized columns count **
|
||||
// **Normalized columns count**
|
||||
//
|
||||
// The tables are normalized to the maximum number of columns found in a table
|
||||
[Test]
|
||||
|
||||
@@ -463,7 +463,7 @@ a | b `
|
||||
<p>a | b <code>0 |</code></p>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #7**
|
||||
**Rule #8**
|
||||
|
||||
A HTML inline has a higher precedence than a column delimiter `|`:
|
||||
|
||||
@@ -488,7 +488,7 @@ a <a href="" title="|"></a> | b
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
**Rule #8**
|
||||
**Rule #9**
|
||||
|
||||
Links have a higher precedence than the column delimiter character `|`:
|
||||
|
||||
@@ -513,7 +513,7 @@ a | b
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
** Rule #9**
|
||||
**Rule #10**
|
||||
|
||||
It is possible to have a single row header only:
|
||||
|
||||
@@ -546,7 +546,7 @@ a | b
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
** Tests **
|
||||
**Tests**
|
||||
|
||||
Tests trailing spaces after pipes
|
||||
|
||||
@@ -586,7 +586,7 @@ Tests trailing spaces after pipes
|
||||
</table>
|
||||
````````````````````````````````
|
||||
|
||||
** Normalized columns count **
|
||||
**Normalized columns count**
|
||||
|
||||
The tables are normalized to the maximum number of columns found in a table
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-08-01 12:33:23
|
||||
|
||||
// --------------------------------
|
||||
// Smarty Pants
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Task Lists
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Generated: 2019-04-05 16:06:14
|
||||
|
||||
// --------------------------------
|
||||
// Yaml
|
||||
|
||||
@@ -47,12 +47,14 @@ namespace Markdig.Tests
|
||||
container.Insert(0, one);
|
||||
Assert.AreEqual(1, container.Count);
|
||||
Assert.AreSame(container[0], one);
|
||||
Assert.AreSame(container, one.Parent);
|
||||
|
||||
var two = new ParagraphBlock();
|
||||
container.Insert(1, two);
|
||||
Assert.AreEqual(2, container.Count);
|
||||
Assert.AreSame(container[0], one);
|
||||
Assert.AreSame(container[1], two);
|
||||
Assert.AreSame(container, two.Parent);
|
||||
|
||||
var three = new ParagraphBlock();
|
||||
container.Insert(0, three);
|
||||
@@ -60,11 +62,31 @@ namespace Markdig.Tests
|
||||
Assert.AreSame(container[0], three);
|
||||
Assert.AreSame(container[1], one);
|
||||
Assert.AreSame(container[2], two);
|
||||
Assert.AreSame(container, three.Parent);
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => container.Insert(0, null));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => container.Insert(4, new ParagraphBlock()));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => container.Insert(-1, new ParagraphBlock()));
|
||||
Assert.Throws<ArgumentException>(() => container.Insert(0, one)); // one already has a parent
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanBeSet()
|
||||
{
|
||||
ContainerBlock container = new MockContainerBlock();
|
||||
|
||||
var one = new ParagraphBlock();
|
||||
container.Insert(0, one);
|
||||
Assert.AreEqual(1, container.Count);
|
||||
Assert.AreSame(container[0], one);
|
||||
Assert.AreSame(container, one.Parent);
|
||||
|
||||
var two = new ParagraphBlock();
|
||||
container[0] = two;
|
||||
Assert.AreSame(container, two.Parent);
|
||||
Assert.Null(one.Parent);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => container[0] = two); // two already has a parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
src/Markdig.Tests/TestContainerInlines.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
public class TestContainerInlines
|
||||
{
|
||||
private class MockLeafBlock : LeafBlock
|
||||
{
|
||||
public MockLeafBlock()
|
||||
: base(null)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanBeAddedToLeafBlock()
|
||||
{
|
||||
var leafBlock1 = new MockLeafBlock();
|
||||
|
||||
var one = new ContainerInline();
|
||||
Assert.Null(one.ParentBlock);
|
||||
|
||||
leafBlock1.Inline = one;
|
||||
Assert.AreSame(leafBlock1, one.ParentBlock);
|
||||
|
||||
var two = new ContainerInline();
|
||||
Assert.Null(two.ParentBlock);
|
||||
|
||||
leafBlock1.Inline = two;
|
||||
Assert.AreSame(leafBlock1, two.ParentBlock);
|
||||
Assert.Null(one.ParentBlock);
|
||||
|
||||
var leafBlock2 = new MockLeafBlock();
|
||||
Assert.Throws<ArgumentException>(() => leafBlock2.Inline = two);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Markdig.Extensions.Emoji;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Markdig.Extensions.Emoji;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCustomEmojis
|
||||
{
|
||||
{
|
||||
[Test]
|
||||
[TestCase(":smiley:", "<p>♥</p>\n")]
|
||||
[TestCase(":confused:", "<p>:confused:</p>\n")] // default emoji does not work
|
||||
@@ -28,13 +27,13 @@ namespace Markdig.Tests
|
||||
|
||||
var actual = Markdown.ToHtml(input, pipeline);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(":testheart:", "<p>♥</p>\n")]
|
||||
[TestCase("hello", "<p>♥</p>\n")]
|
||||
[TestCase(":confused:", "<p>:confused:</p>\n")] // default emoji does not work
|
||||
[TestCase(":/", "<p>:/</p>\n")] // default smiley does not work
|
||||
[TestCase(":/", "<p>:/</p>\n")] // default smiley does not work
|
||||
public void TestCustomSmiley(string input, string expected)
|
||||
{
|
||||
var emojiToUnicode = new Dictionary<string, string>();
|
||||
@@ -55,8 +54,8 @@ namespace Markdig.Tests
|
||||
|
||||
[Test]
|
||||
[TestCase(":smiley:", "<p>♥</p>\n")]
|
||||
[TestCase(":)", "<p>♥</p>\n")]
|
||||
[TestCase(":confused:", "<p>😕</p>\n")] // default emoji still works
|
||||
[TestCase(":)", "<p>♥</p>\n")]
|
||||
[TestCase(":confused:", "<p>😕</p>\n")] // default emoji still works
|
||||
[TestCase(":/", "<p>😕</p>\n")] // default smiley still works
|
||||
public void TestOverrideDefaultWithCustomEmoji(string input, string expected)
|
||||
{
|
||||
@@ -73,8 +72,8 @@ namespace Markdig.Tests
|
||||
|
||||
var actual = Markdown.ToHtml(input, pipeline);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(":testheart:", "<p>♥</p>\n")]
|
||||
[TestCase("hello", "<p>♥</p>\n")]
|
||||
@@ -99,31 +98,31 @@ namespace Markdig.Tests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCustomEmojiValidation()
|
||||
{
|
||||
var emojiToUnicode = new Dictionary<string, string>();
|
||||
var smileyToEmoji = new Dictionary<string, string>();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => new EmojiMapping(null, smileyToEmoji));
|
||||
Assert.Throws<ArgumentNullException>(() => new EmojiMapping(emojiToUnicode, null));
|
||||
|
||||
emojiToUnicode.Add("null-value", null);
|
||||
Assert.Throws<ArgumentException>(() => new EmojiMapping(emojiToUnicode, smileyToEmoji));
|
||||
emojiToUnicode.Clear();
|
||||
|
||||
smileyToEmoji.Add("null-value", null);
|
||||
Assert.Throws<ArgumentException>(() => new EmojiMapping(emojiToUnicode, smileyToEmoji));
|
||||
smileyToEmoji.Clear();
|
||||
|
||||
smileyToEmoji.Add("foo", "something-that-does-not-exist-in-emojiToUnicode");
|
||||
Assert.Throws<ArgumentException>(() => new EmojiMapping(emojiToUnicode, smileyToEmoji));
|
||||
smileyToEmoji.Clear();
|
||||
|
||||
emojiToUnicode.Add("a", "aaa");
|
||||
emojiToUnicode.Add("b", "bbb");
|
||||
emojiToUnicode.Add("c", "ccc");
|
||||
smileyToEmoji.Add("a", "c"); // "a" already exists in emojiToUnicode
|
||||
Assert.Throws<ArgumentException>(() => new EmojiMapping(emojiToUnicode, smileyToEmoji));
|
||||
public void TestCustomEmojiValidation()
|
||||
{
|
||||
var emojiToUnicode = new Dictionary<string, string>();
|
||||
var smileyToEmoji = new Dictionary<string, string>();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => new EmojiMapping(null, smileyToEmoji));
|
||||
Assert.Throws<ArgumentNullException>(() => new EmojiMapping(emojiToUnicode, null));
|
||||
|
||||
emojiToUnicode.Add("null-value", null);
|
||||
Assert.Throws<ArgumentException>(() => new EmojiMapping(emojiToUnicode, smileyToEmoji));
|
||||
emojiToUnicode.Clear();
|
||||
|
||||
smileyToEmoji.Add("null-value", null);
|
||||
Assert.Throws<ArgumentException>(() => new EmojiMapping(emojiToUnicode, smileyToEmoji));
|
||||
smileyToEmoji.Clear();
|
||||
|
||||
smileyToEmoji.Add("foo", "something-that-does-not-exist-in-emojiToUnicode");
|
||||
Assert.Throws<ArgumentException>(() => new EmojiMapping(emojiToUnicode, smileyToEmoji));
|
||||
smileyToEmoji.Clear();
|
||||
|
||||
emojiToUnicode.Add("a", "aaa");
|
||||
emojiToUnicode.Add("b", "bbb");
|
||||
emojiToUnicode.Add("c", "ccc");
|
||||
smileyToEmoji.Add("a", "c"); // "a" already exists in emojiToUnicode
|
||||
Assert.Throws<ArgumentException>(() => new EmojiMapping(emojiToUnicode, smileyToEmoji));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +1,152 @@
|
||||
using NUnit.Framework;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestDescendantsOrder
|
||||
{
|
||||
[Test]
|
||||
public void TestSchemas()
|
||||
{
|
||||
foreach (var syntaxTree in TestParser.SpecsSyntaxTrees)
|
||||
{
|
||||
AssertIEnumerablesAreEqual(
|
||||
Descendants_Legacy(syntaxTree),
|
||||
syntaxTree.Descendants());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
syntaxTree.Descendants().OfType<ParagraphBlock>(),
|
||||
syntaxTree.Descendants<ParagraphBlock>());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
syntaxTree.Descendants().OfType<ParagraphBlock>(),
|
||||
(syntaxTree as ContainerBlock).Descendants<ParagraphBlock>());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
syntaxTree.Descendants().OfType<LiteralInline>(),
|
||||
syntaxTree.Descendants<LiteralInline>());
|
||||
|
||||
foreach (LiteralInline literalInline in syntaxTree.Descendants<LiteralInline>())
|
||||
{
|
||||
Assert.AreSame(Array.Empty<ListBlock>(), literalInline.Descendants<ListBlock>());
|
||||
Assert.AreSame(Array.Empty<ParagraphBlock>(), literalInline.Descendants<ParagraphBlock>());
|
||||
Assert.AreSame(Array.Empty<ContainerInline>(), literalInline.Descendants<ContainerInline>());
|
||||
}
|
||||
|
||||
foreach (ContainerInline containerInline in syntaxTree.Descendants<ContainerInline>())
|
||||
{
|
||||
AssertIEnumerablesAreEqual(
|
||||
containerInline.FindDescendants<LiteralInline>(),
|
||||
containerInline.Descendants<LiteralInline>());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
containerInline.FindDescendants<LiteralInline>(),
|
||||
(containerInline as MarkdownObject).Descendants<LiteralInline>());
|
||||
|
||||
if (containerInline.FirstChild is null)
|
||||
{
|
||||
Assert.AreSame(Array.Empty<LiteralInline>(), containerInline.Descendants<LiteralInline>());
|
||||
Assert.AreSame(Array.Empty<LiteralInline>(), containerInline.FindDescendants<LiteralInline>());
|
||||
Assert.AreSame(Array.Empty<LiteralInline>(), (containerInline as MarkdownObject).Descendants<LiteralInline>());
|
||||
}
|
||||
|
||||
Assert.AreSame(Array.Empty<ListBlock>(), containerInline.Descendants<ListBlock>());
|
||||
Assert.AreSame(Array.Empty<ParagraphBlock>(), containerInline.Descendants<ParagraphBlock>());
|
||||
}
|
||||
|
||||
foreach (ParagraphBlock paragraphBlock in syntaxTree.Descendants<ParagraphBlock>())
|
||||
{
|
||||
AssertIEnumerablesAreEqual(
|
||||
(paragraphBlock as MarkdownObject).Descendants<LiteralInline>(),
|
||||
paragraphBlock.Descendants<LiteralInline>());
|
||||
|
||||
Assert.AreSame(Array.Empty<ParagraphBlock>(), paragraphBlock.Descendants<ParagraphBlock>());
|
||||
}
|
||||
|
||||
foreach (ContainerBlock containerBlock in syntaxTree.Descendants<ContainerBlock>())
|
||||
{
|
||||
AssertIEnumerablesAreEqual(
|
||||
containerBlock.Descendants<LiteralInline>(),
|
||||
(containerBlock as MarkdownObject).Descendants<LiteralInline>());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
containerBlock.Descendants<ParagraphBlock>(),
|
||||
(containerBlock as MarkdownObject).Descendants<ParagraphBlock>());
|
||||
|
||||
if (containerBlock.Count == 0)
|
||||
{
|
||||
Assert.AreSame(Array.Empty<LiteralInline>(), containerBlock.Descendants<LiteralInline>());
|
||||
Assert.AreSame(Array.Empty<LiteralInline>(), (containerBlock as Block).Descendants<LiteralInline>());
|
||||
Assert.AreSame(Array.Empty<LiteralInline>(), (containerBlock as MarkdownObject).Descendants<LiteralInline>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertIEnumerablesAreEqual<T>(IEnumerable<T> first, IEnumerable<T> second)
|
||||
{
|
||||
var firstList = new List<T>(first);
|
||||
var secondList = new List<T>(second);
|
||||
|
||||
Assert.AreEqual(firstList.Count, secondList.Count);
|
||||
|
||||
for (int i = 0; i < firstList.Count; i++)
|
||||
{
|
||||
Assert.AreSame(firstList[i], secondList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<MarkdownObject> Descendants_Legacy(MarkdownObject markdownObject)
|
||||
{
|
||||
// TODO: implement a recursiveless method
|
||||
|
||||
var block = markdownObject as ContainerBlock;
|
||||
if (block != null)
|
||||
{
|
||||
foreach (var subBlock in block)
|
||||
{
|
||||
yield return subBlock;
|
||||
|
||||
foreach (var sub in Descendants_Legacy(subBlock))
|
||||
{
|
||||
yield return sub;
|
||||
}
|
||||
|
||||
// Visit leaf block that have inlines
|
||||
var leafBlock = subBlock as LeafBlock;
|
||||
if (leafBlock?.Inline != null)
|
||||
{
|
||||
foreach (var subInline in Descendants_Legacy(leafBlock.Inline))
|
||||
{
|
||||
yield return subInline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var inline = markdownObject as ContainerInline;
|
||||
if (inline != null)
|
||||
{
|
||||
var child = inline.FirstChild;
|
||||
while (child != null)
|
||||
{
|
||||
var next = child.NextSibling;
|
||||
yield return child;
|
||||
|
||||
foreach (var sub in Descendants_Legacy(child))
|
||||
{
|
||||
yield return sub;
|
||||
}
|
||||
|
||||
child = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using NUnit.Framework;
|
||||
using Markdig.Helpers;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestDescendantsOrder
|
||||
{
|
||||
public static void TestSchemas(MarkdownDocument[] specsSyntaxTrees)
|
||||
{
|
||||
foreach (var syntaxTree in specsSyntaxTrees)
|
||||
{
|
||||
AssertIEnumerablesAreEqual(
|
||||
Descendants_Legacy(syntaxTree),
|
||||
syntaxTree.Descendants());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
syntaxTree.Descendants().OfType<ParagraphBlock>(),
|
||||
syntaxTree.Descendants<ParagraphBlock>());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
syntaxTree.Descendants().OfType<ParagraphBlock>(),
|
||||
(syntaxTree as ContainerBlock).Descendants<ParagraphBlock>());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
syntaxTree.Descendants().OfType<LiteralInline>(),
|
||||
syntaxTree.Descendants<LiteralInline>());
|
||||
|
||||
foreach (LiteralInline literalInline in syntaxTree.Descendants<LiteralInline>())
|
||||
{
|
||||
Assert.AreSame(ArrayHelper.Empty<ListBlock>(), literalInline.Descendants<ListBlock>());
|
||||
Assert.AreSame(ArrayHelper.Empty<ParagraphBlock>(), literalInline.Descendants<ParagraphBlock>());
|
||||
Assert.AreSame(ArrayHelper.Empty<ContainerInline>(), literalInline.Descendants<ContainerInline>());
|
||||
}
|
||||
|
||||
foreach (ContainerInline containerInline in syntaxTree.Descendants<ContainerInline>())
|
||||
{
|
||||
AssertIEnumerablesAreEqual(
|
||||
containerInline.FindDescendants<LiteralInline>(),
|
||||
containerInline.Descendants<LiteralInline>());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
containerInline.FindDescendants<LiteralInline>(),
|
||||
(containerInline as MarkdownObject).Descendants<LiteralInline>());
|
||||
|
||||
if (containerInline.FirstChild is null)
|
||||
{
|
||||
Assert.AreSame(ArrayHelper.Empty<LiteralInline>(), containerInline.Descendants<LiteralInline>());
|
||||
Assert.AreSame(ArrayHelper.Empty<LiteralInline>(), containerInline.FindDescendants<LiteralInline>());
|
||||
Assert.AreSame(ArrayHelper.Empty<LiteralInline>(), (containerInline as MarkdownObject).Descendants<LiteralInline>());
|
||||
}
|
||||
|
||||
Assert.AreSame(ArrayHelper.Empty<ListBlock>(), containerInline.Descendants<ListBlock>());
|
||||
Assert.AreSame(ArrayHelper.Empty<ParagraphBlock>(), containerInline.Descendants<ParagraphBlock>());
|
||||
}
|
||||
|
||||
foreach (ParagraphBlock paragraphBlock in syntaxTree.Descendants<ParagraphBlock>())
|
||||
{
|
||||
AssertIEnumerablesAreEqual(
|
||||
(paragraphBlock as MarkdownObject).Descendants<LiteralInline>(),
|
||||
paragraphBlock.Descendants<LiteralInline>());
|
||||
|
||||
Assert.AreSame(ArrayHelper.Empty<ParagraphBlock>(), paragraphBlock.Descendants<ParagraphBlock>());
|
||||
}
|
||||
|
||||
foreach (ContainerBlock containerBlock in syntaxTree.Descendants<ContainerBlock>())
|
||||
{
|
||||
AssertIEnumerablesAreEqual(
|
||||
containerBlock.Descendants<LiteralInline>(),
|
||||
(containerBlock as MarkdownObject).Descendants<LiteralInline>());
|
||||
|
||||
AssertIEnumerablesAreEqual(
|
||||
containerBlock.Descendants<ParagraphBlock>(),
|
||||
(containerBlock as MarkdownObject).Descendants<ParagraphBlock>());
|
||||
|
||||
if (containerBlock.Count == 0)
|
||||
{
|
||||
Assert.AreSame(ArrayHelper.Empty<LiteralInline>(), containerBlock.Descendants<LiteralInline>());
|
||||
Assert.AreSame(ArrayHelper.Empty<LiteralInline>(), (containerBlock as Block).Descendants<LiteralInline>());
|
||||
Assert.AreSame(ArrayHelper.Empty<LiteralInline>(), (containerBlock as MarkdownObject).Descendants<LiteralInline>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertIEnumerablesAreEqual<T>(IEnumerable<T> first, IEnumerable<T> second)
|
||||
{
|
||||
var firstList = new List<T>(first);
|
||||
var secondList = new List<T>(second);
|
||||
|
||||
Assert.AreEqual(firstList.Count, secondList.Count);
|
||||
|
||||
for (int i = 0; i < firstList.Count; i++)
|
||||
{
|
||||
Assert.AreSame(firstList[i], secondList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<MarkdownObject> Descendants_Legacy(MarkdownObject markdownObject)
|
||||
{
|
||||
// TODO: implement a recursiveless method
|
||||
|
||||
var block = markdownObject as ContainerBlock;
|
||||
if (block != null)
|
||||
{
|
||||
foreach (var subBlock in block)
|
||||
{
|
||||
yield return subBlock;
|
||||
|
||||
foreach (var sub in Descendants_Legacy(subBlock))
|
||||
{
|
||||
yield return sub;
|
||||
}
|
||||
|
||||
// Visit leaf block that have inlines
|
||||
var leafBlock = subBlock as LeafBlock;
|
||||
if (leafBlock?.Inline != null)
|
||||
{
|
||||
foreach (var subInline in Descendants_Legacy(leafBlock.Inline))
|
||||
{
|
||||
yield return subInline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var inline = markdownObject as ContainerInline;
|
||||
if (inline != null)
|
||||
{
|
||||
var child = inline.FirstChild;
|
||||
while (child != null)
|
||||
{
|
||||
var next = child.NextSibling;
|
||||
yield return child;
|
||||
|
||||
foreach (var sub in Descendants_Legacy(child))
|
||||
{
|
||||
yield return sub;
|
||||
}
|
||||
|
||||
child = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,168 +1,169 @@
|
||||
using Markdig.Parsers.Inlines;
|
||||
using Markdig.Renderers;
|
||||
using Markdig.Renderers.Html;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestEmphasisExtended
|
||||
{
|
||||
class EmphasisTestExtension : IMarkdownExtension
|
||||
{
|
||||
public void Setup(MarkdownPipelineBuilder pipeline)
|
||||
{
|
||||
var emphasisParser = pipeline.InlineParsers.Find<EmphasisInlineParser>();
|
||||
Debug.Assert(emphasisParser != null);
|
||||
|
||||
foreach (var emphasis in EmphasisTestDescriptors)
|
||||
{
|
||||
emphasisParser.EmphasisDescriptors.Add(
|
||||
new EmphasisDescriptor(emphasis.Character, emphasis.Minimum, emphasis.Maximum, true));
|
||||
}
|
||||
emphasisParser.TryCreateEmphasisInlineList.Add((delimiterChar, delimiterCount) =>
|
||||
{
|
||||
return delimiterChar == '*' || delimiterChar == '_'
|
||||
? null
|
||||
: new CustomEmphasisInline() { DelimiterChar = delimiterChar, DelimiterCount = delimiterCount };
|
||||
});
|
||||
}
|
||||
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
renderer.ObjectRenderers.Insert(0, new EmphasisRenderer());
|
||||
}
|
||||
|
||||
class EmphasisRenderer : HtmlObjectRenderer<CustomEmphasisInline>
|
||||
{
|
||||
protected override void Write(HtmlRenderer renderer, CustomEmphasisInline obj)
|
||||
{
|
||||
var tag = EmphasisTestDescriptors.First(test => test.Character == obj.DelimiterChar).Tags[obj.DelimiterCount];
|
||||
|
||||
renderer.Write(tag.OpeningTag);
|
||||
renderer.WriteChildren(obj);
|
||||
renderer.Write(tag.ClosingTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
class Tag
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public int Level;
|
||||
#pragma warning restore CS0649
|
||||
public string RawTag;
|
||||
public string OpeningTag;
|
||||
public string ClosingTag;
|
||||
|
||||
public Tag(string tag)
|
||||
{
|
||||
RawTag = tag;
|
||||
OpeningTag = "<" + tag + ">";
|
||||
ClosingTag = "</" + tag + ">";
|
||||
}
|
||||
|
||||
public static implicit operator Tag(string tag)
|
||||
=> new Tag(tag);
|
||||
}
|
||||
class EmphasisTestDescriptor
|
||||
{
|
||||
public char Character;
|
||||
public int Minimum;
|
||||
public int Maximum;
|
||||
public Dictionary<int, Tag> Tags = new Dictionary<int, Tag>();
|
||||
|
||||
private EmphasisTestDescriptor(char character, int min, int max)
|
||||
{
|
||||
Character = character;
|
||||
Minimum = min;
|
||||
Maximum = max;
|
||||
}
|
||||
public EmphasisTestDescriptor(char character, int min, int max, params Tag[] tags)
|
||||
: this(character, min, max)
|
||||
{
|
||||
Debug.Assert(tags.Length == max - min + 1);
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
Tags.Add(min++, tag);
|
||||
}
|
||||
}
|
||||
public EmphasisTestDescriptor(char character, int min, int max, string tag)
|
||||
: this(character, min, max, new Tag(tag)) { }
|
||||
}
|
||||
class CustomEmphasisInline : EmphasisInline { }
|
||||
static readonly EmphasisTestDescriptor[] EmphasisTestDescriptors = new[]
|
||||
{
|
||||
// Min Max
|
||||
new EmphasisTestDescriptor('"', 1, 1, "quotation"),
|
||||
new EmphasisTestDescriptor(',', 1, 2, "comma", "extra-comma"),
|
||||
new EmphasisTestDescriptor('!', 2, 3, "warning", "error"),
|
||||
new EmphasisTestDescriptor('=', 1, 3, "equal", "really-equal", "congruent"),
|
||||
new EmphasisTestDescriptor('1', 1, 1, "one-only"),
|
||||
new EmphasisTestDescriptor('2', 2, 2, "two-only"),
|
||||
new EmphasisTestDescriptor('3', 3, 3, "three-only"),
|
||||
};
|
||||
|
||||
static readonly MarkdownPipeline Pipeline = new MarkdownPipelineBuilder().Use<EmphasisTestExtension>().Build();
|
||||
|
||||
[Test]
|
||||
[TestCase("*foo**", "<em>foo</em>*")]
|
||||
[TestCase("**foo*", "*<em>foo</em>")]
|
||||
[TestCase("***foo***", "<em><strong>foo</strong></em>")]
|
||||
[TestCase("**_foo_**", "<strong><em>foo</em></strong>")]
|
||||
[TestCase("_**foo**_", "<em><strong>foo</strong></em>")]
|
||||
[TestCase("\"foo\"", "<quotation>foo</quotation>")]
|
||||
[TestCase("\"\"foo\"\"", "<quotation><quotation>foo</quotation></quotation>")]
|
||||
[TestCase("\"foo\"\"", "<quotation>foo</quotation>"")]
|
||||
[TestCase("\"\"foo\"", ""<quotation>foo</quotation>")]
|
||||
[TestCase(", foo", ", foo")]
|
||||
[TestCase(", foo,", ", foo,")]
|
||||
[TestCase(",some, foo,", "<comma>some</comma> foo,")]
|
||||
[TestCase(",,foo,,", "<extra-comma>foo</extra-comma>")]
|
||||
[TestCase(",foo,,", "<comma>foo</comma>,")]
|
||||
[TestCase(",,,foo,,,", "<comma><extra-comma>foo</extra-comma></comma>")]
|
||||
[TestCase("!1!", "!1!")]
|
||||
[TestCase("!!2!!", "<warning>2</warning>")]
|
||||
[TestCase("!!!3!!!", "<error>3</error>")]
|
||||
[TestCase("!!!34!!!!", "<error>34</error>!")]
|
||||
[TestCase("!!!!43!!!", "!<error>43</error>")]
|
||||
[TestCase("!!!!44!!!!", "!<error>44!</error>")] // This is a new case - should the second ! be before or after </error>?
|
||||
[TestCase("!!!!!5!!!!!", "<warning><error>5</error></warning>")]
|
||||
[TestCase("!!!!!!6!!!!!!", "<error><error>6</error></error>")]
|
||||
[TestCase("!! !mixed!!!", "!! !mixed!!!")] // can't open the delimiter because of the whitespace
|
||||
[TestCase("=", "=")]
|
||||
[TestCase("==", "==")]
|
||||
[TestCase("====", "====")]
|
||||
[TestCase("=a", "=a")]
|
||||
[TestCase("=a=", "<equal>a</equal>")]
|
||||
[TestCase("==a=", "=<equal>a</equal>")]
|
||||
[TestCase("==a==", "<really-equal>a</really-equal>")]
|
||||
[TestCase("==a===", "<really-equal>a</really-equal>=")]
|
||||
[TestCase("===a===", "<congruent>a</congruent>")]
|
||||
[TestCase("====a====", "<equal><congruent>a</congruent></equal>")]
|
||||
[TestCase("=====a=====", "<really-equal><congruent>a</congruent></really-equal>")]
|
||||
[TestCase("1", "1")]
|
||||
[TestCase("1 1", "1 1")]
|
||||
[TestCase("1Foo1", "<one-only>Foo</one-only>")]
|
||||
[TestCase("1121", "1<one-only>2</one-only>")]
|
||||
[TestCase("22322", "<two-only>3</two-only>")]
|
||||
[TestCase("2232", "2232")]
|
||||
[TestCase("333", "333")]
|
||||
[TestCase("3334333", "<three-only>4</three-only>")]
|
||||
[TestCase("33334333", "3<three-only>4</three-only>")]
|
||||
[TestCase("33343333", "<three-only>4</three-only>3")]
|
||||
[TestCase("122122", "<one-only>22</one-only>22")]
|
||||
[TestCase("221221", "<two-only>1</two-only>1")]
|
||||
[TestCase("122foo221", "<one-only><two-only>foo</two-only></one-only>")]
|
||||
[TestCase("122foo122", "<one-only>22foo</one-only>22")]
|
||||
[TestCase("!!!!!Attention:!! \"==1+1== 2\",but ===333 and 222===, mod 111!!!",
|
||||
"<error><warning>Attention:</warning> <quotation><really-equal><one-only>+</one-only></really-equal> 2</quotation><comma>but <congruent>333 and 222</congruent></comma> mod 111</error>")]
|
||||
public void TestEmphasis(string markdown, string expectedHtml)
|
||||
{
|
||||
TestParser.TestSpec(markdown, "<p>" + expectedHtml + "</p>", Pipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
using Markdig.Parsers.Inlines;
|
||||
using Markdig.Renderers;
|
||||
using Markdig.Renderers.Html;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestEmphasisExtended
|
||||
{
|
||||
class EmphasisTestExtension : IMarkdownExtension
|
||||
{
|
||||
public void Setup(MarkdownPipelineBuilder pipeline)
|
||||
{
|
||||
var emphasisParser = pipeline.InlineParsers.Find<EmphasisInlineParser>();
|
||||
Debug.Assert(emphasisParser != null);
|
||||
|
||||
foreach (var emphasis in EmphasisTestDescriptors)
|
||||
{
|
||||
emphasisParser.EmphasisDescriptors.Add(
|
||||
new EmphasisDescriptor(emphasis.Character, emphasis.Minimum, emphasis.Maximum, true));
|
||||
}
|
||||
emphasisParser.TryCreateEmphasisInlineList.Add((delimiterChar, delimiterCount) =>
|
||||
{
|
||||
return delimiterChar == '*' || delimiterChar == '_'
|
||||
? null
|
||||
: new CustomEmphasisInline() { DelimiterChar = delimiterChar, DelimiterCount = delimiterCount };
|
||||
});
|
||||
}
|
||||
|
||||
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
|
||||
{
|
||||
renderer.ObjectRenderers.Insert(0, new EmphasisRenderer());
|
||||
}
|
||||
|
||||
class EmphasisRenderer : HtmlObjectRenderer<CustomEmphasisInline>
|
||||
{
|
||||
protected override void Write(HtmlRenderer renderer, CustomEmphasisInline obj)
|
||||
{
|
||||
var tag = EmphasisTestDescriptors.First(test => test.Character == obj.DelimiterChar).Tags[obj.DelimiterCount];
|
||||
|
||||
renderer.Write(tag.OpeningTag);
|
||||
renderer.WriteChildren(obj);
|
||||
renderer.Write(tag.ClosingTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
class Tag
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public int Level;
|
||||
#pragma warning restore CS0649
|
||||
public string RawTag;
|
||||
public string OpeningTag;
|
||||
public string ClosingTag;
|
||||
|
||||
public Tag(string tag)
|
||||
{
|
||||
RawTag = tag;
|
||||
OpeningTag = "<" + tag + ">";
|
||||
ClosingTag = "</" + tag + ">";
|
||||
}
|
||||
|
||||
public static implicit operator Tag(string tag)
|
||||
=> new Tag(tag);
|
||||
}
|
||||
class EmphasisTestDescriptor
|
||||
{
|
||||
public char Character;
|
||||
public int Minimum;
|
||||
public int Maximum;
|
||||
public Dictionary<int, Tag> Tags = new Dictionary<int, Tag>();
|
||||
|
||||
private EmphasisTestDescriptor(char character, int min, int max)
|
||||
{
|
||||
Character = character;
|
||||
Minimum = min;
|
||||
Maximum = max;
|
||||
}
|
||||
public EmphasisTestDescriptor(char character, int min, int max, params Tag[] tags)
|
||||
: this(character, min, max)
|
||||
{
|
||||
Debug.Assert(tags.Length == max - min + 1);
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
Tags.Add(min++, tag);
|
||||
}
|
||||
}
|
||||
public EmphasisTestDescriptor(char character, int min, int max, string tag)
|
||||
: this(character, min, max, new Tag(tag)) { }
|
||||
}
|
||||
class CustomEmphasisInline : EmphasisInline { }
|
||||
static readonly EmphasisTestDescriptor[] EmphasisTestDescriptors = new[]
|
||||
{
|
||||
// Min Max
|
||||
new EmphasisTestDescriptor('"', 1, 1, "quotation"),
|
||||
new EmphasisTestDescriptor(',', 1, 2, "comma", "extra-comma"),
|
||||
new EmphasisTestDescriptor('!', 2, 3, "warning", "error"),
|
||||
new EmphasisTestDescriptor('=', 1, 3, "equal", "really-equal", "congruent"),
|
||||
new EmphasisTestDescriptor('1', 1, 1, "one-only"),
|
||||
new EmphasisTestDescriptor('2', 2, 2, "two-only"),
|
||||
new EmphasisTestDescriptor('3', 3, 3, "three-only"),
|
||||
};
|
||||
|
||||
static readonly MarkdownPipeline Pipeline = new MarkdownPipelineBuilder().Use<EmphasisTestExtension>().Build();
|
||||
|
||||
[Test]
|
||||
[TestCase("*foo**", "<em>foo</em>*")]
|
||||
[TestCase("**foo*", "*<em>foo</em>")]
|
||||
[TestCase("***foo***", "<em><strong>foo</strong></em>")]
|
||||
[TestCase("**_foo_**", "<strong><em>foo</em></strong>")]
|
||||
[TestCase("_**foo**_", "<em><strong>foo</strong></em>")]
|
||||
[TestCase("\"foo\"", "<quotation>foo</quotation>")]
|
||||
[TestCase("\"\"foo\"\"", "<quotation><quotation>foo</quotation></quotation>")]
|
||||
[TestCase("\"foo\"\"", "<quotation>foo</quotation>"")]
|
||||
[TestCase("\"\"foo\"", ""<quotation>foo</quotation>")]
|
||||
[TestCase(", foo", ", foo")]
|
||||
[TestCase(", foo,", ", foo,")]
|
||||
[TestCase(",some, foo,", "<comma>some</comma> foo,")]
|
||||
[TestCase(",,foo,,", "<extra-comma>foo</extra-comma>")]
|
||||
[TestCase(",foo,,", "<comma>foo</comma>,")]
|
||||
[TestCase(",,,foo,,,", "<comma><extra-comma>foo</extra-comma></comma>")]
|
||||
[TestCase("*foo*&_foo_", "<em>foo</em>&<em>foo</em>")]
|
||||
[TestCase("!1!", "!1!")]
|
||||
[TestCase("!!2!!", "<warning>2</warning>")]
|
||||
[TestCase("!!!3!!!", "<error>3</error>")]
|
||||
[TestCase("!!!34!!!!", "<error>34</error>!")]
|
||||
[TestCase("!!!!43!!!", "!<error>43</error>")]
|
||||
[TestCase("!!!!44!!!!", "!<error>44!</error>")] // This is a new case - should the second ! be before or after </error>?
|
||||
[TestCase("!!!!!5!!!!!", "<warning><error>5</error></warning>")]
|
||||
[TestCase("!!!!!!6!!!!!!", "<error><error>6</error></error>")]
|
||||
[TestCase("!! !mixed!!!", "!! !mixed!!!")] // can't open the delimiter because of the whitespace
|
||||
[TestCase("=", "=")]
|
||||
[TestCase("==", "==")]
|
||||
[TestCase("====", "====")]
|
||||
[TestCase("=a", "=a")]
|
||||
[TestCase("=a=", "<equal>a</equal>")]
|
||||
[TestCase("==a=", "=<equal>a</equal>")]
|
||||
[TestCase("==a==", "<really-equal>a</really-equal>")]
|
||||
[TestCase("==a===", "<really-equal>a</really-equal>=")]
|
||||
[TestCase("===a===", "<congruent>a</congruent>")]
|
||||
[TestCase("====a====", "<equal><congruent>a</congruent></equal>")]
|
||||
[TestCase("=====a=====", "<really-equal><congruent>a</congruent></really-equal>")]
|
||||
[TestCase("1", "1")]
|
||||
[TestCase("1 1", "1 1")]
|
||||
[TestCase("1Foo1", "<one-only>Foo</one-only>")]
|
||||
[TestCase("1121", "1<one-only>2</one-only>")]
|
||||
[TestCase("22322", "<two-only>3</two-only>")]
|
||||
[TestCase("2232", "2232")]
|
||||
[TestCase("333", "333")]
|
||||
[TestCase("3334333", "<three-only>4</three-only>")]
|
||||
[TestCase("33334333", "3<three-only>4</three-only>")]
|
||||
[TestCase("33343333", "<three-only>4</three-only>3")]
|
||||
[TestCase("122122", "<one-only>22</one-only>22")]
|
||||
[TestCase("221221", "<two-only>1</two-only>1")]
|
||||
[TestCase("122foo221", "<one-only><two-only>foo</two-only></one-only>")]
|
||||
[TestCase("122foo122", "<one-only>22foo</one-only>22")]
|
||||
[TestCase("!!!!!Attention:!! \"==1+1== 2\",but ===333 and 222===, mod 111!!!",
|
||||
"<error><warning>Attention:</warning> <quotation><really-equal><one-only>+</one-only></really-equal> 2</quotation><comma>but <congruent>333 and 222</congruent></comma> mod 111</error>")]
|
||||
public void TestEmphasis(string markdown, string expectedHtml)
|
||||
{
|
||||
TestParser.TestSpec(markdown, "<p>" + expectedHtml + "</p>", Pipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
using NUnit.Framework;
|
||||
using Markdig.Extensions.EmphasisExtras;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestEmphasisExtraOptions
|
||||
{
|
||||
[Test]
|
||||
public void OnlyStrikethrough_Single()
|
||||
{
|
||||
TestParser.TestSpec("~foo~", "<p>~foo~</p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Strikethrough).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnlyStrikethrough_Double()
|
||||
{
|
||||
TestParser.TestSpec("~~foo~~", "<p><del>foo</del></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Strikethrough).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnlySubscript_Single()
|
||||
{
|
||||
TestParser.TestSpec("~foo~", "<p><sub>foo</sub></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnlySubscript_Double()
|
||||
{
|
||||
TestParser.TestSpec("~~foo~~", "<p><sub><sub>foo</sub></sub></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SubscriptAndStrikethrough_Single()
|
||||
{
|
||||
TestParser.TestSpec("~foo~", "<p><sub>foo</sub></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Strikethrough | EmphasisExtraOptions.Subscript).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SubscriptAndStrikethrough_Double()
|
||||
{
|
||||
TestParser.TestSpec("~~foo~~", "<p><del>foo</del></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Strikethrough | EmphasisExtraOptions.Subscript).Build());
|
||||
}
|
||||
}
|
||||
using NUnit.Framework;
|
||||
using Markdig.Extensions.EmphasisExtras;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestEmphasisExtraOptions
|
||||
{
|
||||
[Test]
|
||||
public void OnlyStrikethrough_Single()
|
||||
{
|
||||
TestParser.TestSpec("~foo~", "<p>~foo~</p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Strikethrough).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnlyStrikethrough_Double()
|
||||
{
|
||||
TestParser.TestSpec("~~foo~~", "<p><del>foo</del></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Strikethrough).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnlySubscript_Single()
|
||||
{
|
||||
TestParser.TestSpec("~foo~", "<p><sub>foo</sub></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnlySubscript_Double()
|
||||
{
|
||||
TestParser.TestSpec("~~foo~~", "<p><sub><sub>foo</sub></sub></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Subscript).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SubscriptAndStrikethrough_Single()
|
||||
{
|
||||
TestParser.TestSpec("~foo~", "<p><sub>foo</sub></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Strikethrough | EmphasisExtraOptions.Subscript).Build());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SubscriptAndStrikethrough_Double()
|
||||
{
|
||||
TestParser.TestSpec("~~foo~~", "<p><del>foo</del></p>", new MarkdownPipelineBuilder().UseEmphasisExtras(EmphasisExtraOptions.Strikethrough | EmphasisExtraOptions.Subscript).Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
using NUnit.Framework;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestImageAltText
|
||||
{
|
||||
[Test]
|
||||
[TestCase("", "")]
|
||||
[TestCase("", "foo")]
|
||||
[TestCase("![][1]\n\n[1]: image.jpg", "")]
|
||||
[TestCase("![bar][1]\n\n[1]: image.jpg", "bar")]
|
||||
[TestCase("", "")]
|
||||
[TestCase("", "foo")]
|
||||
[TestCase("![][1]\n\n[1]: image.jpg 'title'", "")]
|
||||
[TestCase("![bar][1]\n\n[1]: image.jpg 'title'", "bar")]
|
||||
public void TestImageHtmlAltText(string markdown, string expectedAltText)
|
||||
{
|
||||
string html = Markdown.ToHtml(markdown);
|
||||
string actualAltText = Regex.Match(html, "alt=\"(.*?)\"").Groups[1].Value;
|
||||
Assert.AreEqual(expectedAltText, actualAltText);
|
||||
}
|
||||
}
|
||||
}
|
||||
using NUnit.Framework;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestImageAltText
|
||||
{
|
||||
[Test]
|
||||
[TestCase("", "")]
|
||||
[TestCase("", "foo")]
|
||||
[TestCase("![][1]\n\n[1]: image.jpg", "")]
|
||||
[TestCase("![bar][1]\n\n[1]: image.jpg", "bar")]
|
||||
[TestCase("", "")]
|
||||
[TestCase("", "foo")]
|
||||
[TestCase("![][1]\n\n[1]: image.jpg 'title'", "")]
|
||||
[TestCase("![bar][1]\n\n[1]: image.jpg 'title'", "bar")]
|
||||
public void TestImageHtmlAltText(string markdown, string expectedAltText)
|
||||
{
|
||||
string html = Markdown.ToHtml(markdown);
|
||||
string actualAltText = Regex.Match(html, "alt=\"(.*?)\"").Groups[1].Value;
|
||||
Assert.AreEqual(expectedAltText, actualAltText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using Markdig.Helpers;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using System.Security;
|
||||
using NUnit.Framework;
|
||||
using Markdig.Helpers;
|
||||
using Markdig.Syntax;
|
||||
@@ -16,8 +15,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlSimple()
|
||||
{
|
||||
var text = new StringSlice("toto tutu");
|
||||
string link;
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out link));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
Assert.AreEqual("toto", link);
|
||||
Assert.AreEqual(' ', text.CurrentChar);
|
||||
}
|
||||
@@ -26,8 +24,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlUrl()
|
||||
{
|
||||
var text = new StringSlice("http://google.com)");
|
||||
string link;
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out link));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
Assert.AreEqual("http://google.com", link);
|
||||
Assert.AreEqual(')', text.CurrentChar);
|
||||
}
|
||||
@@ -38,8 +35,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlTrailingFullStop(string uri)
|
||||
{
|
||||
var text = new StringSlice(uri);
|
||||
string link;
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out link, true));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _, true));
|
||||
Assert.AreEqual("http://google.com", link);
|
||||
Assert.AreEqual('.', text.CurrentChar);
|
||||
}
|
||||
@@ -48,8 +44,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlNestedParenthesis()
|
||||
{
|
||||
var text = new StringSlice("(toto)tutu(tata) nooo");
|
||||
string link;
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out link));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
Assert.AreEqual("(toto)tutu(tata)", link);
|
||||
Assert.AreEqual(' ', text.CurrentChar);
|
||||
}
|
||||
@@ -58,8 +53,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlAlternate()
|
||||
{
|
||||
var text = new StringSlice("<toto_tata_tutu> nooo");
|
||||
string link;
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out link));
|
||||
Assert.True(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
Assert.AreEqual("toto_tata_tutu", link);
|
||||
Assert.AreEqual(' ', text.CurrentChar);
|
||||
}
|
||||
@@ -68,16 +62,14 @@ namespace Markdig.Tests
|
||||
public void TestUrlAlternateInvalid()
|
||||
{
|
||||
var text = new StringSlice("<toto_tata_tutu");
|
||||
string link;
|
||||
Assert.False(LinkHelper.TryParseUrl(ref text, out link));
|
||||
Assert.False(LinkHelper.TryParseUrl(ref text, out string link, out _));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTitleSimple()
|
||||
{
|
||||
var text = new StringSlice(@"'tata\tutu\''");
|
||||
string title;
|
||||
Assert.True(LinkHelper.TryParseTitle(ref text, out title));
|
||||
Assert.True(LinkHelper.TryParseTitle(ref text, out string title, out _));
|
||||
Assert.AreEqual(@"tata\tutu'", title);
|
||||
}
|
||||
|
||||
@@ -85,8 +77,7 @@ namespace Markdig.Tests
|
||||
public void TestTitleSimpleAlternate()
|
||||
{
|
||||
var text = new StringSlice(@"""tata\tutu\"""" ");
|
||||
string title;
|
||||
Assert.True(LinkHelper.TryParseTitle(ref text, out title));
|
||||
Assert.True(LinkHelper.TryParseTitle(ref text, out string title, out _));
|
||||
Assert.AreEqual(@"tata\tutu""", title);
|
||||
Assert.AreEqual(' ', text.CurrentChar);
|
||||
}
|
||||
@@ -97,11 +88,7 @@ namespace Markdig.Tests
|
||||
// 0 1 2 3
|
||||
// 0123456789012345678901234567890123456789
|
||||
var text = new StringSlice(@"(http://google.com 'this is a title')ABC");
|
||||
string link;
|
||||
string title;
|
||||
SourceSpan linkSpan;
|
||||
SourceSpan titleSpan;
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out link, out title, out linkSpan, out titleSpan));
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out string link, out string title, out SourceSpan linkSpan, out SourceSpan titleSpan));
|
||||
Assert.AreEqual("http://google.com", link);
|
||||
Assert.AreEqual("this is a title", title);
|
||||
Assert.AreEqual(new SourceSpan(1, 17), linkSpan);
|
||||
@@ -114,11 +101,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
// 01234
|
||||
var text = new StringSlice(@"(<>)A");
|
||||
string link;
|
||||
string title;
|
||||
SourceSpan linkSpan;
|
||||
SourceSpan titleSpan;
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out link, out title, out linkSpan, out titleSpan));
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out string link, out string title, out SourceSpan linkSpan, out SourceSpan titleSpan));
|
||||
Assert.AreEqual(string.Empty, link);
|
||||
Assert.AreEqual(string.Empty, title);
|
||||
Assert.AreEqual(new SourceSpan(1, 2), linkSpan);
|
||||
@@ -131,11 +114,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
// 012345
|
||||
var text = new StringSlice(@"( <> )A");
|
||||
string link;
|
||||
string title;
|
||||
SourceSpan linkSpan;
|
||||
SourceSpan titleSpan;
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out link, out title, out linkSpan, out titleSpan));
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out string link, out string title, out SourceSpan linkSpan, out SourceSpan titleSpan));
|
||||
Assert.AreEqual(string.Empty, link);
|
||||
Assert.AreEqual(string.Empty, title);
|
||||
Assert.AreEqual(new SourceSpan(2, 3), linkSpan);
|
||||
@@ -150,11 +129,7 @@ namespace Markdig.Tests
|
||||
// 0 1 2
|
||||
// 0123456789012345678901234567
|
||||
var text = new StringSlice(@"( <> 'toto' )A");
|
||||
string link;
|
||||
string title;
|
||||
SourceSpan linkSpan;
|
||||
SourceSpan titleSpan;
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out link, out title, out linkSpan, out titleSpan));
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out string link, out string title, out SourceSpan linkSpan, out SourceSpan titleSpan));
|
||||
Assert.AreEqual(string.Empty, link);
|
||||
Assert.AreEqual("toto", title);
|
||||
Assert.AreEqual(new SourceSpan(4, 5), linkSpan);
|
||||
@@ -166,11 +141,7 @@ namespace Markdig.Tests
|
||||
public void TestUrlEmpty()
|
||||
{
|
||||
var text = new StringSlice(@"()A");
|
||||
string link;
|
||||
string title;
|
||||
SourceSpan linkSpan;
|
||||
SourceSpan titleSpan;
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out link, out title, out linkSpan, out titleSpan));
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out string link, out string title, out SourceSpan linkSpan, out SourceSpan titleSpan));
|
||||
Assert.AreEqual(string.Empty, link);
|
||||
Assert.AreEqual(string.Empty, title);
|
||||
Assert.AreEqual(SourceSpan.Empty, linkSpan);
|
||||
@@ -184,11 +155,7 @@ namespace Markdig.Tests
|
||||
// 0 1 2 3
|
||||
// 01 2345678901234567890 1234567890123456789
|
||||
var text = new StringSlice("(\n<http://google.com>\n 'toto' )A");
|
||||
string link;
|
||||
string title;
|
||||
SourceSpan linkSpan;
|
||||
SourceSpan titleSpan;
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out link, out title, out linkSpan, out titleSpan));
|
||||
Assert.True(LinkHelper.TryParseInlineLink(ref text, out string link, out string title, out SourceSpan linkSpan, out SourceSpan titleSpan));
|
||||
Assert.AreEqual("http://google.com", link);
|
||||
Assert.AreEqual("toto", title);
|
||||
Assert.AreEqual(new SourceSpan(2, 20), linkSpan);
|
||||
@@ -201,9 +168,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
// 01234
|
||||
var text = new StringSlice("[foo]");
|
||||
string label;
|
||||
SourceSpan labelSpan;
|
||||
Assert.True(LinkHelper.TryParseLabel(ref text, out label, out labelSpan));
|
||||
Assert.True(LinkHelper.TryParseLabel(ref text, out string label, out SourceSpan labelSpan));
|
||||
Assert.AreEqual(new SourceSpan(1, 3), labelSpan);
|
||||
Assert.AreEqual("foo", label);
|
||||
}
|
||||
@@ -213,9 +178,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
// 012345678
|
||||
var text = new StringSlice(@"[fo\[\]o]");
|
||||
string label;
|
||||
SourceSpan labelSpan;
|
||||
Assert.True(LinkHelper.TryParseLabel(ref text, out label, out labelSpan));
|
||||
Assert.True(LinkHelper.TryParseLabel(ref text, out string label, out SourceSpan labelSpan));
|
||||
Assert.AreEqual(new SourceSpan(1, 7), labelSpan);
|
||||
Assert.AreEqual(@"fo[]o", label);
|
||||
}
|
||||
@@ -225,9 +188,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
// 0123
|
||||
var text = new StringSlice(@"[\]]");
|
||||
string label;
|
||||
SourceSpan labelSpan;
|
||||
Assert.True(LinkHelper.TryParseLabel(ref text, out label, out labelSpan));
|
||||
Assert.True(LinkHelper.TryParseLabel(ref text, out string label, out SourceSpan labelSpan));
|
||||
Assert.AreEqual(new SourceSpan(1, 2), labelSpan);
|
||||
Assert.AreEqual(@"]", label);
|
||||
}
|
||||
@@ -235,8 +196,7 @@ namespace Markdig.Tests
|
||||
[Test]
|
||||
public void TestLabelInvalids()
|
||||
{
|
||||
string label;
|
||||
Assert.False(LinkHelper.TryParseLabel(new StringSlice(@"a"), out label));
|
||||
Assert.False(LinkHelper.TryParseLabel(new StringSlice(@"a"), out string label));
|
||||
Assert.False(LinkHelper.TryParseLabel(new StringSlice(@"["), out label));
|
||||
Assert.False(LinkHelper.TryParseLabel(new StringSlice(@"[\x]"), out label));
|
||||
Assert.False(LinkHelper.TryParseLabel(new StringSlice(@"[[]"), out label));
|
||||
@@ -250,9 +210,7 @@ namespace Markdig.Tests
|
||||
// 0 1 2 3
|
||||
// 0123456789012345678901234567890123456789
|
||||
var text = new StringSlice(@"[ fo o z ]");
|
||||
string label;
|
||||
SourceSpan labelSpan;
|
||||
Assert.True(LinkHelper.TryParseLabel(ref text, out label, out labelSpan));
|
||||
Assert.True(LinkHelper.TryParseLabel(ref text, out string label, out SourceSpan labelSpan));
|
||||
Assert.AreEqual(new SourceSpan(6, 17), labelSpan);
|
||||
Assert.AreEqual(@"fo o z", label);
|
||||
}
|
||||
@@ -263,13 +221,7 @@ namespace Markdig.Tests
|
||||
// 0 1 2 3
|
||||
// 0123456789012345678901234567890123456789
|
||||
var text = new StringSlice(@"[foo]: /toto 'title'");
|
||||
string label;
|
||||
string url;
|
||||
string title;
|
||||
SourceSpan labelSpan;
|
||||
SourceSpan urlSpan;
|
||||
SourceSpan titleSpan;
|
||||
Assert.True(LinkHelper.TryParseLinkReferenceDefinition(ref text, out label, out url, out title, out labelSpan, out urlSpan, out titleSpan));
|
||||
Assert.True(LinkHelper.TryParseLinkReferenceDefinition(ref text, out string label, out string url, out string title, out SourceSpan labelSpan, out SourceSpan urlSpan, out SourceSpan titleSpan));
|
||||
Assert.AreEqual(@"foo", label);
|
||||
Assert.AreEqual(@"/toto", url);
|
||||
Assert.AreEqual(@"title", title);
|
||||
@@ -283,9 +235,7 @@ namespace Markdig.Tests
|
||||
public void TestAutoLinkUrlSimple()
|
||||
{
|
||||
var text = new StringSlice(@"<http://google.com>");
|
||||
string url;
|
||||
bool isEmail;
|
||||
Assert.True(LinkHelper.TryParseAutolink(ref text, out url, out isEmail));
|
||||
Assert.True(LinkHelper.TryParseAutolink(ref text, out string url, out bool isEmail));
|
||||
Assert.False(isEmail);
|
||||
Assert.AreEqual("http://google.com", url);
|
||||
}
|
||||
@@ -294,9 +244,7 @@ namespace Markdig.Tests
|
||||
public void TestAutoLinkEmailSimple()
|
||||
{
|
||||
var text = new StringSlice(@"<user@host.com>");
|
||||
string email;
|
||||
bool isEmail;
|
||||
Assert.True(LinkHelper.TryParseAutolink(ref text, out email, out isEmail));
|
||||
Assert.True(LinkHelper.TryParseAutolink(ref text, out string email, out bool isEmail));
|
||||
Assert.True(isEmail);
|
||||
Assert.AreEqual("user@host.com", email);
|
||||
}
|
||||
@@ -304,9 +252,7 @@ namespace Markdig.Tests
|
||||
[Test]
|
||||
public void TestAutolinkInvalid()
|
||||
{
|
||||
string text;
|
||||
bool isEmail;
|
||||
Assert.False(LinkHelper.TryParseAutolink(new StringSlice(@""), out text, out isEmail));
|
||||
Assert.False(LinkHelper.TryParseAutolink(new StringSlice(@""), out string text, out bool isEmail));
|
||||
Assert.False(LinkHelper.TryParseAutolink(new StringSlice(@"<"), out text, out isEmail));
|
||||
Assert.False(LinkHelper.TryParseAutolink(new StringSlice(@"<ab"), out text, out isEmail));
|
||||
Assert.False(LinkHelper.TryParseAutolink(new StringSlice(@"<user@>"), out text, out isEmail));
|
||||
@@ -327,9 +273,9 @@ namespace Markdig.Tests
|
||||
[TestCase("[HTML], [S5], or [RTF]?", "html-s5-or-rtf")]
|
||||
[TestCase("3. Applications", "3-applications")]
|
||||
[TestCase("33", "33")]
|
||||
public void TestUrilizeGfm(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.UrilizeAsGfm(input));
|
||||
public void TestUrilizeGfm(string input, string expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, LinkHelper.UrilizeAsGfm(input));
|
||||
}
|
||||
|
||||
[TestCase("abc", "abc")]
|
||||
@@ -421,9 +367,9 @@ namespace Markdig.Tests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUnicodeInDomainNameOfLinkReferenceDefinition()
|
||||
{
|
||||
TestParser.TestSpec("[Foo]\n\n[Foo]: http://ünicode.com", "<p><a href=\"http://xn--nicode-2ya.com\">Foo</a></p>");
|
||||
public void TestUnicodeInDomainNameOfLinkReferenceDefinition()
|
||||
{
|
||||
TestParser.TestSpec("[Foo]\n\n[Foo]: http://ünicode.com", "<p><a href=\"http://xn--nicode-2ya.com\">Foo</a></p>");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,61 +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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,22 @@ namespace Markdig.Tests
|
||||
.Build();
|
||||
}
|
||||
|
||||
private MarkdownPipeline GetPipelineWithBootstrap(MediaOptions options = null)
|
||||
{
|
||||
return new MarkdownPipelineBuilder()
|
||||
.UseBootstrap()
|
||||
.UseMediaLinks(options)
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("", "<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"https://sample.com/video.mp4\"></source></video></p>\n")]
|
||||
[TestCase("", "<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n")]
|
||||
[TestCase(@"", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
[TestCase("", "<p><iframe src=\"https://music.yandex.ru/iframe/#track/4402274/411845/\" width=\"500\" height=\"281\" class=\"yandex\" frameborder=\"0\"></iframe></p>\n")]
|
||||
[TestCase("", "<p><iframe src=\"https://player.vimeo.com/video/8607834\" width=\"500\" height=\"281\" class=\"vimeo\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
[TestCase("", "<p><iframe src=\"https://ok.ru/videoembed/26870090463\" width=\"500\" height=\"281\" class=\"odnoklassniki\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
[TestCase("", "<p><iframe src=\"https://ok.ru/videoembed/26870090463\" width=\"500\" height=\"281\" class=\"odnoklassniki\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
[TestCase(@"", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
[TestCase("", "<p><iframe src=\"https://music.yandex.ru/iframe/#track/4402274/411845/\" class=\"yandex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n")]
|
||||
[TestCase("", "<p><iframe src=\"https://player.vimeo.com/video/8607834\" class=\"vimeo\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
[TestCase("", "<p><iframe src=\"https://ok.ru/videoembed/26870090463\" class=\"odnoklassniki\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
[TestCase("", "<p><iframe src=\"https://ok.ru/videoembed/26870090463\" class=\"odnoklassniki\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
public void TestBuiltInHosts(string markdown, string expected)
|
||||
{
|
||||
string html = Markdown.ToHtml(markdown, GetPipeline());
|
||||
@@ -55,9 +63,9 @@ namespace Markdig.Tests
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("", "<p><iframe src=\"https://example.com/video.mp4\" width=\"500\" height=\"281\" class=\"regex\" frameborder=\"0\"></iframe></p>\n", @"^https?://sample.com/(.+)$", @"https://example.com/$1")]
|
||||
[TestCase("", "<p><iframe src=\"https://example.com/video.mp4\" width=\"500\" height=\"281\" class=\"regex\" frameborder=\"0\"></iframe></p>\n", @"^//sample.com/(.+)$", @"https://example.com/$1")]
|
||||
[TestCase("", "<p><iframe src=\"https://example.com/video.mp4?token=aaabbb\" width=\"500\" height=\"281\" class=\"regex\" frameborder=\"0\"></iframe></p>\n", @"^https?://sample.com/(.+)$", @"https://example.com/$1?token=aaabbb")]
|
||||
[TestCase("", "<p><iframe src=\"https://example.com/video.mp4\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^https?://sample.com/(.+)$", @"https://example.com/$1")]
|
||||
[TestCase("", "<p><iframe src=\"https://example.com/video.mp4\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^//sample.com/(.+)$", @"https://example.com/$1")]
|
||||
[TestCase("", "<p><iframe src=\"https://example.com/video.mp4?token=aaabbb\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^https?://sample.com/(.+)$", @"https://example.com/$1?token=aaabbb")]
|
||||
public void TestCustomHostProvider(string markdown, string expected, string provider, string replace)
|
||||
{
|
||||
string html = Markdown.ToHtml(markdown, GetPipeline(new MediaOptions
|
||||
@@ -72,9 +80,9 @@ namespace Markdig.Tests
|
||||
|
||||
[Test]
|
||||
[TestCase("", "<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n", "")]
|
||||
[TestCase(@"", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n", "")]
|
||||
[TestCase("", "<p><video width=\"500\" height=\"281\" controls=\"\" class=\"k\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n", "k")]
|
||||
[TestCase(@"", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" width=\"500\" height=\"281\" class=\"k youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n", "k")]
|
||||
[TestCase(@"", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n", "")]
|
||||
[TestCase("", "<p><video class=\"k\" width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n", "k")]
|
||||
[TestCase(@"", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" class=\"k youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n", "k")]
|
||||
public void TestCustomClass(string markdown, string expected, string klass)
|
||||
{
|
||||
string html = Markdown.ToHtml(markdown, GetPipeline(new MediaOptions
|
||||
@@ -83,5 +91,14 @@ namespace Markdig.Tests
|
||||
}));
|
||||
Assert.AreEqual(html, expected);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("", "<p><video class=\"img-fluid\" width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n")]
|
||||
[TestCase(@"", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" class=\"img-fluid youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
|
||||
public void TestWithBootstrap(string markdown, string expected)
|
||||
{
|
||||
string html = Markdown.ToHtml(markdown, GetPipelineWithBootstrap());
|
||||
Assert.AreEqual(html, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17
src/Markdig.Tests/TestNewLine.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestNewLine
|
||||
{
|
||||
[TestCase("a \nb", "<p>a<br />\nb</p>\n")]
|
||||
[TestCase("a\\\nb", "<p>a<br />\nb</p>\n")]
|
||||
[TestCase("a `b\nc`", "<p>a <code>b c</code></p>\n")]
|
||||
public void Test(string value, string expectedHtml)
|
||||
{
|
||||
Assert.AreEqual(expectedHtml, Markdown.ToHtml(value));
|
||||
Assert.AreEqual(expectedHtml, Markdown.ToHtml(value.Replace("\n", "\r\n")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -1,190 +1,178 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Markdig.Extensions.JiraLinks;
|
||||
using Markdig.Syntax;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
public class TestParser
|
||||
{
|
||||
[Test]
|
||||
public void EnsureSpecsAreUpToDate()
|
||||
{
|
||||
// In CI, SpecFileGen is guaranteed to run
|
||||
if (IsContinuousIntegration)
|
||||
return;
|
||||
|
||||
foreach (var specFilePath in SpecsFilePaths)
|
||||
{
|
||||
string testFilePath = Path.ChangeExtension(specFilePath, ".generated.cs");
|
||||
|
||||
Assert.True(File.Exists(testFilePath),
|
||||
"A new specification file has been added. Add the spec to the list in SpecFileGen and regenerate the tests.");
|
||||
|
||||
DateTime specTime = File.GetLastWriteTimeUtc(specFilePath);
|
||||
DateTime testTime = File.GetLastWriteTimeUtc(testFilePath);
|
||||
|
||||
// If file creation times aren't preserved by git, add some leeway
|
||||
// If specs have come from git, assume that they were regenerated since CI would fail otherwise
|
||||
testTime = testTime.AddMinutes(3);
|
||||
|
||||
// This might not catch a changed spec every time, but should at least sometimes. Otherwise CI will catch it
|
||||
|
||||
// This could also trigger, if a user has modified the spec file but reverted the change - can't think of a good workaround
|
||||
Assert.Less(specTime, testTime,
|
||||
$"{Path.GetFileName(specFilePath)} has been modified. Run SpecFileGen to regenerate the tests. " +
|
||||
"If you have modified a specification file, but reverted all changes, ignore this error or revert the 'changed' timestamp metadata on the file.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestSpec(string inputText, string expectedOutputText, string extensions = null, bool plainText = false)
|
||||
{
|
||||
foreach (var pipeline in GetPipeline(extensions))
|
||||
{
|
||||
Console.WriteLine($"Pipeline configured with extensions: {pipeline.Key}");
|
||||
TestSpec(inputText, expectedOutputText, pipeline.Value, plainText);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestSpec(string inputText, string expectedOutputText, MarkdownPipeline pipeline, bool plainText = false)
|
||||
{
|
||||
// Uncomment this line to get more debug information for process inlines.
|
||||
//pipeline.DebugLog = Console.Out;
|
||||
var result = plainText ? Markdown.ToPlainText(inputText, pipeline) : Markdown.ToHtml(inputText, pipeline);
|
||||
|
||||
result = Compact(result);
|
||||
expectedOutputText = Compact(expectedOutputText);
|
||||
|
||||
PrintAssertExpected(inputText, result, expectedOutputText);
|
||||
}
|
||||
|
||||
public static void PrintAssertExpected(string source, string result, string expected)
|
||||
{
|
||||
Console.WriteLine("```````````````````Source");
|
||||
Console.WriteLine(DisplaySpaceAndTabs(source));
|
||||
Console.WriteLine("```````````````````Result");
|
||||
Console.WriteLine(DisplaySpaceAndTabs(result));
|
||||
Console.WriteLine("```````````````````Expected");
|
||||
Console.WriteLine(DisplaySpaceAndTabs(expected));
|
||||
Console.WriteLine("```````````````````");
|
||||
Console.WriteLine();
|
||||
TextAssert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
public static IEnumerable<KeyValuePair<string, MarkdownPipeline>> GetPipeline(string extensionsGroupText)
|
||||
{
|
||||
// For the standard case, we make sure that both the CommmonMark core and Extra/Advanced are CommonMark compliant!
|
||||
if (string.IsNullOrEmpty(extensionsGroupText))
|
||||
{
|
||||
yield return new KeyValuePair<string, MarkdownPipeline>("default", new MarkdownPipelineBuilder().Build());
|
||||
|
||||
yield return new KeyValuePair<string, MarkdownPipeline>("advanced", new MarkdownPipelineBuilder() // Use similar to advanced extension without auto-identifier
|
||||
.UseAbbreviations()
|
||||
//.UseAutoIdentifiers()
|
||||
.UseCitations()
|
||||
.UseCustomContainers()
|
||||
.UseDefinitionLists()
|
||||
.UseEmphasisExtras()
|
||||
.UseFigures()
|
||||
.UseFooters()
|
||||
.UseFootnotes()
|
||||
.UseGridTables()
|
||||
.UseMathematics()
|
||||
.UseMediaLinks()
|
||||
.UsePipeTables()
|
||||
.UseListExtras()
|
||||
.UseGenericAttributes().Build());
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
var extensionGroups = extensionsGroupText.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var extensionsText in extensionGroups)
|
||||
{
|
||||
var builder = new MarkdownPipelineBuilder();
|
||||
builder.DebugLog = Console.Out;
|
||||
if (extensionsText == "jiralinks")
|
||||
{
|
||||
builder.UseJiraLinks(new JiraLinkOptions("http://your.company.abc"));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder = extensionsText == "self" ? builder.UseSelfPipeline() : builder.Configure(extensionsText);
|
||||
}
|
||||
yield return new KeyValuePair<string, MarkdownPipeline>(extensionsText, builder.Build());
|
||||
}
|
||||
}
|
||||
|
||||
public static string DisplaySpaceAndTabs(string text)
|
||||
{
|
||||
// Output special characters to check correctly the results
|
||||
return text.Replace('\t', '→').Replace(' ', '·');
|
||||
}
|
||||
|
||||
private static string Compact(string html)
|
||||
{
|
||||
// Normalize the output to make it compatible with CommonMark specs
|
||||
html = html.Replace("\r\n", "\n").Replace(@"\r", @"\n").Trim();
|
||||
html = Regex.Replace(html, @"\s+</li>", "</li>");
|
||||
html = Regex.Replace(html, @"<li>\s+", "<li>");
|
||||
html = html.Normalize(NormalizationForm.FormKD);
|
||||
return html;
|
||||
}
|
||||
|
||||
public static readonly bool IsContinuousIntegration = Environment.GetEnvironmentVariable("CI") != null;
|
||||
|
||||
public static readonly string TestsDirectory =
|
||||
Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof(TestParser).Assembly.Location), "../../.."));
|
||||
|
||||
/// <summary>
|
||||
/// Contains absolute paths to specification markdown files (order is the same as in <see cref="SpecsMarkdown"/>)
|
||||
/// </summary>
|
||||
public static readonly string[] SpecsFilePaths;
|
||||
/// <summary>
|
||||
/// Contains the markdown source for specification files (order is the same as in <see cref="SpecsFilePaths"/>)
|
||||
/// </summary>
|
||||
public static readonly string[] SpecsMarkdown;
|
||||
/// <summary>
|
||||
/// Contains the markdown syntax tree for specification files (order is the same as in <see cref="SpecsFilePaths"/>)
|
||||
/// </summary>
|
||||
public static readonly MarkdownDocument[] SpecsSyntaxTrees;
|
||||
|
||||
static TestParser()
|
||||
{
|
||||
const string RunningInsideVisualStudioPath = "\\src\\.vs\\markdig\\";
|
||||
int index = TestsDirectory.IndexOf(RunningInsideVisualStudioPath);
|
||||
if (index != -1)
|
||||
{
|
||||
TestsDirectory = TestsDirectory.Substring(0, index) + "\\src\\Markdig.Tests";
|
||||
}
|
||||
|
||||
SpecsFilePaths = Directory.GetDirectories(TestsDirectory)
|
||||
.Where(dir => dir.EndsWith("Specs"))
|
||||
.SelectMany(dir => Directory.GetFiles(dir)
|
||||
.Where(file => file.EndsWith(".md", StringComparison.OrdinalIgnoreCase))
|
||||
.Where(file => file.IndexOf("readme", StringComparison.OrdinalIgnoreCase) == -1))
|
||||
.ToArray();
|
||||
|
||||
SpecsMarkdown = new string[SpecsFilePaths.Length];
|
||||
SpecsSyntaxTrees = new MarkdownDocument[SpecsFilePaths.Length];
|
||||
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.UseAdvancedExtensions()
|
||||
.Build();
|
||||
|
||||
for (int i = 0; i < SpecsFilePaths.Length; i++)
|
||||
{
|
||||
string markdown = SpecsMarkdown[i] = File.ReadAllText(SpecsFilePaths[i]);
|
||||
SpecsSyntaxTrees[i] = Markdown.Parse(markdown, pipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Markdig.Extensions.JiraLinks;
|
||||
using Markdig.Syntax;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
public class TestParser
|
||||
{
|
||||
[Test]
|
||||
public void EnsureSpecsAreUpToDate()
|
||||
{
|
||||
// In CI, SpecFileGen is guaranteed to run
|
||||
if (IsContinuousIntegration)
|
||||
return;
|
||||
|
||||
var specsFilePaths = Directory.GetDirectories(TestsDirectory)
|
||||
.Where(dir => dir.EndsWith("Specs"))
|
||||
.SelectMany(dir => Directory.GetFiles(dir)
|
||||
.Where(file => file.EndsWith(".md", StringComparison.OrdinalIgnoreCase))
|
||||
.Where(file => file.IndexOf("readme", StringComparison.OrdinalIgnoreCase) == -1))
|
||||
.ToArray();
|
||||
|
||||
var specsMarkdown = new string[specsFilePaths.Length];
|
||||
var specsSyntaxTrees = new MarkdownDocument[specsFilePaths.Length];
|
||||
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.UseAdvancedExtensions()
|
||||
.Build();
|
||||
|
||||
for (int i = 0; i < specsFilePaths.Length; i++)
|
||||
{
|
||||
string markdown = specsMarkdown[i] = File.ReadAllText(specsFilePaths[i]);
|
||||
specsSyntaxTrees[i] = Markdown.Parse(markdown, pipeline);
|
||||
}
|
||||
|
||||
foreach (var specFilePath in specsFilePaths)
|
||||
{
|
||||
string testFilePath = Path.ChangeExtension(specFilePath, ".generated.cs");
|
||||
|
||||
Assert.True(File.Exists(testFilePath),
|
||||
"A new specification file has been added. Add the spec to the list in SpecFileGen and regenerate the tests.");
|
||||
|
||||
DateTime specTime = File.GetLastWriteTimeUtc(specFilePath);
|
||||
DateTime testTime = File.GetLastWriteTimeUtc(testFilePath);
|
||||
|
||||
// If file creation times aren't preserved by git, add some leeway
|
||||
// If specs have come from git, assume that they were regenerated since CI would fail otherwise
|
||||
testTime = testTime.AddMinutes(3);
|
||||
|
||||
// This might not catch a changed spec every time, but should at least sometimes. Otherwise CI will catch it
|
||||
|
||||
// This could also trigger, if a user has modified the spec file but reverted the change - can't think of a good workaround
|
||||
Assert.Less(specTime, testTime,
|
||||
$"{Path.GetFileName(specFilePath)} has been modified. Run SpecFileGen to regenerate the tests. " +
|
||||
"If you have modified a specification file, but reverted all changes, ignore this error or revert the 'changed' timestamp metadata on the file.");
|
||||
}
|
||||
|
||||
TestDescendantsOrder.TestSchemas(specsSyntaxTrees);
|
||||
}
|
||||
|
||||
public static void TestSpec(string inputText, string expectedOutputText, string extensions = null, bool plainText = false)
|
||||
{
|
||||
foreach (var pipeline in GetPipeline(extensions))
|
||||
{
|
||||
Console.WriteLine($"Pipeline configured with extensions: {pipeline.Key}");
|
||||
TestSpec(inputText, expectedOutputText, pipeline.Value, plainText);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestSpec(string inputText, string expectedOutputText, MarkdownPipeline pipeline, bool plainText = false)
|
||||
{
|
||||
// Uncomment this line to get more debug information for process inlines.
|
||||
//pipeline.DebugLog = Console.Out;
|
||||
var result = plainText ? Markdown.ToPlainText(inputText, pipeline) : Markdown.ToHtml(inputText, pipeline);
|
||||
|
||||
result = Compact(result);
|
||||
expectedOutputText = Compact(expectedOutputText);
|
||||
|
||||
PrintAssertExpected(inputText, result, expectedOutputText);
|
||||
}
|
||||
|
||||
public static void PrintAssertExpected(string source, string result, string expected)
|
||||
{
|
||||
Console.WriteLine("```````````````````Source");
|
||||
Console.WriteLine(DisplaySpaceAndTabs(source));
|
||||
Console.WriteLine("```````````````````Result");
|
||||
Console.WriteLine(DisplaySpaceAndTabs(result));
|
||||
Console.WriteLine("```````````````````Expected");
|
||||
Console.WriteLine(DisplaySpaceAndTabs(expected));
|
||||
Console.WriteLine("```````````````````");
|
||||
Console.WriteLine();
|
||||
TextAssert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
public static IEnumerable<KeyValuePair<string, MarkdownPipeline>> GetPipeline(string extensionsGroupText)
|
||||
{
|
||||
// For the standard case, we make sure that both the CommmonMark core and Extra/Advanced are CommonMark compliant!
|
||||
if (string.IsNullOrEmpty(extensionsGroupText))
|
||||
{
|
||||
yield return new KeyValuePair<string, MarkdownPipeline>("default", new MarkdownPipelineBuilder().Build());
|
||||
|
||||
yield return new KeyValuePair<string, MarkdownPipeline>("advanced", new MarkdownPipelineBuilder() // Use similar to advanced extension without auto-identifier
|
||||
.UseAbbreviations()
|
||||
//.UseAutoIdentifiers()
|
||||
.UseCitations()
|
||||
.UseCustomContainers()
|
||||
.UseDefinitionLists()
|
||||
.UseEmphasisExtras()
|
||||
.UseFigures()
|
||||
.UseFooters()
|
||||
.UseFootnotes()
|
||||
.UseGridTables()
|
||||
.UseMathematics()
|
||||
.UseMediaLinks()
|
||||
.UsePipeTables()
|
||||
.UseListExtras()
|
||||
.UseGenericAttributes().Build());
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
var extensionGroups = extensionsGroupText.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var extensionsText in extensionGroups)
|
||||
{
|
||||
var builder = new MarkdownPipelineBuilder();
|
||||
builder.DebugLog = Console.Out;
|
||||
if (extensionsText == "jiralinks")
|
||||
{
|
||||
builder.UseJiraLinks(new JiraLinkOptions("http://your.company.abc"));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder = extensionsText == "self" ? builder.UseSelfPipeline() : builder.Configure(extensionsText);
|
||||
}
|
||||
yield return new KeyValuePair<string, MarkdownPipeline>(extensionsText, builder.Build());
|
||||
}
|
||||
}
|
||||
|
||||
public static string DisplaySpaceAndTabs(string text)
|
||||
{
|
||||
// Output special characters to check correctly the results
|
||||
return text.Replace('\t', '→').Replace(' ', '·');
|
||||
}
|
||||
|
||||
private static string Compact(string html)
|
||||
{
|
||||
// Normalize the output to make it compatible with CommonMark specs
|
||||
html = html.Replace("\r\n", "\n").Replace(@"\r", @"\n").Trim();
|
||||
html = Regex.Replace(html, @"\s+</li>", "</li>");
|
||||
html = Regex.Replace(html, @"<li>\s+", "<li>");
|
||||
html = html.Normalize(NormalizationForm.FormKD);
|
||||
return html;
|
||||
}
|
||||
|
||||
public static readonly bool IsContinuousIntegration = Environment.GetEnvironmentVariable("CI") != null;
|
||||
|
||||
public static readonly string TestsDirectory = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof(TestParser).Assembly.Location), "../../.."));
|
||||
|
||||
static TestParser()
|
||||
{
|
||||
const string RunningInsideVisualStudioPath = "\\src\\.vs\\markdig\\";
|
||||
int index = TestsDirectory.IndexOf(RunningInsideVisualStudioPath);
|
||||
if (index != -1)
|
||||
{
|
||||
TestsDirectory = TestsDirectory.Substring(0, index) + "\\src\\Markdig.Tests";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
@@ -35,9 +36,9 @@ namespace Markdig.Tests
|
||||
TestParser.TestSpec(markdownText, expected, extensions, plainText: true);
|
||||
}
|
||||
|
||||
public static void TestSpec(string markdownText, string expected, string extensions)
|
||||
{
|
||||
TestParser.TestSpec(markdownText, expected, extensions, plainText: true);
|
||||
public static void TestSpec(string markdownText, string expected, string extensions)
|
||||
{
|
||||
TestParser.TestSpec(markdownText, expected, extensions, plainText: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using Markdig.Renderers;
|
||||
using Markdig.Syntax;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
57
src/Markdig.Tests/TestReferralLinks.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestReferralLinks
|
||||
{
|
||||
[Test]
|
||||
public void TestLinksWithNoFollowRel()
|
||||
{
|
||||
var markdown = "[world](http://example.com)";
|
||||
var expected = "nofollow";
|
||||
|
||||
#pragma warning disable 0618
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.UseNoFollowLinks()
|
||||
#pragma warning restore 0618
|
||||
.Build();
|
||||
var html = Markdown.ToHtml(markdown, pipeline);
|
||||
|
||||
Assert.That(html, Contains.Substring($"rel=\"{expected}\""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(new[] { "nofollow" }, "nofollow")]
|
||||
[TestCase(new[] { "noopener" }, "noopener")]
|
||||
[TestCase(new[] { "nofollow", "noopener"}, "nofollow noopener")]
|
||||
public void TestLinksWithCustomRel(string[] rels, string expected)
|
||||
{
|
||||
var markdown = "[world](http://example.com)";
|
||||
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.UseReferralLinks(rels)
|
||||
.Build();
|
||||
var html = Markdown.ToHtml(markdown, pipeline);
|
||||
|
||||
Assert.That(html, Contains.Substring($"rel=\"{expected}\""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(new[] { "noopener" }, "noopener")]
|
||||
[TestCase(new[] { "nofollow" }, "nofollow")]
|
||||
[TestCase(new[] { "nofollow", "noopener" }, "nofollow noopener")]
|
||||
public void TestAutoLinksWithCustomRel(string[] rels, string expected)
|
||||
{
|
||||
var markdown = "http://example.com";
|
||||
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.UseAutoLinks()
|
||||
.UseReferralLinks(rels)
|
||||
.Build();
|
||||
var html = Markdown.ToHtml(markdown, pipeline);
|
||||
|
||||
Assert.That(html, Contains.Substring($"rel=\"{expected}\""));
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,48 +140,48 @@ literal ( 0, 2) 2-3
|
||||
emphasis ( 0, 4) 4-9
|
||||
literal ( 0, 6) 6-7
|
||||
");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFootnoteLinkReferenceDefinition()
|
||||
public void TestFootnoteLinkReferenceDefinition()
|
||||
{
|
||||
// 01 2 345678
|
||||
var footnote = Markdown.Parse("0\n\n [^1]:", new MarkdownPipelineBuilder().UsePreciseSourceLocation().UseFootnotes().Build()).Descendants<FootnoteLinkReferenceDefinition>().FirstOrDefault();
|
||||
Assert.NotNull(footnote);
|
||||
|
||||
Assert.AreEqual(2, footnote.Line);
|
||||
Assert.NotNull(footnote);
|
||||
|
||||
Assert.AreEqual(2, footnote.Line);
|
||||
Assert.AreEqual(new SourceSpan(4, 7), footnote.Span);
|
||||
Assert.AreEqual(new SourceSpan(5, 6), footnote.LabelSpan);
|
||||
}
|
||||
|
||||
Assert.AreEqual(new SourceSpan(5, 6), footnote.LabelSpan);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLinkReferenceDefinition1()
|
||||
public void TestLinkReferenceDefinition1()
|
||||
{
|
||||
// 0 1
|
||||
// 0123456789012345
|
||||
var link = Markdown.Parse("[234]: /56 'yo' ", new MarkdownPipelineBuilder().UsePreciseSourceLocation().Build()).Descendants<LinkReferenceDefinition>().FirstOrDefault();
|
||||
Assert.NotNull(link);
|
||||
|
||||
Assert.AreEqual(0, link.Line);
|
||||
Assert.NotNull(link);
|
||||
|
||||
Assert.AreEqual(0, link.Line);
|
||||
Assert.AreEqual(new SourceSpan(0, 14), link.Span);
|
||||
Assert.AreEqual(new SourceSpan(1, 3), link.LabelSpan);
|
||||
Assert.AreEqual(new SourceSpan(7, 9), link.UrlSpan);
|
||||
Assert.AreEqual(new SourceSpan(11, 14), link.TitleSpan);
|
||||
Assert.AreEqual(new SourceSpan(11, 14), link.TitleSpan);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLinkReferenceDefinition2()
|
||||
public void TestLinkReferenceDefinition2()
|
||||
{
|
||||
// 0 1
|
||||
// 01 2 34567890123456789
|
||||
var link = Markdown.Parse("0\n\n [234]: /56 'yo' ", new MarkdownPipelineBuilder().UsePreciseSourceLocation().Build()).Descendants<LinkReferenceDefinition>().FirstOrDefault();
|
||||
Assert.NotNull(link);
|
||||
|
||||
Assert.AreEqual(2, link.Line);
|
||||
Assert.NotNull(link);
|
||||
|
||||
Assert.AreEqual(2, link.Line);
|
||||
Assert.AreEqual(new SourceSpan(4, 18), link.Span);
|
||||
Assert.AreEqual(new SourceSpan(5, 7), link.LabelSpan);
|
||||
Assert.AreEqual(new SourceSpan(11, 13), link.UrlSpan);
|
||||
Assert.AreEqual(new SourceSpan(15, 18), link.TitleSpan);
|
||||
Assert.AreEqual(new SourceSpan(15, 18), link.TitleSpan);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -395,42 +395,42 @@ listitem ( 1, 0) 4-6
|
||||
paragraph ( 1, 2) 6-6
|
||||
literal ( 1, 2) 6-6
|
||||
");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestListBlock2()
|
||||
public void TestListBlock2()
|
||||
{
|
||||
string test = @"
|
||||
1. Foo
|
||||
9. Bar
|
||||
5. Foo
|
||||
6. Bar
|
||||
1. Foo
|
||||
9. Bar
|
||||
5. Foo
|
||||
6. Bar
|
||||
987123. FooBar";
|
||||
test = test.Replace("\r\n", "\n");
|
||||
var list = Markdown.Parse(test, new MarkdownPipelineBuilder().UsePreciseSourceLocation().Build()).Descendants<ListBlock>().FirstOrDefault();
|
||||
Assert.NotNull(list);
|
||||
|
||||
Assert.AreEqual(1, list.Line);
|
||||
Assert.True(list.IsOrdered);
|
||||
List<ListItemBlock> items = list.Cast<ListItemBlock>().ToList();
|
||||
Assert.AreEqual(5, items.Count);
|
||||
|
||||
// Test orders
|
||||
Assert.AreEqual(1, items[0].Order);
|
||||
Assert.NotNull(list);
|
||||
|
||||
Assert.AreEqual(1, list.Line);
|
||||
Assert.True(list.IsOrdered);
|
||||
List<ListItemBlock> items = list.Cast<ListItemBlock>().ToList();
|
||||
Assert.AreEqual(5, items.Count);
|
||||
|
||||
// Test orders
|
||||
Assert.AreEqual(1, items[0].Order);
|
||||
Assert.AreEqual(9, items[1].Order);
|
||||
Assert.AreEqual(5, items[2].Order);
|
||||
Assert.AreEqual(6, items[3].Order);
|
||||
Assert.AreEqual(987123, items[4].Order);
|
||||
|
||||
// Test positions
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert.AreEqual(i + 1, items[i].Line);
|
||||
Assert.AreEqual(1 + (i * 7), items[i].Span.Start);
|
||||
Assert.AreEqual(6, items[i].Span.Length);
|
||||
}
|
||||
Assert.AreEqual(5, items[4].Line);
|
||||
Assert.AreEqual(new SourceSpan(29, 42), items[4].Span);
|
||||
Assert.AreEqual(987123, items[4].Order);
|
||||
|
||||
// Test positions
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert.AreEqual(i + 1, items[i].Line);
|
||||
Assert.AreEqual(1 + (i * 7), items[i].Span.Start);
|
||||
Assert.AreEqual(6, items[i].Span.Length);
|
||||
}
|
||||
Assert.AreEqual(5, items[4].Line);
|
||||
Assert.AreEqual(new SourceSpan(29, 42), items[4].Span);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Markdig.Helpers;
|
||||
using Markdig.Syntax;
|
||||
using System;
|
||||
|
||||
namespace Markdig.Tests
|
||||
@@ -18,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")
|
||||
};
|
||||
|
||||
@@ -37,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 }
|
||||
};
|
||||
|
||||
@@ -63,7 +61,7 @@ namespace Markdig.Tests
|
||||
{
|
||||
var text = new StringLineGroup(4)
|
||||
{
|
||||
new StringSlice("ABCD"),
|
||||
new StringSlice("ABCD", NewLine.LineFeed),
|
||||
new StringSlice("EF"),
|
||||
}.ToCharIterator();
|
||||
|
||||
@@ -101,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();
|
||||
|
||||
@@ -117,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();
|
||||
|
||||
@@ -135,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();
|
||||
|
||||
@@ -155,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||