def test_markdown_table_extension(self): """ Ensure that the table extension is supported. """ html, toc, meta = build.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_convert_markdown(self): """ Ensure that basic Markdown -> HTML and TOC works. """ html, toc, meta = build.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_indented_toc_html(self): md = dedent(""" # Heading 1 ## <code>Heading</code> 2 ## Heading 3 """) expected = dedent(""" Heading 1 - #heading-1 Heading 2 - #heading-2 Heading 3 - #heading-3 """) toc = self.markdown_to_toc(md) self.assertEqual(str(toc).strip(), expected)
def test_flat_h2_toc(self): md = dedent(""" ## Heading 1 ## Heading 2 ## Heading 3 """) expected = dedent(""" Heading 1 - #heading-1 Heading 2 - #heading-2 Heading 3 - #heading-3 """) toc = self.markdown_to_toc(md) self.assertEqual(str(toc).strip(), expected)
def test_entityref(self): md = dedent(""" # Heading & 1 ## Heading > 2 ### Heading < 3 """) expected = dedent(""" Heading & 1 - #heading-1 Heading > 2 - #heading-2 Heading < 3 - #heading-3 """) toc = get_toc(get_markdown_toc(md)) self.assertEqual(str(toc).strip(), expected) self.assertEqual(len(toc), 1)
def test_flat_toc(self): md = dedent(""" # Heading 1 # Heading 2 # Heading 3 """) expected = dedent(""" Heading 1 - #heading-1 Heading 2 - #heading-2 Heading 3 - #heading-3 """) toc = get_toc(get_markdown_toc(md)) self.assertEqual(str(toc).strip(), expected) self.assertEqual(len(toc), 3)
def test_markdown_fenced_code_extension(self): """ Ensure that the fenced code extension is supported. """ html, toc, meta = build.convert_markdown(dedent(""" ``` print 'foo' ``` """), load_config()) expected_html = dedent(""" <pre><code>print 'foo'\n</code></pre> """) self.assertEqual(html.strip(), expected_html)
def test_no_meta_data(self): doc = dedent( """ Doc body """ ) self.assertEqual(utils.meta.get_data(doc), (doc, {}))
def test_config_option(self): """ Users can explicitly set the config file using the '--config' option. Allows users to specify a config other than the default `mkdocs.yml`. """ expected_result = { 'site_name': 'Example', 'pages': [ {'Introduction': 'index.md'} ], } file_contents = dedent(""" site_name: Example pages: - ['index.md', 'Introduction'] """) config_file = tempfile.NamedTemporaryFile('w', delete=False) try: config_file.write(ensure_utf(file_contents)) config_file.flush() config_file.close() result = config.load_config(config_file=config_file.name) self.assertEqual(result['site_name'], expected_result['site_name']) self.assertEqual(result['pages'], expected_result['pages']) finally: os.remove(config_file.name)
def test_copy_theme_files(self): with TemporaryDirectory() as docs_dir, TemporaryDirectory() as site_dir: # Create a non-empty markdown file. f = open(os.path.join(docs_dir, 'index.md'), 'w') f.write(dedent(""" page_title: custom title # Heading 1 This is some text. """)) f.close() cfg = load_config(docs_dir=docs_dir, site_dir=site_dir) build.build(cfg) # Verify only theme media are copied, not templates or Python files. self.assertTrue(os.path.isfile(os.path.join(site_dir, 'index.html'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'js'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'css'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'img'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, '__init__.py'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, '__init__.pyc'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, 'base.html'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, 'content.html'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, 'nav.html')))
def test_copying_media(self): with TemporaryDirectory() as docs_dir, TemporaryDirectory() as site_dir: # Create a non-empty markdown file, image, html file, dot file and dot directory. f = open(os.path.join(docs_dir, 'index.md'), 'w') f.write(dedent(""" page_title: custom title # Heading 1 This is some text. # Heading 2 And some more text. """)) f.close() open(os.path.join(docs_dir, 'img.jpg'), 'w').close() open(os.path.join(docs_dir, 'example.html'), 'w').close() open(os.path.join(docs_dir, '.hidden'), 'w').close() os.mkdir(os.path.join(docs_dir, '.git')) open(os.path.join(docs_dir, '.git/hidden'), 'w').close() cfg = load_config(docs_dir=docs_dir, site_dir=site_dir) build.build(cfg) # Verify only the markdown (coverted to html) and the image are copied. self.assertTrue(os.path.isfile(os.path.join(site_dir, 'index.html'))) self.assertTrue(os.path.isfile(os.path.join(site_dir, 'img.jpg'))) self.assertTrue(os.path.isfile(os.path.join(site_dir, 'example.html'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, '.hidden'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, '.git/hidden')))
def test_config_option(self): """ Users can explicitly set the config file using the '--config' option. Allows users to specify a config other than the default `mkdocs.yml`. """ expected_result = { 'site_name': 'Example', 'pages': [ {'Introduction': 'index.md'} ], } file_contents = dedent(""" site_name: Example pages: - 'Introduction': 'index.md' """) with TemporaryDirectory() as temp_path: os.mkdir(os.path.join(temp_path, 'docs')) config_path = os.path.join(temp_path, 'mkdocs.yml') config_file = open(config_path, 'w') config_file.write(ensure_utf(file_contents)) config_file.flush() config_file.close() result = config.load_config(config_file=config_file.name) self.assertEqual(result['site_name'], expected_result['site_name']) self.assertEqual(result['pages'], expected_result['pages'])
def test_yaml_load(self): try: from collections import OrderedDict except ImportError: # Don't test if can't import OrderdDict # Exception can be removed when Py26 support is removed return yaml_text = dedent(''' test: key1: 1 key2: 2 key3: 3 key4: 4 key5: 5 key5: 6 key3: 7 ''') self.assertEqual( utils.yaml_load(yaml_text), OrderedDict([('test', OrderedDict([('key1', 1), ('key2', 2), ('key3', 7), ('key4', 4), ('key5', 6)]))]) )
def test_mm_meta_data(self): doc = dedent( """ Title: Foo Bar Date: 2018-07-10 Summary: Line one Line two Tags: foo Tags: bar Doc body """ ) self.assertEqual( utils.meta.get_data(doc), ( "Doc body", { 'title': 'Foo Bar', 'date': '2018-07-10', 'summary': 'Line one Line two', 'tags': 'foo bar' } ) )
def test_find_toc_by_id(self): """ Test finding the relevant TOC item by the tag ID. """ index = search.SearchIndex() md = dedent( """ # Heading 1 ## Heading 2 ### Heading 3 """ ) toc = markdown_to_toc(md) toc_item = index._find_toc_by_id(toc, "heading-1") self.assertEqual(toc_item.url, "#heading-1") self.assertEqual(toc_item.title, "Heading 1") toc_item2 = index._find_toc_by_id(toc, "heading-2") self.assertEqual(toc_item2.url, "#heading-2") self.assertEqual(toc_item2.title, "Heading 2") toc_item3 = index._find_toc_by_id(toc, "heading-3") self.assertEqual(toc_item3.url, "#heading-3") self.assertEqual(toc_item3.title, "Heading 3")
def test_yaml_meta_data(self): doc = dedent( """ --- Title: Foo Bar Date: 2018-07-10 Summary: Line one Line two Tags: - foo - bar --- Doc body """ ) self.assertEqual( utils.meta.get_data(doc), ( "Doc body", { 'Title': 'Foo Bar', 'Date': datetime.date(2018, 7, 10), 'Summary': 'Line one Line two', 'Tags': ['foo', 'bar'] } ) )
def test_copy_theme_files(self): docs_dir = tempfile.mkdtemp() site_dir = tempfile.mkdtemp() try: # Create a non-empty markdown file. f = open(os.path.join(docs_dir, 'index.md'), 'w') f.write(dedent(""" page_title: custom title # Heading 1 This is some text. """)) f.close() cfg = load_config({ 'docs_dir': docs_dir, 'site_dir': site_dir }) build.build(cfg) # Verify only theme media are copied, not templates or Python files. self.assertTrue(os.path.isfile(os.path.join(site_dir, 'index.html'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'js'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'css'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'img'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, '__init__.py'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, '__init__.pyc'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, 'base.html'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, 'content.html'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, 'nav.html'))) finally: shutil.rmtree(docs_dir) shutil.rmtree(site_dir)
def test_indented_toc(self): pages = [ {'Home': 'index.md'}, {'API Guide': [ {'Running': 'api-guide/running.md'}, {'Testing': 'api-guide/testing.md'}, {'Debugging': 'api-guide/debugging.md'}, ]}, {'About': [ {'Release notes': 'about/release-notes.md'}, {'License': 'about/license.md'} ]} ] expected = dedent(""" Home - / API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About Release notes - /about/release-notes/ License - /about/license/ """) site_navigation = nav.SiteNavigation(pages) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.nav_items), 3) self.assertEqual(len(site_navigation.pages), 6)
def test_html_toc(self): html = dedent(""" <div class="toc"> <ul> <li><a href="#foo">Heading 1</a></li> <li><a href="#bar">Heading 2</a></li> </ul> </div> """) expected = dedent(""" Heading 1 - #foo Heading 2 - #bar """) toc = get_toc(html) self.assertEqual(str(toc).strip(), expected) self.assertEqual(len(toc), 2)
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. """ md_text = dedent(""" # A Header """) expected_html = dedent(""" <h1 id="a-header">A Header<a class="headerlink" href="#a-header" title="Permanent link">¶</a></h1> """) config = load_config(pages=[{'Home': 'index.md'}], markdown_extensions=[{'toc': {'permalink': True}}]) page, nav = build_page(None, 'index.md', config, md_text) page.render(config, nav) self.assertEqual(page.content.strip(), expected_html)
def test_mixed_html(self): md = dedent(""" # Heading 1 ## Heading 2 # Heading 3 ### Heading 4 ### <a>Heading 5</a> """) expected = dedent(""" Heading 1 - #heading-1 Heading 2 - #heading-2 Heading 3 - #heading-3 Heading 4 - #heading-4 Heading 5 - #heading-5 """) toc = self.markdown_to_toc(md) self.assertEqual(str(toc).strip(), expected)
def test_nested_anchor(self): md = dedent(""" # Heading 1 ## Heading 2 # Heading 3 ### Heading 4 ### <a href="/">Heading 5</a> """) expected = dedent(""" Heading 1 - #heading-1 Heading 2 - #heading-2 Heading 3 - #heading-3 Heading 4 - #heading-4 Heading 5 - #heading-5 """) toc = markdown_to_toc(md) self.assertEqual(str(toc).strip(), expected)
def test_walk_empty_toc(self): pages = [ 'index.md', {'About': 'about.md'} ] expected = [ dedent(""" Home - / [*] About - /about/ """), dedent(""" Home - / About - /about/ [*] """) ] site_navigation = nav.SiteNavigation(pages) for index, page in enumerate(site_navigation.walk_pages()): self.assertEqual(str(site_navigation).strip(), expected[index])
def test_markdown_fenced_code_extension(self): """ Ensure that the fenced code extension is supported. """ md_text = dedent(""" ``` print 'foo' ``` """) expected_html = dedent(""" <pre><code>print 'foo'\n</code></pre> """) config = load_config(pages=[{'Home': 'index.md'}]) page, nav = build_page(None, 'index.md', config, md_text) page.render(config, nav) self.assertEqual(page.content.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. """ cfg = load_config({ 'markdown_extensions': [{'toc': {'permalink': True}}] }) html, toc, meta = build.convert_markdown(dedent(""" # A Header """), cfg) 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_mixed_toc(self): md = dedent(""" # Heading 1 ## Heading 2 # Heading 3 ### Heading 4 ### Heading 5 """) expected = dedent(""" Heading 1 - #heading-1 Heading 2 - #heading-2 Heading 3 - #heading-3 Heading 4 - #heading-4 Heading 5 - #heading-5 """) toc = get_toc(get_markdown_toc(md)) self.assertEqual(str(toc).strip(), expected) self.assertEqual(len(toc), 2)
def test_walk_simple_toc(self): pages = legacy.pages_compat_shim([ ('index.md', 'Home'), ('about.md', 'About') ]) expected = [ dedent(""" Home - / [*] About - /about/ """), dedent(""" Home - / About - /about/ [*] """) ] site_navigation = nav.SiteNavigation(pages) for index, page in enumerate(site_navigation.walk_pages()): self.assertEqual(str(site_navigation).strip(), expected[index])
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 = build.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_yaml_meta_data_not_dict(self): doc = dedent( """ --- - List item --- Doc body """ ) self.assertEqual(utils.meta.get_data(doc), (doc, {}))
def test_yaml_meta_data_invalid(self): doc = dedent( """ --- foo: bar: baz --- Doc body """ ) self.assertEqual(utils.meta.get_data(doc), (doc, {}))
def test_nav_no_title(self): nav_cfg = ['index.md', {'About': 'about.md'}] expected = dedent(""" Page(title=[blank], url='/') Page(title='About', url='/about/') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File(nav_cfg[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File(nav_cfg[1]['About'], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 2) self.assertEqual(len(site_navigation.pages), 2)
def test_mm_meta_data(self): doc = dedent(""" Title: Foo Bar Date: 2018-07-10 Summary: Line one Line two Tags: foo Tags: bar Doc body """) self.assertEqual(utils.meta.get_data(doc), ("Doc body", { 'title': 'Foo Bar', 'date': '2018-07-10', 'summary': 'Line one Line two', 'tags': 'foo bar' }))
def test_invalid_config(self): file_contents = dedent(""" - ['index.md', 'Introduction'] - ['index.md', 'Introduction'] - ['index.md', 'Introduction'] """) config_file = tempfile.NamedTemporaryFile('w', delete=False) try: config_file.write(ensure_utf(file_contents)) config_file.flush() config_file.close() self.assertRaises(ConfigurationError, config.load_config, config_file=open(config_file.name, 'rb')) finally: os.remove(config_file.name)
def test_create_search_index(self): html_content = """ <h1 id="heading-1">Heading 1</h1> <p>Content 1</p> <h2 id="heading-2">Heading 2</h1> <p>Content 2</p> <h3 id="heading-3">Heading 3</h1> <p>Content 3</p> """ pages = [ ('index.md', 'Home'), ('about.md', 'About') ] site_navigation = nav.SiteNavigation(pages) md = dedent(""" # Heading 1 ## Heading 2 ### Heading 3 """) toc = markdown_to_toc(md) full_content = ''.join("""Heading{0}Content{0}""".format(i) for i in range(1, 4)) for page in site_navigation: index = search.SearchIndex() index.add_entry_from_context(page, html_content, toc) self.assertEqual(len(index._entries), 3) loc = page.abs_url self.assertEqual(index._entries[0]['title'], page.title) self.assertEqual(strip_whitespace(index._entries[0]['text']), full_content) self.assertEqual(index._entries[0]['location'], loc) self.assertEqual(index._entries[1]['title'], "Heading 1") self.assertEqual(index._entries[1]['text'], "Content 1") self.assertEqual(index._entries[1]['location'], "{0}#heading-1".format(loc)) self.assertEqual(index._entries[2]['title'], "Heading 2") self.assertEqual(strip_whitespace(index._entries[2]['text']), "Content2Heading3Content3") self.assertEqual(index._entries[2]['location'], "{0}#heading-2".format(loc))
def test_theme(self): base_config = dedent(""" site_name: Example pages: - ['index.md', 'Introduction'] %s """) configs = [ "site_name: Example", # default theme "theme: readthedocs", # builtin theme "theme_dir: mytheme", # custom only "theme: cosmo\ntheme_dir: custom" # builtin and custom ] abs_path = os.path.abspath(os.path.dirname(__file__)) theme_dir = os.path.abspath(os.path.join(abs_path, '../themes')) results = ( [ '%s/mkdocs' % theme_dir, ], [ '%s/readthedocs' % theme_dir, ], [ 'mytheme', ], [ 'custom', '%s/cosmo' % theme_dir, ], ) for config_contents, expected_result in zip(configs, results): try: config_file = tempfile.NamedTemporaryFile('w', delete=False) config_file.write(ensure_utf(base_config % config_contents)) config_file.flush() options = {'config': config_file.name} result = config.load_config(options=options) self.assertEqual(result['theme_dir'], expected_result) finally: os.remove(config_file.name)
def test_page(title, filename, config): test_page = Page( title, File(filename, config['docs_dir'], config['site_dir'], config['use_directory_urls']), config) test_page.content = """ <h1 id="heading-1">Heading 1</h1> <p>Content 1</p> <h2 id="heading-2">Heading 2</h1> <p>Content 2</p> <h3 id="heading-3">Heading 3</h1> <p>Content 3</p>""" test_page.markdown = dedent(""" # Heading 1 ## Heading 2 ### Heading 3""") test_page.toc = get_toc(get_markdown_toc(test_page.markdown)) return test_page
def test_env_var_in_yaml(self): yaml_src = dedent(''' key1: !ENV VARNAME key2: !ENV UNDEFINED key3: !ENV [UNDEFINED, default] key4: !ENV [UNDEFINED, VARNAME, default] key5: !ENV BOOLVAR ''') config = utils.yaml_load(yaml_src) self.assertIsInstance(config['key1'], str) self.assertEqual(config['key1'], 'Hello, World!') self.assertIsNone(config['key2']) self.assertIsInstance(config['key3'], str) self.assertEqual(config['key3'], 'default') self.assertIsInstance(config['key4'], str) self.assertEqual(config['key4'], 'Hello, World!') self.assertIs(config['key5'], False)
def test_nav_from_files(self): expected = dedent(""" Page(title=[blank], url='/') Page(title=[blank], url='/about/') """) cfg = load_config(site_url='http://example.com/') files = Files([ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 2) self.assertEqual(len(site_navigation.pages), 2) self.assertEqual(repr(site_navigation.homepage), "Page(title=[blank], url='/')")
def test_nav_no_directory_urls(self): nav_cfg = [{'Home': 'index.md'}, {'About': 'about.md'}] expected = dedent(""" Page(title='Home', url='/index.html') Page(title='About', url='/about.html') """) cfg = load_config(nav=nav_cfg, use_directory_urls=False, site_url='http://example.com/') files = Files([ File( list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for item in nav_cfg ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 2) self.assertEqual(len(site_navigation.pages), 2)
def test_nav_missing_page(self): nav_cfg = [{'Home': 'index.md'}] expected = dedent(""" Page(title='Home', url='/') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('page_not_in_nav.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 1) self.assertEqual(len(site_navigation.pages), 1) for file in files: self.assertIsInstance(file.page, Page)
def test_copying_media(self): docs_dir = tempfile.mkdtemp() site_dir = tempfile.mkdtemp() try: # Create a non-empty markdown file, image, dot file and dot directory. f = open(os.path.join(docs_dir, 'index.md'), 'w') f.write( dedent(""" page_title: custom title # Heading 1 This is some text. # Heading 2 And some more text. """)) f.close() open(os.path.join(docs_dir, 'img.jpg'), 'w').close() open(os.path.join(docs_dir, '.hidden'), 'w').close() os.mkdir(os.path.join(docs_dir, '.git')) open(os.path.join(docs_dir, '.git/hidden'), 'w').close() conf = config_base.Config(schema=config_defaults.DEFAULT_SCHEMA) conf.load_dict({ 'site_name': 'Example', 'docs_dir': docs_dir, 'site_dir': site_dir }) conf.validate() build.build(conf) # Verify only the markdown (coverted to html) and the image are copied. self.assertTrue( os.path.isfile(os.path.join(site_dir, 'index.html'))) self.assertTrue(os.path.isfile(os.path.join(site_dir, 'img.jpg'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, '.hidden'))) self.assertFalse( os.path.isfile(os.path.join(site_dir, '.git/hidden'))) finally: shutil.rmtree(docs_dir) shutil.rmtree(site_dir)
def test_theme(self): base_config = dedent(""" site_name: Example pages: - ['index.md', 'Introduction'] %s """) configs = [ "site_name: Example", # default theme "theme: readthedocs", # builtin theme "theme_dir: mytheme", # custom only "theme: cosmo\ntheme_dir: custom" # builtin and custom ] abs_path = os.path.abspath(os.path.dirname(__file__)) theme_dir = os.path.abspath(os.path.join(abs_path, '..', 'themes')) search_asset_dir = os.path.abspath( os.path.join(abs_path, '..', 'assets', 'search')) results = ( [os.path.join(theme_dir, 'mkdocs'), search_asset_dir], [os.path.join(theme_dir, 'readthedocs'), search_asset_dir], ['mytheme', search_asset_dir], ['custom', os.path.join(theme_dir, 'cosmo'), search_asset_dir], ) for config_contents, expected_result in zip(configs, results): try: config_file = tempfile.NamedTemporaryFile('w', delete=False) config_file.write(ensure_utf(base_config % config_contents)) config_file.flush() result = config.load_config( config_file=open(config_file.name, 'rb')) self.assertEqual(result['theme_dir'], expected_result) finally: try: config_file.close() os.remove(config_file.name) except: # This failed on Windows for some reason? pass
def test_nested_ungrouped_nav_no_titles(self): nav_cfg = ['index.md', 'about/contact.md', 'about/sub/license.md'] expected = dedent(""" Page(title=[blank], url='/') Page(title=[blank], url='/about/contact/') Page(title=[blank], url='/about/sub/license/') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File(item, cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for item in nav_cfg ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 3) self.assertEqual(len(site_navigation.pages), 3) self.assertEqual(repr(site_navigation.homepage), "Page(title=[blank], url='/')")
def test_page_render(self): cfg = load_config() fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', fl, cfg) pg.read_source(cfg) self.assertEqual(pg.content, None) self.assertEqual(pg.toc, []) pg.render(cfg, [fl]) self.assertTrue( pg.content.startswith( '<h1 id="welcome-to-mkdocs">Welcome to MkDocs</h1>\n')) self.assertEqual( str(pg.toc).strip(), dedent(""" Welcome to MkDocs - #welcome-to-mkdocs Commands - #commands Project layout - #project-layout """))
def test_yaml_meta_data(self): doc = dedent(""" --- Title: Foo Bar Date: 2018-07-10 Summary: Line one Line two Tags: - foo - bar --- Doc body """) self.assertEqual(utils.meta.get_data(doc), ("Doc body", { 'Title': 'Foo Bar', 'Date': datetime.date(2018, 7, 10), 'Summary': 'Line one Line two', 'Tags': ['foo', 'bar'] }))
def test_nested_ungrouped_nav(self): nav_cfg = [ {'Home': 'test.md'}, {'Contact': 'about/contact.md'}, {'License Title': 'about/sub/license.md'}, ] expected = dedent(""" Page(title='Home', url='/') Page(title='Contact', url='/about/contact/') Page(title='License Title', url='/about/sub/license/') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files( [File(list(item.values())[0], cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) for item in nav_cfg] ) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 3) self.assertEqual(len(site_navigation.pages), 3)
def test_dont_convert_code_block_urls(self): pages = [ 'index.md', 'internal.md', 'sub/internal.md', ] config = load_config(pages=pages) site_navigation = nav.SiteNavigation(config) 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(): page.markdown = 'An HTML Anchor::\n\n <a href="index.md">My example link</a>\n' page.render(config, site_navigation) self.assertEqual(page.content, expected)
def test_nested_ungrouped(self): pages = [ { 'Home': 'index.md' }, { 'Contact': 'about/contact.md' }, { 'License Title': 'about/sub/license.md' }, ] expected = dedent(""" Home - / Contact - /about/contact/ License Title - /about/sub/license/ """) site_navigation = nav.SiteNavigation(pages) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.nav_items), 3) self.assertEqual(len(site_navigation.pages), 3)
def test_indented_toc(self): pages = [('index.md', 'Home'), ('api-guide/running.md', 'API Guide', 'Running'), ('api-guide/testing.md', 'API Guide', 'Testing'), ('api-guide/debugging.md', 'API Guide', 'Debugging'), ('about/release-notes.md', 'About', 'Release notes'), ('about/license.md', 'About', 'License')] expected = dedent(""" Home - / API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About Release notes - /about/release-notes/ License - /about/license/ """) site_navigation = nav.SiteNavigation(pages) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.nav_items), 3) self.assertEqual(len(site_navigation.pages), 6)
def test_copying_media(self): docs_dir = tempfile.mkdtemp() site_dir = tempfile.mkdtemp() try: # Create a non-empty markdown file, image, html file, dot file and dot directory. f = open(os.path.join(docs_dir, 'index.md'), 'w') f.write( dedent(""" page_title: custom title # Heading 1 This is some text. # Heading 2 And some more text. """)) f.close() open(os.path.join(docs_dir, 'img.jpg'), 'w').close() open(os.path.join(docs_dir, 'example.html'), 'w').close() open(os.path.join(docs_dir, '.hidden'), 'w').close() os.mkdir(os.path.join(docs_dir, '.git')) open(os.path.join(docs_dir, '.git/hidden'), 'w').close() cfg = load_config(docs_dir=docs_dir, site_dir=site_dir) build.build(cfg) # Verify only the markdown (coverted to html) and the image are copied. self.assertTrue( os.path.isfile(os.path.join(site_dir, 'index.html'))) self.assertTrue(os.path.isfile(os.path.join(site_dir, 'img.jpg'))) self.assertTrue( os.path.isfile(os.path.join(site_dir, 'example.html'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, '.hidden'))) self.assertFalse( os.path.isfile(os.path.join(site_dir, '.git/hidden'))) finally: shutil.rmtree(docs_dir) shutil.rmtree(site_dir)
def test_nav_external_links(self): nav_cfg = [{ 'Home': 'index.md' }, { 'Local': '/local.html' }, { 'External': 'http://example.com/external.html' }] expected = dedent(""" Page(title='Home', url='/') Link(title='Local', url='/local.html') Link(title='External', url='http://example.com/external.html') """) cfg = load_config(nav=nav_cfg, site_url='http://example.com/') files = Files([ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 3) self.assertEqual(len(site_navigation.pages), 1)
def test_copy_theme_files(self): docs_dir = tempfile.mkdtemp() site_dir = tempfile.mkdtemp() try: # Create a non-empty markdown file. f = open(os.path.join(docs_dir, 'index.md'), 'w') f.write( dedent(""" page_title: custom title # Heading 1 This is some text. """)) f.close() cfg = load_config(docs_dir=docs_dir, site_dir=site_dir) build.build(cfg) # Verify only theme media are copied, not templates or Python files. self.assertTrue( os.path.isfile(os.path.join(site_dir, 'index.html'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'js'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'css'))) self.assertTrue(os.path.isdir(os.path.join(site_dir, 'img'))) self.assertFalse( os.path.isfile(os.path.join(site_dir, '__init__.py'))) self.assertFalse( os.path.isfile(os.path.join(site_dir, '__init__.pyc'))) self.assertFalse( os.path.isfile(os.path.join(site_dir, 'base.html'))) self.assertFalse( os.path.isfile(os.path.join(site_dir, 'content.html'))) self.assertFalse(os.path.isfile(os.path.join(site_dir, 'nav.html'))) finally: shutil.rmtree(docs_dir) shutil.rmtree(site_dir)
def test_indented_toc(self): pages = [{ 'Home': 'index.md' }, { 'API Guide': [ { 'Running': 'api-guide/running.md' }, { 'Testing': 'api-guide/testing.md' }, { 'Debugging': 'api-guide/debugging.md' }, ] }, { 'About': [ 'about/index.md', { 'Release notes': 'about/release-notes.md' }, { 'License': 'about/license.md' } ] }] expected = dedent(""" Home - / API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About - /about/ Release notes - /about/release-notes/ License - /about/license/ """) site_navigation = nav.SiteNavigation(pages) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.nav_items), 3) self.assertEqual(len(site_navigation.pages), 7)
def test_nav_from_nested_files(self): expected = dedent(""" Page(title=[blank], url='/') Section(title='About') Page(title=[blank], url='/about/license/') Page(title=[blank], url='/about/release-notes/') Section(title='Api guide') Page(title=[blank], url='/api-guide/debugging/') Page(title=[blank], url='/api-guide/running/') Page(title=[blank], url='/api-guide/testing/') Section(title='Advanced') Page(title=[blank], url='/api-guide/advanced/part-1/') """) cfg = load_config(site_url='http://example.com/') files = Files([ File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('about/license.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('about/release-notes.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('api-guide/debugging.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('api-guide/running.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('api-guide/testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), File('api-guide/advanced/part-1.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), ]) site_navigation = get_navigation(files, cfg) self.assertEqual(str(site_navigation).strip(), expected) self.assertEqual(len(site_navigation.items), 3) self.assertEqual(len(site_navigation.pages), 7) self.assertEqual(repr(site_navigation.homepage), "Page(title=[blank], url='/')")
def test_yaml_load(self): try: from collections import OrderedDict except ImportError: # Don't test if can't import OrderdDict # Exception can be removed when Py26 support is removed return yaml_text = dedent(''' test: key1: 1 key2: 2 key3: 3 key4: 4 key5: 5 key5: 6 key3: 7 ''') self.assertEqual( utils.yaml_load(yaml_text), OrderedDict([('test', OrderedDict([('key1', 1), ('key2', 2), ('key3', 7), ('key4', 4), ('key5', 6)]))]))
def test_find_toc_by_id(self): """ Test finding the relevant TOC item by the tag ID. """ index = search.SearchIndex() md = dedent(""" # Heading 1 ## Heading 2 ### Heading 3 """) toc = markdown_to_toc(md) toc_item = index._find_toc_by_id(toc, "heading-1") self.assertEqual(toc_item.url, "#heading-1") self.assertEqual(toc_item.title, "Heading 1") toc_item2 = index._find_toc_by_id(toc, "heading-2") self.assertEqual(toc_item2.url, "#heading-2") self.assertEqual(toc_item2.title, "Heading 2") toc_item3 = index._find_toc_by_id(toc, "heading-3") self.assertEqual(toc_item3, None)
def test_walk_indented_toc(self): pages = legacy.pages_compat_shim([ ('index.md', 'Home'), ('api-guide/running.md', 'API Guide', 'Running'), ('api-guide/testing.md', 'API Guide', 'Testing'), ('api-guide/debugging.md', 'API Guide', 'Debugging'), ('about/release-notes.md', 'About', 'Release notes'), ('about/license.md', 'About', 'License') ]) expected = [ dedent(""" Home - / [*] API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About Release notes - /about/release-notes/ License - /about/license/ """), dedent(""" Home - / API Guide [*] Running - /api-guide/running/ [*] Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About Release notes - /about/release-notes/ License - /about/license/ """), dedent(""" Home - / API Guide [*] Running - /api-guide/running/ Testing - /api-guide/testing/ [*] Debugging - /api-guide/debugging/ About Release notes - /about/release-notes/ License - /about/license/ """), dedent(""" Home - / API Guide [*] Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ [*] About Release notes - /about/release-notes/ License - /about/license/ """), dedent(""" Home - / API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About [*] Release notes - /about/release-notes/ [*] License - /about/license/ """), dedent(""" Home - / API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About [*] Release notes - /about/release-notes/ License - /about/license/ [*] """) ] site_navigation = nav.SiteNavigation(pages) for index, page in enumerate(site_navigation.walk_pages()): self.assertEqual(str(site_navigation).strip(), expected[index])
def test_nesting(self): pages_config = [{ 'Home': 'index.md' }, { 'Install': [ { 'Pre-install': 'install/install-pre.md' }, { 'The install': 'install/install-actual.md' }, { 'Post install': 'install/install-post.md' }, ] }, { 'Guide': [ { 'Tutorial': [ { 'Getting Started': 'guide/tutorial/running.md' }, { 'Advanced Features': 'guide/tutorial/testing.md' }, { 'Further Reading': 'guide/tutorial/debugging.md' }, ] }, { 'API Reference': [ { 'Feature 1': 'guide/api-ref/running.md' }, { 'Feature 2': 'guide/api-ref/testing.md' }, { 'Feature 3': 'guide/api-ref/debugging.md' }, ] }, { 'Testing': 'guide/testing.md' }, { 'Deploying': 'guide/deploying.md' }, ] }] site_navigation = nav.SiteNavigation(pages_config) self.assertEqual([n.title for n in site_navigation.nav_items], ['Home', 'Install', 'Guide']) self.assertEqual(len(site_navigation.pages), 12) expected = dedent(""" Home - / Install Pre-install - /install/install-pre/ The install - /install/install-actual/ Post install - /install/install-post/ Guide Tutorial Getting Started - /guide/tutorial/running/ Advanced Features - /guide/tutorial/testing/ Further Reading - /guide/tutorial/debugging/ API Reference Feature 1 - /guide/api-ref/running/ Feature 2 - /guide/api-ref/testing/ Feature 3 - /guide/api-ref/debugging/ Testing - /guide/testing/ Deploying - /guide/deploying/ """) self.maxDiff = None self.assertEqual(str(site_navigation).strip(), expected)
def test_walk_indented_toc(self): pages = [{ 'Home': 'index.md' }, { 'API Guide': [ { 'Running': 'api-guide/running.md' }, { 'Testing': 'api-guide/testing.md' }, { 'Debugging': 'api-guide/debugging.md' }, ] }, { 'About': [{ 'Release notes': 'about/release-notes.md' }, { 'License': 'about/license.md' }] }] expected = [ dedent(""" Home - / [*] API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About Release notes - /about/release-notes/ License - /about/license/ """), dedent(""" Home - / API Guide [*] Running - /api-guide/running/ [*] Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About Release notes - /about/release-notes/ License - /about/license/ """), dedent(""" Home - / API Guide [*] Running - /api-guide/running/ Testing - /api-guide/testing/ [*] Debugging - /api-guide/debugging/ About Release notes - /about/release-notes/ License - /about/license/ """), dedent(""" Home - / API Guide [*] Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ [*] About Release notes - /about/release-notes/ License - /about/license/ """), dedent(""" Home - / API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About [*] Release notes - /about/release-notes/ [*] License - /about/license/ """), dedent(""" Home - / API Guide Running - /api-guide/running/ Testing - /api-guide/testing/ Debugging - /api-guide/debugging/ About [*] Release notes - /about/release-notes/ License - /about/license/ [*] """) ] site_navigation = nav.SiteNavigation(pages) for index, page in enumerate(site_navigation.walk_pages()): self.assertEqual(str(site_navigation).strip(), expected[index])
def test_no_meta_data(self): doc = dedent(""" Doc body """) self.assertEqual(utils.meta.get_data(doc), (doc, {}))