def test_strict_mode_valid(self): pages = [ ('index.md',), ('internal.md',), ('sub/internal.md') ] site_nav = nav.SiteNavigation(pages) valid = "[test](internal.md)" convert_markdown(valid, site_nav, strict=False) convert_markdown(valid, site_nav, strict=True)
def test_strict_mode_invalid(self): pages = [ ('index.md',), ('internal.md',), ('sub/internal.md') ] site_nav = nav.SiteNavigation(pages) invalid = "[test](bad_link.md)" convert_markdown(invalid, site_nav, strict=False) self.assertRaises( MarkdownNotFound, convert_markdown, invalid, site_nav, strict=True)
def test_markdown_duplicate_custom_extension(self): """ Duplicated extension names should not cause problems. """ md_input = "foo" html_ext, _, _ = convert_markdown(md_input, ['toc']) self.assertEqual(html_ext.strip(), '<p>foo</p>')
def file_to_title(filename): """ Automatically generate a default title, given a filename. The method parses the file to check for a title, uses the filename as a title otherwise. """ if utils.is_homepage(filename): return 'Home' try: with open(filename, 'r') as f: lines = f.read() _, table_of_contents, meta = utils.convert_markdown(lines, ['meta', 'toc']) if "title" in meta: return meta["title"][0] if len(table_of_contents.items) > 0: return table_of_contents.items[0].title except IOError: # File couldn't be found - use filename as the title # this is used in tests. We use the filename as the title # in that case pass # No title found in the document, using the filename title = os.path.splitext(filename)[0] title = title.replace('-', ' ').replace('_', ' ') # Capitalize if the filename was all lowercase, otherwise leave it as-is. if title.lower() == title: title = title.capitalize() return title
def convert_markdown(markdown_source, site_navigation=None, extensions=(), strict=False): """ Convert the Markdown source file to HTML content, and additionally return the parsed table of contents, and a dictionary of any metadata that was specified in the Markdown file. `extensions` is an optional sequence of Python Markdown extensions to add to the default set. """ # Generate the HTML from the markdown source if isinstance(extensions, dict): user_extensions = list(extensions.keys()) extension_configs = dict([(k, v) for k, v in extensions.items() if isinstance(v, dict)]) else: user_extensions = list(extensions) extension_configs = {} builtin_extensions = ['meta', 'toc', 'tables', 'fenced_code'] mkdocs_extensions = [ RelativePathExtension(site_navigation, strict), ] extensions = utils.reduce_list(builtin_extensions + mkdocs_extensions + user_extensions) html_content, table_of_contents, meta = utils.convert_markdown( markdown_source, extensions, extension_configs) return (html_content, table_of_contents, meta)
def test_markdown_custom_extension(self): """ Check that an extension applies when requested in the arguments to `convert_markdown`. """ md_input = "foo__bar__baz" # Check that the plugin is not active when not requested. expected_without_smartstrong = "<p>foo<strong>bar</strong>baz</p>" html_base, _, _ = convert_markdown(md_input) self.assertEqual(html_base.strip(), expected_without_smartstrong) # Check that the plugin is active when requested. expected_with_smartstrong = "<p>foo__bar__baz</p>" html_ext, _, _ = convert_markdown(md_input, extensions=['smart_strong']) self.assertEqual(html_ext.strip(), expected_with_smartstrong)
def test_convert_markdown(self): """ Ensure that basic Markdown -> HTML and TOC works. """ html, toc, meta = convert_markdown(dedent(""" page_title: custom title # Heading 1 This is some text. # Heading 2 And some more text. """)) expected_html = dedent(""" <h1 id="heading-1">Heading 1</h1> <p>This is some text.</p> <h1 id="heading-2">Heading 2</h1> <p>And some more text.</p> """) expected_toc = dedent(""" Heading 1 - #heading-1 Heading 2 - #heading-2 """) expected_meta = {'page_title': ['custom title']} self.assertEqual(html.strip(), expected_html) self.assertEqual(str(toc).strip(), expected_toc) self.assertEqual(meta, expected_meta)
def test_markdown_table_extension(self): """ Ensure that the table extension is supported. """ html, toc, meta = convert_markdown(dedent(""" First Header | Second Header -------------- | -------------- Content Cell 1 | Content Cell 2 Content Cell 3 | Content Cell 4 """)) expected_html = dedent(""" <table> <thead> <tr> <th>First Header</th> <th>Second Header</th> </tr> </thead> <tbody> <tr> <td>Content Cell 1</td> <td>Content Cell 2</td> </tr> <tr> <td>Content Cell 3</td> <td>Content Cell 4</td> </tr> </tbody> </table> """) self.assertEqual(html.strip(), expected_html)
def test_not_use_directory_urls(self): md_text = 'An [internal link](internal.md) to another document.' expected = '<p>An <a href="internal/index.html">internal link</a> to another document.</p>' pages = [ ('internal.md',) ] site_navigation = nav.SiteNavigation(pages, use_directory_urls=False) html, toc, meta = convert_markdown(md_text, site_navigation=site_navigation) self.assertEqual(html.strip(), expected.strip())
def convert_markdown(markdown_source, config, site_navigation=None): """ Convert the Markdown source file to HTML as per the config and site_navigation. Return a tuple of the HTML as a string, the parsed table of contents, and a dictionary of any metadata that was specified in the Markdown file. """ return utils.convert_markdown( markdown_source=markdown_source, extensions=[RelativePathExtension(site_navigation, config['strict'])] + config['markdown_extensions'], extension_configs=config['mdx_configs'] )
def test_anchor_only_link(self): pages = [ ('index.md',), ('internal.md',), ('sub/internal.md') ] site_navigation = nav.SiteNavigation(pages) for page in site_navigation.walk_pages(): markdown = '[test](#test)' html, _, _ = convert_markdown(markdown, site_navigation=site_navigation) self.assertEqual(html, '<p><a href="#test">test</a></p>')
def convert_markdown(markdown_source, config, site_navigation=None): """ Convert the Markdown source file to HTML as per the config and site_navigation. Return a tuple of the HTML as a string, the parsed table of contents, and a dictionary of any metadata that was specified in the Markdown file. """ extensions = [RelativePathExtension(site_navigation, config['strict']) ] + config['markdown_extensions'] return utils.convert_markdown(markdown_source=markdown_source, extensions=extensions, extension_configs=config['mdx_configs'])
def test_markdown_fenced_code_extension(self): """ Ensure that the fenced code extension is supported. """ html, toc, meta = convert_markdown(dedent(""" ``` print 'foo' ``` """)) expected_html = dedent(""" <pre><code>print 'foo'\n</code></pre> """) self.assertEqual(html.strip(), expected_html)
def test_extension_config(self): """ Test that a dictionary of 'markdown_extensions' is recognized as both a list of extensions and a dictionary of extnesion configs. """ markdown_extensions = { 'toc': {'permalink': True}, 'meta': None # This gets ignored as it is an invalid config } html, toc, meta = convert_markdown(dedent(""" # A Header """), extensions=markdown_extensions) expected_html = dedent(""" <h1 id="a-header">A Header<a class="headerlink" href="#a-header" title="Permanent link">¶</a></h1> """) self.assertEqual(html.strip(), expected_html)
def test_dont_convert_code_block_urls(self): pages = [ ('index.md',), ('internal.md',), ('sub/internal.md') ] site_navigation = nav.SiteNavigation(pages) expected = dedent(""" <p>An HTML Anchor::</p> <pre><code><a href="index.md">My example link</a> </code></pre> """) for page in site_navigation.walk_pages(): markdown = 'An HTML Anchor::\n\n <a href="index.md">My example link</a>\n' html, _, _ = convert_markdown(markdown, site_navigation=site_navigation) self.assertEqual(dedent(html), expected)
def test_convert_internal_media(self): """Test relative image URL's are the same for different base_urls""" pages = [ ('index.md',), ('internal.md',), ('sub/internal.md') ] site_navigation = nav.SiteNavigation(pages) expected_results = ( './img/initial-layout.png', '../img/initial-layout.png', '../img/initial-layout.png', ) template = '<p><img alt="The initial MkDocs layout" src="%s" /></p>' for (page, expected) in zip(site_navigation.walk_pages(), expected_results): md_text = '![The initial MkDocs layout](img/initial-layout.png)' html, _, _ = convert_markdown(md_text, site_navigation=site_navigation) self.assertEqual(html, template % expected)
def convert_markdown(markdown_source, site_navigation=None, extensions=(), strict=False): """ Convert the Markdown source file to HTML content, and additionally return the parsed table of contents, and a dictionary of any metadata that was specified in the Markdown file. `extensions` is an optional sequence of Python Markdown extensions to add to the default set. """ # Generate the HTML from the markdown source if isinstance(extensions, dict): user_extensions = list(extensions.keys()) extension_configs = dict([(k, v) for k, v in extensions.items() if isinstance(v, dict)]) else: user_extensions = list(extensions) extension_configs = {} builtin_extensions = ['meta', 'toc', 'tables', 'fenced_code'] mkdocs_extensions = [RelativePathExtension(site_navigation, strict), ] extensions = utils.reduce_list(builtin_extensions + mkdocs_extensions + user_extensions) html_content, table_of_contents, meta = utils.convert_markdown(markdown_source, extensions, extension_configs) return (html_content, table_of_contents, meta)
def test_ignore_external_link(self): md_text = 'An [external link](http://example.com/external.md).' expected = '<p>An <a href="http://example.com/external.md">external link</a>.</p>' html, toc, meta = convert_markdown(md_text) self.assertEqual(html.strip(), expected.strip())
def test_empty_document(self): html, toc, meta = convert_markdown("") self.assertEqual(html, '') self.assertEqual(len(list(toc)), 0) self.assertEqual(meta, {})
def test_convert_internal_link_with_anchor(self): md_text = 'An [internal link](internal.md#section1.1) to another document.' expected = '<p>An <a href="internal/#section1.1">internal link</a> to another document.</p>' html, toc, meta = convert_markdown(md_text) self.assertEqual(html.strip(), expected.strip())
def test_convert_internal_link_differing_directory(self): md_text = 'An [internal link](../internal.md) to another document.' expected = '<p>An <a href="../internal/">internal link</a> to another document.</p>' html, toc, meta = convert_markdown(md_text) self.assertEqual(html.strip(), expected.strip())
def test_convert_multiple_internal_links(self): md_text = '[First link](first.md) [second link](second.md).' expected = '<p><a href="first/">First link</a> <a href="second/">second link</a>.</p>' html, toc, meta = convert_markdown(md_text) self.assertEqual(html.strip(), expected.strip())