""" 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-2019 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 import markdown.extensions.codehilite import os try: import pygments # noqa import pygments.formatters # noqa has_pygments = True except ImportError: has_pygments = False # The version required by the tests is the version specified and installed in the 'pygments' tox env. # In any environment where the PYGMENTS_VERSION environment variable is either not defined or doesn't # match the version of Pygments installed, all tests which rely in pygments will be skipped. required_pygments_version = os.environ.get('PYGMENTS_VERSION', '') class TestFencedCode(TestCase): def testBasicFence(self): self.assertMarkdownRenders( self.dedent( ''' A paragraph before a fenced code block: ``` Fenced code block ``` ''' ), self.dedent( '''

A paragraph before a fenced code block:

Fenced code block
                
''' ), extensions=['fenced_code'] ) def testNestedFence(self): self.assertMarkdownRenders( self.dedent( ''' ```` ``` ```` ''' ), self.dedent( '''

                ```
                
''' ), extensions=['fenced_code'] ) def testFencedTildes(self): self.assertMarkdownRenders( self.dedent( ''' ~~~ # Arbitrary code ``` # these backticks will not close the block ~~~ ''' ), self.dedent( '''
# Arbitrary code
                ``` # these backticks will not close the block
                
''' ), extensions=['fenced_code'] ) def testFencedLanguageNoDot(self): self.assertMarkdownRenders( self.dedent( ''' ``` python # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def testFencedLanguageWithDot(self): self.assertMarkdownRenders( self.dedent( ''' ``` .python # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def test_fenced_code_in_raw_html(self): self.assertMarkdownRenders( self.dedent( """
``` Begone placeholders! ```
""" ), self.dedent( """
Begone placeholders!
                
""" ), extensions=['fenced_code'] ) def testFencedLanguageInAttr(self): self.assertMarkdownRenders( self.dedent( ''' ``` {.python} # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def testFencedMultipleClassesInAttr(self): self.assertMarkdownRenders( self.dedent( ''' ``` {.python .foo .bar} # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def testFencedIdInAttr(self): self.assertMarkdownRenders( self.dedent( ''' ``` { #foo } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def testFencedIdAndLangInAttr(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python #foo } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def testFencedIdAndLangAndClassInAttr(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python #foo .bar } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def testFencedLanguageIdAndPygmentsDisabledInAttrNoCodehilite(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python #foo use_pygments=False } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def testFencedLanguageIdAndPygmentsEnabledInAttrNoCodehilite(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python #foo use_pygments=True } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code'] ) def testFencedLanguageNoCodehiliteWithAttrList(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python foo=bar } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code', 'attr_list'] ) def testFencedLanguagePygmentsDisabledInAttrNoCodehiliteWithAttrList(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python foo=bar use_pygments=False } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code', 'attr_list'] ) def testFencedLanguagePygmentsEnabledInAttrNoCodehiliteWithAttrList(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python foo=bar use_pygments=True } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code', 'attr_list'] ) def testFencedLanguageNoPrefix(self): self.assertMarkdownRenders( self.dedent( ''' ``` python # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=[markdown.extensions.fenced_code.FencedCodeExtension(lang_prefix='')] ) def testFencedLanguageAltPrefix(self): self.assertMarkdownRenders( self.dedent( ''' ``` python # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=[markdown.extensions.fenced_code.FencedCodeExtension(lang_prefix='lang-')] ) def testFencedCodeEscapedAttrs(self): self.assertMarkdownRenders( self.dedent( ''' ``` { ."weird #"foo bar=">baz } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['fenced_code', 'attr_list'] ) class TestFencedCodeWithCodehilite(TestCase): def setUp(self): if has_pygments and pygments.__version__ != required_pygments_version: self.skipTest(f'Pygments=={required_pygments_version} is required') def test_shebang(self): if has_pygments: expected = '''
#!test
            
''' else: expected = '''
#!test
            
''' self.assertMarkdownRenders( self.dedent( ''' ``` #!test ``` ''' ), self.dedent( expected ), extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(linenums=None, guess_lang=False), 'fenced_code' ] ) def testFencedCodeWithHighlightLines(self): if has_pygments: expected = self.dedent( '''
line 1
                line 2
                line 3
                
''' ) else: expected = self.dedent( '''
line 1
                    line 2
                    line 3
                    
''' ) self.assertMarkdownRenders( self.dedent( ''' ```hl_lines="1 3" line 1 line 2 line 3 ``` ''' ), expected, extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(linenums=None, guess_lang=False), 'fenced_code' ] ) def testFencedLanguageAndHighlightLines(self): if has_pygments: expected = ( '
'
                'line 1\n'
                'line 2\n'
                'line 3\n'
                '
' ) else: expected = self.dedent( '''
line 1
                    line 2
                    line 3
                    
''' ) self.assertMarkdownRenders( self.dedent( ''' ``` .python hl_lines="1 3" line 1 line 2 line 3 ``` ''' ), expected, extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(linenums=None, guess_lang=False), 'fenced_code' ] ) def testFencedLanguageAndPygmentsDisabled(self): self.assertMarkdownRenders( self.dedent( ''' ``` .python # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(use_pygments=False), 'fenced_code' ] ) def testFencedLanguageDoubleEscape(self): if has_pygments: expected = ( '
'
                '<span'
                '>This&amp;'
                'That</span'
                '>\n'
                '
' ) else: expected = ( '
'
                '<span>This&amp;That</span>\n'
                '
' ) self.assertMarkdownRenders( self.dedent( ''' ```html This&That ``` ''' ), expected, extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(), 'fenced_code' ] ) def testFencedAmps(self): if has_pygments: expected = self.dedent( '''
&
                &amp;
                &amp;amp;
                
''' ) else: expected = self.dedent( '''
&
                &amp;
                &amp;amp;
                
''' ) self.assertMarkdownRenders( self.dedent( ''' ```text & & &amp; ``` ''' ), expected, extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(), 'fenced_code' ] ) def testFencedCodeWithHighlightLinesInAttr(self): if has_pygments: expected = self.dedent( '''
line 1
                line 2
                line 3
                
''' ) else: expected = self.dedent( '''
line 1
                    line 2
                    line 3
                    
''' ) self.assertMarkdownRenders( self.dedent( ''' ```{ hl_lines="1 3" } line 1 line 2 line 3 ``` ''' ), expected, extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(linenums=None, guess_lang=False), 'fenced_code' ] ) def testFencedLanguageAndHighlightLinesInAttr(self): if has_pygments: expected = ( '
'
                'line 1\n'
                'line 2\n'
                'line 3\n'
                '
' ) else: expected = self.dedent( '''
line 1
                    line 2
                    line 3
                    
''' ) self.assertMarkdownRenders( self.dedent( ''' ``` { .python hl_lines="1 3" } line 1 line 2 line 3 ``` ''' ), expected, extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(linenums=None, guess_lang=False), 'fenced_code' ] ) def testFencedLanguageIdInAttrAndPygmentsDisabled(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python #foo } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(use_pygments=False), 'fenced_code' ] ) def testFencedLanguageIdAndPygmentsDisabledInAttr(self): self.assertMarkdownRenders( self.dedent( ''' ``` { .python #foo use_pygments=False } # Some python code ``` ''' ), self.dedent( '''
# Some python code
                
''' ), extensions=['codehilite', 'fenced_code'] ) def testFencedLanguageAttrCssclass(self): if has_pygments: expected = self.dedent( '''
# Some python code
                
''' ) else: expected = ( '
# Some python code\n'
                '
' ) self.assertMarkdownRenders( self.dedent( ''' ``` { .python css_class='pygments' } # Some python code ``` ''' ), expected, extensions=['codehilite', 'fenced_code'] ) def testFencedLanguageAttrLinenums(self): if has_pygments: expected = ( '' '' '
1
'
                '# Some python code\n'
                '
\n' '
' ) else: expected = ( '
# Some python code\n'
                '
' ) self.assertMarkdownRenders( self.dedent( ''' ``` { .python linenums=True } # Some python code ``` ''' ), expected, extensions=['codehilite', 'fenced_code'] ) def testFencedLanguageAttrGuesslang(self): if has_pygments: expected = self.dedent( '''
# Some python code
                
''' ) else: expected = ( '
# Some python code\n'
                '
' ) self.assertMarkdownRenders( self.dedent( ''' ``` { guess_lang=False } # Some python code ``` ''' ), expected, extensions=['codehilite', 'fenced_code'] ) def testFencedLanguageAttrNoclasses(self): if has_pygments: expected = ( '
' '
'
                '# Some python code\n'
                '
' ) else: expected = ( '
# Some python code\n'
                '
' ) self.assertMarkdownRenders( self.dedent( ''' ``` { .python noclasses=True } # Some python code ``` ''' ), expected, extensions=['codehilite', 'fenced_code'] ) def testFencedMultipleBlocksSameStyle(self): if has_pygments: # See also: https://github.com/Python-Markdown/markdown/issues/1240 expected = ( '
'
                '# First Code Block\n'
                '
\n\n' '

Normal paragraph

\n' '
'
                '# Second Code Block\n'
                '
' ) else: expected = '''
# First Code Block
            

Normal paragraph

# Second Code Block
            
''' self.assertMarkdownRenders( self.dedent( ''' ``` { .python } # First Code Block ``` Normal paragraph ``` { .python } # Second Code Block ``` ''' ), self.dedent( expected ), extensions=[ markdown.extensions.codehilite.CodeHiliteExtension(pygments_style="native", noclasses=True), 'fenced_code' ] ) def testCustomPygmentsFormatter(self): if has_pygments: class CustomFormatter(pygments.formatters.HtmlFormatter): def wrap(self, source, outfile): return self._wrap_div(self._wrap_code(source)) def _wrap_code(self, source): yield 0, '' for i, t in source: if i == 1: t += '
' yield i, t yield 0, '
' expected = '''
hello world
hello another world
''' else: CustomFormatter = None expected = '''
hello world
            hello another world
            
''' self.assertMarkdownRenders( self.dedent( ''' ``` hello world hello another world ``` ''' ), self.dedent( expected ), extensions=[ markdown.extensions.codehilite.CodeHiliteExtension( pygments_formatter=CustomFormatter, guess_lang=False, ), 'fenced_code' ] ) def testPygmentsAddLangClassFormatter(self): if has_pygments: class CustomAddLangHtmlFormatter(pygments.formatters.HtmlFormatter): def __init__(self, lang_str='', **options): super().__init__(**options) self.lang_str = lang_str def _wrap_code(self, source): yield 0, f'' yield from source yield 0, '' expected = '''
hello world
                hello another world
                
''' else: CustomAddLangHtmlFormatter = None expected = '''
hello world
                hello another world
                
''' self.assertMarkdownRenders( self.dedent( ''' ```text hello world hello another world ``` ''' ), self.dedent( expected ), extensions=[ markdown.extensions.codehilite.CodeHiliteExtension( guess_lang=False, pygments_formatter=CustomAddLangHtmlFormatter, ), 'fenced_code' ] ) def testSvgCustomPygmentsFormatter(self): if has_pygments: expected = ''' hello world hello another world ''' else: expected = '''
hello world
            hello another world
            
''' self.assertMarkdownRenders( self.dedent( ''' ``` hello world hello another world ``` ''' ), self.dedent( expected ), extensions=[ markdown.extensions.codehilite.CodeHiliteExtension( pygments_formatter='svg', linenos=False, guess_lang=False, ), 'fenced_code' ] ) def testInvalidCustomPygmentsFormatter(self): if has_pygments: expected = '''
hello world
            hello another world
            
''' else: expected = '''
hello world
            hello another world
            
''' self.assertMarkdownRenders( self.dedent( ''' ``` hello world hello another world ``` ''' ), self.dedent( expected ), extensions=[ markdown.extensions.codehilite.CodeHiliteExtension( pygments_formatter='invalid', guess_lang=False, ), 'fenced_code' ] )