all repos — grayfriday @ 510be64de022c25096c6f476b7b7c240a8eca1a5

blackfriday fork with a few changes

block_test.go (view raw)

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