aboutsummaryrefslogtreecommitdiff
path: root/tests/test_syntax/blocks
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_syntax/blocks')
-rw-r--r--tests/test_syntax/blocks/__init__.py20
-rw-r--r--tests/test_syntax/blocks/test_blockquotes.py51
-rw-r--r--tests/test_syntax/blocks/test_code_blocks.py88
-rw-r--r--tests/test_syntax/blocks/test_headers.py729
-rw-r--r--tests/test_syntax/blocks/test_hr.py402
-rw-r--r--tests/test_syntax/blocks/test_html_blocks.py1619
-rw-r--r--tests/test_syntax/blocks/test_paragraphs.py229
7 files changed, 3138 insertions, 0 deletions
diff --git a/tests/test_syntax/blocks/__init__.py b/tests/test_syntax/blocks/__init__.py
new file mode 100644
index 0000000..564ba3b
--- /dev/null
+++ b/tests/test_syntax/blocks/__init__.py
@@ -0,0 +1,20 @@
+"""
+Python Markdown
+
+A Python implementation of John Gruber's Markdown.
+
+Documentation: https://python-markdown.github.io/
+GitHub: https://github.com/Python-Markdown/markdown/
+PyPI: https://pypi.org/project/Markdown/
+
+Started by Manfred Stienstra (http://www.dwerg.net/).
+Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
+Currently maintained by Waylan Limberg (https://github.com/waylan),
+Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
+
+Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see LICENSE.md for details).
+"""
diff --git a/tests/test_syntax/blocks/test_blockquotes.py b/tests/test_syntax/blocks/test_blockquotes.py
new file mode 100644
index 0000000..3422f9f
--- /dev/null
+++ b/tests/test_syntax/blocks/test_blockquotes.py
@@ -0,0 +1,51 @@
+"""
+Python Markdown
+
+A Python implementation of John Gruber's Markdown.
+
+Documentation: https://python-markdown.github.io/
+GitHub: https://github.com/Python-Markdown/markdown/
+PyPI: https://pypi.org/project/Markdown/
+
+Started by Manfred Stienstra (http://www.dwerg.net/).
+Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
+Currently maintained by Waylan Limberg (https://github.com/waylan),
+Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
+
+Copyright 2007-2020 The Python Markdown Project (v. 1.7 and later)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see LICENSE.md for details).
+"""
+
+from markdown.test_tools import TestCase, recursionlimit
+
+
+class TestBlockquoteBlocks(TestCase):
+
+ # TODO: Move legacy tests here
+
+ def test_nesting_limit(self):
+ # Test that the nesting limit is within 100 levels of recursion limit. Future code changes could cause the
+ # recursion limit to need adjusted here. We need to account for all of Markdown's internal calls. Finally, we
+ # need to account for the 100 level cushion which we are testing.
+ with recursionlimit(120):
+ self.assertMarkdownRenders(
+ '>>>>>>>>>>',
+ self.dedent(
+ """
+ <blockquote>
+ <blockquote>
+ <blockquote>
+ <blockquote>
+ <blockquote>
+ <p>&gt;&gt;&gt;&gt;&gt;</p>
+ </blockquote>
+ </blockquote>
+ </blockquote>
+ </blockquote>
+ </blockquote>
+ """
+ )
+ )
diff --git a/tests/test_syntax/blocks/test_code_blocks.py b/tests/test_syntax/blocks/test_code_blocks.py
new file mode 100644
index 0000000..54b6860
--- /dev/null
+++ b/tests/test_syntax/blocks/test_code_blocks.py
@@ -0,0 +1,88 @@
+"""
+Python Markdown
+
+A Python implementation of John Gruber's Markdown.
+
+Documentation: https://python-markdown.github.io/
+GitHub: https://github.com/Python-Markdown/markdown/
+PyPI: https://pypi.org/project/Markdown/
+
+Started by Manfred Stienstra (http://www.dwerg.net/).
+Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
+Currently maintained by Waylan Limberg (https://github.com/waylan),
+Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
+
+Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see LICENSE.md for details).
+"""
+
+from markdown.test_tools import TestCase
+
+
+class TestCodeBlocks(TestCase):
+
+ def test_spaced_codeblock(self):
+ self.assertMarkdownRenders(
+ ' # A code block.',
+
+ self.dedent(
+ """
+ <pre><code># A code block.
+ </code></pre>
+ """
+ )
+ )
+
+ def test_tabbed_codeblock(self):
+ self.assertMarkdownRenders(
+ '\t# A code block.',
+
+ self.dedent(
+ """
+ <pre><code># A code block.
+ </code></pre>
+ """
+ )
+ )
+
+ def test_multiline_codeblock(self):
+ self.assertMarkdownRenders(
+ ' # Line 1\n # Line 2\n',
+
+ self.dedent(
+ """
+ <pre><code># Line 1
+ # Line 2
+ </code></pre>
+ """
+ )
+ )
+
+ def test_codeblock_with_blankline(self):
+ self.assertMarkdownRenders(
+ ' # Line 1\n\n # Line 2\n',
+
+ self.dedent(
+ """
+ <pre><code># Line 1
+
+ # Line 2
+ </code></pre>
+ """
+ )
+ )
+
+ def test_codeblock_escape(self):
+ self.assertMarkdownRenders(
+ ' <foo & bar>',
+
+ self.dedent(
+ """
+ <pre><code>&lt;foo &amp; bar&gt;
+ </code></pre>
+ """
+ )
+ )
diff --git a/tests/test_syntax/blocks/test_headers.py b/tests/test_syntax/blocks/test_headers.py
new file mode 100644
index 0000000..ca065a5
--- /dev/null
+++ b/tests/test_syntax/blocks/test_headers.py
@@ -0,0 +1,729 @@
+"""
+Python Markdown
+
+A Python implementation of John Gruber's Markdown.
+
+Documentation: https://python-markdown.github.io/
+GitHub: https://github.com/Python-Markdown/markdown/
+PyPI: https://pypi.org/project/Markdown/
+
+Started by Manfred Stienstra (http://www.dwerg.net/).
+Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
+Currently maintained by Waylan Limberg (https://github.com/waylan),
+Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
+
+Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see LICENSE.md for details).
+"""
+
+import unittest
+from markdown.test_tools import TestCase
+
+
+class TestSetextHeaders(TestCase):
+
+ def test_setext_h1(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is an H1
+ =============
+ """
+ ),
+
+ '<h1>This is an H1</h1>'
+ )
+
+ def test_setext_h2(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is an H2
+ -------------
+ """
+ ),
+
+ '<h2>This is an H2</h2>'
+ )
+
+ def test_setext_h1_mismatched_length(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is an H1
+ ===
+ """
+ ),
+
+ '<h1>This is an H1</h1>'
+ )
+
+ def test_setext_h2_mismatched_length(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is an H2
+ ---
+ """
+ ),
+
+ '<h2>This is an H2</h2>'
+ )
+
+ def test_setext_h1_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is an H1
+ =============
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h1>This is an H1</h1>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_setext_h2_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is an H2
+ -------------
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h2>This is an H2</h2>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ # TODO: fix this
+ # see https://johnmacfarlane.net/babelmark2/?normalize=1&text=Paragraph%0AAn+H1%0A%3D%3D%3D%3D%3D
+ @unittest.skip('This is broken in Python-Markdown')
+ def test_p_followed_by_setext_h1(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is a Paragraph.
+ Followed by an H1 with no blank line.
+ =====================================
+ """
+ ),
+ self.dedent(
+ """
+ <p>This is a Paragraph.</p>
+ <h1>Followed by an H1 with no blank line.</h1>
+ """
+ )
+ )
+
+ # TODO: fix this
+ # see https://johnmacfarlane.net/babelmark2/?normalize=1&text=Paragraph%0AAn+H2%0A-----
+ @unittest.skip('This is broken in Python-Markdown')
+ def test_p_followed_by_setext_h2(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is a Paragraph.
+ Followed by an H2 with no blank line.
+ -------------------------------------
+ """
+ ),
+ self.dedent(
+ """
+ <p>This is a Paragraph.</p>
+ <h2>Followed by an H2 with no blank line.</h2>
+ """
+ )
+ )
+
+
+class TestHashHeaders(TestCase):
+
+ def test_hash_h1_open(self):
+ self.assertMarkdownRenders(
+ '# This is an H1',
+
+ '<h1>This is an H1</h1>'
+ )
+
+ def test_hash_h2_open(self):
+ self.assertMarkdownRenders(
+ '## This is an H2',
+
+ '<h2>This is an H2</h2>'
+ )
+
+ def test_hash_h3_open(self):
+ self.assertMarkdownRenders(
+ '### This is an H3',
+
+ '<h3>This is an H3</h3>'
+ )
+
+ def test_hash_h4_open(self):
+ self.assertMarkdownRenders(
+ '#### This is an H4',
+
+ '<h4>This is an H4</h4>'
+ )
+
+ def test_hash_h5_open(self):
+ self.assertMarkdownRenders(
+ '##### This is an H5',
+
+ '<h5>This is an H5</h5>'
+ )
+
+ def test_hash_h6_open(self):
+ self.assertMarkdownRenders(
+ '###### This is an H6',
+
+ '<h6>This is an H6</h6>'
+ )
+
+ def test_hash_gt6_open(self):
+ self.assertMarkdownRenders(
+ '####### This is an H6',
+
+ '<h6># This is an H6</h6>'
+ )
+
+ def test_hash_h1_open_missing_space(self):
+ self.assertMarkdownRenders(
+ '#This is an H1',
+
+ '<h1>This is an H1</h1>'
+ )
+
+ def test_hash_h2_open_missing_space(self):
+ self.assertMarkdownRenders(
+ '##This is an H2',
+
+ '<h2>This is an H2</h2>'
+ )
+
+ def test_hash_h3_open_missing_space(self):
+ self.assertMarkdownRenders(
+ '###This is an H3',
+
+ '<h3>This is an H3</h3>'
+ )
+
+ def test_hash_h4_open_missing_space(self):
+ self.assertMarkdownRenders(
+ '####This is an H4',
+
+ '<h4>This is an H4</h4>'
+ )
+
+ def test_hash_h5_open_missing_space(self):
+ self.assertMarkdownRenders(
+ '#####This is an H5',
+
+ '<h5>This is an H5</h5>'
+ )
+
+ def test_hash_h6_open_missing_space(self):
+ self.assertMarkdownRenders(
+ '######This is an H6',
+
+ '<h6>This is an H6</h6>'
+ )
+
+ def test_hash_gt6_open_missing_space(self):
+ self.assertMarkdownRenders(
+ '#######This is an H6',
+
+ '<h6>#This is an H6</h6>'
+ )
+
+ def test_hash_h1_closed(self):
+ self.assertMarkdownRenders(
+ '# This is an H1 #',
+
+ '<h1>This is an H1</h1>'
+ )
+
+ def test_hash_h2_closed(self):
+ self.assertMarkdownRenders(
+ '## This is an H2 ##',
+
+ '<h2>This is an H2</h2>'
+ )
+
+ def test_hash_h3_closed(self):
+ self.assertMarkdownRenders(
+ '### This is an H3 ###',
+
+ '<h3>This is an H3</h3>'
+ )
+
+ def test_hash_h4_closed(self):
+ self.assertMarkdownRenders(
+ '#### This is an H4 ####',
+
+ '<h4>This is an H4</h4>'
+ )
+
+ def test_hash_h5_closed(self):
+ self.assertMarkdownRenders(
+ '##### This is an H5 #####',
+
+ '<h5>This is an H5</h5>'
+ )
+
+ def test_hash_h6_closed(self):
+ self.assertMarkdownRenders(
+ '###### This is an H6 ######',
+
+ '<h6>This is an H6</h6>'
+ )
+
+ def test_hash_gt6_closed(self):
+ self.assertMarkdownRenders(
+ '####### This is an H6 #######',
+
+ '<h6># This is an H6</h6>'
+ )
+
+ def test_hash_h1_closed_missing_space(self):
+ self.assertMarkdownRenders(
+ '#This is an H1#',
+
+ '<h1>This is an H1</h1>'
+ )
+
+ def test_hash_h2_closed_missing_space(self):
+ self.assertMarkdownRenders(
+ '##This is an H2##',
+
+ '<h2>This is an H2</h2>'
+ )
+
+ def test_hash_h3_closed_missing_space(self):
+ self.assertMarkdownRenders(
+ '###This is an H3###',
+
+ '<h3>This is an H3</h3>'
+ )
+
+ def test_hash_h4_closed_missing_space(self):
+ self.assertMarkdownRenders(
+ '####This is an H4####',
+
+ '<h4>This is an H4</h4>'
+ )
+
+ def test_hash_h5_closed_missing_space(self):
+ self.assertMarkdownRenders(
+ '#####This is an H5#####',
+
+ '<h5>This is an H5</h5>'
+ )
+
+ def test_hash_h6_closed_missing_space(self):
+ self.assertMarkdownRenders(
+ '######This is an H6######',
+
+ '<h6>This is an H6</h6>'
+ )
+
+ def test_hash_gt6_closed_missing_space(self):
+ self.assertMarkdownRenders(
+ '#######This is an H6#######',
+
+ '<h6>#This is an H6</h6>'
+ )
+
+ def test_hash_h1_closed_mismatch(self):
+ self.assertMarkdownRenders(
+ '# This is an H1 ##',
+
+ '<h1>This is an H1</h1>'
+ )
+
+ def test_hash_h2_closed_mismatch(self):
+ self.assertMarkdownRenders(
+ '## This is an H2 #',
+
+ '<h2>This is an H2</h2>'
+ )
+
+ def test_hash_h3_closed_mismatch(self):
+ self.assertMarkdownRenders(
+ '### This is an H3 #',
+
+ '<h3>This is an H3</h3>'
+ )
+
+ def test_hash_h4_closed_mismatch(self):
+ self.assertMarkdownRenders(
+ '#### This is an H4 #',
+
+ '<h4>This is an H4</h4>'
+ )
+
+ def test_hash_h5_closed_mismatch(self):
+ self.assertMarkdownRenders(
+ '##### This is an H5 #',
+
+ '<h5>This is an H5</h5>'
+ )
+
+ def test_hash_h6_closed_mismatch(self):
+ self.assertMarkdownRenders(
+ '###### This is an H6 #',
+
+ '<h6>This is an H6</h6>'
+ )
+
+ def test_hash_gt6_closed_mismatch(self):
+ self.assertMarkdownRenders(
+ '####### This is an H6 ##################',
+
+ '<h6># This is an H6</h6>'
+ )
+
+ def test_hash_h1_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ # This is an H1
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h1>This is an H1</h1>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_hash_h2_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ ## This is an H2
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h2>This is an H2</h2>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_hash_h3_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ ### This is an H3
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h3>This is an H3</h3>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_hash_h4_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ #### This is an H4
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h4>This is an H4</h4>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_hash_h5_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ ##### This is an H5
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h5>This is an H5</h5>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_hash_h6_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ ###### This is an H6
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h6>This is an H6</h6>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_hash_h1_leading_space(self):
+ self.assertMarkdownRenders(
+ ' # This is an H1',
+
+ '<p># This is an H1</p>'
+ )
+
+ def test_hash_h2_leading_space(self):
+ self.assertMarkdownRenders(
+ ' ## This is an H2',
+
+ '<p>## This is an H2</p>'
+ )
+
+ def test_hash_h3_leading_space(self):
+ self.assertMarkdownRenders(
+ ' ### This is an H3',
+
+ '<p>### This is an H3</p>'
+ )
+
+ def test_hash_h4_leading_space(self):
+ self.assertMarkdownRenders(
+ ' #### This is an H4',
+
+ '<p>#### This is an H4</p>'
+ )
+
+ def test_hash_h5_leading_space(self):
+ self.assertMarkdownRenders(
+ ' ##### This is an H5',
+
+ '<p>##### This is an H5</p>'
+ )
+
+ def test_hash_h6_leading_space(self):
+ self.assertMarkdownRenders(
+ ' ###### This is an H6',
+
+ '<p>###### This is an H6</p>'
+ )
+
+ def test_hash_h1_open_trailing_space(self):
+ self.assertMarkdownRenders(
+ '# This is an H1 ',
+
+ '<h1>This is an H1</h1>'
+ )
+
+ def test_hash_h2_open_trailing_space(self):
+ self.assertMarkdownRenders(
+ '## This is an H2 ',
+
+ '<h2>This is an H2</h2>'
+ )
+
+ def test_hash_h3_open_trailing_space(self):
+ self.assertMarkdownRenders(
+ '### This is an H3 ',
+
+ '<h3>This is an H3</h3>'
+ )
+
+ def test_hash_h4_open_trailing_space(self):
+ self.assertMarkdownRenders(
+ '#### This is an H4 ',
+
+ '<h4>This is an H4</h4>'
+ )
+
+ def test_hash_h5_open_trailing_space(self):
+ self.assertMarkdownRenders(
+ '##### This is an H5 ',
+
+ '<h5>This is an H5</h5>'
+ )
+
+ def test_hash_h6_open_trailing_space(self):
+ self.assertMarkdownRenders(
+ '###### This is an H6 ',
+
+ '<h6>This is an H6</h6>'
+ )
+
+ def test_hash_gt6_open_trailing_space(self):
+ self.assertMarkdownRenders(
+ '####### This is an H6 ',
+
+ '<h6># This is an H6</h6>'
+ )
+
+ # TODO: Possibly change the following behavior. While this follows the behavior
+ # of markdown.pl, it is rather uncommon and not necessarily intuitive.
+ # See: https://johnmacfarlane.net/babelmark2/?normalize=1&text=%23+This+is+an+H1+%23+
+ def test_hash_h1_closed_trailing_space(self):
+ self.assertMarkdownRenders(
+ '# This is an H1 # ',
+
+ '<h1>This is an H1 #</h1>'
+ )
+
+ def test_hash_h2_closed_trailing_space(self):
+ self.assertMarkdownRenders(
+ '## This is an H2 ## ',
+
+ '<h2>This is an H2 ##</h2>'
+ )
+
+ def test_hash_h3_closed_trailing_space(self):
+ self.assertMarkdownRenders(
+ '### This is an H3 ### ',
+
+ '<h3>This is an H3 ###</h3>'
+ )
+
+ def test_hash_h4_closed_trailing_space(self):
+ self.assertMarkdownRenders(
+ '#### This is an H4 #### ',
+
+ '<h4>This is an H4 ####</h4>'
+ )
+
+ def test_hash_h5_closed_trailing_space(self):
+ self.assertMarkdownRenders(
+ '##### This is an H5 ##### ',
+
+ '<h5>This is an H5 #####</h5>'
+ )
+
+ def test_hash_h6_closed_trailing_space(self):
+ self.assertMarkdownRenders(
+ '###### This is an H6 ###### ',
+
+ '<h6>This is an H6 ######</h6>'
+ )
+
+ def test_hash_gt6_closed_trailing_space(self):
+ self.assertMarkdownRenders(
+ '####### This is an H6 ####### ',
+
+ '<h6># This is an H6 #######</h6>'
+ )
+
+ def test_no_blank_lines_between_hashs(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ # This is an H1
+ ## This is an H2
+ """
+ ),
+ self.dedent(
+ """
+ <h1>This is an H1</h1>
+ <h2>This is an H2</h2>
+ """
+ )
+ )
+
+ def test_random_hash_levels(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ ### H3
+ ###### H6
+ # H1
+ ##### H5
+ #### H4
+ ## H2
+ ### H3
+ """
+ ),
+ self.dedent(
+ """
+ <h3>H3</h3>
+ <h6>H6</h6>
+ <h1>H1</h1>
+ <h5>H5</h5>
+ <h4>H4</h4>
+ <h2>H2</h2>
+ <h3>H3</h3>
+ """
+ )
+ )
+
+ def test_hash_followed_by_p(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ # This is an H1
+ Followed by a Paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <h1>This is an H1</h1>
+ <p>Followed by a Paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_p_followed_by_hash(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is a Paragraph.
+ # Followed by an H1 with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <p>This is a Paragraph.</p>
+ <h1>Followed by an H1 with no blank line.</h1>
+ """
+ )
+ )
+
+ def test_escaped_hash(self):
+ self.assertMarkdownRenders(
+ "### H3 \\###",
+ self.dedent(
+ """
+ <h3>H3 #</h3>
+ """
+ )
+ )
+
+ def test_unescaped_hash(self):
+ self.assertMarkdownRenders(
+ "### H3 \\\\###",
+ self.dedent(
+ """
+ <h3>H3 \\</h3>
+ """
+ )
+ )
diff --git a/tests/test_syntax/blocks/test_hr.py b/tests/test_syntax/blocks/test_hr.py
new file mode 100644
index 0000000..85a51b3
--- /dev/null
+++ b/tests/test_syntax/blocks/test_hr.py
@@ -0,0 +1,402 @@
+"""
+Python Markdown
+
+A Python implementation of John Gruber's Markdown.
+
+Documentation: https://python-markdown.github.io/
+GitHub: https://github.com/Python-Markdown/markdown/
+PyPI: https://pypi.org/project/Markdown/
+
+Started by Manfred Stienstra (http://www.dwerg.net/).
+Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
+Currently maintained by Waylan Limberg (https://github.com/waylan),
+Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
+
+Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see LICENSE.md for details).
+"""
+
+from markdown.test_tools import TestCase
+
+
+class TestHorizontalRules(TestCase):
+
+ def test_hr_asterisks(self):
+ self.assertMarkdownRenders(
+ '***',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_spaces(self):
+ self.assertMarkdownRenders(
+ '* * *',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_long(self):
+ self.assertMarkdownRenders(
+ '*******',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_spaces_long(self):
+ self.assertMarkdownRenders(
+ '* * * * * * *',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_1_indent(self):
+ self.assertMarkdownRenders(
+ ' ***',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_spaces_1_indent(self):
+ self.assertMarkdownRenders(
+ ' * * *',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_2_indent(self):
+ self.assertMarkdownRenders(
+ ' ***',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_spaces_2_indent(self):
+ self.assertMarkdownRenders(
+ ' * * *',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_3_indent(self):
+ self.assertMarkdownRenders(
+ ' ***',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_spaces_3_indent(self):
+ self.assertMarkdownRenders(
+ ' * * *',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_trailing_space(self):
+ self.assertMarkdownRenders(
+ '*** ',
+
+ '<hr />'
+ )
+
+ def test_hr_asterisks_spaces_trailing_space(self):
+ self.assertMarkdownRenders(
+ '* * * ',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens(self):
+ self.assertMarkdownRenders(
+ '---',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_spaces(self):
+ self.assertMarkdownRenders(
+ '- - -',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_long(self):
+ self.assertMarkdownRenders(
+ '-------',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_spaces_long(self):
+ self.assertMarkdownRenders(
+ '- - - - - - -',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_1_indent(self):
+ self.assertMarkdownRenders(
+ ' ---',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_spaces_1_indent(self):
+ self.assertMarkdownRenders(
+ ' - - -',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_2_indent(self):
+ self.assertMarkdownRenders(
+ ' ---',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_spaces_2_indent(self):
+ self.assertMarkdownRenders(
+ ' - - -',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_3_indent(self):
+ self.assertMarkdownRenders(
+ ' ---',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_spaces_3_indent(self):
+ self.assertMarkdownRenders(
+ ' - - -',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_trailing_space(self):
+ self.assertMarkdownRenders(
+ '--- ',
+
+ '<hr />'
+ )
+
+ def test_hr_hyphens_spaces_trailing_space(self):
+ self.assertMarkdownRenders(
+ '- - - ',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores(self):
+ self.assertMarkdownRenders(
+ '___',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_spaces(self):
+ self.assertMarkdownRenders(
+ '_ _ _',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_long(self):
+ self.assertMarkdownRenders(
+ '_______',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_spaces_long(self):
+ self.assertMarkdownRenders(
+ '_ _ _ _ _ _ _',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_1_indent(self):
+ self.assertMarkdownRenders(
+ ' ___',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_spaces_1_indent(self):
+ self.assertMarkdownRenders(
+ ' _ _ _',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_2_indent(self):
+ self.assertMarkdownRenders(
+ ' ___',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_spaces_2_indent(self):
+ self.assertMarkdownRenders(
+ ' _ _ _',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_3_indent(self):
+ self.assertMarkdownRenders(
+ ' ___',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_spaces_3_indent(self):
+ self.assertMarkdownRenders(
+ ' _ _ _',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_trailing_space(self):
+ self.assertMarkdownRenders(
+ '___ ',
+
+ '<hr />'
+ )
+
+ def test_hr_underscores_spaces_trailing_space(self):
+ self.assertMarkdownRenders(
+ '_ _ _ ',
+
+ '<hr />'
+ )
+
+ def test_hr_before_paragraph(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ ***
+ An HR followed by a paragraph with no blank line.
+ """
+ ),
+ self.dedent(
+ """
+ <hr />
+ <p>An HR followed by a paragraph with no blank line.</p>
+ """
+ )
+ )
+
+ def test_hr_after_paragraph(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ A paragraph followed by an HR with no blank line.
+ ***
+ """
+ ),
+ self.dedent(
+ """
+ <p>A paragraph followed by an HR with no blank line.</p>
+ <hr />
+ """
+ )
+ )
+
+ def test_hr_after_emstrong(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ ***text***
+ ***
+ """
+ ),
+ self.dedent(
+ """
+ <p><strong><em>text</em></strong></p>
+ <hr />
+ """
+ )
+ )
+
+ def test_not_hr_2_asterisks(self):
+ self.assertMarkdownRenders(
+ '**',
+
+ '<p>**</p>'
+ )
+
+ def test_not_hr_2_asterisks_spaces(self):
+ self.assertMarkdownRenders(
+ '* *',
+
+ self.dedent(
+ """
+ <ul>
+ <li>*</li>
+ </ul>
+ """
+ )
+ )
+
+ def test_not_hr_2_hyphens(self):
+ self.assertMarkdownRenders(
+ '--',
+
+ '<p>--</p>'
+ )
+
+ def test_not_hr_2_hyphens_spaces(self):
+ self.assertMarkdownRenders(
+ '- -',
+
+ self.dedent(
+ """
+ <ul>
+ <li>-</li>
+ </ul>
+ """
+ )
+ )
+
+ def test_not_hr_2_underscores(self):
+ self.assertMarkdownRenders(
+ '__',
+
+ '<p>__</p>'
+ )
+
+ def test_not_hr_2_underscores_spaces(self):
+ self.assertMarkdownRenders(
+ '_ _',
+
+ '<p>_ _</p>'
+ )
+
+ def test_2_consecutive_hr(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ - - -
+ - - -
+ """
+ ),
+ self.dedent(
+ """
+ <hr />
+ <hr />
+ """
+ )
+ )
+
+ def test_not_hr_end_in_char(self):
+ self.assertMarkdownRenders(
+ '--------------------------------------c',
+
+ '<p>--------------------------------------c</p>'
+ )
diff --git a/tests/test_syntax/blocks/test_html_blocks.py b/tests/test_syntax/blocks/test_html_blocks.py
new file mode 100644
index 0000000..9ec0668
--- /dev/null
+++ b/tests/test_syntax/blocks/test_html_blocks.py
@@ -0,0 +1,1619 @@
+# -*- coding: utf-8 -*-
+"""
+Python Markdown
+
+A Python implementation of John Gruber's Markdown.
+
+Documentation: https://python-markdown.github.io/
+GitHub: https://github.com/Python-Markdown/markdown/
+PyPI: https://pypi.org/project/Markdown/
+
+Started by Manfred Stienstra (http://www.dwerg.net/).
+Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
+Currently maintained by Waylan Limberg (https://github.com/waylan),
+Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
+
+Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see LICENSE.md for details).
+"""
+
+from markdown.test_tools import TestCase
+import markdown
+
+
+class TestHTMLBlocks(TestCase):
+
+ def test_raw_paragraph(self):
+ self.assertMarkdownRenders(
+ '<p>A raw paragraph.</p>',
+ '<p>A raw paragraph.</p>'
+ )
+
+ def test_raw_skip_inline_markdown(self):
+ self.assertMarkdownRenders(
+ '<p>A *raw* paragraph.</p>',
+ '<p>A *raw* paragraph.</p>'
+ )
+
+ def test_raw_indent_one_space(self):
+ self.assertMarkdownRenders(
+ ' <p>A *raw* paragraph.</p>',
+ '<p>A *raw* paragraph.</p>'
+ )
+
+ def test_raw_indent_two_spaces(self):
+ self.assertMarkdownRenders(
+ ' <p>A *raw* paragraph.</p>',
+ '<p>A *raw* paragraph.</p>'
+ )
+
+ def test_raw_indent_three_spaces(self):
+ self.assertMarkdownRenders(
+ ' <p>A *raw* paragraph.</p>',
+ '<p>A *raw* paragraph.</p>'
+ )
+
+ def test_raw_indent_four_spaces(self):
+ self.assertMarkdownRenders(
+ ' <p>code block</p>',
+ self.dedent(
+ """
+ <pre><code>&lt;p&gt;code block&lt;/p&gt;
+ </code></pre>
+ """
+ )
+ )
+
+ def test_raw_span(self):
+ self.assertMarkdownRenders(
+ '<span>*inline*</span>',
+ '<p><span><em>inline</em></span></p>'
+ )
+
+ def test_code_span(self):
+ self.assertMarkdownRenders(
+ '`<p>code span</p>`',
+ '<p><code>&lt;p&gt;code span&lt;/p&gt;</code></p>'
+ )
+
+ def test_code_span_open_gt(self):
+ self.assertMarkdownRenders(
+ '*bar* `<` *foo*',
+ '<p><em>bar</em> <code>&lt;</code> <em>foo</em></p>'
+ )
+
+ def test_raw_empty(self):
+ self.assertMarkdownRenders(
+ '<p></p>',
+ '<p></p>'
+ )
+
+ def test_raw_empty_space(self):
+ self.assertMarkdownRenders(
+ '<p> </p>',
+ '<p> </p>'
+ )
+
+ def test_raw_empty_newline(self):
+ self.assertMarkdownRenders(
+ '<p>\n</p>',
+ '<p>\n</p>'
+ )
+
+ def test_raw_empty_blank_line(self):
+ self.assertMarkdownRenders(
+ '<p>\n\n</p>',
+ '<p>\n\n</p>'
+ )
+
+ def test_raw_uppercase(self):
+ self.assertMarkdownRenders(
+ '<DIV>*foo*</DIV>',
+ '<DIV>*foo*</DIV>'
+ )
+
+ def test_raw_uppercase_multiline(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <DIV>
+ *foo*
+ </DIV>
+ """
+ ),
+ self.dedent(
+ """
+ <DIV>
+ *foo*
+ </DIV>
+ """
+ )
+ )
+
+ def test_multiple_raw_single_line(self):
+ self.assertMarkdownRenders(
+ '<p>*foo*</p><div>*bar*</div>',
+ self.dedent(
+ """
+ <p>*foo*</p>
+ <div>*bar*</div>
+ """
+ )
+ )
+
+ def test_multiple_raw_single_line_with_pi(self):
+ self.assertMarkdownRenders(
+ "<p>*foo*</p><?php echo '>'; ?>",
+ self.dedent(
+ """
+ <p>*foo*</p>
+ <?php echo '>'; ?>
+ """
+ )
+ )
+
+ def test_multiline_raw(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <p>
+ A raw paragraph
+ with multiple lines.
+ </p>
+ """
+ ),
+ self.dedent(
+ """
+ <p>
+ A raw paragraph
+ with multiple lines.
+ </p>
+ """
+ )
+ )
+
+ def test_blank_lines_in_raw(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <p>
+
+ A raw paragraph...
+
+ with many blank lines.
+
+ </p>
+ """
+ ),
+ self.dedent(
+ """
+ <p>
+
+ A raw paragraph...
+
+ with many blank lines.
+
+ </p>
+ """
+ )
+ )
+
+ def test_raw_surrounded_by_Markdown(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ Some *Markdown* text.
+
+ <p>*Raw* HTML.</p>
+
+ More *Markdown* text.
+ """
+ ),
+ self.dedent(
+ """
+ <p>Some <em>Markdown</em> text.</p>
+ <p>*Raw* HTML.</p>
+
+ <p>More <em>Markdown</em> text.</p>
+ """
+ )
+ )
+
+ def test_raw_surrounded_by_text_without_blank_lines(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ Some *Markdown* text.
+ <p>*Raw* HTML.</p>
+ More *Markdown* text.
+ """
+ ),
+ self.dedent(
+ """
+ <p>Some <em>Markdown</em> text.</p>
+ <p>*Raw* HTML.</p>
+ <p>More <em>Markdown</em> text.</p>
+ """
+ )
+ )
+
+ def test_multiline_markdown_with_code_span(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ A paragraph with a block-level
+ `<p>code span</p>`, which is
+ at the start of a line.
+ """
+ ),
+ self.dedent(
+ """
+ <p>A paragraph with a block-level
+ <code>&lt;p&gt;code span&lt;/p&gt;</code>, which is
+ at the start of a line.</p>
+ """
+ )
+ )
+
+ def test_raw_block_preceded_by_markdown_code_span_with_unclosed_block_tag(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ A paragraph with a block-level code span: `<div>`.
+
+ <p>*not markdown*</p>
+
+ This is *markdown*
+ """
+ ),
+ self.dedent(
+ """
+ <p>A paragraph with a block-level code span: <code>&lt;div&gt;</code>.</p>
+ <p>*not markdown*</p>
+
+ <p>This is <em>markdown</em></p>
+ """
+ )
+ )
+
+ def test_raw_one_line_followed_by_text(self):
+ self.assertMarkdownRenders(
+ '<p>*foo*</p>*bar*',
+ self.dedent(
+ """
+ <p>*foo*</p>
+ <p><em>bar</em></p>
+ """
+ )
+ )
+
+ def test_raw_one_line_followed_by_span(self):
+ self.assertMarkdownRenders(
+ "<p>*foo*</p><span>*bar*</span>",
+ self.dedent(
+ """
+ <p>*foo*</p>
+ <p><span><em>bar</em></span></p>
+ """
+ )
+ )
+
+ def test_raw_with_markdown_blocks(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div>
+ Not a Markdown paragraph.
+
+ * Not a list item.
+ * Another non-list item.
+
+ Another non-Markdown paragraph.
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div>
+ Not a Markdown paragraph.
+
+ * Not a list item.
+ * Another non-list item.
+
+ Another non-Markdown paragraph.
+ </div>
+ """
+ )
+ )
+
+ def test_adjacent_raw_blocks(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <p>A raw paragraph.</p>
+ <p>A second raw paragraph.</p>
+ """
+ ),
+ self.dedent(
+ """
+ <p>A raw paragraph.</p>
+ <p>A second raw paragraph.</p>
+ """
+ )
+ )
+
+ def test_adjacent_raw_blocks_with_blank_lines(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <p>A raw paragraph.</p>
+
+ <p>A second raw paragraph.</p>
+ """
+ ),
+ self.dedent(
+ """
+ <p>A raw paragraph.</p>
+
+ <p>A second raw paragraph.</p>
+ """
+ )
+ )
+
+ def test_nested_raw_one_line(self):
+ self.assertMarkdownRenders(
+ '<div><p>*foo*</p></div>',
+ '<div><p>*foo*</p></div>'
+ )
+
+ def test_nested_raw_block(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div>
+ <p>A raw paragraph.</p>
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div>
+ <p>A raw paragraph.</p>
+ </div>
+ """
+ )
+ )
+
+ def test_nested_indented_raw_block(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div>
+ <p>A raw paragraph.</p>
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div>
+ <p>A raw paragraph.</p>
+ </div>
+ """
+ )
+ )
+
+ def test_nested_raw_blocks(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div>
+ <p>A raw paragraph.</p>
+ <p>A second raw paragraph.</p>
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div>
+ <p>A raw paragraph.</p>
+ <p>A second raw paragraph.</p>
+ </div>
+ """
+ )
+ )
+
+ def test_nested_raw_blocks_with_blank_lines(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div>
+
+ <p>A raw paragraph.</p>
+
+ <p>A second raw paragraph.</p>
+
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div>
+
+ <p>A raw paragraph.</p>
+
+ <p>A second raw paragraph.</p>
+
+ </div>
+ """
+ )
+ )
+
+ def test_nested_inline_one_line(self):
+ self.assertMarkdownRenders(
+ '<p><em>foo</em><br></p>',
+ '<p><em>foo</em><br></p>'
+ )
+
+ def test_raw_nested_inline(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div>
+ <p>
+ <span>*text*</span>
+ </p>
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div>
+ <p>
+ <span>*text*</span>
+ </p>
+ </div>
+ """
+ )
+ )
+
+ def test_raw_nested_inline_with_blank_lines(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div>
+
+ <p>
+
+ <span>*text*</span>
+
+ </p>
+
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div>
+
+ <p>
+
+ <span>*text*</span>
+
+ </p>
+
+ </div>
+ """
+ )
+ )
+
+ def test_raw_html5(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <section>
+ <header>
+ <hgroup>
+ <h1>Hello :-)</h1>
+ </hgroup>
+ </header>
+ <figure>
+ <img src="image.png" alt="" />
+ <figcaption>Caption</figcaption>
+ </figure>
+ <footer>
+ <p>Some footer</p>
+ </footer>
+ </section>
+ """
+ ),
+ self.dedent(
+ """
+ <section>
+ <header>
+ <hgroup>
+ <h1>Hello :-)</h1>
+ </hgroup>
+ </header>
+ <figure>
+ <img src="image.png" alt="" />
+ <figcaption>Caption</figcaption>
+ </figure>
+ <footer>
+ <p>Some footer</p>
+ </footer>
+ </section>
+ """
+ )
+ )
+
+ def test_raw_pre_tag(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ Preserve whitespace in raw html
+
+ <pre>
+ class Foo():
+ bar = 'bar'
+
+ @property
+ def baz(self):
+ return self.bar
+ </pre>
+ """
+ ),
+ self.dedent(
+ """
+ <p>Preserve whitespace in raw html</p>
+ <pre>
+ class Foo():
+ bar = 'bar'
+
+ @property
+ def baz(self):
+ return self.bar
+ </pre>
+ """
+ )
+ )
+
+ def test_raw_pre_tag_nested_escaped_html(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <pre>
+ &lt;p&gt;foo&lt;/p&gt;
+ </pre>
+ """
+ ),
+ self.dedent(
+ """
+ <pre>
+ &lt;p&gt;foo&lt;/p&gt;
+ </pre>
+ """
+ )
+ )
+
+ def test_raw_p_no_end_tag(self):
+ self.assertMarkdownRenders(
+ '<p>*text*',
+ '<p>*text*'
+ )
+
+ def test_raw_multiple_p_no_end_tag(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <p>*text*'
+
+ <p>more *text*
+ """
+ ),
+ self.dedent(
+ """
+ <p>*text*'
+
+ <p>more *text*
+ """
+ )
+ )
+
+ def test_raw_p_no_end_tag_followed_by_blank_line(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <p>*raw text*'
+
+ Still part of *raw* text.
+ """
+ ),
+ self.dedent(
+ """
+ <p>*raw text*'
+
+ Still part of *raw* text.
+ """
+ )
+ )
+
+ def test_raw_nested_p_no_end_tag(self):
+ self.assertMarkdownRenders(
+ '<div><p>*text*</div>',
+ '<div><p>*text*</div>'
+ )
+
+ def test_raw_open_bracket_only(self):
+ self.assertMarkdownRenders(
+ '<',
+ '<p>&lt;</p>'
+ )
+
+ def test_raw_open_bracket_followed_by_space(self):
+ self.assertMarkdownRenders(
+ '< foo',
+ '<p>&lt; foo</p>'
+ )
+
+ def test_raw_missing_close_bracket(self):
+ self.assertMarkdownRenders(
+ '<foo',
+ '<p>&lt;foo</p>'
+ )
+
+ def test_raw_unclosed_tag_in_code_span(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ `<div`.
+
+ <div>
+ hello
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <p><code>&lt;div</code>.</p>
+ <div>
+ hello
+ </div>
+ """
+ )
+ )
+
+ def test_raw_unclosed_tag_in_code_span_space(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ ` <div `.
+
+ <div>
+ hello
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <p><code>&lt;div</code>.</p>
+ <div>
+ hello
+ </div>
+ """
+ )
+ )
+
+ def test_raw_attributes(self):
+ self.assertMarkdownRenders(
+ '<p id="foo", class="bar baz", style="margin: 15px; line-height: 1.5; text-align: center;">text</p>',
+ '<p id="foo", class="bar baz", style="margin: 15px; line-height: 1.5; text-align: center;">text</p>'
+ )
+
+ def test_raw_attributes_nested(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div id="foo, class="bar", style="background: #ffe7e8; border: 2px solid #e66465;">
+ <p id="baz", style="margin: 15px; line-height: 1.5; text-align: center;">
+ <img scr="../foo.jpg" title="with 'quoted' text." valueless_attr weirdness="<i>foo</i>" />
+ </p>
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div id="foo, class="bar", style="background: #ffe7e8; border: 2px solid #e66465;">
+ <p id="baz", style="margin: 15px; line-height: 1.5; text-align: center;">
+ <img scr="../foo.jpg" title="with 'quoted' text." valueless_attr weirdness="<i>foo</i>" />
+ </p>
+ </div>
+ """
+ )
+ )
+
+ def test_raw_comment_one_line(self):
+ self.assertMarkdownRenders(
+ '<!-- *foo* -->',
+ '<!-- *foo* -->'
+ )
+
+ def test_raw_comment_one_line_with_tag(self):
+ self.assertMarkdownRenders(
+ '<!-- <tag> -->',
+ '<!-- <tag> -->'
+ )
+
+ def test_comment_in_code_span(self):
+ self.assertMarkdownRenders(
+ '`<!-- *foo* -->`',
+ '<p><code>&lt;!-- *foo* --&gt;</code></p>'
+ )
+
+ def test_raw_comment_one_line_followed_by_text(self):
+ self.assertMarkdownRenders(
+ '<!-- *foo* -->*bar*',
+ self.dedent(
+ """
+ <!-- *foo* -->
+ <p><em>bar</em></p>
+ """
+ )
+ )
+
+ def test_raw_comment_one_line_followed_by_html(self):
+ self.assertMarkdownRenders(
+ '<!-- *foo* --><p>*bar*</p>',
+ self.dedent(
+ """
+ <!-- *foo* -->
+ <p>*bar*</p>
+ """
+ )
+ )
+
+ # Note: Trailing (insignificant) whitespace is not preserved, which does not match the
+ # reference implementation. However, it is not a change in behavior for Python-Markdown.
+ def test_raw_comment_trailing_whitespace(self):
+ self.assertMarkdownRenders(
+ '<!-- *foo* --> ',
+ '<!-- *foo* -->'
+ )
+
+ # Note: this is a change in behavior for Python-Markdown, which does *not* match the reference
+ # implementation. However, it does match the HTML5 spec. Declarations must start with either
+ # `<!DOCTYPE` or `<![`. Anything else that starts with `<!` is a comment. According to the
+ # HTML5 spec, a comment without the hyphens is a "bogus comment", but a comment nonetheless.
+ # See https://www.w3.org/TR/html52/syntax.html#markup-declaration-open-state.
+ # If we wanted to change this behavior, we could override `HTMLParser.parse_bogus_comment()`.
+ def test_bogus_comment(self):
+ self.assertMarkdownRenders(
+ '<!*foo*>',
+ '<!--*foo*-->'
+ )
+
+ def test_raw_multiline_comment(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!--
+ *foo*
+ -->
+ """
+ ),
+ self.dedent(
+ """
+ <!--
+ *foo*
+ -->
+ """
+ )
+ )
+
+ def test_raw_multiline_comment_with_tag(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!--
+ <tag>
+ -->
+ """
+ ),
+ self.dedent(
+ """
+ <!--
+ <tag>
+ -->
+ """
+ )
+ )
+
+ def test_raw_multiline_comment_first_line(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!-- *foo*
+ -->
+ """
+ ),
+ self.dedent(
+ """
+ <!-- *foo*
+ -->
+ """
+ )
+ )
+
+ def test_raw_multiline_comment_last_line(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!--
+ *foo* -->
+ """
+ ),
+ self.dedent(
+ """
+ <!--
+ *foo* -->
+ """
+ )
+ )
+
+ def test_raw_comment_with_blank_lines(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!--
+
+ *foo*
+
+ -->
+ """
+ ),
+ self.dedent(
+ """
+ <!--
+
+ *foo*
+
+ -->
+ """
+ )
+ )
+
+ def test_raw_comment_with_blank_lines_with_tag(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!--
+
+ <tag>
+
+ -->
+ """
+ ),
+ self.dedent(
+ """
+ <!--
+
+ <tag>
+
+ -->
+ """
+ )
+ )
+
+ def test_raw_comment_with_blank_lines_first_line(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!-- *foo*
+
+ -->
+ """
+ ),
+ self.dedent(
+ """
+ <!-- *foo*
+
+ -->
+ """
+ )
+ )
+
+ def test_raw_comment_with_blank_lines_last_line(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!--
+
+ *foo* -->
+ """
+ ),
+ self.dedent(
+ """
+ <!--
+
+ *foo* -->
+ """
+ )
+ )
+
+ def test_raw_comment_indented(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!--
+
+ *foo*
+
+ -->
+ """
+ ),
+ self.dedent(
+ """
+ <!--
+
+ *foo*
+
+ -->
+ """
+ )
+ )
+
+ def test_raw_comment_indented_with_tag(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!--
+
+ <tag>
+
+ -->
+ """
+ ),
+ self.dedent(
+ """
+ <!--
+
+ <tag>
+
+ -->
+ """
+ )
+ )
+
+ def test_raw_comment_nested(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <div>
+ <!-- *foo* -->
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <div>
+ <!-- *foo* -->
+ </div>
+ """
+ )
+ )
+
+ def test_comment_in_code_block(self):
+ self.assertMarkdownRenders(
+ ' <!-- *foo* -->',
+ self.dedent(
+ """
+ <pre><code>&lt;!-- *foo* --&gt;
+ </code></pre>
+ """
+ )
+ )
+
+ # Note: This is a change in behavior. Previously, Python-Markdown interpreted this in the same manner
+ # as browsers and all text after the opening comment tag was considered to be in a comment. However,
+ # that did not match the reference implementation. The new behavior does.
+ def test_unclosed_comment_(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!-- unclosed comment
+
+ *not* a comment
+ """
+ ),
+ self.dedent(
+ """
+ <p>&lt;!-- unclosed comment</p>
+ <p><em>not</em> a comment</p>
+ """
+ )
+ )
+
+ def test_raw_processing_instruction_one_line(self):
+ self.assertMarkdownRenders(
+ "<?php echo '>'; ?>",
+ "<?php echo '>'; ?>"
+ )
+
+ # This is a change in behavior and does not match the reference implementation.
+ # We have no way to determine if text is on the same line, so we get this. TODO: reevaluate!
+ def test_raw_processing_instruction_one_line_followed_by_text(self):
+ self.assertMarkdownRenders(
+ "<?php echo '>'; ?>*bar*",
+ self.dedent(
+ """
+ <?php echo '>'; ?>
+ <p><em>bar</em></p>
+ """
+ )
+ )
+
+ def test_raw_multiline_processing_instruction(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <?php
+ echo '>';
+ ?>
+ """
+ ),
+ self.dedent(
+ """
+ <?php
+ echo '>';
+ ?>
+ """
+ )
+ )
+
+ def test_raw_processing_instruction_with_blank_lines(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <?php
+
+ echo '>';
+
+ ?>
+ """
+ ),
+ self.dedent(
+ """
+ <?php
+
+ echo '>';
+
+ ?>
+ """
+ )
+ )
+
+ def test_raw_processing_instruction_indented(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <?php
+
+ echo '>';
+
+ ?>
+ """
+ ),
+ self.dedent(
+ """
+ <?php
+
+ echo '>';
+
+ ?>
+ """
+ )
+ )
+
+ def test_raw_processing_instruction_code_span(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ `<?php`
+
+ <div>
+ foo
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <p><code>&lt;?php</code></p>
+ <div>
+ foo
+ </div>
+ """
+ )
+ )
+
+ def test_raw_declaration_one_line(self):
+ self.assertMarkdownRenders(
+ '<!DOCTYPE html>',
+ '<!DOCTYPE html>'
+ )
+
+ # This is a change in behavior and does not match the reference implementation.
+ # We have no way to determine if text is on the same line, so we get this. TODO: reevaluate!
+ def test_raw_declaration_one_line_followed_by_text(self):
+ self.assertMarkdownRenders(
+ '<!DOCTYPE html>*bar*',
+ self.dedent(
+ """
+ <!DOCTYPE html>
+ <p><em>bar</em></p>
+ """
+ )
+ )
+
+ def test_raw_multiline_declaration(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <!DOCTYPE html PUBLIC
+ "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+ """
+ ),
+ self.dedent(
+ """
+ <!DOCTYPE html PUBLIC
+ "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+ """
+ )
+ )
+
+ def test_raw_declaration_code_span(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ `<!`
+
+ <div>
+ foo
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <p><code>&lt;!</code></p>
+ <div>
+ foo
+ </div>
+ """
+ )
+ )
+
+ def test_raw_cdata_one_line(self):
+ self.assertMarkdownRenders(
+ '<![CDATA[ document.write(">"); ]]>',
+ '<![CDATA[ document.write(">"); ]]>'
+ )
+
+ # Note: this is a change. Neither previous output nor this match reference implementation.
+ def test_raw_cdata_one_line_followed_by_text(self):
+ self.assertMarkdownRenders(
+ '<![CDATA[ document.write(">"); ]]>*bar*',
+ self.dedent(
+ """
+ <![CDATA[ document.write(">"); ]]>
+ <p><em>bar</em></p>
+ """
+ )
+ )
+
+ def test_raw_multiline_cdata(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <![CDATA[
+ document.write(">");
+ ]]>
+ """
+ ),
+ self.dedent(
+ """
+ <![CDATA[
+ document.write(">");
+ ]]>
+ """
+ )
+ )
+
+ def test_raw_cdata_with_blank_lines(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <![CDATA[
+
+ document.write(">");
+
+ ]]>
+ """
+ ),
+ self.dedent(
+ """
+ <![CDATA[
+
+ document.write(">");
+
+ ]]>
+ """
+ )
+ )
+
+ def test_raw_cdata_indented(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <![CDATA[
+
+ document.write(">");
+
+ ]]>
+ """
+ ),
+ self.dedent(
+ """
+ <![CDATA[
+
+ document.write(">");
+
+ ]]>
+ """
+ )
+ )
+
+ def test_raw_cdata_code_span(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ `<![`
+
+ <div>
+ foo
+ </div>
+ """
+ ),
+ self.dedent(
+ """
+ <p><code>&lt;![</code></p>
+ <div>
+ foo
+ </div>
+ """
+ )
+ )
+
+ def test_charref(self):
+ self.assertMarkdownRenders(
+ '&sect;',
+ '<p>&sect;</p>'
+ )
+
+ def test_nested_charref(self):
+ self.assertMarkdownRenders(
+ '<p>&sect;</p>',
+ '<p>&sect;</p>'
+ )
+
+ def test_entityref(self):
+ self.assertMarkdownRenders(
+ '&#167;',
+ '<p>&#167;</p>'
+ )
+
+ def test_nested_entityref(self):
+ self.assertMarkdownRenders(
+ '<p>&#167;</p>',
+ '<p>&#167;</p>'
+ )
+
+ def test_amperstand(self):
+ self.assertMarkdownRenders(
+ 'AT&T & AT&amp;T',
+ '<p>AT&amp;T &amp; AT&amp;T</p>'
+ )
+
+ def test_startendtag(self):
+ self.assertMarkdownRenders(
+ '<hr>',
+ '<hr>'
+ )
+
+ def test_startendtag_with_attrs(self):
+ self.assertMarkdownRenders(
+ '<hr id="foo" class="bar">',
+ '<hr id="foo" class="bar">'
+ )
+
+ def test_startendtag_with_space(self):
+ self.assertMarkdownRenders(
+ '<hr >',
+ '<hr >'
+ )
+
+ def test_closed_startendtag(self):
+ self.assertMarkdownRenders(
+ '<hr />',
+ '<hr />'
+ )
+
+ def test_closed_startendtag_without_space(self):
+ self.assertMarkdownRenders(
+ '<hr/>',
+ '<hr/>'
+ )
+
+ def test_closed_startendtag_with_attrs(self):
+ self.assertMarkdownRenders(
+ '<hr id="foo" class="bar" />',
+ '<hr id="foo" class="bar" />'
+ )
+
+ def test_nested_startendtag(self):
+ self.assertMarkdownRenders(
+ '<div><hr></div>',
+ '<div><hr></div>'
+ )
+
+ def test_nested_closed_startendtag(self):
+ self.assertMarkdownRenders(
+ '<div><hr /></div>',
+ '<div><hr /></div>'
+ )
+
+ def test_auto_links_dont_break_parser(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <https://example.com>
+
+ <email@example.com>
+ """
+ ),
+ '<p><a href="https://example.com">https://example.com</a></p>\n'
+ '<p><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#101;&#109;'
+ '&#97;&#105;&#108;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;'
+ '&#46;&#99;&#111;&#109;">&#101;&#109;&#97;&#105;&#108;&#64;&#101;'
+ '&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;</a></p>'
+ )
+
+ def test_text_links_ignored(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ https://example.com
+
+ email@example.com
+ """
+ ),
+ self.dedent(
+ """
+ <p>https://example.com</p>
+ <p>email@example.com</p>
+ """
+ ),
+ )
+
+ def text_invalid_tags(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <some [weird](http://example.com) stuff>
+
+ <some>> <<unbalanced>> <<brackets>
+ """
+ ),
+ self.dedent(
+ """
+ <p><some <a href="http://example.com">weird</a> stuff></p>
+ <p><some>&gt; &lt;<unbalanced>&gt; &lt;<brackets></p>
+ """
+ )
+ )
+
+ def test_script_tags(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <script>
+ *random stuff* <div> &amp;
+ </script>
+
+ <style>
+ **more stuff**
+ </style>
+ """
+ ),
+ self.dedent(
+ """
+ <script>
+ *random stuff* <div> &amp;
+ </script>
+
+ <style>
+ **more stuff**
+ </style>
+ """
+ )
+ )
+
+ def test_unclosed_script_tag(self):
+ # Ensure we have a working fix for https://bugs.python.org/issue41989
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ <script>
+ *random stuff* <div> &amp;
+
+ Still part of the *script* tag
+ """
+ ),
+ self.dedent(
+ """
+ <script>
+ *random stuff* <div> &amp;
+
+ Still part of the *script* tag
+ """
+ )
+ )
+
+ def test_inline_script_tags(self):
+ # Ensure inline script tags doesn't cause the parser to eat content (see #1036).
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ Text `<script>` more *text*.
+
+ <div>
+ *foo*
+ </div>
+
+ <div>
+
+ bar
+
+ </div>
+
+ A new paragraph with a closing `</script>` tag.
+ """
+ ),
+ self.dedent(
+ """
+ <p>Text <code>&lt;script&gt;</code> more <em>text</em>.</p>
+ <div>
+ *foo*
+ </div>
+
+ <div>
+
+ bar
+
+ </div>
+
+ <p>A new paragraph with a closing <code>&lt;/script&gt;</code> tag.</p>
+ """
+ )
+ )
+
+ def test_hr_only_start(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ *emphasis1*
+ <hr>
+ *emphasis2*
+ """
+ ),
+ self.dedent(
+ """
+ <p><em>emphasis1</em></p>
+ <hr>
+ <p><em>emphasis2</em></p>
+ """
+ )
+ )
+
+ def test_hr_self_close(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ *emphasis1*
+ <hr/>
+ *emphasis2*
+ """
+ ),
+ self.dedent(
+ """
+ <p><em>emphasis1</em></p>
+ <hr/>
+ <p><em>emphasis2</em></p>
+ """
+ )
+ )
+
+ def test_hr_start_and_end(self):
+ # Browsers ignore ending hr tags, so we don't try to do anything to handle them special.
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ *emphasis1*
+ <hr></hr>
+ *emphasis2*
+ """
+ ),
+ self.dedent(
+ """
+ <p><em>emphasis1</em></p>
+ <hr>
+ <p></hr>
+ <em>emphasis2</em></p>
+ """
+ )
+ )
+
+ def test_hr_only_end(self):
+ # Browsers ignore ending hr tags, so we don't try to do anything to handle them special.
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ *emphasis1*
+ </hr>
+ *emphasis2*
+ """
+ ),
+ self.dedent(
+ """
+ <p><em>emphasis1</em>
+ </hr>
+ <em>emphasis2</em></p>
+ """
+ )
+ )
+
+ def test_hr_with_content(self):
+ # Browsers ignore ending hr tags, so we don't try to do anything to handle them special.
+ # Content is not allowed and will be treated as normal content between two hr tags.
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ *emphasis1*
+ <hr>
+ **content**
+ </hr>
+ *emphasis2*
+ """
+ ),
+ self.dedent(
+ """
+ <p><em>emphasis1</em></p>
+ <hr>
+ <p><strong>content</strong>
+ </hr>
+ <em>emphasis2</em></p>
+ """
+ )
+ )
+
+ def test_placeholder_in_source(self):
+ # This should never occur, but third party extensions could create weird edge cases.
+ md = markdown.Markdown()
+ # Ensure there is an htmlstash so relevant code (nested in `if replacements`) is run.
+ md.htmlStash.store('foo')
+ # Run with a placeholder which is not in the stash
+ placeholder = md.htmlStash.get_placeholder(md.htmlStash.html_counter + 1)
+ result = md.postprocessors['raw_html'].run(placeholder)
+ self.assertEqual(placeholder, result)
diff --git a/tests/test_syntax/blocks/test_paragraphs.py b/tests/test_syntax/blocks/test_paragraphs.py
new file mode 100644
index 0000000..9b7ba03
--- /dev/null
+++ b/tests/test_syntax/blocks/test_paragraphs.py
@@ -0,0 +1,229 @@
+"""
+Python Markdown
+
+A Python implementation of John Gruber's Markdown.
+
+Documentation: https://python-markdown.github.io/
+GitHub: https://github.com/Python-Markdown/markdown/
+PyPI: https://pypi.org/project/Markdown/
+
+Started by Manfred Stienstra (http://www.dwerg.net/).
+Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
+Currently maintained by Waylan Limberg (https://github.com/waylan),
+Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
+
+Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see LICENSE.md for details).
+"""
+
+from markdown.test_tools import TestCase
+
+
+class TestParagraphBlocks(TestCase):
+
+ def test_simple_paragraph(self):
+ self.assertMarkdownRenders(
+ 'A simple paragraph.',
+
+ '<p>A simple paragraph.</p>'
+ )
+
+ def test_blank_line_before_paragraph(self):
+ self.assertMarkdownRenders(
+ '\nA paragraph preceded by a blank line.',
+
+ '<p>A paragraph preceded by a blank line.</p>'
+ )
+
+ def test_multiline_paragraph(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ This is a paragraph
+ on multiple lines
+ with hard returns.
+ """
+ ),
+ self.dedent(
+ """
+ <p>This is a paragraph
+ on multiple lines
+ with hard returns.</p>
+ """
+ )
+ )
+
+ def test_paragraph_long_line(self):
+ self.assertMarkdownRenders(
+ 'A very long long long long long long long long long long long long long long long long long long long '
+ 'long long long long long long long long long long long long long paragraph on 1 line.',
+
+ '<p>A very long long long long long long long long long long long long long long long long long long '
+ 'long long long long long long long long long long long long long long paragraph on 1 line.</p>'
+ )
+
+ def test_2_paragraphs_long_line(self):
+ self.assertMarkdownRenders(
+ 'A very long long long long long long long long long long long long long long long long long long long '
+ 'long long long long long long long long long long long long long paragraph on 1 line.\n\n'
+
+ 'A new long long long long long long long long long long long long long long long '
+ 'long paragraph on 1 line.',
+
+ '<p>A very long long long long long long long long long long long long long long long long long long '
+ 'long long long long long long long long long long long long long long paragraph on 1 line.</p>\n'
+ '<p>A new long long long long long long long long long long long long long long long '
+ 'long paragraph on 1 line.</p>'
+ )
+
+ def test_consecutive_paragraphs(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ Paragraph 1.
+
+ Paragraph 2.
+ """
+ ),
+ self.dedent(
+ """
+ <p>Paragraph 1.</p>
+ <p>Paragraph 2.</p>
+ """
+ )
+ )
+
+ def test_consecutive_paragraphs_tab(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ Paragraph followed by a line with a tab only.
+ \t
+ Paragraph after a line with a tab only.
+ """
+ ),
+ self.dedent(
+ """
+ <p>Paragraph followed by a line with a tab only.</p>
+ <p>Paragraph after a line with a tab only.</p>
+ """
+ )
+ )
+
+ def test_consecutive_paragraphs_space(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ Paragraph followed by a line with a space only.
+
+ Paragraph after a line with a space only.
+ """
+ ),
+ self.dedent(
+ """
+ <p>Paragraph followed by a line with a space only.</p>
+ <p>Paragraph after a line with a space only.</p>
+ """
+ )
+ )
+
+ def test_consecutive_multiline_paragraphs(self):
+ self.assertMarkdownRenders(
+ self.dedent(
+ """
+ Paragraph 1, line 1.
+ Paragraph 1, line 2.
+
+ Paragraph 2, line 1.
+ Paragraph 2, line 2.
+ """
+ ),
+ self.dedent(
+ """
+ <p>Paragraph 1, line 1.
+ Paragraph 1, line 2.</p>
+ <p>Paragraph 2, line 1.
+ Paragraph 2, line 2.</p>
+ """
+ )
+ )
+
+ def test_paragraph_leading_space(self):
+ self.assertMarkdownRenders(
+ ' A paragraph with 1 leading space.',
+
+ '<p>A paragraph with 1 leading space.</p>'
+ )
+
+ def test_paragraph_2_leading_spaces(self):
+ self.assertMarkdownRenders(
+ ' A paragraph with 2 leading spaces.',
+
+ '<p>A paragraph with 2 leading spaces.</p>'
+ )
+
+ def test_paragraph_3_leading_spaces(self):
+ self.assertMarkdownRenders(
+ ' A paragraph with 3 leading spaces.',
+
+ '<p>A paragraph with 3 leading spaces.</p>'
+ )
+
+ def test_paragraph_trailing_leading_space(self):
+ self.assertMarkdownRenders(
+ ' A paragraph with 1 trailing and 1 leading space. ',
+
+ '<p>A paragraph with 1 trailing and 1 leading space. </p>'
+ )
+
+ def test_paragraph_trailing_tab(self):
+ self.assertMarkdownRenders(
+ 'A paragraph with 1 trailing tab.\t',
+
+ '<p>A paragraph with 1 trailing tab. </p>'
+ )
+
+ def test_paragraphs_CR(self):
+ self.assertMarkdownRenders(
+ 'Paragraph 1, line 1.\rParagraph 1, line 2.\r\rParagraph 2, line 1.\rParagraph 2, line 2.\r',
+
+ self.dedent(
+ """
+ <p>Paragraph 1, line 1.
+ Paragraph 1, line 2.</p>
+ <p>Paragraph 2, line 1.
+ Paragraph 2, line 2.</p>
+ """
+ )
+ )
+
+ def test_paragraphs_LF(self):
+ self.assertMarkdownRenders(
+ 'Paragraph 1, line 1.\nParagraph 1, line 2.\n\nParagraph 2, line 1.\nParagraph 2, line 2.\n',
+
+ self.dedent(
+ """
+ <p>Paragraph 1, line 1.
+ Paragraph 1, line 2.</p>
+ <p>Paragraph 2, line 1.
+ Paragraph 2, line 2.</p>
+ """
+ )
+ )
+
+ def test_paragraphs_CR_LF(self):
+ self.assertMarkdownRenders(
+ 'Paragraph 1, line 1.\r\nParagraph 1, line 2.\r\n\r\nParagraph 2, line 1.\r\nParagraph 2, line 2.\r\n',
+
+ self.dedent(
+ """
+ <p>Paragraph 1, line 1.
+ Paragraph 1, line 2.</p>
+ <p>Paragraph 2, line 1.
+ Paragraph 2, line 2.</p>
+ """
+ )
+ )