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

    def test_bogus_comment(self):
        self.assertMarkdownRenders(
            '<!invalid>',
            '<p>&lt;!invalid&gt;</p>'
        )

    def test_bogus_comment_endtag(self):
        self.assertMarkdownRenders(
            '</#invalid>',
            '<p>&lt;/#invalid&gt;</p>'
        )

    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_invalid_comment_end(self):
        self.assertMarkdownRenders(
            self.dedent(
                """
                <!-- This comment is malformed and never closes -- >
                Some content after the bad comment.
                """
            ),
            self.dedent(
                """
                <p>&lt;!-- This comment is malformed and never closes -- &gt;
                Some content after the bad 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_not_actually_cdata(self):
        # Ensure bug reported in #1534 is avoided.
        self.assertMarkdownRenders(
            '<![',
            '<p>&lt;![</p>'
        )

    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_multiline_attributes(self):
        self.assertMarkdownRenders(
            self.dedent(
                """
                <div id="foo"
                     class="bar">
                    text
                </div>

                <hr class="foo"
                    id="bar" >
                """
            ),
            self.dedent(
                """
                <div id="foo"
                     class="bar">
                    text
                </div>

                <hr class="foo"
                    id="bar" >
                """
            )
        )

    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)

    def test_noname_tag(self):
        self.assertMarkdownRenders(
            self.dedent(
                """
                <div>
                </>
                </div>
                """
            ),
            self.dedent(
                """
                <div>
                </>
                </div>
                """
            )
        )

    def test_multiple_bogus_comments_no_hang(self):
        """Test that multiple bogus comments (</` patterns) don't cause infinite loop."""
        self.assertMarkdownRenders(
            '`</` and `</`',
            '<p><code>&lt;/</code> and <code>&lt;/</code></p>'
        )

    def test_multiple_unclosed_comments_no_hang(self):
        """Test that multiple unclosed comments don't cause infinite loop."""
        self.assertMarkdownRenders(
            '<!-- and <!--',
            '<p>&lt;!-- and &lt;!--</p>'
        )

    def test_no_hang_issue_1586(self):
        """Test no hang condition for issue #1586."""

        self.assertMarkdownRenders(
            'Test `<!--[if mso]>` and `<!--[if !mso]>`',
            '<p>Test <code>&lt;!--[if mso]&gt;</code> and <code>&lt;!--[if !mso]&gt;</code></p>'
        )

    def test_issue_1590(self):
        """Test case with comments in table for issue #1590."""

        self.assertMarkdownRenders(
            self.dedent(
                '''
                <table>
                <!--[if mso]>-->
                <td>foo</td>
                <!--<!endif]-->
                <td>bar</td>
                </table>
                '''
            ),
            self.dedent(
                '''
                <table>
                <!--[if mso]>-->
                <td>foo</td>
                <!--<!endif]-->
                <td>bar</td>
                </table>
                '''
            )
        )

    def test_stress_comment_handling(self):
        """Stress test the comment handling."""

        self.assertMarkdownRenders(
            self.dedent(
                '''
                `</` <!-- `<!--[if mso]>` and <!-- </> and `<!--[if mso]>`

                <!-- and <!-- `<!--[if mso]>` and </> `</` and `<!--[if mso]>`

                <!-- Real comment -->

                `<!--[if mso]>` `</` `<!--[if mso]>` and </> <!-- and <!--

                </> `<!--[if mso]>` `</` <!--  and <!--  and `<!--[if mso]>`
                '''
            ),
            self.dedent(
                '''
                <p><code>&lt;/</code> &lt;!-- <code>&lt;!--[if mso]&gt;</code> and &lt;!-- &lt;/&gt; and <code>&lt;!--[if mso]&gt;</code></p>
                <p>&lt;!-- and &lt;!-- <code>&lt;!--[if mso]&gt;</code> and &lt;/&gt; <code>&lt;/</code> and <code>&lt;!--[if mso]&gt;</code></p>
                <!-- Real comment -->
                <p><code>&lt;!--[if mso]&gt;</code> <code>&lt;/</code> <code>&lt;!--[if mso]&gt;</code> and &lt;/&gt; &lt;!-- and &lt;!--</p>
                <p>&lt;/&gt; <code>&lt;!--[if mso]&gt;</code> <code>&lt;/</code> &lt;!--  and &lt;!--  and <code>&lt;!--[if mso]&gt;</code></p>
                '''  # noqa: E501
            )
        )

    def test_unclosed_endtag(self):
        """Ensure unclosed end tag does not have side effects."""

        self.assertMarkdownRenders(
            self.dedent(
                '''
                `</`

                <div>
                <!--[if mso]>-->
                <p>foo</p>
                <!--<!endif]-->
                </div>
                '''
            ),
            self.dedent(
                '''
                <p><code>&lt;/</code></p>
                <div>
                <!--[if mso]>-->
                <p>foo</p>
                <!--<!endif]-->
                </div>
                '''
            )
        )
