all repos — grayfriday @ 6762cd3685caa542c3ea8637ceac38c403fb8b08

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 TestPrefixHeaderNoExtensions(t *testing.T) {
  22	var tests = []string{
  23		"# Header 1\n",
  24		"<h1>Header 1</h1>\n",
  25
  26		"## Header 2\n",
  27		"<h2>Header 2</h2>\n",
  28
  29		"### Header 3\n",
  30		"<h3>Header 3</h3>\n",
  31
  32		"#### Header 4\n",
  33		"<h4>Header 4</h4>\n",
  34
  35		"##### Header 5\n",
  36		"<h5>Header 5</h5>\n",
  37
  38		"###### Header 6\n",
  39		"<h6>Header 6</h6>\n",
  40
  41		"####### Header 7\n",
  42		"<h6># Header 7</h6>\n",
  43
  44		"#Header 1\n",
  45		"<h1>Header 1</h1>\n",
  46
  47		"##Header 2\n",
  48		"<h2>Header 2</h2>\n",
  49
  50		"###Header 3\n",
  51		"<h3>Header 3</h3>\n",
  52
  53		"####Header 4\n",
  54		"<h4>Header 4</h4>\n",
  55
  56		"#####Header 5\n",
  57		"<h5>Header 5</h5>\n",
  58
  59		"######Header 6\n",
  60		"<h6>Header 6</h6>\n",
  61
  62		"#######Header 7\n",
  63		"<h6>#Header 7</h6>\n",
  64
  65		"Hello\n# Header 1\nGoodbye\n",
  66		"<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
  67
  68		"* List\n# Header\n* List\n",
  69		"<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  70
  71		"* List\n#Header\n* List\n",
  72		"<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  73
  74		"*   List\n    * Nested list\n    # Nested header\n",
  75		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
  76			"<h1>Nested header</h1></li>\n</ul></li>\n</ul>\n",
  77
  78		"#Header 1 \\#\n",
  79		"<h1>Header 1 #</h1>\n",
  80
  81		"#Header 1 \\# foo\n",
  82		"<h1>Header 1 # foo</h1>\n",
  83
  84		"#Header 1 #\\##\n",
  85		"<h1>Header 1 ##</h1>\n",
  86	}
  87	doTestsBlock(t, tests, 0)
  88}
  89
  90func TestPrefixHeaderSpaceExtension(t *testing.T) {
  91	var tests = []string{
  92		"# Header 1\n",
  93		"<h1>Header 1</h1>\n",
  94
  95		"## Header 2\n",
  96		"<h2>Header 2</h2>\n",
  97
  98		"### Header 3\n",
  99		"<h3>Header 3</h3>\n",
 100
 101		"#### Header 4\n",
 102		"<h4>Header 4</h4>\n",
 103
 104		"##### Header 5\n",
 105		"<h5>Header 5</h5>\n",
 106
 107		"###### Header 6\n",
 108		"<h6>Header 6</h6>\n",
 109
 110		"####### Header 7\n",
 111		"<p>####### Header 7</p>\n",
 112
 113		"#Header 1\n",
 114		"<p>#Header 1</p>\n",
 115
 116		"##Header 2\n",
 117		"<p>##Header 2</p>\n",
 118
 119		"###Header 3\n",
 120		"<p>###Header 3</p>\n",
 121
 122		"####Header 4\n",
 123		"<p>####Header 4</p>\n",
 124
 125		"#####Header 5\n",
 126		"<p>#####Header 5</p>\n",
 127
 128		"######Header 6\n",
 129		"<p>######Header 6</p>\n",
 130
 131		"#######Header 7\n",
 132		"<p>#######Header 7</p>\n",
 133
 134		"Hello\n# Header 1\nGoodbye\n",
 135		"<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
 136
 137		"* List\n# Header\n* List\n",
 138		"<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 139
 140		"* List\n#Header\n* List\n",
 141		"<ul>\n<li>List\n#Header</li>\n<li>List</li>\n</ul>\n",
 142
 143		"*   List\n    * Nested list\n    # Nested header\n",
 144		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 145			"<h1>Nested header</h1></li>\n</ul></li>\n</ul>\n",
 146	}
 147	doTestsBlock(t, tests, SpaceHeadings)
 148}
 149
 150func TestPrefixHeaderIdExtension(t *testing.T) {
 151	var tests = []string{
 152		"# Header 1 {#someid}\n",
 153		"<h1 id=\"someid\">Header 1</h1>\n",
 154
 155		"# Header 1 {#someid}   \n",
 156		"<h1 id=\"someid\">Header 1</h1>\n",
 157
 158		"# Header 1         {#someid}\n",
 159		"<h1 id=\"someid\">Header 1</h1>\n",
 160
 161		"# Header 1 {#someid\n",
 162		"<h1>Header 1 {#someid</h1>\n",
 163
 164		"# Header 1 {#someid\n",
 165		"<h1>Header 1 {#someid</h1>\n",
 166
 167		"# Header 1 {#someid}}\n",
 168		"<h1 id=\"someid\">Header 1</h1>\n\n<p>}</p>\n",
 169
 170		"## Header 2 {#someid}\n",
 171		"<h2 id=\"someid\">Header 2</h2>\n",
 172
 173		"### Header 3 {#someid}\n",
 174		"<h3 id=\"someid\">Header 3</h3>\n",
 175
 176		"#### Header 4 {#someid}\n",
 177		"<h4 id=\"someid\">Header 4</h4>\n",
 178
 179		"##### Header 5 {#someid}\n",
 180		"<h5 id=\"someid\">Header 5</h5>\n",
 181
 182		"###### Header 6 {#someid}\n",
 183		"<h6 id=\"someid\">Header 6</h6>\n",
 184
 185		"####### Header 7 {#someid}\n",
 186		"<h6 id=\"someid\"># Header 7</h6>\n",
 187
 188		"# Header 1 # {#someid}\n",
 189		"<h1 id=\"someid\">Header 1</h1>\n",
 190
 191		"## Header 2 ## {#someid}\n",
 192		"<h2 id=\"someid\">Header 2</h2>\n",
 193
 194		"Hello\n# Header 1\nGoodbye\n",
 195		"<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
 196
 197		"* List\n# Header {#someid}\n* List\n",
 198		"<ul>\n<li><p>List</p>\n\n<h1 id=\"someid\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 199
 200		"* List\n#Header {#someid}\n* List\n",
 201		"<ul>\n<li><p>List</p>\n\n<h1 id=\"someid\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 202
 203		"*   List\n    * Nested list\n    # Nested header {#someid}\n",
 204		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 205			"<h1 id=\"someid\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
 206	}
 207	doTestsBlock(t, tests, HeadingIDs)
 208}
 209
 210func TestPrefixHeaderIdExtensionWithPrefixAndSuffix(t *testing.T) {
 211	var tests = []string{
 212		"# header 1 {#someid}\n",
 213		"<h1 id=\"PRE:someid:POST\">header 1</h1>\n",
 214
 215		"## header 2 {#someid}\n",
 216		"<h2 id=\"PRE:someid:POST\">header 2</h2>\n",
 217
 218		"### header 3 {#someid}\n",
 219		"<h3 id=\"PRE:someid:POST\">header 3</h3>\n",
 220
 221		"#### header 4 {#someid}\n",
 222		"<h4 id=\"PRE:someid:POST\">header 4</h4>\n",
 223
 224		"##### header 5 {#someid}\n",
 225		"<h5 id=\"PRE:someid:POST\">header 5</h5>\n",
 226
 227		"###### header 6 {#someid}\n",
 228		"<h6 id=\"PRE:someid:POST\">header 6</h6>\n",
 229
 230		"####### header 7 {#someid}\n",
 231		"<h6 id=\"PRE:someid:POST\"># header 7</h6>\n",
 232
 233		"# header 1 # {#someid}\n",
 234		"<h1 id=\"PRE:someid:POST\">header 1</h1>\n",
 235
 236		"## header 2 ## {#someid}\n",
 237		"<h2 id=\"PRE:someid:POST\">header 2</h2>\n",
 238
 239		"* List\n# Header {#someid}\n* List\n",
 240		"<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",
 241
 242		"* List\n#Header {#someid}\n* List\n",
 243		"<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",
 244
 245		"*   List\n    * Nested list\n    # Nested header {#someid}\n",
 246		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 247			"<h1 id=\"PRE:someid:POST\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
 248	}
 249
 250	parameters := HTMLRendererParameters{
 251		HeadingIDPrefix: "PRE:",
 252		HeadingIDSuffix: ":POST",
 253	}
 254
 255	doTestsParam(t, tests, TestParams{
 256		extensions:             HeadingIDs,
 257		HTMLFlags:              UseXHTML,
 258		HTMLRendererParameters: parameters,
 259	})
 260}
 261
 262func TestPrefixAutoHeaderIdExtension(t *testing.T) {
 263	var tests = []string{
 264		"# Header 1\n",
 265		"<h1 id=\"header-1\">Header 1</h1>\n",
 266
 267		"# Header 1   \n",
 268		"<h1 id=\"header-1\">Header 1</h1>\n",
 269
 270		"## Header 2\n",
 271		"<h2 id=\"header-2\">Header 2</h2>\n",
 272
 273		"### Header 3\n",
 274		"<h3 id=\"header-3\">Header 3</h3>\n",
 275
 276		"#### Header 4\n",
 277		"<h4 id=\"header-4\">Header 4</h4>\n",
 278
 279		"##### Header 5\n",
 280		"<h5 id=\"header-5\">Header 5</h5>\n",
 281
 282		"###### Header 6\n",
 283		"<h6 id=\"header-6\">Header 6</h6>\n",
 284
 285		"####### Header 7\n",
 286		"<h6 id=\"header-7\"># Header 7</h6>\n",
 287
 288		"Hello\n# Header 1\nGoodbye\n",
 289		"<p>Hello</p>\n\n<h1 id=\"header-1\">Header 1</h1>\n\n<p>Goodbye</p>\n",
 290
 291		"* List\n# Header\n* List\n",
 292		"<ul>\n<li><p>List</p>\n\n<h1 id=\"header\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 293
 294		"* List\n#Header\n* List\n",
 295		"<ul>\n<li><p>List</p>\n\n<h1 id=\"header\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
 296
 297		"*   List\n    * Nested list\n    # Nested header\n",
 298		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 299			"<h1 id=\"nested-header\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
 300
 301		"# Header\n\n# Header\n",
 302		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n",
 303
 304		"# Header 1\n\n# Header 1",
 305		"<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
 306
 307		"# Header\n\n# Header 1\n\n# Header\n\n# Header",
 308		"<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",
 309	}
 310	doTestsBlock(t, tests, AutoHeadingIDs)
 311}
 312
 313func TestPrefixAutoHeaderIdExtensionWithPrefixAndSuffix(t *testing.T) {
 314	var tests = []string{
 315		"# Header 1\n",
 316		"<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n",
 317
 318		"# Header 1   \n",
 319		"<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n",
 320
 321		"## Header 2\n",
 322		"<h2 id=\"PRE:header-2:POST\">Header 2</h2>\n",
 323
 324		"### Header 3\n",
 325		"<h3 id=\"PRE:header-3:POST\">Header 3</h3>\n",
 326
 327		"#### Header 4\n",
 328		"<h4 id=\"PRE:header-4:POST\">Header 4</h4>\n",
 329
 330		"##### Header 5\n",
 331		"<h5 id=\"PRE:header-5:POST\">Header 5</h5>\n",
 332
 333		"###### Header 6\n",
 334		"<h6 id=\"PRE:header-6:POST\">Header 6</h6>\n",
 335
 336		"####### Header 7\n",
 337		"<h6 id=\"PRE:header-7:POST\"># Header 7</h6>\n",
 338
 339		"Hello\n# Header 1\nGoodbye\n",
 340		"<p>Hello</p>\n\n<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<p>Goodbye</p>\n",
 341
 342		"* List\n# Header\n* List\n",
 343		"<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",
 344
 345		"* List\n#Header\n* List\n",
 346		"<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",
 347
 348		"*   List\n    * Nested list\n    # Nested header\n",
 349		"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
 350			"<h1 id=\"PRE:nested-header:POST\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
 351
 352		"# Header\n\n# Header\n",
 353		"<h1 id=\"PRE:header:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1:POST\">Header</h1>\n",
 354
 355		"# Header 1\n\n# Header 1",
 356		"<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<h1 id=\"PRE:header-1-1:POST\">Header 1</h1>\n",
 357
 358		"# Header\n\n# Header 1\n\n# Header\n\n# Header",
 359		"<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",
 360	}
 361
 362	parameters := HTMLRendererParameters{
 363		HeadingIDPrefix: "PRE:",
 364		HeadingIDSuffix: ":POST",
 365	}
 366
 367	doTestsParam(t, tests, TestParams{
 368		extensions:             AutoHeadingIDs,
 369		HTMLFlags:              UseXHTML,
 370		HTMLRendererParameters: parameters,
 371	})
 372}
 373
 374func TestPrefixHeaderLevelOffset(t *testing.T) {
 375	var offsetTests = []struct {
 376		offset int
 377		tests  []string
 378	}{{
 379		offset: 0,
 380		tests: []string{
 381			"# Header 1\n",
 382			"<h1>Header 1</h1>\n",
 383
 384			"## Header 2\n",
 385			"<h2>Header 2</h2>\n",
 386
 387			"### Header 3\n",
 388			"<h3>Header 3</h3>\n",
 389
 390			"#### Header 4\n",
 391			"<h4>Header 4</h4>\n",
 392
 393			"##### Header 5\n",
 394			"<h5>Header 5</h5>\n",
 395
 396			"###### Header 6\n",
 397			"<h6>Header 6</h6>\n",
 398
 399			"####### Header 7\n",
 400			"<h6># Header 7</h6>\n",
 401		},
 402	}, {
 403		offset: 1,
 404		tests: []string{
 405			"# Header 1\n",
 406			"<h2>Header 1</h2>\n",
 407
 408			"## Header 2\n",
 409			"<h3>Header 2</h3>\n",
 410
 411			"### Header 3\n",
 412			"<h4>Header 3</h4>\n",
 413
 414			"#### Header 4\n",
 415			"<h5>Header 4</h5>\n",
 416
 417			"##### Header 5\n",
 418			"<h6>Header 5</h6>\n",
 419
 420			"###### Header 6\n",
 421			"<h6>Header 6</h6>\n",
 422
 423			"####### Header 7\n",
 424			"<h6># Header 7</h6>\n",
 425		},
 426	}, {
 427		offset: -1,
 428		tests: []string{
 429			"# Header 1\n",
 430			"<h1>Header 1</h1>\n",
 431
 432			"## Header 2\n",
 433			"<h1>Header 2</h1>\n",
 434
 435			"### Header 3\n",
 436			"<h2>Header 3</h2>\n",
 437
 438			"#### Header 4\n",
 439			"<h3>Header 4</h3>\n",
 440
 441			"##### Header 5\n",
 442			"<h4>Header 5</h4>\n",
 443
 444			"###### Header 6\n",
 445			"<h5>Header 6</h5>\n",
 446
 447			"####### Header 7\n",
 448			"<h5># Header 7</h5>\n",
 449		},
 450	}}
 451	for _, offsetTest := range offsetTests {
 452		offset := offsetTest.offset
 453		tests := offsetTest.tests
 454		doTestsParam(t, tests, TestParams{
 455			HTMLRendererParameters: HTMLRendererParameters{HeadingLevelOffset: offset},
 456		})
 457	}
 458}
 459
 460func TestPrefixMultipleHeaderExtensions(t *testing.T) {
 461	var tests = []string{
 462		"# Header\n\n# Header {#header}\n\n# Header 1",
 463		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
 464	}
 465	doTestsBlock(t, tests, AutoHeadingIDs|HeadingIDs)
 466}
 467
 468func TestUnderlineHeaders(t *testing.T) {
 469	var tests = []string{
 470		"Header 1\n========\n",
 471		"<h1>Header 1</h1>\n",
 472
 473		"Header 2\n--------\n",
 474		"<h2>Header 2</h2>\n",
 475
 476		"A\n=\n",
 477		"<h1>A</h1>\n",
 478
 479		"B\n-\n",
 480		"<h2>B</h2>\n",
 481
 482		"Paragraph\nHeader\n=\n",
 483		"<p>Paragraph</p>\n\n<h1>Header</h1>\n",
 484
 485		"Header\n===\nParagraph\n",
 486		"<h1>Header</h1>\n\n<p>Paragraph</p>\n",
 487
 488		"Header\n===\nAnother header\n---\n",
 489		"<h1>Header</h1>\n\n<h2>Another header</h2>\n",
 490
 491		"   Header\n======\n",
 492		"<h1>Header</h1>\n",
 493
 494		"    Code\n========\n",
 495		"<pre><code>Code\n</code></pre>\n\n<p>========</p>\n",
 496
 497		"Header with *inline*\n=====\n",
 498		"<h1>Header with <em>inline</em></h1>\n",
 499
 500		"*   List\n    * Sublist\n    Not a header\n    ------\n",
 501		"<ul>\n<li>List\n\n<ul>\n<li>Sublist\nNot a header\n------</li>\n</ul></li>\n</ul>\n",
 502
 503		"Paragraph\n\n\n\n\nHeader\n===\n",
 504		"<p>Paragraph</p>\n\n<h1>Header</h1>\n",
 505
 506		"Trailing space \n====        \n\n",
 507		"<h1>Trailing space</h1>\n",
 508
 509		"Trailing spaces\n====        \n\n",
 510		"<h1>Trailing spaces</h1>\n",
 511
 512		"Double underline\n=====\n=====\n",
 513		"<h1>Double underline</h1>\n\n<p>=====</p>\n",
 514	}
 515	doTestsBlock(t, tests, 0)
 516}
 517
 518func TestUnderlineHeadersAutoIDs(t *testing.T) {
 519	var tests = []string{
 520		"Header 1\n========\n",
 521		"<h1 id=\"header-1\">Header 1</h1>\n",
 522
 523		"Header 2\n--------\n",
 524		"<h2 id=\"header-2\">Header 2</h2>\n",
 525
 526		"A\n=\n",
 527		"<h1 id=\"a\">A</h1>\n",
 528
 529		"B\n-\n",
 530		"<h2 id=\"b\">B</h2>\n",
 531
 532		"Paragraph\nHeader\n=\n",
 533		"<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
 534
 535		"Header\n===\nParagraph\n",
 536		"<h1 id=\"header\">Header</h1>\n\n<p>Paragraph</p>\n",
 537
 538		"Header\n===\nAnother header\n---\n",
 539		"<h1 id=\"header\">Header</h1>\n\n<h2 id=\"another-header\">Another header</h2>\n",
 540
 541		"   Header\n======\n",
 542		"<h1 id=\"header\">Header</h1>\n",
 543
 544		"Header with *inline*\n=====\n",
 545		"<h1 id=\"header-with-inline\">Header with <em>inline</em></h1>\n",
 546
 547		"Paragraph\n\n\n\n\nHeader\n===\n",
 548		"<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
 549
 550		"Trailing space \n====        \n\n",
 551		"<h1 id=\"trailing-space\">Trailing space</h1>\n",
 552
 553		"Trailing spaces\n====        \n\n",
 554		"<h1 id=\"trailing-spaces\">Trailing spaces</h1>\n",
 555
 556		"Double underline\n=====\n=====\n",
 557		"<h1 id=\"double-underline\">Double underline</h1>\n\n<p>=====</p>\n",
 558
 559		"Header\n======\n\nHeader\n======\n",
 560		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n",
 561
 562		"Header 1\n========\n\nHeader 1\n========\n",
 563		"<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
 564	}
 565	doTestsBlock(t, tests, AutoHeadingIDs)
 566}
 567
 568func TestHorizontalRule(t *testing.T) {
 569	var tests = []string{
 570		"-\n",
 571		"<p>-</p>\n",
 572
 573		"--\n",
 574		"<p>--</p>\n",
 575
 576		"---\n",
 577		"<hr />\n",
 578
 579		"----\n",
 580		"<hr />\n",
 581
 582		"*\n",
 583		"<p>*</p>\n",
 584
 585		"**\n",
 586		"<p>**</p>\n",
 587
 588		"***\n",
 589		"<hr />\n",
 590
 591		"****\n",
 592		"<hr />\n",
 593
 594		"_\n",
 595		"<p>_</p>\n",
 596
 597		"__\n",
 598		"<p>__</p>\n",
 599
 600		"___\n",
 601		"<hr />\n",
 602
 603		"____\n",
 604		"<hr />\n",
 605
 606		"-*-\n",
 607		"<p>-*-</p>\n",
 608
 609		"- - -\n",
 610		"<hr />\n",
 611
 612		"* * *\n",
 613		"<hr />\n",
 614
 615		"_ _ _\n",
 616		"<hr />\n",
 617
 618		"-----*\n",
 619		"<p>-----*</p>\n",
 620
 621		"   ------   \n",
 622		"<hr />\n",
 623
 624		"Hello\n***\n",
 625		"<p>Hello</p>\n\n<hr />\n",
 626
 627		"---\n***\n___\n",
 628		"<hr />\n\n<hr />\n\n<hr />\n",
 629	}
 630	doTestsBlock(t, tests, 0)
 631}
 632
 633func TestUnorderedList(t *testing.T) {
 634	var tests = []string{
 635		"* Hello\n",
 636		"<ul>\n<li>Hello</li>\n</ul>\n",
 637
 638		"* Yin\n* Yang\n",
 639		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 640
 641		"* Ting\n* Bong\n* Goo\n",
 642		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 643
 644		"* Yin\n\n* Yang\n",
 645		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 646
 647		"* Ting\n\n* Bong\n* Goo\n",
 648		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 649
 650		"+ Hello\n",
 651		"<ul>\n<li>Hello</li>\n</ul>\n",
 652
 653		"+ Yin\n+ Yang\n",
 654		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 655
 656		"+ Ting\n+ Bong\n+ Goo\n",
 657		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 658
 659		"+ Yin\n\n+ Yang\n",
 660		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 661
 662		"+ Ting\n\n+ Bong\n+ Goo\n",
 663		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 664
 665		"- Hello\n",
 666		"<ul>\n<li>Hello</li>\n</ul>\n",
 667
 668		"- Yin\n- Yang\n",
 669		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 670
 671		"- Ting\n- Bong\n- Goo\n",
 672		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 673
 674		"- Yin\n\n- Yang\n",
 675		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 676
 677		"- Ting\n\n- Bong\n- Goo\n",
 678		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 679
 680		"*Hello\n",
 681		"<p>*Hello</p>\n",
 682
 683		"*   Hello \n",
 684		"<ul>\n<li>Hello</li>\n</ul>\n",
 685
 686		"*   Hello \n    Next line \n",
 687		"<ul>\n<li>Hello\nNext line</li>\n</ul>\n",
 688
 689		"Paragraph\n* No linebreak\n",
 690		"<p>Paragraph\n* No linebreak</p>\n",
 691
 692		"Paragraph\n\n* Linebreak\n",
 693		"<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n",
 694
 695		"*   List\n    * Nested list\n",
 696		"<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
 697
 698		"*   List\n\n    * Nested list\n",
 699		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
 700
 701		"*   List\n    Second line\n\n    + Nested\n",
 702		"<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n",
 703
 704		"*   List\n    + Nested\n\n    Continued\n",
 705		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n",
 706
 707		"*   List\n   * shallow indent\n",
 708		"<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n",
 709
 710		"* List\n" +
 711			" * shallow indent\n" +
 712			"  * part of second list\n" +
 713			"   * still second\n" +
 714			"    * almost there\n" +
 715			"     * third level\n",
 716		"<ul>\n" +
 717			"<li>List\n\n" +
 718			"<ul>\n" +
 719			"<li>shallow indent</li>\n" +
 720			"<li>part of second list</li>\n" +
 721			"<li>still second</li>\n" +
 722			"<li>almost there\n\n" +
 723			"<ul>\n" +
 724			"<li>third level</li>\n" +
 725			"</ul></li>\n" +
 726			"</ul></li>\n" +
 727			"</ul>\n",
 728
 729		"* List\n        extra indent, same paragraph\n",
 730		"<ul>\n<li>List\n    extra indent, same paragraph</li>\n</ul>\n",
 731
 732		"* List\n\n        code block\n",
 733		"<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n",
 734
 735		"* List\n\n          code block with spaces\n",
 736		"<ul>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ul>\n",
 737
 738		"* List\n\n    * sublist\n\n    normal text\n\n    * another sublist\n",
 739		"<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",
 740	}
 741	doTestsBlock(t, tests, 0)
 742}
 743
 744func TestOrderedList(t *testing.T) {
 745	var tests = []string{
 746		"1. Hello\n",
 747		"<ol>\n<li>Hello</li>\n</ol>\n",
 748
 749		"1. Yin\n2. Yang\n",
 750		"<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n",
 751
 752		"1. Ting\n2. Bong\n3. Goo\n",
 753		"<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n",
 754
 755		"1. Yin\n\n2. Yang\n",
 756		"<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n",
 757
 758		"1. Ting\n\n2. Bong\n3. Goo\n",
 759		"<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n",
 760
 761		"1 Hello\n",
 762		"<p>1 Hello</p>\n",
 763
 764		"1.Hello\n",
 765		"<p>1.Hello</p>\n",
 766
 767		"1.  Hello \n",
 768		"<ol>\n<li>Hello</li>\n</ol>\n",
 769
 770		"1.  Hello \n    Next line \n",
 771		"<ol>\n<li>Hello\nNext line</li>\n</ol>\n",
 772
 773		"Paragraph\n1. No linebreak\n",
 774		"<p>Paragraph\n1. No linebreak</p>\n",
 775
 776		"Paragraph\n\n1. Linebreak\n",
 777		"<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n",
 778
 779		"1.  List\n    1. Nested list\n",
 780		"<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
 781
 782		"1.  List\n\n    1. Nested list\n",
 783		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
 784
 785		"1.  List\n    Second line\n\n    1. Nested\n",
 786		"<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n",
 787
 788		"1.  List\n    1. Nested\n\n    Continued\n",
 789		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n",
 790
 791		"1.  List\n   1. shallow indent\n",
 792		"<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n",
 793
 794		"1. List\n" +
 795			" 1. shallow indent\n" +
 796			"  2. part of second list\n" +
 797			"   3. still second\n" +
 798			"    4. almost there\n" +
 799			"     1. third level\n",
 800		"<ol>\n" +
 801			"<li>List\n\n" +
 802			"<ol>\n" +
 803			"<li>shallow indent</li>\n" +
 804			"<li>part of second list</li>\n" +
 805			"<li>still second</li>\n" +
 806			"<li>almost there\n\n" +
 807			"<ol>\n" +
 808			"<li>third level</li>\n" +
 809			"</ol></li>\n" +
 810			"</ol></li>\n" +
 811			"</ol>\n",
 812
 813		"1. List\n        extra indent, same paragraph\n",
 814		"<ol>\n<li>List\n    extra indent, same paragraph</li>\n</ol>\n",
 815
 816		"1. List\n\n        code block\n",
 817		"<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n",
 818
 819		"1. List\n\n          code block with spaces\n",
 820		"<ol>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ol>\n",
 821
 822		"1. List\n    * Mixted list\n",
 823		"<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n",
 824
 825		"1. List\n * Mixed list\n",
 826		"<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n",
 827
 828		"* Start with unordered\n 1. Ordered\n",
 829		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
 830
 831		"* Start with unordered\n    1. Ordered\n",
 832		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
 833
 834		"1. numbers\n1. are ignored\n",
 835		"<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n",
 836	}
 837	doTestsBlock(t, tests, 0)
 838}
 839
 840func TestDefinitionList(t *testing.T) {
 841	var tests = []string{
 842		"Term 1\n:   Definition a\n",
 843		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 844
 845		"Term 1\n:   Definition a \n",
 846		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 847
 848		"Term 1\n:   Definition a\n:   Definition b\n",
 849		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n<dd>Definition b</dd>\n</dl>\n",
 850
 851		"Term 1\n:   Definition a\n\nTerm 2\n:   Definition b\n",
 852		"<dl>\n" +
 853			"<dt>Term 1</dt>\n" +
 854			"<dd>Definition a</dd>\n" +
 855			"<dt>Term 2</dt>\n" +
 856			"<dd>Definition b</dd>\n" +
 857			"</dl>\n",
 858
 859		"Term 1\n:   Definition a\n\nTerm 2\n:   Definition b\n\nTerm 3\n:   Definition c\n",
 860		"<dl>\n" +
 861			"<dt>Term 1</dt>\n" +
 862			"<dd>Definition a</dd>\n" +
 863			"<dt>Term 2</dt>\n" +
 864			"<dd>Definition b</dd>\n" +
 865			"<dt>Term 3</dt>\n" +
 866			"<dd>Definition c</dd>\n" +
 867			"</dl>\n",
 868
 869		"Term 1\n:   Definition a\n:   Definition b\n\nTerm 2\n:   Definition c\n",
 870		"<dl>\n" +
 871			"<dt>Term 1</dt>\n" +
 872			"<dd>Definition a</dd>\n" +
 873			"<dd>Definition b</dd>\n" +
 874			"<dt>Term 2</dt>\n" +
 875			"<dd>Definition c</dd>\n" +
 876			"</dl>\n",
 877
 878		"Term 1\n\n:   Definition a\n\nTerm 2\n\n:   Definition b\n",
 879		"<dl>\n" +
 880			"<dt>Term 1</dt>\n" +
 881			"<dd><p>Definition a</p></dd>\n" +
 882			"<dt>Term 2</dt>\n" +
 883			"<dd><p>Definition b</p></dd>\n" +
 884			"</dl>\n",
 885
 886		"Term 1\n\n:   Definition a\n\n:   Definition b\n\nTerm 2\n\n:   Definition c\n",
 887		"<dl>\n" +
 888			"<dt>Term 1</dt>\n" +
 889			"<dd><p>Definition a</p></dd>\n" +
 890			"<dd><p>Definition b</p></dd>\n" +
 891			"<dt>Term 2</dt>\n" +
 892			"<dd><p>Definition c</p></dd>\n" +
 893			"</dl>\n",
 894
 895		"Term 1\n:   Definition a\nNext line\n",
 896		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 897
 898		"Term 1\n:   Definition a\n  Next line\n",
 899		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 900
 901		"Term 1\n:   Definition a \n  Next line \n",
 902		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 903
 904		"Term 1\n:   Definition a\nNext line\n\nTerm 2\n:   Definition b",
 905		"<dl>\n" +
 906			"<dt>Term 1</dt>\n" +
 907			"<dd>Definition a\nNext line</dd>\n" +
 908			"<dt>Term 2</dt>\n" +
 909			"<dd>Definition b</dd>\n" +
 910			"</dl>\n",
 911
 912		"Term 1\n: Definition a\n",
 913		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 914
 915		"Term 1\n:Definition a\n",
 916		"<p>Term 1\n:Definition a</p>\n",
 917
 918		"Term 1\n\n:   Definition a\n\nTerm 2\n\n:   Definition b\n\nText 1",
 919		"<dl>\n" +
 920			"<dt>Term 1</dt>\n" +
 921			"<dd><p>Definition a</p></dd>\n" +
 922			"<dt>Term 2</dt>\n" +
 923			"<dd><p>Definition b</p></dd>\n" +
 924			"</dl>\n" +
 925			"\n<p>Text 1</p>\n",
 926
 927		"Term 1\n\n:   Definition a\n\nText 1\n\nTerm 2\n\n:   Definition b\n\nText 2",
 928		"<dl>\n" +
 929			"<dt>Term 1</dt>\n" +
 930			"<dd><p>Definition a</p></dd>\n" +
 931			"</dl>\n" +
 932			"\n<p>Text 1</p>\n" +
 933			"\n<dl>\n" +
 934			"<dt>Term 2</dt>\n" +
 935			"<dd><p>Definition b</p></dd>\n" +
 936			"</dl>\n" +
 937			"\n<p>Text 2</p>\n",
 938	}
 939	doTestsBlock(t, tests, DefinitionLists)
 940}
 941
 942func TestConsecutiveLists(t *testing.T) {
 943	var tests = []string{
 944		"1. Hello\n\n* Hello\n\nTerm 1\n:   Definition a\n",
 945		"<ol>\n<li>Hello</li>\n</ol>\n\n<ul>\n<li>Hello</li>\n</ul>\n\n<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 946
 947		"1. Not nested\n2. ordered list\n\n\t1. nested\n\t2. ordered list\n\n\t* nested\n\t* unordered list\n* Not nested\n* unordered list",
 948		"<ol>\n<li><p>Not nested</p></li>\n\n<li><p>ordered list</p>\n\n<ol>\n<li>nested</li>\n<li>ordered list</li>\n</ol>\n\n<ul>\n<li>nested</li>\n<li>unordered list</li>\n</ul></li>\n</ol>\n\n<ul>\n<li>Not nested</li>\n<li>unordered list</li>\n</ul>\n",
 949	}
 950	doTestsBlock(t, tests, DefinitionLists)
 951}
 952
 953func TestPreformattedHtml(t *testing.T) {
 954	var tests = []string{
 955		"<div></div>\n",
 956		"<div></div>\n",
 957
 958		"<div>\n</div>\n",
 959		"<div>\n</div>\n",
 960
 961		"<div>\n</div>\nParagraph\n",
 962		"<p><div>\n</div>\nParagraph</p>\n",
 963
 964		"<div class=\"foo\">\n</div>\n",
 965		"<div class=\"foo\">\n</div>\n",
 966
 967		"<div>\nAnything here\n</div>\n",
 968		"<div>\nAnything here\n</div>\n",
 969
 970		"<div>\n  Anything here\n</div>\n",
 971		"<div>\n  Anything here\n</div>\n",
 972
 973		"<div>\nAnything here\n  </div>\n",
 974		"<div>\nAnything here\n  </div>\n",
 975
 976		"<div>\nThis is *not* &proceessed\n</div>\n",
 977		"<div>\nThis is *not* &proceessed\n</div>\n",
 978
 979		"<faketag>\n  Something\n</faketag>\n",
 980		"<p><faketag>\n  Something\n</faketag></p>\n",
 981
 982		"<div>\n  Something here\n</divv>\n",
 983		"<p><div>\n  Something here\n</divv></p>\n",
 984
 985		"Paragraph\n<div>\nHere? >&<\n</div>\n",
 986		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div></p>\n",
 987
 988		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n",
 989		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n",
 990
 991		"Paragraph\n<div>\nHere? >&<\n</div>\nAnd here?\n",
 992		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div>\nAnd here?</p>\n",
 993
 994		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\nAnd here?\n",
 995		"<p>Paragraph</p>\n\n<p><div>\nHow about here? &gt;&amp;&lt;\n</div>\nAnd here?</p>\n",
 996
 997		"Paragraph\n<div>\nHere? >&<\n</div>\n\nAnd here?\n",
 998		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div></p>\n\n<p>And here?</p>\n",
 999
1000		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n\nAnd here?\n",
1001		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
1002	}
1003	doTestsBlock(t, tests, 0)
1004}
1005
1006func TestPreformattedHtmlLax(t *testing.T) {
1007	var tests = []string{
1008		"Paragraph\n<div>\nHere? >&<\n</div>\n",
1009		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n",
1010
1011		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n",
1012		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n",
1013
1014		"Paragraph\n<div>\nHere? >&<\n</div>\nAnd here?\n",
1015		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n\n<p>And here?</p>\n",
1016
1017		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\nAnd here?\n",
1018		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
1019
1020		"Paragraph\n<div>\nHere? >&<\n</div>\n\nAnd here?\n",
1021		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n\n<p>And here?</p>\n",
1022
1023		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n\nAnd here?\n",
1024		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
1025	}
1026	doTestsBlock(t, tests, LaxHTMLBlocks)
1027}
1028
1029func TestFencedCodeBlock(t *testing.T) {
1030	var tests = []string{
1031		"``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n",
1032		"<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
1033
1034		"``` go foo bar\nfunc foo() bool {\n\treturn true;\n}\n```\n",
1035		"<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
1036
1037		"``` c\n/* special & char < > \" escaping */\n```\n",
1038		"<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",
1039
1040		"``` c\nno *inline* processing ~~of text~~\n```\n",
1041		"<pre><code class=\"language-c\">no *inline* processing ~~of text~~\n</code></pre>\n",
1042
1043		"```\nNo language\n```\n",
1044		"<pre><code>No language\n</code></pre>\n",
1045
1046		"``` {ocaml}\nlanguage in braces\n```\n",
1047		"<pre><code class=\"language-ocaml\">language in braces\n</code></pre>\n",
1048
1049		"```    {ocaml}      \nwith extra whitespace\n```\n",
1050		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
1051
1052		"```{   ocaml   }\nwith extra whitespace\n```\n",
1053		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
1054
1055		"~ ~~ java\nWith whitespace\n~~~\n",
1056		"<p>~ ~~ java\nWith whitespace\n~~~</p>\n",
1057
1058		"~~\nonly two\n~~\n",
1059		"<p>~~\nonly two\n~~</p>\n",
1060
1061		"```` python\nextra\n````\n",
1062		"<pre><code class=\"language-python\">extra\n</code></pre>\n",
1063
1064		"~~~ perl\nthree to start, four to end\n~~~~\n",
1065		"<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n",
1066
1067		"~~~~ perl\nfour to start, three to end\n~~~\n",
1068		"<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n",
1069
1070		"~~~ bash\ntildes\n~~~\n",
1071		"<pre><code class=\"language-bash\">tildes\n</code></pre>\n",
1072
1073		"``` lisp\nno ending\n",
1074		"<p>``` lisp\nno ending</p>\n",
1075
1076		"~~~ lisp\nend with language\n~~~ lisp\n",
1077		"<p>~~~ lisp\nend with language\n~~~ lisp</p>\n",
1078
1079		"```\nmismatched begin and end\n~~~\n",
1080		"<p>```\nmismatched begin and end\n~~~</p>\n",
1081
1082		"~~~\nmismatched begin and end\n```\n",
1083		"<p>~~~\nmismatched begin and end\n```</p>\n",
1084
1085		"   ``` oz\nleading spaces\n```\n",
1086		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1087
1088		"  ``` oz\nleading spaces\n ```\n",
1089		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1090
1091		" ``` oz\nleading spaces\n  ```\n",
1092		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1093
1094		"``` oz\nleading spaces\n   ```\n",
1095		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1096
1097		"    ``` oz\nleading spaces\n    ```\n",
1098		"<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces\n    ```</p>\n",
1099
1100		"Bla bla\n\n``` oz\ncode blocks breakup paragraphs\n```\n\nBla Bla\n",
1101		"<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",
1102
1103		"Some text before a fenced code block\n``` oz\ncode blocks breakup paragraphs\n```\nAnd some text after a fenced code block",
1104		"<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",
1105
1106		"`",
1107		"<p>`</p>\n",
1108
1109		"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",
1110		"<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",
1111
1112		"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",
1113		"<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",
1114
1115		"```\n[]:()\n```\n",
1116		"<pre><code>[]:()\n</code></pre>\n",
1117
1118		"```\n[]:()\n[]:)\n[]:(\n[]:x\n[]:testing\n[:testing\n\n[]:\nlinebreak\n[]()\n\n[]:\n[]()\n```",
1119		"<pre><code>[]:()\n[]:)\n[]:(\n[]:x\n[]:testing\n[:testing\n\n[]:\nlinebreak\n[]()\n\n[]:\n[]()\n</code></pre>\n",
1120	}
1121	doTestsBlock(t, tests, FencedCode)
1122}
1123
1124func TestFencedCodeInsideBlockquotes(t *testing.T) {
1125	cat := func(s ...string) string { return strings.Join(s, "\n") }
1126	var tests = []string{
1127		cat("> ```go",
1128			"package moo",
1129			"",
1130			"```",
1131			""),
1132		`<blockquote>
1133<pre><code class="language-go">package moo
1134
1135</code></pre>
1136</blockquote>
1137`,
1138		// -------------------------------------------
1139		cat("> foo",
1140			"> ",
1141			"> ```go",
1142			"package moo",
1143			"```",
1144			"> ",
1145			"> goo.",
1146			""),
1147		`<blockquote>
1148<p>foo</p>
1149
1150<pre><code class="language-go">package moo
1151</code></pre>
1152
1153<p>goo.</p>
1154</blockquote>
1155`,
1156		// -------------------------------------------
1157		cat("> foo",
1158			"> ",
1159			"> quote",
1160			"continues",
1161			"```",
1162			""),
1163		`<blockquote>
1164<p>foo</p>
1165
1166<p>quote
1167continues
1168` + "```" + `</p>
1169</blockquote>
1170`,
1171		// -------------------------------------------
1172		cat("> foo",
1173			"> ",
1174			"> ```go",
1175			"package moo",
1176			"```",
1177			"> ",
1178			"> goo.",
1179			"> ",
1180			"> ```go",
1181			"package zoo",
1182			"```",
1183			"> ",
1184			"> woo.",
1185			""),
1186		`<blockquote>
1187<p>foo</p>
1188
1189<pre><code class="language-go">package moo
1190</code></pre>
1191
1192<p>goo.</p>
1193
1194<pre><code class="language-go">package zoo
1195</code></pre>
1196
1197<p>woo.</p>
1198</blockquote>
1199`,
1200	}
1201
1202	// These 2 alternative forms of blockquoted fenced code blocks should produce same output.
1203	forms := [2]string{
1204		cat("> plain quoted text",
1205			"> ```fenced",
1206			"code",
1207			" with leading single space correctly preserved",
1208			"okay",
1209			"```",
1210			"> rest of quoted text"),
1211		cat("> plain quoted text",
1212			"> ```fenced",
1213			"> code",
1214			">  with leading single space correctly preserved",
1215			"> okay",
1216			"> ```",
1217			"> rest of quoted text"),
1218	}
1219	want := `<blockquote>
1220<p>plain quoted text</p>
1221
1222<pre><code class="language-fenced">code
1223 with leading single space correctly preserved
1224okay
1225</code></pre>
1226
1227<p>rest of quoted text</p>
1228</blockquote>
1229`
1230	tests = append(tests, forms[0], want)
1231	tests = append(tests, forms[1], want)
1232
1233	doTestsBlock(t, tests, FencedCode)
1234}
1235
1236func TestTable(t *testing.T) {
1237	var tests = []string{
1238		"a | b\n---|---\nc | d\n",
1239		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n\n" +
1240			"<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n",
1241
1242		"a | b\n---|--\nc | d\n",
1243		"<p>a | b\n---|--\nc | d</p>\n",
1244
1245		"|a|b|c|d|\n|----|----|----|---|\n|e|f|g|h|\n",
1246		"<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" +
1247			"<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",
1248
1249		"*a*|__b__|[c](C)|d\n---|---|---|---\ne|f|g|h\n",
1250		"<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" +
1251			"<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",
1252
1253		"a|b|c\n---|---|---\nd|e|f\ng|h\ni|j|k|l|m\nn|o|p\n",
1254		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n" +
1255			"<tbody>\n<tr>\n<td>d</td>\n<td>e</td>\n<td>f</td>\n</tr>\n\n" +
1256			"<tr>\n<td>g</td>\n<td>h</td>\n<td></td>\n</tr>\n\n" +
1257			"<tr>\n<td>i</td>\n<td>j</td>\n<td>k</td>\n</tr>\n\n" +
1258			"<tr>\n<td>n</td>\n<td>o</td>\n<td>p</td>\n</tr>\n</tbody>\n</table>\n",
1259
1260		"a|b|c\n---|---|---\n*d*|__e__|f\n",
1261		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n" +
1262			"<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",
1263
1264		"a|b|c|d\n:--|--:|:-:|---\ne|f|g|h\n",
1265		"<table>\n<thead>\n<tr>\n<th align=\"left\">a</th>\n<th align=\"right\">b</th>\n" +
1266			"<th align=\"center\">c</th>\n<th>d</th>\n</tr>\n</thead>\n\n" +
1267			"<tbody>\n<tr>\n<td align=\"left\">e</td>\n<td align=\"right\">f</td>\n" +
1268			"<td align=\"center\">g</td>\n<td>h</td>\n</tr>\n</tbody>\n</table>\n",
1269
1270		"a|b|c\n---|---|---\n",
1271		"<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",
1272
1273		"a| b|c | d | e\n---|---|---|---|---\nf| g|h | i |j\n",
1274		"<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" +
1275			"<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",
1276
1277		"a|b\\|c|d\n---|---|---\nf|g\\|h|i\n",
1278		"<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",
1279	}
1280	doTestsBlock(t, tests, Tables)
1281}
1282
1283func TestUnorderedListWith_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1284	var tests = []string{
1285		"* Hello\n",
1286		"<ul>\n<li>Hello</li>\n</ul>\n",
1287
1288		"* Yin\n* Yang\n",
1289		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1290
1291		"* Ting\n* Bong\n* Goo\n",
1292		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1293
1294		"* Yin\n\n* Yang\n",
1295		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1296
1297		"* Ting\n\n* Bong\n* Goo\n",
1298		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1299
1300		"+ Hello\n",
1301		"<ul>\n<li>Hello</li>\n</ul>\n",
1302
1303		"+ Yin\n+ Yang\n",
1304		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1305
1306		"+ Ting\n+ Bong\n+ Goo\n",
1307		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1308
1309		"+ Yin\n\n+ Yang\n",
1310		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1311
1312		"+ Ting\n\n+ Bong\n+ Goo\n",
1313		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1314
1315		"- Hello\n",
1316		"<ul>\n<li>Hello</li>\n</ul>\n",
1317
1318		"- Yin\n- Yang\n",
1319		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1320
1321		"- Ting\n- Bong\n- Goo\n",
1322		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1323
1324		"- Yin\n\n- Yang\n",
1325		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1326
1327		"- Ting\n\n- Bong\n- Goo\n",
1328		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1329
1330		"*Hello\n",
1331		"<p>*Hello</p>\n",
1332
1333		"*   Hello \n",
1334		"<ul>\n<li>Hello</li>\n</ul>\n",
1335
1336		"*   Hello \n    Next line \n",
1337		"<ul>\n<li>Hello\nNext line</li>\n</ul>\n",
1338
1339		"Paragraph\n* No linebreak\n",
1340		"<p>Paragraph</p>\n\n<ul>\n<li>No linebreak</li>\n</ul>\n",
1341
1342		"Paragraph\n\n* Linebreak\n",
1343		"<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n",
1344
1345		"*   List\n    * Nested list\n",
1346		"<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
1347
1348		"*   List\n\n    * Nested list\n",
1349		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
1350
1351		"*   List\n    Second line\n\n    + Nested\n",
1352		"<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n",
1353
1354		"*   List\n    + Nested\n\n    Continued\n",
1355		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n",
1356
1357		"*   List\n   * shallow indent\n",
1358		"<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n",
1359
1360		"* List\n" +
1361			" * shallow indent\n" +
1362			"  * part of second list\n" +
1363			"   * still second\n" +
1364			"    * almost there\n" +
1365			"     * third level\n",
1366		"<ul>\n" +
1367			"<li>List\n\n" +
1368			"<ul>\n" +
1369			"<li>shallow indent</li>\n" +
1370			"<li>part of second list</li>\n" +
1371			"<li>still second</li>\n" +
1372			"<li>almost there\n\n" +
1373			"<ul>\n" +
1374			"<li>third level</li>\n" +
1375			"</ul></li>\n" +
1376			"</ul></li>\n" +
1377			"</ul>\n",
1378
1379		"* List\n        extra indent, same paragraph\n",
1380		"<ul>\n<li>List\n    extra indent, same paragraph</li>\n</ul>\n",
1381
1382		"* List\n\n        code block\n",
1383		"<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n",
1384
1385		"* List\n\n          code block with spaces\n",
1386		"<ul>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ul>\n",
1387
1388		"* List\n\n    * sublist\n\n    normal text\n\n    * another sublist\n",
1389		"<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",
1390	}
1391	doTestsBlock(t, tests, NoEmptyLineBeforeBlock)
1392}
1393
1394func TestOrderedList_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1395	var tests = []string{
1396		"1. Hello\n",
1397		"<ol>\n<li>Hello</li>\n</ol>\n",
1398
1399		"1. Yin\n2. Yang\n",
1400		"<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n",
1401
1402		"1. Ting\n2. Bong\n3. Goo\n",
1403		"<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n",
1404
1405		"1. Yin\n\n2. Yang\n",
1406		"<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n",
1407
1408		"1. Ting\n\n2. Bong\n3. Goo\n",
1409		"<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n",
1410
1411		"1 Hello\n",
1412		"<p>1 Hello</p>\n",
1413
1414		"1.Hello\n",
1415		"<p>1.Hello</p>\n",
1416
1417		"1.  Hello \n",
1418		"<ol>\n<li>Hello</li>\n</ol>\n",
1419
1420		"1.  Hello \n    Next line \n",
1421		"<ol>\n<li>Hello\nNext line</li>\n</ol>\n",
1422
1423		"Paragraph\n1. No linebreak\n",
1424		"<p>Paragraph</p>\n\n<ol>\n<li>No linebreak</li>\n</ol>\n",
1425
1426		"Paragraph\n\n1. Linebreak\n",
1427		"<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n",
1428
1429		"1.  List\n    1. Nested list\n",
1430		"<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
1431
1432		"1.  List\n\n    1. Nested list\n",
1433		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
1434
1435		"1.  List\n    Second line\n\n    1. Nested\n",
1436		"<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n",
1437
1438		"1.  List\n    1. Nested\n\n    Continued\n",
1439		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n",
1440
1441		"1.  List\n   1. shallow indent\n",
1442		"<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n",
1443
1444		"1. List\n" +
1445			" 1. shallow indent\n" +
1446			"  2. part of second list\n" +
1447			"   3. still second\n" +
1448			"    4. almost there\n" +
1449			"     1. third level\n",
1450		"<ol>\n" +
1451			"<li>List\n\n" +
1452			"<ol>\n" +
1453			"<li>shallow indent</li>\n" +
1454			"<li>part of second list</li>\n" +
1455			"<li>still second</li>\n" +
1456			"<li>almost there\n\n" +
1457			"<ol>\n" +
1458			"<li>third level</li>\n" +
1459			"</ol></li>\n" +
1460			"</ol></li>\n" +
1461			"</ol>\n",
1462
1463		"1. List\n        extra indent, same paragraph\n",
1464		"<ol>\n<li>List\n    extra indent, same paragraph</li>\n</ol>\n",
1465
1466		"1. List\n\n        code block\n",
1467		"<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n",
1468
1469		"1. List\n\n          code block with spaces\n",
1470		"<ol>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ol>\n",
1471
1472		"1. List\n    * Mixted list\n",
1473		"<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n",
1474
1475		"1. List\n * Mixed list\n",
1476		"<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n",
1477
1478		"* Start with unordered\n 1. Ordered\n",
1479		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
1480
1481		"* Start with unordered\n    1. Ordered\n",
1482		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
1483
1484		"1. numbers\n1. are ignored\n",
1485		"<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n",
1486	}
1487	doTestsBlock(t, tests, NoEmptyLineBeforeBlock)
1488}
1489
1490func TestFencedCodeBlock_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1491	var tests = []string{
1492		"``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n",
1493		"<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
1494
1495		"``` go foo bar\nfunc foo() bool {\n\treturn true;\n}\n```\n",
1496		"<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
1497
1498		"``` c\n/* special & char < > \" escaping */\n```\n",
1499		"<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",
1500
1501		"``` c\nno *inline* processing ~~of text~~\n```\n",
1502		"<pre><code class=\"language-c\">no *inline* processing ~~of text~~\n</code></pre>\n",
1503
1504		"```\nNo language\n```\n",
1505		"<pre><code>No language\n</code></pre>\n",
1506
1507		"``` {ocaml}\nlanguage in braces\n```\n",
1508		"<pre><code class=\"language-ocaml\">language in braces\n</code></pre>\n",
1509
1510		"```    {ocaml}      \nwith extra whitespace\n```\n",
1511		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
1512
1513		"```{   ocaml   }\nwith extra whitespace\n```\n",
1514		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
1515
1516		"~ ~~ java\nWith whitespace\n~~~\n",
1517		"<p>~ ~~ java\nWith whitespace\n~~~</p>\n",
1518
1519		"~~\nonly two\n~~\n",
1520		"<p>~~\nonly two\n~~</p>\n",
1521
1522		"```` python\nextra\n````\n",
1523		"<pre><code class=\"language-python\">extra\n</code></pre>\n",
1524
1525		"~~~ perl\nthree to start, four to end\n~~~~\n",
1526		"<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n",
1527
1528		"~~~~ perl\nfour to start, three to end\n~~~\n",
1529		"<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n",
1530
1531		"~~~ bash\ntildes\n~~~\n",
1532		"<pre><code class=\"language-bash\">tildes\n</code></pre>\n",
1533
1534		"``` lisp\nno ending\n",
1535		"<p>``` lisp\nno ending</p>\n",
1536
1537		"~~~ lisp\nend with language\n~~~ lisp\n",
1538		"<p>~~~ lisp\nend with language\n~~~ lisp</p>\n",
1539
1540		"```\nmismatched begin and end\n~~~\n",
1541		"<p>```\nmismatched begin and end\n~~~</p>\n",
1542
1543		"~~~\nmismatched begin and end\n```\n",
1544		"<p>~~~\nmismatched begin and end\n```</p>\n",
1545
1546		"   ``` oz\nleading spaces\n```\n",
1547		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1548
1549		"  ``` oz\nleading spaces\n ```\n",
1550		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1551
1552		" ``` oz\nleading spaces\n  ```\n",
1553		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1554
1555		"``` oz\nleading spaces\n   ```\n",
1556		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1557
1558		"    ``` oz\nleading spaces\n    ```\n",
1559		"<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces</p>\n\n<pre><code>```\n</code></pre>\n",
1560	}
1561	doTestsBlock(t, tests, FencedCode|NoEmptyLineBeforeBlock)
1562}
1563
1564func TestListWithFencedCodeBlock(t *testing.T) {
1565	var tests = []string{
1566		"1. one\n\n    ```\n    code\n    ```\n\n2. two\n",
1567		"<ol>\n<li><p>one</p>\n\n<pre><code>code\n</code></pre></li>\n\n<li><p>two</p></li>\n</ol>\n",
1568		// https://github.com/russross/blackfriday/issues/239
1569		"1. one\n\n    ```\n    - code\n    ```\n\n2. two\n",
1570		"<ol>\n<li><p>one</p>\n\n<pre><code>- code\n</code></pre></li>\n\n<li><p>two</p></li>\n</ol>\n",
1571	}
1572	doTestsBlock(t, tests, FencedCode)
1573}
1574
1575func TestListWithMalformedFencedCodeBlock(t *testing.T) {
1576	// Ensure that in the case of an unclosed fenced code block in a list,
1577	// no source gets ommitted (even if it is malformed).
1578	// See russross/blackfriday#372 for context.
1579	var tests = []string{
1580		"1. one\n\n    ```\n    code\n\n2. two\n",
1581		"<ol>\n<li>one\n```\ncode\n2. two</li>\n</ol>\n",
1582
1583		"1. one\n\n    ```\n    - code\n\n2. two\n",
1584		"<ol>\n<li>one\n```\n- code\n2. two</li>\n</ol>\n",
1585	}
1586	doTestsBlock(t, tests, FencedCode)
1587}
1588
1589func TestListWithFencedCodeBlockNoExtensions(t *testing.T) {
1590	// If there is a fenced code block in a list, and FencedCode is not set,
1591	// lists should be processed normally.
1592	var tests = []string{
1593		"1. one\n\n    ```\n    code\n    ```\n\n2. two\n",
1594		"<ol>\n<li><p>one</p>\n\n<p><code>\ncode\n</code></p></li>\n\n<li><p>two</p></li>\n</ol>\n",
1595
1596		"1. one\n\n    ```\n    - code\n    ```\n\n2. two\n",
1597		"<ol>\n<li><p>one</p>\n\n<p>```</p>\n\n<ul>\n<li>code\n```</li>\n</ul></li>\n\n<li><p>two</p></li>\n</ol>\n",
1598	}
1599	doTestsBlock(t, tests, 0)
1600}
1601
1602func TestTitleBlock_EXTENSION_TITLEBLOCK(t *testing.T) {
1603	var tests = []string{
1604		"% Some title\n" +
1605			"% Another title line\n" +
1606			"% Yep, more here too\n",
1607		"<h1 class=\"title\">" +
1608			"Some title\n" +
1609			"Another title line\n" +
1610			"Yep, more here too" +
1611			"</h1>\n",
1612	}
1613	doTestsBlock(t, tests, Titleblock)
1614}
1615
1616func TestBlockComments(t *testing.T) {
1617	var tests = []string{
1618		"Some text\n\n<!-- comment -->\n",
1619		"<p>Some text</p>\n\n<!-- comment -->\n",
1620
1621		"Some text\n\n<!--\n\nmultiline\ncomment\n-->\n",
1622		"<p>Some text</p>\n\n<!--\n\nmultiline\ncomment\n-->\n",
1623
1624		"Some text\n\n<!--\n\n<div><p>Commented</p>\n<span>html</span></div>\n-->\n",
1625		"<p>Some text</p>\n\n<!--\n\n<div><p>Commented</p>\n<span>html</span></div>\n-->\n",
1626	}
1627	doTestsBlock(t, tests, 0)
1628}
1629
1630func TestTOC(t *testing.T) {
1631	var tests = []string{
1632		"# Title\n\n##Subtitle1\n\n##Subtitle2",
1633		//"<nav>\n<ul>\n<li><a href=\"#toc_0\">Title</a>\n<ul>\n<li><a href=\"#toc_1\">Subtitle1</a></li>\n<li><a href=\"#toc_2\">Subtitle2</a></li>\n</ul></li>\n</ul>\n</nav>\n\n<h1 id=\"toc_0\">Title</h1>\n\n<h2 id=\"toc_1\">Subtitle1</h2>\n\n<h2 id=\"toc_2\">Subtitle2</h2>\n",
1634		`<nav>
1635
1636<ul>
1637<li><a href="#toc_0">Title</a>
1638<ul>
1639<li><a href="#toc_1">Subtitle1</a></li>
1640
1641<li><a href="#toc_2">Subtitle2</a></li>
1642</ul></li>
1643</ul>
1644
1645</nav>
1646
1647<h1 id="toc_0">Title</h1>
1648
1649<h2 id="toc_1">Subtitle1</h2>
1650
1651<h2 id="toc_2">Subtitle2</h2>
1652`,
1653
1654		"# Title\n\n##Subtitle\n\n#Title2",
1655		//"<nav>\n<ul>\n<li><a href=\"#toc_0\">Title</a>\n<ul>\n<li><a href=\"#toc_1\">Subtitle</a></li>\n</ul></li>\n<li><a href=\"#toc_2\">Title2</a></li>\n</ul>\n</nav>\n\n<h1 id=\"toc_0\">Title</h1>\n\n<h2 id=\"toc_1\">Subtitle</h2>\n\n<h1 id=\"toc_2\">Title2</h1>\n",
1656		`<nav>
1657
1658<ul>
1659<li><a href="#toc_0">Title</a>
1660<ul>
1661<li><a href="#toc_1">Subtitle</a></li>
1662</ul></li>
1663
1664<li><a href="#toc_2">Title2</a></li>
1665</ul>
1666
1667</nav>
1668
1669<h1 id="toc_0">Title</h1>
1670
1671<h2 id="toc_1">Subtitle</h2>
1672
1673<h1 id="toc_2">Title2</h1>
1674`,
1675
1676		"## Subtitle\n\n# Title",
1677		`<nav>
1678
1679<ul>
1680<li>
1681<ul>
1682<li><a href="#toc_0">Subtitle</a></li>
1683</ul></li>
1684
1685<li><a href="#toc_1">Title</a></li>
1686</ul>
1687
1688</nav>
1689
1690<h2 id="toc_0">Subtitle</h2>
1691
1692<h1 id="toc_1">Title</h1>
1693`,
1694
1695		"# Title 1\n\n## Subtitle 1\n\n### Subsubtitle 1\n\n# Title 2\n\n### Subsubtitle 2",
1696		`<nav>
1697
1698<ul>
1699<li><a href="#toc_0">Title 1</a>
1700<ul>
1701<li><a href="#toc_1">Subtitle 1</a>
1702<ul>
1703<li><a href="#toc_2">Subsubtitle 1</a></li>
1704</ul></li>
1705</ul></li>
1706
1707<li><a href="#toc_3">Title 2</a>
1708<ul>
1709<li>
1710<ul>
1711<li><a href="#toc_4">Subsubtitle 2</a></li>
1712</ul></li>
1713</ul></li>
1714</ul>
1715
1716</nav>
1717
1718<h1 id="toc_0">Title 1</h1>
1719
1720<h2 id="toc_1">Subtitle 1</h2>
1721
1722<h3 id="toc_2">Subsubtitle 1</h3>
1723
1724<h1 id="toc_3">Title 2</h1>
1725
1726<h3 id="toc_4">Subsubtitle 2</h3>
1727`,
1728
1729		"# Title with `code`",
1730		`<nav>
1731
1732<ul>
1733<li><a href="#toc_0">Title with <code>code</code></a></li>
1734</ul>
1735
1736</nav>
1737
1738<h1 id="toc_0">Title with <code>code</code></h1>
1739`,
1740
1741		// Trigger empty TOC
1742		"#",
1743		"",
1744	}
1745	doTestsParam(t, tests, TestParams{
1746		HTMLFlags: UseXHTML | TOC,
1747	})
1748}
1749
1750func TestCompletePage(t *testing.T) {
1751	var tests = []string{
1752		"*foo*",
1753		`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1754<html xmlns="http://www.w3.org/1999/xhtml">
1755<head>
1756  <title></title>
1757  <meta name="GENERATOR" content="Blackfriday Markdown Processor v2.0" />
1758  <meta charset="utf-8" />
1759</head>
1760<body>
1761
1762<p><em>foo</em></p>
1763
1764</body>
1765</html>
1766`,
1767	}
1768	doTestsParam(t, tests, TestParams{HTMLFlags: UseXHTML | CompletePage})
1769}
1770
1771func TestIsFenceLine(t *testing.T) {
1772	tests := []struct {
1773		data          []byte
1774		infoRequested bool
1775		wantEnd       int
1776		wantMarker    string
1777		wantInfo      string
1778	}{
1779		{
1780			data:       []byte("```"),
1781			wantEnd:    3,
1782			wantMarker: "```",
1783		},
1784		{
1785			data:       []byte("```\nstuff here\n"),
1786			wantEnd:    4,
1787			wantMarker: "```",
1788		},
1789		{
1790			data:          []byte("```\nstuff here\n"),
1791			infoRequested: true,
1792			wantEnd:       4,
1793			wantMarker:    "```",
1794		},
1795		{
1796			data:    []byte("stuff here\n```\n"),
1797			wantEnd: 0,
1798		},
1799		{
1800			data:          []byte("```"),
1801			infoRequested: true,
1802			wantEnd:       3,
1803			wantMarker:    "```",
1804		},
1805		{
1806			data:          []byte("``` go"),
1807			infoRequested: true,
1808			wantEnd:       6,
1809			wantMarker:    "```",
1810			wantInfo:      "go",
1811		},
1812		{
1813			data:          []byte("``` go foo bar"),
1814			infoRequested: true,
1815			wantEnd:       14,
1816			wantMarker:    "```",
1817			wantInfo:      "go foo bar",
1818		},
1819		{
1820			data:          []byte("``` go foo bar  "),
1821			infoRequested: true,
1822			wantEnd:       16,
1823			wantMarker:    "```",
1824			wantInfo:      "go foo bar",
1825		},
1826	}
1827
1828	for _, test := range tests {
1829		var info *string
1830		if test.infoRequested {
1831			info = new(string)
1832		}
1833		end, marker := isFenceLine(test.data, info, "```")
1834		if got, want := end, test.wantEnd; got != want {
1835			t.Errorf("got end %v, want %v", got, want)
1836		}
1837		if got, want := marker, test.wantMarker; got != want {
1838			t.Errorf("got marker %q, want %q", got, want)
1839		}
1840		if test.infoRequested {
1841			if got, want := *info, test.wantInfo; got != want {
1842				t.Errorf("got info string %q, want %q", got, want)
1843			}
1844		}
1845	}
1846}