Edit on GitHub

pdoc.render

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

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:
117@defuse_unsafe_reprs()
118def html_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
119    """Renders the module index."""
120    return env.get_template("index.html.jinja2").render(
121        all_modules=all_modules,
122        root_module_name=root_module_name(all_modules),
123    )

Renders the module index.

@defuse_unsafe_reprs()
def html_error(error: str, details: str = '') -> str:
126@defuse_unsafe_reprs()
127def html_error(error: str, details: str = "") -> str:
128    """Renders an error message."""
129    return env.get_template("error.html.jinja2").render(
130        error=error,
131        details=details,
132    )

Renders an error message.

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

Renders the Elasticlunr.js search index.

@defuse_unsafe_reprs()
def repr_module(module: pdoc.doc.Module) -> str:
163@defuse_unsafe_reprs()
164def repr_module(module: pdoc.doc.Module) -> str:
165    """Renders `repr(pdoc.doc.Module)`, primarily used for tests and debugging."""
166    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.