Make TemplateContext typed, move utils.filters to utils.templates

This commit is contained in:
Oleh Prypin
2023-06-03 17:54:12 +02:00
parent 73e503990e
commit 0f793b9984
7 changed files with 73 additions and 35 deletions

View File

@@ -14,6 +14,11 @@ NOTE: The main entry point to the API is through [Events](plugins.md#events) tha
options: options:
show_root_heading: true show_root_heading: true
::: mkdocs.utils.templates.TemplateContext
options:
show_root_heading: true
show_if_no_docstring: true
::: mkdocs.livereload.LiveReloadServer ::: mkdocs.livereload.LiveReloadServer
options: options:
show_root_heading: true show_root_heading: true

View File

@@ -4,7 +4,7 @@ import gzip
import logging import logging
import os import os
import time import time
from typing import TYPE_CHECKING, Any, Sequence from typing import TYPE_CHECKING, Sequence
from urllib.parse import urlsplit from urllib.parse import urlsplit
import jinja2 import jinja2
@@ -15,6 +15,7 @@ from mkdocs import utils
from mkdocs.exceptions import Abort, BuildError from mkdocs.exceptions import Abort, BuildError
from mkdocs.structure.files import File, Files, get_files from mkdocs.structure.files import File, Files, get_files
from mkdocs.structure.nav import Navigation, get_navigation from mkdocs.structure.nav import Navigation, get_navigation
from mkdocs.utils import templates
if TYPE_CHECKING: if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig from mkdocs.config.defaults import MkDocsConfig
@@ -43,7 +44,7 @@ def get_context(
config: MkDocsConfig, config: MkDocsConfig,
page: Page | None = None, page: Page | None = None,
base_url: str = '', base_url: str = '',
) -> dict[str, Any]: ) -> templates.TemplateContext:
""" """
Return the template context for a given page or template. Return the template context for a given page or template.
""" """
@@ -57,17 +58,17 @@ def get_context(
if isinstance(files, Files): if isinstance(files, Files):
files = files.documentation_pages() files = files.documentation_pages()
return { return templates.TemplateContext(
'nav': nav, nav=nav,
'pages': files, pages=files,
'base_url': base_url, base_url=base_url,
'extra_css': extra_css, extra_css=extra_css,
'extra_javascript': extra_javascript, extra_javascript=extra_javascript,
'mkdocs_version': mkdocs.__version__, mkdocs_version=mkdocs.__version__,
'build_date_utc': utils.get_build_datetime(), build_date_utc=utils.get_build_datetime(),
'config': config, config=config,
'page': page, page=page,
} )
def _build_template( def _build_template(

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
import logging import logging
import os import os
from typing import TYPE_CHECKING, Any, List from typing import TYPE_CHECKING, List
from mkdocs import utils from mkdocs import utils
from mkdocs.config import base from mkdocs.config import base
@@ -12,6 +12,7 @@ from mkdocs.plugins import BasePlugin
if TYPE_CHECKING: if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig from mkdocs.config.defaults import MkDocsConfig
from mkdocs.util.templates import TemplateContext
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
base_path = os.path.dirname(os.path.abspath(__file__)) base_path = os.path.dirname(os.path.abspath(__file__))
@@ -85,7 +86,7 @@ class SearchPlugin(BasePlugin[_PluginConfig]):
"Create search index instance for later use." "Create search index instance for later use."
self.search_index = SearchIndex(**self.config) 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." "Add page to search index."
self.search_index.add_entry_from_context(context['page']) self.search_index.add_entry_from_context(context['page'])

View File

@@ -30,6 +30,7 @@ if TYPE_CHECKING:
from mkdocs.structure.files import Files from mkdocs.structure.files import Files
from mkdocs.structure.nav import Navigation from mkdocs.structure.nav import Navigation
from mkdocs.structure.pages import Page from mkdocs.structure.pages import Page
from mkdocs.utils.templates import TemplateContext
log = logging.getLogger('mkdocs.plugins') log = logging.getLogger('mkdocs.plugins')
@@ -267,8 +268,8 @@ class BasePlugin(Generic[SomeConfig]):
return template return template
def on_template_context( def on_template_context(
self, context: dict[str, Any], *, template_name: str, config: MkDocsConfig self, context: TemplateContext, *, template_name: str, config: MkDocsConfig
) -> dict[str, Any] | None: ) -> TemplateContext | None:
""" """
The `template_context` event is called immediately after the context is created 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 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 return html
def on_page_context( def on_page_context(
self, context: dict[str, Any], *, page: Page, config: MkDocsConfig, nav: Navigation self, context: TemplateContext, *, page: Page, config: MkDocsConfig, nav: Navigation
) -> dict[str, Any] | None: ) -> TemplateContext | None:
""" """
The `page_context` event is called after the context for a page is created 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. and can be used to alter the context for that specific page only.

View File

@@ -8,7 +8,7 @@ import jinja2
from mkdocs import localization, utils from mkdocs import localization, utils
from mkdocs.config.base import ValidationError from mkdocs.config.base import ValidationError
from mkdocs.utils import filters from mkdocs.utils import templates
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -116,6 +116,6 @@ class Theme:
loader = jinja2.FileSystemLoader(self.dirs) loader = jinja2.FileSystemLoader(self.dirs)
# No autoreload because editing a template in the middle of a build is not useful. # No autoreload because editing a template in the middle of a build is not useful.
env = jinja2.Environment(loader=loader, auto_reload=False) 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) localization.install_translations(env, self._vars['locale'], self.dirs)
return env return env

View File

@@ -1,14 +1 @@
from __future__ import annotations from .templates import url_filter # noqa - legacy re-export
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'])

43
mkdocs/utils/templates.py Normal file
View File

@@ -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'])