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