1""" 2Python Markdown 3 4A Python implementation of John Gruber's Markdown. 5 6Documentation: https://python-markdown.github.io/ 7GitHub: https://github.com/Python-Markdown/markdown/ 8PyPI: https://pypi.org/project/Markdown/ 9 10Started by Manfred Stienstra (http://www.dwerg.net/). 11Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org). 12Currently maintained by Waylan Limberg (https://github.com/waylan), 13Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser). 14 15Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later) 16Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) 17Copyright 2004 Manfred Stienstra (the original version) 18 19License: BSD (see LICENSE.md for details). 20""" 21 22import unittest 23from markdown.test_tools import TestCase 24 25 26class TestSetextHeaders(TestCase): 27 28 def test_setext_h1(self): 29 self.assertMarkdownRenders( 30 self.dedent( 31 """ 32 This is an H1 33 ============= 34 """ 35 ), 36 37 '<h1>This is an H1</h1>' 38 ) 39 40 def test_setext_h2(self): 41 self.assertMarkdownRenders( 42 self.dedent( 43 """ 44 This is an H2 45 ------------- 46 """ 47 ), 48 49 '<h2>This is an H2</h2>' 50 ) 51 52 def test_setext_h1_mismatched_length(self): 53 self.assertMarkdownRenders( 54 self.dedent( 55 """ 56 This is an H1 57 === 58 """ 59 ), 60 61 '<h1>This is an H1</h1>' 62 ) 63 64 def test_setext_h2_mismatched_length(self): 65 self.assertMarkdownRenders( 66 self.dedent( 67 """ 68 This is an H2 69 --- 70 """ 71 ), 72 73 '<h2>This is an H2</h2>' 74 ) 75 76 def test_setext_h1_followed_by_p(self): 77 self.assertMarkdownRenders( 78 self.dedent( 79 """ 80 This is an H1 81 ============= 82 Followed by a Paragraph with no blank line. 83 """ 84 ), 85 self.dedent( 86 """ 87 <h1>This is an H1</h1> 88 <p>Followed by a Paragraph with no blank line.</p> 89 """ 90 ) 91 ) 92 93 def test_setext_h2_followed_by_p(self): 94 self.assertMarkdownRenders( 95 self.dedent( 96 """ 97 This is an H2 98 ------------- 99 Followed by a Paragraph with no blank line. 100 """ 101 ), 102 self.dedent( 103 """ 104 <h2>This is an H2</h2> 105 <p>Followed by a Paragraph with no blank line.</p> 106 """ 107 ) 108 ) 109 110 # TODO: fix this 111 # see https://johnmacfarlane.net/babelmark2/?normalize=1&text=Paragraph%0AAn+H1%0A%3D%3D%3D%3D%3D 112 @unittest.skip('This is broken in Python-Markdown') 113 def test_p_followed_by_setext_h1(self): 114 self.assertMarkdownRenders( 115 self.dedent( 116 """ 117 This is a Paragraph. 118 Followed by an H1 with no blank line. 119 ===================================== 120 """ 121 ), 122 self.dedent( 123 """ 124 <p>This is a Paragraph.</p> 125 <h1>Followed by an H1 with no blank line.</h1> 126 """ 127 ) 128 ) 129 130 # TODO: fix this 131 # see https://johnmacfarlane.net/babelmark2/?normalize=1&text=Paragraph%0AAn+H2%0A----- 132 @unittest.skip('This is broken in Python-Markdown') 133 def test_p_followed_by_setext_h2(self): 134 self.assertMarkdownRenders( 135 self.dedent( 136 """ 137 This is a Paragraph. 138 Followed by an H2 with no blank line. 139 ------------------------------------- 140 """ 141 ), 142 self.dedent( 143 """ 144 <p>This is a Paragraph.</p> 145 <h2>Followed by an H2 with no blank line.</h2> 146 """ 147 ) 148 ) 149 150 151class TestHashHeaders(TestCase): 152 153 def test_hash_h1_open(self): 154 self.assertMarkdownRenders( 155 '# This is an H1', 156 157 '<h1>This is an H1</h1>' 158 ) 159 160 def test_hash_h2_open(self): 161 self.assertMarkdownRenders( 162 '## This is an H2', 163 164 '<h2>This is an H2</h2>' 165 ) 166 167 def test_hash_h3_open(self): 168 self.assertMarkdownRenders( 169 '### This is an H3', 170 171 '<h3>This is an H3</h3>' 172 ) 173 174 def test_hash_h4_open(self): 175 self.assertMarkdownRenders( 176 '#### This is an H4', 177 178 '<h4>This is an H4</h4>' 179 ) 180 181 def test_hash_h5_open(self): 182 self.assertMarkdownRenders( 183 '##### This is an H5', 184 185 '<h5>This is an H5</h5>' 186 ) 187 188 def test_hash_h6_open(self): 189 self.assertMarkdownRenders( 190 '###### This is an H6', 191 192 '<h6>This is an H6</h6>' 193 ) 194 195 def test_hash_gt6_open(self): 196 self.assertMarkdownRenders( 197 '####### This is an H6', 198 199 '<h6># This is an H6</h6>' 200 ) 201 202 def test_hash_h1_open_missing_space(self): 203 self.assertMarkdownRenders( 204 '#This is an H1', 205 206 '<h1>This is an H1</h1>' 207 ) 208 209 def test_hash_h2_open_missing_space(self): 210 self.assertMarkdownRenders( 211 '##This is an H2', 212 213 '<h2>This is an H2</h2>' 214 ) 215 216 def test_hash_h3_open_missing_space(self): 217 self.assertMarkdownRenders( 218 '###This is an H3', 219 220 '<h3>This is an H3</h3>' 221 ) 222 223 def test_hash_h4_open_missing_space(self): 224 self.assertMarkdownRenders( 225 '####This is an H4', 226 227 '<h4>This is an H4</h4>' 228 ) 229 230 def test_hash_h5_open_missing_space(self): 231 self.assertMarkdownRenders( 232 '#####This is an H5', 233 234 '<h5>This is an H5</h5>' 235 ) 236 237 def test_hash_h6_open_missing_space(self): 238 self.assertMarkdownRenders( 239 '######This is an H6', 240 241 '<h6>This is an H6</h6>' 242 ) 243 244 def test_hash_gt6_open_missing_space(self): 245 self.assertMarkdownRenders( 246 '#######This is an H6', 247 248 '<h6>#This is an H6</h6>' 249 ) 250 251 def test_hash_h1_closed(self): 252 self.assertMarkdownRenders( 253 '# This is an H1 #', 254 255 '<h1>This is an H1</h1>' 256 ) 257 258 def test_hash_h2_closed(self): 259 self.assertMarkdownRenders( 260 '## This is an H2 ##', 261 262 '<h2>This is an H2</h2>' 263 ) 264 265 def test_hash_h3_closed(self): 266 self.assertMarkdownRenders( 267 '### This is an H3 ###', 268 269 '<h3>This is an H3</h3>' 270 ) 271 272 def test_hash_h4_closed(self): 273 self.assertMarkdownRenders( 274 '#### This is an H4 ####', 275 276 '<h4>This is an H4</h4>' 277 ) 278 279 def test_hash_h5_closed(self): 280 self.assertMarkdownRenders( 281 '##### This is an H5 #####', 282 283 '<h5>This is an H5</h5>' 284 ) 285 286 def test_hash_h6_closed(self): 287 self.assertMarkdownRenders( 288 '###### This is an H6 ######', 289 290 '<h6>This is an H6</h6>' 291 ) 292 293 def test_hash_gt6_closed(self): 294 self.assertMarkdownRenders( 295 '####### This is an H6 #######', 296 297 '<h6># This is an H6</h6>' 298 ) 299 300 def test_hash_h1_closed_missing_space(self): 301 self.assertMarkdownRenders( 302 '#This is an H1#', 303 304 '<h1>This is an H1</h1>' 305 ) 306 307 def test_hash_h2_closed_missing_space(self): 308 self.assertMarkdownRenders( 309 '##This is an H2##', 310 311 '<h2>This is an H2</h2>' 312 ) 313 314 def test_hash_h3_closed_missing_space(self): 315 self.assertMarkdownRenders( 316 '###This is an H3###', 317 318 '<h3>This is an H3</h3>' 319 ) 320 321 def test_hash_h4_closed_missing_space(self): 322 self.assertMarkdownRenders( 323 '####This is an H4####', 324 325 '<h4>This is an H4</h4>' 326 ) 327 328 def test_hash_h5_closed_missing_space(self): 329 self.assertMarkdownRenders( 330 '#####This is an H5#####', 331 332 '<h5>This is an H5</h5>' 333 ) 334 335 def test_hash_h6_closed_missing_space(self): 336 self.assertMarkdownRenders( 337 '######This is an H6######', 338 339 '<h6>This is an H6</h6>' 340 ) 341 342 def test_hash_gt6_closed_missing_space(self): 343 self.assertMarkdownRenders( 344 '#######This is an H6#######', 345 346 '<h6>#This is an H6</h6>' 347 ) 348 349 def test_hash_h1_closed_mismatch(self): 350 self.assertMarkdownRenders( 351 '# This is an H1 ##', 352 353 '<h1>This is an H1</h1>' 354 ) 355 356 def test_hash_h2_closed_mismatch(self): 357 self.assertMarkdownRenders( 358 '## This is an H2 #', 359 360 '<h2>This is an H2</h2>' 361 ) 362 363 def test_hash_h3_closed_mismatch(self): 364 self.assertMarkdownRenders( 365 '### This is an H3 #', 366 367 '<h3>This is an H3</h3>' 368 ) 369 370 def test_hash_h4_closed_mismatch(self): 371 self.assertMarkdownRenders( 372 '#### This is an H4 #', 373 374 '<h4>This is an H4</h4>' 375 ) 376 377 def test_hash_h5_closed_mismatch(self): 378 self.assertMarkdownRenders( 379 '##### This is an H5 #', 380 381 '<h5>This is an H5</h5>' 382 ) 383 384 def test_hash_h6_closed_mismatch(self): 385 self.assertMarkdownRenders( 386 '###### This is an H6 #', 387 388 '<h6>This is an H6</h6>' 389 ) 390 391 def test_hash_gt6_closed_mismatch(self): 392 self.assertMarkdownRenders( 393 '####### This is an H6 ##################', 394 395 '<h6># This is an H6</h6>' 396 ) 397 398 def test_hash_h1_followed_by_p(self): 399 self.assertMarkdownRenders( 400 self.dedent( 401 """ 402 # This is an H1 403 Followed by a Paragraph with no blank line. 404 """ 405 ), 406 self.dedent( 407 """ 408 <h1>This is an H1</h1> 409 <p>Followed by a Paragraph with no blank line.</p> 410 """ 411 ) 412 ) 413 414 def test_hash_h2_followed_by_p(self): 415 self.assertMarkdownRenders( 416 self.dedent( 417 """ 418 ## This is an H2 419 Followed by a Paragraph with no blank line. 420 """ 421 ), 422 self.dedent( 423 """ 424 <h2>This is an H2</h2> 425 <p>Followed by a Paragraph with no blank line.</p> 426 """ 427 ) 428 ) 429 430 def test_hash_h3_followed_by_p(self): 431 self.assertMarkdownRenders( 432 self.dedent( 433 """ 434 ### This is an H3 435 Followed by a Paragraph with no blank line. 436 """ 437 ), 438 self.dedent( 439 """ 440 <h3>This is an H3</h3> 441 <p>Followed by a Paragraph with no blank line.</p> 442 """ 443 ) 444 ) 445 446 def test_hash_h4_followed_by_p(self): 447 self.assertMarkdownRenders( 448 self.dedent( 449 """ 450 #### This is an H4 451 Followed by a Paragraph with no blank line. 452 """ 453 ), 454 self.dedent( 455 """ 456 <h4>This is an H4</h4> 457 <p>Followed by a Paragraph with no blank line.</p> 458 """ 459 ) 460 ) 461 462 def test_hash_h5_followed_by_p(self): 463 self.assertMarkdownRenders( 464 self.dedent( 465 """ 466 ##### This is an H5 467 Followed by a Paragraph with no blank line. 468 """ 469 ), 470 self.dedent( 471 """ 472 <h5>This is an H5</h5> 473 <p>Followed by a Paragraph with no blank line.</p> 474 """ 475 ) 476 ) 477 478 def test_hash_h6_followed_by_p(self): 479 self.assertMarkdownRenders( 480 self.dedent( 481 """ 482 ###### This is an H6 483 Followed by a Paragraph with no blank line. 484 """ 485 ), 486 self.dedent( 487 """ 488 <h6>This is an H6</h6> 489 <p>Followed by a Paragraph with no blank line.</p> 490 """ 491 ) 492 ) 493 494 def test_hash_h1_leading_space(self): 495 self.assertMarkdownRenders( 496 ' # This is an H1', 497 498 '<p># This is an H1</p>' 499 ) 500 501 def test_hash_h2_leading_space(self): 502 self.assertMarkdownRenders( 503 ' ## This is an H2', 504 505 '<p>## This is an H2</p>' 506 ) 507 508 def test_hash_h3_leading_space(self): 509 self.assertMarkdownRenders( 510 ' ### This is an H3', 511 512 '<p>### This is an H3</p>' 513 ) 514 515 def test_hash_h4_leading_space(self): 516 self.assertMarkdownRenders( 517 ' #### This is an H4', 518 519 '<p>#### This is an H4</p>' 520 ) 521 522 def test_hash_h5_leading_space(self): 523 self.assertMarkdownRenders( 524 ' ##### This is an H5', 525 526 '<p>##### This is an H5</p>' 527 ) 528 529 def test_hash_h6_leading_space(self): 530 self.assertMarkdownRenders( 531 ' ###### This is an H6', 532 533 '<p>###### This is an H6</p>' 534 ) 535 536 def test_hash_h1_open_trailing_space(self): 537 self.assertMarkdownRenders( 538 '# This is an H1 ', 539 540 '<h1>This is an H1</h1>' 541 ) 542 543 def test_hash_h2_open_trailing_space(self): 544 self.assertMarkdownRenders( 545 '## This is an H2 ', 546 547 '<h2>This is an H2</h2>' 548 ) 549 550 def test_hash_h3_open_trailing_space(self): 551 self.assertMarkdownRenders( 552 '### This is an H3 ', 553 554 '<h3>This is an H3</h3>' 555 ) 556 557 def test_hash_h4_open_trailing_space(self): 558 self.assertMarkdownRenders( 559 '#### This is an H4 ', 560 561 '<h4>This is an H4</h4>' 562 ) 563 564 def test_hash_h5_open_trailing_space(self): 565 self.assertMarkdownRenders( 566 '##### This is an H5 ', 567 568 '<h5>This is an H5</h5>' 569 ) 570 571 def test_hash_h6_open_trailing_space(self): 572 self.assertMarkdownRenders( 573 '###### This is an H6 ', 574 575 '<h6>This is an H6</h6>' 576 ) 577 578 def test_hash_gt6_open_trailing_space(self): 579 self.assertMarkdownRenders( 580 '####### This is an H6 ', 581 582 '<h6># This is an H6</h6>' 583 ) 584 585 # TODO: Possibly change the following behavior. While this follows the behavior 586 # of markdown.pl, it is rather uncommon and not nessecarily intuitive. 587 # See: https://johnmacfarlane.net/babelmark2/?normalize=1&text=%23+This+is+an+H1+%23+ 588 def test_hash_h1_closed_trailing_space(self): 589 self.assertMarkdownRenders( 590 '# This is an H1 # ', 591 592 '<h1>This is an H1 #</h1>' 593 ) 594 595 def test_hash_h2_closed_trailing_space(self): 596 self.assertMarkdownRenders( 597 '## This is an H2 ## ', 598 599 '<h2>This is an H2 ##</h2>' 600 ) 601 602 def test_hash_h3_closed_trailing_space(self): 603 self.assertMarkdownRenders( 604 '### This is an H3 ### ', 605 606 '<h3>This is an H3 ###</h3>' 607 ) 608 609 def test_hash_h4_closed_trailing_space(self): 610 self.assertMarkdownRenders( 611 '#### This is an H4 #### ', 612 613 '<h4>This is an H4 ####</h4>' 614 ) 615 616 def test_hash_h5_closed_trailing_space(self): 617 self.assertMarkdownRenders( 618 '##### This is an H5 ##### ', 619 620 '<h5>This is an H5 #####</h5>' 621 ) 622 623 def test_hash_h6_closed_trailing_space(self): 624 self.assertMarkdownRenders( 625 '###### This is an H6 ###### ', 626 627 '<h6>This is an H6 ######</h6>' 628 ) 629 630 def test_hash_gt6_closed_trailing_space(self): 631 self.assertMarkdownRenders( 632 '####### This is an H6 ####### ', 633 634 '<h6># This is an H6 #######</h6>' 635 ) 636 637 def test_no_blank_lines_between_hashs(self): 638 self.assertMarkdownRenders( 639 self.dedent( 640 """ 641 # This is an H1 642 ## This is an H2 643 """ 644 ), 645 self.dedent( 646 """ 647 <h1>This is an H1</h1> 648 <h2>This is an H2</h2> 649 """ 650 ) 651 ) 652 653 def test_random_hash_levels(self): 654 self.assertMarkdownRenders( 655 self.dedent( 656 """ 657 ### H3 658 ###### H6 659 # H1 660 ##### H5 661 #### H4 662 ## H2 663 ### H3 664 """ 665 ), 666 self.dedent( 667 """ 668 <h3>H3</h3> 669 <h6>H6</h6> 670 <h1>H1</h1> 671 <h5>H5</h5> 672 <h4>H4</h4> 673 <h2>H2</h2> 674 <h3>H3</h3> 675 """ 676 ) 677 ) 678 679 def test_hash_followed_by_p(self): 680 self.assertMarkdownRenders( 681 self.dedent( 682 """ 683 # This is an H1 684 Followed by a Paragraph with no blank line. 685 """ 686 ), 687 self.dedent( 688 """ 689 <h1>This is an H1</h1> 690 <p>Followed by a Paragraph with no blank line.</p> 691 """ 692 ) 693 ) 694 695 def test_p_followed_by_hash(self): 696 self.assertMarkdownRenders( 697 self.dedent( 698 """ 699 This is a Paragraph. 700 # Followed by an H1 with no blank line. 701 """ 702 ), 703 self.dedent( 704 """ 705 <p>This is a Paragraph.</p> 706 <h1>Followed by an H1 with no blank line.</h1> 707 """ 708 ) 709 ) 710 711 def test_escaped_hash(self): 712 self.assertMarkdownRenders( 713 "### H3 \\###", 714 self.dedent( 715 """ 716 <h3>H3 #</h3> 717 """ 718 ) 719 ) 720 721 def test_unescaped_hash(self): 722 self.assertMarkdownRenders( 723 "### H3 \\\\###", 724 self.dedent( 725 """ 726 <h3>H3 \\</h3> 727 """ 728 ) 729 ) 730