Compare commits

...

408 Commits

Author SHA1 Message Date
Alexandre Mutel
983187eace Fix emphasis when EnableTrackTrivia() is used (#561) 2022-03-11 08:16:42 +01:00
Alexandre Mutel
94581d9655 Try to workaround track trivia not generating valid HTML (#561) 2022-03-10 09:36:24 +01:00
Alexandre Mutel
6aebd68413 Fix specfilegen 2022-03-10 09:35:08 +01:00
Alexandre Mutel
a3f21b7639 Merge pull request #600 from gauss-lvs/master
Version "Unknown" if AssemblyFileVersionAttribute is missing
2022-03-03 18:43:54 +01:00
Patrick
653c9d7f16 Version returns "Unknown" if the AssemblyFileVersionAttribute is not found. 2022-03-02 09:09:59 +01:00
Alexandre Mutel
9bbf6855e1 Use bash with dotnet-releaser in GitHub Action 2022-03-01 08:27:16 +01:00
Alexandre Mutel
28f5503cfe Fix ci with dotnet-releaser when secrets are not available (bis) 2022-02-28 22:17:49 +01:00
Alexandre Mutel
ba990c739e Fix ci with dotnet-releaser when secrets are not available 2022-02-28 21:43:54 +01:00
Alexandre Mutel
0c45e19723 Remove logs from tests if no errors 2022-02-28 09:47:11 +01:00
Alexandre Mutel
73b8bbe1c7 Update ci to use dotnet-releaser 2022-02-28 09:18:40 +01:00
Alexandre Mutel
996b04cadb Merge pull request #593 from tibel/define-NETCORE-removed
remove NETCORE constant
2022-02-05 14:38:17 +01:00
Thomas Ibel
e7d7cbe010 remove NETCORE constant
and replace by NETSTANDARD2_1_OR_GREATER and NETCOREAPP3_1_OR_GREATER
2022-02-05 07:19:49 +01:00
Alexandre Mutel
ff89b48c33 Merge pull request #591 from carbon/net60
Drop .netcoreapp2.1 target and cross target .net6.0
2022-01-30 18:36:39 +01:00
Jason Nelson
58de5dbcea Update build note 2022-01-28 11:53:06 -08:00
Jason Nelson
fbd7d83cda Future proof NETCORE pragmas 2022-01-28 11:50:34 -08:00
Jason Nelson
13a9c066f7 Use built-in MemberNotNullAttribute on NET5.0+ 2022-01-28 11:47:05 -08:00
Jason Nelson
b7be61a914 Remove NETCOREAPP2_1 conditions 2022-01-27 19:56:53 -08:00
Jason Nelson
c212f9efa8 Use C# 10 2022-01-27 19:56:19 -08:00
Jason Nelson
e0961d7e86 Run benchmarks against net6.0 2022-01-27 19:53:54 -08:00
Jason Nelson
c67a802e69 Drop netcoreapp2.1 target and cross-target net6.0 2022-01-27 19:52:41 -08:00
Alexandre Mutel
5e3527b7d2 Bump to 0.27.0 2022-01-23 16:10:37 +01:00
Alexandre Mutel
d56e080fd7 Merge pull request #590 from yufeih/bug-crlf-link
Fix link reference definition parse bug with title and CRLF
2022-01-23 16:05:02 +01:00
Yufei Huang
d807255e13 Fix link reference definition parse bug with title and CRLF 2022-01-21 23:37:27 +08:00
Alexandre Mutel
029da6c99b Merge pull request #587 from wbaldoumas/add_markdown_colorcode
Add Markdown.ColorCode to README
2022-01-20 13:29:33 +01:00
Alexandre Mutel
b59c9e8925 Merge pull request #586 from tibel/feature/net6.0
.NET 6.0
2022-01-20 13:29:18 +01:00
Alexandre Mutel
22662b248d Update src/global.json 2022-01-20 12:50:58 +01:00
William Baldoumas
9d51ab176c Add Markdown.ColorCode 2022-01-19 21:37:52 -05:00
Thomas Ibel
584378967d fix build warnings 2022-01-19 20:12:41 +01:00
Thomas Ibel
f553bdd4c7 use await for http client 2022-01-19 19:18:46 +01:00
Thomas Ibel
16d77b7bb8 fix github action version 2022-01-19 18:46:54 +01:00
Thomas Ibel
d267cbe173 update github actions 2022-01-19 18:40:19 +01:00
Thomas Ibel
f54944962f update test and benchmark dependencies 2022-01-19 18:32:17 +01:00
Thomas Ibel
5a54af1235 fix warnings 2022-01-19 18:05:28 +01:00
Thomas Ibel
4567d86c15 use .NET 6.0 SDK 2022-01-19 18:01:30 +01:00
Alexandre Mutel
2b6dde9415 Merge pull request #576 from SimonCropp/patch-1
Strike.V8 is deprecated
2021-11-26 08:11:18 +01:00
Simon Cropp
ea8d9b608a Strike.V8 is deprecated 2021-11-15 13:53:50 +11:00
Alexandre Mutel
1469cc8fdb Merge pull request #575 from boxofyellow/master
Fix typo in EmphasisExtraOptions descriptions
2021-10-31 09:14:13 +01:00
Alexandre Mutel
daf2171366 Update src/Markdig/Extensions/EmphasisExtras/EmphasisExtraOptions.cs
Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
2021-10-31 08:54:20 +01:00
Alexandre Mutel
63a9f2406b Update src/Markdig/Extensions/EmphasisExtras/EmphasisExtraOptions.cs
Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
2021-10-31 08:54:12 +01:00
boxofyellow
fd100d1796 Fix typos in EmphasisExtraOptions descriptions 2021-10-30 14:55:59 -04:00
Alexandre Mutel
2c5a51d89b Merge pull request #572 from flcdrg/patch-1
Fix named parameter syntax
2021-09-16 06:21:45 +02:00
Alexandre Mutel
28db7fbd6b Merge pull request #573 from lajjne/target-blank
Fixes #571
2021-09-16 06:21:14 +02:00
Linus Birgerstam
56470a72a8 Fixes #571 2021-09-15 20:08:17 +02:00
David Gardiner
6b163a50c3 Fix named parameter syntax 2021-09-14 18:40:25 +09:30
Alexandre Mutel
c0ee97a803 Bump to 0.26.0 2021-08-27 20:34:30 +02:00
Alexandre Mutel
63ce549ea2 Merge pull request #570 from Sleepyowl/master
Fixes xoofx/markdig#567
2021-08-27 20:24:45 +02:00
Dmtry Soloviev
0faf0ef430 Make Mathematics extension respect EnableHtml* options 2021-08-24 23:03:02 +02:00
Alexandre Mutel
cdd4b40469 Merge pull request #560 from yufeih/yufeih/fix-crlf
Fix rendering diff between line endings
2021-07-06 18:36:32 +02:00
Yufei Huang
54d85ebac6 Fix rendering diff between line endings 2021-06-29 16:18:42 +08:00
Alexandre Mutel
64875c3dd9 Bump to 0.25.0 2021-06-10 09:02:03 +02:00
Alexandre Mutel
4c92fe5a3b Fix regression when parsing link reference definitions (#543) 2021-06-10 08:58:53 +02:00
Alexandre Mutel
27f625f15b Merge pull request #548 from Mysteryduck001/master
JiraLinkInlineParser.cs - Make digits in JiraKey's posible
2021-05-08 12:01:32 +02:00
Mysteryduck001
aca085703e JiraLinks.Generated.cs - add test for JiraKey's starting with a digit (not allowed) 2021-05-03 17:28:11 +02:00
Mysteryduck001
8aa0948b20 JiraLinkInlineParser.cs - prevent Jira key's to start with a digit 2021-05-03 17:22:13 +02:00
Mysteryduck001
8ce6f4d9ad JiraLinks.md - Do not allow a digit to be the first Char of the Key 2021-05-03 17:18:36 +02:00
Mysteryduck001
3a47a5115a JiraLinks.generated.cs - updated tests for JiraLink 2021-05-03 17:14:25 +02:00
Mysteryduck001
a8737e8481 JiraLinks.md - add examples with JiraKeys using Digits 2021-05-03 17:03:31 +02:00
Mysteryduck001
f56b8e6ba7 JiraLinkInlineParser.cs - Make digits in JiraKey's posible 2021-05-03 16:32:08 +02:00
Alexandre Mutel
0a0040450f Merge pull request #544 from generateui/fix_535
ignore whitespace at end of pipe table row header
2021-04-14 16:38:40 +02:00
Alexandre Mutel
fb12be5ab0 Merge pull request #540 from MihaZupan/coverage-link
Update coverage badge link
2021-04-13 07:35:27 +02:00
Ruud Poutsma
2277596e2e ignore whitespace at end of pipe table row header 2021-04-10 17:59:32 +02:00
MihaZupan
a10f6f6b8c Update coverage badge link 2021-04-07 00:18:57 +02:00
Alexandre Mutel
203cfd6508 Bump to 0.24.0 2021-03-20 08:47:20 +01:00
Alexandre Mutel
5fefcbb5b3 Merge pull request #530 from carbon/cq
Improve Code Quality
2021-03-15 20:40:54 +01:00
Alexandre Mutel
7ad7b55c48 Merge pull request #529 from MihaZupan/cache-parsers
Cache the MarkdownParser & Processors
2021-03-15 06:34:36 +01:00
Alexandre Mutel
e9ea103e32 Merge pull request #532 from MihaZupan/more-allocs
Avoid char[] & string allocations in HtmlBlockParser
2021-03-15 06:33:02 +01:00
Alexandre Mutel
c680910828 Merge pull request #531 from MihaZupan/random-perf-3
A handful of codegen improvements
2021-03-15 06:32:26 +01:00
Jason Nelson
4526d886c8 Use WriteLine char overload 2021-03-14 09:24:09 -07:00
Jason Nelson
397de86e2f Remove obvious parameter label 2021-03-14 09:15:41 -07:00
MihaZupan
f985750b82 Don't use the Roundtrip InfoParser by default 2021-03-14 11:21:34 +01:00
MihaZupan
00c175a79c Remove char[], string allocations in HtmlBlockParser 2021-03-14 11:21:14 +01:00
MihaZupan
6204095261 Remove static ctor from CharNormalizer 2021-03-14 04:13:27 +01:00
MihaZupan
63fddf4511 Add quick range check in CharNormalizer 2021-03-14 04:10:58 +01:00
MihaZupan
c964659085 Optimize Globalization StartsWithRtlCharacter check 2021-03-14 03:56:36 +01:00
MihaZupan
eabfe74e92 Avoid struct copy in Roundtrip CodeBlockRenderer 2021-03-14 03:17:59 +01:00
MihaZupan
bd1dcd952c Improve HtmlHelper 2021-03-14 03:06:47 +01:00
MihaZupan
54e2514778 Avoid struct copies in StringLineGroup 2021-03-14 02:31:08 +01:00
MihaZupan
4b7a4d21de Optimize NewLine.Length() 2021-03-14 02:07:45 +01:00
MihaZupan
6b1399ba23 Use IsEmpty instead of Length == 0 or CurrentChar == '\0' 2021-03-14 02:00:37 +01:00
MihaZupan
07467d6c30 Add ICharIterator SkipChar and PeekChar
PeekChar() already existed on StringSlice, but not on the interface, so it wasn't always getting used
2021-03-14 01:50:56 +01:00
MihaZupan
2f9588498c Add missing null check 2021-03-13 20:44:55 +01:00
MihaZupan
80ed85e2a8 Cache the MarkdownParser & Processors 2021-03-13 20:41:35 +01:00
Jason Nelson
b2306db388 Make CodeInline.Content nonnull 2021-03-12 11:31:11 -08:00
Jason Nelson
8db238797b Enable nullable on AutolinkInline 2021-03-12 11:29:53 -08:00
Jason Nelson
780e16a9c9 Simplify list initialization 2021-03-12 11:28:05 -08:00
Jason Nelson
8fdc0d59d7 Format TableState 2021-03-12 11:21:15 -08:00
Jason Nelson
f1cd0cb1b8 Enable nullable on CharacterMap 2021-03-12 11:20:57 -08:00
Jason Nelson
a724783e3f CodeBlockLines is always defined. Remove lazy initializer 2021-03-12 11:20:42 -08:00
Jason Nelson
1c862a1e07 Remove unused using statement 2021-03-12 11:10:17 -08:00
Jason Nelson
35d3160ad2 Eliminate a few allocations to hold indents 2021-03-12 11:09:53 -08:00
Jason Nelson
e0a2f9e52d Add notes on why we continue to support net452 2021-03-12 11:05:54 -08:00
Jason Nelson
c9ba236dbc Write chars, instead of strings, where possible 2021-03-12 11:01:06 -08:00
Jason Nelson
0c9b5dddc9 Use is (not) pattern to match constant strings 2021-03-12 10:50:18 -08:00
Jason Nelson
bd2bb98631 Compare strings using StringComparison.Ordinal 2021-03-12 10:49:26 -08:00
Alexandre Mutel
da0ba34165 Merge pull request #527 from MihaZupan/last-nullable
A few nullable changes
2021-03-12 06:08:54 +01:00
MihaZupan
51c5bec315 A few nullable changes 2021-03-11 20:56:55 +01:00
Alexandre Mutel
13bdab4570 Merge pull request #526 from carbon/nullability2
Complete nullable annotations
2021-03-11 20:20:50 +01:00
Jason Nelson
6b9433c7d8 Remove temporary #nullable enable directives 2021-03-11 10:41:14 -08:00
Jason Nelson
eedbb494fc Revert accidental readonly removal 2021-03-11 10:27:02 -08:00
Jason Nelson
9d36a74312 Replace == null with is null 2021-03-10 22:45:49 -08:00
Jason Nelson
4009c89321 Enable nullable at project level and add remaining nullable annotations 2021-03-10 22:44:42 -08:00
Alexandre Mutel
6b433d9352 Merge pull request #525 from carbon/nullability2
Enable nullability, round 3 of x
2021-03-11 07:05:12 +01:00
Jason Nelson
f6e6001d94 Remove unnecessary suppression 2021-03-10 18:18:41 -08:00
Jason Nelson
1474b7b29a Fix default NewLine 2021-03-10 15:28:31 -08:00
Jason Nelson
61b29b6d41 Fix incorrect logic 2021-03-10 15:20:43 -08:00
Jason Nelson
6684c8257c Enable nullable, round 3 2021-03-10 15:12:30 -08:00
Alexandre Mutel
247cd92926 Merge pull request #524 from carbon/nullability2
Enable nullable annotations, round 2 of x
2021-03-10 22:55:24 +01:00
Jason Nelson
404a94f284 Fix nullability in MarkdownParser 2021-03-10 10:01:05 -08:00
Jason Nelson
1cc8a40473 Use pattern matching to test for non-empty collections 2021-03-10 09:39:12 -08:00
Jason Nelson
dc4968d5ab Reapply nullable annotations after merge 2021-03-10 09:32:02 -08:00
Jason Nelson
b2b36038ff Merge remote-tracking branch 'upstream/master' into nullability2 2021-03-10 09:27:12 -08:00
Alexandre Mutel
4a57035aec Merge pull request #521 from MihaZupan/random-perf-2
Random perf improvements
2021-03-10 07:27:10 +01:00
Jason Nelson
1752178631 Make attachedDatas nullable 2021-03-09 17:07:02 -08:00
Jason Nelson
39c05f34d1 Enable nullable annotations, round 2 of x 2021-03-09 16:55:13 -08:00
Alexandre Mutel
640196a18f Merge pull request #520 from MihaZupan/cleanup
Some minor cleanup
2021-03-09 07:55:19 +01:00
MihaZupan
4f9119fc96 Merge master 2021-03-09 07:54:20 +01:00
MihaZupan
5eb600afc3 Expose TrackTrivia on PipelineBuilder as get-only 2021-03-09 07:35:49 +01:00
Alexandre Mutel
64ebff4012 Merge pull request #519 from grishat/document-to-html
ADD: Markdown.ToHtml from MarkdownDocument
2021-03-09 07:13:49 +01:00
Alexandre Mutel
9e5d30cd4c Merge pull request #522 from carbon/master
Enable nullability
2021-03-09 07:13:18 +01:00
Alexandre Mutel
4324caaaea Update src/Markdig/Markdown.cs 2021-03-09 07:08:15 +01:00
Jason Nelson
46c2d49243 Begin nullability enablement 2021-03-08 11:43:02 -08:00
MihaZupan
80b1cf6020 Rename NoBlockFoundBlockRenderer.cs => EmptyBlockRenderer.cs 2021-03-08 12:19:43 +01:00
MihaZupan
264f7f2132 Update Roundtrip.md 2021-03-08 12:18:12 +01:00
MihaZupan
80ec8da7d3 Add missing license headers 2021-03-08 11:54:43 +01:00
MihaZupan
1e2399669d Fix most build warnings 2021-03-08 11:37:29 +01:00
MihaZupan
ab53969f06 Revert "Fix some build warnings"
This reverts commit 325fb7158e.
2021-03-08 11:16:31 +01:00
MihaZupan
168217b4e0 Expose TrackTrivia on Pipeline as get-only 2021-03-08 11:12:55 +01:00
MihaZupan
a3ce1903c1 Cache renderers for custom writers 2021-03-07 21:28:39 +01:00
MihaZupan
db1021a979 Avoid minor allocations in ProcessInlines loop 2021-03-07 20:08:04 +01:00
MihaZupan
cbd00a45af Remove test dependency on source file's line endings
This test uses '@' strings so if source files are checked out with different line endings, it will fail
2021-03-07 19:53:57 +01:00
MihaZupan
fef4719e41 Don't change Writer's NewLine 2021-03-07 19:29:17 +01:00
MihaZupan
ae25a8f12c Reduce the size of MarkdownObject by 1 pointer size
Since this is the base type of every node on the AST, it amounts to ~3% allocated bytes reduction
2021-03-07 19:19:03 +01:00
MihaZupan
bb5403c795 Hide TrackTrivia from PipelineBuilder
EnableTrackTrivia is exposed to enable trivia
2021-03-07 19:13:34 +01:00
MihaZupan
325fb7158e Fix some build warnings 2021-03-07 18:59:23 +01:00
MihaZupan
67416e4b45 Hide TrackTrivia from Pipeline 2021-03-07 18:52:41 +01:00
Alexandre Mutel
8b48accb7e Merge pull request #481 from generateui/cst
Roundtrip implementation
2021-03-07 16:18:35 +01:00
Ruud Poutsma
bb42ee42ca code review feedback 2021-03-07 16:14:48 +01:00
Rishat Gildanov
d17660fe5d ADD: Markdown.ToHtml from MarkdownDocument (already parsed Markdown text) 2021-03-07 17:39:43 +05:00
Ruud Poutsma
19e409ceca correctly calculate newlines in StringLineGroup PeekChar 2021-03-04 23:28:37 +01:00
Ruud Poutsma
59df6d1a2e primarily define TrackTrivia on MarkdownPipeline 2021-03-04 22:57:57 +01:00
Ruud Poutsma
763ed32212 NewLine renaming remnants 2021-03-04 22:42:48 +01:00
Ruud Poutsma
8aa522c4bf Merge branch 'cst' of https://github.com/generateui/markdig into cst 2021-03-04 22:36:00 +01:00
Ruud Poutsma
9031be96f8 rename Newline to NewLine 2021-03-04 22:35:48 +01:00
Ruud Poutsma
4bc2e847d5 PR feedback 2021-03-04 22:04:26 +01:00
Alexandre Mutel
80d4e6f344 Fix StringSlice overlaps
Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
2021-03-03 05:32:28 +01:00
Ruud Poutsma
b6e38a0a96 fix ContainerBlocksBlockQuotes_Example210 2021-03-01 23:26:55 +01:00
Ruud Poutsma
1d79ad8436 rerun specFileGen 2021-03-01 23:11:31 +01:00
Ruud Poutsma
383b197490 document roundtrip parsing feature 2021-03-01 23:07:40 +01:00
Ruud Poutsma
7aeee0681f rename Whitespace* member names to Trvia* member names 2021-03-01 21:12:51 +01:00
Ruud Poutsma
e017adae84 remove TODO: RTPs 2021-02-27 23:38:48 +01:00
Ruud Poutsma
7035aed74a Refactor Newline struct into enum 2021-02-27 23:32:09 +01:00
Ruud Poutsma
21b6a3869a implement NoBlocksFoundBlock, fix null character tests 2021-02-27 22:00:43 +01:00
Ruud Poutsma
aa92e59b2c merge from master 2021-02-27 21:25:44 +01:00
Alexandre Mutel
5f87e56651 Merge pull request #518 from grishat/master
FIX: Markdown.ToHtml doesnt get MarkdownParserContext parameter
2021-02-26 08:12:34 +01:00
Rishat Gildanov
9934c0033a FIX: Markdown.ToHtml doesnt get MarkdownParserContext parameter 2021-02-26 10:55:59 +05:00
Alexandre Mutel
5d1da2deac Merge pull request #511 from AndreyChechel/issue-508
Expose `TextRendererBase.Reset` method to inheritors
2021-02-17 20:57:48 +01:00
Andrey Chechel
4e424c43fb Expose TextRendererBase.Reset method to inheritors 2021-02-09 17:27:02 +03:00
Alexandre Mutel
3030b72f78 Bump to 0.23.0 2021-01-16 08:35:47 +01:00
Alexandre Mutel
d1784676b2 Rename AutolineInlineParser to AutolinkInlineParser 2021-01-16 08:34:45 +01:00
Alexandre Mutel
47e49f0a4f Add test documentation for root namespace 2021-01-16 08:28:20 +01:00
Alexandre Mutel
0bfc456509 Merge pull request #502 from yufeih/code-inline-plain-text
Fix CodeInline to plain text incorrect escape
2021-01-14 20:33:17 +01:00
Alexandre Mutel
8e14997bc1 Merge pull request #500 from MihaZupan/depth-limit
Add depth limits to avoid pathological-case parsing times/StackOverflows
2021-01-14 20:32:00 +01:00
Yufei Huang
a8ec3c1a48 Fix CodeInline to plain text incorrect escape 2021-01-12 16:11:31 +08:00
MihaZupan
f6f617a746 Add depth limits 2021-01-07 23:16:25 +01:00
Alexandre Mutel
3d65b9f6b6 Upgrade webapp settings 2020-12-22 14:36:26 +01:00
Alexandre Mutel
5f7d93be52 Use net5.0 2020-12-22 12:30:10 +01:00
Alexandre Mutel
3ec787687c Force not to use a pre-release in global.json 2020-12-22 11:16:38 +01:00
Ruud Poutsma
9fbe5eb21d merge from lunet-io/master 2020-12-12 14:26:02 +01:00
Alexandre Mutel
e523dfd7f4 Update the logo for the NuGet package 2020-12-02 08:04:32 +01:00
Alexandre Mutel
412500158c Merge pull request #492 from ilich/master
Added a reference to WebStoating.Markdig.Prism
2020-12-02 07:56:38 +01:00
Alexandre Mutel
fc942b4d01 Update logo 2020-12-02 07:55:18 +01:00
Ilya Verbitskiy
d1d64842ca Added a reference to WebStoating.Markdig.Prism 2020-11-10 16:40:19 +08:00
Alexandre Mutel
930eee383f Use dotnet 3.1 for SpecFileGen 2020-11-08 11:06:16 +01:00
Alexandre Mutel
87c45db46b Use latest dotnet 3.1.x SDK 2020-11-08 10:52:17 +01:00
Ruud Poutsma
fb4abdfae3 fix broken multi-empty-line after UnorderedList and make naming of before/after consistent 2020-11-07 23:49:25 +01:00
Ruud Poutsma
7ab34d5cef fix paragraph with more then 2 newlines after 2020-11-07 18:58:37 +01:00
Ruud Poutsma
b576b08332 document MarkdownParser assigning empty lines 2020-11-07 12:46:22 +01:00
Ruud Poutsma
9c43b802bd update Roundtrip.md todo list 2020-11-07 12:38:33 +01:00
Ruud Poutsma
7dda864e4a document and cleanup 2020-11-07 12:36:07 +01:00
Ruud Poutsma
b3953dbe23 use StringSlice instead of string in InlineLink and LinkReferenceDefinition 2020-11-07 11:47:12 +01:00
Ruud Poutsma
453e8239d2 use StringSlice in IFencedBlock 2020-11-06 17:33:27 +01:00
Ruud Poutsma
8e8b95c3bb fix broken newline parsing for LineBreakInline and PipeTableParser 2020-11-06 13:27:46 +01:00
Ruud Poutsma
35b64052d6 fix whitespaces for QuoteBlock 2020-11-01 22:48:04 +01:00
Ruud Poutsma
ef495da097 fix whitespace after atx heading char 2020-11-01 20:03:13 +01:00
Ruud Poutsma
a6b9c9a41e don't trip up SpecFileGen test by placing docs in *Spec folder in .Test project 2020-11-01 17:52:26 +01:00
Ruud Poutsma
5bb2d92180 fix quoteblock > orderedlist > quoteblock rendering 2020-11-01 17:38:12 +01:00
Ruud Poutsma
929ec36c76 fix FencedCodeBlock parsing 2020-11-01 13:48:08 +01:00
Ruud Poutsma
8e17d9c94e fix newlines surrounding IndentedCodeBlock 2020-11-01 13:04:44 +01:00
Ruud Poutsma
a11cd8c28c merge from main 2020-10-31 15:48:00 +01:00
Ruud Poutsma
68d2a20d20 fix broken PeekChar() of StringLineGroup.Iterator 2020-10-31 15:38:00 +01:00
Ruud Poutsma
e3531413e1 fix broken StringSlice tests 2020-10-31 15:07:10 +01:00
Ruud Poutsma
ef534224f8 fix heading SoureceSpan bugs 2020-10-31 14:34:25 +01:00
Ruud Poutsma
2f3e1451b8 ensure to write indents when indents are added to the text renderer 2020-10-27 20:56:57 +01:00
Ruud Poutsma
a34e257d2c fix ParagraphBlockParser parsing into paragraphs instead of setext headings 2020-10-26 22:59:29 +01:00
Ruud Poutsma
9d83631cfe fix horribly broken OrderedList 2020-10-26 22:37:44 +01:00
Ruud Poutsma
61b3ffde91 better respect TrackTrivia flag 2020-10-25 21:11:37 +01:00
Ruud Poutsma
bebdf0179e respect TrackTrivia flag much more widely, restore intentionally broken behaviors 2020-10-25 20:26:56 +01:00
Ruud Poutsma
ab5e8ae9e2 apply review feedback 2020-10-25 16:12:06 +01:00
Ruud Poutsma
c8da430134 cleanup RoundtripRenderer 2020-10-25 15:48:19 +01:00
Ruud Poutsma
0e8c312fda extract RoundtripRenderer and restore NormalizeRenderer 2020-10-25 15:43:27 +01:00
Ruud Poutsma
4814e9cea5 introduce trackTrivia feature flag 2020-10-25 15:21:13 +01:00
Ruud Poutsma
068a6e7af5 check IsNewline calls 2020-10-25 14:54:52 +01:00
Ruud Poutsma
e4f2892a23 do "TODO: RTP:" todos 2020-10-25 14:52:23 +01:00
Ruud Poutsma
c2cfb05d8d fix whitespace between heading and headingchar for atx headings 2020-10-25 14:31:25 +01:00
Ruud Poutsma
813647ca10 place newline on LinkReferenceDefinition instead of leaf whitespace properties 2020-10-25 14:16:53 +01:00
Ruud Poutsma
83357dc929 fix whitespace in nested QuoteBlock 2020-10-25 13:33:06 +01:00
Ruud Poutsma
420aa79a48 fix LinkReferenceDefinition bugs 2020-10-25 13:15:46 +01:00
Ruud Poutsma
24be820827 omit LinkReferenceDefinitionGroup and insert LinkReferenceDefinitions at proper indexes of document/parent 2020-10-25 11:32:25 +01:00
Ruud Poutsma
694a764f96 fix escaped within local label of InlineLink 2020-10-24 16:18:33 +02:00
Ruud Poutsma
bb1da73da2 fix whitespace in HtmlBlock within ListItemBlock 2020-10-24 15:53:34 +02:00
Ruud Poutsma
e6b591c035 fix escapes in FencedCodeBlock info and arguments 2020-10-24 15:32:14 +02:00
Ruud Poutsma
5a19cdfebb implement ordered list item bullet rendering 2020-10-24 15:27:37 +02:00
Ruud Poutsma
34e439f494 fix whitespace rendering of FencedCodeBlock as child of ListItemBlock 2020-10-24 15:27:10 +02:00
Ruud Poutsma
b0602a7bb0 fix HtmlBlock whitespace regression 2020-10-24 14:51:09 +02:00
Ruud Poutsma
d7558f0442 fix FencedCodeBlock beforewhitespace regression 2020-10-24 14:41:35 +02:00
Ruud Poutsma
eac0ab3cca fix broken InlineLink rendering 2020-10-24 14:37:49 +02:00
Ruud Poutsma
147cd48a8d fix escapes in InlineLink regression 2020-10-24 14:29:39 +02:00
Ruud Poutsma
1b44256fc0 improve whitespace handling in FencedCodeBlock 2020-10-24 14:13:38 +02:00
Ruud Poutsma
db2856daf7 fix label rendering on LinkInline 2020-10-24 13:53:29 +02:00
Ruud Poutsma
9beb0c1613 fix whitespace on empty lines 2020-10-24 00:24:00 +02:00
Ruud Poutsma
ef343158b7 fix escapes in LinkReferenceDefinition 2020-10-24 00:11:35 +02:00
Ruud Poutsma
de5526877d fix broken AtxHeading whitespace 2020-10-23 23:31:31 +02:00
Ruud Poutsma
b00d75607b fix tabs in IndentedCodeBlock 2020-10-23 23:21:11 +02:00
Ruud Poutsma
8c37a1bef5 fix HtmlBlock whitespace before 2020-10-23 23:00:38 +02:00
Ruud Poutsma
7a9405ec9e fix ThematicBreakParser 2020-10-23 22:55:55 +02:00
Ruud Poutsma
6506e4594c fix escaped characters in LinkInline 2020-10-23 22:47:39 +02:00
Ruud Poutsma
7b20299d2b fix empty ListItem 2020-10-23 19:34:16 +02:00
Ruud Poutsma
55eaadce67 fix optional space after Atx heading leaders 2020-10-23 19:29:12 +02:00
Ruud Poutsma
87269d88b9 fix newlines after LinkReferenceDefinition 2020-10-23 18:52:48 +02:00
Ruud Poutsma
fb8162f5d7 fix whitespace surrounding closing fences of FencedCodeBlock 2020-10-23 18:28:28 +02:00
Ruud Poutsma
a04aa8a4de fix empty QuoteBlock lines 2020-10-23 17:50:07 +02:00
Ruud Poutsma
352443d9cd fix unclosed FencedCodeBlock in QuoteBlock 2020-10-23 11:32:15 +02:00
Ruud Poutsma
cd798b8d95 fix newlines after links 2020-10-18 22:40:17 +02:00
Ruud Poutsma
c5b260f708 fix rendering of empty lines with whitespace 2020-10-18 16:09:24 +02:00
Ruud Poutsma
2583463ea2 fix broken links 2020-10-18 15:05:41 +02:00
Ruud Poutsma
777ac71bd1 fix HardLineBreak, CodeInline tests 2020-10-18 14:11:47 +02:00
Ruud Poutsma
810ae49cc7 fix SetextHeading tests 2020-10-18 13:08:40 +02:00
Ruud Poutsma
225e308438 fix AtxHeading tests 2020-10-18 12:40:57 +02:00
Ruud Poutsma
05dd543d16 fix HtmlBlock tests 2020-10-18 12:17:33 +02:00
Ruud Poutsma
c711201b34 implement codegen for roundtrip parsing 2020-10-17 23:49:44 +02:00
Ruud Poutsma
47b3ac5d99 fix Autlink tests 2020-10-17 23:19:44 +02:00
Ruud Poutsma
49aa856f52 implement LinkInline 2020-10-17 23:09:53 +02:00
Ruud Poutsma
5e15575929 implement LinkReferenceDefinition 2020-10-17 15:48:36 +02:00
Ruud Poutsma
c9fc608598 update todo 2020-10-11 14:07:32 +02:00
Ruud Poutsma
6ba3c3d683 implement newline 2020-10-11 14:00:09 +02:00
Ruud Poutsma
d15edb79fa fix broken whitespace starting on newlines within a paragraph 2020-10-10 17:25:22 +02:00
Ruud Poutsma
fa3b67342d add some tests, update todolist 2020-10-10 17:10:18 +02:00
Ruud Poutsma
033f156b2b add many tests, create todolist 2020-10-10 16:37:17 +02:00
Ruud Poutsma
f3db5e882e fix FencedCodeBlock 2020-10-09 19:47:16 +02:00
Ruud Poutsma
c9365f3551 correctly render whitespace for IndentedCodeBlock 2020-10-09 18:30:03 +02:00
Ruud Poutsma
9ecb5b9950 test nested indented codeblock in quoteblock 2020-10-09 17:20:58 +02:00
Ruud Poutsma
95fb53cbc9 fix IndentedCodeBlock newlines 2020-10-09 16:44:16 +02:00
Ruud Poutsma
9d82088e03 fix quoteblock 2020-10-09 14:14:41 +02:00
Ruud Poutsma
340b75b557 add some tests, fix nested blockquote in listitem 2020-10-09 13:24:44 +02:00
Alexandre Mutel
751c79fce4 Bump to 0.22.0 2020-10-05 08:20:45 +02:00
Alexandre Mutel
4dc8cc3977 Bump packages in tests 2020-10-05 08:20:31 +02:00
Alexandre Mutel
a1891e2984 Fix coverlet 2020-10-05 08:10:53 +02:00
Alexandre Mutel
ff0637993c Merge branch 'pr/n471_master' 2020-10-05 07:59:19 +02:00
Alexandre Mutel
8b64ce456f Fix quoteblock with setexheading when no lazy continuations are involved 2020-10-05 07:58:48 +02:00
Alexandre Mutel
a781ae1e5b Change tests to exe 2020-10-05 07:57:16 +02:00
Alexandre Mutel
2e5007241d Delay parsing of all specs in the tests itself instead of using static to restore the debuggability of markdig 2020-10-05 07:55:24 +02:00
Alexandre Mutel
cf6d98b7f8 Update tests 2020-10-05 07:54:13 +02:00
Ruud Poutsma
0b79389b14 fix CodeInline parsing & rendering 2020-10-04 21:49:54 +02:00
Ruud Poutsma
111d3d3362 fix multiline quote blocks, split tests into file per node type 2020-10-04 21:20:32 +02:00
Ruud Poutsma
ac6ceb23e8 restore whitespace parsing in BlockProcessor 2020-10-03 23:13:04 +02:00
Ruud Poutsma
d31fa47cd1 add some testcases 2020-10-03 18:55:02 +02:00
Ruud Poutsma
d7f6a94f12 cleanup, add some testcases 2020-10-03 18:54:45 +02:00
Ruud Poutsma
dbdd752b73 Keep line info when parsing quoteblocks and render accordingly 2020-10-03 16:11:01 +02:00
Ham Vocke
ccb7e8edfa add failing test, partial fix for setext headings in blockquotes
attempts to fix #465
2020-10-03 07:32:03 +02:00
Alexandre Mutel
db25c1db43 Merge pull request #473 from aloisdg/patch-1
Add a link to try the example
2020-10-03 07:22:22 +02:00
Alexandre Mutel
5db90ede4b Merge pull request #470 from iskcal/iss469
Fix issue 469
2020-10-03 07:21:34 +02:00
Alexandre Mutel
fef1ad3563 Merge pull request #474 from Wurstfried/pubFirstParentOfType
Make Inline.FirstParentOfType public
2020-10-03 07:20:20 +02:00
Alexandre Mutel
e9302d93bd Merge branch 'master' into pubFirstParentOfType 2020-10-03 07:15:02 +02:00
Alexandre Mutel
4704c49fbf Merge pull request #478 from yufeih/fix-476
Fix tel: treated as autolink
2020-10-03 07:12:36 +02:00
Alexandre Mutel
aca70e5c9a Merge pull request #479 from yufeih/fix-ci
Fix NETSDK1045 CI build failure
2020-10-03 06:34:36 +02:00
Yufei Huang
da5eff075d Fix NETSDK1045 CI build failure 2020-09-30 16:32:37 +08:00
Yufei Huang
971207e942 Fix tel: treated as autolink 2020-09-30 16:23:46 +08:00
Ruud Poutsma
4c2b46e0fc fix listblock-paragraph 2020-09-27 13:27:14 +02:00
Ruud Poutsma
68d12d0212 fix newlines and list blocks 2020-09-27 13:16:53 +02:00
Ruud Poutsma
fa1c117011 experiemnt with list rendering 2020-09-26 14:24:58 +02:00
Ruud Poutsma
6b1c5bc816 fix thematic break 2020-09-26 14:07:57 +02:00
Ruud Poutsma
e2cafc6b3d fix newline after listblock 2020-09-26 13:46:33 +02:00
Ruud Poutsma
aff7604b4b fix completely broken unordered list 2020-09-26 13:34:37 +02:00
Ruud Poutsma
68530aa4e0 improve linebreak handling 2020-09-26 12:59:48 +02:00
Ruud Poutsma
bfc1152b8a default newline after Html block, fix newlines before list block 2020-09-25 22:35:49 +02:00
Ruud Poutsma
37af8f8ecb implement newline with HtmlBlock 2020-09-25 22:03:34 +02:00
Ruud Poutsma
6792bffb5e better thematic break handling 2020-09-25 21:39:53 +02:00
Ruud Poutsma
976855a4c3 implement TheamticBreak renderer 2020-09-25 21:23:28 +02:00
Ruud Poutsma
acf2ba9502 allow CodeInline with multiple delimiter characters 2020-09-25 19:23:11 +02:00
Ruud Poutsma
cadbc67825 fix newline between blocks 2020-09-25 18:55:54 +02:00
Ruud Poutsma
0d86a93200 fix block nodes 2020-09-25 17:58:58 +02:00
Ruud Poutsma
f78b5c83cd handle whitespace before and after paragraphs correctly 2020-09-25 17:07:10 +02:00
iskcal
fb942f9810 fix typo 2020-09-15 19:31:29 +08:00
Sebastian Raffel
25a227fffd CI: Use dotnet SDK 3.1.402 2020-09-13 10:19:54 +02:00
Sebastian Raffel
2be8cd4aa7 Make Inline.FirstParentOfType public 2020-09-13 08:05:34 +02:00
Alois
569b80befe Add a link to try the example 2020-09-09 18:10:36 +02:00
iskcal
0b8b14490e fix issue 469 2020-08-25 13:05:44 +08:00
Alexandre Mutel
c59fd5c651 Merge pull request #468 from yufeih/parentblock
Add ParentBlock property to ContainerInline
2020-08-18 09:59:18 +02:00
Alexandre Mutel
4893e2b177 Merge pull request #467 from yufeih/container-block-parent
Set Parent in ContainerBlock.set[index] method
2020-08-18 09:44:41 +02:00
Yufei Huang
b30b219237 Add ParentBlock property to ContainerInline 2020-08-18 15:42:29 +08:00
Yufei Huang
d6c627aa88 Address PR feedback 2020-08-18 15:40:27 +08:00
Yufei Huang
a26f4298a4 Set Parent in ContainerBlock.set[index] method 2020-08-18 14:55:15 +08:00
Alexandre Mutel
d5b80f6a7b Bump to 0.21.1 2020-08-17 12:38:37 +02:00
Alexandre Mutel
98d747c839 Fix Pack signed 2020-08-17 12:38:07 +02:00
Alexandre Mutel
7dd9321a97 Bump to 0.21.0 2020-08-17 12:13:19 +02:00
Alexandre Mutel
c22d681c20 Merge pull request #464 from 928PJY/public-property
Expose IndentCount of FencedCodeBlock
2020-08-16 15:51:26 +02:00
Alexandre Mutel
ffe7f56bc2 Merge pull request #466 from Kryptos-FR/feature/net45
Bring back net45 target
2020-08-16 15:46:14 +02:00
Nicolas Musset
16c0b6a3fa ArrayHelper is needed for the tests
Slightly different from the previous implementation in order to mimic `System.Array.Empty<T>()` closely.
2020-08-16 13:13:45 +09:00
Nicolas Musset
db867dee48 Bring back net45 target 2020-08-16 12:47:04 +09:00
JiayinPei
d35b1b82ea Expose ColumnWidth of ListBlockItem 2020-08-13 14:34:07 +08:00
JiayinPei
8b829a2dea Export IndentCount of FencedCodeBlock 2020-08-13 12:07:04 +08:00
Ruud Poutsma
0234d60d74 fix broken whitespace calculation 2020-08-08 18:25:08 +02:00
Ruud Poutsma
cd18087e29 implement cst for header 2020-08-08 18:18:55 +02:00
Ruud Poutsma
30f670bf5f fix NRE 2020-08-08 17:24:16 +02:00
Ruud Poutsma
c73785372b implement cst for Paragraph 2020-08-08 17:22:53 +02:00
Ruud Poutsma
147698daab revert LinkInlineRenderer 2020-08-08 14:54:57 +02:00
Ruud Poutsma
2b07e9a5b9 add naive cst implementation 2020-08-08 14:41:02 +02:00
Alexandre Mutel
4f7ef61303 Merge pull request #459 from iskcal/fix456
Write custom rel into links
2020-08-06 18:51:02 +02:00
iskcal
831a529338 fix456 2020-08-03 11:51:38 +08:00
Alexandre Mutel
4f5e9cd334 Merge pull request #455 from hamvocke/master
Pipe Tables: Normalize using header column count
2020-07-30 18:18:28 +02:00
Ham Vocke
cb0b3a6292 add 'gfm-pipetables' pipeline mode, introduce new gfm test spec 2020-07-30 17:50:53 +02:00
Ham Vocke
4390ff289e add option to PipeTableOptions, use for normalization 2020-07-30 16:16:20 +02:00
Ham Vocke
be53e778be remove extra cells, use header row to find maxColumn 2020-07-30 15:03:33 +02:00
Ham Vocke
0eab0a3107 set up example006 of pipe table spec according to new behavior 2020-07-30 15:02:15 +02:00
Ham Vocke
8fa47427ac change test for pipe table normalization 2020-07-30 14:14:52 +02:00
Alexandre Mutel
bca544575b Merge pull request #449 from MihaZupan/invalid-idn-fallback
Fallback to non-punycode encoding for invalid IDN urls
2020-07-22 22:26:10 +02:00
Alexandre Mutel
0017dbffc4 Merge pull request #444 from iskcal/master
add the missing fact attribute
2020-07-22 22:25:14 +02:00
Alexandre Mutel
569efa357a Merge pull request #453 from davidackroyd99/feature/autolink-tel-uri
Autolink tel: uri
2020-07-22 22:24:47 +02:00
Alexandre Mutel
7e9df72173 Merge pull request #452 from davidackroyd99/bug/parsing-math
Bug/parsing math
2020-07-22 22:16:54 +02:00
David Ackroyd
b2fcb1cc37 autolink tel: uri, with basic test 2020-07-21 23:10:55 +00:00
David Ackroyd
8758ba460f fix: parsing math blocks with no leading or trailing whitespace 2020-07-21 21:35:52 +00:00
David Ackroyd
477a290538 typo: fixed comment in ApiController 2020-07-21 21:17:34 +00:00
MihaZupan
0fc112a6b8 Fallback to non-punycode encoding for invalid IDN urls 2020-07-12 00:15:02 +02:00
iskcal
b7aea44502 add the missing fact attribute 2020-06-17 16:22:34 +08:00
Alexandre Mutel
0545faa9af Merge pull request #435 from RudeySH/patch-1
Fix media link classes not being added
2020-06-09 20:34:11 +02:00
Rudey
ea67a295b2 Test CSS classes using both Bootstrap and MediaLinks 2020-05-12 22:32:05 +02:00
Rudey
d53128d56d Reorder class attribute in spec tests 2020-05-12 22:02:01 +02:00
Rudey
ba192ce065 Remove redundancy, apply same fix to audio/video 2020-05-12 21:45:50 +02:00
Rudey
42462d71ac Reorder class attribute in test cases 2020-05-12 21:41:52 +02:00
Rudey
6e0363aa91 Fix media link classes not being added 2020-05-12 21:29:28 +02:00
Alexandre Mutel
e9be3725d6 Merge pull request #431 from mlaily/escape-scheme
Escape URLs scheme
2020-04-30 07:34:03 +02:00
Melvyn Laïly
38f4332de1 Escape URLs scheme (fix #365) 2020-04-27 09:35:44 +02:00
Alexandre Mutel
bcc123d240 Merge pull request #429 from KrisVandermotten/StringSliceCountAndSkipChar
Added StringSlice.CountAndSkipChar(char)
2020-04-27 09:12:15 +02:00
Alexandre Mutel
144e8ad156 Merge pull request #430 from mlaily/fix-relative-url-replacement
Fix relative uri detection to be cross-platform compatible
2020-04-26 18:26:57 +02:00
Melvyn Laïly
55a7eae4d4 Fix relative uri detection to be cross-platform compatible 2020-04-26 18:02:45 +02:00
Kris Vandermotten
d96862378d Added StringSlice.CountAndSkipChar(char) 2020-04-26 15:17:19 +02:00
Alexandre Mutel
8acf5a548e Merge pull request #427 from MihaZupan/cleanup
Cleanup
2020-04-23 07:12:28 +02:00
MihaZupan
222a99c7e4 Pattern matching, inline variable declarations 2020-04-23 01:32:22 +02:00
MihaZupan
ac4a75bdf9 Fix comment warnings 2020-04-23 00:38:16 +02:00
MihaZupan
fc2e1ab896 Cleanup license headers 2020-04-22 17:48:44 +02:00
MihaZupan
ef7f20482e Remove unused usings 2020-04-22 17:10:14 +02:00
MihaZupan
fc50e2e2e7 Simplify crefs 2020-04-22 17:08:52 +02:00
Alexandre Mutel
4d513acf6b Add rider/idea to gitignore 2020-04-22 07:03:34 +02:00
Alexandre Mutel
32b1ee7eaa Remove Scriban.Signed from solution, keep it in the CI. Remove a warning 2020-04-22 06:59:57 +02:00
Alexandre Mutel
3e2a498ae7 Merge pull request #426 from MihaZupan/renormalize
git add --renormalize .
2020-04-22 06:55:35 +02:00
Alexandre Mutel
e0ac9b7ddf Merge pull request #425 from lellid/ContainerReadonlyList
Add IReadOnlyList interface to ContainerBlock to unify and simplify e…
2020-04-22 06:54:00 +02:00
Alexandre Mutel
bbf10a7ad0 Merge pull request #420 from SebastianRaffel/patch-1
PipeTableSpecs.md: Fix duplicate Rule numbering + bold headlines
2020-04-22 06:53:41 +02:00
MihaZupan
62a0992e5e git add --renormalize . 2020-04-22 00:47:46 +02:00
MihaZupan
b2e49d174e Add .gitattributes 2020-04-22 00:46:40 +02:00
SebastianRaffel
5e218721e7 Merge branch 'master' into patch-1 2020-04-20 09:25:36 +02:00
Sebastian Raffel
c64cd53ac3 Exec SpecFileGen 2020-04-20 09:23:13 +02:00
Dirk Lellinger
920ab6cb60 Add IReadonlyList interface to ContainerBlock to unify and simplify enumeration 2020-04-19 22:43:42 +02:00
Alexandre Mutel
3ef1d735d5 Bump to 0.20.0 2020-04-18 18:31:44 +02:00
Alexandre Mutel
47c6c49f5c Merge pull request #417 from KrisVandermotten/StringBuilderCache
Cleanup StringBuilderCache
2020-04-18 18:21:39 +02:00
Kris Vandermotten
a19f78342f merged from master 2020-04-18 18:17:40 +02:00
Alexandre Mutel
edb4c6c3cb Merge pull request #422 from KrisVandermotten/ListBlockParser
Cleanup ListBlockParser
2020-04-18 17:58:49 +02:00
Alexandre Mutel
4b6d7c78f5 Merge pull request #421 from KrisVandermotten/ParagraphBlockParser
Cleanup ParagraphBlockParser
2020-04-18 17:57:51 +02:00
Alexandre Mutel
0386cfd617 Merge pull request #418 from KrisVandermotten/CodeInlineParser
Optimized away the expensive StringBuilder.Remove(0, 1) in CodeInlineParser
2020-04-18 17:55:53 +02:00
Alexandre Mutel
5c52a7249d Merge pull request #416 from MihaZupan/new
Random improvements
2020-04-18 17:54:22 +02:00
Kris Vandermotten
14fb550704 Merge branch 'master' into StringBuilderCache 2020-04-18 14:21:48 +02:00
Kris Vandermotten
741d09a4e8 Merge branch 'master' into CodeInlineParser 2020-04-18 14:21:09 +02:00
Kris Vandermotten
34d9fa2bcc Merge branch 'master' into ParagraphBlockParser 2020-04-18 14:20:24 +02:00
Kris Vandermotten
8ee50a265d Merge branch 'master' into ListBlockParser 2020-04-18 14:19:46 +02:00
MihaZupan
eb002db3c7 Cross-target netstandard2.1 2020-04-18 14:14:57 +02:00
MihaZupan
a15203a061 Don't count non-ascii chars into maxChar limit in CharacterMap 2020-04-18 14:10:01 +02:00
MihaZupan
b0a2f19ed7 Optimize CharacterMap further 2020-04-18 14:10:00 +02:00
MihaZupan
a9d78e04a1 Cross-target Core 3.1 2020-04-18 14:10:00 +02:00
MihaZupan
a8b6e2c2e4 Remove allocation in EntityHelper.DecodeEntity 2020-04-18 14:10:00 +02:00
MihaZupan
665f5f5e51 Cache string representations of numbers 0-26 2020-04-18 14:10:00 +02:00
MihaZupan
86a72c3582 Avoid delegate allocation in LinkInlineParser.MarkParentAsInactive 2020-04-18 14:10:00 +02:00
MihaZupan
784b999d6c Improve CodeGen by using ThrowHelper everywhere 2020-04-18 14:10:00 +02:00
MihaZupan
be3a893d3d Use foreach where appropriate 2020-04-18 14:10:00 +02:00
MihaZupan
2679c84788 Remove .Net Foundation license header 2020-04-18 14:10:00 +02:00
MihaZupan
3d005d6444 Avoid allocations in EntityHelper 2020-04-18 14:09:59 +02:00
MihaZupan
09593ff3da Remove unused Helper 2020-04-18 14:09:59 +02:00
MihaZupan
f0269fc61f Remove ArrayHelper 2020-04-18 14:09:59 +02:00
MihaZupan
2d97628cfd Optimize StringSlice helpers 2020-04-18 14:09:59 +02:00
MihaZupan
ee97d32ef0 Remove MethodImplOptionPortable compat helper 2020-04-18 14:09:59 +02:00
MihaZupan
9ca5cdcb31 Remove substring allocation in RomanToArabic 2020-04-18 14:09:59 +02:00
MihaZupan
5f453fbe92 Remove ExcludeFromCodeCoverage compat for net35 2020-04-18 14:09:59 +02:00
MihaZupan
8300a9cca2 Add System.Memory package for netstandard2.0 2020-04-18 14:09:59 +02:00
MihaZupan
f7d763230d Unseal MarkdownParserContext 2020-04-18 14:09:58 +02:00
MihaZupan
cce1b99edc Drop net35 and net40 targets 2020-04-18 14:07:48 +02:00
Alexandre Mutel
2dca2119fa Run coveralls.net upload only on push 2020-04-18 09:13:32 +02:00
Alexandre Mutel
faf0a20816 Fix coverlet and coverall.net upload 2020-04-18 09:02:02 +02:00
Alexandre Mutel
68196c1ce6 Fix specs 2020-04-18 08:48:49 +02:00
Kris Vandermotten
fdf125d05d Cleanup ListBlockParser 2020-04-16 20:09:00 +02:00
Kris Vandermotten
46133715ab Cleanup ParagraphBlockParser 2020-04-16 20:03:40 +02:00
SebastianRaffel
ae726b3796 Fix duplicate Rule numbering + bold headlines 2020-04-14 08:51:44 +02:00
Kris Vandermotten
4151ac2287 Optimized away the expensive StringBuilder.Remove(0, 1) in CodeInlineParser 2020-04-13 16:24:35 +02:00
Kris Vandermotten
305f722899 Cleanup StringBuilderCache 2020-04-13 16:02:04 +02:00
Alexandre Mutel
abc8aa25b7 Merge pull request #411 from WeihanLi/patch-1
make dotnet framework ReferenceAssemblies Private
2020-03-23 20:49:37 +01:00
Alexandre Mutel
e6bb83ecdf Merge pull request #410 from KrisVandermotten/RendererBase
Optimized RendererBase
2020-03-23 20:48:54 +01:00
Weihan Li
e6ea8ad274 make dotnet framework ReferenceAssemblies Private 2020-03-19 13:33:18 +08:00
Kris Vandermotten
1f3cf5962f Optimized RendererBase 2020-03-09 15:32:29 +01:00
Alexandre Mutel
83b3427805 Fix Microsoft.SourceLink.GitHub 2020-03-08 10:45:00 +01:00
Alexandre Mutel
3ff3f1ccb9 Bump to 0.18.3 2020-03-08 10:33:57 +01:00
Alexandre Mutel
5d91f0e26f Fix NuGet symbol packages 2020-03-08 10:33:13 +01:00
403 changed files with 41490 additions and 10413 deletions

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
* text=auto
*.cs text=auto diff=csharp
*.sln text=auto eol=crlf

View File

@@ -1,8 +1,5 @@
name: ci
env:
PROJECT_NAME: Markdig
on:
push:
paths-ignore:
@@ -18,46 +15,18 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v2
with:
submodules: true
fetch-depth: 0
- name: Install .NET Core
- name: Install .NET 6.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.0.100
dotnet-version: '6.0.x'
- name: Add coveralls.net
run: dotnet tool install coveralls.net --version 1.0.0 --tool-path tools
- name: Build (Release)
run: dotnet build src -c Release
- name: SpecFileGen
run: dotnet src/SpecFileGen/bin/Release/netcoreapp2.1/SpecFileGen.dll
- name: Test (Release)
run: dotnet test src -c Release
- name: Build & Test (Debug)
run: dotnet test src -c Debug
- name: Coveralls
run: dotnet test src -c Release -f netcoreapp2.1 /p:Include=\"[${{env.PROJECT_NAME}}]*\" /p:CollectCoverage=true /p:CoverletOutputFormat=lcov /p:CoverletOutput=./coverage.info
- name: Coveralls Upload
uses: coverallsapp/github-action@v1.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: src/${{env.PROJECT_NAME}}.Tests/coverage.info
- name: Pack
run: dotnet pack src -c Release
- name: Publish
if: github.event_name == 'push'
run: |
if ( "${{github.ref}}" -match "^refs/tags/[0-9]+\.[0-9]+\.[0-9]+$" ) {
dotnet nuget push src\${{env.PROJECT_NAME}}\bin\Release\*.nupkg -s nuget.org -k ${{secrets.NUGET_TOKEN}}
dotnet nuget push src\${{env.PROJECT_NAME}}.Signed\bin\Release\*.nupkg -s nuget.org -k ${{secrets.NUGET_TOKEN}}
} else {
echo "publish is only enabled by tagging with a release tag"
}
- name: Build, Test, Pack, Publish
shell: bash
run: |
dotnet tool install -g dotnet-releaser
dotnet-releaser run --nuget-token "${{secrets.NUGET_TOKEN}}" --github-token "${{secrets.GITHUB_TOKEN}}" src/dotnet-releaser.toml

28
.gitignore vendored
View File

@@ -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,29 @@ 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
# Remove artifacts produced by dotnet-releaser
artifacts-dotnet-releaser/

View File

@@ -1,201 +1,259 @@
# Changelog
## 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 `&lt;/iframe&gt;` 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.27.0 (23 Jan 2022)
- Fix link reference definition parse bug with title and CRLF ([PR #590](https://github.com/lunet-io/markdig/pull/590))
- Move tests to net6.0 ([PR #560](https://github.com/lunet-io/markdig/pull/560))
## 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 `&lt;/iframe&gt;` 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,4 +1,4 @@
# Markdig [![Build Status](https://github.com/lunet-io/markdig/workflows/ci/badge.svg?branch=master)](https://github.com/lunet-io/markdig/actions) [![Coverage Status](https://coveralls.io/repos/github/lunet-io/markdig/badge.svg?branch=master)](https://coveralls.io/github/lunet-io/markdig?branch=master) [![NuGet](https://img.shields.io/nuget/v/Markdig.svg)](https://www.nuget.org/packages/Markdig/) [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
# Markdig [![Build Status](https://github.com/lunet-io/markdig/workflows/ci/badge.svg?branch=master)](https://github.com/lunet-io/markdig/actions) [![Coverage Status](https://coveralls.io/repos/github/xoofx/markdig/badge.svg?branch=master)](https://coveralls.io/github/xoofx/markdig?branch=master) [![NuGet](https://img.shields.io/nuget/v/Markdig.svg)](https://www.nuget.org/packages/Markdig/) [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
<img align="right" width="160px" height="160px" src="img/markdig.png">
@@ -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))
@@ -50,13 +51,17 @@ You can **try Markdig online** and compare it to other implementations on [babel
- [**Diagrams**](src/Markdig.Tests/Specs/DiagramsSpecs.md) extension whenever a fenced code block contains a special keyword, it will be converted to a div block with the content as-is (currently, supports [`mermaid`](https://knsv.github.io/mermaid/) and [`nomnoml`](https://github.com/skanaar/nomnoml) diagrams)
- [**YAML Front Matter**](src/Markdig.Tests/Specs/YamlSpecs.md) to parse without evaluating the front matter and to discard it from the HTML output (typically used for previewing without the front matter in MarkdownEditor)
- [**JIRA links**](src/Markdig.Tests/Specs/JiraLinks.md) to automatically generate links for JIRA project references (Thanks to @clarkd: https://github.com/clarkd/MarkdigJiraLinker)
- Compatible with .NET 3.5, 4.0+ and .NET Core (`netstandard1.1+`)
- Starting with Markdig version `0.20.0+`, Markdig is compatible only with `NETStandard 2.0`, `NETStandard 2.1`, `NETCoreApp 2.1` and `NETCoreApp 3.1`.
If you are looking for support for an old .NET Framework 3.5 or 4.0, you can download Markdig `0.18.3`.
### Third Party Extensions
- [**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 ColorCode-Universal**: `Markdown.ColorCode`](https://github.com/wbaldoumas/markdown-colorcode)
- [**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
@@ -92,11 +97,13 @@ 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
In order to build Markdig, you need to install [.NET Core RTM](https://www.microsoft.com/net/core)
In order to build Markdig, you need to install [.NET 6.0](https://dotnet.microsoft.com/en-us/download)
## License
@@ -122,10 +129,6 @@ This is an early preview of the benchmarking against various implementations:
- [Marked.NET](https://github.com/T-Alex/MarkedNet) (version: 1.0.5) port of original [marked.js](https://github.com/chjj/marked) project
- [Microsoft.DocAsCode.MarkdownLite](https://github.com/dotnet/docfx/tree/dev/src/Microsoft.DocAsCode.MarkdownLite) (version: 2.0.1) used by the [docfx](https://github.com/dotnet/docfx) project
**JavaScript/V8 implementations**:
- [Strike.V8](https://github.com/SimonCropp/Strike) (version: 1.5.0) [marked.js](https://github.com/chjj/marked) running in Google V8 (not .NET based)
### Analysis of the results:
- Markdig is roughly **x100 times faster than MarkdownSharp**, **30x times faster than docfx**
@@ -160,7 +163,6 @@ CommonMark.NET(pipe_tables) | 5.6164 ms | 0.0298 ms | 0.72 | 111.00| 56.00|
MarkdownDeep | 7.8193 ms | 0.0334 ms | 1.00 | 120.00| 56.00| 49.00| 1,884,854.85 |
cmark | 4.2698 ms | 0.1526 ms | 0.55 | -| -| -| NA |
Moonshine | 6.0929 ms | 0.1053 ms | 1.28 | -| -| -| NA |
Strike.V8 | 10.5895 ms | 0.0492 ms | 1.35 | -| -| -| NA |
Marked.NET | 207.3169 ms | 5.2628 ms | 26.51 | 0.00| 0.00| 0.00| 303,125,228.65 |
MarkdownSharp | 675.0185 ms | 2.8447 ms | 86.32 | 40.00| 27.00| 41.00| 2,413,394.17 |
Microsoft DocfxMarkdownLite | 166.3357 ms | 0.4529 ms | 21.27 |4,452.00|948.00|11,167.00| 180,218,359.60 |

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net471</TargetFrameworks>
<TargetFramework>net6.0</TargetFramework>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsPackable>false</IsPackable>
@@ -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.13.1" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.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.226801" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.74" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Markdig\Markdig.csproj" />

View File

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

View File

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

View File

@@ -1,23 +1,53 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net451;netcoreapp2.1</TargetFrameworks>
<OutputType>Library</OutputType>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="2.6.2">
<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>net6.0</TargetFramework>
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<StartupObject>Markdig.Tests.Program</StartupObject>
<SpecExecutable>$(MSBuildProjectDirectory)\..\SpecFileGen\bin\$(Configuration)\net6.0\SpecFileGen.dll</SpecExecutable>
<SpecTimestamp>$(MSBuildProjectDirectory)\..\SpecFileGen\bin\$(Configuration)\net6.0\SpecFileGen.timestamp</SpecTimestamp>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="3.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Markdig\Markdig.csproj" />
<ProjectReference Include="..\SpecFileGen\SpecFileGen.csproj" />
</ItemGroup>
<ItemGroup>
<ItemSpecExecutable Include="$(SpecExecutable)" />
<InputSpecFiles Include="Specs\*.md" />
<InputSpecFiles Include="NormalizeSpecs\*.md" />
<InputSpecFiles Include="PlainTextSpecs\*.md" />
<InputSpecFiles Include="RoundtripSpecs\*.md" />
<InputSpecFiles Remove="Specs\readme.md" />
<!-- Allow Visual Studio up-to-date check to verify that nothing has changed - https://github.com/dotnet/project-system/blob/main/docs/up-to-date-check.md -->
<UpToDateCheckInput Include="@(InputSpecFiles)"/>
<OutputSpecFiles Include="@(InputSpecFiles->'%(RelativeDir)%(Filename).generated.cs')" />
</ItemGroup>
<Target Name="GeneratedSpecsFile" BeforeTargets="BeforeCompile;CoreCompile" Inputs="@(ItemSpecExecutable);@(InputSpecFiles)" Outputs="@(ItemSpecExecutable->'%(RelativeDir)%(Filename).timestamp');@(InputSpecFiles->'%(RelativeDir)%(Filename).generated.cs')">
<Message Importance="high" Text="Regenerating Specs Files" />
<Exec Command="dotnet $(SpecExecutable)" />
<WriteLinesToFile File="$(SpecTimestamp)" Lines="$([System.DateTime]::Now)" />
<ItemGroup>
<FileWrites Include="$(SpecTimestamp)" />
<_GeneratedSpecsFile Include="Specs\*.generated.cs" />
<_GeneratedSpecsFile Include="NormalizeSpecs\*.generated.cs" />
<_GeneratedSpecsFile Include="PlainTextSpecs\*.generated.cs" />
<_GeneratedSpecsFile Include="RoundtripSpecs\*.generated.cs" />
<_GeneratedSpecsFile Remove="@(Compile)" />
<Compile Include="@(_GeneratedSpecsFile)" />
</ItemGroup>
</Target>
</Project>

View File

@@ -1,241 +1,296 @@
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(
@"![This is image alt text with quotation ' and double quotation ""hello"" world](girl.png)",
@"<p><img src=""girl.png"" alt=""This is image alt text with quotation ' and double quotation &quot;hello&quot; 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&amp;ddr;&amp;*&amp;ddr;&amp;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&#174;*&#174;";
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 = "![image](\"onclick=\"alert&amp;#40;'click'&amp;#41;\"://)";
string expected = "<p><img src=\"%22onclick=%22alert&amp;#40;%27click%27&amp;#41;%22://\" alt=\"image\" /></p>";
TestParser.TestSpec(input, expected);
}
[Test]
public void TestAltTextIsCorrectlyEscaped()
{
TestParser.TestSpec(
@"![This is image alt text with quotation ' and double quotation ""hello"" world](girl.png)",
@"<p><img src=""girl.png"" alt=""This is image alt text with quotation ' and double quotation &quot;hello&quot; 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&amp;ddr;&amp;*&amp;ddr;&amp;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&#174;*&#174;";
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);
var test1 = html.Contains("<p><span class=\"math\">\\(");
var test2 = html.Contains("\\)</span></p>");
if (!test1 || !test2)
{
Console.WriteLine(html);
}
Assert.IsTrue(test1, "Leading bracket missing");
Assert.IsTrue(test2, "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);
var test1 = html.Contains("<div class=\"math\">\n\\[");
var test2 = html.Contains("\\]</div>");
if (!test1 || !test2)
{
Console.WriteLine(html);
}
Assert.IsTrue(test1, "Leading bracket missing");
Assert.IsTrue(test2, "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);
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Headings
@@ -45,8 +44,7 @@ namespace Markdig.Tests.Specs.Normalize.Headings
//
// ###### Heading 6
Console.WriteLine("Example 1\nSection Headings\n");
TestNormalize.TestSpec("# Heading 1\n\n## Heading 2\n\n### Heading 3\n\n#### Heading 4\n\n##### Heading 5\n\n###### Heading 6", "# Heading 1\n\n## Heading 2\n\n### Heading 3\n\n#### Heading 4\n\n##### Heading 5\n\n###### Heading 6", "");
TestNormalize.TestSpec("# Heading 1\n\n## Heading 2\n\n### Heading 3\n\n#### Heading 4\n\n##### Heading 5\n\n###### Heading 6", "# Heading 1\n\n## Heading 2\n\n### Heading 3\n\n#### Heading 4\n\n##### Heading 5\n\n###### Heading 6", "", context: "Example 1\nSection Headings\n");
}
[Test]
@@ -65,8 +63,7 @@ namespace Markdig.Tests.Specs.Normalize.Headings
//
// Text after two newlines
Console.WriteLine("Example 2\nSection Headings\n");
TestNormalize.TestSpec("###### Heading\n\nText after two newlines", "###### Heading\n\nText after two newlines", "");
TestNormalize.TestSpec("###### Heading\n\nText after two newlines", "###### Heading\n\nText after two newlines", "", context: "Example 2\nSection Headings\n");
}
[Test]
@@ -79,15 +76,14 @@ 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", "", context: "Example 3\nSection Headings\n");
}
}
}

View File

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

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Sample
@@ -28,8 +27,7 @@ namespace Markdig.Tests.Specs.PlainText.Sample
// Hello, world!
//
Console.WriteLine("Example 1\nSection Sample plain text spec\n");
TestPlainText.TestSpec("*Hello*, [world](http://example.com)!", "Hello, world!\n", "");
TestPlainText.TestSpec("*Hello*, [world](http://example.com)!", "Hello, world!\n", "", context: "Example 1\nSection Sample plain text spec\n");
}
}
}

View 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();
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

View File

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

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

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

View File

@@ -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("&gt;")]
[TestCase("&lt;")]
[TestCase("&nbsp;")]
[TestCase("&heartsuit;")]
[TestCase("&#42;")]
[TestCase("&#0;")]
[TestCase("&#1234;")]
[TestCase("&#xcab;")]
[TestCase(" &gt;")]
[TestCase(" &lt;")]
[TestCase(" &nbsp;")]
[TestCase(" &heartsuit;")]
[TestCase(" &#42;")]
[TestCase(" &#0;")]
[TestCase(" &#1234;")]
[TestCase(" &#xcab;")]
[TestCase("&gt; ")]
[TestCase("&lt; ")]
[TestCase("&nbsp; ")]
[TestCase("&heartsuit; ")]
[TestCase("&#42; ")]
[TestCase("&#0; ")]
[TestCase("&#1234; ")]
[TestCase("&#xcab; ")]
[TestCase(" &gt; ")]
[TestCase(" &lt; ")]
[TestCase(" &nbsp; ")]
[TestCase(" &heartsuit; ")]
[TestCase(" &#42; ")]
[TestCase(" &#0; ")]
[TestCase(" &#1234; ")]
[TestCase(" &#xcab; ")]
public void Test(string value)
{
RoundTrip(value);
}
}
}

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

View File

@@ -0,0 +1,25 @@
using NUnit.Framework;
using static Markdig.Tests.TestRoundtrip;
namespace Markdig.Tests.RoundtripSpecs.Inlines
{
[TestFixture]
public class TestImageInline
{
[TestCase("![](a)")]
[TestCase(" ![](a)")]
[TestCase("![](a) ")]
[TestCase(" ![](a) ")]
[TestCase(" ![description](http://example.com)")]
public void Test(string value)
{
RoundTrip(value);
}
[TestCase("paragraph ![description](http://example.com)")]
public void TestParagraph(string value)
{
RoundTrip(value);
}
}
}

View File

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

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

View File

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

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

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

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

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

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

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

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

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

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

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

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

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

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

View File

@@ -1,4 +1,3 @@
// Generated: 2019-05-15 02:46:55
// --------------------------------
// Abbreviations
@@ -35,8 +34,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p>Later in a text we are using <abbr title="Hypertext Markup Language">HTML</abbr> and it becomes an abbr tag <abbr title="Hypertext Markup Language">HTML</abbr></p>
Console.WriteLine("Example 1\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[HTML]: Hypertext Markup Language\n\nLater in a text we are using HTML and it becomes an abbr tag HTML", "<p>Later in a text we are using <abbr title=\"Hypertext Markup Language\">HTML</abbr> and it becomes an abbr tag <abbr title=\"Hypertext Markup Language\">HTML</abbr></p>", "abbreviations|advanced");
TestParser.TestSpec("*[HTML]: Hypertext Markup Language\n\nLater in a text we are using HTML and it becomes an abbr tag HTML", "<p>Later in a text we are using <abbr title=\"Hypertext Markup Language\">HTML</abbr> and it becomes an abbr tag <abbr title=\"Hypertext Markup Language\">HTML</abbr></p>", "abbreviations|advanced", context: "Example 1\nSection Extensions / Abbreviation\n");
}
// An abbreviation definition can be indented at most 3 spaces
@@ -54,8 +52,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// <pre><code>*[This]: is not an abbreviation
// </code></pre>
Console.WriteLine("Example 2\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[HTML]: Hypertext Markup Language\n *[This]: is not an abbreviation", "<pre><code>*[This]: is not an abbreviation\n</code></pre>", "abbreviations|advanced");
TestParser.TestSpec("*[HTML]: Hypertext Markup Language\n *[This]: is not an abbreviation", "<pre><code>*[This]: is not an abbreviation\n</code></pre>", "abbreviations|advanced", context: "Example 2\nSection Extensions / Abbreviation\n");
}
// An abbreviation may contain spaces:
@@ -73,8 +70,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p>This is a <abbr title="Super Hypertext Markup Language">SUPER HTML</abbr> document</p>
Console.WriteLine("Example 3\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[SUPER HTML]: Super Hypertext Markup Language\n\nThis is a SUPER HTML document ", "<p>This is a <abbr title=\"Super Hypertext Markup Language\">SUPER HTML</abbr> document</p>", "abbreviations|advanced");
TestParser.TestSpec("*[SUPER HTML]: Super Hypertext Markup Language\n\nThis is a SUPER HTML document ", "<p>This is a <abbr title=\"Super Hypertext Markup Language\">SUPER HTML</abbr> document</p>", "abbreviations|advanced", context: "Example 3\nSection Extensions / Abbreviation\n");
}
// Abbreviation may contain any unicode characters:
@@ -92,8 +88,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p>This is a <abbr title="Hypertext Markup Language">😃 HTML</abbr> document</p>
Console.WriteLine("Example 4\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[😃 HTML]: Hypertext Markup Language\n\nThis is a 😃 HTML document ", "<p>This is a <abbr title=\"Hypertext Markup Language\">😃 HTML</abbr> document</p>", "abbreviations|advanced");
TestParser.TestSpec("*[😃 HTML]: Hypertext Markup Language\n\nThis is a 😃 HTML document ", "<p>This is a <abbr title=\"Hypertext Markup Language\">😃 HTML</abbr> document</p>", "abbreviations|advanced", context: "Example 4\nSection Extensions / Abbreviation\n");
}
// Abbreviations may be similar:
@@ -113,8 +108,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p>We can abbreviate <abbr title="First">1A</abbr>, <abbr title="Second">1A1</abbr> and <abbr title="Third">1A2</abbr>!</p>
Console.WriteLine("Example 5\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[1A]: First\n*[1A1]: Second\n*[1A2]: Third\n\nWe can abbreviate 1A, 1A1 and 1A2!", "<p>We can abbreviate <abbr title=\"First\">1A</abbr>, <abbr title=\"Second\">1A1</abbr> and <abbr title=\"Third\">1A2</abbr>!</p>", "abbreviations|advanced");
TestParser.TestSpec("*[1A]: First\n*[1A1]: Second\n*[1A2]: Third\n\nWe can abbreviate 1A, 1A1 and 1A2!", "<p>We can abbreviate <abbr title=\"First\">1A</abbr>, <abbr title=\"Second\">1A1</abbr> and <abbr title=\"Third\">1A2</abbr>!</p>", "abbreviations|advanced", context: "Example 5\nSection Extensions / Abbreviation\n");
}
// Abbreviations should match whole word only:
@@ -132,8 +126,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p>We should not abbreviate 1.1A or 11A!</p>
Console.WriteLine("Example 6\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[1A]: First\n\nWe should not abbreviate 1.1A or 11A!", "<p>We should not abbreviate 1.1A or 11A!</p>", "abbreviations|advanced");
TestParser.TestSpec("*[1A]: First\n\nWe should not abbreviate 1.1A or 11A!", "<p>We should not abbreviate 1.1A or 11A!</p>", "abbreviations|advanced", context: "Example 6\nSection Extensions / Abbreviation\n");
}
// Abbreviations should match whole word only, even if the word is the entire content:
@@ -151,8 +144,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p>1.1A</p>
Console.WriteLine("Example 7\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[1A]: First\n\n1.1A", "<p>1.1A</p>", "abbreviations|advanced");
TestParser.TestSpec("*[1A]: First\n\n1.1A", "<p>1.1A</p>", "abbreviations|advanced", context: "Example 7\nSection Extensions / Abbreviation\n");
}
// Abbreviations should match whole word only, even if there is another glossary term:
@@ -171,8 +163,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p><abbr title="Second">SCOM</abbr></p>
Console.WriteLine("Example 8\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[SCO]: First\n*[SCOM]: Second\n\nSCOM", "<p><abbr title=\"Second\">SCOM</abbr></p>", "abbreviations|advanced");
TestParser.TestSpec("*[SCO]: First\n*[SCOM]: Second\n\nSCOM", "<p><abbr title=\"Second\">SCOM</abbr></p>", "abbreviations|advanced", context: "Example 8\nSection Extensions / Abbreviation\n");
}
// Abbreviations should only match when surrounded by whitespace:
@@ -190,8 +181,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p>PRAA</p>
Console.WriteLine("Example 9\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[PR]: Pull Request\n\nPRAA", "<p>PRAA</p>", "abbreviations|advanced");
TestParser.TestSpec("*[PR]: Pull Request\n\nPRAA", "<p>PRAA</p>", "abbreviations|advanced", context: "Example 9\nSection Extensions / Abbreviation\n");
}
// Single character abbreviations should be matched
@@ -209,8 +199,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p><abbr title="Foo">A</abbr></p>
Console.WriteLine("Example 10\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[A]: Foo\n\nA", "<p><abbr title=\"Foo\">A</abbr></p>", "abbreviations|advanced");
TestParser.TestSpec("*[A]: Foo\n\nA", "<p><abbr title=\"Foo\">A</abbr></p>", "abbreviations|advanced", context: "Example 10\nSection Extensions / Abbreviation\n");
}
// The longest matching abbreviation should be used
@@ -229,8 +218,7 @@ namespace Markdig.Tests.Specs.Abbreviations
// Should be rendered as:
// <p><abbr title="foo">Foo</abbr> B</p>
Console.WriteLine("Example 11\nSection Extensions / Abbreviation\n");
TestParser.TestSpec("*[Foo]: foo\n*[Foo Bar]: foobar\n\nFoo B", "<p><abbr title=\"foo\">Foo</abbr> B</p>", "abbreviations|advanced");
TestParser.TestSpec("*[Foo]: foo\n*[Foo Bar]: foobar\n\nFoo B", "<p><abbr title=\"foo\">Foo</abbr> B</p>", "abbreviations|advanced", context: "Example 11\nSection Extensions / Abbreviation\n");
}
}
}

View File

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

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Auto Identifiers
@@ -31,8 +30,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// Should be rendered as:
// <h1 id="this-is-a-heading">This is a heading</h1>
Console.WriteLine("Example 1\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("# This is a heading", "<h1 id=\"this-is-a-heading\">This is a heading</h1>", "autoidentifiers|advanced");
TestParser.TestSpec("# This is a heading", "<h1 id=\"this-is-a-heading\">This is a heading</h1>", "autoidentifiers|advanced", context: "Example 1\nSection Extensions / Heading Auto Identifiers\n");
}
// Only punctuation `-`, `_` and `.` is kept, all other non letter characters are discarded.
@@ -50,8 +48,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// Should be rendered as:
// <h1 id="this-is-a-heading_with.and">This - is a &amp;@! heading _ with . and ! -</h1>
Console.WriteLine("Example 2\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("# This - is a &@! heading _ with . and ! -", "<h1 id=\"this-is-a-heading_with.and\">This - is a &amp;@! heading _ with . and ! -</h1>", "autoidentifiers|advanced");
TestParser.TestSpec("# This - is a &@! heading _ with . and ! -", "<h1 id=\"this-is-a-heading_with.and\">This - is a &amp;@! heading _ with . and ! -</h1>", "autoidentifiers|advanced", context: "Example 2\nSection Extensions / Heading Auto Identifiers\n");
}
// Formatting (emphasis) are also discarded:
@@ -67,8 +64,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// Should be rendered as:
// <h1 id="this-is-a-heading">This is a <em>heading</em></h1>
Console.WriteLine("Example 3\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("# This is a *heading*", "<h1 id=\"this-is-a-heading\">This is a <em>heading</em></h1>", "autoidentifiers|advanced");
TestParser.TestSpec("# This is a *heading*", "<h1 id=\"this-is-a-heading\">This is a <em>heading</em></h1>", "autoidentifiers|advanced", context: "Example 3\nSection Extensions / Heading Auto Identifiers\n");
}
// Links are also removed:
@@ -84,8 +80,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// Should be rendered as:
// <h1 id="this-is-a-heading">This is a <a href="/url">heading</a></h1>
Console.WriteLine("Example 4\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("# This is a [heading](/url)", "<h1 id=\"this-is-a-heading\">This is a <a href=\"/url\">heading</a></h1>", "autoidentifiers|advanced");
TestParser.TestSpec("# This is a [heading](/url)", "<h1 id=\"this-is-a-heading\">This is a <a href=\"/url\">heading</a></h1>", "autoidentifiers|advanced", context: "Example 4\nSection Extensions / Heading Auto Identifiers\n");
}
// If multiple heading have the same text, -1, -2...-n will be postfix to the header id.
@@ -103,8 +98,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// <h1 id="this-is-a-heading">This is a heading</h1>
// <h1 id="this-is-a-heading-1">This is a heading</h1>
Console.WriteLine("Example 5\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("# This is a heading\n# This is a heading", "<h1 id=\"this-is-a-heading\">This is a heading</h1>\n<h1 id=\"this-is-a-heading-1\">This is a heading</h1>", "autoidentifiers|advanced");
TestParser.TestSpec("# This is a heading\n# This is a heading", "<h1 id=\"this-is-a-heading\">This is a heading</h1>\n<h1 id=\"this-is-a-heading-1\">This is a heading</h1>", "autoidentifiers|advanced", context: "Example 5\nSection Extensions / Heading Auto Identifiers\n");
}
// The heading Id will start on the first letter character of the heading, all previous characters will be discarded:
@@ -120,8 +114,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// Should be rendered as:
// <h1 id="this-is-a-heading">1.0 This is a heading</h1>
Console.WriteLine("Example 6\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("# 1.0 This is a heading", "<h1 id=\"this-is-a-heading\">1.0 This is a heading</h1>", "autoidentifiers|advanced");
TestParser.TestSpec("# 1.0 This is a heading", "<h1 id=\"this-is-a-heading\">1.0 This is a heading</h1>", "autoidentifiers|advanced", context: "Example 6\nSection Extensions / Heading Auto Identifiers\n");
}
// If the heading is all stripped by the previous rules, the id `section` will be used instead:
@@ -139,8 +132,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// <h1 id="section">1.0 &amp; ^ % *</h1>
// <h1 id="section-1">1.0 &amp; ^ % *</h1>
Console.WriteLine("Example 7\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("# 1.0 & ^ % *\n# 1.0 & ^ % *", "<h1 id=\"section\">1.0 &amp; ^ % *</h1>\n<h1 id=\"section-1\">1.0 &amp; ^ % *</h1>", "autoidentifiers|advanced");
TestParser.TestSpec("# 1.0 & ^ % *\n# 1.0 & ^ % *", "<h1 id=\"section\">1.0 &amp; ^ % *</h1>\n<h1 id=\"section-1\">1.0 &amp; ^ % *</h1>", "autoidentifiers|advanced", context: "Example 7\nSection Extensions / Heading Auto Identifiers\n");
}
// When the options "AutoLink" is setup, it is possible to link to an existing heading by using the
@@ -159,8 +151,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// <h1 id="this-is-a-heading">This is a heading</h1>
// <p><a href="#this-is-a-heading">This is a heading</a></p>
Console.WriteLine("Example 8\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("# This is a heading\n[This is a heading]", "<h1 id=\"this-is-a-heading\">This is a heading</h1>\n<p><a href=\"#this-is-a-heading\">This is a heading</a></p>", "autoidentifiers|advanced");
TestParser.TestSpec("# This is a heading\n[This is a heading]", "<h1 id=\"this-is-a-heading\">This is a heading</h1>\n<p><a href=\"#this-is-a-heading\">This is a heading</a></p>", "autoidentifiers|advanced", context: "Example 8\nSection Extensions / Heading Auto Identifiers\n");
}
// Links before the heading are also working:
@@ -178,8 +169,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// <p><a href="#this-is-a-heading">This is a heading</a></p>
// <h1 id="this-is-a-heading">This is a heading</h1>
Console.WriteLine("Example 9\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("[This is a heading]\n# This is a heading", "<p><a href=\"#this-is-a-heading\">This is a heading</a></p>\n<h1 id=\"this-is-a-heading\">This is a heading</h1>", "autoidentifiers|advanced");
TestParser.TestSpec("[This is a heading]\n# This is a heading", "<p><a href=\"#this-is-a-heading\">This is a heading</a></p>\n<h1 id=\"this-is-a-heading\">This is a heading</h1>", "autoidentifiers|advanced", context: "Example 9\nSection Extensions / Heading Auto Identifiers\n");
}
// The text of the link can be changed:
@@ -197,8 +187,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// <p><a href="#this-is-a-heading">With a new text</a></p>
// <h1 id="this-is-a-heading">This is a heading</h1>
Console.WriteLine("Example 10\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("[With a new text][This is a heading]\n# This is a heading", "<p><a href=\"#this-is-a-heading\">With a new text</a></p>\n<h1 id=\"this-is-a-heading\">This is a heading</h1>", "autoidentifiers|advanced");
TestParser.TestSpec("[With a new text][This is a heading]\n# This is a heading", "<p><a href=\"#this-is-a-heading\">With a new text</a></p>\n<h1 id=\"this-is-a-heading\">This is a heading</h1>", "autoidentifiers|advanced", context: "Example 10\nSection Extensions / Heading Auto Identifiers\n");
}
// An autoidentifier should not conflict with an existing link:
@@ -217,8 +206,7 @@ namespace Markdig.Tests.Specs.AutoIdentifiers
// <p><img src="./scenario.png" alt="scenario image" /></p>
// <h2 id="scenario">Scenario</h2>
Console.WriteLine("Example 11\nSection Extensions / Heading Auto Identifiers\n");
TestParser.TestSpec("![scenario image][scenario]\n## Scenario\n[scenario]: ./scenario.png", "<p><img src=\"./scenario.png\" alt=\"scenario image\" /></p>\n<h2 id=\"scenario\">Scenario</h2>", "autoidentifiers|advanced");
TestParser.TestSpec("![scenario image][scenario]\n## Scenario\n[scenario]: ./scenario.png", "<p><img src=\"./scenario.png\" alt=\"scenario image\" /></p>\n<h2 id=\"scenario\">Scenario</h2>", "autoidentifiers|advanced", context: "Example 11\nSection Extensions / Heading Auto Identifiers\n");
}
}
}

View File

@@ -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,17 @@ 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", context: "Example 1\nSection Extensions / AutoLinks\n");
}
// But incomplete links will not be matched:
@@ -58,15 +59,16 @@ 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", context: "Example 2\nSection Extensions / AutoLinks\n");
}
// Previous character must be a punctuation or a valid space (tab, space, new line):
@@ -82,8 +84,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p>This is not a nhttp://www.google.com URL but this is (<a href="https://www.google.com">https://www.google.com</a>)</p>
Console.WriteLine("Example 3\nSection Extensions / AutoLinks\n");
TestParser.TestSpec("This is not a nhttp://www.google.com URL but this is (https://www.google.com)", "<p>This is not a nhttp://www.google.com URL but this is (<a href=\"https://www.google.com\">https://www.google.com</a>)</p>", "autolinks|advanced");
TestParser.TestSpec("This is not a nhttp://www.google.com URL but this is (https://www.google.com)", "<p>This is not a nhttp://www.google.com URL but this is (<a href=\"https://www.google.com\">https://www.google.com</a>)</p>", "autolinks|advanced", context: "Example 3\nSection Extensions / AutoLinks\n");
}
// An autolink should not interfere with an `<a>` HTML inline:
@@ -99,8 +100,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com">http://www.google.com</a> link</p>
Console.WriteLine("Example 4\nSection Extensions / AutoLinks\n");
TestParser.TestSpec("This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link", "<p>This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link</p>", "autolinks|advanced");
TestParser.TestSpec("This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link", "<p>This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link</p>", "autolinks|advanced", context: "Example 4\nSection Extensions / AutoLinks\n");
}
// or even within emphasis:
@@ -116,8 +116,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com"> <strong>http://www.google.com</strong> </a> link</p>
Console.WriteLine("Example 5\nSection Extensions / AutoLinks\n");
TestParser.TestSpec("This is an HTML <a href=\"http://www.google.com\"> **http://www.google.com** </a> link", "<p>This is an HTML <a href=\"http://www.google.com\"> <strong>http://www.google.com</strong> </a> link</p>", "autolinks|advanced");
TestParser.TestSpec("This is an HTML <a href=\"http://www.google.com\"> **http://www.google.com** </a> link", "<p>This is an HTML <a href=\"http://www.google.com\"> <strong>http://www.google.com</strong> </a> link</p>", "autolinks|advanced", context: "Example 5\nSection Extensions / AutoLinks\n");
}
// An autolink should not interfere with a markdown link:
@@ -133,8 +132,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p>This is an HTML <a href="http://www.google.com">http://www.google.com</a> link</p>
Console.WriteLine("Example 6\nSection Extensions / AutoLinks\n");
TestParser.TestSpec("This is an HTML [http://www.google.com](http://www.google.com) link", "<p>This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link</p>", "autolinks|advanced");
TestParser.TestSpec("This is an HTML [http://www.google.com](http://www.google.com) link", "<p>This is an HTML <a href=\"http://www.google.com\">http://www.google.com</a> link</p>", "autolinks|advanced", context: "Example 6\nSection Extensions / AutoLinks\n");
}
// A link embraced by pending emphasis should let the emphasis takes precedence if characters are placed at the end of the matched link:
@@ -150,8 +148,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p>Check <strong><a href="http://www.a.com">http://www.a.com</a></strong> or <strong><a href="http://www.b.com">http://www.b.com</a></strong></p>
Console.WriteLine("Example 7\nSection Extensions / AutoLinks\n");
TestParser.TestSpec("Check **http://www.a.com** or __http://www.b.com__", "<p>Check <strong><a href=\"http://www.a.com\">http://www.a.com</a></strong> or <strong><a href=\"http://www.b.com\">http://www.b.com</a></strong></p>", "autolinks|advanced");
TestParser.TestSpec("Check **http://www.a.com** or __http://www.b.com__", "<p>Check <strong><a href=\"http://www.a.com\">http://www.a.com</a></strong> or <strong><a href=\"http://www.b.com\">http://www.b.com</a></strong></p>", "autolinks|advanced", context: "Example 7\nSection Extensions / AutoLinks\n");
}
// It is not mentioned by the spec, but empty emails won't be matched (only a subset of [RFC2368](https://tools.ietf.org/html/rfc2368) is supported by auto links):
@@ -167,8 +164,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p><a href="mailto:email@test.com">email@test.com</a> is okay, but mailto:@test.com is not</p>
Console.WriteLine("Example 8\nSection Extensions / AutoLinks\n");
TestParser.TestSpec("mailto:email@test.com is okay, but mailto:@test.com is not", "<p><a href=\"mailto:email@test.com\">email@test.com</a> is okay, but mailto:@test.com is not</p>", "autolinks|advanced");
TestParser.TestSpec("mailto:email@test.com is okay, but mailto:@test.com is not", "<p><a href=\"mailto:email@test.com\">email@test.com</a> is okay, but mailto:@test.com is not</p>", "autolinks|advanced", context: "Example 8\nSection Extensions / AutoLinks\n");
}
}
@@ -190,8 +186,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p><a href="http://www.commonmark.org">www.commonmark.org</a></p>
Console.WriteLine("Example 9\nSection Extensions / AutoLinks / GFM Support\n");
TestParser.TestSpec("www.commonmark.org", "<p><a href=\"http://www.commonmark.org\">www.commonmark.org</a></p>", "autolinks|advanced");
TestParser.TestSpec("www.commonmark.org", "<p><a href=\"http://www.commonmark.org\">www.commonmark.org</a></p>", "autolinks|advanced", context: "Example 9\nSection Extensions / AutoLinks / GFM Support\n");
}
[Test]
@@ -206,8 +201,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p>Visit <a href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
Console.WriteLine("Example 10\nSection Extensions / AutoLinks / GFM Support\n");
TestParser.TestSpec("Visit www.commonmark.org/help for more information.", "<p>Visit <a href=\"http://www.commonmark.org/help\">www.commonmark.org/help</a> for more information.</p>", "autolinks|advanced");
TestParser.TestSpec("Visit www.commonmark.org/help for more information.", "<p>Visit <a href=\"http://www.commonmark.org/help\">www.commonmark.org/help</a> for more information.</p>", "autolinks|advanced", context: "Example 10\nSection Extensions / AutoLinks / GFM Support\n");
}
[Test]
@@ -225,8 +219,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// <p>Visit <a href="http://www.commonmark.org">www.commonmark.org</a>.</p>
// <p>Visit <a href="http://www.commonmark.org/a.b">www.commonmark.org/a.b</a>.</p>
Console.WriteLine("Example 11\nSection Extensions / AutoLinks / GFM Support\n");
TestParser.TestSpec("Visit www.commonmark.org.\n\nVisit www.commonmark.org/a.b.", "<p>Visit <a href=\"http://www.commonmark.org\">www.commonmark.org</a>.</p>\n<p>Visit <a href=\"http://www.commonmark.org/a.b\">www.commonmark.org/a.b</a>.</p>", "autolinks|advanced");
TestParser.TestSpec("Visit www.commonmark.org.\n\nVisit www.commonmark.org/a.b.", "<p>Visit <a href=\"http://www.commonmark.org\">www.commonmark.org</a>.</p>\n<p>Visit <a href=\"http://www.commonmark.org/a.b\">www.commonmark.org/a.b</a>.</p>", "autolinks|advanced", context: "Example 11\nSection Extensions / AutoLinks / GFM Support\n");
}
[Test]
@@ -244,8 +237,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// <p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
// <p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>)</p>
Console.WriteLine("Example 12\nSection Extensions / AutoLinks / GFM Support\n");
TestParser.TestSpec("www.google.com/search?q=Markup+(business)\n\n(www.google.com/search?q=Markup+(business))", "<p><a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a></p>\n<p>(<a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a>)</p>", "autolinks|advanced");
TestParser.TestSpec("www.google.com/search?q=Markup+(business)\n\n(www.google.com/search?q=Markup+(business))", "<p><a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a></p>\n<p>(<a href=\"http://www.google.com/search?q=Markup+(business)\">www.google.com/search?q=Markup+(business)</a>)</p>", "autolinks|advanced", context: "Example 12\nSection Extensions / AutoLinks / GFM Support\n");
}
[Test]
@@ -263,8 +255,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// <p><a href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
// <p><a href="http://www.google.com/search?q=commonmark">www.google.com/search?q=commonmark</a>&amp;hl;</p>
Console.WriteLine("Example 13\nSection Extensions / AutoLinks / GFM Support\n");
TestParser.TestSpec("www.google.com/search?q=commonmark&hl=en\n\nwww.google.com/search?q=commonmark&hl;", "<p><a href=\"http://www.google.com/search?q=commonmark&amp;hl=en\">www.google.com/search?q=commonmark&amp;hl=en</a></p>\n<p><a href=\"http://www.google.com/search?q=commonmark\">www.google.com/search?q=commonmark</a>&amp;hl;</p>", "autolinks|advanced");
TestParser.TestSpec("www.google.com/search?q=commonmark&hl=en\n\nwww.google.com/search?q=commonmark&hl;", "<p><a href=\"http://www.google.com/search?q=commonmark&amp;hl=en\">www.google.com/search?q=commonmark&amp;hl=en</a></p>\n<p><a href=\"http://www.google.com/search?q=commonmark\">www.google.com/search?q=commonmark</a>&amp;hl;</p>", "autolinks|advanced", context: "Example 13\nSection Extensions / AutoLinks / GFM Support\n");
}
[Test]
@@ -279,8 +270,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
Console.WriteLine("Example 14\nSection Extensions / AutoLinks / GFM Support\n");
TestParser.TestSpec("www.commonmark.org/he<lp", "<p><a href=\"http://www.commonmark.org/he\">www.commonmark.org/he</a>&lt;lp</p>", "autolinks|advanced");
TestParser.TestSpec("www.commonmark.org/he<lp", "<p><a href=\"http://www.commonmark.org/he\">www.commonmark.org/he</a>&lt;lp</p>", "autolinks|advanced", context: "Example 14\nSection Extensions / AutoLinks / GFM Support\n");
}
[Test]
@@ -301,8 +291,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// <p>(Visit <a href="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
// <p>Anonymous FTP is available at <a href="ftp://foo.bar.baz">ftp://foo.bar.baz</a>.</p>
Console.WriteLine("Example 15\nSection Extensions / AutoLinks / GFM Support\n");
TestParser.TestSpec("http://commonmark.org\n\n(Visit https://encrypted.google.com/search?q=Markup+(business))\n\nAnonymous FTP is available at ftp://foo.bar.baz.", "<p><a href=\"http://commonmark.org\">http://commonmark.org</a></p>\n<p>(Visit <a href=\"https://encrypted.google.com/search?q=Markup+(business)\">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>\n<p>Anonymous FTP is available at <a href=\"ftp://foo.bar.baz\">ftp://foo.bar.baz</a>.</p>", "autolinks|advanced");
TestParser.TestSpec("http://commonmark.org\n\n(Visit https://encrypted.google.com/search?q=Markup+(business))\n\nAnonymous FTP is available at ftp://foo.bar.baz.", "<p><a href=\"http://commonmark.org\">http://commonmark.org</a></p>\n<p>(Visit <a href=\"https://encrypted.google.com/search?q=Markup+(business)\">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>\n<p>Anonymous FTP is available at <a href=\"ftp://foo.bar.baz\">ftp://foo.bar.baz</a>.</p>", "autolinks|advanced", context: "Example 15\nSection Extensions / AutoLinks / GFM Support\n");
}
}
@@ -342,8 +331,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// mailto:email@test.
// mailto:email@.test</p>
Console.WriteLine("Example 16\nSection Extensions / AutoLinks / Valid Domain Tests\n");
TestParser.TestSpec("www..\nwww..com\nhttp://test.\nhttp://.test\nhttp://.\nhttp://..\nftp://test.\nftp://.test\nmailto:email@test.\nmailto:email@.test", "<p>www..\nwww..com\nhttp://test.\nhttp://.test\nhttp://.\nhttp://..\nftp://test.\nftp://.test\nmailto:email@test.\nmailto:email@.test</p>", "autolinks|advanced");
TestParser.TestSpec("www..\nwww..com\nhttp://test.\nhttp://.test\nhttp://.\nhttp://..\nftp://test.\nftp://.test\nmailto:email@test.\nmailto:email@.test", "<p>www..\nwww..com\nhttp://test.\nhttp://.test\nhttp://.\nhttp://..\nftp://test.\nftp://.test\nmailto:email@test.\nmailto:email@.test</p>", "autolinks|advanced", context: "Example 16\nSection Extensions / AutoLinks / Valid Domain Tests\n");
}
// Domain names with too few segments won't be matched
@@ -367,8 +355,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// ftp://test
// mailto:email@test</p>
Console.WriteLine("Example 17\nSection Extensions / AutoLinks / Valid Domain Tests\n");
TestParser.TestSpec("www\nwww.com\nhttp://test\nftp://test\nmailto:email@test", "<p>www\nwww.com\nhttp://test\nftp://test\nmailto:email@test</p>", "autolinks|advanced");
TestParser.TestSpec("www\nwww.com\nhttp://test\nftp://test\nmailto:email@test", "<p>www\nwww.com\nhttp://test\nftp://test\nmailto:email@test</p>", "autolinks|advanced", context: "Example 17\nSection Extensions / AutoLinks / Valid Domain Tests\n");
}
// Domain names that contain an underscores in the last two segments won't be matched
@@ -396,8 +383,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// <p><a href="ftp://test_.foo.bar">ftp://test_.foo.bar</a> is okay, but ftp://test.fo_o is not</p>
// <p><a href="mailto:email@_test.foo.bar">email@_test.foo.bar</a> is okay, but mailto:email@_test.foo is not</p>
Console.WriteLine("Example 18\nSection Extensions / AutoLinks / Valid Domain Tests\n");
TestParser.TestSpec("www._test.foo.bar is okay, but www._test.foo is not\n\nhttp://te_st.foo.bar is okay, as is http://test.foo_.bar.foo\n\nBut http://te_st.foo, http://test.foo_.bar and http://test._foo are not\n\nftp://test_.foo.bar is okay, but ftp://test.fo_o is not\n\nmailto:email@_test.foo.bar is okay, but mailto:email@_test.foo is not", "<p><a href=\"http://www._test.foo.bar\">www._test.foo.bar</a> is okay, but www._test.foo is not</p>\n<p><a href=\"http://te_st.foo.bar\">http://te_st.foo.bar</a> is okay, as is <a href=\"http://test.foo_.bar.foo\">http://test.foo_.bar.foo</a></p>\n<p>But http://te_st.foo, http://test.foo_.bar and http://test._foo are not</p>\n<p><a href=\"ftp://test_.foo.bar\">ftp://test_.foo.bar</a> is okay, but ftp://test.fo_o is not</p>\n<p><a href=\"mailto:email@_test.foo.bar\">email@_test.foo.bar</a> is okay, but mailto:email@_test.foo is not</p>", "autolinks|advanced");
TestParser.TestSpec("www._test.foo.bar is okay, but www._test.foo is not\n\nhttp://te_st.foo.bar is okay, as is http://test.foo_.bar.foo\n\nBut http://te_st.foo, http://test.foo_.bar and http://test._foo are not\n\nftp://test_.foo.bar is okay, but ftp://test.fo_o is not\n\nmailto:email@_test.foo.bar is okay, but mailto:email@_test.foo is not", "<p><a href=\"http://www._test.foo.bar\">www._test.foo.bar</a> is okay, but www._test.foo is not</p>\n<p><a href=\"http://te_st.foo.bar\">http://te_st.foo.bar</a> is okay, as is <a href=\"http://test.foo_.bar.foo\">http://test.foo_.bar.foo</a></p>\n<p>But http://te_st.foo, http://test.foo_.bar and http://test._foo are not</p>\n<p><a href=\"ftp://test_.foo.bar\">ftp://test_.foo.bar</a> is okay, but ftp://test.fo_o is not</p>\n<p><a href=\"mailto:email@_test.foo.bar\">email@_test.foo.bar</a> is okay, but mailto:email@_test.foo is not</p>", "autolinks|advanced", context: "Example 18\nSection Extensions / AutoLinks / Valid Domain Tests\n");
}
// Domain names that contain invalid characters (not AlphaNumberic, -, _ or .) won't be matched
@@ -413,8 +399,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p>https://[your-domain]/api</p>
Console.WriteLine("Example 19\nSection Extensions / AutoLinks / Valid Domain Tests\n");
TestParser.TestSpec("https://[your-domain]/api", "<p>https://[your-domain]/api</p>", "autolinks|advanced");
TestParser.TestSpec("https://[your-domain]/api", "<p>https://[your-domain]/api</p>", "autolinks|advanced", context: "Example 19\nSection Extensions / AutoLinks / Valid Domain Tests\n");
}
// Domain names followed by ?, : or # instead of / are matched
@@ -442,8 +427,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// <p><a href="https://github.com">https://github.com</a>:</p>
// <p><a href="https://github.com:443">https://github.com:443</a></p>
Console.WriteLine("Example 20\nSection Extensions / AutoLinks / Valid Domain Tests\n");
TestParser.TestSpec("https://github.com?\n\nhttps://github.com?a\n\nhttps://github.com#a\n\nhttps://github.com:\n\nhttps://github.com:443", "<p><a href=\"https://github.com\">https://github.com</a>?</p>\n<p><a href=\"https://github.com?a\">https://github.com?a</a></p>\n<p><a href=\"https://github.com#a\">https://github.com#a</a></p>\n<p><a href=\"https://github.com\">https://github.com</a>:</p>\n<p><a href=\"https://github.com:443\">https://github.com:443</a></p>", "autolinks|advanced");
TestParser.TestSpec("https://github.com?\n\nhttps://github.com?a\n\nhttps://github.com#a\n\nhttps://github.com:\n\nhttps://github.com:443", "<p><a href=\"https://github.com\">https://github.com</a>?</p>\n<p><a href=\"https://github.com?a\">https://github.com?a</a></p>\n<p><a href=\"https://github.com#a\">https://github.com#a</a></p>\n<p><a href=\"https://github.com\">https://github.com</a>:</p>\n<p><a href=\"https://github.com:443\">https://github.com:443</a></p>", "autolinks|advanced", context: "Example 20\nSection Extensions / AutoLinks / Valid Domain Tests\n");
}
}
@@ -474,8 +458,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// <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>
Console.WriteLine("Example 21\nSection Extensions / AutoLinks / Unicode support\n");
TestParser.TestSpec("http://abc.net/☃\n\nhttp://abc.net?☃\n\nhttp://abc.net#☃\n\nhttp://abc.net/foo#☃", "<p><a href=\"http://abc.net/%E2%98%83\">http://abc.net/☃</a></p>\n<p><a href=\"http://abc.net?%E2%98%83\">http://abc.net?☃</a></p>\n<p><a href=\"http://abc.net#%E2%98%83\">http://abc.net#☃</a></p>\n<p><a href=\"http://abc.net/foo#%E2%98%83\">http://abc.net/foo#☃</a></p>", "autolinks|advanced");
TestParser.TestSpec("http://abc.net/☃\n\nhttp://abc.net?☃\n\nhttp://abc.net#☃\n\nhttp://abc.net/foo#☃", "<p><a href=\"http://abc.net/%E2%98%83\">http://abc.net/☃</a></p>\n<p><a href=\"http://abc.net?%E2%98%83\">http://abc.net?☃</a></p>\n<p><a href=\"http://abc.net#%E2%98%83\">http://abc.net#☃</a></p>\n<p><a href=\"http://abc.net/foo#%E2%98%83\">http://abc.net/foo#☃</a></p>", "autolinks|advanced", context: "Example 21\nSection Extensions / AutoLinks / Unicode support\n");
}
// Unicode characters in the FQDN are matched and IDNA encoded
@@ -491,8 +474,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p><a href="http://xn--n3h.net?%E2%98%83">http://☃.net?☃</a></p>
Console.WriteLine("Example 22\nSection Extensions / AutoLinks / Unicode support\n");
TestParser.TestSpec("http://☃.net?☃", "<p><a href=\"http://xn--n3h.net?%E2%98%83\">http://☃.net?☃</a></p>", "autolinks|advanced");
TestParser.TestSpec("http://☃.net?☃", "<p><a href=\"http://xn--n3h.net?%E2%98%83\">http://☃.net?☃</a></p>", "autolinks|advanced", context: "Example 22\nSection Extensions / AutoLinks / Unicode support\n");
}
// Same goes for regular autolinks
@@ -517,8 +499,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// <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>
Console.WriteLine("Example 23\nSection Extensions / AutoLinks / Unicode support\n");
TestParser.TestSpec("<http://abc.net/☃>\n\n<http://abc.net?☃>\n\n<http://abc.net#☃>\n\n<http://abc.net/foo#☃>", "<p><a href=\"http://abc.net/%E2%98%83\">http://abc.net/☃</a></p>\n<p><a href=\"http://abc.net?%E2%98%83\">http://abc.net?☃</a></p>\n<p><a href=\"http://abc.net#%E2%98%83\">http://abc.net#☃</a></p>\n<p><a href=\"http://abc.net/foo#%E2%98%83\">http://abc.net/foo#☃</a></p>", "autolinks|advanced");
TestParser.TestSpec("<http://abc.net/☃>\n\n<http://abc.net?☃>\n\n<http://abc.net#☃>\n\n<http://abc.net/foo#☃>", "<p><a href=\"http://abc.net/%E2%98%83\">http://abc.net/☃</a></p>\n<p><a href=\"http://abc.net?%E2%98%83\">http://abc.net?☃</a></p>\n<p><a href=\"http://abc.net#%E2%98%83\">http://abc.net#☃</a></p>\n<p><a href=\"http://abc.net/foo#%E2%98%83\">http://abc.net/foo#☃</a></p>", "autolinks|advanced", context: "Example 23\nSection Extensions / AutoLinks / Unicode support\n");
}
[Test]
@@ -533,8 +514,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p><a href="http://xn--n3h.net?%E2%98%83">http://☃.net?☃</a></p>
Console.WriteLine("Example 24\nSection Extensions / AutoLinks / Unicode support\n");
TestParser.TestSpec("<http://☃.net?☃>", "<p><a href=\"http://xn--n3h.net?%E2%98%83\">http://☃.net?☃</a></p>", "autolinks|advanced");
TestParser.TestSpec("<http://☃.net?☃>", "<p><a href=\"http://xn--n3h.net?%E2%98%83\">http://☃.net?☃</a></p>", "autolinks|advanced", context: "Example 24\nSection Extensions / AutoLinks / Unicode support\n");
}
// It also complies with CommonMark's vision of priority.
@@ -551,8 +531,7 @@ namespace Markdig.Tests.Specs.AutoLinks
// Should be rendered as:
// <p><a href="http://xn--fo-gka.bar.%60baz">http://foö.bar.`baz</a>`</p>
Console.WriteLine("Example 25\nSection Extensions / AutoLinks / Unicode support\n");
TestParser.TestSpec("<http://foö.bar.`baz>`", "<p><a href=\"http://xn--fo-gka.bar.%60baz\">http://foö.bar.`baz</a>`</p>", "autolinks|advanced");
TestParser.TestSpec("<http://foö.bar.`baz>`", "<p><a href=\"http://xn--fo-gka.bar.%60baz\">http://foö.bar.`baz</a>`</p>", "autolinks|advanced", context: "Example 25\nSection Extensions / AutoLinks / Unicode support\n");
}
}
}

View File

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

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-15 05:23:49
// --------------------------------
// Bootstrap
@@ -46,8 +45,7 @@ namespace Markdig.Tests.Specs.Bootstrap
// </tbody>
// </table>
Console.WriteLine("Example 1\nSection Extensions / Bootstrap\n");
TestParser.TestSpec("Name | Value\n-----| -----\nAbc | 16", "<table class=\"table\">\n<thead>\n<tr>\n<th>Name</th>\n<th>Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Abc</td>\n<td>16</td>\n</tr>\n</tbody>\n</table>", "bootstrap+pipetables+figures+attributes");
TestParser.TestSpec("Name | Value\n-----| -----\nAbc | 16", "<table class=\"table\">\n<thead>\n<tr>\n<th>Name</th>\n<th>Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Abc</td>\n<td>16</td>\n</tr>\n</tbody>\n</table>", "bootstrap+pipetables+figures+attributes", context: "Example 1\nSection Extensions / Bootstrap\n");
}
// Adds bootstrap `.blockquote` class to `<blockquote>`:
@@ -65,8 +63,7 @@ namespace Markdig.Tests.Specs.Bootstrap
// <p>This is a blockquote</p>
// </blockquote>
Console.WriteLine("Example 2\nSection Extensions / Bootstrap\n");
TestParser.TestSpec("> This is a blockquote", "<blockquote class=\"blockquote\">\n<p>This is a blockquote</p>\n</blockquote>", "bootstrap+pipetables+figures+attributes");
TestParser.TestSpec("> This is a blockquote", "<blockquote class=\"blockquote\">\n<p>This is a blockquote</p>\n</blockquote>", "bootstrap+pipetables+figures+attributes", context: "Example 2\nSection Extensions / Bootstrap\n");
}
// Adds bootstrap `.figure` class to `<figure>` and `.figure-caption` to `<figcaption>`
@@ -87,8 +84,7 @@ namespace Markdig.Tests.Specs.Bootstrap
// <figcaption class="figure-caption">This is the caption</figcaption>
// </figure>
Console.WriteLine("Example 3\nSection Extensions / Bootstrap\n");
TestParser.TestSpec("^^^\nThis is a text in a caption\n^^^ This is the caption", "<figure class=\"figure\">\n<p>This is a text in a caption</p>\n<figcaption class=\"figure-caption\">This is the caption</figcaption>\n</figure>", "bootstrap+pipetables+figures+attributes");
TestParser.TestSpec("^^^\nThis is a text in a caption\n^^^ This is the caption", "<figure class=\"figure\">\n<p>This is a text in a caption</p>\n<figcaption class=\"figure-caption\">This is the caption</figcaption>\n</figure>", "bootstrap+pipetables+figures+attributes", context: "Example 3\nSection Extensions / Bootstrap\n");
}
// Adds the `.img-fluid` class to all image links `<img>`
@@ -104,8 +100,7 @@ namespace Markdig.Tests.Specs.Bootstrap
// Should be rendered as:
// <p><img src="/url" class="img-fluid" alt="Image Link" /></p>
Console.WriteLine("Example 4\nSection Extensions / Bootstrap\n");
TestParser.TestSpec("![Image Link](/url)", "<p><img src=\"/url\" class=\"img-fluid\" alt=\"Image Link\" /></p>", "bootstrap+pipetables+figures+attributes");
TestParser.TestSpec("![Image Link](/url)", "<p><img src=\"/url\" class=\"img-fluid\" alt=\"Image Link\" /></p>", "bootstrap+pipetables+figures+attributes", context: "Example 4\nSection Extensions / Bootstrap\n");
}
}
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Custom Containers
@@ -34,8 +33,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// <div class="spoiler"><p>This is a <em>spoiler</em></p>
// </div>
Console.WriteLine("Example 1\nSection Extensions / Custom Container\n");
TestParser.TestSpec(":::spoiler\nThis is a *spoiler*\n:::", "<div class=\"spoiler\"><p>This is a <em>spoiler</em></p>\n</div>", "customcontainers+attributes|advanced");
TestParser.TestSpec(":::spoiler\nThis is a *spoiler*\n:::", "<div class=\"spoiler\"><p>This is a <em>spoiler</em></p>\n</div>", "customcontainers+attributes|advanced", context: "Example 1\nSection Extensions / Custom Container\n");
}
// The text following the opened custom container is optional:
@@ -54,8 +52,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// <div><p>This is a regular div</p>
// </div>
Console.WriteLine("Example 2\nSection Extensions / Custom Container\n");
TestParser.TestSpec(":::\nThis is a regular div\n:::", "<div><p>This is a regular div</p>\n</div>", "customcontainers+attributes|advanced");
TestParser.TestSpec(":::\nThis is a regular div\n:::", "<div><p>This is a regular div</p>\n</div>", "customcontainers+attributes|advanced", context: "Example 2\nSection Extensions / Custom Container\n");
}
// Like for fenced code block, you can use more than 3 `:` characters as long as the closing has the same number of characters:
@@ -74,8 +71,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// <div class="spoiler"><p>This is a spoiler</p>
// </div>
Console.WriteLine("Example 3\nSection Extensions / Custom Container\n");
TestParser.TestSpec("::::::::::::spoiler\nThis is a spoiler\n::::::::::::", "<div class=\"spoiler\"><p>This is a spoiler</p>\n</div>", "customcontainers+attributes|advanced");
TestParser.TestSpec("::::::::::::spoiler\nThis is a spoiler\n::::::::::::", "<div class=\"spoiler\"><p>This is a spoiler</p>\n</div>", "customcontainers+attributes|advanced", context: "Example 3\nSection Extensions / Custom Container\n");
}
// Like for fenced code block, a custom container can span over multiple empty lines in a list block:
@@ -107,8 +103,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// <li>A second item in the list</li>
// </ul>
Console.WriteLine("Example 4\nSection Extensions / Custom Container\n");
TestParser.TestSpec("- This is a list\n :::spoiler\n This is a spoiler\n - item1\n - item2\n :::\n- A second item in the list", "<ul>\n<li>This is a list\n<div class=\"spoiler\">This is a spoiler\n<ul>\n<li>item1</li>\n<li>item2</li>\n</ul>\n</div>\n</li>\n<li>A second item in the list</li>\n</ul>", "customcontainers+attributes|advanced");
TestParser.TestSpec("- This is a list\n :::spoiler\n This is a spoiler\n - item1\n - item2\n :::\n- A second item in the list", "<ul>\n<li>This is a list\n<div class=\"spoiler\">This is a spoiler\n<ul>\n<li>item1</li>\n<li>item2</li>\n</ul>\n</div>\n</li>\n<li>A second item in the list</li>\n</ul>", "customcontainers+attributes|advanced", context: "Example 4\nSection Extensions / Custom Container\n");
}
// Attributes extension is also supported for Custom Container, as long as the Attributes extension is activated after the CustomContainer extension (`.UseCustomContainer().UseAttributes()`)
@@ -127,8 +122,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// <div id="myspoiler" class="spoiler" myprop="yes"><p>This is a spoiler</p>
// </div>
Console.WriteLine("Example 5\nSection Extensions / Custom Container\n");
TestParser.TestSpec(":::spoiler {#myspoiler myprop=yes}\nThis is a spoiler\n:::", "<div id=\"myspoiler\" class=\"spoiler\" myprop=\"yes\"><p>This is a spoiler</p>\n</div>", "customcontainers+attributes|advanced");
TestParser.TestSpec(":::spoiler {#myspoiler myprop=yes}\nThis is a spoiler\n:::", "<div id=\"myspoiler\" class=\"spoiler\" myprop=\"yes\"><p>This is a spoiler</p>\n</div>", "customcontainers+attributes|advanced", context: "Example 5\nSection Extensions / Custom Container\n");
}
// The content of a custom container can contain any blocks:
@@ -147,8 +141,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// <div class="mycontainer"><p>This is a raw spoiler</p>
// </div>
Console.WriteLine("Example 6\nSection Extensions / Custom Container\n");
TestParser.TestSpec(":::mycontainer\n<p>This is a raw spoiler</p>\n:::", "<div class=\"mycontainer\"><p>This is a raw spoiler</p>\n</div>", "customcontainers+attributes|advanced");
TestParser.TestSpec(":::mycontainer\n<p>This is a raw spoiler</p>\n:::", "<div class=\"mycontainer\"><p>This is a raw spoiler</p>\n</div>", "customcontainers+attributes|advanced", context: "Example 6\nSection Extensions / Custom Container\n");
}
}
@@ -170,8 +163,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// Should be rendered as:
// <p>This is a text <span>with special emphasis</span></p>
Console.WriteLine("Example 7\nSection Extensions / Inline Custom Container \n");
TestParser.TestSpec("This is a text ::with special emphasis::", "<p>This is a text <span>with special emphasis</span></p>", "customcontainers+attributes|advanced");
TestParser.TestSpec("This is a text ::with special emphasis::", "<p>This is a text <span>with special emphasis</span></p>", "customcontainers+attributes|advanced", context: "Example 7\nSection Extensions / Inline Custom Container \n");
}
// Any other emphasis inline can be used within this emphasis inline container:
@@ -187,8 +179,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// Should be rendered as:
// <p>This is a text <span>with special <em>emphasis</em></span></p>
Console.WriteLine("Example 8\nSection Extensions / Inline Custom Container \n");
TestParser.TestSpec("This is a text ::with special *emphasis*::", "<p>This is a text <span>with special <em>emphasis</em></span></p>", "customcontainers+attributes|advanced");
TestParser.TestSpec("This is a text ::with special *emphasis*::", "<p>This is a text <span>with special <em>emphasis</em></span></p>", "customcontainers+attributes|advanced", context: "Example 8\nSection Extensions / Inline Custom Container \n");
}
// Attributes can be attached to a inline custom container:
@@ -204,8 +195,7 @@ namespace Markdig.Tests.Specs.CustomContainers
// Should be rendered as:
// <p>This is a text <span id="myId" class="myemphasis">with special emphasis</span></p>
Console.WriteLine("Example 9\nSection Extensions / Inline Custom Container \n");
TestParser.TestSpec("This is a text ::with special emphasis::{#myId .myemphasis}", "<p>This is a text <span id=\"myId\" class=\"myemphasis\">with special emphasis</span></p>", "customcontainers+attributes|advanced");
TestParser.TestSpec("This is a text ::with special emphasis::{#myId .myemphasis}", "<p>This is a text <span id=\"myId\" class=\"myemphasis\">with special emphasis</span></p>", "customcontainers+attributes|advanced", context: "Example 9\nSection Extensions / Inline Custom Container \n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-15 05:06:35
// --------------------------------
// Definition Lists
@@ -72,8 +71,7 @@ namespace Markdig.Tests.Specs.DefinitionLists
// <dd>This is another definition for term2</dd>
// </dl>
Console.WriteLine("Example 1\nSection Extensions / Definition lists\n");
TestParser.TestSpec("\nTerm 1\n: This is a definition item\n With a paragraph\n > This is a block quote\n\n - This is a list\n - with an item2\n\n ```java\n Test\n\n\n ```\n\n And a last line\n: This ia another definition item\n\nTerm2\nTerm3 *with some inline*\n: This is another definition for term2", "<dl>\n<dt>Term 1</dt>\n<dd><p>This is a definition item\nWith a paragraph</p>\n<blockquote>\n<p>This is a block quote</p>\n</blockquote>\n<ul>\n<li>This is a list</li>\n<li>with an item2</li>\n</ul>\n<pre><code class=\"language-java\">Test\n\n\n</code></pre>\n<p>And a last line</p>\n</dd>\n<dd>This ia another definition item</dd>\n<dt>Term2</dt>\n<dt>Term3 <em>with some inline</em></dt>\n<dd>This is another definition for term2</dd>\n</dl>", "definitionlists+attributes|advanced");
TestParser.TestSpec("\nTerm 1\n: This is a definition item\n With a paragraph\n > This is a block quote\n\n - This is a list\n - with an item2\n\n ```java\n Test\n\n\n ```\n\n And a last line\n: This ia another definition item\n\nTerm2\nTerm3 *with some inline*\n: This is another definition for term2", "<dl>\n<dt>Term 1</dt>\n<dd><p>This is a definition item\nWith a paragraph</p>\n<blockquote>\n<p>This is a block quote</p>\n</blockquote>\n<ul>\n<li>This is a list</li>\n<li>with an item2</li>\n</ul>\n<pre><code class=\"language-java\">Test\n\n\n</code></pre>\n<p>And a last line</p>\n</dd>\n<dd>This ia another definition item</dd>\n<dt>Term2</dt>\n<dt>Term3 <em>with some inline</em></dt>\n<dd>This is another definition for term2</dd>\n</dl>", "definitionlists+attributes|advanced", context: "Example 1\nSection Extensions / Definition lists\n");
}
// A definition term can be followed at most by one blank line. Lazy continuations are supported for definitions:
@@ -100,8 +98,7 @@ namespace Markdig.Tests.Specs.DefinitionLists
// </dd>
// </dl>
Console.WriteLine("Example 2\nSection Extensions / Definition lists\n");
TestParser.TestSpec("Term 1\n\n: Definition\nwith lazy continuation.\n\n Second paragraph of the definition.", "<dl>\n<dt>Term 1</dt>\n<dd><p>Definition\nwith lazy continuation.</p>\n<p>Second paragraph of the definition.</p>\n</dd>\n</dl>", "definitionlists+attributes|advanced");
TestParser.TestSpec("Term 1\n\n: Definition\nwith lazy continuation.\n\n Second paragraph of the definition.", "<dl>\n<dt>Term 1</dt>\n<dd><p>Definition\nwith lazy continuation.</p>\n<p>Second paragraph of the definition.</p>\n</dd>\n</dl>", "definitionlists+attributes|advanced", context: "Example 2\nSection Extensions / Definition lists\n");
}
// The definition must be indented to 4 characters including the `:`.
@@ -119,8 +116,7 @@ namespace Markdig.Tests.Specs.DefinitionLists
// <p>Term 1
// : Invalid with less than 3 characters</p>
Console.WriteLine("Example 3\nSection Extensions / Definition lists\n");
TestParser.TestSpec("Term 1\n: Invalid with less than 3 characters", "<p>Term 1\n: Invalid with less than 3 characters</p>", "definitionlists+attributes|advanced");
TestParser.TestSpec("Term 1\n: Invalid with less than 3 characters", "<p>Term 1\n: Invalid with less than 3 characters</p>", "definitionlists+attributes|advanced", context: "Example 3\nSection Extensions / Definition lists\n");
}
// The `:` can be indented up to 3 spaces:
@@ -140,8 +136,7 @@ namespace Markdig.Tests.Specs.DefinitionLists
// <dd>Valid even if <code>:</code> starts at most 3 spaces</dd>
// </dl>
Console.WriteLine("Example 4\nSection Extensions / Definition lists\n");
TestParser.TestSpec("Term 1\n : Valid even if `:` starts at most 3 spaces", "<dl>\n<dt>Term 1</dt>\n<dd>Valid even if <code>:</code> starts at most 3 spaces</dd>\n</dl>", "definitionlists+attributes|advanced");
TestParser.TestSpec("Term 1\n : Valid even if `:` starts at most 3 spaces", "<dl>\n<dt>Term 1</dt>\n<dd>Valid even if <code>:</code> starts at most 3 spaces</dd>\n</dl>", "definitionlists+attributes|advanced", context: "Example 4\nSection Extensions / Definition lists\n");
}
// But more than 3 spaces before `:` will trigger an indented code block:
@@ -161,8 +156,7 @@ namespace Markdig.Tests.Specs.DefinitionLists
// <pre><code>: Not valid
// </code></pre>
Console.WriteLine("Example 5\nSection Extensions / Definition lists\n");
TestParser.TestSpec("Term 1\n\n : Not valid", "<p>Term 1</p>\n<pre><code>: Not valid\n</code></pre>", "definitionlists+attributes|advanced");
TestParser.TestSpec("Term 1\n\n : Not valid", "<p>Term 1</p>\n<pre><code>: Not valid\n</code></pre>", "definitionlists+attributes|advanced", context: "Example 5\nSection Extensions / Definition lists\n");
}
// Definition lists can be nested inside list items
@@ -195,8 +189,7 @@ namespace Markdig.Tests.Specs.DefinitionLists
// </dl></li>
// </ol>
Console.WriteLine("Example 6\nSection Extensions / Definition lists\n");
TestParser.TestSpec("1. First\n \n2. Second\n \n Term 1\n : Definition\n \n Term 2\n : Second Definition", "<ol>\n<li><p>First</p></li>\n<li><p>Second</p>\n<dl>\n<dt>Term 1</dt>\n<dd>Definition</dd>\n<dt>Term 2</dt>\n<dd>Second Definition</dd>\n</dl></li>\n</ol>", "definitionlists+attributes|advanced");
TestParser.TestSpec("1. First\n \n2. Second\n \n Term 1\n : Definition\n \n Term 2\n : Second Definition", "<ol>\n<li><p>First</p></li>\n<li><p>Second</p>\n<dl>\n<dt>Term 1</dt>\n<dd>Definition</dd>\n<dt>Term 2</dt>\n<dd>Second Definition</dd>\n</dl></li>\n</ol>", "definitionlists+attributes|advanced", context: "Example 6\nSection Extensions / Definition lists\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Diagrams
@@ -42,8 +41,7 @@ namespace Markdig.Tests.Specs.Diagrams
// C-->D;
// </div>
Console.WriteLine("Example 1\nSection Extensions / Mermaid diagrams\n");
TestParser.TestSpec("```mermaid\ngraph TD;\n A-->B;\n A-->C;\n B-->D;\n C-->D;\n```", "<div class=\"mermaid\">graph TD;\n A-->B;\n A-->C;\n B-->D;\n C-->D;\n</div>", "diagrams|advanced");
TestParser.TestSpec("```mermaid\ngraph TD;\n A-->B;\n A-->C;\n B-->D;\n C-->D;\n```", "<div class=\"mermaid\">graph TD;\n A-->B;\n A-->C;\n B-->D;\n C-->D;\n</div>", "diagrams|advanced", context: "Example 1\nSection Extensions / Mermaid diagrams\n");
}
}
@@ -86,8 +84,7 @@ namespace Markdig.Tests.Specs.Diagrams
// ]
// </div>
Console.WriteLine("Example 2\nSection Extensions / nomnoml diagrams\n");
TestParser.TestSpec("```nomnoml\n[example|\n propertyA: Int\n propertyB: string\n|\n methodA()\n methodB()\n|\n [subA]--[subB]\n [subA]-:>[sub C]\n]\n```", "<div class=\"nomnoml\">[example|\n propertyA: Int\n propertyB: string\n|\n methodA()\n methodB()\n|\n [subA]--[subB]\n [subA]-:>[sub C]\n]\n</div>", "diagrams|advanced");
TestParser.TestSpec("```nomnoml\n[example|\n propertyA: Int\n propertyB: string\n|\n methodA()\n methodB()\n|\n [subA]--[subB]\n [subA]-:>[sub C]\n]\n```", "<div class=\"nomnoml\">[example|\n propertyA: Int\n propertyB: string\n|\n methodA()\n methodB()\n|\n [subA]--[subB]\n [subA]-:>[sub C]\n]\n</div>", "diagrams|advanced", context: "Example 2\nSection Extensions / nomnoml diagrams\n");
}
// TODO: Add other text diagram languages
}

View File

@@ -1,4 +1,3 @@
// Generated: 2020-01-13 21:08:58
// --------------------------------
// Emoji
@@ -31,8 +30,7 @@ namespace Markdig.Tests.Specs.Emoji
// Should be rendered as:
// <p>This is a test with a 😃 and a 😠 smiley</p>
Console.WriteLine("Example 1\nSection Extensions / Emoji\n");
TestParser.TestSpec("This is a test with a :) and a :angry: smiley", "<p>This is a test with a 😃 and a 😠 smiley</p>", "emojis|advanced+emojis");
TestParser.TestSpec("This is a test with a :) and a :angry: smiley", "<p>This is a test with a 😃 and a 😠 smiley</p>", "emojis|advanced+emojis", context: "Example 1\nSection Extensions / Emoji\n");
}
// An emoji needs to be preceded by a space:
@@ -48,8 +46,7 @@ namespace Markdig.Tests.Specs.Emoji
// Should be rendered as:
// <p>These are not:) an emoji with a:) x:angry:x</p>
Console.WriteLine("Example 2\nSection Extensions / Emoji\n");
TestParser.TestSpec("These are not:) an emoji with a:) x:angry:x", "<p>These are not:) an emoji with a:) x:angry:x</p>", "emojis|advanced+emojis");
TestParser.TestSpec("These are not:) an emoji with a:) x:angry:x", "<p>These are not:) an emoji with a:) x:angry:x</p>", "emojis|advanced+emojis", context: "Example 2\nSection Extensions / Emoji\n");
}
// Emojis can be followed by close punctuation (or any other characters):
@@ -65,8 +62,7 @@ namespace Markdig.Tests.Specs.Emoji
// Should be rendered as:
// <p>We all need 😃, it makes us 💪. (and 👌).</p>
Console.WriteLine("Example 3\nSection Extensions / Emoji\n");
TestParser.TestSpec("We all need :), it makes us :muscle:. (and :ok_hand:).", "<p>We all need 😃, it makes us 💪. (and 👌).</p>", "emojis|advanced+emojis");
TestParser.TestSpec("We all need :), it makes us :muscle:. (and :ok_hand:).", "<p>We all need 😃, it makes us 💪. (and 👌).</p>", "emojis|advanced+emojis", context: "Example 3\nSection Extensions / Emoji\n");
}
// Sentences can end with emojis:
@@ -84,8 +80,7 @@ namespace Markdig.Tests.Specs.Emoji
// <p>This is a sentence 👌
// and keeps going to the next line 😃</p>
Console.WriteLine("Example 4\nSection Extensions / Emoji\n");
TestParser.TestSpec("This is a sentence :ok_hand:\nand keeps going to the next line :)", "<p>This is a sentence 👌\nand keeps going to the next line 😃</p>", "emojis|advanced+emojis");
TestParser.TestSpec("This is a sentence :ok_hand:\nand keeps going to the next line :)", "<p>This is a sentence 👌\nand keeps going to the next line 😃</p>", "emojis|advanced+emojis", context: "Example 4\nSection Extensions / Emoji\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Emphasis Extra
@@ -31,8 +30,7 @@ namespace Markdig.Tests.Specs.EmphasisExtra
// Should be rendered as:
// <p>The following text <del>is deleted</del></p>
Console.WriteLine("Example 1\nSection Extensions / Strikethrough\n");
TestParser.TestSpec("The following text ~~is deleted~~", "<p>The following text <del>is deleted</del></p>", "emphasisextras|advanced");
TestParser.TestSpec("The following text ~~is deleted~~", "<p>The following text <del>is deleted</del></p>", "emphasisextras|advanced", context: "Example 1\nSection Extensions / Strikethrough\n");
}
}
@@ -54,8 +52,7 @@ namespace Markdig.Tests.Specs.EmphasisExtra
// Should be rendered as:
// <p>H<sub>2</sub>O is a liquid. 2<sup>10</sup> is 1024</p>
Console.WriteLine("Example 2\nSection Extensions / Superscript and Subscript\n");
TestParser.TestSpec("H~2~O is a liquid. 2^10^ is 1024", "<p>H<sub>2</sub>O is a liquid. 2<sup>10</sup> is 1024</p>", "emphasisextras|advanced");
TestParser.TestSpec("H~2~O is a liquid. 2^10^ is 1024", "<p>H<sub>2</sub>O is a liquid. 2<sup>10</sup> is 1024</p>", "emphasisextras|advanced", context: "Example 2\nSection Extensions / Superscript and Subscript\n");
}
// Certain punctuation characters are exempted from the rule forbidding them within inline delimiters
@@ -74,8 +71,7 @@ namespace Markdig.Tests.Specs.EmphasisExtra
// <p>One quintillionth can be expressed as 10<sup>-18</sup></p>
// <p>Daggers<sup>†</sup> and double-daggers<sup>‡</sup> can be used to denote notes.</p>
Console.WriteLine("Example 3\nSection Extensions / Superscript and Subscript\n");
TestParser.TestSpec("One quintillionth can be expressed as 10^-18^\n\nDaggers^†^ and double-daggers^‡^ can be used to denote notes.", "<p>One quintillionth can be expressed as 10<sup>-18</sup></p>\n<p>Daggers<sup>†</sup> and double-daggers<sup>‡</sup> can be used to denote notes.</p>", "emphasisextras|advanced");
TestParser.TestSpec("One quintillionth can be expressed as 10^-18^\n\nDaggers^†^ and double-daggers^‡^ can be used to denote notes.", "<p>One quintillionth can be expressed as 10<sup>-18</sup></p>\n<p>Daggers<sup>†</sup> and double-daggers<sup>‡</sup> can be used to denote notes.</p>", "emphasisextras|advanced", context: "Example 3\nSection Extensions / Superscript and Subscript\n");
}
}
@@ -97,8 +93,7 @@ namespace Markdig.Tests.Specs.EmphasisExtra
// Should be rendered as:
// <p><ins>Inserted text</ins></p>
Console.WriteLine("Example 4\nSection Extensions / Inserted\n");
TestParser.TestSpec("++Inserted text++", "<p><ins>Inserted text</ins></p>", "emphasisextras|advanced");
TestParser.TestSpec("++Inserted text++", "<p><ins>Inserted text</ins></p>", "emphasisextras|advanced", context: "Example 4\nSection Extensions / Inserted\n");
}
}
@@ -120,8 +115,7 @@ namespace Markdig.Tests.Specs.EmphasisExtra
// Should be rendered as:
// <p><mark>Marked text</mark></p>
Console.WriteLine("Example 5\nSection Extensions / Marked\n");
TestParser.TestSpec("==Marked text==", "<p><mark>Marked text</mark></p>", "emphasisextras|advanced");
TestParser.TestSpec("==Marked text==", "<p><mark>Marked text</mark></p>", "emphasisextras|advanced", context: "Example 5\nSection Extensions / Marked\n");
}
}
@@ -145,8 +139,7 @@ namespace Markdig.Tests.Specs.EmphasisExtra
// This is text MyBrand<sup>®</sup> and MyTrademark<sup>TM</sup>
// This is text MyBrand<sub>®</sub> and MyCopyright<sup>©</sup></p>
Console.WriteLine("Example 6\nSection Extensions / Emphasis on Html Entities\n");
TestParser.TestSpec("This is text MyBrand ^&reg;^ and MyTrademark ^&trade;^\nThis is text MyBrand^&reg;^ and MyTrademark^&trade;^\nThis is text MyBrand~&reg;~ and MyCopyright^&copy;^", "<p>This is text MyBrand <sup>®</sup> and MyTrademark <sup>TM</sup>\nThis is text MyBrand<sup>®</sup> and MyTrademark<sup>TM</sup>\nThis is text MyBrand<sub>®</sub> and MyCopyright<sup>©</sup></p>", "emphasisextras|advanced");
TestParser.TestSpec("This is text MyBrand ^&reg;^ and MyTrademark ^&trade;^\nThis is text MyBrand^&reg;^ and MyTrademark^&trade;^\nThis is text MyBrand~&reg;~ and MyCopyright^&copy;^", "<p>This is text MyBrand <sup>®</sup> and MyTrademark <sup>TM</sup>\nThis is text MyBrand<sup>®</sup> and MyTrademark<sup>TM</sup>\nThis is text MyBrand<sub>®</sub> and MyCopyright<sup>©</sup></p>", "emphasisextras|advanced", context: "Example 6\nSection Extensions / Emphasis on Html Entities\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Figures, Footers and Cites
@@ -36,8 +35,7 @@ namespace Markdig.Tests.Specs.FiguresFootersAndCites
// <figcaption>This is a <em>caption</em></figcaption>
// </figure>
Console.WriteLine("Example 1\nSection Extensions / Figures\n");
TestParser.TestSpec("^^^\nThis is a figure\n^^^ This is a *caption*", "<figure>\n<p>This is a figure</p>\n<figcaption>This is a <em>caption</em></figcaption>\n</figure>", "figures+footers+citations|advanced");
TestParser.TestSpec("^^^\nThis is a figure\n^^^ This is a *caption*", "<figure>\n<p>This is a figure</p>\n<figcaption>This is a <em>caption</em></figcaption>\n</figure>", "figures+footers+citations|advanced", context: "Example 1\nSection Extensions / Figures\n");
}
}
@@ -61,8 +59,7 @@ namespace Markdig.Tests.Specs.FiguresFootersAndCites
// <footer>This is a footer
// multi-line</footer>
Console.WriteLine("Example 2\nSection Extensions / Footers\n");
TestParser.TestSpec("^^ This is a footer\n^^ multi-line", "<footer>This is a footer\nmulti-line</footer>", "figures+footers+citations|advanced");
TestParser.TestSpec("^^ This is a footer\n^^ multi-line", "<footer>This is a footer\nmulti-line</footer>", "figures+footers+citations|advanced", context: "Example 2\nSection Extensions / Footers\n");
}
}
@@ -84,8 +81,7 @@ namespace Markdig.Tests.Specs.FiguresFootersAndCites
// Should be rendered as:
// <p>This is a <cite>citation of someone</cite></p>
Console.WriteLine("Example 3\nSection Extensions / Cite\n");
TestParser.TestSpec("This is a \"\"citation of someone\"\"", "<p>This is a <cite>citation of someone</cite></p>", "figures+footers+citations|advanced");
TestParser.TestSpec("This is a \"\"citation of someone\"\"", "<p>This is a <cite>citation of someone</cite></p>", "figures+footers+citations|advanced", context: "Example 3\nSection Extensions / Cite\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-15 05:33:49
// --------------------------------
// Footnotes
@@ -80,8 +79,7 @@ namespace Markdig.Tests.Specs.Footnotes
// </ol>
// </div>
Console.WriteLine("Example 1\nSection Extensions / Footnotes\n");
TestParser.TestSpec("Here is a footnote reference,[^1] and another.[^longnote]\n\nThis is another reference to [^1]\n\n[^1]: Here is the footnote.\n\nAnd another reference to [^longnote]\n\n[^longnote]: Here's one with multiple blocks.\n\n Subsequent paragraphs are indented to show that they\nbelong to the previous footnote.\n\n > This is a block quote\n > Inside a footnote\n\n { some.code }\n\n The whole paragraph can be indented, or just the first\n line. In this way, multi-paragraph footnotes work like\n multi-paragraph list items.\n\nThis paragraph won't be part of the note, because it\nisn't indented.", "<p>Here is a footnote reference,<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a> and another.<a id=\"fnref:3\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a></p>\n<p>This is another reference to <a id=\"fnref:2\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a></p>\n<p>And another reference to <a id=\"fnref:4\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a></p>\n<p>This paragraph won't be part of the note, because it\nisn't indented.</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Here is the footnote.<a href=\"#fnref:1\" class=\"footnote-back-ref\">&#8617;</a><a href=\"#fnref:2\" class=\"footnote-back-ref\">&#8617;</a></p>\n</li>\n<li id=\"fn:2\">\n<p>Here's one with multiple blocks.</p>\n<p>Subsequent paragraphs are indented to show that they\nbelong to the previous footnote.</p>\n<blockquote>\n<p>This is a block quote\nInside a footnote</p>\n</blockquote>\n<pre><code>{ some.code }\n</code></pre>\n<p>The whole paragraph can be indented, or just the first\nline. In this way, multi-paragraph footnotes work like\nmulti-paragraph list items.<a href=\"#fnref:3\" class=\"footnote-back-ref\">&#8617;</a><a href=\"#fnref:4\" class=\"footnote-back-ref\">&#8617;</a></p>\n</li>\n</ol>\n</div>", "footnotes|advanced");
TestParser.TestSpec("Here is a footnote reference,[^1] and another.[^longnote]\n\nThis is another reference to [^1]\n\n[^1]: Here is the footnote.\n\nAnd another reference to [^longnote]\n\n[^longnote]: Here's one with multiple blocks.\n\n Subsequent paragraphs are indented to show that they\nbelong to the previous footnote.\n\n > This is a block quote\n > Inside a footnote\n\n { some.code }\n\n The whole paragraph can be indented, or just the first\n line. In this way, multi-paragraph footnotes work like\n multi-paragraph list items.\n\nThis paragraph won't be part of the note, because it\nisn't indented.", "<p>Here is a footnote reference,<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a> and another.<a id=\"fnref:3\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a></p>\n<p>This is another reference to <a id=\"fnref:2\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a></p>\n<p>And another reference to <a id=\"fnref:4\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a></p>\n<p>This paragraph won't be part of the note, because it\nisn't indented.</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Here is the footnote.<a href=\"#fnref:1\" class=\"footnote-back-ref\">&#8617;</a><a href=\"#fnref:2\" class=\"footnote-back-ref\">&#8617;</a></p>\n</li>\n<li id=\"fn:2\">\n<p>Here's one with multiple blocks.</p>\n<p>Subsequent paragraphs are indented to show that they\nbelong to the previous footnote.</p>\n<blockquote>\n<p>This is a block quote\nInside a footnote</p>\n</blockquote>\n<pre><code>{ some.code }\n</code></pre>\n<p>The whole paragraph can be indented, or just the first\nline. In this way, multi-paragraph footnotes work like\nmulti-paragraph list items.<a href=\"#fnref:3\" class=\"footnote-back-ref\">&#8617;</a><a href=\"#fnref:4\" class=\"footnote-back-ref\">&#8617;</a></p>\n</li>\n</ol>\n</div>", "footnotes|advanced", context: "Example 1\nSection Extensions / Footnotes\n");
}
// Check with multiple consecutive footnotes:
@@ -121,8 +119,7 @@ namespace Markdig.Tests.Specs.Footnotes
// </ol>
// </div>
Console.WriteLine("Example 2\nSection Extensions / Footnotes\n");
TestParser.TestSpec("Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].\n\n[^1]: Footnote 1 text\n\n[^2]: Footnote 2 text\n\na\n\n[^3]: Footnote 3 text\n\n[^4]: Footnote 4 text", "<p>Here is a footnote<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a>. And another one<a id=\"fnref:2\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a>. And a third one<a id=\"fnref:3\" href=\"#fn:3\" class=\"footnote-ref\"><sup>3</sup></a>. And a fourth<a id=\"fnref:4\" href=\"#fn:4\" class=\"footnote-ref\"><sup>4</sup></a>.</p>\n<p>a</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Footnote 1 text<a href=\"#fnref:1\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:2\">\n<p>Footnote 2 text<a href=\"#fnref:2\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:3\">\n<p>Footnote 3 text<a href=\"#fnref:3\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:4\">\n<p>Footnote 4 text<a href=\"#fnref:4\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n</ol>\n</div>", "footnotes|advanced");
TestParser.TestSpec("Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].\n\n[^1]: Footnote 1 text\n\n[^2]: Footnote 2 text\n\na\n\n[^3]: Footnote 3 text\n\n[^4]: Footnote 4 text", "<p>Here is a footnote<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a>. And another one<a id=\"fnref:2\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a>. And a third one<a id=\"fnref:3\" href=\"#fn:3\" class=\"footnote-ref\"><sup>3</sup></a>. And a fourth<a id=\"fnref:4\" href=\"#fn:4\" class=\"footnote-ref\"><sup>4</sup></a>.</p>\n<p>a</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Footnote 1 text<a href=\"#fnref:1\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:2\">\n<p>Footnote 2 text<a href=\"#fnref:2\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:3\">\n<p>Footnote 3 text<a href=\"#fnref:3\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:4\">\n<p>Footnote 4 text<a href=\"#fnref:4\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n</ol>\n</div>", "footnotes|advanced", context: "Example 2\nSection Extensions / Footnotes\n");
}
// Another test with consecutive footnotes without a blank line separator:
@@ -156,8 +153,7 @@ namespace Markdig.Tests.Specs.Footnotes
// </ol>
// </div>
Console.WriteLine("Example 3\nSection Extensions / Footnotes\n");
TestParser.TestSpec("Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].\n\n[^1]: Footnote 1 text\n[^2]: Footnote 2 text\n[^3]: Footnote 3 text\n[^4]: Footnote 4 text", "<p>Here is a footnote<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a>. And another one<a id=\"fnref:2\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a>. And a third one<a id=\"fnref:3\" href=\"#fn:3\" class=\"footnote-ref\"><sup>3</sup></a>. And a fourth<a id=\"fnref:4\" href=\"#fn:4\" class=\"footnote-ref\"><sup>4</sup></a>.</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Footnote 1 text<a href=\"#fnref:1\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:2\">\n<p>Footnote 2 text<a href=\"#fnref:2\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:3\">\n<p>Footnote 3 text<a href=\"#fnref:3\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:4\">\n<p>Footnote 4 text<a href=\"#fnref:4\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n</ol>\n</div>", "footnotes|advanced");
TestParser.TestSpec("Here is a footnote[^1]. And another one[^2]. And a third one[^3]. And a fourth[^4].\n\n[^1]: Footnote 1 text\n[^2]: Footnote 2 text\n[^3]: Footnote 3 text\n[^4]: Footnote 4 text", "<p>Here is a footnote<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a>. And another one<a id=\"fnref:2\" href=\"#fn:2\" class=\"footnote-ref\"><sup>2</sup></a>. And a third one<a id=\"fnref:3\" href=\"#fn:3\" class=\"footnote-ref\"><sup>3</sup></a>. And a fourth<a id=\"fnref:4\" href=\"#fn:4\" class=\"footnote-ref\"><sup>4</sup></a>.</p>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Footnote 1 text<a href=\"#fnref:1\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:2\">\n<p>Footnote 2 text<a href=\"#fnref:2\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:3\">\n<p>Footnote 3 text<a href=\"#fnref:3\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n<li id=\"fn:4\">\n<p>Footnote 4 text<a href=\"#fnref:4\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n</ol>\n</div>", "footnotes|advanced", context: "Example 3\nSection Extensions / Footnotes\n");
}
// A footnote link inside a list should work as well:
@@ -186,8 +182,7 @@ namespace Markdig.Tests.Specs.Footnotes
// </ol>
// </div>
Console.WriteLine("Example 4\nSection Extensions / Footnotes\n");
TestParser.TestSpec("- abc\n- def[^1]\n\n[^1]: Here is the footnote.", "<ul>\n<li>abc</li>\n<li>def<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a></li>\n</ul>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Here is the footnote.<a href=\"#fnref:1\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n</ol>\n</div>", "footnotes|advanced");
TestParser.TestSpec("- abc\n- def[^1]\n\n[^1]: Here is the footnote.", "<ul>\n<li>abc</li>\n<li>def<a id=\"fnref:1\" href=\"#fn:1\" class=\"footnote-ref\"><sup>1</sup></a></li>\n</ul>\n<div class=\"footnotes\">\n<hr />\n<ol>\n<li id=\"fn:1\">\n<p>Here is the footnote.<a href=\"#fnref:1\" class=\"footnote-back-ref\">&#8617;</a></p></li>\n</ol>\n</div>", "footnotes|advanced", context: "Example 4\nSection Extensions / Footnotes\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-08-01 13:57:17
// --------------------------------
// Generic Attributes
@@ -55,8 +54,7 @@ namespace Markdig.Tests.Specs.GenericAttributes
// <h2 id="heading-link2">This is a heading</h2>
// <p id="myparagraph" attached-bool-property="" attached-bool-property2="">This is a paragraph with an attached attributes </p>
Console.WriteLine("Example 1\nSection Extensions / Generic Attributes\n");
TestParser.TestSpec("# This is a heading with an an attribute{#heading-link}\n\n# This is a heading # {#heading-link2}\n\n[This is a link](http://google.com){#a-link .myclass data-lang=fr data-value=\"This is a value\"}\n\nThis is a heading{#heading-link2}\n-----------------\n\nThis is a paragraph with an attached attributes {#myparagraph attached-bool-property attached-bool-property2}", "<h1 id=\"heading-link\">This is a heading with an an attribute</h1>\n<h1 id=\"heading-link2\">This is a heading</h1>\n<p><a href=\"http://google.com\" id=\"a-link\" class=\"myclass\" data-lang=\"fr\" data-value=\"This is a value\">This is a link</a></p>\n<h2 id=\"heading-link2\">This is a heading</h2>\n<p id=\"myparagraph\" attached-bool-property=\"\" attached-bool-property2=\"\">This is a paragraph with an attached attributes </p>", "attributes|advanced");
TestParser.TestSpec("# This is a heading with an an attribute{#heading-link}\n\n# This is a heading # {#heading-link2}\n\n[This is a link](http://google.com){#a-link .myclass data-lang=fr data-value=\"This is a value\"}\n\nThis is a heading{#heading-link2}\n-----------------\n\nThis is a paragraph with an attached attributes {#myparagraph attached-bool-property attached-bool-property2}", "<h1 id=\"heading-link\">This is a heading with an an attribute</h1>\n<h1 id=\"heading-link2\">This is a heading</h1>\n<p><a href=\"http://google.com\" id=\"a-link\" class=\"myclass\" data-lang=\"fr\" data-value=\"This is a value\">This is a link</a></p>\n<h2 id=\"heading-link2\">This is a heading</h2>\n<p id=\"myparagraph\" attached-bool-property=\"\" attached-bool-property2=\"\">This is a paragraph with an attached attributes </p>", "attributes|advanced", context: "Example 1\nSection Extensions / Generic Attributes\n");
}
// The following shows that attributes can be attached to the next block if they are used inside a single line just preceding the block (and preceded by a blank line or beginning of a block container):
@@ -76,8 +74,7 @@ namespace Markdig.Tests.Specs.GenericAttributes
// <pre><code id="fenced-id" class="fenced-class">This is a fenced with attached attributes
// </code></pre>
Console.WriteLine("Example 2\nSection Extensions / Generic Attributes\n");
TestParser.TestSpec("{#fenced-id .fenced-class}\n~~~\nThis is a fenced with attached attributes\n~~~ ", "<pre><code id=\"fenced-id\" class=\"fenced-class\">This is a fenced with attached attributes\n</code></pre>", "attributes|advanced");
TestParser.TestSpec("{#fenced-id .fenced-class}\n~~~\nThis is a fenced with attached attributes\n~~~ ", "<pre><code id=\"fenced-id\" class=\"fenced-class\">This is a fenced with attached attributes\n</code></pre>", "attributes|advanced", context: "Example 2\nSection Extensions / Generic Attributes\n");
}
// Attribute values can be one character long
@@ -99,8 +96,7 @@ namespace Markdig.Tests.Specs.GenericAttributes
// <p><a href="url" data-x="1">Foo</a></p>
// <p><a href="url" data-x="11">Foo</a></p>
Console.WriteLine("Example 3\nSection Extensions / Generic Attributes\n");
TestParser.TestSpec("[Foo](url){data-x=1}\n\n[Foo](url){data-x='1'}\n\n[Foo](url){data-x=11}", "<p><a href=\"url\" data-x=\"1\">Foo</a></p>\n<p><a href=\"url\" data-x=\"1\">Foo</a></p>\n<p><a href=\"url\" data-x=\"11\">Foo</a></p>", "attributes|advanced");
TestParser.TestSpec("[Foo](url){data-x=1}\n\n[Foo](url){data-x='1'}\n\n[Foo](url){data-x=11}", "<p><a href=\"url\" data-x=\"1\">Foo</a></p>\n<p><a href=\"url\" data-x=\"1\">Foo</a></p>\n<p><a href=\"url\" data-x=\"11\">Foo</a></p>", "attributes|advanced", context: "Example 3\nSection Extensions / Generic Attributes\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-15 05:25:26
// --------------------------------
// Globalization
@@ -57,8 +56,7 @@ namespace Markdig.Tests.Specs.Globalization
// -- نەزانراو</p>
// </blockquote>
Console.WriteLine("Example 1\nSection Extensions / Globalization\n");
TestParser.TestSpec("# Fruits\nIn botany, a [fruit](https://en.wikipedia.org/wiki/Fruit) is the seed-bearing structure in flowering plants (also known as angiosperms) formed from the ovary after flowering.\n\n> Fruits are good for health\n-- Anonymous\n\n# میوە\n[میوە](https://ckb.wikipedia.org/wiki/%D9%85%DB%8C%D9%88%DB%95) یان مێوە بەروبوومی ڕوەکیە کە ڕوەکەکان ھەڵیان ئەگرن وەک بەرگێک بۆ تۆوەکانیان، بە زۆری جیادەکرێتەوە بە شیرینی یان ترشی لە تامدا و بە بوونی بڕێکی زۆر ئاو\n\n> میوە بۆ تەندروستی باشە\n-- نەزانراو", "<h1 id=\"fruits\">Fruits</h1>\n<p>In botany, a <a href=\"https://en.wikipedia.org/wiki/Fruit\">fruit</a> is the seed-bearing structure in flowering plants (also known as angiosperms) formed from the ovary after flowering.</p>\n<blockquote>\n<p>Fruits are good for health\n-- Anonymous</p>\n</blockquote>\n<h1 id=\"section\" dir=\"rtl\">میوە</h1>\n<p dir=\"rtl\"><a href=\"https://ckb.wikipedia.org/wiki/%D9%85%DB%8C%D9%88%DB%95\" dir=\"rtl\">میوە</a> یان مێوە بەروبوومی ڕوەکیە کە ڕوەکەکان ھەڵیان ئەگرن وەک بەرگێک بۆ تۆوەکانیان، بە زۆری جیادەکرێتەوە بە شیرینی یان ترشی لە تامدا و بە بوونی بڕێکی زۆر ئاو</p>\n<blockquote dir=\"rtl\">\n<p dir=\"rtl\">میوە بۆ تەندروستی باشە\n-- نەزانراو</p>\n</blockquote>", "globalization+advanced+emojis");
TestParser.TestSpec("# Fruits\nIn botany, a [fruit](https://en.wikipedia.org/wiki/Fruit) is the seed-bearing structure in flowering plants (also known as angiosperms) formed from the ovary after flowering.\n\n> Fruits are good for health\n-- Anonymous\n\n# میوە\n[میوە](https://ckb.wikipedia.org/wiki/%D9%85%DB%8C%D9%88%DB%95) یان مێوە بەروبوومی ڕوەکیە کە ڕوەکەکان ھەڵیان ئەگرن وەک بەرگێک بۆ تۆوەکانیان، بە زۆری جیادەکرێتەوە بە شیرینی یان ترشی لە تامدا و بە بوونی بڕێکی زۆر ئاو\n\n> میوە بۆ تەندروستی باشە\n-- نەزانراو", "<h1 id=\"fruits\">Fruits</h1>\n<p>In botany, a <a href=\"https://en.wikipedia.org/wiki/Fruit\">fruit</a> is the seed-bearing structure in flowering plants (also known as angiosperms) formed from the ovary after flowering.</p>\n<blockquote>\n<p>Fruits are good for health\n-- Anonymous</p>\n</blockquote>\n<h1 id=\"section\" dir=\"rtl\">میوە</h1>\n<p dir=\"rtl\"><a href=\"https://ckb.wikipedia.org/wiki/%D9%85%DB%8C%D9%88%DB%95\" dir=\"rtl\">میوە</a> یان مێوە بەروبوومی ڕوەکیە کە ڕوەکەکان ھەڵیان ئەگرن وەک بەرگێک بۆ تۆوەکانیان، بە زۆری جیادەکرێتەوە بە شیرینی یان ترشی لە تامدا و بە بوونی بڕێکی زۆر ئاو</p>\n<blockquote dir=\"rtl\">\n<p dir=\"rtl\">میوە بۆ تەندروستی باشە\n-- نەزانراو</p>\n</blockquote>", "globalization+advanced+emojis", context: "Example 1\nSection Extensions / Globalization\n");
}
// Lists:
@@ -161,8 +159,7 @@ namespace Markdig.Tests.Specs.Globalization
// <li class="task-list-item"><input disabled="disabled" type="checkbox" /> هەنجیر</li>
// </ul>
Console.WriteLine("Example 2\nSection Extensions / Globalization\n");
TestParser.TestSpec("## Types of fruits\n- Berries\n - Strawberry\n - kiwifruit\n- Citrus\n - Orange\n - Lemon\n\n## Examples of fruits :yum:\n1. Apple\n2. Banana\n3. Orange\n\n## Grocery List\n- [X] 􏿽 Watermelon\n- [X] Apricot\n- [ ] Fig \n\n## نموونەی میوە :yum:\n1. ? سێو\n2. 5 مۆز \n3. 􏿽 پرتەقاڵ\n\n## جۆرەکانی میوە\n- توو\n - فڕاولە\n - کیوی\n- مزرەمەنی\n - پڕتەقاڵ\n - لیمۆ\n\n## لیستی کڕین\n- [X] شووتی\n- [X] قەیسی\n- [ ] هەنجیر", "<h2 id=\"types-of-fruits\">Types of fruits</h2>\n<ul>\n<li>Berries\n<ul>\n<li>Strawberry</li>\n<li>kiwifruit</li>\n</ul>\n</li>\n<li>Citrus\n<ul>\n<li>Orange</li>\n<li>Lemon</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"examples-of-fruits\">Examples of fruits 😋</h2>\n<ol>\n<li>Apple</li>\n<li>Banana</li>\n<li>Orange</li>\n</ol>\n<h2 id=\"grocery-list\">Grocery List</h2>\n<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> 􏿽 Watermelon</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> Apricot</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" /> Fig</li>\n</ul>\n<h2 id=\"section\" dir=\"rtl\">نموونەی میوە 😋</h2>\n<ol dir=\"rtl\">\n<li>? سێو</li>\n<li>5 مۆز</li>\n<li>􏿽 پرتەقاڵ</li>\n</ol>\n<h2 id=\"section-1\" dir=\"rtl\">جۆرەکانی میوە</h2>\n<ul dir=\"rtl\">\n<li>توو\n<ul dir=\"rtl\">\n<li>فڕاولە</li>\n<li>کیوی</li>\n</ul>\n</li>\n<li>مزرەمەنی\n<ul dir=\"rtl\">\n<li>پڕتەقاڵ</li>\n<li>لیمۆ</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"section-2\" dir=\"rtl\">لیستی کڕین</h2>\n<ul class=\"contains-task-list\" dir=\"rtl\">\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> شووتی</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> قەیسی</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" /> هەنجیر</li>\n</ul>", "globalization+advanced+emojis");
TestParser.TestSpec("## Types of fruits\n- Berries\n - Strawberry\n - kiwifruit\n- Citrus\n - Orange\n - Lemon\n\n## Examples of fruits :yum:\n1. Apple\n2. Banana\n3. Orange\n\n## Grocery List\n- [X] 􏿽 Watermelon\n- [X] Apricot\n- [ ] Fig \n\n## نموونەی میوە :yum:\n1. ? سێو\n2. 5 مۆز \n3. 􏿽 پرتەقاڵ\n\n## جۆرەکانی میوە\n- توو\n - فڕاولە\n - کیوی\n- مزرەمەنی\n - پڕتەقاڵ\n - لیمۆ\n\n## لیستی کڕین\n- [X] شووتی\n- [X] قەیسی\n- [ ] هەنجیر", "<h2 id=\"types-of-fruits\">Types of fruits</h2>\n<ul>\n<li>Berries\n<ul>\n<li>Strawberry</li>\n<li>kiwifruit</li>\n</ul>\n</li>\n<li>Citrus\n<ul>\n<li>Orange</li>\n<li>Lemon</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"examples-of-fruits\">Examples of fruits 😋</h2>\n<ol>\n<li>Apple</li>\n<li>Banana</li>\n<li>Orange</li>\n</ol>\n<h2 id=\"grocery-list\">Grocery List</h2>\n<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> 􏿽 Watermelon</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> Apricot</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" /> Fig</li>\n</ul>\n<h2 id=\"section\" dir=\"rtl\">نموونەی میوە 😋</h2>\n<ol dir=\"rtl\">\n<li>? سێو</li>\n<li>5 مۆز</li>\n<li>􏿽 پرتەقاڵ</li>\n</ol>\n<h2 id=\"section-1\" dir=\"rtl\">جۆرەکانی میوە</h2>\n<ul dir=\"rtl\">\n<li>توو\n<ul dir=\"rtl\">\n<li>فڕاولە</li>\n<li>کیوی</li>\n</ul>\n</li>\n<li>مزرەمەنی\n<ul dir=\"rtl\">\n<li>پڕتەقاڵ</li>\n<li>لیمۆ</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"section-2\" dir=\"rtl\">لیستی کڕین</h2>\n<ul class=\"contains-task-list\" dir=\"rtl\">\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> شووتی</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> قەیسی</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" /> هەنجیر</li>\n</ul>", "globalization+advanced+emojis", context: "Example 2\nSection Extensions / Globalization\n");
}
// Tables:
@@ -227,8 +224,7 @@ namespace Markdig.Tests.Specs.Globalization
// </tbody>
// </table>
Console.WriteLine("Example 3\nSection Extensions / Globalization\n");
TestParser.TestSpec("Nutrition |Apple | Oranges\n--|-- | --\nCalories|52|47\nSugar|10g|9g\n\n پێکهاتە |سێو | پڕتەقاڵ\n--|-- | --\nکالۆری|٥٢|٤٧\nشەکر| ١٠گ|٩گ", "<table>\n<thead>\n<tr>\n<th>Nutrition</th>\n<th>Apple</th>\n<th>Oranges</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Calories</td>\n<td>52</td>\n<td>47</td>\n</tr>\n<tr>\n<td>Sugar</td>\n<td>10g</td>\n<td>9g</td>\n</tr>\n</tbody>\n</table>\n<table dir=\"rtl\" align=\"right\">\n<thead>\n<tr>\n<th>پێکهاتە</th>\n<th>سێو</th>\n<th>پڕتەقاڵ</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>کالۆری</td>\n<td>٥٢</td>\n<td>٤٧</td>\n</tr>\n<tr>\n<td>شەکر</td>\n<td>١٠گ</td>\n<td>٩گ</td>\n</tr>\n</tbody>\n</table>", "globalization+advanced+emojis");
TestParser.TestSpec("Nutrition |Apple | Oranges\n--|-- | --\nCalories|52|47\nSugar|10g|9g\n\n پێکهاتە |سێو | پڕتەقاڵ\n--|-- | --\nکالۆری|٥٢|٤٧\nشەکر| ١٠گ|٩گ", "<table>\n<thead>\n<tr>\n<th>Nutrition</th>\n<th>Apple</th>\n<th>Oranges</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Calories</td>\n<td>52</td>\n<td>47</td>\n</tr>\n<tr>\n<td>Sugar</td>\n<td>10g</td>\n<td>9g</td>\n</tr>\n</tbody>\n</table>\n<table dir=\"rtl\" align=\"right\">\n<thead>\n<tr>\n<th>پێکهاتە</th>\n<th>سێو</th>\n<th>پڕتەقاڵ</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>کالۆری</td>\n<td>٥٢</td>\n<td>٤٧</td>\n</tr>\n<tr>\n<td>شەکر</td>\n<td>١٠گ</td>\n<td>٩گ</td>\n</tr>\n</tbody>\n</table>", "globalization+advanced+emojis", context: "Example 3\nSection Extensions / Globalization\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Grid Tables
@@ -62,8 +61,8 @@ namespace Markdig.Tests.Specs.GridTables
//
// Should be rendered as:
// <table>
// <col style="width:50%">
// <col style="width:50%">
// <col style="width:50%" />
// <col style="width:50%" />
// <tbody>
// <tr>
// <td>This is</td>
@@ -72,8 +71,7 @@ namespace Markdig.Tests.Specs.GridTables
// </tbody>
// </table>
Console.WriteLine("Example 1\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+---------+---------+\n| This is | a table |", "<table>\n<col style=\"width:50%\">\n<col style=\"width:50%\">\n<tbody>\n<tr>\n<td>This is</td>\n<td>a table</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced");
TestParser.TestSpec("+---------+---------+\n| This is | a table |", "<table>\n<col style=\"width:50%\" />\n<col style=\"width:50%\" />\n<tbody>\n<tr>\n<td>This is</td>\n<td>a table</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced", context: "Example 1\nSection Extensions / Grid Table\n");
}
// The following is not a valid row separator
@@ -91,8 +89,7 @@ namespace Markdig.Tests.Specs.GridTables
// <p>|-----xxx----+---------+
// | This is | not a table</p>
Console.WriteLine("Example 2\nSection Extensions / Grid Table\n");
TestParser.TestSpec("|-----xxx----+---------+\n| This is | not a table", "<p>|-----xxx----+---------+\n| This is | not a table</p>", "gridtables|advanced");
TestParser.TestSpec("|-----xxx----+---------+\n| This is | not a table", "<p>|-----xxx----+---------+\n| This is | not a table</p>", "gridtables|advanced", context: "Example 2\nSection Extensions / Grid Table\n");
}
// **Rule #2**
@@ -112,9 +109,9 @@ namespace Markdig.Tests.Specs.GridTables
//
// Should be rendered as:
// <table>
// <col style="width:33.33%">
// <col style="width:33.33%">
// <col style="width:33.33%">
// <col style="width:33.33%" />
// <col style="width:33.33%" />
// <col style="width:33.33%" />
// <tbody>
// <tr>
// <td>Col1
@@ -134,8 +131,7 @@ namespace Markdig.Tests.Specs.GridTables
// </tbody>
// </table>
Console.WriteLine("Example 3\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+---------+---------+---------+\n| Col1 | Col2 | Col3 |\n| Col1a | Col2a | Col3a |\n| Col1b | Col3b |\n| Col1c |", "<table>\n<col style=\"width:33.33%\">\n<col style=\"width:33.33%\">\n<col style=\"width:33.33%\">\n<tbody>\n<tr>\n<td>Col1\nCol1a</td>\n<td>Col2\nCol2a</td>\n<td>Col3\nCol3a</td>\n</tr>\n<tr>\n<td colspan=\"2\">Col1b</td>\n<td>Col3b</td>\n</tr>\n<tr>\n<td colspan=\"3\">Col1c</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced");
TestParser.TestSpec("+---------+---------+---------+\n| Col1 | Col2 | Col3 |\n| Col1a | Col2a | Col3a |\n| Col1b | Col3b |\n| Col1c |", "<table>\n<col style=\"width:33.33%\" />\n<col style=\"width:33.33%\" />\n<col style=\"width:33.33%\" />\n<tbody>\n<tr>\n<td>Col1\nCol1a</td>\n<td>Col2\nCol2a</td>\n<td>Col3\nCol3a</td>\n</tr>\n<tr>\n<td colspan=\"2\">Col1b</td>\n<td>Col3b</td>\n</tr>\n<tr>\n<td colspan=\"3\">Col1c</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced", context: "Example 3\nSection Extensions / Grid Table\n");
}
// A row header is separated using `+========+` instead of `+---------+`:
@@ -152,8 +148,8 @@ namespace Markdig.Tests.Specs.GridTables
//
// Should be rendered as:
// <table>
// <col style="width:50%">
// <col style="width:50%">
// <col style="width:50%" />
// <col style="width:50%" />
// <thead>
// <tr>
// <th>This is</th>
@@ -162,8 +158,7 @@ namespace Markdig.Tests.Specs.GridTables
// </thead>
// </table>
Console.WriteLine("Example 4\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+---------+---------+\n| This is | a table |\n+=========+=========+", "<table>\n<col style=\"width:50%\">\n<col style=\"width:50%\">\n<thead>\n<tr>\n<th>This is</th>\n<th>a table</th>\n</tr>\n</thead>\n</table>", "gridtables|advanced");
TestParser.TestSpec("+---------+---------+\n| This is | a table |\n+=========+=========+", "<table>\n<col style=\"width:50%\" />\n<col style=\"width:50%\" />\n<thead>\n<tr>\n<th>This is</th>\n<th>a table</th>\n</tr>\n</thead>\n</table>", "gridtables|advanced", context: "Example 4\nSection Extensions / Grid Table\n");
}
// The last column separator `|` may be omitted:
@@ -179,8 +174,8 @@ namespace Markdig.Tests.Specs.GridTables
//
// Should be rendered as:
// <table>
// <col style="width:50%">
// <col style="width:50%">
// <col style="width:50%" />
// <col style="width:50%" />
// <tbody>
// <tr>
// <td>This is</td>
@@ -189,8 +184,7 @@ namespace Markdig.Tests.Specs.GridTables
// </tbody>
// </table>
Console.WriteLine("Example 5\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+---------+---------+\n| This is | a table with a longer text in the second column", "<table>\n<col style=\"width:50%\">\n<col style=\"width:50%\">\n<tbody>\n<tr>\n<td>This is</td>\n<td>a table with a longer text in the second column</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced");
TestParser.TestSpec("+---------+---------+\n| This is | a table with a longer text in the second column", "<table>\n<col style=\"width:50%\" />\n<col style=\"width:50%\" />\n<tbody>\n<tr>\n<td>This is</td>\n<td>a table with a longer text in the second column</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced", context: "Example 5\nSection Extensions / Grid Table\n");
}
// The respective width of the columns are calculated from the ratio between the total size of the first table row without counting the `+`: `+----+--------+----+` would be divided between:
@@ -215,9 +209,9 @@ namespace Markdig.Tests.Specs.GridTables
//
// Should be rendered as:
// <table>
// <col style="width:25%">
// <col style="width:50%">
// <col style="width:25%">
// <col style="width:25%" />
// <col style="width:50%" />
// <col style="width:25%" />
// <tbody>
// <tr>
// <td>A</td>
@@ -227,8 +221,7 @@ namespace Markdig.Tests.Specs.GridTables
// </tbody>
// </table>
Console.WriteLine("Example 6\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+----+--------+----+\n| A | B C D | E |\n+----+--------+----+", "<table>\n<col style=\"width:25%\">\n<col style=\"width:50%\">\n<col style=\"width:25%\">\n<tbody>\n<tr>\n<td>A</td>\n<td>B C D</td>\n<td>E</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced");
TestParser.TestSpec("+----+--------+----+\n| A | B C D | E |\n+----+--------+----+", "<table>\n<col style=\"width:25%\" />\n<col style=\"width:50%\" />\n<col style=\"width:25%\" />\n<tbody>\n<tr>\n<td>A</td>\n<td>B C D</td>\n<td>E</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced", context: "Example 6\nSection Extensions / Grid Table\n");
}
// Alignment might be specified on the first row using the character `:`:
@@ -245,9 +238,9 @@ namespace Markdig.Tests.Specs.GridTables
//
// Should be rendered as:
// <table>
// <col style="width:33.33%">
// <col style="width:33.33%">
// <col style="width:33.33%">
// <col style="width:33.33%" />
// <col style="width:33.33%" />
// <col style="width:33.33%" />
// <tbody>
// <tr>
// <td>A</td>
@@ -257,8 +250,7 @@ namespace Markdig.Tests.Specs.GridTables
// </tbody>
// </table>
Console.WriteLine("Example 7\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+-----+:---:+-----+\n| A | B | C |\n+-----+-----+-----+", "<table>\n<col style=\"width:33.33%\">\n<col style=\"width:33.33%\">\n<col style=\"width:33.33%\">\n<tbody>\n<tr>\n<td>A</td>\n<td style=\"text-align: center;\">B</td>\n<td>C</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced");
TestParser.TestSpec("+-----+:---:+-----+\n| A | B | C |\n+-----+-----+-----+", "<table>\n<col style=\"width:33.33%\" />\n<col style=\"width:33.33%\" />\n<col style=\"width:33.33%\" />\n<tbody>\n<tr>\n<td>A</td>\n<td style=\"text-align: center;\">B</td>\n<td>C</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced", context: "Example 7\nSection Extensions / Grid Table\n");
}
// A grid table may have cells spanning both columns and rows:
@@ -279,9 +271,9 @@ namespace Markdig.Tests.Specs.GridTables
//
// Should be rendered as:
// <table>
// <col style="width:33.33%">
// <col style="width:33.33%">
// <col style="width:33.33%">
// <col style="width:33.33%" />
// <col style="width:33.33%" />
// <col style="width:33.33%" />
// <tbody>
// <tr>
// <td colspan="2">AAAAA</td>
@@ -301,8 +293,7 @@ namespace Markdig.Tests.Specs.GridTables
// </tbody>
// </table>
Console.WriteLine("Example 8\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+---+---+---+\n| AAAAA | B |\n+---+---+ B +\n| D | E | B |\n+ D +---+---+\n| D | CCCCC |\n+---+---+---+", "<table>\n<col style=\"width:33.33%\">\n<col style=\"width:33.33%\">\n<col style=\"width:33.33%\">\n<tbody>\n<tr>\n<td colspan=\"2\">AAAAA</td>\n<td rowspan=\"2\">B\nB\nB</td>\n</tr>\n<tr>\n<td rowspan=\"2\">D\nD\nD</td>\n<td>E</td>\n</tr>\n<tr>\n<td colspan=\"2\">CCCCC</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced");
TestParser.TestSpec("+---+---+---+\n| AAAAA | B |\n+---+---+ B +\n| D | E | B |\n+ D +---+---+\n| D | CCCCC |\n+---+---+---+", "<table>\n<col style=\"width:33.33%\" />\n<col style=\"width:33.33%\" />\n<col style=\"width:33.33%\" />\n<tbody>\n<tr>\n<td colspan=\"2\">AAAAA</td>\n<td rowspan=\"2\">B\nB\nB</td>\n</tr>\n<tr>\n<td rowspan=\"2\">D\nD\nD</td>\n<td>E</td>\n</tr>\n<tr>\n<td colspan=\"2\">CCCCC</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced", context: "Example 8\nSection Extensions / Grid Table\n");
}
// A grid table may have cells with both colspan and rowspan:
@@ -323,9 +314,9 @@ namespace Markdig.Tests.Specs.GridTables
//
// Should be rendered as:
// <table>
// <col style="width:33.33%">
// <col style="width:33.33%">
// <col style="width:33.33%">
// <col style="width:33.33%" />
// <col style="width:33.33%" />
// <col style="width:33.33%" />
// <tbody>
// <tr>
// <td colspan="2" rowspan="2">AAAAA
@@ -344,8 +335,7 @@ namespace Markdig.Tests.Specs.GridTables
// </tbody>
// </table>
Console.WriteLine("Example 9\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+---+---+---+\n| AAAAA | B |\n+ AAAAA +---+\n| AAAAA | C |\n+---+---+---+\n| D | E | F |\n+---+---+---+", "<table>\n<col style=\"width:33.33%\">\n<col style=\"width:33.33%\">\n<col style=\"width:33.33%\">\n<tbody>\n<tr>\n<td colspan=\"2\" rowspan=\"2\">AAAAA\nAAAAA\nAAAAA</td>\n<td>B</td>\n</tr>\n<tr>\n<td>C</td>\n</tr>\n<tr>\n<td>D</td>\n<td>E</td>\n<td>F</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced");
TestParser.TestSpec("+---+---+---+\n| AAAAA | B |\n+ AAAAA +---+\n| AAAAA | C |\n+---+---+---+\n| D | E | F |\n+---+---+---+", "<table>\n<col style=\"width:33.33%\" />\n<col style=\"width:33.33%\" />\n<col style=\"width:33.33%\" />\n<tbody>\n<tr>\n<td colspan=\"2\" rowspan=\"2\">AAAAA\nAAAAA\nAAAAA</td>\n<td>B</td>\n</tr>\n<tr>\n<td>C</td>\n</tr>\n<tr>\n<td>D</td>\n<td>E</td>\n<td>F</td>\n</tr>\n</tbody>\n</table>", "gridtables|advanced", context: "Example 9\nSection Extensions / Grid Table\n");
}
// A grid table may not have irregularly shaped cells:
@@ -373,8 +363,7 @@ namespace Markdig.Tests.Specs.GridTables
// | DDDDD | E |
// +---+---+---+</p>
Console.WriteLine("Example 10\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+---+---+---+\n| AAAAA | B |\n+ A +---+ B +\n| A | C | B |\n+---+---+---+\n| DDDDD | E |\n+---+---+---+", "<p>+---+---+---+\n| AAAAA | B |\n+ A +---+ B +\n| A | C | B |\n+---+---+---+\n| DDDDD | E |\n+---+---+---+</p>", "gridtables|advanced");
TestParser.TestSpec("+---+---+---+\n| AAAAA | B |\n+ A +---+ B +\n| A | C | B |\n+---+---+---+\n| DDDDD | E |\n+---+---+---+", "<p>+---+---+---+\n| AAAAA | B |\n+ A +---+ B +\n| A | C | B |\n+---+---+---+\n| DDDDD | E |\n+---+---+---+</p>", "gridtables|advanced", context: "Example 10\nSection Extensions / Grid Table\n");
}
// An empty `+` on a line should result in a simple empty list output:
@@ -392,8 +381,7 @@ namespace Markdig.Tests.Specs.GridTables
// <li></li>
// </ul>
Console.WriteLine("Example 11\nSection Extensions / Grid Table\n");
TestParser.TestSpec("+", "<ul>\n<li></li>\n</ul>", "gridtables|advanced");
TestParser.TestSpec("+", "<ul>\n<li></li>\n</ul>", "gridtables|advanced", context: "Example 11\nSection Extensions / Grid Table\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Hardline Breaks
@@ -33,8 +32,7 @@ namespace Markdig.Tests.Specs.HardlineBreaks
// <p>This is a paragraph<br />
// with a break inside</p>
Console.WriteLine("Example 1\nSection Extensions / Hardline break\n");
TestParser.TestSpec("This is a paragraph\nwith a break inside", "<p>This is a paragraph<br />\nwith a break inside</p>", "hardlinebreak|advanced+hardlinebreak");
TestParser.TestSpec("This is a paragraph\nwith a break inside", "<p>This is a paragraph<br />\nwith a break inside</p>", "hardlinebreak|advanced+hardlinebreak", context: "Example 1\nSection Extensions / Hardline break\n");
}
}
}

View File

@@ -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.
@@ -41,10 +40,9 @@ namespace Markdig.Tests.Specs.JiraLinks
// This is a ABCD-123 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/ABCD-123" target="_blank">ABCD-123</a> issue</p>
Console.WriteLine("Example 1\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 ABCD-123 issue", "<p>This is a <a href=\"http://your.company.abc/browse/ABCD-123\" target=\"_blank\">ABCD-123</a> issue</p>", "jiralinks", context: "Example 1\nSection Jira Links\n");
}
[Test]
@@ -54,13 +52,12 @@ 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", context: "Example 2\nSection Jira Links\n");
}
[Test]
@@ -70,16 +67,14 @@ 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", context: "Example 3\nSection Jira Links\n");
}
// These are also valid links with `(` and `)`:
[Test]
public void JiraLinks_Example004()
{
@@ -87,13 +82,12 @@ 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", context: "Example 4\nSection Jira Links\n");
}
[Test]
@@ -103,15 +97,15 @@ 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", context: "Example 5\nSection Jira Links\n");
}
// These are also valid links with `(` and `)`:
[Test]
public void JiraLinks_Example006()
{
@@ -119,16 +113,14 @@ 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", context: "Example 6\nSection Jira Links\n");
}
// These are not valid links:
[Test]
public void JiraLinks_Example007()
{
@@ -136,13 +128,12 @@ 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", context: "Example 7\nSection Jira Links\n");
}
[Test]
@@ -152,13 +143,12 @@ 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", context: "Example 8\nSection Jira Links\n");
}
[Test]
@@ -168,13 +158,88 @@ 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>
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", context: "Example 9\nSection Jira Links\n");
}
// 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>
TestParser.TestSpec("This is not aJIRA-123 issue", "<p>This is not aJIRA-123 issue</p>", "jiralinks", context: "Example 10\nSection Jira Links\n");
}
[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>
TestParser.TestSpec("This is not 4JIRA-123 issue", "<p>This is not 4JIRA-123 issue</p>", "jiralinks", context: "Example 11\nSection Jira Links\n");
}
[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>
TestParser.TestSpec("This is not JIRA-123a issue", "<p>This is not JIRA-123a issue</p>", "jiralinks", context: "Example 12\nSection Jira Links\n");
}
[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");
TestParser.TestSpec("This is not JIRA- issue", "<p>This is not JIRA- issue</p>", "jiralinks");
TestParser.TestSpec("This is not JIRA- issue", "<p>This is not JIRA- issue</p>", "jiralinks", context: "Example 13\nSection Jira Links\n");
}
[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>
TestParser.TestSpec("This is not JIR4- issue", "<p>This is not JIR4- issue</p>", "jiralinks", context: "Example 14\nSection Jira Links\n");
}
}
}

View File

@@ -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.
@@ -21,19 +21,31 @@ The following are valid examples:
```````````````````````````````` example
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>
<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
.
<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/KIRA-1" target="_blank">KIRA-1</a> issue</p>
````````````````````````````````
```````````````````````````````` example
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>
<p>This is a <a href="http://your.company.abc/browse/Z-1" target="_blank">Z-1</a> issue</p>
````````````````````````````````
These are also valid links with `(` and `)`:
@@ -41,19 +53,25 @@ These are also valid links with `(` and `)`:
```````````````````````````````` example
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>
<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
.
<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/KIRA-1" target="_blank">KIRA-1</a>) issue</p>
````````````````````````````````
```````````````````````````````` example
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>
<p>This is a (<a href="http://your.company.abc/browse/Z-1" target="_blank">Z-1</a>) issue</p>
````````````````````````````````
These are not valid links:
@@ -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>
````````````````````````````````

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// List Extras
@@ -37,8 +36,7 @@ namespace Markdig.Tests.Specs.ListExtras
// <li>Last item</li>
// </ol>
Console.WriteLine("Example 1\nSection Extensions / Ordered list with alpha letter\n");
TestParser.TestSpec("a. First item\nb. Second item\nc. Last item", "<ol type=\"a\">\n<li>First item</li>\n<li>Second item</li>\n<li>Last item</li>\n</ol>", "listextras|advanced");
TestParser.TestSpec("a. First item\nb. Second item\nc. Last item", "<ol type=\"a\">\n<li>First item</li>\n<li>Second item</li>\n<li>Last item</li>\n</ol>", "listextras|advanced", context: "Example 1\nSection Extensions / Ordered list with alpha letter\n");
}
// It works also for uppercase alpha:
@@ -60,8 +58,7 @@ namespace Markdig.Tests.Specs.ListExtras
// <li>Last item</li>
// </ol>
Console.WriteLine("Example 2\nSection Extensions / Ordered list with alpha letter\n");
TestParser.TestSpec("A. First item\nB. Second item\nC. Last item", "<ol type=\"A\">\n<li>First item</li>\n<li>Second item</li>\n<li>Last item</li>\n</ol>", "listextras|advanced");
TestParser.TestSpec("A. First item\nB. Second item\nC. Last item", "<ol type=\"A\">\n<li>First item</li>\n<li>Second item</li>\n<li>Last item</li>\n</ol>", "listextras|advanced", context: "Example 2\nSection Extensions / Ordered list with alpha letter\n");
}
// Like for numbered list, a list can start with a different letter
@@ -81,8 +78,7 @@ namespace Markdig.Tests.Specs.ListExtras
// <li>Second item</li>
// </ol>
Console.WriteLine("Example 3\nSection Extensions / Ordered list with alpha letter\n");
TestParser.TestSpec("b. First item\nc. Second item", "<ol type=\"a\" start=\"2\">\n<li>First item</li>\n<li>Second item</li>\n</ol>", "listextras|advanced");
TestParser.TestSpec("b. First item\nc. Second item", "<ol type=\"a\" start=\"2\">\n<li>First item</li>\n<li>Second item</li>\n</ol>", "listextras|advanced", context: "Example 3\nSection Extensions / Ordered list with alpha letter\n");
}
// A different type of list will break the existing list:
@@ -106,8 +102,7 @@ namespace Markdig.Tests.Specs.ListExtras
// <li>First item2</li>
// </ol>
Console.WriteLine("Example 4\nSection Extensions / Ordered list with alpha letter\n");
TestParser.TestSpec("a. First item1\nb. Second item\nA. First item2", "<ol type=\"a\">\n<li>First item1</li>\n<li>Second item</li>\n</ol>\n<ol type=\"A\">\n<li>First item2</li>\n</ol>", "listextras|advanced");
TestParser.TestSpec("a. First item1\nb. Second item\nA. First item2", "<ol type=\"a\">\n<li>First item1</li>\n<li>Second item</li>\n</ol>\n<ol type=\"A\">\n<li>First item2</li>\n</ol>", "listextras|advanced", context: "Example 4\nSection Extensions / Ordered list with alpha letter\n");
}
}
@@ -137,8 +132,7 @@ namespace Markdig.Tests.Specs.ListExtras
// <li>Last item</li>
// </ol>
Console.WriteLine("Example 5\nSection Extensions / Ordered list with roman letter\n");
TestParser.TestSpec("i. First item\nii. Second item\niii. Third item\niv. Last item", "<ol type=\"i\">\n<li>First item</li>\n<li>Second item</li>\n<li>Third item</li>\n<li>Last item</li>\n</ol>", "listextras|advanced");
TestParser.TestSpec("i. First item\nii. Second item\niii. Third item\niv. Last item", "<ol type=\"i\">\n<li>First item</li>\n<li>Second item</li>\n<li>Third item</li>\n<li>Last item</li>\n</ol>", "listextras|advanced", context: "Example 5\nSection Extensions / Ordered list with roman letter\n");
}
// It works also for uppercase alpha:
@@ -162,8 +156,7 @@ namespace Markdig.Tests.Specs.ListExtras
// <li>Last item</li>
// </ol>
Console.WriteLine("Example 6\nSection Extensions / Ordered list with roman letter\n");
TestParser.TestSpec("I. First item\nII. Second item\nIII. Third item\nIV. Last item", "<ol type=\"I\">\n<li>First item</li>\n<li>Second item</li>\n<li>Third item</li>\n<li>Last item</li>\n</ol>", "listextras|advanced");
TestParser.TestSpec("I. First item\nII. Second item\nIII. Third item\nIV. Last item", "<ol type=\"I\">\n<li>First item</li>\n<li>Second item</li>\n<li>Third item</li>\n<li>Last item</li>\n</ol>", "listextras|advanced", context: "Example 6\nSection Extensions / Ordered list with roman letter\n");
}
// Like for numbered list, a list can start with a different letter
@@ -183,8 +176,7 @@ namespace Markdig.Tests.Specs.ListExtras
// <li>Second item</li>
// </ol>
Console.WriteLine("Example 7\nSection Extensions / Ordered list with roman letter\n");
TestParser.TestSpec("ii. First item\niii. Second item", "<ol type=\"i\" start=\"2\">\n<li>First item</li>\n<li>Second item</li>\n</ol>", "listextras|advanced");
TestParser.TestSpec("ii. First item\niii. Second item", "<ol type=\"i\" start=\"2\">\n<li>First item</li>\n<li>Second item</li>\n</ol>", "listextras|advanced", context: "Example 7\nSection Extensions / Ordered list with roman letter\n");
}
// Lists can be restarted, specifying the start point.
@@ -210,8 +202,7 @@ namespace Markdig.Tests.Specs.ListExtras
// <li>Second item</li>
// </ol>
Console.WriteLine("Example 8\nSection Extensions / Ordered list with roman letter\n");
TestParser.TestSpec("1. First item\n\nSome text\n\n2. Second item", "<ol>\n<li>First item</li>\n</ol>\n<p>Some text</p>\n<ol start=\"2\">\n<li>Second item</li>\n</ol>", "listextras|advanced");
TestParser.TestSpec("1. First item\n\nSome text\n\n2. Second item", "<ol>\n<li>First item</li>\n</ol>\n<p>Some text</p>\n<ol start=\"2\">\n<li>Second item</li>\n</ol>", "listextras|advanced", context: "Example 8\nSection Extensions / Ordered list with roman letter\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Math
@@ -31,8 +30,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a <span class="math">\(math block\)</span></p>
Console.WriteLine("Example 1\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a $math block$", "<p>This is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced");
TestParser.TestSpec("This is a $math block$", "<p>This is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced", context: "Example 1\nSection Extensions / Math Inline\n");
}
// Or by `$$...$$` embracing it by:
@@ -48,8 +46,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a <span class="math">\(math block\)</span></p>
Console.WriteLine("Example 2\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a $$math block$$", "<p>This is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced");
TestParser.TestSpec("This is a $$math block$$", "<p>This is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced", context: "Example 2\nSection Extensions / Math Inline\n");
}
// Newlines inside an inline math are not allowed:
@@ -67,8 +64,7 @@ namespace Markdig.Tests.Specs.Math
// <p>This is not a $$math
// block$$ and? this is a <span class="math">\(math block\)</span></p>
Console.WriteLine("Example 3\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is not a $$math \nblock$$ and? this is a $$math block$$", "<p>This is not a $$math\nblock$$ and? this is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced");
TestParser.TestSpec("This is not a $$math \nblock$$ and? this is a $$math block$$", "<p>This is not a $$math\nblock$$ and? this is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced", context: "Example 3\nSection Extensions / Math Inline\n");
}
[Test]
@@ -85,8 +81,7 @@ namespace Markdig.Tests.Specs.Math
// <p>This is not a $math
// block$ and? this is a <span class="math">\(math block\)</span></p>
Console.WriteLine("Example 4\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is not a $math \nblock$ and? this is a $math block$", "<p>This is not a $math\nblock$ and? this is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced");
TestParser.TestSpec("This is not a $math \nblock$ and? this is a $math block$", "<p>This is not a $math\nblock$ and? this is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced", context: "Example 4\nSection Extensions / Math Inline\n");
}
// An opening `$` can be followed by a space if the closing is also preceded by a space `$`:
@@ -102,8 +97,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a <span class="math">\(math block\)</span></p>
Console.WriteLine("Example 5\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a $ math block $", "<p>This is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced");
TestParser.TestSpec("This is a $ math block $", "<p>This is a <span class=\"math\">\\(math block\\)</span></p>", "mathematics|advanced", context: "Example 5\nSection Extensions / Math Inline\n");
}
[Test]
@@ -118,8 +112,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a <span class="math">\(math block\)</span> after</p>
Console.WriteLine("Example 6\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a $ math block $ after", "<p>This is a <span class=\"math\">\\(math block\\)</span> after</p>", "mathematics|advanced");
TestParser.TestSpec("This is a $ math block $ after", "<p>This is a <span class=\"math\">\\(math block\\)</span> after</p>", "mathematics|advanced", context: "Example 6\nSection Extensions / Math Inline\n");
}
[Test]
@@ -134,8 +127,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a <span class="math">\(math block\)</span> after</p>
Console.WriteLine("Example 7\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a $$ math block $$ after", "<p>This is a <span class=\"math\">\\(math block\\)</span> after</p>", "mathematics|advanced");
TestParser.TestSpec("This is a $$ math block $$ after", "<p>This is a <span class=\"math\">\\(math block\\)</span> after</p>", "mathematics|advanced", context: "Example 7\nSection Extensions / Math Inline\n");
}
[Test]
@@ -150,8 +142,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a not $ math block$ because there is not a whitespace before the closing</p>
Console.WriteLine("Example 8\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a not $ math block$ because there is not a whitespace before the closing", "<p>This is a not $ math block$ because there is not a whitespace before the closing</p>", "mathematics|advanced");
TestParser.TestSpec("This is a not $ math block$ because there is not a whitespace before the closing", "<p>This is a not $ math block$ because there is not a whitespace before the closing</p>", "mathematics|advanced", context: "Example 8\nSection Extensions / Math Inline\n");
}
// For the opening `$` it requires a space or a punctuation before (but cannot be used within a word):
@@ -167,8 +158,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is not a m$ath block$</p>
Console.WriteLine("Example 9\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is not a m$ath block$", "<p>This is not a m$ath block$</p>", "mathematics|advanced");
TestParser.TestSpec("This is not a m$ath block$", "<p>This is not a m$ath block$</p>", "mathematics|advanced", context: "Example 9\nSection Extensions / Math Inline\n");
}
// For the closing `$` it requires a space after or a punctuation (but cannot be preceded by a space and cannot be used within a word):
@@ -184,8 +174,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is not a $math bloc$k</p>
Console.WriteLine("Example 10\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is not a $math bloc$k", "<p>This is not a $math bloc$k</p>", "mathematics|advanced");
TestParser.TestSpec("This is not a $math bloc$k", "<p>This is not a $math bloc$k</p>", "mathematics|advanced", context: "Example 10\nSection Extensions / Math Inline\n");
}
// For the closing `$` it requires a space after or a punctuation (but cannot be preceded by a space and cannot be used within a word):
@@ -201,8 +190,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is should not match a 16$ or a $15</p>
Console.WriteLine("Example 11\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is should not match a 16$ or a $15", "<p>This is should not match a 16$ or a $15</p>", "mathematics|advanced");
TestParser.TestSpec("This is should not match a 16$ or a $15", "<p>This is should not match a 16$ or a $15</p>", "mathematics|advanced", context: "Example 11\nSection Extensions / Math Inline\n");
}
// A `$` can be escaped between a math inline block by using the escape `\\`
@@ -218,8 +206,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a <span class="math">\(math \$ block\)</span></p>
Console.WriteLine("Example 12\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a $math \\$ block$", "<p>This is a <span class=\"math\">\\(math \\$ block\\)</span></p>", "mathematics|advanced");
TestParser.TestSpec("This is a $math \\$ block$", "<p>This is a <span class=\"math\">\\(math \\$ block\\)</span></p>", "mathematics|advanced", context: "Example 12\nSection Extensions / Math Inline\n");
}
// At most, two `$` will be matched for the opening and closing:
@@ -235,8 +222,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a <span class="math">\($math block$\)</span></p>
Console.WriteLine("Example 13\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a $$$math block$$$", "<p>This is a <span class=\"math\">\\($math block$\\)</span></p>", "mathematics|advanced");
TestParser.TestSpec("This is a $$$math block$$$", "<p>This is a <span class=\"math\">\\($math block$\\)</span></p>", "mathematics|advanced", context: "Example 13\nSection Extensions / Math Inline\n");
}
// Regular text can come both before and after the math inline
@@ -252,8 +238,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is a <span class="math">\(math block\)</span> with text on both sides.</p>
Console.WriteLine("Example 14\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is a $math block$ with text on both sides.", "<p>This is a <span class=\"math\">\\(math block\\)</span> with text on both sides.</p>", "mathematics|advanced");
TestParser.TestSpec("This is a $math block$ with text on both sides.", "<p>This is a <span class=\"math\">\\(math block\\)</span> with text on both sides.</p>", "mathematics|advanced", context: "Example 14\nSection Extensions / Math Inline\n");
}
// A mathematic block takes precedence over standard emphasis `*` `_`:
@@ -269,8 +254,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p>This is *a <span class="math">\(math* block\)</span></p>
Console.WriteLine("Example 15\nSection Extensions / Math Inline\n");
TestParser.TestSpec("This is *a $math* block$", "<p>This is *a <span class=\"math\">\\(math* block\\)</span></p>", "mathematics|advanced");
TestParser.TestSpec("This is *a $math* block$", "<p>This is *a <span class=\"math\">\\(math* block\\)</span></p>", "mathematics|advanced", context: "Example 15\nSection Extensions / Math Inline\n");
}
// An opening $$ at the beginning of a line should not be interpreted as a Math block:
@@ -286,8 +270,7 @@ namespace Markdig.Tests.Specs.Math
// Should be rendered as:
// <p><span class="math">\(math\)</span> starting at a line</p>
Console.WriteLine("Example 16\nSection Extensions / Math Inline\n");
TestParser.TestSpec("$$ math $$ starting at a line", "<p><span class=\"math\">\\(math\\)</span> starting at a line</p>", "mathematics|advanced");
TestParser.TestSpec("$$ math $$ starting at a line", "<p><span class=\"math\">\\(math\\)</span> starting at a line</p>", "mathematics|advanced", context: "Example 16\nSection Extensions / Math Inline\n");
}
}
@@ -321,8 +304,7 @@ namespace Markdig.Tests.Specs.Math
// \end{equation}
// \]</div>
Console.WriteLine("Example 17\nSection Extensions / Math Block\n");
TestParser.TestSpec("$$\n\\begin{equation}\n \\int_0^\\infty \\frac{x^3}{e^x-1}\\,dx = \\frac{\\pi^4}{15}\n \\label{eq:sample}\n\\end{equation}\n$$", "<div class=\"math\">\n\\[\n\\begin{equation}\n \\int_0^\\infty \\frac{x^3}{e^x-1}\\,dx = \\frac{\\pi^4}{15}\n \\label{eq:sample}\n\\end{equation}\n\\]</div>", "mathematics|advanced");
TestParser.TestSpec("$$\n\\begin{equation}\n \\int_0^\\infty \\frac{x^3}{e^x-1}\\,dx = \\frac{\\pi^4}{15}\n \\label{eq:sample}\n\\end{equation}\n$$", "<div class=\"math\">\n\\[\n\\begin{equation}\n \\int_0^\\infty \\frac{x^3}{e^x-1}\\,dx = \\frac{\\pi^4}{15}\n \\label{eq:sample}\n\\end{equation}\n\\]</div>", "mathematics|advanced", context: "Example 17\nSection Extensions / Math Block\n");
}
}
}

View File

@@ -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
// ![youtu.be with t](https://youtu.be/mswPy5bt3TQ?t=100)
//
// ![youtube.com/embed 1](https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0)
//
//
// ![youtube.com/embed 2](https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6)
//
// ![vimeo](https://vimeo.com/8607834)
@@ -47,19 +46,18 @@ namespace Markdig.Tests.Specs.Media
// ![ok.ru](https://ok.ru/video/26870090463)
//
// 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&amp;rel=0" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
// <p><iframe src="https://www.youtube.com/embed?listType=playlist&amp;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&amp;rel=0" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
// <p><iframe src="https://www.youtube.com/embed?listType=playlist&amp;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("![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)\n\n![youtube.com with t](https://www.youtube.com/watch?v=mswPy5bt3TQ&t=100)\n\n![youtu.be](https://youtu.be/mswPy5bt3TQ)\n\n![youtu.be with t](https://youtu.be/mswPy5bt3TQ?t=100)\n\n![youtube.com/embed 1](https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0)\n \n![youtube.com/embed 2](https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6)\n\n![vimeo](https://vimeo.com/8607834)\n\n![static mp4](https://sample.com/video.mp4)\n\n![yandex.ru](https://music.yandex.ru/album/411845/track/4402274)\n\n![ok.ru](https://ok.ru/video/26870090463)", "<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&amp;rel=0\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed?listType=playlist&amp;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("![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)\n\n![youtube.com with t](https://www.youtube.com/watch?v=mswPy5bt3TQ&t=100)\n\n![youtu.be](https://youtu.be/mswPy5bt3TQ)\n\n![youtu.be with t](https://youtu.be/mswPy5bt3TQ?t=100)\n\n![youtube.com/embed 1](https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0)\n\n![youtube.com/embed 2](https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6)\n\n![vimeo](https://vimeo.com/8607834)\n\n![static mp4](https://sample.com/video.mp4)\n\n![yandex.ru](https://music.yandex.ru/album/411845/track/4402274)\n\n![ok.ru](https://ok.ru/video/26870090463)", "<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&amp;rel=0\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n<p><iframe src=\"https://www.youtube.com/embed?listType=playlist&amp;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", context: "Example 1\nSection Extensions / Media links\n");
}
}
}

View File

@@ -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:
![youtu.be with t](https://youtu.be/mswPy5bt3TQ?t=100)
![youtube.com/embed 1](https://www.youtube.com/embed/mswPy5bt3TQ?start=100&rel=0)
![youtube.com/embed 2](https://www.youtube.com/embed?listType=playlist&list=PLC77007E23FF423C6)
![vimeo](https://vimeo.com/8607834)
@@ -27,14 +27,14 @@ Allows to embed audio/video links to popular website:
![ok.ru](https://ok.ru/video/26870090463)
.
<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&amp;rel=0" width="500" height="281" class="youtube" frameborder="0" allowfullscreen=""></iframe></p>
<p><iframe src="https://www.youtube.com/embed?listType=playlist&amp;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&amp;rel=0" class="youtube" width="500" height="281" frameborder="0" allowfullscreen=""></iframe></p>
<p><iframe src="https://www.youtube.com/embed?listType=playlist&amp;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>
````````````````````````````````

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// No Html
@@ -31,8 +30,7 @@ namespace Markdig.Tests.Specs.NoHtml
// Should be rendered as:
// <p>this is some text&lt;/td&gt;&lt;/tr&gt;</p>
Console.WriteLine("Example 1\nSection Extensions / NoHTML\n");
TestParser.TestSpec("this is some text</td></tr>", "<p>this is some text&lt;/td&gt;&lt;/tr&gt;</p>", "nohtml");
TestParser.TestSpec("this is some text</td></tr>", "<p>this is some text&lt;/td&gt;&lt;/tr&gt;</p>", "nohtml", context: "Example 1\nSection Extensions / NoHTML\n");
}
// For Block HTML:
@@ -52,8 +50,7 @@ namespace Markdig.Tests.Specs.NoHtml
// this is some text
// &lt;/div&gt;</p>
Console.WriteLine("Example 2\nSection Extensions / NoHTML\n");
TestParser.TestSpec("<div>\nthis is some text\n</div>", "<p>&lt;div&gt;\nthis is some text\n&lt;/div&gt;</p>", "nohtml");
TestParser.TestSpec("<div>\nthis is some text\n</div>", "<p>&lt;div&gt;\nthis is some text\n&lt;/div&gt;</p>", "nohtml", context: "Example 2\nSection Extensions / NoHTML\n");
}
}
}

View File

@@ -0,0 +1,831 @@
// --------------------------------
// 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>
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", context: "Example 1\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 2\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 3\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 4\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
TestParser.TestSpec("a b\nc | d\ne | f", "<p>a b\nc | d\ne | f</p>", "gfm-pipetables", context: "Example 5\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
TestParser.TestSpec("a | b\nc no d", "<p>a | b\nc no d</p>", "gfm-pipetables", context: "Example 6\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 7\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 8\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 9\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 10\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 11\nSection Extensions / Gfm Pipe Table\n");
}
[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>
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", context: "Example 12\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 13\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 14\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 15\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
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", context: "Example 16\nSection Extensions / Gfm Pipe Table\n");
}
// 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>
TestParser.TestSpec(" a | b\n-------|---x---\n 0 | 1\n 2 | 3 ", "<p>a | b\n-------|---x---\n0 | 1\n2 | 3</p> ", "gfm-pipetables", context: "Example 17\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 18\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
TestParser.TestSpec("a | b `\n0 | ` ", "<p>a | b <code>0 |</code></p> ", "gfm-pipetables", context: "Example 19\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 20\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 21\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 22\nSection Extensions / Gfm Pipe Table\n");
}
[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>
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", context: "Example 23\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 24\nSection Extensions / Gfm Pipe Table\n");
}
// **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>
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", context: "Example 25\nSection Extensions / Gfm Pipe Table\n");
}
}
}

View 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>
````````````````````````````````

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-15 05:54:35
// --------------------------------
// Pipe Tables
@@ -57,8 +56,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 1\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 1\nSection Extensions / Pipe Table\n");
}
// The following is also considered as a table, even if the second line starts like a list:
@@ -89,8 +87,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 2\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 2\nSection Extensions / Pipe Table\n");
}
// A pipe table with only one header row is allowed:
@@ -114,8 +111,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </thead>
// </table>
Console.WriteLine("Example 3\nSection Extensions / 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>", "pipetables|advanced");
TestParser.TestSpec("a | b\n-- | --", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n</table>", "pipetables|advanced", context: "Example 3\nSection Extensions / Pipe Table\n");
}
// After a row separator header, they will be interpreted as plain column:
@@ -146,8 +142,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 4\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 4\nSection Extensions / Pipe Table\n");
}
// 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
@@ -167,8 +162,7 @@ namespace Markdig.Tests.Specs.PipeTables
// c | d
// e | f</p>
Console.WriteLine("Example 5\nSection Extensions / Pipe Table\n");
TestParser.TestSpec("a b\nc | d\ne | f", "<p>a b\nc | d\ne | f</p>", "pipetables|advanced");
TestParser.TestSpec("a b\nc | d\ne | f", "<p>a b\nc | d\ne | f</p>", "pipetables|advanced", context: "Example 5\nSection Extensions / Pipe Table\n");
}
// If a line doesn't have a column delimiter `|` the table is not detected
@@ -186,8 +180,7 @@ namespace Markdig.Tests.Specs.PipeTables
// <p>a | b
// c no d</p>
Console.WriteLine("Example 6\nSection Extensions / Pipe Table\n");
TestParser.TestSpec("a | b\nc no d", "<p>a | b\nc no d</p>", "pipetables|advanced");
TestParser.TestSpec("a | b\nc no d", "<p>a | b\nc no d</p>", "pipetables|advanced", context: "Example 6\nSection Extensions / Pipe Table\n");
}
// If a row contains more column than the header row, it will still be added as a column:
@@ -232,8 +225,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 7\nSection Extensions / 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<th></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n</tr>\n<tr>\n<td>3</td>\n<td>4</td>\n<td></td>\n</tr>\n<tr>\n<td>5</td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
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<th></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n</tr>\n<tr>\n<td>3</td>\n<td>4</td>\n<td></td>\n</tr>\n<tr>\n<td>5</td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced", context: "Example 7\nSection Extensions / Pipe Table\n");
}
// **Rule #2**
@@ -268,8 +260,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 8\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 8\nSection Extensions / Pipe Table\n");
}
// **Rule #4**
@@ -311,8 +302,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 9\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 9\nSection Extensions / Pipe Table\n");
}
// A pipe may be present at both the beginning/ending of each line:
@@ -343,8 +333,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 10\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 10\nSection Extensions / Pipe Table\n");
}
// Or may be omitted on one side:
@@ -375,8 +364,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 11\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 11\nSection Extensions / Pipe Table\n");
}
[Test]
@@ -406,8 +394,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 12\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 12\nSection Extensions / Pipe Table\n");
}
// Single column table can be declared with lines starting only by a column delimiter:
@@ -440,8 +427,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 13\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 13\nSection Extensions / Pipe Table\n");
}
// **Rule #5**
@@ -485,8 +471,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 14\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 14\nSection Extensions / Pipe Table\n");
}
// 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.
@@ -527,8 +512,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 15\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 15\nSection Extensions / Pipe Table\n");
}
// Test alignment with starting and ending pipes:
@@ -561,8 +545,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 16\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 16\nSection Extensions / Pipe Table\n");
}
// The following example shows a non matching header column separator:
@@ -584,8 +567,7 @@ namespace Markdig.Tests.Specs.PipeTables
// 0 | 1
// 2 | 3</p>
Console.WriteLine("Example 17\nSection Extensions / 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> ", "pipetables|advanced");
TestParser.TestSpec(" a | b\n-------|---x---\n 0 | 1\n 2 | 3 ", "<p>a | b\n-------|---x---\n0 | 1\n2 | 3</p> ", "pipetables|advanced", context: "Example 17\nSection Extensions / Pipe Table\n");
}
// **Rule #6**
@@ -623,8 +605,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 18\nSection Extensions / 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>", "pipetables|advanced");
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>", "pipetables|advanced", context: "Example 18\nSection Extensions / Pipe Table\n");
}
// **Rule #7**
@@ -643,11 +624,10 @@ namespace Markdig.Tests.Specs.PipeTables
// Should be rendered as:
// <p>a | b <code>0 |</code></p>
Console.WriteLine("Example 19\nSection Extensions / Pipe Table\n");
TestParser.TestSpec("a | b `\n0 | ` ", "<p>a | b <code>0 |</code></p> ", "pipetables|advanced");
TestParser.TestSpec("a | b `\n0 | ` ", "<p>a | b <code>0 |</code></p> ", "pipetables|advanced", context: "Example 19\nSection Extensions / Pipe Table\n");
}
// **Rule #7**
// **Rule #8**
//
// A HTML inline has a higher precedence than a column delimiter `|`:
[Test]
@@ -677,11 +657,10 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 20\nSection Extensions / 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>", "pipetables|advanced");
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", context: "Example 20\nSection Extensions / Pipe Table\n");
}
// **Rule #8**
// **Rule #9**
//
// Links have a higher precedence than the column delimiter character `|`:
[Test]
@@ -711,11 +690,10 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 21\nSection Extensions / 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>", "pipetables|advanced");
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", context: "Example 21\nSection Extensions / Pipe Table\n");
}
// ** Rule #9**
// **Rule #10**
//
// It is possible to have a single row header only:
[Test]
@@ -738,8 +716,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </thead>
// </table>
Console.WriteLine("Example 22\nSection Extensions / 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>", "pipetables|advanced");
TestParser.TestSpec("a | b\n-- | --", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n</table>", "pipetables|advanced", context: "Example 22\nSection Extensions / Pipe Table\n");
}
[Test]
@@ -763,11 +740,10 @@ namespace Markdig.Tests.Specs.PipeTables
// </thead>
// </table>
Console.WriteLine("Example 23\nSection Extensions / 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>", "pipetables|advanced");
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", context: "Example 23\nSection Extensions / Pipe Table\n");
}
// ** Tests **
// **Tests**
//
// Tests trailing spaces after pipes
[Test]
@@ -812,11 +788,10 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 24\nSection Extensions / 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>", "pipetables|advanced");
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", context: "Example 24\nSection Extensions / Pipe Table\n");
}
// ** Normalized columns count **
// **Normalized columns count**
//
// The tables are normalized to the maximum number of columns found in a table
[Test]
@@ -848,8 +823,7 @@ namespace Markdig.Tests.Specs.PipeTables
// </tbody>
// </table>
Console.WriteLine("Example 25\nSection Extensions / Pipe Table\n");
TestParser.TestSpec("a | b\n-- | - \n0 | 1 | 2", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced");
TestParser.TestSpec("a | b\n-- | - \n0 | 1 | 2", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n<td>2</td>\n</tr>\n</tbody>\n</table>", "pipetables|advanced", context: "Example 25\nSection Extensions / Pipe Table\n");
}
}
}

View File

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

View File

@@ -1,4 +1,3 @@
// Generated: 2019-08-01 12:33:23
// --------------------------------
// Smarty Pants
@@ -31,8 +30,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &ldquo;text&rdquo;</p>
Console.WriteLine("Example 1\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a \"text\"", "<p>This is a &ldquo;text&rdquo;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a \"text\"", "<p>This is a &ldquo;text&rdquo;</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 1\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -47,8 +45,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &lsquo;text&rsquo;</p>
Console.WriteLine("Example 2\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a 'text'", "<p>This is a &lsquo;text&rsquo;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a 'text'", "<p>This is a &lsquo;text&rsquo;</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 2\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -63,8 +60,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &laquo;text&raquo;</p>
Console.WriteLine("Example 3\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a <<text>>", "<p>This is a &laquo;text&raquo;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a <<text>>", "<p>This is a &laquo;text&raquo;</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 3\nSection Extensions / SmartyPants Quotes\n");
}
// Unbalanced quotes are not changed:
@@ -80,8 +76,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &quot;text</p>
Console.WriteLine("Example 4\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a \"text", "<p>This is a &quot;text</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a \"text", "<p>This is a &quot;text</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 4\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -96,8 +91,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a 'text</p>
Console.WriteLine("Example 5\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a 'text", "<p>This is a 'text</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a 'text", "<p>This is a 'text</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 5\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -112,8 +106,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &lt;&lt;text</p>
Console.WriteLine("Example 6\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a <<text", "<p>This is a &lt;&lt;text</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a <<text", "<p>This is a &lt;&lt;text</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 6\nSection Extensions / SmartyPants Quotes\n");
}
// Unbalanced quotes inside other quotes are not changed:
@@ -129,8 +122,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &ldquo;text 'with&rdquo; a another text'</p>
Console.WriteLine("Example 7\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a \"text 'with\" a another text'", "<p>This is a &ldquo;text 'with&rdquo; a another text'</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a \"text 'with\" a another text'", "<p>This is a &ldquo;text 'with&rdquo; a another text'</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 7\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -145,8 +137,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is &lsquo;a &ldquo;text 'with&rdquo; a another text&rsquo;</p>
Console.WriteLine("Example 8\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is 'a \"text 'with\" a another text'", "<p>This is &lsquo;a &ldquo;text 'with&rdquo; a another text&rsquo;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is 'a \"text 'with\" a another text'", "<p>This is &lsquo;a &ldquo;text 'with&rdquo; a another text&rsquo;</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 8\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -161,8 +152,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &lsquo;text &lt;&lt;with&rsquo; a another text&gt;&gt;</p>
Console.WriteLine("Example 9\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a 'text <<with' a another text>>", "<p>This is a &lsquo;text &lt;&lt;with&rsquo; a another text&gt;&gt;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a 'text <<with' a another text>>", "<p>This is a &lsquo;text &lt;&lt;with&rsquo; a another text&gt;&gt;</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 9\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -177,8 +167,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &laquo;text 'with&raquo; a another text'</p>
Console.WriteLine("Example 10\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a <<text 'with>> a another text'", "<p>This is a &laquo;text 'with&raquo; a another text'</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a <<text 'with>> a another text'", "<p>This is a &laquo;text 'with&raquo; a another text'</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 10\nSection Extensions / SmartyPants Quotes\n");
}
// Quotes requires to have the same rules than emphasis `_` regarding left/right frankling rules:
@@ -194,8 +183,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>It's not quotes'</p>
Console.WriteLine("Example 11\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("It's not quotes'", "<p>It's not quotes'</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("It's not quotes'", "<p>It's not quotes'</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 11\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -210,8 +198,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>They are ' not matching quotes '</p>
Console.WriteLine("Example 12\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("They are ' not matching quotes '", "<p>They are ' not matching quotes '</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("They are ' not matching quotes '", "<p>They are ' not matching quotes '</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 12\nSection Extensions / SmartyPants Quotes\n");
}
[Test]
@@ -226,8 +213,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>They are' not matching 'quotes</p>
Console.WriteLine("Example 13\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("They are' not matching 'quotes", "<p>They are' not matching 'quotes</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("They are' not matching 'quotes", "<p>They are' not matching 'quotes</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 13\nSection Extensions / SmartyPants Quotes\n");
}
// An emphasis starting inside left/right quotes will span over the right quote:
@@ -243,8 +229,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is &ldquo;a <em>text&rdquo; with an emphasis</em></p>
Console.WriteLine("Example 14\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is \"a *text\" with an emphasis*", "<p>This is &ldquo;a <em>text&rdquo; with an emphasis</em></p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is \"a *text\" with an emphasis*", "<p>This is &ldquo;a <em>text&rdquo; with an emphasis</em></p>", "pipetables+smartypants|advanced+smartypants", context: "Example 14\nSection Extensions / SmartyPants Quotes\n");
}
// Multiple sets of quotes can be used
@@ -260,8 +245,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>&ldquo;aaa&rdquo; &ldquo;bbb&rdquo; &ldquo;ccc&rdquo; &ldquo;ddd&rdquo;</p>
Console.WriteLine("Example 15\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("\"aaa\" \"bbb\" \"ccc\" \"ddd\"", "<p>&ldquo;aaa&rdquo; &ldquo;bbb&rdquo; &ldquo;ccc&rdquo; &ldquo;ddd&rdquo;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("\"aaa\" \"bbb\" \"ccc\" \"ddd\"", "<p>&ldquo;aaa&rdquo; &ldquo;bbb&rdquo; &ldquo;ccc&rdquo; &ldquo;ddd&rdquo;</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 15\nSection Extensions / SmartyPants Quotes\n");
}
}
@@ -281,8 +265,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &ndash; text</p>
Console.WriteLine("Example 16\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("This is a -- text", "<p>This is a &ndash; text</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a -- text", "<p>This is a &ndash; text</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 16\nSection Extensions / SmartyPants Separators\n");
}
[Test]
@@ -297,8 +280,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &mdash; text</p>
Console.WriteLine("Example 17\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("This is a --- text", "<p>This is a &mdash; text</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a --- text", "<p>This is a &mdash; text</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 17\nSection Extensions / SmartyPants Separators\n");
}
[Test]
@@ -313,8 +295,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a en ellipsis&hellip;</p>
Console.WriteLine("Example 18\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("This is a en ellipsis...", "<p>This is a en ellipsis&hellip;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is a en ellipsis...", "<p>This is a en ellipsis&hellip;</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 18\nSection Extensions / SmartyPants Separators\n");
}
// Check that a smartypants are not breaking pipetable parsing:
@@ -345,8 +326,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// </tbody>
// </table>
Console.WriteLine("Example 19\nSection Extensions / SmartyPants Separators\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>", "pipetables+smartypants|advanced+smartypants");
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>", "pipetables+smartypants|advanced+smartypants", context: "Example 19\nSection Extensions / SmartyPants Separators\n");
}
// Check quotes and dash:
@@ -362,8 +342,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>A &ldquo;quote&rdquo; with a &mdash;</p>
Console.WriteLine("Example 20\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("A \"quote\" with a ---", "<p>A &ldquo;quote&rdquo; with a &mdash;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("A \"quote\" with a ---", "<p>A &ldquo;quote&rdquo; with a &mdash;</p>", "pipetables+smartypants|advanced+smartypants", context: "Example 20\nSection Extensions / SmartyPants Separators\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Task Lists
@@ -39,8 +38,7 @@ namespace Markdig.Tests.Specs.TaskLists
// <li>Item4</li>
// </ul>
Console.WriteLine("Example 1\nSection Extensions / TaskLists\n");
TestParser.TestSpec("- [ ] Item1\n- [x] Item2\n- [ ] Item3\n- Item4", "<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" /> Item1</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> Item2</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" /> Item3</li>\n<li>Item4</li>\n</ul>", "tasklists|advanced");
TestParser.TestSpec("- [ ] Item1\n- [x] Item2\n- [ ] Item3\n- Item4", "<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" /> Item1</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" checked=\"checked\" /> Item2</li>\n<li class=\"task-list-item\"><input disabled=\"disabled\" type=\"checkbox\" /> Item3</li>\n<li>Item4</li>\n</ul>", "tasklists|advanced", context: "Example 1\nSection Extensions / TaskLists\n");
}
// A task is not recognized outside a list item:
@@ -56,8 +54,7 @@ namespace Markdig.Tests.Specs.TaskLists
// Should be rendered as:
// <p>[ ] This is not a task list</p>
Console.WriteLine("Example 2\nSection Extensions / TaskLists\n");
TestParser.TestSpec("[ ] This is not a task list", "<p>[ ] This is not a task list</p>", "tasklists|advanced");
TestParser.TestSpec("[ ] This is not a task list", "<p>[ ] This is not a task list</p>", "tasklists|advanced", context: "Example 2\nSection Extensions / TaskLists\n");
}
}
}

View File

@@ -1,4 +1,3 @@
// Generated: 2019-04-05 16:06:14
// --------------------------------
// Yaml
@@ -34,8 +33,7 @@ namespace Markdig.Tests.Specs.Yaml
// Should be rendered as:
// <p>This is a text</p>
Console.WriteLine("Example 1\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("---\nthis: is a frontmatter\n---\nThis is a text", "<p>This is a text</p>", "yaml");
TestParser.TestSpec("---\nthis: is a frontmatter\n---\nThis is a text", "<p>This is a text</p>", "yaml", context: "Example 1\nSection Extensions / YAML frontmatter discard\n");
}
// But if a frontmatter doesn't happen on the first line, it will be parse as regular Markdown content
@@ -57,8 +55,7 @@ namespace Markdig.Tests.Specs.Yaml
// <h2>this: is a frontmatter</h2>
// <p>This is a text2</p>
Console.WriteLine("Example 2\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("This is a text1\n---\nthis: is a frontmatter\n---\nThis is a text2", "<h2>This is a text1</h2>\n<h2>this: is a frontmatter</h2>\n<p>This is a text2</p>", "yaml");
TestParser.TestSpec("This is a text1\n---\nthis: is a frontmatter\n---\nThis is a text2", "<h2>This is a text1</h2>\n<h2>this: is a frontmatter</h2>\n<p>This is a text2</p>", "yaml", context: "Example 2\nSection Extensions / YAML frontmatter discard\n");
}
// It expects an exact 3 dashes `---`:
@@ -79,8 +76,7 @@ namespace Markdig.Tests.Specs.Yaml
// <h2>this: is a frontmatter</h2>
// <p>This is a text</p>
Console.WriteLine("Example 3\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("----\nthis: is a frontmatter\n----\nThis is a text", "<hr />\n<h2>this: is a frontmatter</h2>\n<p>This is a text</p>", "yaml");
TestParser.TestSpec("----\nthis: is a frontmatter\n----\nThis is a text", "<hr />\n<h2>this: is a frontmatter</h2>\n<p>This is a text</p>", "yaml", context: "Example 3\nSection Extensions / YAML frontmatter discard\n");
}
// It can end with three dots `...`:
@@ -100,8 +96,7 @@ namespace Markdig.Tests.Specs.Yaml
// Should be rendered as:
// <p>This is a text</p>
Console.WriteLine("Example 4\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("---\nthis: is a frontmatter\n\n...\nThis is a text", "<p>This is a text</p>", "yaml");
TestParser.TestSpec("---\nthis: is a frontmatter\n\n...\nThis is a text", "<p>This is a text</p>", "yaml", context: "Example 4\nSection Extensions / YAML frontmatter discard\n");
}
// If the end front matter marker (`...` or `---`) is not present, it will render the `---` has a `<hr>`:
@@ -121,8 +116,7 @@ namespace Markdig.Tests.Specs.Yaml
// <p>this: is a frontmatter
// This is a text</p>
Console.WriteLine("Example 5\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("---\nthis: is a frontmatter\nThis is a text", "<hr />\n<p>this: is a frontmatter\nThis is a text</p>", "yaml");
TestParser.TestSpec("---\nthis: is a frontmatter\nThis is a text", "<hr />\n<p>this: is a frontmatter\nThis is a text</p>", "yaml", context: "Example 5\nSection Extensions / YAML frontmatter discard\n");
}
// It expects exactly three dots `...`:
@@ -144,8 +138,7 @@ namespace Markdig.Tests.Specs.Yaml
// ....
// This is a text</p>
Console.WriteLine("Example 6\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("---\nthis: is a frontmatter\n....\nThis is a text", "<hr />\n<p>this: is a frontmatter\n....\nThis is a text</p>", "yaml");
TestParser.TestSpec("---\nthis: is a frontmatter\n....\nThis is a text", "<hr />\n<p>this: is a frontmatter\n....\nThis is a text</p>", "yaml", context: "Example 6\nSection Extensions / YAML frontmatter discard\n");
}
// Front matter ends with the first line containing three dots `...` or three dashes `---`:
@@ -167,8 +160,7 @@ namespace Markdig.Tests.Specs.Yaml
// Should be rendered as:
// <p>This is a text</p>
Console.WriteLine("Example 7\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("---\nthis: is a frontmatter\n....\n\nHello\n---\nThis is a text", "<p>This is a text</p>", "yaml");
TestParser.TestSpec("---\nthis: is a frontmatter\n....\n\nHello\n---\nThis is a text", "<p>This is a text</p>", "yaml", context: "Example 7\nSection Extensions / YAML frontmatter discard\n");
}
// It expects whitespace can exist after the leading characters
@@ -187,8 +179,7 @@ namespace Markdig.Tests.Specs.Yaml
// Should be rendered as:
// <p>This is a text</p>
Console.WriteLine("Example 8\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("--- \nthis: is a frontmatter\n...\nThis is a text", "<p>This is a text</p>", "yaml");
TestParser.TestSpec("--- \nthis: is a frontmatter\n...\nThis is a text", "<p>This is a text</p>", "yaml", context: "Example 8\nSection Extensions / YAML frontmatter discard\n");
}
// It expects whitespace can exist after the trailing characters
@@ -207,8 +198,7 @@ namespace Markdig.Tests.Specs.Yaml
// Should be rendered as:
// <p>This is a text</p>
Console.WriteLine("Example 9\nSection Extensions / YAML frontmatter discard\n");
TestParser.TestSpec("---\nthis: is a frontmatter\n... \nThis is a text", "<p>This is a text</p>", "yaml");
TestParser.TestSpec("---\nthis: is a frontmatter\n... \nThis is a text", "<p>This is a text</p>", "yaml", context: "Example 9\nSection Extensions / YAML frontmatter discard\n");
}
}
}

View File

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

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

View File

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

View File

@@ -1,153 +1,152 @@
using NUnit.Framework;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
using System.Linq;
using System.Collections.Generic;
using Markdig.Helpers;
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(ArrayHelper<ListBlock>.Empty, literalInline.Descendants<ListBlock>());
Assert.AreSame(ArrayHelper<ParagraphBlock>.Empty, literalInline.Descendants<ParagraphBlock>());
Assert.AreSame(ArrayHelper<ContainerInline>.Empty, 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<LiteralInline>.Empty, containerInline.Descendants<LiteralInline>());
Assert.AreSame(ArrayHelper<LiteralInline>.Empty, containerInline.FindDescendants<LiteralInline>());
Assert.AreSame(ArrayHelper<LiteralInline>.Empty, (containerInline as MarkdownObject).Descendants<LiteralInline>());
}
Assert.AreSame(ArrayHelper<ListBlock>.Empty, containerInline.Descendants<ListBlock>());
Assert.AreSame(ArrayHelper<ParagraphBlock>.Empty, containerInline.Descendants<ParagraphBlock>());
}
foreach (ParagraphBlock paragraphBlock in syntaxTree.Descendants<ParagraphBlock>())
{
AssertIEnumerablesAreEqual(
(paragraphBlock as MarkdownObject).Descendants<LiteralInline>(),
paragraphBlock.Descendants<LiteralInline>());
Assert.AreSame(ArrayHelper<ParagraphBlock>.Empty, 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<LiteralInline>.Empty, containerBlock.Descendants<LiteralInline>());
Assert.AreSame(ArrayHelper<LiteralInline>.Empty, (containerBlock as Block).Descendants<LiteralInline>());
Assert.AreSame(ArrayHelper<LiteralInline>.Empty, (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;
}
}
}
}
}
}

View File

@@ -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>&quot;")]
[TestCase("\"\"foo\"", "&quot;<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>&quot;")]
[TestCase("\"\"foo\"", "&quot;<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>&amp;<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);
}
}
}

View File

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

View File

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

View File

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

View File

@@ -1,25 +1,25 @@
using NUnit.Framework;
using System.Text.RegularExpressions;
namespace Markdig.Tests
{
[TestFixture]
public class TestImageAltText
{
[Test]
[TestCase("![](image.jpg)", "")]
[TestCase("![foo](image.jpg)", "foo")]
[TestCase("![][1]\n\n[1]: image.jpg", "")]
[TestCase("![bar][1]\n\n[1]: image.jpg", "bar")]
[TestCase("![](image.jpg 'title')", "")]
[TestCase("![foo](image.jpg 'title')", "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("![](image.jpg)", "")]
[TestCase("![foo](image.jpg)", "foo")]
[TestCase("![][1]\n\n[1]: image.jpg", "")]
[TestCase("![bar][1]\n\n[1]: image.jpg", "bar")]
[TestCase("![](image.jpg 'title')", "")]
[TestCase("![foo](image.jpg 'title')", "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);
}
}
}

View File

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

View File

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

View File

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

View File

@@ -15,14 +15,22 @@ namespace Markdig.Tests
.Build();
}
private MarkdownPipeline GetPipelineWithBootstrap(MediaOptions options = null)
{
return new MarkdownPipelineBuilder()
.UseBootstrap()
.UseMediaLinks(options)
.Build();
}
[Test]
[TestCase("![static mp4](https://sample.com/video.mp4)", "<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"https://sample.com/video.mp4\"></source></video></p>\n")]
[TestCase("![static mp4](//sample.com/video.mp4)", "<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n")]
[TestCase(@"![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
[TestCase("![yandex.ru](https://music.yandex.ru/album/411845/track/4402274)", "<p><iframe src=\"https://music.yandex.ru/iframe/#track/4402274/411845/\" width=\"500\" height=\"281\" class=\"yandex\" frameborder=\"0\"></iframe></p>\n")]
[TestCase("![vimeo](https://vimeo.com/8607834)", "<p><iframe src=\"https://player.vimeo.com/video/8607834\" width=\"500\" height=\"281\" class=\"vimeo\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
[TestCase("![ok.ru](https://ok.ru/video/26870090463)", "<p><iframe src=\"https://ok.ru/videoembed/26870090463\" width=\"500\" height=\"281\" class=\"odnoklassniki\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
[TestCase("![ok.ru](//ok.ru/video/26870090463)", "<p><iframe src=\"https://ok.ru/videoembed/26870090463\" width=\"500\" height=\"281\" class=\"odnoklassniki\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
[TestCase(@"![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
[TestCase("![yandex.ru](https://music.yandex.ru/album/411845/track/4402274)", "<p><iframe src=\"https://music.yandex.ru/iframe/#track/4402274/411845/\" class=\"yandex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n")]
[TestCase("![vimeo](https://vimeo.com/8607834)", "<p><iframe src=\"https://player.vimeo.com/video/8607834\" class=\"vimeo\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
[TestCase("![ok.ru](https://ok.ru/video/26870090463)", "<p><iframe src=\"https://ok.ru/videoembed/26870090463\" class=\"odnoklassniki\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n")]
[TestCase("![ok.ru](//ok.ru/video/26870090463)", "<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("![p1](https://sample.com/video.mp4)", "<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("![p1](//sample.com/video.mp4)", "<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("![p1](https://sample.com/video.mp4)", "<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("![p1](https://sample.com/video.mp4)", "<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("![p1](//sample.com/video.mp4)", "<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("![p1](https://sample.com/video.mp4)", "<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("![static mp4](//sample.com/video.mp4)", "<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n", "")]
[TestCase(@"![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" width=\"500\" height=\"281\" class=\"youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n", "")]
[TestCase("![static mp4](//sample.com/video.mp4)", "<p><video width=\"500\" height=\"281\" controls=\"\" class=\"k\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n", "k")]
[TestCase(@"![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" width=\"500\" height=\"281\" class=\"k youtube\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n", "k")]
[TestCase(@"![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)", "<p><iframe src=\"https://www.youtube.com/embed/mswPy5bt3TQ\" class=\"youtube\" width=\"500\" height=\"281\" frameborder=\"0\" allowfullscreen=\"\"></iframe></p>\n", "")]
[TestCase("![static mp4](//sample.com/video.mp4)", "<p><video class=\"k\" width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n", "k")]
[TestCase(@"![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)", "<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("![static mp4](//sample.com/video.mp4)", "<p><video class=\"img-fluid\" width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n")]
[TestCase(@"![youtube.com](https://www.youtube.com/watch?v=mswPy5bt3TQ)", "<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);
}
}
}

View 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")));
}
}
}

View File

@@ -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)
{
@@ -457,18 +458,18 @@ This is a last line";
Assert.AreEqual(expected, actual);
}
public static void TestSpec(string inputText, string expectedOutputText, string extensions = null)
public static void TestSpec(string inputText, string expectedOutputText, string extensions = null, string context = null)
{
foreach (var pipeline in TestParser.GetPipeline(extensions))
{
AssertNormalize(inputText, expectedOutputText, trim: false, pipeline: pipeline.Value);
AssertNormalize(inputText, expectedOutputText, trim: false, pipeline: pipeline.Value, context: context);
}
}
public static void AssertNormalizeNoTrim(string input, string expected = null, NormalizeOptions options = null)
=> AssertNormalize(input, expected, false, options);
public static void AssertNormalize(string input, string expected = null, bool trim = true, NormalizeOptions options = null, MarkdownPipeline pipeline = null)
public static void AssertNormalize(string input, string expected = null, bool trim = true, NormalizeOptions options = null, MarkdownPipeline pipeline = null, string context = null)
{
expected = expected ?? input;
input = NormText(input, trim);
@@ -483,7 +484,7 @@ This is a last line";
var result = Markdown.Normalize(input, options, pipeline: pipeline);
result = NormText(result, trim);
TestParser.PrintAssertExpected(input, result, expected);
TestParser.PrintAssertExpected(input, result, expected, context);
}
private static string NormText(string text, bool trim)

View File

@@ -1,190 +1,191 @@
// 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, string context = null)
{
context ??= string.Empty;
if (!string.IsNullOrEmpty(context))
{
context += "\n";
}
foreach (var pipeline in GetPipeline(extensions))
{
TestSpec(inputText, expectedOutputText, pipeline.Value, plainText, context: context + $"Pipeline configured with extensions: {pipeline.Key}");
}
}
public static void TestSpec(string inputText, string expectedOutputText, MarkdownPipeline pipeline, bool plainText = false, string context = null)
{
// 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, context);
}
public static void PrintAssertExpected(string source, string result, string expected, string context = null)
{
if (expected != result)
{
if (context != null)
{
Console.WriteLine(context);
}
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>("default-trivia", new MarkdownPipelineBuilder().EnableTrackTrivia().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";
}
}
}
}

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

View File

@@ -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&lt;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, string context = null)
{
TestParser.TestSpec(markdownText, expected, extensions, plainText: true, context: context);
}
}
}

View File

@@ -12,6 +12,22 @@ 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 TestLinksWithTitleAndCarriageReturn()
{
var text = "[Link 1][link-1], [link 2][link-2].\r\n\r\n[link-1]: https://example.com \"title 1\" \r\n[link-2]: https://example.com \"title 2\"";
var result = Markdown.ToHtml(text).TrimEnd();
Assert.AreEqual("<p><a href=\"https://example.com\" title=\"title 1\">Link 1</a>, <a href=\"https://example.com\" title=\"title 2\">link 2</a>.</p>", result);
}
[Test]
public void TestLink()
{
@@ -39,7 +55,6 @@ namespace Markdig.Tests
Later in a text we are using HTML and it becomes an abbr tag HTML
";
// var reader = new StringReader(@"> > toto tata
//> titi toto
//");
@@ -47,7 +62,7 @@ Later in a text we are using HTML and it becomes an abbr tag HTML
//var result = Markdown.ToHtml(text, new MarkdownPipeline().UseFootnotes().UseEmphasisExtras());
var result = Markdown.ToHtml(text, new MarkdownPipelineBuilder().UseAbbreviations().Build());
//File.WriteAllText("test.html", result, Encoding.UTF8);
Console.WriteLine(result);
//Console.WriteLine(result);
}
[Test]

View File

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

View 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}\""));
}
}
}

View 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, string context = null)
{
RoundTrip(markdownText, context);
}
internal static void RoundTrip(string markdown, string context = null)
{
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();
TestParser.PrintAssertExpected("", result, markdown, context);
}
}
}

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More