From 864180f4595c43e1b07bd6e027681e93c45c1dce Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 01:04:05 +0300 Subject: [PATCH 01/22] Add basic support for nested pages What works: template-generated paths (css, js, navbar, etc.) What doesnt: pretty much all rest, including rst-generated urls, breadcrumb, pages hierarchy --- documentation/python.py | 93 +++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index 0c750426..ab77c959 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -45,6 +45,7 @@ import typing from enum import Enum +from pathlib import Path from types import SimpleNamespace as Empty from importlib.machinery import SourceFileLoader from typing import Tuple, Dict, Set, Any, List, Callable, Optional @@ -111,9 +112,11 @@ def default_url_formatter(type: EntryType, path: List[str]) -> Tuple[str, str]: url = 'search-v{}.js'.format(searchdata_format_version) return url, url - - url = '.'.join(path) + '.html' - assert '/' not in url + if type == EntryType.PAGE: + path_sep = '/' + else: + path_sep = '.' + url = path_sep.join(path) + '.html' return url, url # [/default-url-formatter] @@ -1867,7 +1870,38 @@ def extract_data_doc(state: State, parent, entry: Empty): return out -def render(*, config, template: str, url: str, filename: str, env: jinja2.Environment, **kwargs): +def render(*, state, template: str, url: str, filename: str, env: jinja2.Environment, **kwargs): + config=state.config + site_root = ['..'] * filename.count('/') # relative to generated page + + # Filter to return formatted URL or the full URL, if already absolute + def format_url(path): + if urllib.parse.urlparse(path).netloc: return path + + # If file is found relative to the conf file, use that + if os.path.exists(os.path.join(config['INPUT'], path)): + path = os.path.join(config['INPUT'], path) + # Otherwise use path relative to script directory + else: + path = os.path.join(os.path.dirname(os.path.realpath(__file__)), path) + + return '/'.join(site_root + [config['URL_FORMATTER'](EntryType.STATIC, [path])[1]]) # TODO: url shortening can be applied + # Filter to return URL for given symbol. If the path is a string, first try + # to treat it as an URL -- either it needs to have the scheme or at least + # one slash for relative links (in contrast, Python names don't have + # slashes). If that fails, turn it into a list and try to look it up in + # various dicts. + def path_to_url(path): + if isinstance(path, str): + if urllib.parse.urlparse(path).netloc: + return path + path = [path] + entry = state.name_map['.'.join(path)] + return '/'.join(site_root + [entry.url]) # TODO: url shortening can be applied + + env.filters['format_url'] = format_url + env.filters['path_to_url'] = path_to_url + template = env.get_template(template) rendered = template.render(URL=url, SEARCHDATA_FORMAT_VERSION=searchdata_format_version, @@ -1958,7 +1992,7 @@ def render_module(state: State, path, module, env): result.name = path[-1] state.search += [result] - render(config=state.config, + render(state=state, template='module.html', filename=page.filename, url=page.url, @@ -2059,7 +2093,7 @@ def render_class(state: State, path, class_, env): result.name = path[-1] state.search += [result] - render(config=state.config, + render(state=state, template='class.html', filename=page.filename, url=page.url, @@ -2254,7 +2288,7 @@ def render_page(state: State, path, input_filename, env): entry = state.name_map['.'.join(path)] entry.summary = page.summary entry.name = page.breadcrumb[-1][0] - render(config=state.config, + render(state=state, template='page.html', filename=page.filename, url=page.url, @@ -2288,7 +2322,7 @@ def render_page(state: State, path, input_filename, env): metadata[name.lower()] = value # Breadcrumb, we don't do page hierarchy yet - assert len(path) == 1 + # assert len(path) == 1 page.breadcrumb = [(pub.writer.parts.get('title'), url)] # Set page content and add extra metadata from there @@ -2310,7 +2344,7 @@ def render_page(state: State, path, input_filename, env): result.name = path[-1] state.search += [result] - render(config=state.config, + render(state=state, template='page.html', filename=page.filename, url=page.url, @@ -2412,32 +2446,7 @@ def run(basedir, config, *, templates=default_templates, search_add_lookahead_ba env = jinja2.Environment( loader=jinja2.FileSystemLoader(templates), trim_blocks=True, lstrip_blocks=True, enable_async=True) - # Filter to return formatted URL or the full URL, if already absolute - def format_url(path): - if urllib.parse.urlparse(path).netloc: return path - - # If file is found relative to the conf file, use that - if os.path.exists(os.path.join(config['INPUT'], path)): - path = os.path.join(config['INPUT'], path) - # Otherwise use path relative to script directory - else: - path = os.path.join(os.path.dirname(os.path.realpath(__file__)), path) - return config['URL_FORMATTER'](EntryType.STATIC, [path])[1] - # Filter to return URL for given symbol. If the path is a string, first try - # to treat it as an URL -- either it needs to have the scheme or at least - # one slash for relative links (in contrast, Python names don't have - # slashes). If that fails, turn it into a list and try to look it up in - # various dicts. - def path_to_url(path): - if isinstance(path, str): - if urllib.parse.urlparse(path).netloc or '/' in path: return path - path = [path] - entry = state.name_map['.'.join(path)] - return entry.url - - env.filters['format_url'] = format_url - env.filters['path_to_url'] = path_to_url env.filters['urljoin'] = urljoin # Set up extra plugin paths. The one for m.css plugins was added above. @@ -2504,17 +2513,21 @@ def path_to_url(path): # TODO: turn also into some crawl_page() function? once we have subpages? page_index = [] for page in config['INPUT_PAGES']: - page_name = os.path.splitext(os.path.basename(page))[0] + page_path = Path(page) + page_name = page_path.stem entry = Empty() entry.type = EntryType.PAGE - entry.path = [page_name] + entry.path = [parent.name for parent in page_path.parents if parent.name not in ['', '.']] + [page_name] entry.url = config['URL_FORMATTER'](EntryType.PAGE, entry.path)[1] entry.filename = os.path.join(config['INPUT'], page) - state.name_map[page_name] = entry + # using '.' for pages avoids diversity of separator in `path -> name_map key` conversions (there are many) + entry_key = '.'.join(entry.path) + state.name_map[entry_key] = entry # The index page doesn't go to the index - if page_name != 'index': page_index += [page_name] + if entry.path != ['index']: + page_index += [entry_key] # Call all registered post-crawl hooks for hook in state.hooks_post_crawl: @@ -2592,7 +2605,7 @@ def fetch_class_index(entry): index.pages = page_index for file in special_pages[1:]: # exclude index filename, url = config['URL_FORMATTER'](EntryType.SPECIAL, [file]) - render(config=config, + render(state=state, template=file + '.html', filename=filename, url=url, @@ -2609,7 +2622,7 @@ def fetch_class_index(entry): page.filename = filename page.url = url page.breadcrumb = [(config['PROJECT_TITLE'], url)] - render(config=config, + render(state=state, template='page.html', filename=page.filename, url=page.url, From a8174d2a68b27c9fe4a26b0b8dd40f1ca4d28847 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 02:20:29 +0300 Subject: [PATCH 02/22] Patch references in nested pages --- documentation/python.py | 66 +++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index ab77c959..e5b36a81 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -1870,22 +1870,25 @@ def extract_data_doc(state: State, parent, entry: Empty): return out -def render(*, state, template: str, url: str, filename: str, env: jinja2.Environment, **kwargs): - config=state.config - site_root = ['..'] * filename.count('/') # relative to generated page - # Filter to return formatted URL or the full URL, if already absolute - def format_url(path): - if urllib.parse.urlparse(path).netloc: return path +# Filter to return formatted URL or the full URL, if already absolute +def format_url(path, config, site_root): + if urllib.parse.urlparse(path).netloc: return path - # If file is found relative to the conf file, use that - if os.path.exists(os.path.join(config['INPUT'], path)): - path = os.path.join(config['INPUT'], path) - # Otherwise use path relative to script directory - else: - path = os.path.join(os.path.dirname(os.path.realpath(__file__)), path) + # If file is found relative to the conf file, use that + if os.path.exists(os.path.join(config['INPUT'], path)): + path = os.path.join(config['INPUT'], path) + # Otherwise use path relative to script directory + else: + path = os.path.join(os.path.dirname(os.path.realpath(__file__)), path) + + return '/'.join(site_root + [config['URL_FORMATTER'](EntryType.STATIC, [path])[1]]) # TODO: url shortening can be applied + + +def render(*, state, template: str, url: str, filename: str, env: jinja2.Environment, **kwargs): + config = state.config + site_root = ['..'] * filename.count('/') # relative to generated page - return '/'.join(site_root + [config['URL_FORMATTER'](EntryType.STATIC, [path])[1]]) # TODO: url shortening can be applied # Filter to return URL for given symbol. If the path is a string, first try # to treat it as an URL -- either it needs to have the scheme or at least # one slash for relative links (in contrast, Python names don't have @@ -1899,7 +1902,7 @@ def path_to_url(path): entry = state.name_map['.'.join(path)] return '/'.join(site_root + [entry.url]) # TODO: url shortening can be applied - env.filters['format_url'] = format_url + env.filters['format_url'] = lambda path: format_url(path, config, site_root) env.filters['path_to_url'] = path_to_url template = env.get_template(template) @@ -2134,17 +2137,48 @@ def apply(self): # Patch the URL according to the URL formatter image['uri'] = ExtractImages._url_formatter(EntryType.STATIC, [absolute_uri])[1] +# A work-around for stateless Docutils transforms +def get_reference_patcher(site_root, config): + # Patches references in nested pages + class PatchReferences(Transform): + # Run after ExtractImages + default_priority = 992 + + def __init__(self, document, startnode): + Transform.__init__(self, document, startnode=startnode) + + def apply(self): + for ref in self.document.traverse(docutils.nodes.reference): + if 'refuri' in ref.attributes: + old = ref.attributes['refuri'] + new = format_url(old, config, site_root) + if old != new: + ref.attributes['refuri'] = new + logging.debug("reference patched {} -> {} ".format(old, new)) + return PatchReferences + + class DocumentationWriter(m.htmlsanity.SaneHtmlWriter): + def __init__(self, extra_transforms=[]): + super().__init__() + self.extra_transforms = extra_transforms + def get_transforms(self): - return m.htmlsanity.SaneHtmlWriter.get_transforms(self) + [ExtractImages] + return m.htmlsanity.SaneHtmlWriter.get_transforms(self) + [ExtractImages] + self.extra_transforms def publish_rst(state: State, source, *, source_path=None, translator_class=m.htmlsanity.SaneHtmlTranslator): # Make the URL formatter known to the image extractor so it can use it for # patching the URLs ExtractImages._url_formatter = state.config['URL_FORMATTER'] + # FIXME: should count '/' in output uri, not in source_path + if source_path: + site_root = ['..'] * os.path.relpath(source_path, state.config['INPUT']).count('/') + else: + site_root = [] + pub = docutils.core.Publisher( - writer=DocumentationWriter(), + writer=DocumentationWriter(extra_transforms=[get_reference_patcher(site_root, state.config)]), source_class=docutils.io.StringInput, destination_class=docutils.io.StringOutput) pub.set_components('standalone', 'restructuredtext', 'html') From 4006ec09ac00698e685f132137bcb4bd0ba8e697 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 02:40:15 +0300 Subject: [PATCH 03/22] Prevent caching 'format_url' filter results --- documentation/python.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/documentation/python.py b/documentation/python.py index e5b36a81..23aaff31 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -1902,6 +1902,11 @@ def path_to_url(path): entry = state.name_map['.'.join(path)] return '/'.join(site_root + [entry.url]) # TODO: url shortening can be applied + # 'format_url' and 'path_to_url' does not take arguments + # therefore reasonably treated as stateless by Jinja and cached + # A better alternative to cache.clear() would be to pass site_root argument to those filters + env.cache.clear() + env.filters['format_url'] = lambda path: format_url(path, config, site_root) env.filters['path_to_url'] = path_to_url From ec4c8f913a84d7bade7f7d1c5a682dab8044d30e Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 03:13:21 +0300 Subject: [PATCH 04/22] Create breadcrumb for nested pages --- documentation/python.py | 10 +++++++--- documentation/templates/python/page.html | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index 23aaff31..acc9dff5 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -2360,9 +2360,13 @@ def render_page(state: State, path, input_filename, env): value = body_elem.astext() metadata[name.lower()] = value - # Breadcrumb, we don't do page hierarchy yet - # assert len(path) == 1 - page.breadcrumb = [(pub.writer.parts.get('title'), url)] + site_root = ['..'] * url.count('/') # relative to generated page + breadcrumb = [] + for i in range(len(path) - (1 if path[-1] != "index" else 2)): + parent_path = path[:i + 1] + ['index'] + parent = state.name_map['.'.join(parent_path)] + breadcrumb += [(parent.name, '/'.join(site_root + [parent.url]))] + page.breadcrumb = breadcrumb + [(pub.writer.parts.get('title'), url)] # Set page content and add extra metadata from there page.content = pub.writer.parts.get('body').rstrip() diff --git a/documentation/templates/python/page.html b/documentation/templates/python/page.html index f3be8bad..a9c75185 100644 --- a/documentation/templates/python/page.html +++ b/documentation/templates/python/page.html @@ -1,10 +1,10 @@ {% extends 'base.html' %} -{% block title %}{% set j = joiner('.') %}{% for name, _ in page.breadcrumb %}{{ j() }}{{ name }}{% endfor %} | {{ super() }}{% endblock %} +{% block title %}{% set j = joiner(' » ') %}{% for name, _ in page.breadcrumb %}{{ j() }}{{ name }}{% endfor %} | {{ super() }}{% endblock %} {% block main %}

- {%+ for name, target in page.breadcrumb[:-1] %}{{ name }}.{% endfor %}{{ page.breadcrumb[-1][0] }} + {%+ for name, target in page.breadcrumb[:-1] %}{{ name }} » {% endfor %}{{ page.breadcrumb[-1][0] }}

{% if page.summary %}

{{ page.summary }}

From 64302c99dbe2fdce959850e7cbd052c5e2de0739 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 03:40:18 +0300 Subject: [PATCH 05/22] Patch image src too --- documentation/python.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index acc9dff5..974094f5 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -2153,13 +2153,18 @@ def __init__(self, document, startnode): Transform.__init__(self, document, startnode=startnode) def apply(self): - for ref in self.document.traverse(docutils.nodes.reference): - if 'refuri' in ref.attributes: - old = ref.attributes['refuri'] - new = format_url(old, config, site_root) - if old != new: - ref.attributes['refuri'] = new - logging.debug("reference patched {} -> {} ".format(old, new)) + for attr, node_type in [ + ('uri', docutils.nodes.image), + ('refuri', docutils.nodes.reference) + ]: + for ref in self.document.traverse(node_type): + if attr in ref.attributes: + old = ref.attributes[attr] + new = format_url(old, config, site_root) + if old != new: + ref.attributes[attr] = new + logging.debug("reference patched {} -> {} ".format(old, new)) + return PatchReferences From db974439c71ee3baf61bbebdc71fdb5b22439957 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 04:06:43 +0300 Subject: [PATCH 06/22] Add nested page test --- .../test_python/page_nested/classes.html | 46 ++++++++++++++++ .../page_nested/examples/advanced/barz.html | 31 +++++++++++ .../page_nested/examples/advanced/barz.rst | 4 ++ .../page_nested/examples/advanced/fooz.html | 31 +++++++++++ .../page_nested/examples/advanced/fooz.rst | 4 ++ .../page_nested/examples/advanced/index.html | 31 +++++++++++ .../page_nested/examples/advanced/index.rst | 5 ++ .../test_python/page_nested/examples/bar.html | 31 +++++++++++ .../test_python/page_nested/examples/bar.rst | 4 ++ .../test_python/page_nested/examples/foo.html | 31 +++++++++++ .../test_python/page_nested/examples/foo.rst | 4 ++ .../page_nested/examples/index.html | 31 +++++++++++ .../page_nested/examples/index.rst | 4 ++ .../test_python/page_nested/index.html | 31 +++++++++++ .../test_python/page_nested/index.rst | 1 + .../test_python/page_nested/modules.html | 46 ++++++++++++++++ .../test_python/page_nested/pages.html | 52 +++++++++++++++++++ documentation/test_python/test_page.py | 16 ++++++ 18 files changed, 403 insertions(+) create mode 100644 documentation/test_python/page_nested/classes.html create mode 100644 documentation/test_python/page_nested/examples/advanced/barz.html create mode 100644 documentation/test_python/page_nested/examples/advanced/barz.rst create mode 100644 documentation/test_python/page_nested/examples/advanced/fooz.html create mode 100644 documentation/test_python/page_nested/examples/advanced/fooz.rst create mode 100644 documentation/test_python/page_nested/examples/advanced/index.html create mode 100644 documentation/test_python/page_nested/examples/advanced/index.rst create mode 100644 documentation/test_python/page_nested/examples/bar.html create mode 100644 documentation/test_python/page_nested/examples/bar.rst create mode 100644 documentation/test_python/page_nested/examples/foo.html create mode 100644 documentation/test_python/page_nested/examples/foo.rst create mode 100644 documentation/test_python/page_nested/examples/index.html create mode 100644 documentation/test_python/page_nested/examples/index.rst create mode 100644 documentation/test_python/page_nested/index.html create mode 120000 documentation/test_python/page_nested/index.rst create mode 100644 documentation/test_python/page_nested/modules.html create mode 100644 documentation/test_python/page_nested/pages.html diff --git a/documentation/test_python/page_nested/classes.html b/documentation/test_python/page_nested/classes.html new file mode 100644 index 00000000..42e6f455 --- /dev/null +++ b/documentation/test_python/page_nested/classes.html @@ -0,0 +1,46 @@ + + + + + My Python Project + + + + + +
+
+
+
+
+

Classes

+
    +
+ +
+
+
+
+ + diff --git a/documentation/test_python/page_nested/examples/advanced/barz.html b/documentation/test_python/page_nested/examples/advanced/barz.html new file mode 100644 index 00000000..7079708d --- /dev/null +++ b/documentation/test_python/page_nested/examples/advanced/barz.html @@ -0,0 +1,31 @@ + + + + + Examples » Advanced » Barz | My Python Project + + + + + +
+
+ + diff --git a/documentation/test_python/page_nested/examples/advanced/barz.rst b/documentation/test_python/page_nested/examples/advanced/barz.rst new file mode 100644 index 00000000..8d2e9b7a --- /dev/null +++ b/documentation/test_python/page_nested/examples/advanced/barz.rst @@ -0,0 +1,4 @@ +Barz +#### + +Barz example diff --git a/documentation/test_python/page_nested/examples/advanced/fooz.html b/documentation/test_python/page_nested/examples/advanced/fooz.html new file mode 100644 index 00000000..b80926b8 --- /dev/null +++ b/documentation/test_python/page_nested/examples/advanced/fooz.html @@ -0,0 +1,31 @@ + + + + + Examples » Advanced » Fooz | My Python Project + + + + + +
+
+ + diff --git a/documentation/test_python/page_nested/examples/advanced/fooz.rst b/documentation/test_python/page_nested/examples/advanced/fooz.rst new file mode 100644 index 00000000..766e72bc --- /dev/null +++ b/documentation/test_python/page_nested/examples/advanced/fooz.rst @@ -0,0 +1,4 @@ +Fooz +#### + +Fooz example diff --git a/documentation/test_python/page_nested/examples/advanced/index.html b/documentation/test_python/page_nested/examples/advanced/index.html new file mode 100644 index 00000000..490ecec9 --- /dev/null +++ b/documentation/test_python/page_nested/examples/advanced/index.html @@ -0,0 +1,31 @@ + + + + + Examples » Advanced | My Python Project + + + + + +
+
+
+
+
+

+ Examples » Advanced +

+

List of advanced examples

+
+
+
+
+ + diff --git a/documentation/test_python/page_nested/examples/advanced/index.rst b/documentation/test_python/page_nested/examples/advanced/index.rst new file mode 100644 index 00000000..8e6c5ec2 --- /dev/null +++ b/documentation/test_python/page_nested/examples/advanced/index.rst @@ -0,0 +1,5 @@ +Advanced +######## + +List of advanced examples + diff --git a/documentation/test_python/page_nested/examples/bar.html b/documentation/test_python/page_nested/examples/bar.html new file mode 100644 index 00000000..f1c96574 --- /dev/null +++ b/documentation/test_python/page_nested/examples/bar.html @@ -0,0 +1,31 @@ + + + + + Examples » Bar | My Python Project + + + + + +
+
+
+
+
+

+ Examples » Bar +

+

Bar example

+
+
+
+
+ + diff --git a/documentation/test_python/page_nested/examples/bar.rst b/documentation/test_python/page_nested/examples/bar.rst new file mode 100644 index 00000000..983f5d06 --- /dev/null +++ b/documentation/test_python/page_nested/examples/bar.rst @@ -0,0 +1,4 @@ +Bar +### + +Bar example diff --git a/documentation/test_python/page_nested/examples/foo.html b/documentation/test_python/page_nested/examples/foo.html new file mode 100644 index 00000000..b6c1b064 --- /dev/null +++ b/documentation/test_python/page_nested/examples/foo.html @@ -0,0 +1,31 @@ + + + + + Examples » Foo | My Python Project + + + + + +
+
+
+
+
+

+ Examples » Foo +

+

Foo example

+
+
+
+
+ + diff --git a/documentation/test_python/page_nested/examples/foo.rst b/documentation/test_python/page_nested/examples/foo.rst new file mode 100644 index 00000000..807f058a --- /dev/null +++ b/documentation/test_python/page_nested/examples/foo.rst @@ -0,0 +1,4 @@ +Foo +### + +Foo example diff --git a/documentation/test_python/page_nested/examples/index.html b/documentation/test_python/page_nested/examples/index.html new file mode 100644 index 00000000..e2ea497e --- /dev/null +++ b/documentation/test_python/page_nested/examples/index.html @@ -0,0 +1,31 @@ + + + + + Examples | My Python Project + + + + + +
+
+
+
+
+

+ Examples +

+

List of basic examples

+
+
+
+
+ + diff --git a/documentation/test_python/page_nested/examples/index.rst b/documentation/test_python/page_nested/examples/index.rst new file mode 100644 index 00000000..15f379e0 --- /dev/null +++ b/documentation/test_python/page_nested/examples/index.rst @@ -0,0 +1,4 @@ +Examples +######## + +List of basic examples diff --git a/documentation/test_python/page_nested/index.html b/documentation/test_python/page_nested/index.html new file mode 100644 index 00000000..845beadc --- /dev/null +++ b/documentation/test_python/page_nested/index.html @@ -0,0 +1,31 @@ + + + + + Main Page | My Python Project + + + + + +
+
+
+
+
+

+ Main Page +

+

This page is not shown in the page tree.

+
+
+
+
+ + diff --git a/documentation/test_python/page_nested/index.rst b/documentation/test_python/page_nested/index.rst new file mode 120000 index 00000000..c6913089 --- /dev/null +++ b/documentation/test_python/page_nested/index.rst @@ -0,0 +1 @@ +../page/index.rst \ No newline at end of file diff --git a/documentation/test_python/page_nested/modules.html b/documentation/test_python/page_nested/modules.html new file mode 100644 index 00000000..94513796 --- /dev/null +++ b/documentation/test_python/page_nested/modules.html @@ -0,0 +1,46 @@ + + + + + My Python Project + + + + + +
+
+
+
+
+

Modules

+
    +
+ +
+
+
+
+ + diff --git a/documentation/test_python/page_nested/pages.html b/documentation/test_python/page_nested/pages.html new file mode 100644 index 00000000..4d053682 --- /dev/null +++ b/documentation/test_python/page_nested/pages.html @@ -0,0 +1,52 @@ + + + + + My Python Project + + + + + +
+
+
+
+
+

Pages

+ + +
+
+
+
+ + diff --git a/documentation/test_python/test_page.py b/documentation/test_python/test_page.py index 0d412dbb..8d776060 100644 --- a/documentation/test_python/test_page.py +++ b/documentation/test_python/test_page.py @@ -44,6 +44,22 @@ def test(self): self.assertEqual(*self.actual_expected_contents('error.html')) self.assertEqual(*self.actual_expected_contents('pages.html')) + +class Nested(BaseTestCase): + def test(self): + self.run_python({ + 'INPUT_PAGES': [ + 'index.rst', + 'examples/index.rst', + 'examples/foo.rst', + 'examples/bar.rst', + 'examples/advanced/index.rst', + 'examples/advanced/fooz.rst', + 'examples/advanced/barz.rst', + ] + }) + self.assertEqual(*self.actual_expected_contents('index.html')) + class InputSubdir(BaseTestCase): def test(self): self.run_python({ From 004d8815ac0aebb2d372f1505219795221cf0090 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 04:07:06 +0300 Subject: [PATCH 07/22] Fix order of parents) --- documentation/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/python.py b/documentation/python.py index 974094f5..5ae9226a 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -2566,7 +2566,7 @@ def run(basedir, config, *, templates=default_templates, search_add_lookahead_ba entry = Empty() entry.type = EntryType.PAGE - entry.path = [parent.name for parent in page_path.parents if parent.name not in ['', '.']] + [page_name] + entry.path = [parent.name for parent in page_path.parents if parent.name not in ['', '.']][::-1] + [page_name] entry.url = config['URL_FORMATTER'](EntryType.PAGE, entry.path)[1] entry.filename = os.path.join(config['INPUT'], page) # using '.' for pages avoids diversity of separator in `path -> name_map key` conversions (there are many) From 8686cd0854ca1b24dfed0fd0ad55ff231a423a15 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 12:26:14 +0300 Subject: [PATCH 08/22] Fix double-formatting urls --- documentation/python.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/python.py b/documentation/python.py index 5ae9226a..9131ede4 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -2160,7 +2160,8 @@ def apply(self): for ref in self.document.traverse(node_type): if attr in ref.attributes: old = ref.attributes[attr] - new = format_url(old, config, site_root) + if urllib.parse.urlparse(old).netloc: continue + new = '/'.join(site_root + [old]) if old != new: ref.attributes[attr] = new logging.debug("reference patched {} -> {} ".format(old, new)) From f47af6ddcbca9ad24954be27f548b9b71df8fd4a Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 13:55:18 +0300 Subject: [PATCH 09/22] Add cross references to nested page test --- .../page_nested/examples/advanced/barz.html | 2 +- .../page_nested/examples/advanced/barz.rst | 4 +++- .../page_nested/examples/advanced/fooz.rst | 2 ++ .../page_nested/examples/advanced/index.html | 6 +++++- .../page_nested/examples/advanced/index.rst | 4 +++- .../test_python/page_nested/examples/index.html | 12 +++++++++++- .../test_python/page_nested/examples/index.rst | 16 +++++++++++++++- documentation/test_python/page_nested/index.html | 3 ++- documentation/test_python/page_nested/index.rst | 6 +++++- documentation/test_python/test_page.py | 9 +++++++++ 10 files changed, 56 insertions(+), 8 deletions(-) mode change 120000 => 100644 documentation/test_python/page_nested/index.rst diff --git a/documentation/test_python/page_nested/examples/advanced/barz.html b/documentation/test_python/page_nested/examples/advanced/barz.html index 7079708d..c9ef0bc0 100644 --- a/documentation/test_python/page_nested/examples/advanced/barz.html +++ b/documentation/test_python/page_nested/examples/advanced/barz.html @@ -22,7 +22,7 @@

Examples » Advanced » Barz

-

Barz example

+

The barz section example is shown here. It's one of advanced examples,

diff --git a/documentation/test_python/page_nested/examples/advanced/barz.rst b/documentation/test_python/page_nested/examples/advanced/barz.rst index 8d2e9b7a..36f768b2 100644 --- a/documentation/test_python/page_nested/examples/advanced/barz.rst +++ b/documentation/test_python/page_nested/examples/advanced/barz.rst @@ -1,4 +1,6 @@ +.. _Barz: + Barz #### -Barz example +The `barz section `_ example is shown here. It's one of :ref:`advanced examples `, diff --git a/documentation/test_python/page_nested/examples/advanced/fooz.rst b/documentation/test_python/page_nested/examples/advanced/fooz.rst index 766e72bc..27d94780 100644 --- a/documentation/test_python/page_nested/examples/advanced/fooz.rst +++ b/documentation/test_python/page_nested/examples/advanced/fooz.rst @@ -1,3 +1,5 @@ +.. _Fooz: + Fooz #### diff --git a/documentation/test_python/page_nested/examples/advanced/index.html b/documentation/test_python/page_nested/examples/advanced/index.html index 490ecec9..e0b909a6 100644 --- a/documentation/test_python/page_nested/examples/advanced/index.html +++ b/documentation/test_python/page_nested/examples/advanced/index.html @@ -22,7 +22,11 @@

Examples » Advanced

-

List of advanced examples

+

List of advanced examples:

+ diff --git a/documentation/test_python/page_nested/examples/advanced/index.rst b/documentation/test_python/page_nested/examples/advanced/index.rst index 8e6c5ec2..8b8d597b 100644 --- a/documentation/test_python/page_nested/examples/advanced/index.rst +++ b/documentation/test_python/page_nested/examples/advanced/index.rst @@ -1,5 +1,7 @@ Advanced ######## -List of advanced examples +List of advanced examples: +- :ref:`Fooz ` +- :ref:`Barz ` diff --git a/documentation/test_python/page_nested/examples/index.html b/documentation/test_python/page_nested/examples/index.html index e2ea497e..9627e91f 100644 --- a/documentation/test_python/page_nested/examples/index.html +++ b/documentation/test_python/page_nested/examples/index.html @@ -22,7 +22,17 @@

Examples

-

List of basic examples

+
+

Basic

+ +
+
+

Advanced

+

See also advanced page

+
diff --git a/documentation/test_python/page_nested/examples/index.rst b/documentation/test_python/page_nested/examples/index.rst index 15f379e0..6d2dbee5 100644 --- a/documentation/test_python/page_nested/examples/index.rst +++ b/documentation/test_python/page_nested/examples/index.rst @@ -1,4 +1,18 @@ +.. _examples: + Examples ######## -List of basic examples +Basic +----- + +- :ref:`Foo ` +- :ref:`Bar ` + +Advanced +-------- + +See also :ref:`advanced page ` + + + diff --git a/documentation/test_python/page_nested/index.html b/documentation/test_python/page_nested/index.html index 845beadc..b467025a 100644 --- a/documentation/test_python/page_nested/index.html +++ b/documentation/test_python/page_nested/index.html @@ -22,7 +22,8 @@

Main Page

-

This page is not shown in the page tree.

+

This page is not shown in the page tree. +See furious Examples page

diff --git a/documentation/test_python/page_nested/index.rst b/documentation/test_python/page_nested/index.rst deleted file mode 120000 index c6913089..00000000 --- a/documentation/test_python/page_nested/index.rst +++ /dev/null @@ -1 +0,0 @@ -../page/index.rst \ No newline at end of file diff --git a/documentation/test_python/page_nested/index.rst b/documentation/test_python/page_nested/index.rst new file mode 100644 index 00000000..9bdfa40a --- /dev/null +++ b/documentation/test_python/page_nested/index.rst @@ -0,0 +1,5 @@ +Main Page +######### + +This page is not shown in the page tree. +See furious :ref:`Examples page ` diff --git a/documentation/test_python/test_page.py b/documentation/test_python/test_page.py index 8d776060..d49cac63 100644 --- a/documentation/test_python/test_page.py +++ b/documentation/test_python/test_page.py @@ -56,9 +56,18 @@ def test(self): 'examples/advanced/index.rst', 'examples/advanced/fooz.rst', 'examples/advanced/barz.rst', + ], + 'PLUGINS': [ + 'm.sphinx' ] }) self.assertEqual(*self.actual_expected_contents('index.html')) + self.assertEqual(*self.actual_expected_contents('examples/index.html')) + self.assertEqual(*self.actual_expected_contents('examples/foo.html')) + self.assertEqual(*self.actual_expected_contents('examples/bar.html')) + self.assertEqual(*self.actual_expected_contents('examples/advanced/index.html')) + self.assertEqual(*self.actual_expected_contents('examples/advanced/fooz.html')) + self.assertEqual(*self.actual_expected_contents('examples/advanced/barz.html')) class InputSubdir(BaseTestCase): def test(self): From 0f8371832157f05a3a35044c8fa37bc242493a7d Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 14:24:17 +0300 Subject: [PATCH 10/22] Use '/' as nested page separator, avoid `/index` suffix --- documentation/python.py | 17 ++++++++++------- .../page_nested/examples/advanced/barz.rst | 2 +- .../page_nested/examples/advanced/index.rst | 4 ++-- .../test_python/page_nested/examples/index.rst | 6 +++--- documentation/test_python/page_nested/index.rst | 2 +- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index 9131ede4..9dbbe2d0 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -2301,6 +2301,10 @@ def render_doc(state: State, filename): docutils.utils.extract_options = prev_extract_options docutils.utils.assemble_option_dict = prev_assemble_option_dict +def page_path_to_entry_key(path): + # strip 'index' from entry key except for main page + return '/'.join(path[:(-1 if (path[-1] == 'index' and len(path) > 1) else None)]) + def render_page(state: State, path, input_filename, env): filename, url = state.config['URL_FORMATTER'](EntryType.PAGE, path) @@ -2330,7 +2334,7 @@ def render_page(state: State, path, input_filename, env): page.breadcrumb = [(os.path.basename(input_filename), url)] page.summary = '' page.content = '' - entry = state.name_map['.'.join(path)] + entry = state.name_map[page_path_to_entry_key(path)] entry.summary = page.summary entry.name = page.breadcrumb[-1][0] render(state=state, @@ -2369,8 +2373,8 @@ def render_page(state: State, path, input_filename, env): site_root = ['..'] * url.count('/') # relative to generated page breadcrumb = [] for i in range(len(path) - (1 if path[-1] != "index" else 2)): - parent_path = path[:i + 1] + ['index'] - parent = state.name_map['.'.join(parent_path)] + parent_path = path[:i + 1] + parent = state.name_map[page_path_to_entry_key(parent_path)] breadcrumb += [(parent.name, '/'.join(site_root + [parent.url]))] page.breadcrumb = breadcrumb + [(pub.writer.parts.get('title'), url)] @@ -2381,7 +2385,7 @@ def render_page(state: State, path, input_filename, env): # Find itself in the global map, save the page title and summary back there # for index - entry = state.name_map['.'.join(path)] + entry = state.name_map[page_path_to_entry_key(path)] entry.summary = page.summary entry.name = page.breadcrumb[-1][0] @@ -2570,11 +2574,10 @@ def run(basedir, config, *, templates=default_templates, search_add_lookahead_ba entry.path = [parent.name for parent in page_path.parents if parent.name not in ['', '.']][::-1] + [page_name] entry.url = config['URL_FORMATTER'](EntryType.PAGE, entry.path)[1] entry.filename = os.path.join(config['INPUT'], page) - # using '.' for pages avoids diversity of separator in `path -> name_map key` conversions (there are many) - entry_key = '.'.join(entry.path) + entry_key = page_path_to_entry_key(entry.path) state.name_map[entry_key] = entry - # The index page doesn't go to the index + # The main page doesn't go to the index if entry.path != ['index']: page_index += [entry_key] diff --git a/documentation/test_python/page_nested/examples/advanced/barz.rst b/documentation/test_python/page_nested/examples/advanced/barz.rst index 36f768b2..29b09d87 100644 --- a/documentation/test_python/page_nested/examples/advanced/barz.rst +++ b/documentation/test_python/page_nested/examples/advanced/barz.rst @@ -3,4 +3,4 @@ Barz #### -The `barz section `_ example is shown here. It's one of :ref:`advanced examples `, +The `barz section `_ example is shown here. It's one of :ref:`advanced examples `, diff --git a/documentation/test_python/page_nested/examples/advanced/index.rst b/documentation/test_python/page_nested/examples/advanced/index.rst index 8b8d597b..7be2b553 100644 --- a/documentation/test_python/page_nested/examples/advanced/index.rst +++ b/documentation/test_python/page_nested/examples/advanced/index.rst @@ -3,5 +3,5 @@ Advanced List of advanced examples: -- :ref:`Fooz ` -- :ref:`Barz ` +- :ref:`Fooz ` +- :ref:`Barz ` diff --git a/documentation/test_python/page_nested/examples/index.rst b/documentation/test_python/page_nested/examples/index.rst index 6d2dbee5..70a82919 100644 --- a/documentation/test_python/page_nested/examples/index.rst +++ b/documentation/test_python/page_nested/examples/index.rst @@ -6,13 +6,13 @@ Examples Basic ----- -- :ref:`Foo ` -- :ref:`Bar ` +- :ref:`Foo ` +- :ref:`Bar ` Advanced -------- -See also :ref:`advanced page ` +See also :ref:`advanced page ` diff --git a/documentation/test_python/page_nested/index.rst b/documentation/test_python/page_nested/index.rst index 9bdfa40a..254d79d7 100644 --- a/documentation/test_python/page_nested/index.rst +++ b/documentation/test_python/page_nested/index.rst @@ -2,4 +2,4 @@ Main Page ######### This page is not shown in the page tree. -See furious :ref:`Examples page ` +See furious :ref:`Examples page ` From 576320d6f8ae3b064baccfc39bbad591cd462d58 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 19:15:28 +0300 Subject: [PATCH 11/22] Simplify site_root handling --- documentation/python.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index 9dbbe2d0..0f01b51a 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -1882,12 +1882,12 @@ def format_url(path, config, site_root): else: path = os.path.join(os.path.dirname(os.path.realpath(__file__)), path) - return '/'.join(site_root + [config['URL_FORMATTER'](EntryType.STATIC, [path])[1]]) # TODO: url shortening can be applied + return site_root + config['URL_FORMATTER'](EntryType.STATIC, [path])[1] # TODO: url shortening can be applied def render(*, state, template: str, url: str, filename: str, env: jinja2.Environment, **kwargs): config = state.config - site_root = ['..'] * filename.count('/') # relative to generated page + site_root = '../' * filename.count('/') # relative to generated page # Filter to return URL for given symbol. If the path is a string, first try # to treat it as an URL -- either it needs to have the scheme or at least @@ -1900,7 +1900,7 @@ def path_to_url(path): return path path = [path] entry = state.name_map['.'.join(path)] - return '/'.join(site_root + [entry.url]) # TODO: url shortening can be applied + return site_root + entry.url # TODO: url shortening can be applied # 'format_url' and 'path_to_url' does not take arguments # therefore reasonably treated as stateless by Jinja and cached @@ -2143,7 +2143,7 @@ def apply(self): image['uri'] = ExtractImages._url_formatter(EntryType.STATIC, [absolute_uri])[1] # A work-around for stateless Docutils transforms -def get_reference_patcher(site_root, config): +def get_reference_patcher(site_root): # Patches references in nested pages class PatchReferences(Transform): # Run after ExtractImages @@ -2153,6 +2153,8 @@ def __init__(self, document, startnode): Transform.__init__(self, document, startnode=startnode) def apply(self): + if not site_root: + return for attr, node_type in [ ('uri', docutils.nodes.image), ('refuri', docutils.nodes.reference) @@ -2161,7 +2163,7 @@ def apply(self): if attr in ref.attributes: old = ref.attributes[attr] if urllib.parse.urlparse(old).netloc: continue - new = '/'.join(site_root + [old]) + new = site_root + old if old != new: ref.attributes[attr] = new logging.debug("reference patched {} -> {} ".format(old, new)) @@ -2177,19 +2179,15 @@ def __init__(self, extra_transforms=[]): def get_transforms(self): return m.htmlsanity.SaneHtmlWriter.get_transforms(self) + [ExtractImages] + self.extra_transforms -def publish_rst(state: State, source, *, source_path=None, translator_class=m.htmlsanity.SaneHtmlTranslator): +def publish_rst(state: State, source, *, source_path=None, translator_class=m.htmlsanity.SaneHtmlTranslator, subdir_level=0): # Make the URL formatter known to the image extractor so it can use it for # patching the URLs ExtractImages._url_formatter = state.config['URL_FORMATTER'] - # FIXME: should count '/' in output uri, not in source_path - if source_path: - site_root = ['..'] * os.path.relpath(source_path, state.config['INPUT']).count('/') - else: - site_root = [] + site_root = '../' * subdir_level pub = docutils.core.Publisher( - writer=DocumentationWriter(extra_transforms=[get_reference_patcher(site_root, state.config)]), + writer=DocumentationWriter(extra_transforms=[get_reference_patcher(site_root)]), source_class=docutils.io.StringInput, destination_class=docutils.io.StringOutput) pub.set_components('standalone', 'restructuredtext', 'html') @@ -2326,7 +2324,7 @@ def render_page(state: State, path, input_filename, env): # Render the file with open(input_filename, 'r') as f: try: - pub = publish_rst(state, f.read(), source_path=input_filename) + pub = publish_rst(state, f.read(), source_path=input_filename, subdir_level=url.count('/')) except docutils.utils.SystemMessage: logging.error("Failed to process %s, rendering an empty page", input_filename) @@ -2370,12 +2368,16 @@ def render_page(state: State, path, input_filename, env): value = body_elem.astext() metadata[name.lower()] = value - site_root = ['..'] * url.count('/') # relative to generated page + site_root = '../' * url.count('/') # relative to generated page breadcrumb = [] for i in range(len(path) - (1 if path[-1] != "index" else 2)): parent_path = path[:i + 1] - parent = state.name_map[page_path_to_entry_key(parent_path)] - breadcrumb += [(parent.name, '/'.join(site_root + [parent.url]))] + parent_key = page_path_to_entry_key(parent_path) + if parent_key in state.name_map: + parent = state.name_map[parent_key] + breadcrumb += [(parent.name, site_root + parent.url)] + else: + logging.warning("Nested parent page `" + parent_key + "` is not found, skipping from breadcrumb") page.breadcrumb = breadcrumb + [(pub.writer.parts.get('title'), url)] # Set page content and add extra metadata from there From 6b38389aad2c94ef2a8a27c27b12c53ec8897c7b Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 19:26:47 +0300 Subject: [PATCH 12/22] Augment search resuls with '../'* prefixes in nested pages --- documentation/python.py | 2 +- documentation/search.js | 3 +- documentation/templates/python/base.html | 1 + .../test_python/page_nested/classes.html | 54 +++++++++++++++++++ .../page_nested/examples/advanced/barz.html | 54 +++++++++++++++++++ .../page_nested/examples/advanced/fooz.html | 54 +++++++++++++++++++ .../page_nested/examples/advanced/index.html | 54 +++++++++++++++++++ .../test_python/page_nested/examples/bar.html | 54 +++++++++++++++++++ .../test_python/page_nested/examples/foo.html | 54 +++++++++++++++++++ .../page_nested/examples/index.html | 54 +++++++++++++++++++ .../test_python/page_nested/index.html | 54 +++++++++++++++++++ .../test_python/page_nested/modules.html | 54 +++++++++++++++++++ .../test_python/page_nested/pages.html | 54 +++++++++++++++++++ documentation/test_python/test_page.py | 1 + 14 files changed, 545 insertions(+), 2 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index 0f01b51a..d8548c11 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -1913,7 +1913,7 @@ def path_to_url(path): template = env.get_template(template) rendered = template.render(URL=url, SEARCHDATA_FORMAT_VERSION=searchdata_format_version, - **config, **kwargs) + **config, **kwargs, site_root=site_root) output = os.path.join(config['OUTPUT'], filename) output_dir = os.path.dirname(output) if not os.path.exists(output_dir): os.makedirs(output_dir) diff --git a/documentation/search.js b/documentation/search.js index 56ba52fe..5018fbc4 100644 --- a/documentation/search.js +++ b/documentation/search.js @@ -33,6 +33,7 @@ var Search = { map: null, typeMap: null, maxResults: 0, + siteRoot: '', /* a '(../)*' string, needed for nested page support */ /* Always contains at least the root node offset and then one node offset per entered character */ @@ -511,7 +512,7 @@ var Search = { let list = ''; for(let i = 0; i != results.length; ++i) { /* Labels + */ - list += '
' + results[i].typeName + '
' + (results[i].flags & 2 ? '
deprecated
' : '') + (results[i].flags & 4 ? '
deleted
' : ''); + list += '
' + results[i].typeName + '
' + (results[i].flags & 2 ? '
deprecated
' : '') + (results[i].flags & 4 ? '
deleted
' : ''); /* Render the alias (cut off from the right) */ if(results[i].alias) { diff --git a/documentation/templates/python/base.html b/documentation/templates/python/base.html index 79718698..06ba692c 100644 --- a/documentation/templates/python/base.html +++ b/documentation/templates/python/base.html @@ -130,6 +130,7 @@ + {% if SEARCH_DOWNLOAD_BINARY %} + + diff --git a/documentation/test_python/page_nested/examples/advanced/barz.html b/documentation/test_python/page_nested/examples/advanced/barz.html index c9ef0bc0..4e9f8334 100644 --- a/documentation/test_python/page_nested/examples/advanced/barz.html +++ b/documentation/test_python/page_nested/examples/advanced/barz.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -27,5 +45,41 @@

+ + + + diff --git a/documentation/test_python/page_nested/examples/advanced/fooz.html b/documentation/test_python/page_nested/examples/advanced/fooz.html index b80926b8..fbe93559 100644 --- a/documentation/test_python/page_nested/examples/advanced/fooz.html +++ b/documentation/test_python/page_nested/examples/advanced/fooz.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -27,5 +45,41 @@

+ + + + diff --git a/documentation/test_python/page_nested/examples/advanced/index.html b/documentation/test_python/page_nested/examples/advanced/index.html index e0b909a6..b421eeef 100644 --- a/documentation/test_python/page_nested/examples/advanced/index.html +++ b/documentation/test_python/page_nested/examples/advanced/index.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -31,5 +49,41 @@

+ + + + diff --git a/documentation/test_python/page_nested/examples/bar.html b/documentation/test_python/page_nested/examples/bar.html index f1c96574..c0274816 100644 --- a/documentation/test_python/page_nested/examples/bar.html +++ b/documentation/test_python/page_nested/examples/bar.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -27,5 +45,41 @@

+ + + + diff --git a/documentation/test_python/page_nested/examples/foo.html b/documentation/test_python/page_nested/examples/foo.html index b6c1b064..c6d9e7ef 100644 --- a/documentation/test_python/page_nested/examples/foo.html +++ b/documentation/test_python/page_nested/examples/foo.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -27,5 +45,41 @@

+ + + + diff --git a/documentation/test_python/page_nested/examples/index.html b/documentation/test_python/page_nested/examples/index.html index 9627e91f..8294fe1d 100644 --- a/documentation/test_python/page_nested/examples/index.html +++ b/documentation/test_python/page_nested/examples/index.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -37,5 +55,41 @@

Advanced

+ + + + diff --git a/documentation/test_python/page_nested/index.html b/documentation/test_python/page_nested/index.html index b467025a..52fb8266 100644 --- a/documentation/test_python/page_nested/index.html +++ b/documentation/test_python/page_nested/index.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -28,5 +46,41 @@

+ + + + diff --git a/documentation/test_python/page_nested/modules.html b/documentation/test_python/page_nested/modules.html index 94513796..4d6e5eec 100644 --- a/documentation/test_python/page_nested/modules.html +++ b/documentation/test_python/page_nested/modules.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -42,5 +60,41 @@

Modules

+ + + + diff --git a/documentation/test_python/page_nested/pages.html b/documentation/test_python/page_nested/pages.html index 4d053682..0934a8c5 100644 --- a/documentation/test_python/page_nested/pages.html +++ b/documentation/test_python/page_nested/pages.html @@ -12,6 +12,24 @@
My Python Project +
+ + + + + +
+
@@ -48,5 +66,41 @@

Pages

+ + + + diff --git a/documentation/test_python/test_page.py b/documentation/test_python/test_page.py index d49cac63..3dedd37d 100644 --- a/documentation/test_python/test_page.py +++ b/documentation/test_python/test_page.py @@ -57,6 +57,7 @@ def test(self): 'examples/advanced/fooz.rst', 'examples/advanced/barz.rst', ], + 'SEARCH_DISABLED': False, 'PLUGINS': [ 'm.sphinx' ] From 7d09e76adb20b8c485841dd8ae20d138662fdbd4 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 19:41:22 +0300 Subject: [PATCH 13/22] Use breadcrumb page names in search instead of path --- documentation/python.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index d8548c11..01652cc4 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -2395,8 +2395,8 @@ def render_page(state: State, path, input_filename, env): result = Empty() result.flags = ResultFlag.from_type(ResultFlag.NONE, EntryType.PAGE) result.url = page.url - result.prefix = path[:-1] - result.name = path[-1] + result.prefix = [name for name, _ in breadcrumb] + result.name = entry.name state.search += [result] render(state=state, From 8a4ac517db0e5d5072133f540ce55e0f98574ec7 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 20:25:43 +0300 Subject: [PATCH 14/22] Avoid adding extra script line in flat sites --- documentation/templates/python/base.html | 2 ++ documentation/test_python/page_nested/classes.html | 1 - documentation/test_python/page_nested/index.html | 1 - documentation/test_python/page_nested/modules.html | 1 - documentation/test_python/page_nested/pages.html | 1 - 5 files changed, 2 insertions(+), 4 deletions(-) diff --git a/documentation/templates/python/base.html b/documentation/templates/python/base.html index 06ba692c..20c3cb19 100644 --- a/documentation/templates/python/base.html +++ b/documentation/templates/python/base.html @@ -130,7 +130,9 @@ +{% if site_root %} +{% endif %} {% if SEARCH_DOWNLOAD_BINARY %} - diff --git a/documentation/test_python/page_nested/index.html b/documentation/test_python/page_nested/index.html index 52fb8266..f25dc1c8 100644 --- a/documentation/test_python/page_nested/index.html +++ b/documentation/test_python/page_nested/index.html @@ -80,7 +80,6 @@

- diff --git a/documentation/test_python/page_nested/modules.html b/documentation/test_python/page_nested/modules.html index 4d6e5eec..e2e76b05 100644 --- a/documentation/test_python/page_nested/modules.html +++ b/documentation/test_python/page_nested/modules.html @@ -94,7 +94,6 @@

Modules

- diff --git a/documentation/test_python/page_nested/pages.html b/documentation/test_python/page_nested/pages.html index 0934a8c5..78b92119 100644 --- a/documentation/test_python/page_nested/pages.html +++ b/documentation/test_python/page_nested/pages.html @@ -100,7 +100,6 @@

Pages

- From 34c32ce56802acf76bfe639067aa316734900e66 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 20:47:33 +0300 Subject: [PATCH 15/22] (?) Fix discrepancy between offset calculation and entry write --- documentation/_search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/_search.py b/documentation/_search.py index a5db63c0..f66c5c2f 100644 --- a/documentation/_search.py +++ b/documentation/_search.py @@ -264,7 +264,7 @@ def serialize(self, merge_prefixes=True) -> bytearray: if e.flags & ResultFlag.HAS_SUFFIX: output += self.suffix_length_struct.pack(e.suffix_length) output += e.name.encode('utf-8') - if e.url: + if e.name and e.url: output += b'\0' output += e.url.encode('utf-8') From c98516fcbfb70543a5858236fbf589adc154dd8e Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 20:58:03 +0300 Subject: [PATCH 16/22] Fix searchdata.bin download url in nested pages --- documentation/templates/python/base.html | 2 +- documentation/test_python/page_nested/classes.html | 4 +++- .../test_python/page_nested/examples/advanced/barz.html | 4 +++- .../test_python/page_nested/examples/advanced/fooz.html | 4 +++- .../test_python/page_nested/examples/advanced/index.html | 4 +++- documentation/test_python/page_nested/examples/bar.html | 4 +++- documentation/test_python/page_nested/examples/foo.html | 4 +++- documentation/test_python/page_nested/examples/index.html | 4 +++- documentation/test_python/page_nested/index.html | 4 +++- documentation/test_python/page_nested/modules.html | 4 +++- documentation/test_python/page_nested/pages.html | 6 +++++- documentation/test_python/test_page.py | 1 + 12 files changed, 34 insertions(+), 11 deletions(-) diff --git a/documentation/templates/python/base.html b/documentation/templates/python/base.html index 20c3cb19..60db580a 100644 --- a/documentation/templates/python/base.html +++ b/documentation/templates/python/base.html @@ -135,7 +135,7 @@ {% endif %} {% if SEARCH_DOWNLOAD_BINARY %} {% else %} diff --git a/documentation/test_python/page_nested/classes.html b/documentation/test_python/page_nested/classes.html index eb0c2410..878331a1 100644 --- a/documentation/test_python/page_nested/classes.html +++ b/documentation/test_python/page_nested/classes.html @@ -94,6 +94,8 @@

Classes

- + diff --git a/documentation/test_python/page_nested/examples/advanced/barz.html b/documentation/test_python/page_nested/examples/advanced/barz.html index 4e9f8334..eeb286f6 100644 --- a/documentation/test_python/page_nested/examples/advanced/barz.html +++ b/documentation/test_python/page_nested/examples/advanced/barz.html @@ -80,6 +80,8 @@

- + diff --git a/documentation/test_python/page_nested/examples/advanced/fooz.html b/documentation/test_python/page_nested/examples/advanced/fooz.html index fbe93559..99c5b2ed 100644 --- a/documentation/test_python/page_nested/examples/advanced/fooz.html +++ b/documentation/test_python/page_nested/examples/advanced/fooz.html @@ -80,6 +80,8 @@

- + diff --git a/documentation/test_python/page_nested/examples/advanced/index.html b/documentation/test_python/page_nested/examples/advanced/index.html index b421eeef..b10d9970 100644 --- a/documentation/test_python/page_nested/examples/advanced/index.html +++ b/documentation/test_python/page_nested/examples/advanced/index.html @@ -84,6 +84,8 @@

- + diff --git a/documentation/test_python/page_nested/examples/bar.html b/documentation/test_python/page_nested/examples/bar.html index c0274816..1874150e 100644 --- a/documentation/test_python/page_nested/examples/bar.html +++ b/documentation/test_python/page_nested/examples/bar.html @@ -80,6 +80,8 @@

- + diff --git a/documentation/test_python/page_nested/examples/foo.html b/documentation/test_python/page_nested/examples/foo.html index c6d9e7ef..d3cf920a 100644 --- a/documentation/test_python/page_nested/examples/foo.html +++ b/documentation/test_python/page_nested/examples/foo.html @@ -80,6 +80,8 @@

- + diff --git a/documentation/test_python/page_nested/examples/index.html b/documentation/test_python/page_nested/examples/index.html index 8294fe1d..ec1fe97e 100644 --- a/documentation/test_python/page_nested/examples/index.html +++ b/documentation/test_python/page_nested/examples/index.html @@ -90,6 +90,8 @@

Advanced

- + diff --git a/documentation/test_python/page_nested/index.html b/documentation/test_python/page_nested/index.html index f25dc1c8..91dad508 100644 --- a/documentation/test_python/page_nested/index.html +++ b/documentation/test_python/page_nested/index.html @@ -80,6 +80,8 @@

- + diff --git a/documentation/test_python/page_nested/modules.html b/documentation/test_python/page_nested/modules.html index e2e76b05..68beaf0f 100644 --- a/documentation/test_python/page_nested/modules.html +++ b/documentation/test_python/page_nested/modules.html @@ -94,6 +94,8 @@

Modules

- + diff --git a/documentation/test_python/page_nested/pages.html b/documentation/test_python/page_nested/pages.html index 78b92119..347a65ee 100644 --- a/documentation/test_python/page_nested/pages.html +++ b/documentation/test_python/page_nested/pages.html @@ -45,6 +45,8 @@

Pages

  • Advanced
  • Fooz
  • Barz
  • +
  • Page 1
  • +
  • Page 2
  • - + diff --git a/documentation/test_python/test_page.py b/documentation/test_python/test_page.py index 3dedd37d..4ae58465 100644 --- a/documentation/test_python/test_page.py +++ b/documentation/test_python/test_page.py @@ -58,6 +58,7 @@ def test(self): 'examples/advanced/barz.rst', ], 'SEARCH_DISABLED': False, + 'SEARCH_DOWNLOAD_BINARY': True, 'PLUGINS': [ 'm.sphinx' ] From e65d5bd5ec446cfed78f4f2b04f56e05524d59f8 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 21:19:43 +0300 Subject: [PATCH 17/22] Test for missing `index.rst` in nested pages --- .../test_python/page_nested/sub/page1.html | 87 +++++++++++++++++++ .../test_python/page_nested/sub/page1.rst | 4 + .../test_python/page_nested/sub/page2.html | 87 +++++++++++++++++++ .../test_python/page_nested/sub/page2.rst | 4 + documentation/test_python/test_page.py | 4 + 5 files changed, 186 insertions(+) create mode 100644 documentation/test_python/page_nested/sub/page1.html create mode 100644 documentation/test_python/page_nested/sub/page1.rst create mode 100644 documentation/test_python/page_nested/sub/page2.html create mode 100644 documentation/test_python/page_nested/sub/page2.rst diff --git a/documentation/test_python/page_nested/sub/page1.html b/documentation/test_python/page_nested/sub/page1.html new file mode 100644 index 00000000..90f3193c --- /dev/null +++ b/documentation/test_python/page_nested/sub/page1.html @@ -0,0 +1,87 @@ + + + + + Page 1 | My Python Project + + + + + +
    +
    +
    +
    +
    +

    + Page 1 +

    +

    This page doesn't have breadcrumb since there is no corresponding index.rst file

    +
    +
    +
    +
    + + + + + + diff --git a/documentation/test_python/page_nested/sub/page1.rst b/documentation/test_python/page_nested/sub/page1.rst new file mode 100644 index 00000000..74cec7e1 --- /dev/null +++ b/documentation/test_python/page_nested/sub/page1.rst @@ -0,0 +1,4 @@ +Page 1 +====== + +This page doesn't have breadcrumb since there is no corresponding ``index.rst`` file \ No newline at end of file diff --git a/documentation/test_python/page_nested/sub/page2.html b/documentation/test_python/page_nested/sub/page2.html new file mode 100644 index 00000000..0b54de27 --- /dev/null +++ b/documentation/test_python/page_nested/sub/page2.html @@ -0,0 +1,87 @@ + + + + + Page 2 | My Python Project + + + + + +
    +
    +
    +
    +
    +

    + Page 2 +

    +

    This page doesn't have breadcrumb since there is no corresponding index.rst file

    +
    +
    +
    +
    + + + + + + diff --git a/documentation/test_python/page_nested/sub/page2.rst b/documentation/test_python/page_nested/sub/page2.rst new file mode 100644 index 00000000..db5b62f1 --- /dev/null +++ b/documentation/test_python/page_nested/sub/page2.rst @@ -0,0 +1,4 @@ +Page 2 +====== + +This page doesn't have breadcrumb since there is no corresponding ``index.rst`` file \ No newline at end of file diff --git a/documentation/test_python/test_page.py b/documentation/test_python/test_page.py index 4ae58465..2933a0d1 100644 --- a/documentation/test_python/test_page.py +++ b/documentation/test_python/test_page.py @@ -56,6 +56,8 @@ def test(self): 'examples/advanced/index.rst', 'examples/advanced/fooz.rst', 'examples/advanced/barz.rst', + 'sub/page1.rst', + 'sub/page2.rst', ], 'SEARCH_DISABLED': False, 'SEARCH_DOWNLOAD_BINARY': True, @@ -70,6 +72,8 @@ def test(self): self.assertEqual(*self.actual_expected_contents('examples/advanced/index.html')) self.assertEqual(*self.actual_expected_contents('examples/advanced/fooz.html')) self.assertEqual(*self.actual_expected_contents('examples/advanced/barz.html')) + self.assertEqual(*self.actual_expected_contents('sub/page1.html')) + self.assertEqual(*self.actual_expected_contents('sub/page2.html')) class InputSubdir(BaseTestCase): def test(self): From 887f9da99036a2bae948373d87eac0ebeb2d453f Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sat, 27 Jun 2020 22:51:12 +0300 Subject: [PATCH 18/22] Restore old behavior for input paths with `/` The only change is path with '/' first searched in name_map, if not found return as is --- documentation/python.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/documentation/python.py b/documentation/python.py index 01652cc4..85696633 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -1898,6 +1898,10 @@ def path_to_url(path): if isinstance(path, str): if urllib.parse.urlparse(path).netloc: return path + if '/' in path: + if path in state.name_map: + path = state.name_map[path] + return site_root + path path = [path] entry = state.name_map['.'.join(path)] return site_root + entry.url # TODO: url shortening can be applied From d27d5c0c18cf5612bdfea7321ab1f4b46dedc8e7 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sun, 28 Jun 2020 01:13:02 +0300 Subject: [PATCH 19/22] Build hierarchy for 'pages' page --- documentation/python.py | 28 +++++++++++++++---- .../test_python/page_nested/pages.html | 20 +++++++++---- documentation/test_python/test_page.py | 1 + 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index 85696633..00ef5dcf 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -2642,21 +2642,37 @@ def fetch_class_index(entry): for i in range(len(class_index)): class_index[i] = fetch_class_index(state.name_map[class_index[i]]) - # Create page index from the toplevel name list - # TODO: rework when we have nested page support - for i in range(len(page_index)): - entry = state.name_map[page_index[i]] + page_index_map = {} + for page in page_index: + entry = state.name_map[page] assert entry.type == EntryType.PAGE index_entry = Empty() index_entry.kind = 'page' index_entry.name = entry.name - index_entry.url = config['URL_FORMATTER'](entry.type, entry.path)[1] + index_entry.url = entry.url index_entry.summary = entry.summary + index_entry.path = entry.path index_entry.has_nestable_children = False index_entry.children = [] + page_index_map[entry.url] = index_entry + + children_pages = [] + for page_url in list(page_index_map.keys()): + index_entry = page_index_map[page_url] + path = index_entry.path + # Find first existing parent page starting from longest + for i in reversed(range(len(path) - (1 if path[-1] != "index" else 2))): + parent_path = path[:i + 1] + parent_key = page_path_to_entry_key(parent_path) + if parent_key in state.name_map: + parent = page_index_map[state.name_map[parent_key].url] + parent.has_nestable_children = True + parent.children += [index_entry] + children_pages += [page_url] + break - page_index[i] = index_entry + page_index = [page for url, page in page_index_map.items() if url not in children_pages] index = Empty() index.classes = class_index diff --git a/documentation/test_python/page_nested/pages.html b/documentation/test_python/page_nested/pages.html index 347a65ee..fc41bd3a 100644 --- a/documentation/test_python/page_nested/pages.html +++ b/documentation/test_python/page_nested/pages.html @@ -39,12 +39,20 @@

    Pages

    diff --git a/documentation/test_python/test_page.py b/documentation/test_python/test_page.py index 2933a0d1..73119a85 100644 --- a/documentation/test_python/test_page.py +++ b/documentation/test_python/test_page.py @@ -74,6 +74,7 @@ def test(self): self.assertEqual(*self.actual_expected_contents('examples/advanced/barz.html')) self.assertEqual(*self.actual_expected_contents('sub/page1.html')) self.assertEqual(*self.actual_expected_contents('sub/page2.html')) + self.assertEqual(*self.actual_expected_contents('pages.html')) class InputSubdir(BaseTestCase): def test(self): From a3fb4477bd8c5f0a1d97ab5911aa44d67a0f5c57 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sun, 28 Jun 2020 02:09:18 +0300 Subject: [PATCH 20/22] Mirror images location in INPUT directory in OUTPUT --- documentation/python.py | 71 ++++++++++--------- .../page_nested/examples/advanced/fooz.html | 3 +- .../page_nested/examples/advanced/fooz.rst | 5 +- .../page_nested/examples/advanced/icon.svg | 8 +++ .../test_python/page_nested/examples/foo.html | 3 +- .../test_python/page_nested/examples/foo.rst | 5 +- .../test_python/page_nested/examples/icon.svg | 6 ++ documentation/test_python/test_page.py | 2 + 8 files changed, 65 insertions(+), 38 deletions(-) create mode 100644 documentation/test_python/page_nested/examples/advanced/icon.svg create mode 100644 documentation/test_python/page_nested/examples/icon.svg diff --git a/documentation/python.py b/documentation/python.py index 00ef5dcf..0ff79c2e 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -105,6 +105,8 @@ class EntryType(Enum): # [default-url-formatter] def default_url_formatter(type: EntryType, path: List[str]) -> Tuple[str, str]: if type == EntryType.STATIC: + if not os.path.isabs(path[0]): + return path[0], path[0] url = os.path.basename(path[0]) # Encode version information into the search driver @@ -2116,35 +2118,40 @@ def render_class(state: State, path, class_, env): for hook in state.hooks_post_scope: hook(type=EntryType.CLASS, path=path) -# Extracts image paths and transforms them to just the filenames -class ExtractImages(Transform): - # Max Docutils priority is 990, be sure that this is applied at the very - # last - default_priority = 991 - # There is no simple way to have stateful transforms (the publisher always - # gets just the class, not the instance) so we have to make all data - # awfully global. UGH. - # TODO: maybe the pending nodes could solve this? - _url_formatter = None - _external_data = set() +# A helper function to work-around for stateless Docutils transforms +def get_image_extracter(source, external_data:set, config): - def __init__(self, document, startnode): - Transform.__init__(self, document, startnode=startnode) + # Extracts image paths and transforms them to just the filenames + class ExtractImages(Transform): + # Max Docutils priority is 990, be sure that this is applied at the very + # last + default_priority = 991 - def apply(self): - ExtractImages._external_data = set() - for image in self.document.traverse(docutils.nodes.image): - # Skip absolute URLs - if urllib.parse.urlparse(image['uri']).netloc: continue + def __init__(self, document, startnode): + Transform.__init__(self, document, startnode=startnode) - # TODO: is there a non-private access to current document source - # path? - absolute_uri = os.path.join(os.path.dirname(self.document.settings._source), image['uri']) if isinstance(self.document.settings._source, str) else image['uri'] - ExtractImages._external_data.add(absolute_uri) + def apply(self): + input_path = os.path.realpath(config['INPUT']) + for image in self.document.traverse(docutils.nodes.image): + # Skip absolute URLs + if urllib.parse.urlparse(image['uri']).netloc: + continue - # Patch the URL according to the URL formatter - image['uri'] = ExtractImages._url_formatter(EntryType.STATIC, [absolute_uri])[1] + if isinstance(source, str): + image_abs_path = os.path.realpath(os.path.join(os.path.dirname(source), image['uri'])) + # Use relative path if image within INPUT directory, otherwise absolute + if image_abs_path.startswith(input_path): + image_path = os.path.relpath(image_abs_path, input_path) + else: + image_path = image_abs_path + else: + image_path = image['uri'] + external_data.add(image_path) + + # Patch the URL according to the URL formatter + image['uri'] = config['URL_FORMATTER'](EntryType.STATIC, [image_path])[1] + return ExtractImages # A work-around for stateless Docutils transforms def get_reference_patcher(site_root): @@ -2181,17 +2188,13 @@ def __init__(self, extra_transforms=[]): self.extra_transforms = extra_transforms def get_transforms(self): - return m.htmlsanity.SaneHtmlWriter.get_transforms(self) + [ExtractImages] + self.extra_transforms + return m.htmlsanity.SaneHtmlWriter.get_transforms(self) + self.extra_transforms def publish_rst(state: State, source, *, source_path=None, translator_class=m.htmlsanity.SaneHtmlTranslator, subdir_level=0): - # Make the URL formatter known to the image extractor so it can use it for - # patching the URLs - ExtractImages._url_formatter = state.config['URL_FORMATTER'] - site_root = '../' * subdir_level - + external_data = set() pub = docutils.core.Publisher( - writer=DocumentationWriter(extra_transforms=[get_reference_patcher(site_root)]), + writer=DocumentationWriter(extra_transforms=[get_reference_patcher(site_root), get_image_extracter(source_path, external_data, state.config)]), source_class=docutils.io.StringInput, destination_class=docutils.io.StringOutput) pub.set_components('standalone', 'restructuredtext', 'html') @@ -2209,7 +2212,7 @@ def publish_rst(state: State, source, *, source_path=None, translator_class=m.ht pub.publish() # External images to pull later - state.external_data = state.external_data.union(ExtractImages._external_data) + state.external_data = state.external_data.union(external_data) return pub @@ -2742,13 +2745,13 @@ def fetch_class_index(entry): # If file is found relative to the conf file, use that if os.path.exists(os.path.join(config['INPUT'], i)): + output = os.path.join(config['OUTPUT'], config['URL_FORMATTER'](EntryType.STATIC, [i])[0]) i = os.path.join(config['INPUT'], i) - # Otherwise use path relative to script directory else: i = os.path.join(os.path.dirname(os.path.realpath(__file__)), i) + output = os.path.join(config['OUTPUT'], config['URL_FORMATTER'](EntryType.STATIC, [i])[0]) - output = os.path.join(config['OUTPUT'], config['URL_FORMATTER'](EntryType.STATIC, [i])[0]) output_dir = os.path.dirname(output) if not os.path.exists(output_dir): os.makedirs(output_dir) logging.debug("copying %s to output", i) diff --git a/documentation/test_python/page_nested/examples/advanced/fooz.html b/documentation/test_python/page_nested/examples/advanced/fooz.html index 99c5b2ed..40c2356f 100644 --- a/documentation/test_python/page_nested/examples/advanced/fooz.html +++ b/documentation/test_python/page_nested/examples/advanced/fooz.html @@ -40,7 +40,8 @@

    Examples » Advanced » Fooz

    -

    Fooz example

    +

    Fooz example contains square

    +square
    diff --git a/documentation/test_python/page_nested/examples/advanced/fooz.rst b/documentation/test_python/page_nested/examples/advanced/fooz.rst index 27d94780..bd195e8f 100644 --- a/documentation/test_python/page_nested/examples/advanced/fooz.rst +++ b/documentation/test_python/page_nested/examples/advanced/fooz.rst @@ -3,4 +3,7 @@ Fooz #### -Fooz example +Fooz example contains square + +.. image:: icon.svg + :alt: square \ No newline at end of file diff --git a/documentation/test_python/page_nested/examples/advanced/icon.svg b/documentation/test_python/page_nested/examples/advanced/icon.svg new file mode 100644 index 00000000..cd27e616 --- /dev/null +++ b/documentation/test_python/page_nested/examples/advanced/icon.svg @@ -0,0 +1,8 @@ + + + + + red + square + + diff --git a/documentation/test_python/page_nested/examples/foo.html b/documentation/test_python/page_nested/examples/foo.html index d3cf920a..a7e5c0e5 100644 --- a/documentation/test_python/page_nested/examples/foo.html +++ b/documentation/test_python/page_nested/examples/foo.html @@ -40,7 +40,8 @@

    Examples » Foo

    -

    Foo example

    +

    Foo example contains a pentagon

    +a pentagon diff --git a/documentation/test_python/page_nested/examples/foo.rst b/documentation/test_python/page_nested/examples/foo.rst index 807f058a..4b6da85d 100644 --- a/documentation/test_python/page_nested/examples/foo.rst +++ b/documentation/test_python/page_nested/examples/foo.rst @@ -1,4 +1,7 @@ Foo ### -Foo example +Foo example contains a pentagon + +.. image:: icon.svg + :alt: a pentagon \ No newline at end of file diff --git a/documentation/test_python/page_nested/examples/icon.svg b/documentation/test_python/page_nested/examples/icon.svg new file mode 100644 index 00000000..fbaa9a42 --- /dev/null +++ b/documentation/test_python/page_nested/examples/icon.svg @@ -0,0 +1,6 @@ + + + + ACID + pentagon + diff --git a/documentation/test_python/test_page.py b/documentation/test_python/test_page.py index 73119a85..8e31ec1a 100644 --- a/documentation/test_python/test_page.py +++ b/documentation/test_python/test_page.py @@ -75,6 +75,8 @@ def test(self): self.assertEqual(*self.actual_expected_contents('sub/page1.html')) self.assertEqual(*self.actual_expected_contents('sub/page2.html')) self.assertEqual(*self.actual_expected_contents('pages.html')) + self.assertEqual(*self.actual_expected_contents('examples/icon.svg')) + self.assertEqual(*self.actual_expected_contents('examples/advanced/icon.svg')) class InputSubdir(BaseTestCase): def test(self): From 6a9f3ad1063edfea93f64ad4d5128ec2885e86ab Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sun, 28 Jun 2020 13:06:30 +0300 Subject: [PATCH 21/22] Use stateless template filters, revert most of changes from 864180f4 --- documentation/python.py | 86 +++++++++++------------- documentation/templates/python/base.html | 26 +++---- 2 files changed, 52 insertions(+), 60 deletions(-) diff --git a/documentation/python.py b/documentation/python.py index 0ff79c2e..453d90a5 100755 --- a/documentation/python.py +++ b/documentation/python.py @@ -1873,49 +1873,9 @@ def extract_data_doc(state: State, parent, entry: Empty): return out -# Filter to return formatted URL or the full URL, if already absolute -def format_url(path, config, site_root): - if urllib.parse.urlparse(path).netloc: return path - - # If file is found relative to the conf file, use that - if os.path.exists(os.path.join(config['INPUT'], path)): - path = os.path.join(config['INPUT'], path) - # Otherwise use path relative to script directory - else: - path = os.path.join(os.path.dirname(os.path.realpath(__file__)), path) - - return site_root + config['URL_FORMATTER'](EntryType.STATIC, [path])[1] # TODO: url shortening can be applied - - -def render(*, state, template: str, url: str, filename: str, env: jinja2.Environment, **kwargs): - config = state.config +def render(*, config, template: str, url: str, filename: str, env: jinja2.Environment, **kwargs): site_root = '../' * filename.count('/') # relative to generated page - # Filter to return URL for given symbol. If the path is a string, first try - # to treat it as an URL -- either it needs to have the scheme or at least - # one slash for relative links (in contrast, Python names don't have - # slashes). If that fails, turn it into a list and try to look it up in - # various dicts. - def path_to_url(path): - if isinstance(path, str): - if urllib.parse.urlparse(path).netloc: - return path - if '/' in path: - if path in state.name_map: - path = state.name_map[path] - return site_root + path - path = [path] - entry = state.name_map['.'.join(path)] - return site_root + entry.url # TODO: url shortening can be applied - - # 'format_url' and 'path_to_url' does not take arguments - # therefore reasonably treated as stateless by Jinja and cached - # A better alternative to cache.clear() would be to pass site_root argument to those filters - env.cache.clear() - - env.filters['format_url'] = lambda path: format_url(path, config, site_root) - env.filters['path_to_url'] = path_to_url - template = env.get_template(template) rendered = template.render(URL=url, SEARCHDATA_FORMAT_VERSION=searchdata_format_version, @@ -2006,7 +1966,7 @@ def render_module(state: State, path, module, env): result.name = path[-1] state.search += [result] - render(state=state, + render(config=state.config, template='module.html', filename=page.filename, url=page.url, @@ -2107,7 +2067,7 @@ def render_class(state: State, path, class_, env): result.name = path[-1] state.search += [result] - render(state=state, + render(config=state.config, template='class.html', filename=page.filename, url=page.url, @@ -2342,7 +2302,7 @@ def render_page(state: State, path, input_filename, env): entry = state.name_map[page_path_to_entry_key(path)] entry.summary = page.summary entry.name = page.breadcrumb[-1][0] - render(state=state, + render(config=state.config, template='page.html', filename=page.filename, url=page.url, @@ -2406,7 +2366,7 @@ def render_page(state: State, path, input_filename, env): result.name = entry.name state.search += [result] - render(state=state, + render(config=state.config, template='page.html', filename=page.filename, url=page.url, @@ -2509,6 +2469,38 @@ def run(basedir, config, *, templates=default_templates, search_add_lookahead_ba loader=jinja2.FileSystemLoader(templates), trim_blocks=True, lstrip_blocks=True, enable_async=True) + # Filter to return formatted URL or the full URL, if already absolute + def format_url(path, site_root): + if urllib.parse.urlparse(path).netloc: return path + + # If file is found relative to the conf file, use that + if os.path.exists(os.path.join(config['INPUT'], path)): + path = os.path.join(config['INPUT'], path) + # Otherwise use path relative to script directory + else: + path = os.path.join(os.path.dirname(os.path.realpath(__file__)), path) + + return site_root + config['URL_FORMATTER'](EntryType.STATIC, [path])[1] # TODO: url shortening can be applied + + # Filter to return URL for given symbol. If the path is a string, first try + # to treat it as an URL -- either it needs to have the scheme or at least + # one slash for relative links (in contrast, Python names don't have + # slashes). If that fails, turn it into a list and try to look it up in + # various dicts. + def path_to_url(path, site_root): + if isinstance(path, str): + if urllib.parse.urlparse(path).netloc: + return path + if '/' in path: + if path in state.name_map: + path = state.name_map[path] + return site_root + path + path = [path] + entry = state.name_map['.'.join(path)] + return site_root + entry.url # TODO: url shortening can be applied + + env.filters['format_url'] = format_url + env.filters['path_to_url'] = path_to_url env.filters['urljoin'] = urljoin # Set up extra plugin paths. The one for m.css plugins was added above. @@ -2682,7 +2674,7 @@ def fetch_class_index(entry): index.pages = page_index for file in special_pages[1:]: # exclude index filename, url = config['URL_FORMATTER'](EntryType.SPECIAL, [file]) - render(state=state, + render(config=config, template=file + '.html', filename=filename, url=url, @@ -2699,7 +2691,7 @@ def fetch_class_index(entry): page.filename = filename page.url = url page.breadcrumb = [(config['PROJECT_TITLE'], url)] - render(state=state, + render(config=config, template='page.html', filename=page.filename, url=page.url, diff --git a/documentation/templates/python/base.html b/documentation/templates/python/base.html index 60db580a..421cf3c1 100644 --- a/documentation/templates/python/base.html +++ b/documentation/templates/python/base.html @@ -4,10 +4,10 @@ {% block title %}{{ PROJECT_TITLE }}{% if PROJECT_SUBTITLE %} {{ PROJECT_SUBTITLE }}{% endif %}{% endblock %} {% for css in STYLESHEETS %} - + {% endfor %} {% if FAVICON %} - + {% endif %} {% if not SEARCH_DISABLED and SEARCH_BASE_URL %} @@ -28,10 +28,10 @@
    {% if MAIN_PROJECT_URL and PROJECT_SUBTITLE %} - {% if PROJECT_LOGO %}{% endif %}{{ PROJECT_TITLE }} | {{ PROJECT_SUBTITLE }} + {% if PROJECT_LOGO %}{% endif %}{{ PROJECT_TITLE }} | {{ PROJECT_SUBTITLE }} {% else %} - {% if PROJECT_LOGO %}{% endif %}{{ PROJECT_TITLE }}{% if PROJECT_SUBTITLE %} {{ PROJECT_SUBTITLE }}{% endif %} + {% if PROJECT_LOGO %}{% endif %}{{ PROJECT_TITLE }}{% if PROJECT_SUBTITLE %} {{ PROJECT_SUBTITLE }}{% endif %} {% endif %} {% if LINKS_NAVBAR1 or LINKS_NAVBAR2 or not SEARCH_DISABLED %}
    @@ -48,13 +48,13 @@
    - + {% if site_root %} {% endif %} {% if SEARCH_DOWNLOAD_BINARY %} {% else %} - + {% endif %} {% endif %} {% if FINE_PRINT %} From 38617764a4301c2c112de33a4be7df8cdcf495f2 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sun, 28 Jun 2020 13:31:40 +0300 Subject: [PATCH 22/22] Test pure paths links --- documentation/test_python/page_nested/classes.html | 3 ++- .../test_python/page_nested/examples/advanced/barz.html | 3 ++- .../test_python/page_nested/examples/advanced/fooz.html | 3 ++- .../test_python/page_nested/examples/advanced/index.html | 3 ++- documentation/test_python/page_nested/examples/bar.html | 3 ++- documentation/test_python/page_nested/examples/foo.html | 3 ++- documentation/test_python/page_nested/examples/index.html | 3 ++- documentation/test_python/page_nested/index.html | 3 ++- documentation/test_python/page_nested/modules.html | 3 ++- documentation/test_python/page_nested/pages.html | 3 ++- documentation/test_python/page_nested/sub/page1.html | 3 ++- documentation/test_python/page_nested/sub/page2.html | 3 ++- documentation/test_python/test_page.py | 3 ++- 13 files changed, 26 insertions(+), 13 deletions(-) diff --git a/documentation/test_python/page_nested/classes.html b/documentation/test_python/page_nested/classes.html index 878331a1..127b52ef 100644 --- a/documentation/test_python/page_nested/classes.html +++ b/documentation/test_python/page_nested/classes.html @@ -22,8 +22,9 @@