def test_create_media_urls(self): expected_results = { 'https://media.cdn.org/jq.js': [ 'https://media.cdn.org/jq.js', 'https://media.cdn.org/jq.js', 'https://media.cdn.org/jq.js' ], 'http://media.cdn.org/jquery.js': [ 'http://media.cdn.org/jquery.js', 'http://media.cdn.org/jquery.js', 'http://media.cdn.org/jquery.js' ], '//media.cdn.org/jquery.js': [ '//media.cdn.org/jquery.js', '//media.cdn.org/jquery.js', '//media.cdn.org/jquery.js' ], 'media.cdn.org/jquery.js': [ 'media.cdn.org/jquery.js', 'media.cdn.org/jquery.js', '../media.cdn.org/jquery.js' ], 'local/file/jquery.js': [ 'local/file/jquery.js', 'local/file/jquery.js', '../local/file/jquery.js' ], 'local\\windows\\file\\jquery.js': [ 'local/windows/file/jquery.js', 'local/windows/file/jquery.js', '../local/windows/file/jquery.js' ], 'image.png': [ 'image.png', 'image.png', '../image.png' ], 'style.css?v=20180308c': [ 'style.css?v=20180308c', 'style.css?v=20180308c', '../style.css?v=20180308c' ], '#some_id': [ '#some_id', '#some_id', '#some_id' ] } cfg = load_config(use_directory_urls=False) pages = [ Page('Home', File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg), Page('About', File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg), Page('FooBar', File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg) ] for i, page in enumerate(pages): urls = utils.create_media_urls(expected_results.keys(), page) self.assertEqual([v[i] for v in expected_results.values()], urls)
def test_missing_page(self): cfg = load_config() fl = File('missing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', fl, cfg) with self.assertRaises(OSError): pg.read_source(cfg)
def on_page_markdown( self, markdown: str, page: Page, config: Config, files: Files, ): """Inject page template path, if necessary.""" page.iri = iri_by_page(page) try: template_url = Render( ldflex=self.octiron.ldflex, ).find_facet_iri( node=page.iri, environments=[URIRef(OCTA)], ) except FacetNotFound: return markdown page.meta['template'] = re.sub( '^templates:', '', template_url, ) return markdown
def test_nested_index_page_no_parent_no_directory_urls(self): cfg = load_config(docs_dir=self.DOCS_DIR, use_directory_urls=False) fl = File('sub1/index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', fl, cfg) pg.parent = None # non-homepage at nav root level; see #1919. self.assertEqual(pg.url, 'sub1/index.html') self.assertEqual(pg.abs_url, '/sub1/index.html') self.assertEqual(pg.canonical_url, 'https://example.com/sub1/index.html') self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertFalse(pg.is_homepage) self.assertTrue(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertEqual(pg.markdown, None) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Foo') self.assertEqual(pg.toc, [])
def build_page(title, path, config, md_src=''): """ Helper which returns a Page object. """ files = Files([File(path, config['docs_dir'], config['site_dir'], config['use_directory_urls'])]) page = Page(title, list(files)[0], config) # Fake page.read_source() page.markdown, page.meta = meta.get_data(md_src) return page, files
def get_rendered_result(self, files): cfg = load_config(docs_dir=self.DOCS_DIR) fs = [] for f in files: fs.append(File(f.replace('/', os.sep), cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls'])) pg = Page('Foo', fs[0], cfg) pg.read_source(cfg) pg.render(cfg, Files(fs)) return pg.content
def test_page_ne(self): cfg = load_config() f1 = File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) f2 = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', f1, cfg) # Different Title self.assertTrue(pg != Page('Bar', f1, cfg)) # Different File self.assertTrue(pg != Page('Foo', f2, cfg))
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> """ cfg = load_config() pages = [ Page('Home', File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg), Page('About', File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']), cfg) ] md = dedent(""" # Heading 1 ## Heading 2 ### Heading 3 """) toc = get_toc(get_markdown_toc(md)) full_content = ''.join("""Heading{0}Content{0}""".format(i) for i in range(1, 4)) for page in pages: # Fake page.read_source() and page.render() page.markdown = md page.toc = toc page.content = html_content index = search_index.SearchIndex() index.add_entry_from_context(page) self.assertEqual(len(index._entries), 4) loc = page.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']), "Content2") self.assertEqual(index._entries[2]['location'], "{0}#heading-2".format(loc)) self.assertEqual(index._entries[3]['title'], "Heading 3") self.assertEqual(strip_whitespace(index._entries[3]['text']), "Content3") self.assertEqual(index._entries[3]['location'], "{0}#heading-3".format(loc))
def _rearrange_page(self, page: Page) -> Page: iri = iri_by_page(page) page_from_graph = self.pages_from_graph.get(iri) if page_from_graph: page.title = page_from_graph.title page.position = page_from_graph.position else: page.position = PAGE_DEFAULT_POSITION return page
def test_BOM(self): md_src = '# An UTF-8 encoded file with a BOM' with TemporaryDirectory() as docs_dir: # We don't use mkdocs.tests.base.tempdir decorator here due to uniqueness of this test. cfg = load_config(docs_dir=docs_dir) fl = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page(None, fl, cfg) # Create an UTF-8 Encoded file with BOM (as Micorsoft editors do). See #1186 with open(fl.abs_src_path, 'w', encoding='utf-8-sig') as f: f.write(md_src) # Now read the file. pg.read_source(cfg) # Ensure the BOM (`\ufeff`) is removed self.assertNotIn('\ufeff', pg.markdown) self.assertEqual(pg.markdown, md_src) self.assertEqual(pg.meta, {})
def test_BOM(self): md_src = '# An UTF-8 encoded file with a BOM' with TemporaryDirectory() as docs_dir: # We don't use mkdocs.tests.base.tempdir decorator here due to uniqueness of this test. cfg = load_config(docs_dir=docs_dir) fl = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page(None, fl, cfg) # Create an UTF-8 Encoded file with BOM (as Micorsoft editors do). See #1186 with io.open(fl.abs_src_path, 'w', encoding='utf-8-sig') as f: f.write(md_src) # Now read the file. pg.read_source(cfg) # Ensure the BOM (`\ufeff`) is removed self.assertNotIn('\ufeff', pg.markdown) self.assertEqual(pg.markdown, md_src) self.assertEqual(pg.meta, {})
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_populate_page_dirty_modified(self, site_dir): cfg = load_config(site_dir=site_dir) file = File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) page = Page('Foo', file, cfg) build._populate_page(page, cfg, Files([file]), dirty=True) self.assertTrue(page.markdown.startswith('# Welcome to MkDocs')) self.assertTrue(page.content.startswith('<h1 id="welcome-to-mkdocs">Welcome to MkDocs</h1>'))
def test_populate_page(self, docs_dir): cfg = load_config(docs_dir=docs_dir) file = File('test.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) page = Page('Foo', file, cfg) build._populate_page(page, cfg, Files([file])) self.assertEqual(page.content, '<p>page content</p>')
def test_homepage(self): cfg = load_config(docs_dir=self.DOCS_DIR) fl = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) self.assertIsNone(fl.page) pg = Page('Foo', fl, cfg) self.assertEqual(fl.page, pg) self.assertEqual(pg.url, '') self.assertEqual(pg.abs_url, None) self.assertEqual(pg.canonical_url, None) self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertTrue(pg.is_homepage) self.assertTrue(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertEqual(pg.markdown, None) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Foo') self.assertEqual(pg.toc, [])
def test_populate_page_dirty_not_modified(self, site_dir, docs_dir): cfg = load_config(docs_dir=docs_dir, site_dir=site_dir) file = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) page = Page('Foo', file, cfg) build._populate_page(page, cfg, Files([file]), dirty=True) # Content is empty as file read was skipped self.assertEqual(page.markdown, None) self.assertEqual(page.content, None)
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 on_page_context( self, context: TemplateContext, page: Page, config: Config, nav: Page, ) -> TemplateContext: """Attach the views to certain pages.""" page_iri = rdflib.URIRef( f'{LOCAL}{page.file.src_path}', ) this_choices = list(map( operator.itemgetter(rdflib.Variable('this')), self.octiron.graph.query( 'SELECT * WHERE { ?this octa:subjectOf ?page_iri }', initBindings={ 'page_iri': page_iri, }, ).bindings, )) if this_choices: context['this'] = this_choices[0] else: context['this'] = page_iri context['graph'] = self.octiron.graph context['iri'] = page_iri # noinspection PyTypedDict context['query'] = partial( query, instance=self.octiron.graph, ) context['queries'] = self.stored_query context['local'] = LOCAL context['LOCAL'] = LOCAL context.update(self.octiron.namespaces) context['render'] = partial( render, octiron=self.octiron, ) # Provide all the support namespaces into template context context['octiron'] = self.octiron context['link'] = partial( link, octiron=self.octiron, ) # Page attributes page.iri = page_iri return context
def on_page_content(self, html, page: Page, config: Config, files: Files): repo_url = config.get("repo_url", None) edit_uri = config.get("edit_uri", None) if page.file.src_path in self._edit_paths: path = self._edit_paths.pop(page.file.src_path) if repo_url and edit_uri: page.edit_url = path and urllib.parse.urljoin( urllib.parse.urljoin(repo_url, edit_uri), path) return html
def test_populate_page_read_plugin_error(self, docs_dir, mock_open): cfg = load_config(docs_dir=docs_dir) file = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) page = Page('Foo', file, cfg) with self.assertLogs('mkdocs', level='ERROR') as cm: self.assertRaises(PluginError, build._populate_page, page, cfg, Files([file])) self.assertEqual( cm.output, [ "ERROR:mkdocs.commands.build:Error reading page 'index.md':" ] ) self.assert_mock_called_once(mock_open)
def test_populate_page_read_error(self, docs_dir, mock_open): cfg = load_config(docs_dir=docs_dir) file = File('missing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) page = Page('Foo', file, cfg) with self.assertLogs('mkdocs', level='ERROR') as cm: self.assertRaises(OSError, build._populate_page, page, cfg, Files([file])) self.assertEqual( cm.output, [ 'ERROR:mkdocs.structure.pages:File not found: missing.md', "ERROR:mkdocs.commands.build:Error reading page 'missing.md': Error message." ] ) self.assert_mock_called_once(mock_open)
def test_page_title_from_homepage_filename(self): cfg = load_config(docs_dir=self.DOCS_DIR) fl = File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page(None, fl, cfg) pg.read_source(cfg) self.assertEqual(pg.url, '') self.assertEqual(pg.abs_url, None) self.assertEqual(pg.canonical_url, None) self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertTrue(pg.is_homepage) self.assertTrue(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertTrue(pg.markdown.startswith('## Test')) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Home') self.assertEqual(pg.toc, [])
def test_page_title_from_markdown(self): cfg = load_config() fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page(None, fl, cfg) pg.read_source(cfg) self.assertEqual(pg.url, 'testing/') self.assertEqual(pg.abs_url, None) self.assertEqual(pg.canonical_url, None) self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertFalse(pg.is_homepage) self.assertFalse(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertTrue(pg.markdown.startswith('# Welcome to MkDocs\n')) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Welcome to MkDocs') self.assertEqual(pg.toc, [])
def test_nested_nonindex_page(self): cfg = load_config(docs_dir=self.DOCS_DIR) fl = File('sub1/non-index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', fl, cfg) pg.parent = 'foo' self.assertEqual(pg.url, 'sub1/non-index/') self.assertEqual(pg.abs_url, None) self.assertEqual(pg.canonical_url, None) self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertFalse(pg.is_homepage) self.assertFalse(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertFalse(pg.is_top_level) self.assertEqual(pg.markdown, None) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, 'foo') self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Foo') self.assertEqual(pg.toc, [])
def test_page_title_from_meta(self): cfg = load_config(docs_dir=self.DOCS_DIR) fl = File('metadata.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page(None, fl, cfg) pg.read_source(cfg) self.assertEqual(pg.url, 'metadata/') self.assertEqual(pg.abs_url, '/metadata/') self.assertEqual(pg.canonical_url, 'https://example.com/metadata/') self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertFalse(pg.is_homepage) self.assertFalse(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertTrue(pg.markdown.startswith('# Welcome to MkDocs\n')) self.assertEqual(pg.meta, {'title': 'A Page Title'}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'A Page Title') self.assertEqual(pg.toc, [])
def get_navigation(files, config): """ Build site navigation from config and files.""" nav_config = config['nav'] or nest_paths( f.src_path for f in files.documentation_pages()) items = _data_to_navigation(nav_config, files, config) if not isinstance(items, list): items = [items] # Get only the pages from the navigation, ignoring any sections and links. pages = _get_by_type(items, Page) # Include next, previous and parent links. _add_previous_and_next_links(pages) _add_parent_links(items) missing_from_config = [ file for file in files.documentation_pages() if file.page is None ] if missing_from_config: log.info( 'The following pages exist in the docs directory, but are not ' 'included in the "nav" configuration:\n - {}'.format( '\n - '.join([file.src_path for file in missing_from_config]))) # Any documentation files not found in the nav should still have an associated page, so we # create them here. The Page object will automatically be assigned to `file.page` during # its creation (and this is the only way in which these page objects are accessable). for file in missing_from_config: Page(None, file, config) links = _get_by_type(items, Link) for link in links: scheme, netloc, path, params, query, fragment = urlparse(link.url) if scheme or netloc: log.debug("An external link to '{}' is included in " "the 'nav' configuration.".format(link.url)) elif link.url.startswith('/'): log.debug( "An absolute path to '{}' is included in the 'nav' configuration, " "which presumably points to an external resource.".format( link.url)) else: msg = ( "A relative path to '{}' is included in the 'nav' configuration, " "which is not found in the documentation files".format( link.url)) log.warning(msg) return Navigation(items, pages)
def on_page_content(self, html: str, page: Page, config: MkDocsConfig, files: Files): if str(page.file.abs_src_path).endswith("ipynb") and not ( "markdown.extensions.md_in_html" in config["markdown_extensions"] or "markdown.extensions.extra" in config["markdown_extensions"]): log.debug(f"Re-rendering page with markdown in divs: {page}") extensions = [ _RelativePathExtension(page.file, files), "markdown.extensions.md_in_html", ] + config["markdown_extensions"] md = markdown.Markdown(extensions=extensions, extension_configs=config["mdx_configs"] or {}) html = md.convert(page.markdown) page.toc = get_toc(getattr(md, "toc_tokens", [])) return html
def _data_to_navigation(data, files, config): if isinstance(data, dict): return [ _data_to_navigation((key, value), files, config) if isinstance(value, str) else Section( title=key, children=_data_to_navigation(value, files, config)) for key, value in data.items() ] elif isinstance(data, list): return [ _data_to_navigation(item, files, config)[0] if isinstance(item, dict) and len(item) == 1 else _data_to_navigation( item, files, config) for item in data ] title, path = data if isinstance(data, tuple) else (None, data) file = files.get_file_from_path(path) if file: return Page(title, file, config) return Link(title, path)
def test_page_no_directory_url(self): cfg = load_config(use_directory_urls=False) fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', fl, cfg) self.assertEqual(pg.url, 'testing.html') self.assertEqual(pg.abs_url, None) self.assertEqual(pg.canonical_url, None) self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertFalse(pg.is_homepage) self.assertFalse(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertEqual(pg.markdown, None) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Foo') self.assertEqual(pg.toc, [])
def test_page_canonical_url_nested_no_slash(self): cfg = load_config(site_url='http://example.com/foo') fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', fl, cfg) self.assertEqual(pg.url, 'testing/') self.assertEqual(pg.abs_url, '/foo/testing/') self.assertEqual(pg.canonical_url, 'http://example.com/foo/testing/') self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertFalse(pg.is_homepage) self.assertFalse(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertEqual(pg.markdown, None) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Foo') self.assertEqual(pg.toc, [])
def get_navigation(files, config): """ Build site navigation from config and files.""" nav_config = config['nav'] or nest_paths(f.src_path for f in files.documentation_pages()) items = _data_to_navigation(nav_config, files, config) if not isinstance(items, list): items = [items] # Get only the pages from the navigation, ignoring any sections and links. pages = _get_by_type(items, Page) # Include next, previous and parent links. _add_previous_and_next_links(pages) _add_parent_links(items) missing_from_config = [file for file in files.documentation_pages() if file.page is None] if missing_from_config: log.info( 'The following pages exist in the docs directory, but are not ' 'included in the "nav" configuration:\n - {}'.format( '\n - '.join([file.src_path for file in missing_from_config])) ) # Any documentation files not found in the nav should still have an associated page. # However, these page objects are only accessable from File instances as `file.page`. for file in missing_from_config: Page(None, file, config) links = _get_by_type(items, Link) if links: # Assume all links are external. # TODO: warn or error on internal links? log.info( 'The following paths are included in the "nav" configuration, ' 'but do not exist in the docs directory:\n - {}'.format( '\n - '.join([link.url for link in links])) ) return Navigation(items, pages)
def test_page_defaults(self): cfg = load_config() fl = File('testing.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']) pg = Page('Foo', fl, cfg) self.assertRegex(pg.update_date, r'\d{4}-\d{2}-\d{2}') self.assertEqual(pg.url, 'testing/') self.assertEqual(pg.abs_url, '/testing/') self.assertEqual(pg.canonical_url, 'https://example.com/testing/') self.assertEqual(pg.edit_url, None) self.assertEqual(pg.file, fl) self.assertEqual(pg.content, None) self.assertFalse(pg.is_homepage) self.assertFalse(pg.is_index) self.assertTrue(pg.is_page) self.assertFalse(pg.is_section) self.assertTrue(pg.is_top_level) self.assertEqual(pg.markdown, None) self.assertEqual(pg.meta, {}) self.assertEqual(pg.next_page, None) self.assertEqual(pg.parent, None) self.assertEqual(pg.previous_page, None) self.assertEqual(pg.title, 'Foo') self.assertEqual(pg.toc, [])