diff --git a/markdown/test_tools.py b/markdown/test_tools.py new file mode 100644 index 000000000..cebb2bb7b --- /dev/null +++ b/markdown/test_tools.py @@ -0,0 +1,44 @@ +import unittest +import textwrap +from markdown import markdown + + +class TestCase(unittest.TestCase): + """ + A unittest.TestCase subclass with helpers for testing Markdown output. + + Define `default_kwargs` as a dict of keywords to pass to Markdown for each + test. The defaults can be overridden on individual tests. + + The `assertMarkdownRenders` method accepts the source text, the expected + output, and any keywords to pass to Markdown. The `default_kwargs` are used + except where overridden by `kwargs`. The ouput and expected ouput are passed + to `TestCase.assertMultiLineEqual`. An AssertionError is raised with a diff + if the actual output does not equal the expected output. + + The `dedent` method is available to dedent triple-quoted strings if + necessary. + + In all other respects, behaves as unittest.TestCase. + """ + + default_kwargs = {} + + def assertMarkdownRenders(self, source, expected, **kwargs): + """ + Test that source Markdown text renders to expected output with given keywords. + """ + + kws = self.default_kwargs.copy() + kws.update(kwargs) + output = markdown(source, **kws) + self.assertMultiLineEqual(output, expected) + + def dedent(self, text): + """ + Dedent text. + """ + + # TODO: If/when actual output ends with a newline, then use: + # return textwrap.dedent(text.strip('/n')) + return textwrap.dedent(text).strip() diff --git a/tests/test_syntax/__init__.py b/tests/test_syntax/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_syntax/blocks/__init__.py b/tests/test_syntax/blocks/__init__.py new file mode 100644 index 000000000..e69de29bb 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 000000000..00e607099 --- /dev/null +++ b/tests/test_syntax/blocks/test_code_blocks.py @@ -0,0 +1,67 @@ +from markdown.test_tools import TestCase + + +class TestCodeBlocks(TestCase): + + def test_spaced_codeblock(self): + self.assertMarkdownRenders( + ' # A code block.', + + self.dedent( + """ +
# A code block.
+                
+ """ + ) + ) + + def test_tabbed_codeblock(self): + self.assertMarkdownRenders( + '\t# A code block.', + + self.dedent( + """ +
# A code block.
+                
+ """ + ) + ) + + def test_multiline_codeblock(self): + self.assertMarkdownRenders( + ' # Line 1\n # Line 2\n', + + self.dedent( + """ +
# Line 1
+                # Line 2
+                
+ """ + ) + ) + + def test_codeblock_with_blankline(self): + self.assertMarkdownRenders( + ' # Line 1\n\n # Line 2\n', + + self.dedent( + """ +
# Line 1
+
+                # Line 2
+                
+ """ + ) + ) + + def test_codeblock_escape(self): + self.assertMarkdownRenders( + ' ', + + self.dedent( + """ +
<foo & bar>
+                
+ """ + ) + ) diff --git a/tests/test_syntax/blocks/test_headers.py b/tests/test_syntax/blocks/test_headers.py new file mode 100644 index 000000000..63e3a7f18 --- /dev/null +++ b/tests/test_syntax/blocks/test_headers.py @@ -0,0 +1,688 @@ +import unittest +from markdown.test_tools import TestCase + + +class TestSetextHeaders(TestCase): + + def test_setext_h1(self): + self.assertMarkdownRenders( + self.dedent( + """ + This is an H1 + ============= + """ + ), + + '

This is an H1

' + ) + + def test_setext_h2(self): + self.assertMarkdownRenders( + self.dedent( + """ + This is an H2 + ------------- + """ + ), + + '

This is an H2

' + ) + + def test_setext_h1_mismatched_length(self): + self.assertMarkdownRenders( + self.dedent( + """ + This is an H1 + === + """ + ), + + '

This is an H1

' + ) + + def test_setext_h2_mismatched_length(self): + self.assertMarkdownRenders( + self.dedent( + """ + This is an H2 + --- + """ + ), + + '

This is an 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( + """ +

This is an H1

+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + 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( + """ +

This is an H2

+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + # TODO: fix this + # see http://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( + """ +

This is a Paragraph.

+

Followed by an H1 with no blank line.

+ """ + ) + ) + + # TODO: fix this + # see http://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( + """ +

This is a Paragraph.

+

Followed by an H2 with no blank line.

+ """ + ) + ) + + +class TestHashHeaders(TestCase): + + def test_hash_h1_open(self): + self.assertMarkdownRenders( + '# This is an H1', + + '

This is an H1

' + ) + + def test_hash_h2_open(self): + self.assertMarkdownRenders( + '## This is an H2', + + '

This is an H2

' + ) + + def test_hash_h3_open(self): + self.assertMarkdownRenders( + '### This is an H3', + + '

This is an H3

' + ) + + def test_hash_h4_open(self): + self.assertMarkdownRenders( + '#### This is an H4', + + '

This is an H4

' + ) + + def test_hash_h5_open(self): + self.assertMarkdownRenders( + '##### This is an H5', + + '
This is an H5
' + ) + + def test_hash_h6_open(self): + self.assertMarkdownRenders( + '###### This is an H6', + + '
This is an H6
' + ) + + def test_hash_gt6_open(self): + self.assertMarkdownRenders( + '####### This is an H6', + + '
# This is an H6
' + ) + + def test_hash_h1_open_missing_space(self): + self.assertMarkdownRenders( + '#This is an H1', + + '

This is an H1

' + ) + + def test_hash_h2_open_missing_space(self): + self.assertMarkdownRenders( + '##This is an H2', + + '

This is an H2

' + ) + + def test_hash_h3_open_missing_space(self): + self.assertMarkdownRenders( + '###This is an H3', + + '

This is an H3

' + ) + + def test_hash_h4_open_missing_space(self): + self.assertMarkdownRenders( + '####This is an H4', + + '

This is an H4

' + ) + + def test_hash_h5_open_missing_space(self): + self.assertMarkdownRenders( + '#####This is an H5', + + '
This is an H5
' + ) + + def test_hash_h6_open_missing_space(self): + self.assertMarkdownRenders( + '######This is an H6', + + '
This is an H6
' + ) + + def test_hash_gt6_open_missing_space(self): + self.assertMarkdownRenders( + '#######This is an H6', + + '
#This is an H6
' + ) + + def test_hash_h1_closed(self): + self.assertMarkdownRenders( + '# This is an H1 #', + + '

This is an H1

' + ) + + def test_hash_h2_closed(self): + self.assertMarkdownRenders( + '## This is an H2 ##', + + '

This is an H2

' + ) + + def test_hash_h3_closed(self): + self.assertMarkdownRenders( + '### This is an H3 ###', + + '

This is an H3

' + ) + + def test_hash_h4_closed(self): + self.assertMarkdownRenders( + '#### This is an H4 ####', + + '

This is an H4

' + ) + + def test_hash_h5_closed(self): + self.assertMarkdownRenders( + '##### This is an H5 #####', + + '
This is an H5
' + ) + + def test_hash_h6_closed(self): + self.assertMarkdownRenders( + '###### This is an H6 ######', + + '
This is an H6
' + ) + + def test_hash_gt6_closed(self): + self.assertMarkdownRenders( + '####### This is an H6 #######', + + '
# This is an H6
' + ) + + def test_hash_h1_closed_missing_space(self): + self.assertMarkdownRenders( + '#This is an H1#', + + '

This is an H1

' + ) + + def test_hash_h2_closed_missing_space(self): + self.assertMarkdownRenders( + '##This is an H2##', + + '

This is an H2

' + ) + + def test_hash_h3_closed_missing_space(self): + self.assertMarkdownRenders( + '###This is an H3###', + + '

This is an H3

' + ) + + def test_hash_h4_closed_missing_space(self): + self.assertMarkdownRenders( + '####This is an H4####', + + '

This is an H4

' + ) + + def test_hash_h5_closed_missing_space(self): + self.assertMarkdownRenders( + '#####This is an H5#####', + + '
This is an H5
' + ) + + def test_hash_h6_closed_missing_space(self): + self.assertMarkdownRenders( + '######This is an H6######', + + '
This is an H6
' + ) + + def test_hash_gt6_closed_missing_space(self): + self.assertMarkdownRenders( + '#######This is an H6#######', + + '
#This is an H6
' + ) + + def test_hash_h1_closed_mismatch(self): + self.assertMarkdownRenders( + '# This is an H1 ##', + + '

This is an H1

' + ) + + def test_hash_h2_closed_mismatch(self): + self.assertMarkdownRenders( + '## This is an H2 #', + + '

This is an H2

' + ) + + def test_hash_h3_closed_mismatch(self): + self.assertMarkdownRenders( + '### This is an H3 #', + + '

This is an H3

' + ) + + def test_hash_h4_closed_mismatch(self): + self.assertMarkdownRenders( + '#### This is an H4 #', + + '

This is an H4

' + ) + + def test_hash_h5_closed_mismatch(self): + self.assertMarkdownRenders( + '##### This is an H5 #', + + '
This is an H5
' + ) + + def test_hash_h6_closed_mismatch(self): + self.assertMarkdownRenders( + '###### This is an H6 #', + + '
This is an H6
' + ) + + def test_hash_gt6_closed_mismatch(self): + self.assertMarkdownRenders( + '####### This is an H6 ##################', + + '
# This is an 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( + """ +

This is an H1

+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + 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( + """ +

This is an H2

+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + 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( + """ +

This is an H3

+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + 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( + """ +

This is an H4

+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + 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( + """ +
This is an H5
+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + 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( + """ +
This is an H6
+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + def test_hash_h1_leading_space(self): + self.assertMarkdownRenders( + ' # This is an H1', + + '

# This is an H1

' + ) + + def test_hash_h2_leading_space(self): + self.assertMarkdownRenders( + ' ## This is an H2', + + '

## This is an H2

' + ) + + def test_hash_h3_leading_space(self): + self.assertMarkdownRenders( + ' ### This is an H3', + + '

### This is an H3

' + ) + + def test_hash_h4_leading_space(self): + self.assertMarkdownRenders( + ' #### This is an H4', + + '

#### This is an H4

' + ) + + def test_hash_h5_leading_space(self): + self.assertMarkdownRenders( + ' ##### This is an H5', + + '

##### This is an H5

' + ) + + def test_hash_h6_leading_space(self): + self.assertMarkdownRenders( + ' ###### This is an H6', + + '

###### This is an H6

' + ) + + def test_hash_h1_open_trailing_space(self): + self.assertMarkdownRenders( + '# This is an H1 ', + + '

This is an H1

' + ) + + def test_hash_h2_open_trailing_space(self): + self.assertMarkdownRenders( + '## This is an H2 ', + + '

This is an H2

' + ) + + def test_hash_h3_open_trailing_space(self): + self.assertMarkdownRenders( + '### This is an H3 ', + + '

This is an H3

' + ) + + def test_hash_h4_open_trailing_space(self): + self.assertMarkdownRenders( + '#### This is an H4 ', + + '

This is an H4

' + ) + + def test_hash_h5_open_trailing_space(self): + self.assertMarkdownRenders( + '##### This is an H5 ', + + '
This is an H5
' + ) + + def test_hash_h6_open_trailing_space(self): + self.assertMarkdownRenders( + '###### This is an H6 ', + + '
This is an H6
' + ) + + def test_hash_gt6_open_trailing_space(self): + self.assertMarkdownRenders( + '####### This is an H6 ', + + '
# This is an H6
' + ) + + # TODO: Possably change the following behavior. While this follows the behavior + # of markdown.pl, it is rather uncommon and not nessecarily intuitive. + # See: http://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 # ', + + '

This is an H1 #

' + ) + + def test_hash_h2_closed_trailing_space(self): + self.assertMarkdownRenders( + '## This is an H2 ## ', + + '

This is an H2 ##

' + ) + + def test_hash_h3_closed_trailing_space(self): + self.assertMarkdownRenders( + '### This is an H3 ### ', + + '

This is an H3 ###

' + ) + + def test_hash_h4_closed_trailing_space(self): + self.assertMarkdownRenders( + '#### This is an H4 #### ', + + '

This is an H4 ####

' + ) + + def test_hash_h5_closed_trailing_space(self): + self.assertMarkdownRenders( + '##### This is an H5 ##### ', + + '
This is an H5 #####
' + ) + + def test_hash_h6_closed_trailing_space(self): + self.assertMarkdownRenders( + '###### This is an H6 ###### ', + + '
This is an H6 ######
' + ) + + def test_hash_gt6_closed_trailing_space(self): + self.assertMarkdownRenders( + '####### This is an H6 ####### ', + + '
# This is an H6 #######
' + ) + + def test_no_blank_lines_between_hashs(self): + self.assertMarkdownRenders( + self.dedent( + """ + # This is an H1 + ## This is an H2 + """ + ), + self.dedent( + """ +

This is an H1

+

This is an H2

+ """ + ) + ) + + def test_random_hash_levels(self): + self.assertMarkdownRenders( + self.dedent( + """ + ### H3 + ###### H6 + # H1 + ##### H5 + #### H4 + ## H2 + ### H3 + """ + ), + self.dedent( + """ +

H3

+
H6
+

H1

+
H5
+

H4

+

H2

+

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( + """ +

This is an H1

+

Followed by a Paragraph with no blank line.

+ """ + ) + ) + + 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( + """ +

This is a Paragraph.

+

Followed by an H1 with no blank line.

+ """ + ) + ) diff --git a/tests/test_syntax/blocks/test_hr.py b/tests/test_syntax/blocks/test_hr.py new file mode 100644 index 000000000..ffd082346 --- /dev/null +++ b/tests/test_syntax/blocks/test_hr.py @@ -0,0 +1,342 @@ +from markdown.test_tools import TestCase + + +class TestHorizontalRules(TestCase): + + def test_hr_asterisks(self): + self.assertMarkdownRenders( + '***', + + '
' + ) + + def test_hr_asterisks_spaces(self): + self.assertMarkdownRenders( + '* * *', + + '
' + ) + + def test_hr_asterisks_long(self): + self.assertMarkdownRenders( + '*******', + + '
' + ) + + def test_hr_asterisks_spaces_long(self): + self.assertMarkdownRenders( + '* * * * * * *', + + '
' + ) + + def test_hr_asterisks_1_indent(self): + self.assertMarkdownRenders( + ' ***', + + '
' + ) + + def test_hr_asterisks_spaces_1_indent(self): + self.assertMarkdownRenders( + ' * * *', + + '
' + ) + + def test_hr_asterisks_2_indent(self): + self.assertMarkdownRenders( + ' ***', + + '
' + ) + + def test_hr_asterisks_spaces_2_indent(self): + self.assertMarkdownRenders( + ' * * *', + + '
' + ) + + def test_hr_asterisks_3_indent(self): + self.assertMarkdownRenders( + ' ***', + + '
' + ) + + def test_hr_asterisks_spaces_3_indent(self): + self.assertMarkdownRenders( + ' * * *', + + '
' + ) + + def test_hr_asterisks_trailing_space(self): + self.assertMarkdownRenders( + '*** ', + + '
' + ) + + def test_hr_asterisks_spaces_trailing_space(self): + self.assertMarkdownRenders( + '* * * ', + + '
' + ) + + def test_hr_hyphens(self): + self.assertMarkdownRenders( + '---', + + '
' + ) + + def test_hr_hyphens_spaces(self): + self.assertMarkdownRenders( + '- - -', + + '
' + ) + + def test_hr_hyphens_long(self): + self.assertMarkdownRenders( + '-------', + + '
' + ) + + def test_hr_hyphens_spaces_long(self): + self.assertMarkdownRenders( + '- - - - - - -', + + '
' + ) + + def test_hr_hyphens_1_indent(self): + self.assertMarkdownRenders( + ' ---', + + '
' + ) + + def test_hr_hyphens_spaces_1_indent(self): + self.assertMarkdownRenders( + ' - - -', + + '
' + ) + + def test_hr_hyphens_2_indent(self): + self.assertMarkdownRenders( + ' ---', + + '
' + ) + + def test_hr_hyphens_spaces_2_indent(self): + self.assertMarkdownRenders( + ' - - -', + + '
' + ) + + def test_hr_hyphens_3_indent(self): + self.assertMarkdownRenders( + ' ---', + + '
' + ) + + def test_hr_hyphens_spaces_3_indent(self): + self.assertMarkdownRenders( + ' - - -', + + '
' + ) + + def test_hr_hyphens_trailing_space(self): + self.assertMarkdownRenders( + '--- ', + + '
' + ) + + def test_hr_hyphens_spaces_trailing_space(self): + self.assertMarkdownRenders( + '- - - ', + + '
' + ) + + def test_hr_underscores(self): + self.assertMarkdownRenders( + '___', + + '
' + ) + + def test_hr_underscores_spaces(self): + self.assertMarkdownRenders( + '_ _ _', + + '
' + ) + + def test_hr_underscores_long(self): + self.assertMarkdownRenders( + '_______', + + '
' + ) + + def test_hr_underscores_spaces_long(self): + self.assertMarkdownRenders( + '_ _ _ _ _ _ _', + + '
' + ) + + def test_hr_underscores_1_indent(self): + self.assertMarkdownRenders( + ' ___', + + '
' + ) + + def test_hr_underscores_spaces_1_indent(self): + self.assertMarkdownRenders( + ' _ _ _', + + '
' + ) + + def test_hr_underscores_2_indent(self): + self.assertMarkdownRenders( + ' ___', + + '
' + ) + + def test_hr_underscores_spaces_2_indent(self): + self.assertMarkdownRenders( + ' _ _ _', + + '
' + ) + + def test_hr_underscores_3_indent(self): + self.assertMarkdownRenders( + ' ___', + + '
' + ) + + def test_hr_underscores_spaces_3_indent(self): + self.assertMarkdownRenders( + ' _ _ _', + + '
' + ) + + def test_hr_underscores_trailing_space(self): + self.assertMarkdownRenders( + '___ ', + + '
' + ) + + def test_hr_underscores_spaces_trailing_space(self): + self.assertMarkdownRenders( + '_ _ _ ', + + '
' + ) + + def test_hr_before_paragraph(self): + self.assertMarkdownRenders( + self.dedent( + """ + *** + An HR followed by a paragraph with no blank line. + """ + ), + self.dedent( + """ +
+

An HR followed by a paragraph with no blank line.

+ """ + ) + ) + + def test_hr_after_paragraph(self): + self.assertMarkdownRenders( + self.dedent( + """ + A paragraph followed by an HR with no blank line. + *** + """ + ), + self.dedent( + """ +

A paragraph followed by an HR with no blank line.

+
+ """ + ) + ) + + def test_not_hr_2_asterisks(self): + self.assertMarkdownRenders( + '**', + + '

**

' + ) + + def test_not_hr_2_asterisks_spaces(self): + self.assertMarkdownRenders( + '* *', + + self.dedent( + """ + + """ + ) + ) + + def test_not_hr_2_hyphens(self): + self.assertMarkdownRenders( + '--', + + '

--

' + ) + + def test_not_hr_2_hyphens_spaces(self): + self.assertMarkdownRenders( + '- -', + + self.dedent( + """ + + """ + ) + ) + + def test_not_hr_2_underscores(self): + self.assertMarkdownRenders( + '__', + + '

__

' + ) + + def test_not_hr_2_underscores_spaces(self): + self.assertMarkdownRenders( + '_ _', + + '

_ _

' + ) diff --git a/tests/test_syntax/blocks/test_paragraphs.py b/tests/test_syntax/blocks/test_paragraphs.py new file mode 100644 index 000000000..b458fc1fe --- /dev/null +++ b/tests/test_syntax/blocks/test_paragraphs.py @@ -0,0 +1,208 @@ +from markdown.test_tools import TestCase + + +class TestParagraphBlocks(TestCase): + + def test_simple_paragraph(self): + self.assertMarkdownRenders( + 'A simple paragraph.', + + '

A simple paragraph.

' + ) + + def test_blank_line_before_paragraph(self): + self.assertMarkdownRenders( + '\nA paragraph preceded by a blank line.', + + '

A paragraph preceded by a blank line.

' + ) + + def test_multiline_paragraph(self): + self.assertMarkdownRenders( + self.dedent( + """ + This is a paragraph + on multiple lines + with hard returns. + """ + ), + self.dedent( + """ +

This is a paragraph + on multiple lines + with hard returns.

+ """ + ) + ) + + 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.', + + '

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.

' + ) + + 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.', + + '

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' + '

A new long long long long long long long long long long long long long long long ' + 'long paragraph on 1 line.

' + ) + + def test_consecutive_paragraphs(self): + self.assertMarkdownRenders( + self.dedent( + """ + Paragraph 1. + + Paragraph 2. + """ + ), + self.dedent( + """ +

Paragraph 1.

+

Paragraph 2.

+ """ + ) + ) + + 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( + """ +

Paragraph followed by a line with a tab only.

+

Paragraph after a line with a tab only.

+ """ + ) + ) + + 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( + """ +

Paragraph followed by a line with a space only.

+

Paragraph after a line with a space only.

+ """ + ) + ) + + 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( + """ +

Paragraph 1, line 1. + Paragraph 1, line 2.

+

Paragraph 2, line 1. + Paragraph 2, line 2.

+ """ + ) + ) + + def test_paragraph_leading_space(self): + self.assertMarkdownRenders( + ' A paragraph with 1 leading space.', + + '

A paragraph with 1 leading space.

' + ) + + def test_paragraph_2_leading_spaces(self): + self.assertMarkdownRenders( + ' A paragraph with 2 leading spaces.', + + '

A paragraph with 2 leading spaces.

' + ) + + def test_paragraph_3_leading_spaces(self): + self.assertMarkdownRenders( + ' A paragraph with 3 leading spaces.', + + '

A paragraph with 3 leading spaces.

' + ) + + def test_paragraph_trailing_leading_space(self): + self.assertMarkdownRenders( + ' A paragraph with 1 trailing and 1 leading space. ', + + '

A paragraph with 1 trailing and 1 leading space.

' + ) + + def test_paragraph_trailing_tab(self): + self.assertMarkdownRenders( + 'A paragraph with 1 trailing tab.\t', + + '

A paragraph with 1 trailing tab.

' + ) + + 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( + """ +

Paragraph 1, line 1. + Paragraph 1, line 2.

+

Paragraph 2, line 1. + Paragraph 2, line 2.

+ """ + ) + ) + + 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( + """ +

Paragraph 1, line 1. + Paragraph 1, line 2.

+

Paragraph 2, line 1. + Paragraph 2, line 2.

+ """ + ) + ) + + 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( + """ +

Paragraph 1, line 1. + Paragraph 1, line 2.

+

Paragraph 2, line 1. + Paragraph 2, line 2.

+ """ + ) + )