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