Sphinx 8.1.2__py3-none-any.whl → 8.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Sphinx might be problematic. Click here for more details.
- sphinx/__init__.py +8 -4
- sphinx/__main__.py +2 -0
- sphinx/_cli/__init__.py +2 -5
- sphinx/_cli/util/colour.py +34 -11
- sphinx/_cli/util/errors.py +128 -61
- sphinx/addnodes.py +51 -35
- sphinx/application.py +362 -230
- sphinx/builders/__init__.py +87 -64
- sphinx/builders/_epub_base.py +65 -56
- sphinx/builders/changes.py +17 -23
- sphinx/builders/dirhtml.py +8 -13
- sphinx/builders/epub3.py +70 -38
- sphinx/builders/gettext.py +93 -73
- sphinx/builders/html/__init__.py +240 -186
- sphinx/builders/html/_assets.py +9 -2
- sphinx/builders/html/_build_info.py +3 -0
- sphinx/builders/latex/__init__.py +64 -54
- sphinx/builders/latex/constants.py +14 -11
- sphinx/builders/latex/nodes.py +2 -0
- sphinx/builders/latex/theming.py +8 -9
- sphinx/builders/latex/transforms.py +7 -5
- sphinx/builders/linkcheck.py +193 -149
- sphinx/builders/manpage.py +17 -17
- sphinx/builders/singlehtml.py +28 -16
- sphinx/builders/texinfo.py +28 -21
- sphinx/builders/text.py +10 -15
- sphinx/builders/xml.py +10 -19
- sphinx/cmd/build.py +49 -119
- sphinx/cmd/make_mode.py +35 -31
- sphinx/cmd/quickstart.py +78 -62
- sphinx/config.py +265 -163
- sphinx/directives/__init__.py +51 -54
- sphinx/directives/admonitions.py +107 -0
- sphinx/directives/code.py +24 -19
- sphinx/directives/other.py +21 -42
- sphinx/directives/patches.py +28 -16
- sphinx/domains/__init__.py +54 -31
- sphinx/domains/_domains_container.py +22 -17
- sphinx/domains/_index.py +5 -8
- sphinx/domains/c/__init__.py +366 -245
- sphinx/domains/c/_ast.py +378 -256
- sphinx/domains/c/_ids.py +89 -31
- sphinx/domains/c/_parser.py +283 -214
- sphinx/domains/c/_symbol.py +269 -198
- sphinx/domains/changeset.py +39 -24
- sphinx/domains/citation.py +54 -24
- sphinx/domains/cpp/__init__.py +517 -362
- sphinx/domains/cpp/_ast.py +999 -682
- sphinx/domains/cpp/_ids.py +133 -65
- sphinx/domains/cpp/_parser.py +746 -588
- sphinx/domains/cpp/_symbol.py +692 -489
- sphinx/domains/index.py +10 -8
- sphinx/domains/javascript.py +152 -74
- sphinx/domains/math.py +50 -40
- sphinx/domains/python/__init__.py +402 -211
- sphinx/domains/python/_annotations.py +134 -61
- sphinx/domains/python/_object.py +155 -68
- sphinx/domains/rst.py +94 -49
- sphinx/domains/std/__init__.py +510 -249
- sphinx/environment/__init__.py +345 -61
- sphinx/environment/adapters/asset.py +7 -1
- sphinx/environment/adapters/indexentries.py +15 -20
- sphinx/environment/adapters/toctree.py +19 -9
- sphinx/environment/collectors/__init__.py +3 -1
- sphinx/environment/collectors/asset.py +18 -15
- sphinx/environment/collectors/dependencies.py +8 -10
- sphinx/environment/collectors/metadata.py +6 -4
- sphinx/environment/collectors/title.py +3 -1
- sphinx/environment/collectors/toctree.py +4 -4
- sphinx/errors.py +1 -3
- sphinx/events.py +4 -4
- sphinx/ext/apidoc/__init__.py +66 -0
- sphinx/ext/apidoc/__main__.py +9 -0
- sphinx/ext/apidoc/_cli.py +356 -0
- sphinx/ext/apidoc/_extension.py +262 -0
- sphinx/ext/apidoc/_generate.py +356 -0
- sphinx/ext/apidoc/_shared.py +99 -0
- sphinx/ext/autodoc/__init__.py +837 -483
- sphinx/ext/autodoc/directive.py +57 -21
- sphinx/ext/autodoc/importer.py +184 -67
- sphinx/ext/autodoc/mock.py +25 -10
- sphinx/ext/autodoc/preserve_defaults.py +17 -9
- sphinx/ext/autodoc/type_comment.py +56 -29
- sphinx/ext/autodoc/typehints.py +49 -26
- sphinx/ext/autosectionlabel.py +28 -11
- sphinx/ext/autosummary/__init__.py +281 -142
- sphinx/ext/autosummary/generate.py +121 -51
- sphinx/ext/coverage.py +152 -91
- sphinx/ext/doctest.py +169 -101
- sphinx/ext/duration.py +12 -6
- sphinx/ext/extlinks.py +33 -21
- sphinx/ext/githubpages.py +8 -8
- sphinx/ext/graphviz.py +175 -109
- sphinx/ext/ifconfig.py +11 -6
- sphinx/ext/imgconverter.py +48 -25
- sphinx/ext/imgmath.py +127 -97
- sphinx/ext/inheritance_diagram.py +177 -103
- sphinx/ext/intersphinx/__init__.py +22 -13
- sphinx/ext/intersphinx/__main__.py +3 -1
- sphinx/ext/intersphinx/_cli.py +18 -14
- sphinx/ext/intersphinx/_load.py +91 -82
- sphinx/ext/intersphinx/_resolve.py +108 -74
- sphinx/ext/intersphinx/_shared.py +2 -2
- sphinx/ext/linkcode.py +28 -12
- sphinx/ext/mathjax.py +60 -29
- sphinx/ext/napoleon/__init__.py +19 -7
- sphinx/ext/napoleon/docstring.py +229 -231
- sphinx/ext/todo.py +44 -49
- sphinx/ext/viewcode.py +105 -57
- sphinx/extension.py +3 -1
- sphinx/highlighting.py +13 -7
- sphinx/io.py +9 -13
- sphinx/jinja2glue.py +29 -26
- sphinx/locale/__init__.py +8 -9
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
- sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +2660 -2555
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/sphinx.pot +2069 -1964
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/parsers.py +8 -7
- sphinx/project.py +2 -2
- sphinx/pycode/__init__.py +31 -21
- sphinx/pycode/ast.py +6 -3
- sphinx/pycode/parser.py +14 -8
- sphinx/pygments_styles.py +4 -5
- sphinx/registry.py +192 -92
- sphinx/roles.py +58 -7
- sphinx/search/__init__.py +75 -54
- sphinx/search/en.py +11 -13
- sphinx/search/fi.py +1 -1
- sphinx/search/ja.py +8 -6
- sphinx/search/nl.py +1 -1
- sphinx/search/zh.py +19 -21
- sphinx/testing/fixtures.py +26 -29
- sphinx/testing/path.py +26 -62
- sphinx/testing/restructuredtext.py +14 -8
- sphinx/testing/util.py +21 -19
- sphinx/texinputs/make.bat.jinja +50 -50
- sphinx/texinputs/sphinx.sty +4 -3
- sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
- sphinx/texinputs/sphinxlatexobjects.sty +29 -10
- sphinx/themes/basic/static/searchtools.js +8 -5
- sphinx/theming.py +49 -61
- sphinx/transforms/__init__.py +17 -38
- sphinx/transforms/compact_bullet_list.py +5 -3
- sphinx/transforms/i18n.py +8 -21
- sphinx/transforms/post_transforms/__init__.py +142 -93
- sphinx/transforms/post_transforms/code.py +5 -5
- sphinx/transforms/post_transforms/images.py +28 -24
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +109 -60
- sphinx/util/_files.py +39 -23
- sphinx/util/_importer.py +4 -1
- sphinx/util/_inventory_file_reader.py +76 -0
- sphinx/util/_io.py +2 -2
- sphinx/util/_lines.py +6 -3
- sphinx/util/_pathlib.py +40 -2
- sphinx/util/build_phase.py +2 -0
- sphinx/util/cfamily.py +19 -14
- sphinx/util/console.py +44 -179
- sphinx/util/display.py +9 -10
- sphinx/util/docfields.py +140 -122
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +118 -77
- sphinx/util/fileutil.py +25 -26
- sphinx/util/http_date.py +2 -0
- sphinx/util/i18n.py +77 -64
- sphinx/util/images.py +8 -6
- sphinx/util/inspect.py +147 -38
- sphinx/util/inventory.py +215 -116
- sphinx/util/logging.py +33 -33
- sphinx/util/matching.py +12 -4
- sphinx/util/nodes.py +18 -13
- sphinx/util/osutil.py +38 -39
- sphinx/util/parallel.py +22 -13
- sphinx/util/parsing.py +2 -1
- sphinx/util/png.py +6 -2
- sphinx/util/requests.py +33 -2
- sphinx/util/rst.py +3 -2
- sphinx/util/tags.py +1 -1
- sphinx/util/template.py +18 -10
- sphinx/util/texescape.py +8 -6
- sphinx/util/typing.py +148 -122
- sphinx/versioning.py +3 -3
- sphinx/writers/html.py +3 -1
- sphinx/writers/html5.py +63 -52
- sphinx/writers/latex.py +83 -67
- sphinx/writers/manpage.py +19 -38
- sphinx/writers/texinfo.py +47 -47
- sphinx/writers/text.py +50 -32
- sphinx/writers/xml.py +11 -8
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
- sphinx-8.2.0.dist-info/RECORD +606 -0
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/WHEEL +1 -1
- sphinx/builders/html/transforms.py +0 -90
- sphinx/ext/apidoc.py +0 -721
- sphinx/util/exceptions.py +0 -74
- sphinx-8.1.2.dist-info/RECORD +0 -598
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import posixpath
|
|
6
5
|
import re
|
|
6
|
+
from pathlib import Path
|
|
7
7
|
from typing import TYPE_CHECKING, cast
|
|
8
8
|
|
|
9
9
|
from docutils import nodes
|
|
10
|
-
from docutils.utils import relative_path
|
|
11
10
|
|
|
12
11
|
from sphinx.addnodes import pending_xref
|
|
13
12
|
from sphinx.deprecation import _deprecation_warning
|
|
@@ -16,9 +15,10 @@ from sphinx.ext.intersphinx._shared import LOGGER, InventoryAdapter
|
|
|
16
15
|
from sphinx.locale import _, __
|
|
17
16
|
from sphinx.transforms.post_transforms import ReferencesResolver
|
|
18
17
|
from sphinx.util.docutils import CustomReSTDispatcher, SphinxRole
|
|
18
|
+
from sphinx.util.osutil import _relative_path
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
|
-
from collections.abc import Iterable
|
|
21
|
+
from collections.abc import Iterable, Sequence, Set
|
|
22
22
|
from types import ModuleType
|
|
23
23
|
from typing import Any
|
|
24
24
|
|
|
@@ -27,31 +27,36 @@ if TYPE_CHECKING:
|
|
|
27
27
|
|
|
28
28
|
from sphinx.application import Sphinx
|
|
29
29
|
from sphinx.domains import Domain
|
|
30
|
+
from sphinx.domains._domains_container import _DomainsContainer
|
|
30
31
|
from sphinx.environment import BuildEnvironment
|
|
31
32
|
from sphinx.ext.intersphinx._shared import InventoryName
|
|
32
|
-
from sphinx.util.
|
|
33
|
+
from sphinx.util.inventory import _InventoryItem
|
|
34
|
+
from sphinx.util.typing import Inventory, RoleFunction
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
def _create_element_from_result(
|
|
36
|
-
|
|
38
|
+
domain_name: str,
|
|
37
39
|
inv_name: InventoryName | None,
|
|
38
|
-
|
|
40
|
+
inv_item: _InventoryItem,
|
|
39
41
|
node: pending_xref,
|
|
40
42
|
contnode: TextElement,
|
|
41
43
|
) -> nodes.reference:
|
|
42
|
-
|
|
44
|
+
uri = inv_item.uri
|
|
43
45
|
if '://' not in uri and node.get('refdoc'):
|
|
44
46
|
# get correct path in case of subdirectories
|
|
45
|
-
uri =
|
|
46
|
-
if
|
|
47
|
-
reftitle = _('(in %s v%s)') % (
|
|
47
|
+
uri = (_relative_path(Path(), Path(node['refdoc']).parent) / uri).as_posix()
|
|
48
|
+
if inv_item.project_version:
|
|
49
|
+
reftitle = _('(in %s v%s)') % (inv_item.project_name, inv_item.project_version)
|
|
48
50
|
else:
|
|
49
|
-
reftitle = _('(in %s)') % (
|
|
51
|
+
reftitle = _('(in %s)') % (inv_item.project_name,)
|
|
52
|
+
|
|
50
53
|
newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=reftitle)
|
|
51
54
|
if node.get('refexplicit'):
|
|
52
55
|
# use whatever title was given
|
|
53
56
|
newnode.append(contnode)
|
|
54
|
-
elif
|
|
57
|
+
elif inv_item.display_name == '-' or (
|
|
58
|
+
domain_name == 'std' and node['reftype'] == 'keyword'
|
|
59
|
+
):
|
|
55
60
|
# use whatever title was given, but strip prefix
|
|
56
61
|
title = contnode.astext()
|
|
57
62
|
if inv_name is not None and title.startswith(inv_name + ':'):
|
|
@@ -64,14 +69,14 @@ def _create_element_from_result(
|
|
|
64
69
|
newnode.append(contnode)
|
|
65
70
|
else:
|
|
66
71
|
# else use the given display name (used for :ref:)
|
|
67
|
-
newnode.append(contnode.__class__(
|
|
72
|
+
newnode.append(contnode.__class__(inv_item.display_name, inv_item.display_name))
|
|
68
73
|
return newnode
|
|
69
74
|
|
|
70
75
|
|
|
71
76
|
def _resolve_reference_in_domain_by_target(
|
|
72
77
|
inv_name: InventoryName | None,
|
|
73
78
|
inventory: Inventory,
|
|
74
|
-
|
|
79
|
+
domain_name: str,
|
|
75
80
|
objtypes: Iterable[str],
|
|
76
81
|
target: str,
|
|
77
82
|
node: pending_xref,
|
|
@@ -128,46 +133,47 @@ def _resolve_reference_in_domain_by_target(
|
|
|
128
133
|
# This is a fix for terms specifically, but potentially should apply to
|
|
129
134
|
# other types.
|
|
130
135
|
continue
|
|
131
|
-
return _create_element_from_result(
|
|
136
|
+
return _create_element_from_result(domain_name, inv_name, data, node, contnode)
|
|
132
137
|
return None
|
|
133
138
|
|
|
134
139
|
|
|
135
140
|
def _resolve_reference_in_domain(
|
|
136
|
-
env: BuildEnvironment,
|
|
137
141
|
inv_name: InventoryName | None,
|
|
138
142
|
inventory: Inventory,
|
|
139
143
|
honor_disabled_refs: bool,
|
|
144
|
+
disabled_reftypes: Set[str],
|
|
140
145
|
domain: Domain,
|
|
141
146
|
objtypes: Iterable[str],
|
|
142
147
|
node: pending_xref,
|
|
143
148
|
contnode: TextElement,
|
|
144
149
|
) -> nodes.reference | None:
|
|
145
|
-
|
|
150
|
+
domain_name = domain.name
|
|
151
|
+
obj_types: dict[str, None] = dict.fromkeys(objtypes)
|
|
146
152
|
|
|
147
153
|
# we adjust the object types for backwards compatibility
|
|
148
|
-
if
|
|
154
|
+
if domain_name == 'std' and 'cmdoption' in obj_types:
|
|
149
155
|
# cmdoptions were stored as std:option until Sphinx 1.6
|
|
150
156
|
obj_types['option'] = None
|
|
151
|
-
if
|
|
157
|
+
if domain_name == 'py' and 'attribute' in obj_types:
|
|
152
158
|
# properties are stored as py:method since Sphinx 2.1
|
|
153
159
|
obj_types['method'] = None
|
|
154
160
|
|
|
155
161
|
# the inventory contains domain:type as objtype
|
|
156
|
-
domain_name = domain.name
|
|
157
162
|
obj_types = {f'{domain_name}:{obj_type}': None for obj_type in obj_types}
|
|
158
163
|
|
|
159
164
|
# now that the objtypes list is complete we can remove the disabled ones
|
|
160
165
|
if honor_disabled_refs:
|
|
161
|
-
disabled = set(env.config.intersphinx_disabled_reftypes)
|
|
162
166
|
obj_types = {
|
|
163
|
-
obj_type: None
|
|
167
|
+
obj_type: None
|
|
168
|
+
for obj_type in obj_types
|
|
169
|
+
if obj_type not in disabled_reftypes
|
|
164
170
|
}
|
|
165
171
|
|
|
166
172
|
objtypes = [*obj_types.keys()]
|
|
167
173
|
|
|
168
174
|
# without qualification
|
|
169
175
|
res = _resolve_reference_in_domain_by_target(
|
|
170
|
-
inv_name, inventory,
|
|
176
|
+
inv_name, inventory, domain_name, objtypes, node['reftarget'], node, contnode
|
|
171
177
|
)
|
|
172
178
|
if res is not None:
|
|
173
179
|
return res
|
|
@@ -177,39 +183,36 @@ def _resolve_reference_in_domain(
|
|
|
177
183
|
if full_qualified_name is None:
|
|
178
184
|
return None
|
|
179
185
|
return _resolve_reference_in_domain_by_target(
|
|
180
|
-
inv_name, inventory,
|
|
186
|
+
inv_name, inventory, domain_name, objtypes, full_qualified_name, node, contnode
|
|
181
187
|
)
|
|
182
188
|
|
|
183
189
|
|
|
184
190
|
def _resolve_reference(
|
|
185
|
-
env: BuildEnvironment,
|
|
186
191
|
inv_name: InventoryName | None,
|
|
192
|
+
domains: _DomainsContainer,
|
|
187
193
|
inventory: Inventory,
|
|
188
194
|
honor_disabled_refs: bool,
|
|
195
|
+
disabled_reftypes: Set[str],
|
|
189
196
|
node: pending_xref,
|
|
190
197
|
contnode: TextElement,
|
|
191
198
|
) -> nodes.reference | None:
|
|
192
199
|
# disabling should only be done if no inventory is given
|
|
193
200
|
honor_disabled_refs = honor_disabled_refs and inv_name is None
|
|
194
|
-
intersphinx_disabled_reftypes = env.config.intersphinx_disabled_reftypes
|
|
195
201
|
|
|
196
|
-
if honor_disabled_refs and '*' in
|
|
202
|
+
if honor_disabled_refs and '*' in disabled_reftypes:
|
|
197
203
|
return None
|
|
198
204
|
|
|
199
205
|
typ = node['reftype']
|
|
200
206
|
if typ == 'any':
|
|
201
|
-
for domain in
|
|
202
|
-
if
|
|
203
|
-
honor_disabled_refs
|
|
204
|
-
and f'{domain.name}:*' in intersphinx_disabled_reftypes
|
|
205
|
-
):
|
|
207
|
+
for domain in domains.sorted():
|
|
208
|
+
if honor_disabled_refs and f'{domain.name}:*' in disabled_reftypes:
|
|
206
209
|
continue
|
|
207
210
|
objtypes: Iterable[str] = domain.object_types.keys()
|
|
208
211
|
res = _resolve_reference_in_domain(
|
|
209
|
-
env,
|
|
210
212
|
inv_name,
|
|
211
213
|
inventory,
|
|
212
214
|
honor_disabled_refs,
|
|
215
|
+
disabled_reftypes,
|
|
213
216
|
domain,
|
|
214
217
|
objtypes,
|
|
215
218
|
node,
|
|
@@ -223,17 +226,22 @@ def _resolve_reference(
|
|
|
223
226
|
if not domain_name:
|
|
224
227
|
# only objects in domains are in the inventory
|
|
225
228
|
return None
|
|
226
|
-
if honor_disabled_refs and f'{domain_name}:*' in
|
|
229
|
+
if honor_disabled_refs and f'{domain_name}:*' in disabled_reftypes:
|
|
227
230
|
return None
|
|
228
|
-
|
|
231
|
+
try:
|
|
232
|
+
domain = domains[domain_name]
|
|
233
|
+
except KeyError as exc:
|
|
234
|
+
msg = __('Domain %r is not registered') % domain_name
|
|
235
|
+
raise ExtensionError(msg) from exc
|
|
236
|
+
|
|
229
237
|
objtypes = domain.objtypes_for_role(typ) or ()
|
|
230
238
|
if not objtypes:
|
|
231
239
|
return None
|
|
232
240
|
return _resolve_reference_in_domain(
|
|
233
|
-
env,
|
|
234
241
|
inv_name,
|
|
235
242
|
inventory,
|
|
236
243
|
honor_disabled_refs,
|
|
244
|
+
disabled_reftypes,
|
|
237
245
|
domain,
|
|
238
246
|
objtypes,
|
|
239
247
|
node,
|
|
@@ -259,10 +267,11 @@ def resolve_reference_in_inventory(
|
|
|
259
267
|
"""
|
|
260
268
|
assert inventory_exists(env, inv_name)
|
|
261
269
|
return _resolve_reference(
|
|
262
|
-
env,
|
|
263
270
|
inv_name,
|
|
271
|
+
env.domains,
|
|
264
272
|
InventoryAdapter(env).named_inventory[inv_name],
|
|
265
273
|
False,
|
|
274
|
+
frozenset(env.config.intersphinx_disabled_reftypes),
|
|
266
275
|
node,
|
|
267
276
|
contnode,
|
|
268
277
|
)
|
|
@@ -279,10 +288,11 @@ def resolve_reference_any_inventory(
|
|
|
279
288
|
Resolution is tried with the target as is in any inventory.
|
|
280
289
|
"""
|
|
281
290
|
return _resolve_reference(
|
|
282
|
-
env,
|
|
283
291
|
None,
|
|
292
|
+
env.domains,
|
|
284
293
|
InventoryAdapter(env).main_inventory,
|
|
285
294
|
honor_disabled_refs,
|
|
295
|
+
frozenset(env.config.intersphinx_disabled_reftypes),
|
|
286
296
|
node,
|
|
287
297
|
contnode,
|
|
288
298
|
)
|
|
@@ -295,9 +305,11 @@ def resolve_reference_detect_inventory(
|
|
|
295
305
|
|
|
296
306
|
Resolution is tried first with the target as is in any inventory.
|
|
297
307
|
If this does not succeed, then the target is split by the first ``:``,
|
|
298
|
-
to form ``inv_name:
|
|
308
|
+
to form ``inv_name:new_target``. If ``inv_name`` is a named inventory, then resolution
|
|
299
309
|
is tried in that inventory with the new target.
|
|
300
310
|
"""
|
|
311
|
+
resolve_self = env.config.intersphinx_resolve_self
|
|
312
|
+
|
|
301
313
|
# ordinary direct lookup, use data as is
|
|
302
314
|
res = resolve_reference_any_inventory(env, True, node, contnode)
|
|
303
315
|
if res is not None:
|
|
@@ -307,10 +319,18 @@ def resolve_reference_detect_inventory(
|
|
|
307
319
|
target = node['reftarget']
|
|
308
320
|
if ':' not in target:
|
|
309
321
|
return None
|
|
310
|
-
inv_name,
|
|
322
|
+
inv_name, _, new_target = target.partition(':')
|
|
323
|
+
|
|
324
|
+
# check if the target is self-referential
|
|
325
|
+
self_referential = bool(resolve_self) and resolve_self == inv_name
|
|
326
|
+
if self_referential:
|
|
327
|
+
node['reftarget'] = new_target
|
|
328
|
+
node['intersphinx_self_referential'] = True
|
|
329
|
+
return None
|
|
330
|
+
|
|
311
331
|
if not inventory_exists(env, inv_name):
|
|
312
332
|
return None
|
|
313
|
-
node['reftarget'] =
|
|
333
|
+
node['reftarget'] = new_target
|
|
314
334
|
res_inv = resolve_reference_in_inventory(env, inv_name, node, contnode)
|
|
315
335
|
node['reftarget'] = target
|
|
316
336
|
return res_inv
|
|
@@ -354,11 +374,16 @@ class IntersphinxRole(SphinxRole):
|
|
|
354
374
|
def run(self) -> tuple[list[Node], list[system_message]]:
|
|
355
375
|
assert self.name == self.orig_name.lower()
|
|
356
376
|
inventory, name_suffix = self.get_inventory_and_name_suffix(self.orig_name)
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
377
|
+
resolve_self = self.env.config.intersphinx_resolve_self
|
|
378
|
+
self_referential = bool(resolve_self) and resolve_self == inventory
|
|
379
|
+
|
|
380
|
+
if not self_referential:
|
|
381
|
+
if inventory and not inventory_exists(self.env, inventory):
|
|
382
|
+
self._emit_warning(
|
|
383
|
+
__('inventory for external cross-reference not found: %r'),
|
|
384
|
+
inventory,
|
|
385
|
+
)
|
|
386
|
+
return [], []
|
|
362
387
|
|
|
363
388
|
domain_name, role_name = self._get_domain_role(name_suffix)
|
|
364
389
|
|
|
@@ -397,27 +422,30 @@ class IntersphinxRole(SphinxRole):
|
|
|
397
422
|
else:
|
|
398
423
|
# the user did not specify a domain,
|
|
399
424
|
# so we check first the default (if available) then standard domains
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
if
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
domains
|
|
425
|
+
default_domain = self.env.current_document.default_domain
|
|
426
|
+
std_domain = self.env.domains.standard_domain
|
|
427
|
+
domains: Sequence[Domain]
|
|
428
|
+
if default_domain is None or std_domain == default_domain:
|
|
429
|
+
domains = (std_domain,)
|
|
430
|
+
else:
|
|
431
|
+
domains = (default_domain, std_domain)
|
|
407
432
|
|
|
408
433
|
role_func = None
|
|
409
434
|
for domain in domains:
|
|
410
|
-
|
|
435
|
+
role_func = domain.roles.get(role_name)
|
|
436
|
+
if role_func is not None:
|
|
411
437
|
domain_name = domain.name
|
|
412
438
|
break
|
|
413
439
|
|
|
414
440
|
if role_func is None or domain_name is None:
|
|
415
|
-
domains_str = self._concat_strings(
|
|
441
|
+
domains_str = self._concat_strings(domain.name for domain in domains)
|
|
416
442
|
msg = 'role for external cross-reference not found in domains %s: %r'
|
|
417
|
-
possible_roles: set[str] =
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
443
|
+
possible_roles: set[str] = {
|
|
444
|
+
f'{domain.name}:{r}'
|
|
445
|
+
for domain in domains
|
|
446
|
+
if (object_types := domain.object_types.get(role_name))
|
|
447
|
+
for r in object_types.roles
|
|
448
|
+
}
|
|
421
449
|
if possible_roles:
|
|
422
450
|
msg = f'{msg} (perhaps you meant one of: %s)'
|
|
423
451
|
self._emit_warning(
|
|
@@ -440,10 +468,14 @@ class IntersphinxRole(SphinxRole):
|
|
|
440
468
|
self.content,
|
|
441
469
|
)
|
|
442
470
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
471
|
+
if not self_referential:
|
|
472
|
+
# We do the intersphinx resolution by inserting our
|
|
473
|
+
# 'intersphinx' and 'inventory' attributes into the nodes.
|
|
474
|
+
# Only do this when it is an external reference.
|
|
475
|
+
for node in result:
|
|
476
|
+
if isinstance(node, pending_xref):
|
|
477
|
+
node['intersphinx'] = True
|
|
478
|
+
node['inventory'] = inventory
|
|
447
479
|
|
|
448
480
|
return result, messages
|
|
449
481
|
|
|
@@ -505,20 +537,21 @@ class IntersphinxRole(SphinxRole):
|
|
|
505
537
|
names = name.split(':')
|
|
506
538
|
if len(names) == 1:
|
|
507
539
|
# role
|
|
508
|
-
|
|
509
|
-
|
|
540
|
+
if (domain := self.env.current_document.default_domain) is not None:
|
|
541
|
+
domain_name = domain.name
|
|
542
|
+
else:
|
|
543
|
+
domain_name = None
|
|
510
544
|
role = names[0]
|
|
511
545
|
elif len(names) == 2:
|
|
512
546
|
# domain:role:
|
|
513
|
-
|
|
514
|
-
role = names[1]
|
|
547
|
+
domain_name, role = names
|
|
515
548
|
else:
|
|
516
549
|
return None
|
|
517
550
|
|
|
518
|
-
if
|
|
519
|
-
return
|
|
551
|
+
if domain_name and self.is_existent_role(domain_name, role):
|
|
552
|
+
return domain_name, role
|
|
520
553
|
elif self.is_existent_role('std', role):
|
|
521
|
-
return
|
|
554
|
+
return 'std', role
|
|
522
555
|
else:
|
|
523
556
|
return None
|
|
524
557
|
|
|
@@ -527,10 +560,11 @@ class IntersphinxRole(SphinxRole):
|
|
|
527
560
|
__name__, f'{self.__class__.__name__}.is_existent_role', '', remove=(9, 0)
|
|
528
561
|
)
|
|
529
562
|
try:
|
|
530
|
-
domain = self.env.
|
|
531
|
-
|
|
532
|
-
except ExtensionError:
|
|
563
|
+
domain = self.env.domains[domain_name]
|
|
564
|
+
except KeyError:
|
|
533
565
|
return False
|
|
566
|
+
else:
|
|
567
|
+
return role_name in domain.roles
|
|
534
568
|
|
|
535
569
|
def invoke_role(
|
|
536
570
|
self, role: tuple[str, str]
|
|
@@ -569,7 +603,7 @@ class IntersphinxRoleResolver(ReferencesResolver):
|
|
|
569
603
|
for node in self.document.findall(pending_xref):
|
|
570
604
|
if 'intersphinx' not in node:
|
|
571
605
|
continue
|
|
572
|
-
contnode = cast(nodes.TextElement, node[0].deepcopy())
|
|
606
|
+
contnode = cast('nodes.TextElement', node[0].deepcopy())
|
|
573
607
|
inv_name = node['inventory']
|
|
574
608
|
if inv_name is not None:
|
|
575
609
|
assert inventory_exists(self.env, inv_name)
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from sphinx.util import logging
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from collections.abc import Sequence
|
|
11
|
-
from typing import TypeAlias
|
|
11
|
+
from typing import Any, Final, NoReturn, TypeAlias
|
|
12
12
|
|
|
13
13
|
from sphinx.environment import BuildEnvironment
|
|
14
14
|
from sphinx.util.typing import Inventory
|
sphinx/ext/linkcode.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from types import FunctionType, NoneType
|
|
5
6
|
from typing import TYPE_CHECKING
|
|
6
7
|
|
|
7
8
|
from docutils import nodes
|
|
@@ -18,12 +19,29 @@ if TYPE_CHECKING:
|
|
|
18
19
|
from sphinx.util.typing import ExtensionMetadata
|
|
19
20
|
|
|
20
21
|
|
|
22
|
+
_DOMAIN_KEYS = {
|
|
23
|
+
'py': ['module', 'fullname'],
|
|
24
|
+
'c': ['names'],
|
|
25
|
+
'cpp': ['names'],
|
|
26
|
+
'js': ['object', 'fullname'],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def add_linkcode_domain(domain: str, keys: list[str], override: bool = False) -> None:
|
|
31
|
+
"""Register a new list of keys to use for a domain.
|
|
32
|
+
|
|
33
|
+
.. versionadded:: 8.2
|
|
34
|
+
"""
|
|
35
|
+
if override or domain not in _DOMAIN_KEYS:
|
|
36
|
+
_DOMAIN_KEYS[domain] = list(keys)
|
|
37
|
+
|
|
38
|
+
|
|
21
39
|
class LinkcodeError(SphinxError):
|
|
22
|
-
category =
|
|
40
|
+
category = 'linkcode error'
|
|
23
41
|
|
|
24
42
|
|
|
25
43
|
def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
26
|
-
env = app.
|
|
44
|
+
env = app.env
|
|
27
45
|
|
|
28
46
|
resolve_target = getattr(env.config, 'linkcode_resolve', None)
|
|
29
47
|
if not callable(env.config.linkcode_resolve):
|
|
@@ -37,13 +55,6 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
|
37
55
|
# ``supported_linkcode`` attribute.
|
|
38
56
|
node_only_expr = getattr(app.builder, 'supported_linkcode', 'html')
|
|
39
57
|
|
|
40
|
-
domain_keys = {
|
|
41
|
-
'py': ['module', 'fullname'],
|
|
42
|
-
'c': ['names'],
|
|
43
|
-
'cpp': ['names'],
|
|
44
|
-
'js': ['object', 'fullname'],
|
|
45
|
-
}
|
|
46
|
-
|
|
47
58
|
for objnode in list(doctree.findall(addnodes.desc)):
|
|
48
59
|
domain = objnode.get('domain')
|
|
49
60
|
uris: set[str] = set()
|
|
@@ -53,7 +64,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
|
53
64
|
|
|
54
65
|
# Convert signode to a specified format
|
|
55
66
|
info = {}
|
|
56
|
-
for key in
|
|
67
|
+
for key in _DOMAIN_KEYS.get(domain, ()):
|
|
57
68
|
value = signode.get(key)
|
|
58
69
|
if not value:
|
|
59
70
|
value = ''
|
|
@@ -80,5 +91,10 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|
|
80
91
|
|
|
81
92
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
82
93
|
app.connect('doctree-read', doctree_read)
|
|
83
|
-
app.add_config_value(
|
|
84
|
-
|
|
94
|
+
app.add_config_value(
|
|
95
|
+
'linkcode_resolve', None, '', types=frozenset({FunctionType, NoneType})
|
|
96
|
+
)
|
|
97
|
+
return {
|
|
98
|
+
'version': sphinx.__display_version__,
|
|
99
|
+
'parallel_read_safe': True,
|
|
100
|
+
}
|
sphinx/ext/mathjax.py
CHANGED
|
@@ -8,18 +8,21 @@ This requires the MathJax JavaScript library on your webserver/computer.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import json
|
|
11
|
-
from
|
|
11
|
+
from types import NoneType
|
|
12
|
+
from typing import TYPE_CHECKING, cast
|
|
12
13
|
|
|
13
14
|
from docutils import nodes
|
|
14
15
|
|
|
15
16
|
import sphinx
|
|
16
|
-
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
17
17
|
from sphinx.errors import ExtensionError
|
|
18
18
|
from sphinx.locale import _
|
|
19
19
|
from sphinx.util.math import get_node_equation_number
|
|
20
20
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
22
24
|
from sphinx.application import Sphinx
|
|
25
|
+
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
23
26
|
from sphinx.util.typing import ExtensionMetadata
|
|
24
27
|
from sphinx.writers.html5 import HTML5Translator
|
|
25
28
|
|
|
@@ -31,16 +34,21 @@ logger = sphinx.util.logging.getLogger(__name__)
|
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
def html_visit_math(self: HTML5Translator, node: nodes.math) -> None:
|
|
34
|
-
self.body.append(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
self.body.append(
|
|
38
|
+
self.starttag(node, 'span', '', CLASS='math notranslate nohighlight')
|
|
39
|
+
)
|
|
40
|
+
self.body.append(
|
|
41
|
+
self.builder.config.mathjax_inline[0]
|
|
42
|
+
+ self.encode(node.astext())
|
|
43
|
+
+ self.builder.config.mathjax_inline[1]
|
|
44
|
+
+ '</span>'
|
|
45
|
+
)
|
|
38
46
|
raise nodes.SkipNode
|
|
39
47
|
|
|
40
48
|
|
|
41
49
|
def html_visit_displaymath(self: HTML5Translator, node: nodes.math_block) -> None:
|
|
42
50
|
self.body.append(self.starttag(node, 'div', CLASS='math notranslate nohighlight'))
|
|
43
|
-
if node
|
|
51
|
+
if node.get('no-wrap', node.get('nowrap', False)):
|
|
44
52
|
self.body.append(self.encode(node.astext()))
|
|
45
53
|
self.body.append('</div>')
|
|
46
54
|
raise nodes.SkipNode
|
|
@@ -70,26 +78,31 @@ def html_visit_displaymath(self: HTML5Translator, node: nodes.math_block) -> Non
|
|
|
70
78
|
raise nodes.SkipNode
|
|
71
79
|
|
|
72
80
|
|
|
73
|
-
def install_mathjax(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
def install_mathjax(
|
|
82
|
+
app: Sphinx,
|
|
83
|
+
pagename: str,
|
|
84
|
+
templatename: str,
|
|
85
|
+
context: dict[str, Any],
|
|
86
|
+
event_arg: Any,
|
|
87
|
+
) -> None:
|
|
88
|
+
if app.builder.format != 'html':
|
|
89
|
+
return
|
|
90
|
+
if app.builder.math_renderer_name != 'mathjax': # type: ignore[attr-defined]
|
|
79
91
|
return
|
|
80
92
|
if not app.config.mathjax_path:
|
|
81
93
|
msg = 'mathjax_path config value must be set for the mathjax extension to work'
|
|
82
94
|
raise ExtensionError(msg)
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if app.registry.html_assets_policy == 'always' or
|
|
96
|
+
builder = cast('StandaloneHTMLBuilder', app.builder)
|
|
97
|
+
page_has_equations = context.get('has_maths_elements', False)
|
|
98
|
+
if app.registry.html_assets_policy == 'always' or page_has_equations:
|
|
87
99
|
# Enable mathjax only if equations exists
|
|
88
100
|
if app.config.mathjax2_config:
|
|
89
101
|
if app.config.mathjax_path == MATHJAX_URL:
|
|
90
102
|
logger.warning(
|
|
91
103
|
'mathjax_config/mathjax2_config does not work '
|
|
92
|
-
'for the current MathJax version, use mathjax3_config instead'
|
|
104
|
+
'for the current MathJax version, use mathjax3_config instead'
|
|
105
|
+
)
|
|
93
106
|
body = 'MathJax.Hub.Config(%s)' % json.dumps(app.config.mathjax2_config)
|
|
94
107
|
builder.add_js_file('', type='text/x-mathjax-config', body=body)
|
|
95
108
|
if app.config.mathjax3_config:
|
|
@@ -110,17 +123,35 @@ def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: dict
|
|
|
110
123
|
|
|
111
124
|
|
|
112
125
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
113
|
-
app.add_html_math_renderer(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
app.add_config_value('
|
|
120
|
-
app.add_config_value('
|
|
121
|
-
app.add_config_value(
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
app.add_html_math_renderer(
|
|
127
|
+
'mathjax',
|
|
128
|
+
inline_renderers=(html_visit_math, None),
|
|
129
|
+
block_renderers=(html_visit_displaymath, None),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
app.add_config_value('mathjax_path', MATHJAX_URL, 'html', types=frozenset({str}))
|
|
133
|
+
app.add_config_value('mathjax_options', {}, 'html', types=frozenset({dict}))
|
|
134
|
+
app.add_config_value(
|
|
135
|
+
'mathjax_inline', [r'\(', r'\)'], 'html', types=frozenset({list, tuple})
|
|
136
|
+
)
|
|
137
|
+
app.add_config_value(
|
|
138
|
+
'mathjax_display', [r'\[', r'\]'], 'html', types=frozenset({list, tuple})
|
|
139
|
+
)
|
|
140
|
+
app.add_config_value(
|
|
141
|
+
'mathjax_config', None, 'html', types=frozenset({dict, NoneType})
|
|
142
|
+
)
|
|
143
|
+
app.add_config_value(
|
|
144
|
+
'mathjax2_config',
|
|
145
|
+
lambda c: c.mathjax_config,
|
|
146
|
+
'html',
|
|
147
|
+
types=frozenset({dict, NoneType}),
|
|
148
|
+
)
|
|
149
|
+
app.add_config_value(
|
|
150
|
+
'mathjax3_config', None, 'html', types=frozenset({dict, NoneType})
|
|
151
|
+
)
|
|
124
152
|
app.connect('html-page-context', install_mathjax)
|
|
125
153
|
|
|
126
|
-
return {
|
|
154
|
+
return {
|
|
155
|
+
'version': sphinx.__display_version__,
|
|
156
|
+
'parallel_read_safe': True,
|
|
157
|
+
}
|