all repos — grayfriday @ 412ca19665064fba55ff7624ba5bcab9afdfb4d0

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