Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion sphinx/builders/epub3.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,20 @@

if TYPE_CHECKING:
from collections.abc import Set
from typing import Any
from typing import Any, Literal

from sphinx.application import Sphinx
from sphinx.builders.html._ctx import _GlobalContextHTML
from sphinx.config import Config
from sphinx.util.typing import ExtensionMetadata

class _GlobalContextEpub3(_GlobalContextHTML):
theme_writing_mode: str | None
html_tag: str
use_meta_charset: bool
skip_ua_compatible: Literal[True]


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -89,6 +97,8 @@ class Epub3Builder(_epub_base.EpubBuilder):
html_tag = HTML_TAG
use_meta_charset = True

globalcontext: _GlobalContextEpub3

# Finish by building the epub file
def handle_finish(self) -> None:
"""Create the metainfo files and finally the epub."""
Expand Down
17 changes: 10 additions & 7 deletions sphinx/builders/html/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
from docutils.nodes import Node

from sphinx.application import Sphinx
from sphinx.builders.html._ctx import _GlobalContextHTML, _PageContextHTML
from sphinx.config import Config
from sphinx.environment import BuildEnvironment
from sphinx.util.typing import ExtensionMetadata
Expand Down Expand Up @@ -137,6 +138,8 @@ class StandaloneHTMLBuilder(Builder):
imgpath: str = ''
domain_indices: list[DOMAIN_INDEX_TYPE] = []

globalcontext: _GlobalContextHTML

def __init__(self, app: Sphinx, env: BuildEnvironment) -> None:
super().__init__(app, env)

Expand Down Expand Up @@ -565,7 +568,7 @@ def prepare_writing(self, docnames: Set[str]) -> None:
'html5_doctype': True,
}
if self.theme:
self.globalcontext |= {
self.globalcontext |= { # type: ignore[typeddict-item]
f'theme_{key}': val
for key, val in self.theme.get_options(self.theme_options).items()
}
Expand All @@ -580,7 +583,7 @@ def get_doc_context(self, docname: str, body: str, metatags: str) -> dict[str, A
# find out relations
prev = next = None
parents = []
rellinks = self.globalcontext['rellinks'][:]
rellinks = list(self.globalcontext['rellinks'])
related = self.relations.get(docname)
titles = self.env.titles
if related and related[2]:
Expand Down Expand Up @@ -921,7 +924,7 @@ def copy_static_files(self) -> None:
self._static_dir.mkdir(parents=True, exist_ok=True)

# prepare context for templates
context = self.globalcontext.copy()
context: dict[str, Any] = self.globalcontext.copy() # type: ignore[assignment]
if self.indexer is not None:
context.update(self.indexer.context_for_searchtool())

Expand Down Expand Up @@ -1040,7 +1043,7 @@ def get_output_path(self, page_name: str, /) -> Path:
def get_outfilename(self, pagename: str) -> _StrPath:
return _StrPath(self.get_output_path(pagename))

def add_sidebars(self, pagename: str, ctx: dict[str, Any]) -> None:
def add_sidebars(self, pagename: str, ctx: _PageContextHTML) -> None:
def has_wildcard(pattern: str) -> bool:
return any(char in pattern for char in '*?[')

Expand Down Expand Up @@ -1080,7 +1083,7 @@ def handle_page(
outfilename: Path | None = None,
event_arg: Any = None,
) -> None:
ctx = self.globalcontext.copy()
ctx: _PageContextHTML = self.globalcontext.copy() # type: ignore[assignment]
# current_page_name is backwards compatibility
ctx['pagename'] = ctx['current_page_name'] = pagename
ctx['encoding'] = self.config.html_output_encoding
Expand Down Expand Up @@ -1124,7 +1127,7 @@ def hasdoc(name: str) -> bool:

ctx['toctree'] = lambda **kwargs: self._get_local_toctree(pagename, **kwargs)
self.add_sidebars(pagename, ctx)
ctx.update(addctx)
ctx.update(addctx) # type: ignore[typeddict-item]

# 'blah.html' should have content_root = './' not ''.
ctx['content_root'] = (f'..{SEP}' * default_baseuri.count(SEP)) or f'.{SEP}'
Expand Down Expand Up @@ -1261,7 +1264,7 @@ def js_tag(js: _JavaScript | str) -> str:
copyfile(self.env.doc2path(pagename), source_file_path, force=True)

def update_page_context(
self, pagename: str, templatename: str, ctx: dict[str, Any], event_arg: Any
self, pagename: str, templatename: str, ctx: _PageContextHTML, event_arg: Any
) -> None:
pass

Expand Down
89 changes: 89 additions & 0 deletions sphinx/builders/html/_ctx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from collections.abc import Callable, Sequence
from typing import Any, Literal, Protocol, TypedDict

from sphinx.builders.html._assets import _CascadingStyleSheet, _JavaScript

class _NavigationRelation(TypedDict):
link: str
title: str

class _GlobalContextHTML(TypedDict):
embedded: bool
project: str
release: str
version: str
last_updated: str | None
copyright: str
master_doc: str
root_doc: str
use_opensearch: bool
docstitle: str | None
shorttitle: str
show_copyright: bool
show_search_summary: bool
show_sphinx: bool
has_source: bool
show_source: bool
sourcelink_suffix: str
file_suffix: str
link_suffix: str
script_files: Sequence[_JavaScript]
language: str | None
css_files: Sequence[_CascadingStyleSheet]
sphinx_version: str
sphinx_version_tuple: tuple[int, int, int, str, int]
docutils_version_info: tuple[int, int, int, str, int]
styles: Sequence[str]
rellinks: Sequence[tuple[str, str, str, str]]
builder: str
parents: Sequence[_NavigationRelation]
logo_url: str
logo_alt: str
favicon_url: str
html5_doctype: Literal[True]

class _PathtoCallable(Protocol):
def __call__(
self, otheruri: str, resource: bool = False, baseuri: str = ...
) -> str: ...

class _ToctreeCallable(Protocol):
def __call__(self, **kwargs: Any) -> str: ...

class _PageContextHTML(_GlobalContextHTML):
# get_doc_context()
prev: Sequence[_NavigationRelation]
next: Sequence[_NavigationRelation]
title: str
meta: dict[str, Any] | None
body: str
metatags: str
sourcename: str
toc: str
display_toc: bool
page_source_suffix: str

# handle_page()
pagename: str
current_page_name: str
encoding: str
pageurl: str | None
pathto: _PathtoCallable
hasdoc: Callable[[str], bool]
toctree: _ToctreeCallable
content_root: str
css_tag: Callable[[_CascadingStyleSheet], str]
js_tag: Callable[[_JavaScript], str]

# add_sidebars()
sidebars: Sequence[str] | None

else:
_NavigationRelation = dict
_GlobalContextHTML = dict
_PageContextHTML = dict
5 changes: 2 additions & 3 deletions tests/test_builders/test_build_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
from tests.test_builders.xpath_util import check_xpath

if TYPE_CHECKING:
from typing import Any

from sphinx.builders.html._ctx import _PageContextHTML
from sphinx.testing.util import SphinxTestApp


Expand Down Expand Up @@ -416,7 +415,7 @@ def test_html_style(app: SphinxTestApp) -> None:
},
)
def test_html_sidebar(app: SphinxTestApp) -> None:
ctx: dict[str, Any] = {}
ctx: _PageContextHTML = {} # type: ignore[typeddict-item]

# default for alabaster
app.build(force_all=True)
Expand Down
Loading