mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Various miscellaneous improvements (#12578)
This commit is contained in:
@@ -969,26 +969,24 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
|
|
||||||
# user sidebar settings
|
# user sidebar settings
|
||||||
html_sidebars = self.get_builder_config('sidebars', 'html')
|
html_sidebars = self.get_builder_config('sidebars', 'html')
|
||||||
for pattern, patsidebars in html_sidebars.items():
|
msg = __('page %s matches two patterns in html_sidebars: %r and %r')
|
||||||
|
for pattern, pat_sidebars in html_sidebars.items():
|
||||||
if patmatch(pagename, pattern):
|
if patmatch(pagename, pattern):
|
||||||
if matched:
|
if matched and has_wildcard(pattern):
|
||||||
if has_wildcard(pattern):
|
# warn if both patterns contain wildcards
|
||||||
# warn if both patterns contain wildcards
|
if has_wildcard(matched):
|
||||||
if has_wildcard(matched):
|
logger.warning(msg, pagename, matched)
|
||||||
logger.warning(__('page %s matches two patterns in '
|
# else the already matched pattern is more specific
|
||||||
'html_sidebars: %r and %r'),
|
# than the present one, because it contains no wildcard
|
||||||
pagename, matched, pattern)
|
continue
|
||||||
# else the already matched pattern is more specific
|
|
||||||
# than the present one, because it contains no wildcard
|
|
||||||
continue
|
|
||||||
matched = pattern
|
matched = pattern
|
||||||
sidebars = patsidebars
|
sidebars = pat_sidebars
|
||||||
|
|
||||||
if len(sidebars) == 0:
|
if len(sidebars) == 0:
|
||||||
# keep defaults
|
# keep defaults
|
||||||
pass
|
pass
|
||||||
|
|
||||||
ctx['sidebars'] = sidebars
|
ctx['sidebars'] = list(sidebars)
|
||||||
|
|
||||||
# --------- these are overwritten by the serialization builder
|
# --------- these are overwritten by the serialization builder
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,10 @@ class PyXrefMixin:
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
_delimiters_re = re.compile(
|
||||||
|
r'(\s*[\[\]\(\),](?:\s*o[rf]\s)?\s*|\s+o[rf]\s+|\s*\|\s*|\.\.\.)'
|
||||||
|
)
|
||||||
|
|
||||||
def make_xrefs(
|
def make_xrefs(
|
||||||
self,
|
self,
|
||||||
rolename: str,
|
rolename: str,
|
||||||
@@ -100,9 +104,7 @@ class PyXrefMixin:
|
|||||||
inliner: Inliner | None = None,
|
inliner: Inliner | None = None,
|
||||||
location: Node | None = None,
|
location: Node | None = None,
|
||||||
) -> list[Node]:
|
) -> list[Node]:
|
||||||
delims = r'(\s*[\[\]\(\),](?:\s*o[rf]\s)?\s*|\s+o[rf]\s+|\s*\|\s*|\.\.\.)'
|
sub_targets = self._delimiters_re.split(target)
|
||||||
delims_re = re.compile(delims)
|
|
||||||
sub_targets = re.split(delims, target)
|
|
||||||
|
|
||||||
split_contnode = bool(contnode and contnode.astext() == target)
|
split_contnode = bool(contnode and contnode.astext() == target)
|
||||||
|
|
||||||
@@ -112,13 +114,13 @@ class PyXrefMixin:
|
|||||||
if split_contnode:
|
if split_contnode:
|
||||||
contnode = nodes.Text(sub_target)
|
contnode = nodes.Text(sub_target)
|
||||||
|
|
||||||
if in_literal or delims_re.match(sub_target):
|
if in_literal or self._delimiters_re.match(sub_target):
|
||||||
results.append(contnode or innernode(sub_target, sub_target)) # type: ignore[call-arg]
|
results.append(contnode or innernode(sub_target, sub_target)) # type: ignore[call-arg]
|
||||||
else:
|
else:
|
||||||
results.append(self.make_xref(rolename, domain, sub_target,
|
results.append(self.make_xref(rolename, domain, sub_target,
|
||||||
innernode, contnode, env, inliner, location))
|
innernode, contnode, env, inliner, location))
|
||||||
|
|
||||||
if sub_target in ('Literal', 'typing.Literal', '~typing.Literal'):
|
if sub_target in {'Literal', 'typing.Literal', '~typing.Literal'}:
|
||||||
in_literal = True
|
in_literal = True
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ from sphinx.util.nodes import apply_source_workaround, is_smartquotable
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterator
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
from docutils.nodes import Node, Text
|
from docutils.nodes import Node, Text
|
||||||
|
from typing_extensions import TypeAlias, TypeIs
|
||||||
|
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.config import Config
|
from sphinx.config import Config
|
||||||
@@ -31,15 +33,22 @@ if TYPE_CHECKING:
|
|||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.util.typing import ExtensionMetadata
|
from sphinx.util.typing import ExtensionMetadata
|
||||||
|
|
||||||
|
_DEFAULT_SUBSTITUTION_NAMES: TypeAlias = Literal[
|
||||||
|
'version',
|
||||||
|
'release',
|
||||||
|
'today',
|
||||||
|
'translation progress',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
default_substitutions = {
|
_DEFAULT_SUBSTITUTIONS = frozenset({
|
||||||
'version',
|
'version',
|
||||||
'release',
|
'release',
|
||||||
'today',
|
'today',
|
||||||
'translation progress',
|
'translation progress',
|
||||||
}
|
})
|
||||||
|
|
||||||
|
|
||||||
class SphinxTransform(Transform):
|
class SphinxTransform(Transform):
|
||||||
@@ -105,20 +114,25 @@ class DefaultSubstitutions(SphinxTransform):
|
|||||||
|
|
||||||
def apply(self, **kwargs: Any) -> None:
|
def apply(self, **kwargs: Any) -> None:
|
||||||
# only handle those not otherwise defined in the document
|
# only handle those not otherwise defined in the document
|
||||||
to_handle = default_substitutions - set(self.document.substitution_defs)
|
to_handle = _DEFAULT_SUBSTITUTIONS - set(self.document.substitution_defs)
|
||||||
for ref in self.document.findall(nodes.substitution_reference):
|
for ref in self.document.findall(nodes.substitution_reference):
|
||||||
refname = ref['refname']
|
if (name := ref['refname']) in to_handle:
|
||||||
if refname in to_handle:
|
ref.replace_self(self._handle_default_substitution(name))
|
||||||
if refname == 'translation progress':
|
|
||||||
# special handling: calculate translation progress
|
def _handle_default_substitution(self, name: _DEFAULT_SUBSTITUTION_NAMES) -> nodes.Text:
|
||||||
text = _calculate_translation_progress(self.document)
|
if name == 'translation progress':
|
||||||
else:
|
# special handling: calculate translation progress
|
||||||
text = self.config[refname]
|
return nodes.Text(_calculate_translation_progress(self.document))
|
||||||
if refname == 'today' and not text:
|
if name == 'today':
|
||||||
# special handling: can also specify a strftime format
|
if text := self.config.today:
|
||||||
text = format_date(self.config.today_fmt or _('%b %d, %Y'),
|
return nodes.Text(text)
|
||||||
language=self.config.language)
|
# special handling: can also specify a strftime format
|
||||||
ref.replace_self(nodes.Text(text))
|
return nodes.Text(format_date(
|
||||||
|
self.config.today_fmt or _('%b %d, %Y'),
|
||||||
|
language=self.config.language,
|
||||||
|
))
|
||||||
|
# config.version and config.release
|
||||||
|
return nodes.Text(getattr(self.config, name))
|
||||||
|
|
||||||
|
|
||||||
def _calculate_translation_progress(document: nodes.document) -> str:
|
def _calculate_translation_progress(document: nodes.document) -> str:
|
||||||
@@ -263,15 +277,15 @@ class ExtraTranslatableNodes(SphinxTransform):
|
|||||||
default_priority = 10
|
default_priority = 10
|
||||||
|
|
||||||
def apply(self, **kwargs: Any) -> None:
|
def apply(self, **kwargs: Any) -> None:
|
||||||
targets = self.config.gettext_additional_targets
|
targets = frozenset(self.config.gettext_additional_targets)
|
||||||
target_nodes = [v for k, v in TRANSLATABLE_NODES.items() if k in targets]
|
target_nodes = tuple(v for k, v in TRANSLATABLE_NODES.items() if k in targets)
|
||||||
if not target_nodes:
|
if not target_nodes:
|
||||||
return
|
return
|
||||||
|
|
||||||
def is_translatable_node(node: Node) -> bool:
|
def is_translatable_node(node: Node) -> TypeIs[nodes.Element]:
|
||||||
return isinstance(node, tuple(target_nodes))
|
return isinstance(node, target_nodes)
|
||||||
|
|
||||||
for node in self.document.findall(is_translatable_node): # type: nodes.Element
|
for node in self.document.findall(is_translatable_node):
|
||||||
node['translatable'] = True
|
node['translatable'] = True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user