unplugged-system/external/markdown/tests/test_syntax/blocks/test_html_blocks.py

1620 lines
40 KiB
Python

# -*- 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)