all repos — grayfriday @ 8e90e8b6455f1608d6a0948d0eb07409bcf874d4

blackfriday fork with a few changes

block_test.go (view raw)

   1//
   2// Blackfriday Markdown Processor
   3// Available at http://github.com/russross/blackfriday
   4//
   5// Copyright © 2011 Russ Ross <russ@russross.com>.
   6// Distributed under the Simplified BSD License.
   7// See README.md for details.
   8//
   9
  10//
  11// Unit tests for block parsing
  12//
  13
  14package blackfriday
  15
  16import (
  17	"strings"
  18	"testing"
  19)
  20
  21func runMarkdownBlockWithRenderer(input string, extensions Extensions, renderer Renderer) string {
  22	return string(Markdown([]byte(input), renderer, extensions))
  23}
  24
  25func runMarkdownBlock(input string, extensions Extensions) string {
  26	renderer := HtmlRenderer(UseXHTML, "", "")
  27	return runMarkdownBlockWithRenderer(input, extensions, renderer)
  28}
  29
  30func runnerWithRendererParameters(parameters HtmlRendererParameters) func(string, Extensions) string {
  31	return func(input string, extensions Extensions) string {
  32		renderer := HtmlRendererWithParameters(UseXHTML, "", "", parameters)
  33		return runMarkdownBlockWithRenderer(input, extensions, renderer)
  34	}
  35}
  36
  37func doTestsBlock(t *testing.T, tests []string, extensions Extensions) {
  38	doTestsBlockWithRunner(t, tests, extensions, runMarkdownBlock)
  39}
  40
  41func doTestsBlockWithRunner(t *testing.T, tests []string, extensions Extensions, runner func(string, Extensions) string) {
  42	// catch and report panics
  43	var candidate string
  44	defer func() {
  45		if err := recover(); err != nil {
  46			t.Errorf("\npanic while processing [%#v]: %s\n", candidate, err)
  47		}
  48	}()
  49
  50	for i := 0; i+1 < len(tests); i += 2 {
  51		input := tests[i]
  52		candidate = input
  53		expected := tests[i+1]
  54		actual := runner(candidate, extensions)
  55		if actual != expected {
  56			t.Errorf("\nInput   [%#v]\nExpected[%#v]\nActual  [%#v]",
  57				candidate, expected, actual)
  58		}
  59
  60		// now test every substring to stress test bounds checking
  61		if !testing.Short() {
  62			for start := 0; start < len(input); start++ {
  63				for end := start + 1; end <= len(input); end++ {
  64					candidate = input[start:end]
  65					_ = runMarkdownBlock(candidate, extensions)
  66				}
  67			}
  68		}
  69	}
  70}
  71
  72func TestPrefixHeaderNoExtensions(t *testing.T) {
  73	var tests = []string{
  74		"# Header 1\n",
  75		"<h1>Header 1</h1>\n",
  76
  77		"## Header 2\n",
  78		"<h2>Header 2</h2>\n",
  79
  80		"### Header 3\n",
  81		"<h3>Header 3</h3>\n",
  82
  83		"#### Header 4\n",
  84		"<h4>Header 4</h4>\n",
  85
  86		"##### Header 5\n",
  87		"<h5>Header 5</h5>\n",
  88
  89		"###### Header 6\n",
  90		"<h6>Header 6</h6>\n",
  91
  92		"####### Header 7\n",
  93		"<h6># Header 7</h6>\n",
  94
  95		"#Header 1\n",
  96		"<h1>Header 1</h1>\n",
  97
  98		"##Header 2\n",
  99		"<h2>Header 2</h2>\n",
 100
 101		"###Header 3\n",
 102		"<h3>Header 3</h3>\n",
 103
 104		"####Header 4\n",
 105		"<h4>Header 4</h4>\n",
 106
 107		"#####Header 5\n",
 108		"<h5>Header 5</h5>\n",
 109
 110		"######Header 6\n",
 111		"<h6>Header 6</h6>\n",
 112
 113		"#######Header 7\n",
 114		"<h6>#Header 7</h6>\n",
 115
 116		"Hello\n# Header 1\nGoodbye\n",
 117		"<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
 118
 119		"* List\n# Header\n* List\n",
 120		"<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 121
 122		"* List\n#Header\n* List\n",
 123		"<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 124
 125		"*   List\n    * Nested list\n    # Nested header\n",
 126		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 127			"<h1>Nested header</h1></li>\n</ul></li>\n</ul>\n",
 128
 129		"#Header 1 \\#\n",
 130		"<h1>Header 1 #</h1>\n",
 131
 132		"#Header 1 \\# foo\n",
 133		"<h1>Header 1 # foo</h1>\n",
 134
 135		"#Header 1 #\\##\n",
 136		"<h1>Header 1 ##</h1>\n",
 137	}
 138	doTestsBlock(t, tests, 0)
 139}
 140
 141func TestPrefixHeaderSpaceExtension(t *testing.T) {
 142	var tests = []string{
 143		"# Header 1\n",
 144		"<h1>Header 1</h1>\n",
 145
 146		"## Header 2\n",
 147		"<h2>Header 2</h2>\n",
 148
 149		"### Header 3\n",
 150		"<h3>Header 3</h3>\n",
 151
 152		"#### Header 4\n",
 153		"<h4>Header 4</h4>\n",
 154
 155		"##### Header 5\n",
 156		"<h5>Header 5</h5>\n",
 157
 158		"###### Header 6\n",
 159		"<h6>Header 6</h6>\n",
 160
 161		"####### Header 7\n",
 162		"<p>####### Header 7</p>\n",
 163
 164		"#Header 1\n",
 165		"<p>#Header 1</p>\n",
 166
 167		"##Header 2\n",
 168		"<p>##Header 2</p>\n",
 169
 170		"###Header 3\n",
 171		"<p>###Header 3</p>\n",
 172
 173		"####Header 4\n",
 174		"<p>####Header 4</p>\n",
 175
 176		"#####Header 5\n",
 177		"<p>#####Header 5</p>\n",
 178
 179		"######Header 6\n",
 180		"<p>######Header 6</p>\n",
 181
 182		"#######Header 7\n",
 183		"<p>#######Header 7</p>\n",
 184
 185		"Hello\n# Header 1\nGoodbye\n",
 186		"<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
 187
 188		"* List\n# Header\n* List\n",
 189		"<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 190
 191		"* List\n#Header\n* List\n",
 192		"<ul>\n<li>List\n#Header</li>\n<li>List</li>\n</ul>\n",
 193
 194		"*   List\n    * Nested list\n    # Nested header\n",
 195		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 196			"<h1>Nested header</h1></li>\n</ul></li>\n</ul>\n",
 197	}
 198	doTestsBlock(t, tests, SpaceHeaders)
 199}
 200
 201func TestPrefixHeaderIdExtension(t *testing.T) {
 202	var tests = []string{
 203		"# Header 1 {#someid}\n",
 204		"<h1 id=\"someid\">Header 1</h1>\n",
 205
 206		"# Header 1 {#someid}   \n",
 207		"<h1 id=\"someid\">Header 1</h1>\n",
 208
 209		"# Header 1         {#someid}\n",
 210		"<h1 id=\"someid\">Header 1</h1>\n",
 211
 212		"# Header 1 {#someid\n",
 213		"<h1>Header 1 {#someid</h1>\n",
 214
 215		"# Header 1 {#someid\n",
 216		"<h1>Header 1 {#someid</h1>\n",
 217
 218		"# Header 1 {#someid}}\n",
 219		"<h1 id=\"someid\">Header 1</h1>\n\n<p>}</p>\n",
 220
 221		"## Header 2 {#someid}\n",
 222		"<h2 id=\"someid\">Header 2</h2>\n",
 223
 224		"### Header 3 {#someid}\n",
 225		"<h3 id=\"someid\">Header 3</h3>\n",
 226
 227		"#### Header 4 {#someid}\n",
 228		"<h4 id=\"someid\">Header 4</h4>\n",
 229
 230		"##### Header 5 {#someid}\n",
 231		"<h5 id=\"someid\">Header 5</h5>\n",
 232
 233		"###### Header 6 {#someid}\n",
 234		"<h6 id=\"someid\">Header 6</h6>\n",
 235
 236		"####### Header 7 {#someid}\n",
 237		"<h6 id=\"someid\"># Header 7</h6>\n",
 238
 239		"# Header 1 # {#someid}\n",
 240		"<h1 id=\"someid\">Header 1</h1>\n",
 241
 242		"## Header 2 ## {#someid}\n",
 243		"<h2 id=\"someid\">Header 2</h2>\n",
 244
 245		"Hello\n# Header 1\nGoodbye\n",
 246		"<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
 247
 248		"* List\n# Header {#someid}\n* List\n",
 249		"<ul>\n<li><p>List</p>\n\n<h1 id=\"someid\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 250
 251		"* List\n#Header {#someid}\n* List\n",
 252		"<ul>\n<li><p>List</p>\n\n<h1 id=\"someid\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 253
 254		"*   List\n    * Nested list\n    # Nested header {#someid}\n",
 255		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 256			"<h1 id=\"someid\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
 257	}
 258	doTestsBlock(t, tests, HeaderIDs)
 259}
 260
 261func TestPrefixHeaderIdExtensionWithPrefixAndSuffix(t *testing.T) {
 262	var tests = []string{
 263		"# header 1 {#someid}\n",
 264		"<h1 id=\"PRE:someid:POST\">header 1</h1>\n",
 265
 266		"## header 2 {#someid}\n",
 267		"<h2 id=\"PRE:someid:POST\">header 2</h2>\n",
 268
 269		"### header 3 {#someid}\n",
 270		"<h3 id=\"PRE:someid:POST\">header 3</h3>\n",
 271
 272		"#### header 4 {#someid}\n",
 273		"<h4 id=\"PRE:someid:POST\">header 4</h4>\n",
 274
 275		"##### header 5 {#someid}\n",
 276		"<h5 id=\"PRE:someid:POST\">header 5</h5>\n",
 277
 278		"###### header 6 {#someid}\n",
 279		"<h6 id=\"PRE:someid:POST\">header 6</h6>\n",
 280
 281		"####### header 7 {#someid}\n",
 282		"<h6 id=\"PRE:someid:POST\"># header 7</h6>\n",
 283
 284		"# header 1 # {#someid}\n",
 285		"<h1 id=\"PRE:someid:POST\">header 1</h1>\n",
 286
 287		"## header 2 ## {#someid}\n",
 288		"<h2 id=\"PRE:someid:POST\">header 2</h2>\n",
 289
 290		"* List\n# Header {#someid}\n* List\n",
 291		"<ul>\n<li><p>List</p>\n\n<h1 id=\"PRE:someid:POST\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 292
 293		"* List\n#Header {#someid}\n* List\n",
 294		"<ul>\n<li><p>List</p>\n\n<h1 id=\"PRE:someid:POST\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 295
 296		"*   List\n    * Nested list\n    # Nested header {#someid}\n",
 297		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 298			"<h1 id=\"PRE:someid:POST\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
 299	}
 300
 301	parameters := HtmlRendererParameters{
 302		HeaderIDPrefix: "PRE:",
 303		HeaderIDSuffix: ":POST",
 304	}
 305
 306	doTestsBlockWithRunner(t, tests, HeaderIDs, runnerWithRendererParameters(parameters))
 307}
 308
 309func TestPrefixAutoHeaderIdExtension(t *testing.T) {
 310	var tests = []string{
 311		"# Header 1\n",
 312		"<h1 id=\"header-1\">Header 1</h1>\n",
 313
 314		"# Header 1   \n",
 315		"<h1 id=\"header-1\">Header 1</h1>\n",
 316
 317		"## Header 2\n",
 318		"<h2 id=\"header-2\">Header 2</h2>\n",
 319
 320		"### Header 3\n",
 321		"<h3 id=\"header-3\">Header 3</h3>\n",
 322
 323		"#### Header 4\n",
 324		"<h4 id=\"header-4\">Header 4</h4>\n",
 325
 326		"##### Header 5\n",
 327		"<h5 id=\"header-5\">Header 5</h5>\n",
 328
 329		"###### Header 6\n",
 330		"<h6 id=\"header-6\">Header 6</h6>\n",
 331
 332		"####### Header 7\n",
 333		"<h6 id=\"header-7\"># Header 7</h6>\n",
 334
 335		"Hello\n# Header 1\nGoodbye\n",
 336		"<p>Hello</p>\n\n<h1 id=\"header-1\">Header 1</h1>\n\n<p>Goodbye</p>\n",
 337
 338		"* List\n# Header\n* List\n",
 339		"<ul>\n<li><p>List</p>\n\n<h1 id=\"header\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 340
 341		"* List\n#Header\n* List\n",
 342		"<ul>\n<li><p>List</p>\n\n<h1 id=\"header\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 343
 344		"*   List\n    * Nested list\n    # Nested header\n",
 345		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 346			"<h1 id=\"nested-header\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
 347
 348		"# Header\n\n# Header\n",
 349		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n",
 350
 351		"# Header 1\n\n# Header 1",
 352		"<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
 353
 354		"# Header\n\n# Header 1\n\n# Header\n\n# Header",
 355		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header</h1>\n\n<h1 id=\"header-1-2\">Header</h1>\n",
 356	}
 357	doTestsBlock(t, tests, AutoHeaderIDs)
 358}
 359
 360func TestPrefixAutoHeaderIdExtensionWithPrefixAndSuffix(t *testing.T) {
 361	var tests = []string{
 362		"# Header 1\n",
 363		"<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n",
 364
 365		"# Header 1   \n",
 366		"<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n",
 367
 368		"## Header 2\n",
 369		"<h2 id=\"PRE:header-2:POST\">Header 2</h2>\n",
 370
 371		"### Header 3\n",
 372		"<h3 id=\"PRE:header-3:POST\">Header 3</h3>\n",
 373
 374		"#### Header 4\n",
 375		"<h4 id=\"PRE:header-4:POST\">Header 4</h4>\n",
 376
 377		"##### Header 5\n",
 378		"<h5 id=\"PRE:header-5:POST\">Header 5</h5>\n",
 379
 380		"###### Header 6\n",
 381		"<h6 id=\"PRE:header-6:POST\">Header 6</h6>\n",
 382
 383		"####### Header 7\n",
 384		"<h6 id=\"PRE:header-7:POST\"># Header 7</h6>\n",
 385
 386		"Hello\n# Header 1\nGoodbye\n",
 387		"<p>Hello</p>\n\n<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<p>Goodbye</p>\n",
 388
 389		"* List\n# Header\n* List\n",
 390		"<ul>\n<li><p>List</p>\n\n<h1 id=\"PRE:header:POST\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 391
 392		"* List\n#Header\n* List\n",
 393		"<ul>\n<li><p>List</p>\n\n<h1 id=\"PRE:header:POST\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 394
 395		"*   List\n    * Nested list\n    # Nested header\n",
 396		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 397			"<h1 id=\"PRE:nested-header:POST\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
 398
 399		"# Header\n\n# Header\n",
 400		"<h1 id=\"PRE:header:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1:POST\">Header</h1>\n",
 401
 402		"# Header 1\n\n# Header 1",
 403		"<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<h1 id=\"PRE:header-1-1:POST\">Header 1</h1>\n",
 404
 405		"# Header\n\n# Header 1\n\n# Header\n\n# Header",
 406		"<h1 id=\"PRE:header:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<h1 id=\"PRE:header-1-1:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1-2:POST\">Header</h1>\n",
 407	}
 408
 409	parameters := HtmlRendererParameters{
 410		HeaderIDPrefix: "PRE:",
 411		HeaderIDSuffix: ":POST",
 412	}
 413
 414	doTestsBlockWithRunner(t, tests, AutoHeaderIDs, runnerWithRendererParameters(parameters))
 415}
 416
 417func TestPrefixMultipleHeaderExtensions(t *testing.T) {
 418	var tests = []string{
 419		"# Header\n\n# Header {#header}\n\n# Header 1",
 420		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
 421	}
 422	doTestsBlock(t, tests, AutoHeaderIDs|HeaderIDs)
 423}
 424
 425func TestUnderlineHeaders(t *testing.T) {
 426	var tests = []string{
 427		"Header 1\n========\n",
 428		"<h1>Header 1</h1>\n",
 429
 430		"Header 2\n--------\n",
 431		"<h2>Header 2</h2>\n",
 432
 433		"A\n=\n",
 434		"<h1>A</h1>\n",
 435
 436		"B\n-\n",
 437		"<h2>B</h2>\n",
 438
 439		"Paragraph\nHeader\n=\n",
 440		"<p>Paragraph</p>\n\n<h1>Header</h1>\n",
 441
 442		"Header\n===\nParagraph\n",
 443		"<h1>Header</h1>\n\n<p>Paragraph</p>\n",
 444
 445		"Header\n===\nAnother header\n---\n",
 446		"<h1>Header</h1>\n\n<h2>Another header</h2>\n",
 447
 448		"   Header\n======\n",
 449		"<h1>Header</h1>\n",
 450
 451		"    Code\n========\n",
 452		"<pre><code>Code\n</code></pre>\n\n<p>========</p>\n",
 453
 454		"Header with *inline*\n=====\n",
 455		"<h1>Header with <em>inline</em></h1>\n",
 456
 457		"*   List\n    * Sublist\n    Not a header\n    ------\n",
 458		"<ul>\n<li>List\n\n<ul>\n<li>Sublist\nNot a header\n------</li>\n</ul></li>\n</ul>\n",
 459
 460		"Paragraph\n\n\n\n\nHeader\n===\n",
 461		"<p>Paragraph</p>\n\n<h1>Header</h1>\n",
 462
 463		"Trailing space \n====        \n\n",
 464		"<h1>Trailing space</h1>\n",
 465
 466		"Trailing spaces\n====        \n\n",
 467		"<h1>Trailing spaces</h1>\n",
 468
 469		"Double underline\n=====\n=====\n",
 470		"<h1>Double underline</h1>\n\n<p>=====</p>\n",
 471	}
 472	doTestsBlock(t, tests, 0)
 473}
 474
 475func TestUnderlineHeadersAutoIDs(t *testing.T) {
 476	var tests = []string{
 477		"Header 1\n========\n",
 478		"<h1 id=\"header-1\">Header 1</h1>\n",
 479
 480		"Header 2\n--------\n",
 481		"<h2 id=\"header-2\">Header 2</h2>\n",
 482
 483		"A\n=\n",
 484		"<h1 id=\"a\">A</h1>\n",
 485
 486		"B\n-\n",
 487		"<h2 id=\"b\">B</h2>\n",
 488
 489		"Paragraph\nHeader\n=\n",
 490		"<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
 491
 492		"Header\n===\nParagraph\n",
 493		"<h1 id=\"header\">Header</h1>\n\n<p>Paragraph</p>\n",
 494
 495		"Header\n===\nAnother header\n---\n",
 496		"<h1 id=\"header\">Header</h1>\n\n<h2 id=\"another-header\">Another header</h2>\n",
 497
 498		"   Header\n======\n",
 499		"<h1 id=\"header\">Header</h1>\n",
 500
 501		"Header with *inline*\n=====\n",
 502		"<h1 id=\"header-with-inline\">Header with <em>inline</em></h1>\n",
 503
 504		"Paragraph\n\n\n\n\nHeader\n===\n",
 505		"<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
 506
 507		"Trailing space \n====        \n\n",
 508		"<h1 id=\"trailing-space\">Trailing space</h1>\n",
 509
 510		"Trailing spaces\n====        \n\n",
 511		"<h1 id=\"trailing-spaces\">Trailing spaces</h1>\n",
 512
 513		"Double underline\n=====\n=====\n",
 514		"<h1 id=\"double-underline\">Double underline</h1>\n\n<p>=====</p>\n",
 515
 516		"Header\n======\n\nHeader\n======\n",
 517		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n",
 518
 519		"Header 1\n========\n\nHeader 1\n========\n",
 520		"<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
 521	}
 522	doTestsBlock(t, tests, AutoHeaderIDs)
 523}
 524
 525func TestHorizontalRule(t *testing.T) {
 526	var tests = []string{
 527		"-\n",
 528		"<p>-</p>\n",
 529
 530		"--\n",
 531		"<p>--</p>\n",
 532
 533		"---\n",
 534		"<hr />\n",
 535
 536		"----\n",
 537		"<hr />\n",
 538
 539		"*\n",
 540		"<p>*</p>\n",
 541
 542		"**\n",
 543		"<p>**</p>\n",
 544
 545		"***\n",
 546		"<hr />\n",
 547
 548		"****\n",
 549		"<hr />\n",
 550
 551		"_\n",
 552		"<p>_</p>\n",
 553
 554		"__\n",
 555		"<p>__</p>\n",
 556
 557		"___\n",
 558		"<hr />\n",
 559
 560		"____\n",
 561		"<hr />\n",
 562
 563		"-*-\n",
 564		"<p>-*-</p>\n",
 565
 566		"- - -\n",
 567		"<hr />\n",
 568
 569		"* * *\n",
 570		"<hr />\n",
 571
 572		"_ _ _\n",
 573		"<hr />\n",
 574
 575		"-----*\n",
 576		"<p>-----*</p>\n",
 577
 578		"   ------   \n",
 579		"<hr />\n",
 580
 581		"Hello\n***\n",
 582		"<p>Hello</p>\n\n<hr />\n",
 583
 584		"---\n***\n___\n",
 585		"<hr />\n\n<hr />\n\n<hr />\n",
 586	}
 587	doTestsBlock(t, tests, 0)
 588}
 589
 590func TestUnorderedList(t *testing.T) {
 591	var tests = []string{
 592		"* Hello\n",
 593		"<ul>\n<li>Hello</li>\n</ul>\n",
 594
 595		"* Yin\n* Yang\n",
 596		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 597
 598		"* Ting\n* Bong\n* Goo\n",
 599		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 600
 601		"* Yin\n\n* Yang\n",
 602		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 603
 604		"* Ting\n\n* Bong\n* Goo\n",
 605		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 606
 607		"+ Hello\n",
 608		"<ul>\n<li>Hello</li>\n</ul>\n",
 609
 610		"+ Yin\n+ Yang\n",
 611		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 612
 613		"+ Ting\n+ Bong\n+ Goo\n",
 614		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 615
 616		"+ Yin\n\n+ Yang\n",
 617		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 618
 619		"+ Ting\n\n+ Bong\n+ Goo\n",
 620		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 621
 622		"- Hello\n",
 623		"<ul>\n<li>Hello</li>\n</ul>\n",
 624
 625		"- Yin\n- Yang\n",
 626		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 627
 628		"- Ting\n- Bong\n- Goo\n",
 629		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 630
 631		"- Yin\n\n- Yang\n",
 632		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 633
 634		"- Ting\n\n- Bong\n- Goo\n",
 635		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 636
 637		"*Hello\n",
 638		"<p>*Hello</p>\n",
 639
 640		"*   Hello \n",
 641		"<ul>\n<li>Hello</li>\n</ul>\n",
 642
 643		"*   Hello \n    Next line \n",
 644		"<ul>\n<li>Hello\nNext line</li>\n</ul>\n",
 645
 646		"Paragraph\n* No linebreak\n",
 647		"<p>Paragraph\n* No linebreak</p>\n",
 648
 649		"Paragraph\n\n* Linebreak\n",
 650		"<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n",
 651
 652		"*   List\n    * Nested list\n",
 653		"<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
 654
 655		"*   List\n\n    * Nested list\n",
 656		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
 657
 658		"*   List\n    Second line\n\n    + Nested\n",
 659		"<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n",
 660
 661		"*   List\n    + Nested\n\n    Continued\n",
 662		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n",
 663
 664		"*   List\n   * shallow indent\n",
 665		"<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n",
 666
 667		"* List\n" +
 668			" * shallow indent\n" +
 669			"  * part of second list\n" +
 670			"   * still second\n" +
 671			"    * almost there\n" +
 672			"     * third level\n",
 673		"<ul>\n" +
 674			"<li>List\n\n" +
 675			"<ul>\n" +
 676			"<li>shallow indent</li>\n" +
 677			"<li>part of second list</li>\n" +
 678			"<li>still second</li>\n" +
 679			"<li>almost there\n\n" +
 680			"<ul>\n" +
 681			"<li>third level</li>\n" +
 682			"</ul></li>\n" +
 683			"</ul></li>\n" +
 684			"</ul>\n",
 685
 686		"* List\n        extra indent, same paragraph\n",
 687		"<ul>\n<li>List\n    extra indent, same paragraph</li>\n</ul>\n",
 688
 689		"* List\n\n        code block\n",
 690		"<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n",
 691
 692		"* List\n\n          code block with spaces\n",
 693		"<ul>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ul>\n",
 694
 695		"* List\n\n    * sublist\n\n    normal text\n\n    * another sublist\n",
 696		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>sublist</li>\n</ul>\n\n<p>normal text</p>\n\n<ul>\n<li>another sublist</li>\n</ul></li>\n</ul>\n",
 697	}
 698	doTestsBlock(t, tests, 0)
 699}
 700
 701func TestOrderedList(t *testing.T) {
 702	var tests = []string{
 703		"1. Hello\n",
 704		"<ol>\n<li>Hello</li>\n</ol>\n",
 705
 706		"1. Yin\n2. Yang\n",
 707		"<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n",
 708
 709		"1. Ting\n2. Bong\n3. Goo\n",
 710		"<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n",
 711
 712		"1. Yin\n\n2. Yang\n",
 713		"<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n",
 714
 715		"1. Ting\n\n2. Bong\n3. Goo\n",
 716		"<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n",
 717
 718		"1 Hello\n",
 719		"<p>1 Hello</p>\n",
 720
 721		"1.Hello\n",
 722		"<p>1.Hello</p>\n",
 723
 724		"1.  Hello \n",
 725		"<ol>\n<li>Hello</li>\n</ol>\n",
 726
 727		"1.  Hello \n    Next line \n",
 728		"<ol>\n<li>Hello\nNext line</li>\n</ol>\n",
 729
 730		"Paragraph\n1. No linebreak\n",
 731		"<p>Paragraph\n1. No linebreak</p>\n",
 732
 733		"Paragraph\n\n1. Linebreak\n",
 734		"<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n",
 735
 736		"1.  List\n    1. Nested list\n",
 737		"<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
 738
 739		"1.  List\n\n    1. Nested list\n",
 740		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
 741
 742		"1.  List\n    Second line\n\n    1. Nested\n",
 743		"<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n",
 744
 745		"1.  List\n    1. Nested\n\n    Continued\n",
 746		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n",
 747
 748		"1.  List\n   1. shallow indent\n",
 749		"<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n",
 750
 751		"1. List\n" +
 752			" 1. shallow indent\n" +
 753			"  2. part of second list\n" +
 754			"   3. still second\n" +
 755			"    4. almost there\n" +
 756			"     1. third level\n",
 757		"<ol>\n" +
 758			"<li>List\n\n" +
 759			"<ol>\n" +
 760			"<li>shallow indent</li>\n" +
 761			"<li>part of second list</li>\n" +
 762			"<li>still second</li>\n" +
 763			"<li>almost there\n\n" +
 764			"<ol>\n" +
 765			"<li>third level</li>\n" +
 766			"</ol></li>\n" +
 767			"</ol></li>\n" +
 768			"</ol>\n",
 769
 770		"1. List\n        extra indent, same paragraph\n",
 771		"<ol>\n<li>List\n    extra indent, same paragraph</li>\n</ol>\n",
 772
 773		"1. List\n\n        code block\n",
 774		"<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n",
 775
 776		"1. List\n\n          code block with spaces\n",
 777		"<ol>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ol>\n",
 778
 779		"1. List\n    * Mixted list\n",
 780		"<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n",
 781
 782		"1. List\n * Mixed list\n",
 783		"<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n",
 784
 785		"* Start with unordered\n 1. Ordered\n",
 786		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
 787
 788		"* Start with unordered\n    1. Ordered\n",
 789		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
 790
 791		"1. numbers\n1. are ignored\n",
 792		"<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n",
 793	}
 794	doTestsBlock(t, tests, 0)
 795}
 796
 797func TestDefinitionList(t *testing.T) {
 798	var tests = []string{
 799		"Term 1\n:   Definition a\n",
 800		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 801
 802		"Term 1\n:   Definition a \n",
 803		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 804
 805		"Term 1\n:   Definition a\n:   Definition b\n",
 806		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n<dd>Definition b</dd>\n</dl>\n",
 807
 808		"Term 1\n:   Definition a\n\nTerm 2\n:   Definition b\n",
 809		"<dl>\n" +
 810			"<dt>Term 1</dt>\n" +
 811			"<dd>Definition a</dd>\n" +
 812			"<dt>Term 2</dt>\n" +
 813			"<dd>Definition b</dd>\n" +
 814			"</dl>\n",
 815
 816		"Term 1\n:   Definition a\n\nTerm 2\n:   Definition b\n\nTerm 3\n:   Definition c\n",
 817		"<dl>\n" +
 818			"<dt>Term 1</dt>\n" +
 819			"<dd>Definition a</dd>\n" +
 820			"<dt>Term 2</dt>\n" +
 821			"<dd>Definition b</dd>\n" +
 822			"<dt>Term 3</dt>\n" +
 823			"<dd>Definition c</dd>\n" +
 824			"</dl>\n",
 825
 826		"Term 1\n:   Definition a\n:   Definition b\n\nTerm 2\n:   Definition c\n",
 827		"<dl>\n" +
 828			"<dt>Term 1</dt>\n" +
 829			"<dd>Definition a</dd>\n" +
 830			"<dd>Definition b</dd>\n" +
 831			"<dt>Term 2</dt>\n" +
 832			"<dd>Definition c</dd>\n" +
 833			"</dl>\n",
 834
 835		"Term 1\n\n:   Definition a\n\nTerm 2\n\n:   Definition b\n",
 836		"<dl>\n" +
 837			"<dt>Term 1</dt>\n" +
 838			"<dd><p>Definition a</p></dd>\n" +
 839			"<dt>Term 2</dt>\n" +
 840			"<dd><p>Definition b</p></dd>\n" +
 841			"</dl>\n",
 842
 843		"Term 1\n\n:   Definition a\n\n:   Definition b\n\nTerm 2\n\n:   Definition c\n",
 844		"<dl>\n" +
 845			"<dt>Term 1</dt>\n" +
 846			"<dd><p>Definition a</p></dd>\n" +
 847			"<dd><p>Definition b</p></dd>\n" +
 848			"<dt>Term 2</dt>\n" +
 849			"<dd><p>Definition c</p></dd>\n" +
 850			"</dl>\n",
 851
 852		"Term 1\n:   Definition a\nNext line\n",
 853		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 854
 855		"Term 1\n:   Definition a\n  Next line\n",
 856		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 857
 858		"Term 1\n:   Definition a \n  Next line \n",
 859		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 860
 861		"Term 1\n:   Definition a\nNext line\n\nTerm 2\n:   Definition b",
 862		"<dl>\n" +
 863			"<dt>Term 1</dt>\n" +
 864			"<dd>Definition a\nNext line</dd>\n" +
 865			"<dt>Term 2</dt>\n" +
 866			"<dd>Definition b</dd>\n" +
 867			"</dl>\n",
 868
 869		"Term 1\n: Definition a\n",
 870		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 871
 872		"Term 1\n:Definition a\n",
 873		"<p>Term 1\n:Definition a</p>\n",
 874
 875		"Term 1\n\n:   Definition a\n\nTerm 2\n\n:   Definition b\n\nText 1",
 876		"<dl>\n" +
 877			"<dt>Term 1</dt>\n" +
 878			"<dd><p>Definition a</p></dd>\n" +
 879			"<dt>Term 2</dt>\n" +
 880			"<dd><p>Definition b</p></dd>\n" +
 881			"</dl>\n" +
 882			"\n<p>Text 1</p>\n",
 883
 884		"Term 1\n\n:   Definition a\n\nText 1\n\nTerm 2\n\n:   Definition b\n\nText 2",
 885		"<dl>\n" +
 886			"<dt>Term 1</dt>\n" +
 887			"<dd><p>Definition a</p></dd>\n" +
 888			"</dl>\n" +
 889			"\n<p>Text 1</p>\n" +
 890			"\n<dl>\n" +
 891			"<dt>Term 2</dt>\n" +
 892			"<dd><p>Definition b</p></dd>\n" +
 893			"</dl>\n" +
 894			"\n<p>Text 2</p>\n",
 895	}
 896	doTestsBlock(t, tests, DefinitionLists)
 897}
 898
 899func TestPreformattedHtml(t *testing.T) {
 900	var tests = []string{
 901		"<div></div>\n",
 902		"<div></div>\n",
 903
 904		"<div>\n</div>\n",
 905		"<div>\n</div>\n",
 906
 907		"<div>\n</div>\nParagraph\n",
 908		"<p><div>\n</div>\nParagraph</p>\n",
 909
 910		"<div class=\"foo\">\n</div>\n",
 911		"<div class=\"foo\">\n</div>\n",
 912
 913		"<div>\nAnything here\n</div>\n",
 914		"<div>\nAnything here\n</div>\n",
 915
 916		"<div>\n  Anything here\n</div>\n",
 917		"<div>\n  Anything here\n</div>\n",
 918
 919		"<div>\nAnything here\n  </div>\n",
 920		"<div>\nAnything here\n  </div>\n",
 921
 922		"<div>\nThis is *not* &proceessed\n</div>\n",
 923		"<div>\nThis is *not* &proceessed\n</div>\n",
 924
 925		"<faketag>\n  Something\n</faketag>\n",
 926		"<p><faketag>\n  Something\n</faketag></p>\n",
 927
 928		"<div>\n  Something here\n</divv>\n",
 929		"<p><div>\n  Something here\n</divv></p>\n",
 930
 931		"Paragraph\n<div>\nHere? >&<\n</div>\n",
 932		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div></p>\n",
 933
 934		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n",
 935		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n",
 936
 937		"Paragraph\n<div>\nHere? >&<\n</div>\nAnd here?\n",
 938		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div>\nAnd here?</p>\n",
 939
 940		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\nAnd here?\n",
 941		"<p>Paragraph</p>\n\n<p><div>\nHow about here? &gt;&amp;&lt;\n</div>\nAnd here?</p>\n",
 942
 943		"Paragraph\n<div>\nHere? >&<\n</div>\n\nAnd here?\n",
 944		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div></p>\n\n<p>And here?</p>\n",
 945
 946		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n\nAnd here?\n",
 947		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
 948	}
 949	doTestsBlock(t, tests, 0)
 950}
 951
 952func TestPreformattedHtmlLax(t *testing.T) {
 953	var tests = []string{
 954		"Paragraph\n<div>\nHere? >&<\n</div>\n",
 955		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n",
 956
 957		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n",
 958		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n",
 959
 960		"Paragraph\n<div>\nHere? >&<\n</div>\nAnd here?\n",
 961		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n\n<p>And here?</p>\n",
 962
 963		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\nAnd here?\n",
 964		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
 965
 966		"Paragraph\n<div>\nHere? >&<\n</div>\n\nAnd here?\n",
 967		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n\n<p>And here?</p>\n",
 968
 969		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n\nAnd here?\n",
 970		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
 971	}
 972	doTestsBlock(t, tests, LaxHTMLBlocks)
 973}
 974
 975func TestFencedCodeBlock(t *testing.T) {
 976	var tests = []string{
 977		"``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n",
 978		"<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
 979
 980		"``` c\n/* special & char < > \" escaping */\n```\n",
 981		"<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",
 982
 983		"``` c\nno *inline* processing ~~of text~~\n```\n",
 984		"<pre><code class=\"language-c\">no *inline* processing ~~of text~~\n</code></pre>\n",
 985
 986		"```\nNo language\n```\n",
 987		"<pre><code>No language\n</code></pre>\n",
 988
 989		"``` {ocaml}\nlanguage in braces\n```\n",
 990		"<pre><code class=\"language-ocaml\">language in braces\n</code></pre>\n",
 991
 992		"```    {ocaml}      \nwith extra whitespace\n```\n",
 993		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
 994
 995		"```{   ocaml   }\nwith extra whitespace\n```\n",
 996		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
 997
 998		"~ ~~ java\nWith whitespace\n~~~\n",
 999		"<p>~ ~~ java\nWith whitespace\n~~~</p>\n",
1000
1001		"~~\nonly two\n~~\n",
1002		"<p>~~\nonly two\n~~</p>\n",
1003
1004		"```` python\nextra\n````\n",
1005		"<pre><code class=\"language-python\">extra\n</code></pre>\n",
1006
1007		"~~~ perl\nthree to start, four to end\n~~~~\n",
1008		"<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n",
1009
1010		"~~~~ perl\nfour to start, three to end\n~~~\n",
1011		"<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n",
1012
1013		"~~~ bash\ntildes\n~~~\n",
1014		"<pre><code class=\"language-bash\">tildes\n</code></pre>\n",
1015
1016		"``` lisp\nno ending\n",
1017		"<p>``` lisp\nno ending</p>\n",
1018
1019		"~~~ lisp\nend with language\n~~~ lisp\n",
1020		"<p>~~~ lisp\nend with language\n~~~ lisp</p>\n",
1021
1022		"```\nmismatched begin and end\n~~~\n",
1023		"<p>```\nmismatched begin and end\n~~~</p>\n",
1024
1025		"~~~\nmismatched begin and end\n```\n",
1026		"<p>~~~\nmismatched begin and end\n```</p>\n",
1027
1028		"   ``` oz\nleading spaces\n```\n",
1029		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1030
1031		"  ``` oz\nleading spaces\n ```\n",
1032		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1033
1034		" ``` oz\nleading spaces\n  ```\n",
1035		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1036
1037		"``` oz\nleading spaces\n   ```\n",
1038		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1039
1040		"    ``` oz\nleading spaces\n    ```\n",
1041		"<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces\n    ```</p>\n",
1042
1043		"Bla bla\n\n``` oz\ncode blocks breakup paragraphs\n```\n\nBla Bla\n",
1044		"<p>Bla bla</p>\n\n<pre><code class=\"language-oz\">code blocks breakup paragraphs\n</code></pre>\n\n<p>Bla Bla</p>\n",
1045
1046		"Some text before a fenced code block\n``` oz\ncode blocks breakup paragraphs\n```\nAnd some text after a fenced code block",
1047		"<p>Some text before a fenced code block</p>\n\n<pre><code class=\"language-oz\">code blocks breakup paragraphs\n</code></pre>\n\n<p>And some text after a fenced code block</p>\n",
1048
1049		"`",
1050		"<p>`</p>\n",
1051
1052		"Bla bla\n\n``` oz\ncode blocks breakup paragraphs\n```\n\nBla Bla\n\n``` oz\nmultiple code blocks work okay\n```\n\nBla Bla\n",
1053		"<p>Bla bla</p>\n\n<pre><code class=\"language-oz\">code blocks breakup paragraphs\n</code></pre>\n\n<p>Bla Bla</p>\n\n<pre><code class=\"language-oz\">multiple code blocks work okay\n</code></pre>\n\n<p>Bla Bla</p>\n",
1054
1055		"Some text before a fenced code block\n``` oz\ncode blocks breakup paragraphs\n```\nSome text in between\n``` oz\nmultiple code blocks work okay\n```\nAnd some text after a fenced code block",
1056		"<p>Some text before a fenced code block</p>\n\n<pre><code class=\"language-oz\">code blocks breakup paragraphs\n</code></pre>\n\n<p>Some text in between</p>\n\n<pre><code class=\"language-oz\">multiple code blocks work okay\n</code></pre>\n\n<p>And some text after a fenced code block</p>\n",
1057	}
1058	doTestsBlock(t, tests, FencedCode)
1059}
1060
1061func TestFencedCodeInsideBlockquotes(t *testing.T) {
1062	cat := func(s ...string) string { return strings.Join(s, "\n") }
1063	var tests = []string{
1064		cat("> ```go",
1065			"package moo",
1066			"",
1067			"```",
1068			""),
1069		`<blockquote>
1070<pre><code class="language-go">package moo
1071
1072</code></pre>
1073</blockquote>
1074`,
1075		// -------------------------------------------
1076		cat("> foo",
1077			"> ",
1078			"> ```go",
1079			"package moo",
1080			"```",
1081			"> ",
1082			"> goo.",
1083			""),
1084		`<blockquote>
1085<p>foo</p>
1086
1087<pre><code class="language-go">package moo
1088</code></pre>
1089
1090<p>goo.</p>
1091</blockquote>
1092`,
1093		// -------------------------------------------
1094		cat("> foo",
1095			"> ",
1096			"> quote",
1097			"continues",
1098			"```",
1099			""),
1100		`<blockquote>
1101<p>foo</p>
1102
1103<p>quote
1104continues
1105` + "```" + `</p>
1106</blockquote>
1107`,
1108		// -------------------------------------------
1109		cat("> foo",
1110			"> ",
1111			"> ```go",
1112			"package moo",
1113			"```",
1114			"> ",
1115			"> goo.",
1116			"> ",
1117			"> ```go",
1118			"package zoo",
1119			"```",
1120			"> ",
1121			"> woo.",
1122			""),
1123		`<blockquote>
1124<p>foo</p>
1125
1126<pre><code class="language-go">package moo
1127</code></pre>
1128
1129<p>goo.</p>
1130
1131<pre><code class="language-go">package zoo
1132</code></pre>
1133
1134<p>woo.</p>
1135</blockquote>
1136`,
1137	}
1138
1139	// These 2 alternative forms of blockquoted fenced code blocks should produce same output.
1140	forms := [2]string{
1141		cat("> plain quoted text",
1142			"> ```fenced",
1143			"code",
1144			" with leading single space correctly preserved",
1145			"okay",
1146			"```",
1147			"> rest of quoted text"),
1148		cat("> plain quoted text",
1149			"> ```fenced",
1150			"> code",
1151			">  with leading single space correctly preserved",
1152			"> okay",
1153			"> ```",
1154			"> rest of quoted text"),
1155	}
1156	want := `<blockquote>
1157<p>plain quoted text</p>
1158
1159<pre><code class="language-fenced">code
1160 with leading single space correctly preserved
1161okay
1162</code></pre>
1163
1164<p>rest of quoted text</p>
1165</blockquote>
1166`
1167	tests = append(tests, forms[0], want)
1168	tests = append(tests, forms[1], want)
1169
1170	doTestsBlock(t, tests, FencedCode)
1171}
1172
1173func TestTable(t *testing.T) {
1174	var tests = []string{
1175		"a | b\n---|---\nc | d\n",
1176		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n\n" +
1177			"<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n",
1178
1179		"a | b\n---|--\nc | d\n",
1180		"<p>a | b\n---|--\nc | d</p>\n",
1181
1182		"|a|b|c|d|\n|----|----|----|---|\n|e|f|g|h|\n",
1183		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n<th>d</th>\n</tr>\n</thead>\n\n" +
1184			"<tbody>\n<tr>\n<td>e</td>\n<td>f</td>\n<td>g</td>\n<td>h</td>\n</tr>\n</tbody>\n</table>\n",
1185
1186		"*a*|__b__|[c](C)|d\n---|---|---|---\ne|f|g|h\n",
1187		"<table>\n<thead>\n<tr>\n<th><em>a</em></th>\n<th><strong>b</strong></th>\n<th><a href=\"C\">c</a></th>\n<th>d</th>\n</tr>\n</thead>\n\n" +
1188			"<tbody>\n<tr>\n<td>e</td>\n<td>f</td>\n<td>g</td>\n<td>h</td>\n</tr>\n</tbody>\n</table>\n",
1189
1190		"a|b|c\n---|---|---\nd|e|f\ng|h\ni|j|k|l|m\nn|o|p\n",
1191		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n" +
1192			"<tbody>\n<tr>\n<td>d</td>\n<td>e</td>\n<td>f</td>\n</tr>\n\n" +
1193			"<tr>\n<td>g</td>\n<td>h</td>\n<td></td>\n</tr>\n\n" +
1194			"<tr>\n<td>i</td>\n<td>j</td>\n<td>k</td>\n</tr>\n\n" +
1195			"<tr>\n<td>n</td>\n<td>o</td>\n<td>p</td>\n</tr>\n</tbody>\n</table>\n",
1196
1197		"a|b|c\n---|---|---\n*d*|__e__|f\n",
1198		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n" +
1199			"<tbody>\n<tr>\n<td><em>d</em></td>\n<td><strong>e</strong></td>\n<td>f</td>\n</tr>\n</tbody>\n</table>\n",
1200
1201		"a|b|c|d\n:--|--:|:-:|---\ne|f|g|h\n",
1202		"<table>\n<thead>\n<tr>\n<th align=\"left\">a</th>\n<th align=\"right\">b</th>\n" +
1203			"<th align=\"center\">c</th>\n<th>d</th>\n</tr>\n</thead>\n\n" +
1204			"<tbody>\n<tr>\n<td align=\"left\">e</td>\n<td align=\"right\">f</td>\n" +
1205			"<td align=\"center\">g</td>\n<td>h</td>\n</tr>\n</tbody>\n</table>\n",
1206
1207		"a|b|c\n---|---|---\n",
1208		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n<tbody>\n</tbody>\n</table>\n",
1209
1210		"a| b|c | d | e\n---|---|---|---|---\nf| g|h | i |j\n",
1211		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n<th>d</th>\n<th>e</th>\n</tr>\n</thead>\n\n" +
1212			"<tbody>\n<tr>\n<td>f</td>\n<td>g</td>\n<td>h</td>\n<td>i</td>\n<td>j</td>\n</tr>\n</tbody>\n</table>\n",
1213
1214		"a|b\\|c|d\n---|---|---\nf|g\\|h|i\n",
1215		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b|c</th>\n<th>d</th>\n</tr>\n</thead>\n\n<tbody>\n<tr>\n<td>f</td>\n<td>g|h</td>\n<td>i</td>\n</tr>\n</tbody>\n</table>\n",
1216	}
1217	doTestsBlock(t, tests, Tables)
1218}
1219
1220func TestUnorderedListWith_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1221	var tests = []string{
1222		"* Hello\n",
1223		"<ul>\n<li>Hello</li>\n</ul>\n",
1224
1225		"* Yin\n* Yang\n",
1226		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1227
1228		"* Ting\n* Bong\n* Goo\n",
1229		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1230
1231		"* Yin\n\n* Yang\n",
1232		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1233
1234		"* Ting\n\n* Bong\n* Goo\n",
1235		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1236
1237		"+ Hello\n",
1238		"<ul>\n<li>Hello</li>\n</ul>\n",
1239
1240		"+ Yin\n+ Yang\n",
1241		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1242
1243		"+ Ting\n+ Bong\n+ Goo\n",
1244		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1245
1246		"+ Yin\n\n+ Yang\n",
1247		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1248
1249		"+ Ting\n\n+ Bong\n+ Goo\n",
1250		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1251
1252		"- Hello\n",
1253		"<ul>\n<li>Hello</li>\n</ul>\n",
1254
1255		"- Yin\n- Yang\n",
1256		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1257
1258		"- Ting\n- Bong\n- Goo\n",
1259		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1260
1261		"- Yin\n\n- Yang\n",
1262		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1263
1264		"- Ting\n\n- Bong\n- Goo\n",
1265		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1266
1267		"*Hello\n",
1268		"<p>*Hello</p>\n",
1269
1270		"*   Hello \n",
1271		"<ul>\n<li>Hello</li>\n</ul>\n",
1272
1273		"*   Hello \n    Next line \n",
1274		"<ul>\n<li>Hello\nNext line</li>\n</ul>\n",
1275
1276		"Paragraph\n* No linebreak\n",
1277		"<p>Paragraph</p>\n\n<ul>\n<li>No linebreak</li>\n</ul>\n",
1278
1279		"Paragraph\n\n* Linebreak\n",
1280		"<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n",
1281
1282		"*   List\n    * Nested list\n",
1283		"<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
1284
1285		"*   List\n\n    * Nested list\n",
1286		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
1287
1288		"*   List\n    Second line\n\n    + Nested\n",
1289		"<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n",
1290
1291		"*   List\n    + Nested\n\n    Continued\n",
1292		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n",
1293
1294		"*   List\n   * shallow indent\n",
1295		"<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n",
1296
1297		"* List\n" +
1298			" * shallow indent\n" +
1299			"  * part of second list\n" +
1300			"   * still second\n" +
1301			"    * almost there\n" +
1302			"     * third level\n",
1303		"<ul>\n" +
1304			"<li>List\n\n" +
1305			"<ul>\n" +
1306			"<li>shallow indent</li>\n" +
1307			"<li>part of second list</li>\n" +
1308			"<li>still second</li>\n" +
1309			"<li>almost there\n\n" +
1310			"<ul>\n" +
1311			"<li>third level</li>\n" +
1312			"</ul></li>\n" +
1313			"</ul></li>\n" +
1314			"</ul>\n",
1315
1316		"* List\n        extra indent, same paragraph\n",
1317		"<ul>\n<li>List\n    extra indent, same paragraph</li>\n</ul>\n",
1318
1319		"* List\n\n        code block\n",
1320		"<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n",
1321
1322		"* List\n\n          code block with spaces\n",
1323		"<ul>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ul>\n",
1324
1325		"* List\n\n    * sublist\n\n    normal text\n\n    * another sublist\n",
1326		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>sublist</li>\n</ul>\n\n<p>normal text</p>\n\n<ul>\n<li>another sublist</li>\n</ul></li>\n</ul>\n",
1327	}
1328	doTestsBlock(t, tests, NoEmptyLineBeforeBlock)
1329}
1330
1331func TestOrderedList_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1332	var tests = []string{
1333		"1. Hello\n",
1334		"<ol>\n<li>Hello</li>\n</ol>\n",
1335
1336		"1. Yin\n2. Yang\n",
1337		"<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n",
1338
1339		"1. Ting\n2. Bong\n3. Goo\n",
1340		"<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n",
1341
1342		"1. Yin\n\n2. Yang\n",
1343		"<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n",
1344
1345		"1. Ting\n\n2. Bong\n3. Goo\n",
1346		"<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n",
1347
1348		"1 Hello\n",
1349		"<p>1 Hello</p>\n",
1350
1351		"1.Hello\n",
1352		"<p>1.Hello</p>\n",
1353
1354		"1.  Hello \n",
1355		"<ol>\n<li>Hello</li>\n</ol>\n",
1356
1357		"1.  Hello \n    Next line \n",
1358		"<ol>\n<li>Hello\nNext line</li>\n</ol>\n",
1359
1360		"Paragraph\n1. No linebreak\n",
1361		"<p>Paragraph</p>\n\n<ol>\n<li>No linebreak</li>\n</ol>\n",
1362
1363		"Paragraph\n\n1. Linebreak\n",
1364		"<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n",
1365
1366		"1.  List\n    1. Nested list\n",
1367		"<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
1368
1369		"1.  List\n\n    1. Nested list\n",
1370		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
1371
1372		"1.  List\n    Second line\n\n    1. Nested\n",
1373		"<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n",
1374
1375		"1.  List\n    1. Nested\n\n    Continued\n",
1376		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n",
1377
1378		"1.  List\n   1. shallow indent\n",
1379		"<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n",
1380
1381		"1. List\n" +
1382			" 1. shallow indent\n" +
1383			"  2. part of second list\n" +
1384			"   3. still second\n" +
1385			"    4. almost there\n" +
1386			"     1. third level\n",
1387		"<ol>\n" +
1388			"<li>List\n\n" +
1389			"<ol>\n" +
1390			"<li>shallow indent</li>\n" +
1391			"<li>part of second list</li>\n" +
1392			"<li>still second</li>\n" +
1393			"<li>almost there\n\n" +
1394			"<ol>\n" +
1395			"<li>third level</li>\n" +
1396			"</ol></li>\n" +
1397			"</ol></li>\n" +
1398			"</ol>\n",
1399
1400		"1. List\n        extra indent, same paragraph\n",
1401		"<ol>\n<li>List\n    extra indent, same paragraph</li>\n</ol>\n",
1402
1403		"1. List\n\n        code block\n",
1404		"<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n",
1405
1406		"1. List\n\n          code block with spaces\n",
1407		"<ol>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ol>\n",
1408
1409		"1. List\n    * Mixted list\n",
1410		"<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n",
1411
1412		"1. List\n * Mixed list\n",
1413		"<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n",
1414
1415		"* Start with unordered\n 1. Ordered\n",
1416		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
1417
1418		"* Start with unordered\n    1. Ordered\n",
1419		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
1420
1421		"1. numbers\n1. are ignored\n",
1422		"<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n",
1423	}
1424	doTestsBlock(t, tests, NoEmptyLineBeforeBlock)
1425}
1426
1427func TestFencedCodeBlock_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1428	var tests = []string{
1429		"``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n",
1430		"<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
1431
1432		"``` c\n/* special & char < > \" escaping */\n```\n",
1433		"<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",
1434
1435		"``` c\nno *inline* processing ~~of text~~\n```\n",
1436		"<pre><code class=\"language-c\">no *inline* processing ~~of text~~\n</code></pre>\n",
1437
1438		"```\nNo language\n```\n",
1439		"<pre><code>No language\n</code></pre>\n",
1440
1441		"``` {ocaml}\nlanguage in braces\n```\n",
1442		"<pre><code class=\"language-ocaml\">language in braces\n</code></pre>\n",
1443
1444		"```    {ocaml}      \nwith extra whitespace\n```\n",
1445		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
1446
1447		"```{   ocaml   }\nwith extra whitespace\n```\n",
1448		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
1449
1450		"~ ~~ java\nWith whitespace\n~~~\n",
1451		"<p>~ ~~ java\nWith whitespace\n~~~</p>\n",
1452
1453		"~~\nonly two\n~~\n",
1454		"<p>~~\nonly two\n~~</p>\n",
1455
1456		"```` python\nextra\n````\n",
1457		"<pre><code class=\"language-python\">extra\n</code></pre>\n",
1458
1459		"~~~ perl\nthree to start, four to end\n~~~~\n",
1460		"<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n",
1461
1462		"~~~~ perl\nfour to start, three to end\n~~~\n",
1463		"<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n",
1464
1465		"~~~ bash\ntildes\n~~~\n",
1466		"<pre><code class=\"language-bash\">tildes\n</code></pre>\n",
1467
1468		"``` lisp\nno ending\n",
1469		"<p>``` lisp\nno ending</p>\n",
1470
1471		"~~~ lisp\nend with language\n~~~ lisp\n",
1472		"<p>~~~ lisp\nend with language\n~~~ lisp</p>\n",
1473
1474		"```\nmismatched begin and end\n~~~\n",
1475		"<p>```\nmismatched begin and end\n~~~</p>\n",
1476
1477		"~~~\nmismatched begin and end\n```\n",
1478		"<p>~~~\nmismatched begin and end\n```</p>\n",
1479
1480		"   ``` oz\nleading spaces\n```\n",
1481		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1482
1483		"  ``` oz\nleading spaces\n ```\n",
1484		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1485
1486		" ``` oz\nleading spaces\n  ```\n",
1487		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1488
1489		"``` oz\nleading spaces\n   ```\n",
1490		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1491
1492		"    ``` oz\nleading spaces\n    ```\n",
1493		"<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces</p>\n\n<pre><code>```\n</code></pre>\n",
1494	}
1495	doTestsBlock(t, tests, FencedCode|NoEmptyLineBeforeBlock)
1496}
1497
1498func TestTitleBlock_EXTENSION_TITLEBLOCK(t *testing.T) {
1499	var tests = []string{
1500		"% Some title\n" +
1501			"% Another title line\n" +
1502			"% Yep, more here too\n",
1503		"<h1 class=\"title\">" +
1504			"Some title\n" +
1505			"Another title line\n" +
1506			"Yep, more here too\n" +
1507			"</h1>",
1508	}
1509	doTestsBlock(t, tests, Titleblock)
1510}
1511
1512func TestBlockComments(t *testing.T) {
1513	var tests = []string{
1514		"Some text\n\n<!-- comment -->\n",
1515		"<p>Some text</p>\n\n<!-- comment -->\n",
1516
1517		"Some text\n\n<!--\n\nmultiline\ncomment\n-->\n",
1518		"<p>Some text</p>\n\n<!--\n\nmultiline\ncomment\n-->\n",
1519
1520		"Some text\n\n<!--\n\n<div><p>Commented</p>\n<span>html</span></div>\n-->\n",
1521		"<p>Some text</p>\n\n<!--\n\n<div><p>Commented</p>\n<span>html</span></div>\n-->\n",
1522	}
1523	doTestsBlock(t, tests, 0)
1524}