diff --git a/docs/dev-guide/api.md b/docs/dev-guide/api.md index 0c1932dd..b0917402 100644 --- a/docs/dev-guide/api.md +++ b/docs/dev-guide/api.md @@ -14,6 +14,11 @@ NOTE: The main entry point to the API is through [Events](plugins.md#events) tha options: show_root_heading: true +::: mkdocs.utils.templates.TemplateContext + options: + show_root_heading: true + show_if_no_docstring: true + ::: mkdocs.livereload.LiveReloadServer options: show_root_heading: true diff --git a/mkdocs/commands/build.py b/mkdocs/commands/build.py index a491ecbc..7933119e 100644 --- a/mkdocs/commands/build.py +++ b/mkdocs/commands/build.py @@ -4,7 +4,7 @@ import gzip import logging import os import time -from typing import TYPE_CHECKING, Any, Sequence +from typing import TYPE_CHECKING, Sequence from urllib.parse import urlsplit import jinja2 @@ -15,6 +15,7 @@ from mkdocs import utils from mkdocs.exceptions import Abort, BuildError from mkdocs.structure.files import File, Files, get_files from mkdocs.structure.nav import Navigation, get_navigation +from mkdocs.utils import templates if TYPE_CHECKING: from mkdocs.config.defaults import MkDocsConfig @@ -43,7 +44,7 @@ def get_context( config: MkDocsConfig, page: Page | None = None, base_url: str = '', -) -> dict[str, Any]: +) -> templates.TemplateContext: """ Return the template context for a given page or template. """ @@ -57,17 +58,17 @@ def get_context( if isinstance(files, Files): files = files.documentation_pages() - return { - 'nav': nav, - 'pages': files, - 'base_url': base_url, - 'extra_css': extra_css, - 'extra_javascript': extra_javascript, - 'mkdocs_version': mkdocs.__version__, - 'build_date_utc': utils.get_build_datetime(), - 'config': config, - 'page': page, - } + return templates.TemplateContext( + nav=nav, + pages=files, + base_url=base_url, + extra_css=extra_css, + extra_javascript=extra_javascript, + mkdocs_version=mkdocs.__version__, + build_date_utc=utils.get_build_datetime(), + config=config, + page=page, + ) def _build_template( diff --git a/mkdocs/contrib/search/__init__.py b/mkdocs/contrib/search/__init__.py index 35eed424..9a6e0627 100644 --- a/mkdocs/contrib/search/__init__.py +++ b/mkdocs/contrib/search/__init__.py @@ -2,7 +2,7 @@ from __future__ import annotations import logging import os -from typing import TYPE_CHECKING, Any, List +from typing import TYPE_CHECKING, List from mkdocs import utils from mkdocs.config import base @@ -12,6 +12,7 @@ from mkdocs.plugins import BasePlugin if TYPE_CHECKING: from mkdocs.config.defaults import MkDocsConfig + from mkdocs.util.templates import TemplateContext log = logging.getLogger(__name__) base_path = os.path.dirname(os.path.abspath(__file__)) @@ -85,7 +86,7 @@ class SearchPlugin(BasePlugin[_PluginConfig]): "Create search index instance for later use." self.search_index = SearchIndex(**self.config) - def on_page_context(self, context: dict[str, Any], **kwargs) -> None: + def on_page_context(self, context: TemplateContext, **kwargs) -> None: "Add page to search index." self.search_index.add_entry_from_context(context['page']) diff --git a/mkdocs/plugins.py b/mkdocs/plugins.py index 5e6abd1f..92e5bf3d 100644 --- a/mkdocs/plugins.py +++ b/mkdocs/plugins.py @@ -30,6 +30,7 @@ if TYPE_CHECKING: from mkdocs.structure.files import Files from mkdocs.structure.nav import Navigation from mkdocs.structure.pages import Page + from mkdocs.utils.templates import TemplateContext log = logging.getLogger('mkdocs.plugins') @@ -267,8 +268,8 @@ class BasePlugin(Generic[SomeConfig]): return template def on_template_context( - self, context: dict[str, Any], *, template_name: str, config: MkDocsConfig - ) -> dict[str, Any] | None: + self, context: TemplateContext, *, template_name: str, config: MkDocsConfig + ) -> TemplateContext | None: """ The `template_context` event is called immediately after the context is created for the subject template and can be used to alter the context for that specific @@ -374,8 +375,8 @@ class BasePlugin(Generic[SomeConfig]): return html def on_page_context( - self, context: dict[str, Any], *, page: Page, config: MkDocsConfig, nav: Navigation - ) -> dict[str, Any] | None: + self, context: TemplateContext, *, page: Page, config: MkDocsConfig, nav: Navigation + ) -> TemplateContext | None: """ The `page_context` event is called after the context for a page is created and can be used to alter the context for that specific page only. diff --git a/mkdocs/theme.py b/mkdocs/theme.py index a8e8ed13..6eecc811 100644 --- a/mkdocs/theme.py +++ b/mkdocs/theme.py @@ -8,7 +8,7 @@ import jinja2 from mkdocs import localization, utils from mkdocs.config.base import ValidationError -from mkdocs.utils import filters +from mkdocs.utils import templates log = logging.getLogger(__name__) @@ -116,6 +116,6 @@ class Theme: loader = jinja2.FileSystemLoader(self.dirs) # No autoreload because editing a template in the middle of a build is not useful. env = jinja2.Environment(loader=loader, auto_reload=False) - env.filters['url'] = filters.url_filter + env.filters['url'] = templates.url_filter localization.install_translations(env, self._vars['locale'], self.dirs) return env diff --git a/mkdocs/utils/filters.py b/mkdocs/utils/filters.py index f8d00821..49ca1aff 100644 --- a/mkdocs/utils/filters.py +++ b/mkdocs/utils/filters.py @@ -1,14 +1 @@ -from __future__ import annotations - -try: - from jinja2 import pass_context as contextfilter # type: ignore -except ImportError: - from jinja2 import contextfilter # type: ignore - -from mkdocs.utils import normalize_url - - -@contextfilter -def url_filter(context, value: str) -> str: - """A Template filter to normalize URLs.""" - return normalize_url(value, page=context['page'], base=context['base_url']) +from .templates import url_filter # noqa - legacy re-export diff --git a/mkdocs/utils/templates.py b/mkdocs/utils/templates.py new file mode 100644 index 00000000..bacab288 --- /dev/null +++ b/mkdocs/utils/templates.py @@ -0,0 +1,43 @@ +from __future__ import annotations + +import sys +from typing import TYPE_CHECKING, Sequence + +if sys.version_info >= (3, 8): + from typing import TypedDict +else: + from typing_extensions import TypedDict + +if TYPE_CHECKING: + import datetime + +try: + from jinja2 import pass_context as contextfilter # type: ignore +except ImportError: + from jinja2 import contextfilter # type: ignore + +from mkdocs.utils import normalize_url + +if TYPE_CHECKING: + from mkdocs.config.defaults import MkDocsConfig + from mkdocs.structure.files import File + from mkdocs.structure.nav import Navigation + from mkdocs.structure.pages import Page + + +class TemplateContext(TypedDict): + nav: Navigation + pages: Sequence[File] + base_url: str + extra_css: Sequence[str] + extra_javascript: Sequence[str] + mkdocs_version: str + build_date_utc: datetime.datetime + config: MkDocsConfig + page: Page | None + + +@contextfilter +def url_filter(context: TemplateContext, value: str) -> str: + """A Template filter to normalize URLs.""" + return normalize_url(value, page=context['page'], base=context['base_url'])