Edit on GitHub

pdoc.render

  1from __future__ import annotations
  2
  3import os
  4import types
  5import warnings
  6from pathlib import Path
  7from typing import cast, Mapping
  8
  9import jinja2
 10from jinja2 import Environment, FileSystemLoader
 11
 12import pdoc.doc
 13import pdoc.docstrings
 14from pdoc._compat import Literal
 15from pdoc.render_helpers import (
 16    DefaultMacroExtension,
 17    defuse_unsafe_reprs,
 18    edit_url,
 19    format_signature,
 20    highlight,
 21    link,
 22    linkify,
 23    minify_css,
 24    root_module_name,
 25    to_html,
 26    to_markdown_with_context,
 27)
 28from pdoc.search import make_index, precompile_index
 29
 30
 31def configure(
 32    *,
 33    docformat: Literal[
 34        "markdown", "google", "numpy", "restructuredtext"
 35    ] = "restructuredtext",
 36    edit_url_map: Mapping[str, str] | None = None,
 37    favicon: str | None = None,
 38    footer_text: str = "",
 39    logo: str | None = None,
 40    logo_link: str | None = None,
 41    math: bool = False,
 42    search: bool = True,
 43    show_source: bool = True,
 44    template_directory: Path | None = None,
 45):
 46    """
 47    Configure the rendering output.
 48
 49    - `docformat` is the docstring flavor in use.
 50      pdoc prefers plain Markdown (the default), but also supports other formats.
 51    - `edit_url_map` is a mapping from module names to URL prefixes. For example,
 52
 53        ```json
 54        {"pdoc": "https://github.com/mitmproxy/pdoc/blob/main/pdoc/"}
 55        ```
 56
 57      renders the "Edit on GitHub" button on this page. The URL prefix can be modified to pin a particular version.
 58    - `favicon` is an optional path/URL for a favicon image
 59    - `footer_text` is additional text that should appear in the navigation footer.
 60    - `logo` is an optional URL to the project's logo image
 61    - `logo_link` is an optional URL the logo should point to
 62    - `math` enables math rendering by including MathJax into the rendered documentation.
 63    - `search` controls whether search functionality is enabled and a search index is built.
 64    - `show_source` controls whether a "View Source" button should be included in the output.
 65    - `template_directory` can be used to set an additional (preferred) directory
 66      for templates. You can find an example in the main documentation of `pdoc`
 67      or in `examples/custom-template`.
 68    """
 69    searchpath = _default_searchpath
 70    if template_directory:
 71        searchpath = [template_directory] + searchpath
 72    env.loader = FileSystemLoader(searchpath)
 73
 74    env.globals["edit_url_map"] = edit_url_map or {}
 75    env.globals["docformat"] = docformat
 76    env.globals["math"] = math
 77    env.globals["show_source"] = show_source
 78    env.globals["favicon"] = favicon
 79    env.globals["logo"] = logo
 80    env.globals["logo_link"] = logo_link
 81    env.globals["footer_text"] = footer_text
 82    env.globals["search"] = search
 83
 84
 85@defuse_unsafe_reprs()
 86def html_module(
 87    module: pdoc.doc.Module,
 88    all_modules: Mapping[str, pdoc.doc.Module],
 89    mtime: str | None = None,
 90) -> str:
 91    """
 92    Renders the documentation for a `pdoc.doc.Module`.
 93
 94    - `all_modules` contains all modules that are rendered in this invocation.
 95      This is used to determine which identifiers should be linked and which should not.
 96    - If `mtime` is given, include additional JavaScript on the page for live-reloading.
 97      This is only passed by `pdoc.web`.
 98    """
 99    return env.get_template("module.html.jinja2").render(
100        module=module,
101        all_modules=all_modules,
102        root_module_name=root_module_name(all_modules),
103        edit_url=edit_url(
104            module.modulename,
105            module.is_package,
106            cast(Mapping[str, str], env.globals["edit_url_map"]),
107        ),
108        mtime=mtime,
109    )
110
111
112@defuse_unsafe_reprs()
113def html_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
114    """Renders the module index."""
115    return env.get_template("index.html.jinja2").render(
116        all_modules=all_modules,
117        root_module_name=root_module_name(all_modules),
118    )
119
120
121@defuse_unsafe_reprs()
122def html_error(error: str, details: str = "") -> str:
123    """Renders an error message."""
124    return env.get_template("error.html.jinja2").render(
125        error=error,
126        details=details,
127    )
128
129
130@defuse_unsafe_reprs()
131def search_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
132    """Renders the Elasticlunr.js search index."""
133    if not env.globals["search"]:
134        return ""
135    # This is a rather terrible hack to determine if a given object is public and should be included in the index.
136    module_template: jinja2.Template = env.get_template("module.html.jinja2")
137    ctx: jinja2.runtime.Context = module_template.new_context(
138        {"module": pdoc.doc.Module(types.ModuleType("")), "all_modules": all_modules}
139    )
140    for _ in module_template.root_render_func(ctx):  # type: ignore
141        pass
142
143    def is_public(x: pdoc.doc.Doc) -> bool:
144        return bool(ctx["is_public"](x).strip())
145
146    index = make_index(
147        all_modules,
148        is_public,
149        cast(str, env.globals["docformat"]),
150    )
151
152    compile_js = Path(env.get_template("build-search-index.js").filename)  # type: ignore
153    return env.get_template("search.js.jinja2").render(
154        search_index=precompile_index(index, compile_js)
155    )
156
157
158@defuse_unsafe_reprs()
159def repr_module(module: pdoc.doc.Module) -> str:
160    """Renders `repr(pdoc.doc.Module)`, primarily used for tests and debugging."""
161    return repr(module)
162
163
164_default_searchpath = [
165    Path(os.environ.get("XDG_CONFIG_HOME", "~/.config")).expanduser() / "pdoc",
166    Path(__file__).parent / "templates",
167    Path(__file__).parent / "templates" / "default",
168    Path(__file__).parent / "templates" / "deprecated",
169]
170
171env = Environment(
172    loader=FileSystemLoader(_default_searchpath),
173    extensions=[DefaultMacroExtension],
174    autoescape=True,
175    trim_blocks=True,
176    lstrip_blocks=True,
177)
178"""
179The Jinja2 environment used to render all templates.
180You can modify this object to add custom filters and globals.
181"""
182env.filters["to_markdown"] = to_markdown_with_context
183env.filters["to_html"] = to_html
184env.filters["highlight"] = highlight
185env.filters["format_signature"] = format_signature
186env.filters["linkify"] = linkify
187env.filters["link"] = link
188env.filters["minify_css"] = minify_css
189env.globals["__version__"] = pdoc.__version__
190env.globals["env"] = os.environ
191env.globals["warn"] = warnings.warn
192configure()  # add default globals
def configure( *, docformat: Literal['markdown', 'google', 'numpy', 'restructuredtext'] = 'restructuredtext', edit_url_map: Optional[Mapping[str, str]] = None, favicon: str | None = None, footer_text: str = '', logo: str | None = None, logo_link: str | None = None, math: bool = False, search: bool = True, show_source: bool = True, template_directory: pathlib.Path | None = None)
32def configure(
33    *,
34    docformat: Literal[
35        "markdown", "google", "numpy", "restructuredtext"
36    ] = "restructuredtext",
37    edit_url_map: Mapping[str, str] | None = None,
38    favicon: str | None = None,
39    footer_text: str = "",
40    logo: str | None = None,
41    logo_link: str | None = None,
42    math: bool = False,
43    search: bool = True,
44    show_source: bool = True,
45    template_directory: Path | None = None,
46):
47    """
48    Configure the rendering output.
49
50    - `docformat` is the docstring flavor in use.
51      pdoc prefers plain Markdown (the default), but also supports other formats.
52    - `edit_url_map` is a mapping from module names to URL prefixes. For example,
53
54        ```json
55        {"pdoc": "https://github.com/mitmproxy/pdoc/blob/main/pdoc/"}
56        ```
57
58      renders the "Edit on GitHub" button on this page. The URL prefix can be modified to pin a particular version.
59    - `favicon` is an optional path/URL for a favicon image
60    - `footer_text` is additional text that should appear in the navigation footer.
61    - `logo` is an optional URL to the project's logo image
62    - `logo_link` is an optional URL the logo should point to
63    - `math` enables math rendering by including MathJax into the rendered documentation.
64    - `search` controls whether search functionality is enabled and a search index is built.
65    - `show_source` controls whether a "View Source" button should be included in the output.
66    - `template_directory` can be used to set an additional (preferred) directory
67      for templates. You can find an example in the main documentation of `pdoc`
68      or in `examples/custom-template`.
69    """
70    searchpath = _default_searchpath
71    if template_directory:
72        searchpath = [template_directory] + searchpath
73    env.loader = FileSystemLoader(searchpath)
74
75    env.globals["edit_url_map"] = edit_url_map or {}
76    env.globals["docformat"] = docformat
77    env.globals["math"] = math
78    env.globals["show_source"] = show_source
79    env.globals["favicon"] = favicon
80    env.globals["logo"] = logo
81    env.globals["logo_link"] = logo_link
82    env.globals["footer_text"] = footer_text
83    env.globals["search"] = search

Configure the rendering output.

  • docformat is the docstring flavor in use. pdoc prefers plain Markdown (the default), but also supports other formats.
  • edit_url_map is a mapping from module names to URL prefixes. For example,

    {"pdoc": "https://github.com/mitmproxy/pdoc/blob/main/pdoc/"}
    

    renders the "Edit on GitHub" button on this page. The URL prefix can be modified to pin a particular version.

  • favicon is an optional path/URL for a favicon image
  • footer_text is additional text that should appear in the navigation footer.
  • logo is an optional URL to the project's logo image
  • logo_link is an optional URL the logo should point to
  • math enables math rendering by including MathJax into the rendered documentation.
  • search controls whether search functionality is enabled and a search index is built.
  • show_source controls whether a "View Source" button should be included in the output.
  • template_directory can be used to set an additional (preferred) directory for templates. You can find an example in the main documentation of pdoc or in examples/custom-template.
@defuse_unsafe_reprs()
def html_module( module: pdoc.doc.Module, all_modules: Mapping[str, pdoc.doc.Module], mtime: str | None = None) -> str:
 86@defuse_unsafe_reprs()
 87def html_module(
 88    module: pdoc.doc.Module,
 89    all_modules: Mapping[str, pdoc.doc.Module],
 90    mtime: str | None = None,
 91) -> str:
 92    """
 93    Renders the documentation for a `pdoc.doc.Module`.
 94
 95    - `all_modules` contains all modules that are rendered in this invocation.
 96      This is used to determine which identifiers should be linked and which should not.
 97    - If `mtime` is given, include additional JavaScript on the page for live-reloading.
 98      This is only passed by `pdoc.web`.
 99    """
100    return env.get_template("module.html.jinja2").render(
101        module=module,
102        all_modules=all_modules,
103        root_module_name=root_module_name(all_modules),
104        edit_url=edit_url(
105            module.modulename,
106            module.is_package,
107            cast(Mapping[str, str], env.globals["edit_url_map"]),
108        ),
109        mtime=mtime,
110    )

Renders the documentation for a pdoc.doc.Module.

  • all_modules contains all modules that are rendered in this invocation. This is used to determine which identifiers should be linked and which should not.
  • If mtime is given, include additional JavaScript on the page for live-reloading. This is only passed by pdoc.web.
@defuse_unsafe_reprs()
def html_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
113@defuse_unsafe_reprs()
114def html_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
115    """Renders the module index."""
116    return env.get_template("index.html.jinja2").render(
117        all_modules=all_modules,
118        root_module_name=root_module_name(all_modules),
119    )

Renders the module index.

@defuse_unsafe_reprs()
def html_error(error: str, details: str = '') -> str:
122@defuse_unsafe_reprs()
123def html_error(error: str, details: str = "") -> str:
124    """Renders an error message."""
125    return env.get_template("error.html.jinja2").render(
126        error=error,
127        details=details,
128    )

Renders an error message.

@defuse_unsafe_reprs()
def search_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
131@defuse_unsafe_reprs()
132def search_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
133    """Renders the Elasticlunr.js search index."""
134    if not env.globals["search"]:
135        return ""
136    # This is a rather terrible hack to determine if a given object is public and should be included in the index.
137    module_template: jinja2.Template = env.get_template("module.html.jinja2")
138    ctx: jinja2.runtime.Context = module_template.new_context(
139        {"module": pdoc.doc.Module(types.ModuleType("")), "all_modules": all_modules}
140    )
141    for _ in module_template.root_render_func(ctx):  # type: ignore
142        pass
143
144    def is_public(x: pdoc.doc.Doc) -> bool:
145        return bool(ctx["is_public"](x).strip())
146
147    index = make_index(
148        all_modules,
149        is_public,
150        cast(str, env.globals["docformat"]),
151    )
152
153    compile_js = Path(env.get_template("build-search-index.js").filename)  # type: ignore
154    return env.get_template("search.js.jinja2").render(
155        search_index=precompile_index(index, compile_js)
156    )

Renders the Elasticlunr.js search index.

@defuse_unsafe_reprs()
def repr_module(module: pdoc.doc.Module) -> str:
159@defuse_unsafe_reprs()
160def repr_module(module: pdoc.doc.Module) -> str:
161    """Renders `repr(pdoc.doc.Module)`, primarily used for tests and debugging."""
162    return repr(module)

Renders repr(pdoc.doc.Module), primarily used for tests and debugging.

env = <jinja2.environment.Environment object>

The Jinja2 environment used to render all templates. You can modify this object to add custom filters and globals.