all repos — grayfriday @ f805c775f5d24cd1ef697388d34e09b1b34c87a4

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, SpaceHeaders)
 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, HeaderIDs)
 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		HeaderIDPrefix: "PRE:",
 252		HeaderIDSuffix: ":POST",
 253	}
 254
 255	doTestsParam(t, tests, TestParams{
 256		Options:                Options{Extensions: HeaderIDs},
 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, AutoHeaderIDs)
 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		HeaderIDPrefix: "PRE:",
 364		HeaderIDSuffix: ":POST",
 365	}
 366
 367	doTestsParam(t, tests, TestParams{
 368		Options:                Options{Extensions: AutoHeaderIDs},
 369		HTMLFlags:              UseXHTML,
 370		HTMLRendererParameters: parameters,
 371	})
 372}
 373
 374func TestPrefixMultipleHeaderExtensions(t *testing.T) {
 375	var tests = []string{
 376		"# Header\n\n# Header {#header}\n\n# Header 1",
 377		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
 378	}
 379	doTestsBlock(t, tests, AutoHeaderIDs|HeaderIDs)
 380}
 381
 382func TestUnderlineHeaders(t *testing.T) {
 383	var tests = []string{
 384		"Header 1\n========\n",
 385		"<h1>Header 1</h1>\n",
 386
 387		"Header 2\n--------\n",
 388		"<h2>Header 2</h2>\n",
 389
 390		"A\n=\n",
 391		"<h1>A</h1>\n",
 392
 393		"B\n-\n",
 394		"<h2>B</h2>\n",
 395
 396		"Paragraph\nHeader\n=\n",
 397		"<p>Paragraph</p>\n\n<h1>Header</h1>\n",
 398
 399		"Header\n===\nParagraph\n",
 400		"<h1>Header</h1>\n\n<p>Paragraph</p>\n",
 401
 402		"Header\n===\nAnother header\n---\n",
 403		"<h1>Header</h1>\n\n<h2>Another header</h2>\n",
 404
 405		"   Header\n======\n",
 406		"<h1>Header</h1>\n",
 407
 408		"    Code\n========\n",
 409		"<pre><code>Code\n</code></pre>\n\n<p>========</p>\n",
 410
 411		"Header with *inline*\n=====\n",
 412		"<h1>Header with <em>inline</em></h1>\n",
 413
 414		"*   List\n    * Sublist\n    Not a header\n    ------\n",
 415		"<ul>\n<li>List\n\n<ul>\n<li>Sublist\nNot a header\n------</li>\n</ul></li>\n</ul>\n",
 416
 417		"Paragraph\n\n\n\n\nHeader\n===\n",
 418		"<p>Paragraph</p>\n\n<h1>Header</h1>\n",
 419
 420		"Trailing space \n====        \n\n",
 421		"<h1>Trailing space</h1>\n",
 422
 423		"Trailing spaces\n====        \n\n",
 424		"<h1>Trailing spaces</h1>\n",
 425
 426		"Double underline\n=====\n=====\n",
 427		"<h1>Double underline</h1>\n\n<p>=====</p>\n",
 428	}
 429	doTestsBlock(t, tests, 0)
 430}
 431
 432func TestUnderlineHeadersAutoIDs(t *testing.T) {
 433	var tests = []string{
 434		"Header 1\n========\n",
 435		"<h1 id=\"header-1\">Header 1</h1>\n",
 436
 437		"Header 2\n--------\n",
 438		"<h2 id=\"header-2\">Header 2</h2>\n",
 439
 440		"A\n=\n",
 441		"<h1 id=\"a\">A</h1>\n",
 442
 443		"B\n-\n",
 444		"<h2 id=\"b\">B</h2>\n",
 445
 446		"Paragraph\nHeader\n=\n",
 447		"<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
 448
 449		"Header\n===\nParagraph\n",
 450		"<h1 id=\"header\">Header</h1>\n\n<p>Paragraph</p>\n",
 451
 452		"Header\n===\nAnother header\n---\n",
 453		"<h1 id=\"header\">Header</h1>\n\n<h2 id=\"another-header\">Another header</h2>\n",
 454
 455		"   Header\n======\n",
 456		"<h1 id=\"header\">Header</h1>\n",
 457
 458		"Header with *inline*\n=====\n",
 459		"<h1 id=\"header-with-inline\">Header with <em>inline</em></h1>\n",
 460
 461		"Paragraph\n\n\n\n\nHeader\n===\n",
 462		"<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
 463
 464		"Trailing space \n====        \n\n",
 465		"<h1 id=\"trailing-space\">Trailing space</h1>\n",
 466
 467		"Trailing spaces\n====        \n\n",
 468		"<h1 id=\"trailing-spaces\">Trailing spaces</h1>\n",
 469
 470		"Double underline\n=====\n=====\n",
 471		"<h1 id=\"double-underline\">Double underline</h1>\n\n<p>=====</p>\n",
 472
 473		"Header\n======\n\nHeader\n======\n",
 474		"<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n",
 475
 476		"Header 1\n========\n\nHeader 1\n========\n",
 477		"<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
 478	}
 479	doTestsBlock(t, tests, AutoHeaderIDs)
 480}
 481
 482func TestHorizontalRule(t *testing.T) {
 483	var tests = []string{
 484		"-\n",
 485		"<p>-</p>\n",
 486
 487		"--\n",
 488		"<p>--</p>\n",
 489
 490		"---\n",
 491		"<hr />\n",
 492
 493		"----\n",
 494		"<hr />\n",
 495
 496		"*\n",
 497		"<p>*</p>\n",
 498
 499		"**\n",
 500		"<p>**</p>\n",
 501
 502		"***\n",
 503		"<hr />\n",
 504
 505		"****\n",
 506		"<hr />\n",
 507
 508		"_\n",
 509		"<p>_</p>\n",
 510
 511		"__\n",
 512		"<p>__</p>\n",
 513
 514		"___\n",
 515		"<hr />\n",
 516
 517		"____\n",
 518		"<hr />\n",
 519
 520		"-*-\n",
 521		"<p>-*-</p>\n",
 522
 523		"- - -\n",
 524		"<hr />\n",
 525
 526		"* * *\n",
 527		"<hr />\n",
 528
 529		"_ _ _\n",
 530		"<hr />\n",
 531
 532		"-----*\n",
 533		"<p>-----*</p>\n",
 534
 535		"   ------   \n",
 536		"<hr />\n",
 537
 538		"Hello\n***\n",
 539		"<p>Hello</p>\n\n<hr />\n",
 540
 541		"---\n***\n___\n",
 542		"<hr />\n\n<hr />\n\n<hr />\n",
 543	}
 544	doTestsBlock(t, tests, 0)
 545}
 546
 547func TestUnorderedList(t *testing.T) {
 548	var tests = []string{
 549		"* Hello\n",
 550		"<ul>\n<li>Hello</li>\n</ul>\n",
 551
 552		"* Yin\n* Yang\n",
 553		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 554
 555		"* Ting\n* Bong\n* Goo\n",
 556		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 557
 558		"* Yin\n\n* Yang\n",
 559		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 560
 561		"* Ting\n\n* Bong\n* Goo\n",
 562		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 563
 564		"+ Hello\n",
 565		"<ul>\n<li>Hello</li>\n</ul>\n",
 566
 567		"+ Yin\n+ Yang\n",
 568		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 569
 570		"+ Ting\n+ Bong\n+ Goo\n",
 571		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 572
 573		"+ Yin\n\n+ Yang\n",
 574		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 575
 576		"+ Ting\n\n+ Bong\n+ Goo\n",
 577		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 578
 579		"- Hello\n",
 580		"<ul>\n<li>Hello</li>\n</ul>\n",
 581
 582		"- Yin\n- Yang\n",
 583		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
 584
 585		"- Ting\n- Bong\n- Goo\n",
 586		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
 587
 588		"- Yin\n\n- Yang\n",
 589		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
 590
 591		"- Ting\n\n- Bong\n- Goo\n",
 592		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
 593
 594		"*Hello\n",
 595		"<p>*Hello</p>\n",
 596
 597		"*   Hello \n",
 598		"<ul>\n<li>Hello</li>\n</ul>\n",
 599
 600		"*   Hello \n    Next line \n",
 601		"<ul>\n<li>Hello\nNext line</li>\n</ul>\n",
 602
 603		"Paragraph\n* No linebreak\n",
 604		"<p>Paragraph\n* No linebreak</p>\n",
 605
 606		"Paragraph\n\n* Linebreak\n",
 607		"<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n",
 608
 609		"*   List\n    * Nested list\n",
 610		"<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
 611
 612		"*   List\n\n    * Nested list\n",
 613		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
 614
 615		"*   List\n    Second line\n\n    + Nested\n",
 616		"<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n",
 617
 618		"*   List\n    + Nested\n\n    Continued\n",
 619		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n",
 620
 621		"*   List\n   * shallow indent\n",
 622		"<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n",
 623
 624		"* List\n" +
 625			" * shallow indent\n" +
 626			"  * part of second list\n" +
 627			"   * still second\n" +
 628			"    * almost there\n" +
 629			"     * third level\n",
 630		"<ul>\n" +
 631			"<li>List\n\n" +
 632			"<ul>\n" +
 633			"<li>shallow indent</li>\n" +
 634			"<li>part of second list</li>\n" +
 635			"<li>still second</li>\n" +
 636			"<li>almost there\n\n" +
 637			"<ul>\n" +
 638			"<li>third level</li>\n" +
 639			"</ul></li>\n" +
 640			"</ul></li>\n" +
 641			"</ul>\n",
 642
 643		"* List\n        extra indent, same paragraph\n",
 644		"<ul>\n<li>List\n    extra indent, same paragraph</li>\n</ul>\n",
 645
 646		"* List\n\n        code block\n",
 647		"<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n",
 648
 649		"* List\n\n          code block with spaces\n",
 650		"<ul>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ul>\n",
 651
 652		"* List\n\n    * sublist\n\n    normal text\n\n    * another sublist\n",
 653		"<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",
 654	}
 655	doTestsBlock(t, tests, 0)
 656}
 657
 658func TestOrderedList(t *testing.T) {
 659	var tests = []string{
 660		"1. Hello\n",
 661		"<ol>\n<li>Hello</li>\n</ol>\n",
 662
 663		"1. Yin\n2. Yang\n",
 664		"<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n",
 665
 666		"1. Ting\n2. Bong\n3. Goo\n",
 667		"<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n",
 668
 669		"1. Yin\n\n2. Yang\n",
 670		"<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n",
 671
 672		"1. Ting\n\n2. Bong\n3. Goo\n",
 673		"<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n",
 674
 675		"1 Hello\n",
 676		"<p>1 Hello</p>\n",
 677
 678		"1.Hello\n",
 679		"<p>1.Hello</p>\n",
 680
 681		"1.  Hello \n",
 682		"<ol>\n<li>Hello</li>\n</ol>\n",
 683
 684		"1.  Hello \n    Next line \n",
 685		"<ol>\n<li>Hello\nNext line</li>\n</ol>\n",
 686
 687		"Paragraph\n1. No linebreak\n",
 688		"<p>Paragraph\n1. No linebreak</p>\n",
 689
 690		"Paragraph\n\n1. Linebreak\n",
 691		"<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n",
 692
 693		"1.  List\n    1. Nested list\n",
 694		"<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
 695
 696		"1.  List\n\n    1. Nested list\n",
 697		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
 698
 699		"1.  List\n    Second line\n\n    1. Nested\n",
 700		"<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n",
 701
 702		"1.  List\n    1. Nested\n\n    Continued\n",
 703		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n",
 704
 705		"1.  List\n   1. shallow indent\n",
 706		"<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n",
 707
 708		"1. List\n" +
 709			" 1. shallow indent\n" +
 710			"  2. part of second list\n" +
 711			"   3. still second\n" +
 712			"    4. almost there\n" +
 713			"     1. third level\n",
 714		"<ol>\n" +
 715			"<li>List\n\n" +
 716			"<ol>\n" +
 717			"<li>shallow indent</li>\n" +
 718			"<li>part of second list</li>\n" +
 719			"<li>still second</li>\n" +
 720			"<li>almost there\n\n" +
 721			"<ol>\n" +
 722			"<li>third level</li>\n" +
 723			"</ol></li>\n" +
 724			"</ol></li>\n" +
 725			"</ol>\n",
 726
 727		"1. List\n        extra indent, same paragraph\n",
 728		"<ol>\n<li>List\n    extra indent, same paragraph</li>\n</ol>\n",
 729
 730		"1. List\n\n        code block\n",
 731		"<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n",
 732
 733		"1. List\n\n          code block with spaces\n",
 734		"<ol>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ol>\n",
 735
 736		"1. List\n    * Mixted list\n",
 737		"<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n",
 738
 739		"1. List\n * Mixed list\n",
 740		"<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n",
 741
 742		"* Start with unordered\n 1. Ordered\n",
 743		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
 744
 745		"* Start with unordered\n    1. Ordered\n",
 746		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
 747
 748		"1. numbers\n1. are ignored\n",
 749		"<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n",
 750	}
 751	doTestsBlock(t, tests, 0)
 752}
 753
 754func TestDefinitionList(t *testing.T) {
 755	var tests = []string{
 756		"Term 1\n:   Definition a\n",
 757		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 758
 759		"Term 1\n:   Definition a \n",
 760		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 761
 762		"Term 1\n:   Definition a\n:   Definition b\n",
 763		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n<dd>Definition b</dd>\n</dl>\n",
 764
 765		"Term 1\n:   Definition a\n\nTerm 2\n:   Definition b\n",
 766		"<dl>\n" +
 767			"<dt>Term 1</dt>\n" +
 768			"<dd>Definition a</dd>\n" +
 769			"<dt>Term 2</dt>\n" +
 770			"<dd>Definition b</dd>\n" +
 771			"</dl>\n",
 772
 773		"Term 1\n:   Definition a\n\nTerm 2\n:   Definition b\n\nTerm 3\n:   Definition c\n",
 774		"<dl>\n" +
 775			"<dt>Term 1</dt>\n" +
 776			"<dd>Definition a</dd>\n" +
 777			"<dt>Term 2</dt>\n" +
 778			"<dd>Definition b</dd>\n" +
 779			"<dt>Term 3</dt>\n" +
 780			"<dd>Definition c</dd>\n" +
 781			"</dl>\n",
 782
 783		"Term 1\n:   Definition a\n:   Definition b\n\nTerm 2\n:   Definition c\n",
 784		"<dl>\n" +
 785			"<dt>Term 1</dt>\n" +
 786			"<dd>Definition a</dd>\n" +
 787			"<dd>Definition b</dd>\n" +
 788			"<dt>Term 2</dt>\n" +
 789			"<dd>Definition c</dd>\n" +
 790			"</dl>\n",
 791
 792		"Term 1\n\n:   Definition a\n\nTerm 2\n\n:   Definition b\n",
 793		"<dl>\n" +
 794			"<dt>Term 1</dt>\n" +
 795			"<dd><p>Definition a</p></dd>\n" +
 796			"<dt>Term 2</dt>\n" +
 797			"<dd><p>Definition b</p></dd>\n" +
 798			"</dl>\n",
 799
 800		"Term 1\n\n:   Definition a\n\n:   Definition b\n\nTerm 2\n\n:   Definition c\n",
 801		"<dl>\n" +
 802			"<dt>Term 1</dt>\n" +
 803			"<dd><p>Definition a</p></dd>\n" +
 804			"<dd><p>Definition b</p></dd>\n" +
 805			"<dt>Term 2</dt>\n" +
 806			"<dd><p>Definition c</p></dd>\n" +
 807			"</dl>\n",
 808
 809		"Term 1\n:   Definition a\nNext line\n",
 810		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 811
 812		"Term 1\n:   Definition a\n  Next line\n",
 813		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 814
 815		"Term 1\n:   Definition a \n  Next line \n",
 816		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
 817
 818		"Term 1\n:   Definition a\nNext line\n\nTerm 2\n:   Definition b",
 819		"<dl>\n" +
 820			"<dt>Term 1</dt>\n" +
 821			"<dd>Definition a\nNext line</dd>\n" +
 822			"<dt>Term 2</dt>\n" +
 823			"<dd>Definition b</dd>\n" +
 824			"</dl>\n",
 825
 826		"Term 1\n: Definition a\n",
 827		"<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
 828
 829		"Term 1\n:Definition a\n",
 830		"<p>Term 1\n:Definition a</p>\n",
 831
 832		"Term 1\n\n:   Definition a\n\nTerm 2\n\n:   Definition b\n\nText 1",
 833		"<dl>\n" +
 834			"<dt>Term 1</dt>\n" +
 835			"<dd><p>Definition a</p></dd>\n" +
 836			"<dt>Term 2</dt>\n" +
 837			"<dd><p>Definition b</p></dd>\n" +
 838			"</dl>\n" +
 839			"\n<p>Text 1</p>\n",
 840
 841		"Term 1\n\n:   Definition a\n\nText 1\n\nTerm 2\n\n:   Definition b\n\nText 2",
 842		"<dl>\n" +
 843			"<dt>Term 1</dt>\n" +
 844			"<dd><p>Definition a</p></dd>\n" +
 845			"</dl>\n" +
 846			"\n<p>Text 1</p>\n" +
 847			"\n<dl>\n" +
 848			"<dt>Term 2</dt>\n" +
 849			"<dd><p>Definition b</p></dd>\n" +
 850			"</dl>\n" +
 851			"\n<p>Text 2</p>\n",
 852	}
 853	doTestsBlock(t, tests, DefinitionLists)
 854}
 855
 856func TestPreformattedHtml(t *testing.T) {
 857	var tests = []string{
 858		"<div></div>\n",
 859		"<div></div>\n",
 860
 861		"<div>\n</div>\n",
 862		"<div>\n</div>\n",
 863
 864		"<div>\n</div>\nParagraph\n",
 865		"<p><div>\n</div>\nParagraph</p>\n",
 866
 867		"<div class=\"foo\">\n</div>\n",
 868		"<div class=\"foo\">\n</div>\n",
 869
 870		"<div>\nAnything here\n</div>\n",
 871		"<div>\nAnything here\n</div>\n",
 872
 873		"<div>\n  Anything here\n</div>\n",
 874		"<div>\n  Anything here\n</div>\n",
 875
 876		"<div>\nAnything here\n  </div>\n",
 877		"<div>\nAnything here\n  </div>\n",
 878
 879		"<div>\nThis is *not* &proceessed\n</div>\n",
 880		"<div>\nThis is *not* &proceessed\n</div>\n",
 881
 882		"<faketag>\n  Something\n</faketag>\n",
 883		"<p><faketag>\n  Something\n</faketag></p>\n",
 884
 885		"<div>\n  Something here\n</divv>\n",
 886		"<p><div>\n  Something here\n</divv></p>\n",
 887
 888		"Paragraph\n<div>\nHere? >&<\n</div>\n",
 889		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div></p>\n",
 890
 891		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n",
 892		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n",
 893
 894		"Paragraph\n<div>\nHere? >&<\n</div>\nAnd here?\n",
 895		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div>\nAnd here?</p>\n",
 896
 897		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\nAnd here?\n",
 898		"<p>Paragraph</p>\n\n<p><div>\nHow about here? &gt;&amp;&lt;\n</div>\nAnd here?</p>\n",
 899
 900		"Paragraph\n<div>\nHere? >&<\n</div>\n\nAnd here?\n",
 901		"<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div></p>\n\n<p>And here?</p>\n",
 902
 903		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n\nAnd here?\n",
 904		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
 905	}
 906	doTestsBlock(t, tests, 0)
 907}
 908
 909func TestPreformattedHtmlLax(t *testing.T) {
 910	var tests = []string{
 911		"Paragraph\n<div>\nHere? >&<\n</div>\n",
 912		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n",
 913
 914		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n",
 915		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n",
 916
 917		"Paragraph\n<div>\nHere? >&<\n</div>\nAnd here?\n",
 918		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n\n<p>And here?</p>\n",
 919
 920		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\nAnd here?\n",
 921		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
 922
 923		"Paragraph\n<div>\nHere? >&<\n</div>\n\nAnd here?\n",
 924		"<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n\n<p>And here?</p>\n",
 925
 926		"Paragraph\n\n<div>\nHow about here? >&<\n</div>\n\nAnd here?\n",
 927		"<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
 928	}
 929	doTestsBlock(t, tests, LaxHTMLBlocks)
 930}
 931
 932func TestFencedCodeBlock(t *testing.T) {
 933	var tests = []string{
 934		"``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n",
 935		"<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
 936
 937		"``` c\n/* special & char < > \" escaping */\n```\n",
 938		"<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",
 939
 940		"``` c\nno *inline* processing ~~of text~~\n```\n",
 941		"<pre><code class=\"language-c\">no *inline* processing ~~of text~~\n</code></pre>\n",
 942
 943		"```\nNo language\n```\n",
 944		"<pre><code>No language\n</code></pre>\n",
 945
 946		"``` {ocaml}\nlanguage in braces\n```\n",
 947		"<pre><code class=\"language-ocaml\">language in braces\n</code></pre>\n",
 948
 949		"```    {ocaml}      \nwith extra whitespace\n```\n",
 950		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
 951
 952		"```{   ocaml   }\nwith extra whitespace\n```\n",
 953		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
 954
 955		"~ ~~ java\nWith whitespace\n~~~\n",
 956		"<p>~ ~~ java\nWith whitespace\n~~~</p>\n",
 957
 958		"~~\nonly two\n~~\n",
 959		"<p>~~\nonly two\n~~</p>\n",
 960
 961		"```` python\nextra\n````\n",
 962		"<pre><code class=\"language-python\">extra\n</code></pre>\n",
 963
 964		"~~~ perl\nthree to start, four to end\n~~~~\n",
 965		"<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n",
 966
 967		"~~~~ perl\nfour to start, three to end\n~~~\n",
 968		"<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n",
 969
 970		"~~~ bash\ntildes\n~~~\n",
 971		"<pre><code class=\"language-bash\">tildes\n</code></pre>\n",
 972
 973		"``` lisp\nno ending\n",
 974		"<p>``` lisp\nno ending</p>\n",
 975
 976		"~~~ lisp\nend with language\n~~~ lisp\n",
 977		"<p>~~~ lisp\nend with language\n~~~ lisp</p>\n",
 978
 979		"```\nmismatched begin and end\n~~~\n",
 980		"<p>```\nmismatched begin and end\n~~~</p>\n",
 981
 982		"~~~\nmismatched begin and end\n```\n",
 983		"<p>~~~\nmismatched begin and end\n```</p>\n",
 984
 985		"   ``` oz\nleading spaces\n```\n",
 986		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
 987
 988		"  ``` oz\nleading spaces\n ```\n",
 989		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
 990
 991		" ``` oz\nleading spaces\n  ```\n",
 992		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
 993
 994		"``` oz\nleading spaces\n   ```\n",
 995		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
 996
 997		"    ``` oz\nleading spaces\n    ```\n",
 998		"<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces\n    ```</p>\n",
 999
1000		"Bla bla\n\n``` oz\ncode blocks breakup paragraphs\n```\n\nBla Bla\n",
1001		"<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",
1002
1003		"Some text before a fenced code block\n``` oz\ncode blocks breakup paragraphs\n```\nAnd some text after a fenced code block",
1004		"<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",
1005
1006		"`",
1007		"<p>`</p>\n",
1008
1009		"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",
1010		"<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",
1011
1012		"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",
1013		"<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",
1014
1015		"```\n[]:()\n```\n",
1016		"<pre><code>[]:()\n</code></pre>\n",
1017
1018		"```\n[]:()\n[]:)\n[]:(\n[]:x\n[]:testing\n[:testing\n\n[]:\nlinebreak\n[]()\n\n[]:\n[]()\n```",
1019		"<pre><code>[]:()\n[]:)\n[]:(\n[]:x\n[]:testing\n[:testing\n\n[]:\nlinebreak\n[]()\n\n[]:\n[]()\n</code></pre>\n",
1020	}
1021	doTestsBlock(t, tests, FencedCode)
1022}
1023
1024func TestFencedCodeInsideBlockquotes(t *testing.T) {
1025	cat := func(s ...string) string { return strings.Join(s, "\n") }
1026	var tests = []string{
1027		cat("> ```go",
1028			"package moo",
1029			"",
1030			"```",
1031			""),
1032		`<blockquote>
1033<pre><code class="language-go">package moo
1034
1035</code></pre>
1036</blockquote>
1037`,
1038		// -------------------------------------------
1039		cat("> foo",
1040			"> ",
1041			"> ```go",
1042			"package moo",
1043			"```",
1044			"> ",
1045			"> goo.",
1046			""),
1047		`<blockquote>
1048<p>foo</p>
1049
1050<pre><code class="language-go">package moo
1051</code></pre>
1052
1053<p>goo.</p>
1054</blockquote>
1055`,
1056		// -------------------------------------------
1057		cat("> foo",
1058			"> ",
1059			"> quote",
1060			"continues",
1061			"```",
1062			""),
1063		`<blockquote>
1064<p>foo</p>
1065
1066<p>quote
1067continues
1068` + "```" + `</p>
1069</blockquote>
1070`,
1071		// -------------------------------------------
1072		cat("> foo",
1073			"> ",
1074			"> ```go",
1075			"package moo",
1076			"```",
1077			"> ",
1078			"> goo.",
1079			"> ",
1080			"> ```go",
1081			"package zoo",
1082			"```",
1083			"> ",
1084			"> woo.",
1085			""),
1086		`<blockquote>
1087<p>foo</p>
1088
1089<pre><code class="language-go">package moo
1090</code></pre>
1091
1092<p>goo.</p>
1093
1094<pre><code class="language-go">package zoo
1095</code></pre>
1096
1097<p>woo.</p>
1098</blockquote>
1099`,
1100	}
1101
1102	// These 2 alternative forms of blockquoted fenced code blocks should produce same output.
1103	forms := [2]string{
1104		cat("> plain quoted text",
1105			"> ```fenced",
1106			"code",
1107			" with leading single space correctly preserved",
1108			"okay",
1109			"```",
1110			"> rest of quoted text"),
1111		cat("> plain quoted text",
1112			"> ```fenced",
1113			"> code",
1114			">  with leading single space correctly preserved",
1115			"> okay",
1116			"> ```",
1117			"> rest of quoted text"),
1118	}
1119	want := `<blockquote>
1120<p>plain quoted text</p>
1121
1122<pre><code class="language-fenced">code
1123 with leading single space correctly preserved
1124okay
1125</code></pre>
1126
1127<p>rest of quoted text</p>
1128</blockquote>
1129`
1130	tests = append(tests, forms[0], want)
1131	tests = append(tests, forms[1], want)
1132
1133	doTestsBlock(t, tests, FencedCode)
1134}
1135
1136func TestTable(t *testing.T) {
1137	var tests = []string{
1138		"a | b\n---|---\nc | d\n",
1139		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n\n" +
1140			"<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n",
1141
1142		"a | b\n---|--\nc | d\n",
1143		"<p>a | b\n---|--\nc | d</p>\n",
1144
1145		"|a|b|c|d|\n|----|----|----|---|\n|e|f|g|h|\n",
1146		"<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" +
1147			"<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",
1148
1149		"*a*|__b__|[c](C)|d\n---|---|---|---\ne|f|g|h\n",
1150		"<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" +
1151			"<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",
1152
1153		"a|b|c\n---|---|---\nd|e|f\ng|h\ni|j|k|l|m\nn|o|p\n",
1154		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n" +
1155			"<tbody>\n<tr>\n<td>d</td>\n<td>e</td>\n<td>f</td>\n</tr>\n\n" +
1156			"<tr>\n<td>g</td>\n<td>h</td>\n<td></td>\n</tr>\n\n" +
1157			"<tr>\n<td>i</td>\n<td>j</td>\n<td>k</td>\n</tr>\n\n" +
1158			"<tr>\n<td>n</td>\n<td>o</td>\n<td>p</td>\n</tr>\n</tbody>\n</table>\n",
1159
1160		"a|b|c\n---|---|---\n*d*|__e__|f\n",
1161		"<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n" +
1162			"<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",
1163
1164		"a|b|c|d\n:--|--:|:-:|---\ne|f|g|h\n",
1165		"<table>\n<thead>\n<tr>\n<th align=\"left\">a</th>\n<th align=\"right\">b</th>\n" +
1166			"<th align=\"center\">c</th>\n<th>d</th>\n</tr>\n</thead>\n\n" +
1167			"<tbody>\n<tr>\n<td align=\"left\">e</td>\n<td align=\"right\">f</td>\n" +
1168			"<td align=\"center\">g</td>\n<td>h</td>\n</tr>\n</tbody>\n</table>\n",
1169
1170		"a|b|c\n---|---|---\n",
1171		"<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",
1172
1173		"a| b|c | d | e\n---|---|---|---|---\nf| g|h | i |j\n",
1174		"<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" +
1175			"<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",
1176
1177		"a|b\\|c|d\n---|---|---\nf|g\\|h|i\n",
1178		"<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",
1179	}
1180	doTestsBlock(t, tests, Tables)
1181}
1182
1183func TestUnorderedListWith_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1184	var tests = []string{
1185		"* Hello\n",
1186		"<ul>\n<li>Hello</li>\n</ul>\n",
1187
1188		"* Yin\n* Yang\n",
1189		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1190
1191		"* Ting\n* Bong\n* Goo\n",
1192		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1193
1194		"* Yin\n\n* Yang\n",
1195		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1196
1197		"* Ting\n\n* Bong\n* Goo\n",
1198		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1199
1200		"+ Hello\n",
1201		"<ul>\n<li>Hello</li>\n</ul>\n",
1202
1203		"+ Yin\n+ Yang\n",
1204		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1205
1206		"+ Ting\n+ Bong\n+ Goo\n",
1207		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1208
1209		"+ Yin\n\n+ Yang\n",
1210		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1211
1212		"+ Ting\n\n+ Bong\n+ Goo\n",
1213		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1214
1215		"- Hello\n",
1216		"<ul>\n<li>Hello</li>\n</ul>\n",
1217
1218		"- Yin\n- Yang\n",
1219		"<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
1220
1221		"- Ting\n- Bong\n- Goo\n",
1222		"<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
1223
1224		"- Yin\n\n- Yang\n",
1225		"<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
1226
1227		"- Ting\n\n- Bong\n- Goo\n",
1228		"<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
1229
1230		"*Hello\n",
1231		"<p>*Hello</p>\n",
1232
1233		"*   Hello \n",
1234		"<ul>\n<li>Hello</li>\n</ul>\n",
1235
1236		"*   Hello \n    Next line \n",
1237		"<ul>\n<li>Hello\nNext line</li>\n</ul>\n",
1238
1239		"Paragraph\n* No linebreak\n",
1240		"<p>Paragraph</p>\n\n<ul>\n<li>No linebreak</li>\n</ul>\n",
1241
1242		"Paragraph\n\n* Linebreak\n",
1243		"<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n",
1244
1245		"*   List\n    * Nested list\n",
1246		"<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
1247
1248		"*   List\n\n    * Nested list\n",
1249		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
1250
1251		"*   List\n    Second line\n\n    + Nested\n",
1252		"<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n",
1253
1254		"*   List\n    + Nested\n\n    Continued\n",
1255		"<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n",
1256
1257		"*   List\n   * shallow indent\n",
1258		"<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n",
1259
1260		"* List\n" +
1261			" * shallow indent\n" +
1262			"  * part of second list\n" +
1263			"   * still second\n" +
1264			"    * almost there\n" +
1265			"     * third level\n",
1266		"<ul>\n" +
1267			"<li>List\n\n" +
1268			"<ul>\n" +
1269			"<li>shallow indent</li>\n" +
1270			"<li>part of second list</li>\n" +
1271			"<li>still second</li>\n" +
1272			"<li>almost there\n\n" +
1273			"<ul>\n" +
1274			"<li>third level</li>\n" +
1275			"</ul></li>\n" +
1276			"</ul></li>\n" +
1277			"</ul>\n",
1278
1279		"* List\n        extra indent, same paragraph\n",
1280		"<ul>\n<li>List\n    extra indent, same paragraph</li>\n</ul>\n",
1281
1282		"* List\n\n        code block\n",
1283		"<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n",
1284
1285		"* List\n\n          code block with spaces\n",
1286		"<ul>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ul>\n",
1287
1288		"* List\n\n    * sublist\n\n    normal text\n\n    * another sublist\n",
1289		"<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",
1290	}
1291	doTestsBlock(t, tests, NoEmptyLineBeforeBlock)
1292}
1293
1294func TestOrderedList_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1295	var tests = []string{
1296		"1. Hello\n",
1297		"<ol>\n<li>Hello</li>\n</ol>\n",
1298
1299		"1. Yin\n2. Yang\n",
1300		"<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n",
1301
1302		"1. Ting\n2. Bong\n3. Goo\n",
1303		"<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n",
1304
1305		"1. Yin\n\n2. Yang\n",
1306		"<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n",
1307
1308		"1. Ting\n\n2. Bong\n3. Goo\n",
1309		"<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n",
1310
1311		"1 Hello\n",
1312		"<p>1 Hello</p>\n",
1313
1314		"1.Hello\n",
1315		"<p>1.Hello</p>\n",
1316
1317		"1.  Hello \n",
1318		"<ol>\n<li>Hello</li>\n</ol>\n",
1319
1320		"1.  Hello \n    Next line \n",
1321		"<ol>\n<li>Hello\nNext line</li>\n</ol>\n",
1322
1323		"Paragraph\n1. No linebreak\n",
1324		"<p>Paragraph</p>\n\n<ol>\n<li>No linebreak</li>\n</ol>\n",
1325
1326		"Paragraph\n\n1. Linebreak\n",
1327		"<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n",
1328
1329		"1.  List\n    1. Nested list\n",
1330		"<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
1331
1332		"1.  List\n\n    1. Nested list\n",
1333		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
1334
1335		"1.  List\n    Second line\n\n    1. Nested\n",
1336		"<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n",
1337
1338		"1.  List\n    1. Nested\n\n    Continued\n",
1339		"<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n",
1340
1341		"1.  List\n   1. shallow indent\n",
1342		"<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n",
1343
1344		"1. List\n" +
1345			" 1. shallow indent\n" +
1346			"  2. part of second list\n" +
1347			"   3. still second\n" +
1348			"    4. almost there\n" +
1349			"     1. third level\n",
1350		"<ol>\n" +
1351			"<li>List\n\n" +
1352			"<ol>\n" +
1353			"<li>shallow indent</li>\n" +
1354			"<li>part of second list</li>\n" +
1355			"<li>still second</li>\n" +
1356			"<li>almost there\n\n" +
1357			"<ol>\n" +
1358			"<li>third level</li>\n" +
1359			"</ol></li>\n" +
1360			"</ol></li>\n" +
1361			"</ol>\n",
1362
1363		"1. List\n        extra indent, same paragraph\n",
1364		"<ol>\n<li>List\n    extra indent, same paragraph</li>\n</ol>\n",
1365
1366		"1. List\n\n        code block\n",
1367		"<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n",
1368
1369		"1. List\n\n          code block with spaces\n",
1370		"<ol>\n<li><p>List</p>\n\n<pre><code>  code block with spaces\n</code></pre></li>\n</ol>\n",
1371
1372		"1. List\n    * Mixted list\n",
1373		"<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n",
1374
1375		"1. List\n * Mixed list\n",
1376		"<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n",
1377
1378		"* Start with unordered\n 1. Ordered\n",
1379		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
1380
1381		"* Start with unordered\n    1. Ordered\n",
1382		"<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
1383
1384		"1. numbers\n1. are ignored\n",
1385		"<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n",
1386	}
1387	doTestsBlock(t, tests, NoEmptyLineBeforeBlock)
1388}
1389
1390func TestFencedCodeBlock_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
1391	var tests = []string{
1392		"``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n",
1393		"<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
1394
1395		"``` c\n/* special & char < > \" escaping */\n```\n",
1396		"<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",
1397
1398		"``` c\nno *inline* processing ~~of text~~\n```\n",
1399		"<pre><code class=\"language-c\">no *inline* processing ~~of text~~\n</code></pre>\n",
1400
1401		"```\nNo language\n```\n",
1402		"<pre><code>No language\n</code></pre>\n",
1403
1404		"``` {ocaml}\nlanguage in braces\n```\n",
1405		"<pre><code class=\"language-ocaml\">language in braces\n</code></pre>\n",
1406
1407		"```    {ocaml}      \nwith extra whitespace\n```\n",
1408		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
1409
1410		"```{   ocaml   }\nwith extra whitespace\n```\n",
1411		"<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
1412
1413		"~ ~~ java\nWith whitespace\n~~~\n",
1414		"<p>~ ~~ java\nWith whitespace\n~~~</p>\n",
1415
1416		"~~\nonly two\n~~\n",
1417		"<p>~~\nonly two\n~~</p>\n",
1418
1419		"```` python\nextra\n````\n",
1420		"<pre><code class=\"language-python\">extra\n</code></pre>\n",
1421
1422		"~~~ perl\nthree to start, four to end\n~~~~\n",
1423		"<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n",
1424
1425		"~~~~ perl\nfour to start, three to end\n~~~\n",
1426		"<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n",
1427
1428		"~~~ bash\ntildes\n~~~\n",
1429		"<pre><code class=\"language-bash\">tildes\n</code></pre>\n",
1430
1431		"``` lisp\nno ending\n",
1432		"<p>``` lisp\nno ending</p>\n",
1433
1434		"~~~ lisp\nend with language\n~~~ lisp\n",
1435		"<p>~~~ lisp\nend with language\n~~~ lisp</p>\n",
1436
1437		"```\nmismatched begin and end\n~~~\n",
1438		"<p>```\nmismatched begin and end\n~~~</p>\n",
1439
1440		"~~~\nmismatched begin and end\n```\n",
1441		"<p>~~~\nmismatched begin and end\n```</p>\n",
1442
1443		"   ``` oz\nleading spaces\n```\n",
1444		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1445
1446		"  ``` oz\nleading spaces\n ```\n",
1447		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1448
1449		" ``` oz\nleading spaces\n  ```\n",
1450		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1451
1452		"``` oz\nleading spaces\n   ```\n",
1453		"<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
1454
1455		"    ``` oz\nleading spaces\n    ```\n",
1456		"<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces</p>\n\n<pre><code>```\n</code></pre>\n",
1457	}
1458	doTestsBlock(t, tests, FencedCode|NoEmptyLineBeforeBlock)
1459}
1460
1461func TestTitleBlock_EXTENSION_TITLEBLOCK(t *testing.T) {
1462	var tests = []string{
1463		"% Some title\n" +
1464			"% Another title line\n" +
1465			"% Yep, more here too\n",
1466		"<h1 class=\"title\">" +
1467			"Some title\n" +
1468			"Another title line\n" +
1469			"Yep, more here too" +
1470			"</h1>\n",
1471	}
1472	doTestsBlock(t, tests, Titleblock)
1473}
1474
1475func TestBlockComments(t *testing.T) {
1476	var tests = []string{
1477		"Some text\n\n<!-- comment -->\n",
1478		"<p>Some text</p>\n\n<!-- comment -->\n",
1479
1480		"Some text\n\n<!--\n\nmultiline\ncomment\n-->\n",
1481		"<p>Some text</p>\n\n<!--\n\nmultiline\ncomment\n-->\n",
1482
1483		"Some text\n\n<!--\n\n<div><p>Commented</p>\n<span>html</span></div>\n-->\n",
1484		"<p>Some text</p>\n\n<!--\n\n<div><p>Commented</p>\n<span>html</span></div>\n-->\n",
1485	}
1486	doTestsBlock(t, tests, 0)
1487}
1488
1489func TestTOC(t *testing.T) {
1490	var tests = []string{
1491		"# Title\n\n##Subtitle1\n\n##Subtitle2",
1492		//"<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",
1493		`<nav>
1494
1495<ul>
1496<li><a href="#toc_0">Title</a>
1497<ul>
1498<li><a href="#toc_1">Subtitle1</a></li>
1499
1500<li><a href="#toc_2">Subtitle2</a></li>
1501</ul></li>
1502</ul>
1503
1504</nav>
1505
1506<h1 id="toc_0">Title</h1>
1507
1508<h2 id="toc_1">Subtitle1</h2>
1509
1510<h2 id="toc_2">Subtitle2</h2>
1511`,
1512
1513		"# Title\n\n##Subtitle\n\n#Title2",
1514		//"<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",
1515		`<nav>
1516
1517<ul>
1518<li><a href="#toc_0">Title</a>
1519<ul>
1520<li><a href="#toc_1">Subtitle</a></li>
1521</ul></li>
1522
1523<li><a href="#toc_2">Title2</a></li>
1524</ul>
1525
1526</nav>
1527
1528<h1 id="toc_0">Title</h1>
1529
1530<h2 id="toc_1">Subtitle</h2>
1531
1532<h1 id="toc_2">Title2</h1>
1533`,
1534
1535		"## Subtitle\n\n# Title",
1536		`<nav>
1537
1538<ul>
1539<li>
1540<ul>
1541<li><a href="#toc_0">Subtitle</a></li>
1542</ul></li>
1543
1544<li><a href="#toc_1">Title</a></li>
1545</ul>
1546
1547</nav>
1548
1549<h2 id="toc_0">Subtitle</h2>
1550
1551<h1 id="toc_1">Title</h1>
1552`,
1553
1554		"# Title 1\n\n## Subtitle 1\n\n### Subsubtitle 1\n\n# Title 2\n\n### Subsubtitle 2",
1555		`<nav>
1556
1557<ul>
1558<li><a href="#toc_0">Title 1</a>
1559<ul>
1560<li><a href="#toc_1">Subtitle 1</a>
1561<ul>
1562<li><a href="#toc_2">Subsubtitle 1</a></li>
1563</ul></li>
1564</ul></li>
1565
1566<li><a href="#toc_3">Title 2</a>
1567<ul>
1568<li>
1569<ul>
1570<li><a href="#toc_4">Subsubtitle 2</a></li>
1571</ul></li>
1572</ul></li>
1573</ul>
1574
1575</nav>
1576
1577<h1 id="toc_0">Title 1</h1>
1578
1579<h2 id="toc_1">Subtitle 1</h2>
1580
1581<h3 id="toc_2">Subsubtitle 1</h3>
1582
1583<h1 id="toc_3">Title 2</h1>
1584
1585<h3 id="toc_4">Subsubtitle 2</h3>
1586`,
1587
1588		"# Title with `code`",
1589		`<nav>
1590
1591<ul>
1592<li><a href="#toc_0">Title with <code>code</code></a></li>
1593</ul>
1594
1595</nav>
1596
1597<h1 id="toc_0">Title with <code>code</code></h1>
1598`,
1599
1600		// Trigger empty TOC
1601		"#",
1602		"",
1603	}
1604	doTestsParam(t, tests, TestParams{
1605		HTMLFlags: UseXHTML | TOC,
1606	})
1607}
1608
1609func TestOmitContents(t *testing.T) {
1610	var tests = []string{
1611		"# Title\n\n##Subtitle\n\n#Title2",
1612		`<nav>
1613
1614<ul>
1615<li><a href="#toc_0">Title</a>
1616<ul>
1617<li><a href="#toc_1">Subtitle</a></li>
1618</ul></li>
1619
1620<li><a href="#toc_2">Title2</a></li>
1621</ul>
1622
1623</nav>
1624`,
1625
1626		// Make sure OmitContents omits even with no TOC
1627		"#\n\nfoo",
1628		"",
1629	}
1630	doTestsParam(t, tests, TestParams{
1631		HTMLFlags: UseXHTML | TOC | OmitContents,
1632	})
1633	// Now run again: make sure OmitContents implies TOC
1634	doTestsParam(t, tests, TestParams{
1635		HTMLFlags: UseXHTML | OmitContents,
1636	})
1637}
1638
1639func TestCompletePage(t *testing.T) {
1640	var tests = []string{
1641		"*foo*",
1642		`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1643<html xmlns="http://www.w3.org/1999/xhtml">
1644<head>
1645  <title></title>
1646  <meta name="GENERATOR" content="Blackfriday Markdown Processor v2.0" />
1647  <meta charset="utf-8" />
1648</head>
1649<body>
1650
1651<p><em>foo</em></p>
1652
1653</body>
1654</html>
1655`,
1656	}
1657	doTestsParam(t, tests, TestParams{HTMLFlags: UseXHTML | CompletePage})
1658}
1659
1660func TestIsFenceLine(t *testing.T) {
1661	tests := []struct {
1662		data            []byte
1663		syntaxRequested bool
1664		newlineOptional bool
1665		wantEnd         int
1666		wantMarker      string
1667		wantSyntax      string
1668	}{
1669		{
1670			data:    []byte("```"),
1671			wantEnd: 0,
1672		},
1673		{
1674			data:       []byte("```\nstuff here\n"),
1675			wantEnd:    4,
1676			wantMarker: "```",
1677		},
1678		{
1679			data:            []byte("```\nstuff here\n"),
1680			syntaxRequested: true,
1681			wantEnd:         4,
1682			wantMarker:      "```",
1683		},
1684		{
1685			data:    []byte("stuff here\n```\n"),
1686			wantEnd: 0,
1687		},
1688		{
1689			data:            []byte("```"),
1690			newlineOptional: true,
1691			wantEnd:         3,
1692			wantMarker:      "```",
1693		},
1694		{
1695			data:            []byte("```"),
1696			syntaxRequested: true,
1697			newlineOptional: true,
1698			wantEnd:         3,
1699			wantMarker:      "```",
1700		},
1701		{
1702			data:            []byte("``` go"),
1703			syntaxRequested: true,
1704			newlineOptional: true,
1705			wantEnd:         6,
1706			wantMarker:      "```",
1707			wantSyntax:      "go",
1708		},
1709	}
1710
1711	for _, test := range tests {
1712		var syntax *string
1713		if test.syntaxRequested {
1714			syntax = new(string)
1715		}
1716		end, marker := isFenceLine(test.data, syntax, "```", test.newlineOptional)
1717		if got, want := end, test.wantEnd; got != want {
1718			t.Errorf("got end %v, want %v", got, want)
1719		}
1720		if got, want := marker, test.wantMarker; got != want {
1721			t.Errorf("got marker %q, want %q", got, want)
1722		}
1723		if test.syntaxRequested {
1724			if got, want := *syntax, test.wantSyntax; got != want {
1725				t.Errorf("got syntax %q, want %q", got, want)
1726			}
1727		}
1728	}
1729}