Sphinx 8.1.3__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 +829 -480
- 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.3.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
- {sphinx-8.1.3.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
- sphinx-8.2.0.dist-info/RECORD +606 -0
- {sphinx-8.1.3.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.3.dist-info/RECORD +0 -598
- {sphinx-8.1.3.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
sphinx/writers/latex.py
CHANGED
|
@@ -8,11 +8,11 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import re
|
|
10
10
|
from collections import defaultdict
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from typing import TYPE_CHECKING, Any, ClassVar, cast
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import TYPE_CHECKING, cast
|
|
14
13
|
|
|
15
14
|
from docutils import nodes, writers
|
|
15
|
+
from roman_numerals import RomanNumeral
|
|
16
16
|
|
|
17
17
|
from sphinx import addnodes, highlighting
|
|
18
18
|
from sphinx.errors import SphinxError
|
|
@@ -24,13 +24,10 @@ from sphinx.util.nodes import clean_astext, get_prev_node
|
|
|
24
24
|
from sphinx.util.template import LaTeXRenderer
|
|
25
25
|
from sphinx.util.texescape import tex_replace_map
|
|
26
26
|
|
|
27
|
-
try:
|
|
28
|
-
from docutils.utils.roman import toRoman
|
|
29
|
-
except ImportError:
|
|
30
|
-
# In Debian/Ubuntu, roman package is provided as roman, not as docutils.utils.roman
|
|
31
|
-
from roman import toRoman # type: ignore[no-redef, import-not-found]
|
|
32
|
-
|
|
33
27
|
if TYPE_CHECKING:
|
|
28
|
+
from collections.abc import Iterable
|
|
29
|
+
from typing import Any, ClassVar
|
|
30
|
+
|
|
34
31
|
from docutils.nodes import Element, Node, Text
|
|
35
32
|
|
|
36
33
|
from sphinx.builders.latex import LaTeXBuilder
|
|
@@ -100,7 +97,7 @@ class LaTeXWriter(writers.Writer): # type: ignore[type-arg]
|
|
|
100
97
|
self.document, self.builder, self.theme
|
|
101
98
|
)
|
|
102
99
|
self.document.walkabout(visitor)
|
|
103
|
-
self.output = cast(LaTeXTranslator, visitor).astext()
|
|
100
|
+
self.output = cast('LaTeXTranslator', visitor).astext()
|
|
104
101
|
|
|
105
102
|
|
|
106
103
|
# Helper classes
|
|
@@ -219,8 +216,8 @@ class Table:
|
|
|
219
216
|
self.cell_id += 1
|
|
220
217
|
for col in range(width):
|
|
221
218
|
for row in range(height):
|
|
222
|
-
assert self.cells[
|
|
223
|
-
self.cells[
|
|
219
|
+
assert self.cells[self.row + row, self.col + col] == 0
|
|
220
|
+
self.cells[self.row + row, self.col + col] = self.cell_id
|
|
224
221
|
|
|
225
222
|
def cell(
|
|
226
223
|
self,
|
|
@@ -246,25 +243,25 @@ class TableCell:
|
|
|
246
243
|
"""Data of a cell in a table."""
|
|
247
244
|
|
|
248
245
|
def __init__(self, table: Table, row: int, col: int) -> None:
|
|
249
|
-
if table.cells[
|
|
246
|
+
if table.cells[row, col] == 0:
|
|
250
247
|
raise IndexError
|
|
251
248
|
|
|
252
249
|
self.table = table
|
|
253
|
-
self.cell_id = table.cells[
|
|
250
|
+
self.cell_id = table.cells[row, col]
|
|
254
251
|
self.row = row
|
|
255
252
|
self.col = col
|
|
256
253
|
|
|
257
254
|
# adjust position for multirow/multicol cell
|
|
258
|
-
while table.cells[
|
|
255
|
+
while table.cells[self.row - 1, self.col] == self.cell_id:
|
|
259
256
|
self.row -= 1
|
|
260
|
-
while table.cells[
|
|
257
|
+
while table.cells[self.row, self.col - 1] == self.cell_id:
|
|
261
258
|
self.col -= 1
|
|
262
259
|
|
|
263
260
|
@property
|
|
264
261
|
def width(self) -> int:
|
|
265
262
|
"""Returns the cell width."""
|
|
266
263
|
width = 0
|
|
267
|
-
while self.table.cells[
|
|
264
|
+
while self.table.cells[self.row, self.col + width] == self.cell_id:
|
|
268
265
|
width += 1
|
|
269
266
|
return width
|
|
270
267
|
|
|
@@ -272,7 +269,7 @@ class TableCell:
|
|
|
272
269
|
def height(self) -> int:
|
|
273
270
|
"""Returns the cell height."""
|
|
274
271
|
height = 0
|
|
275
|
-
while self.table.cells[
|
|
272
|
+
while self.table.cells[self.row + height, self.col] == self.cell_id:
|
|
276
273
|
height += 1
|
|
277
274
|
return height
|
|
278
275
|
|
|
@@ -291,7 +288,7 @@ def rstdim_to_latexdim(width_str: str, scale: int = 100) -> str:
|
|
|
291
288
|
amount, unit = match.groups()[:2]
|
|
292
289
|
if scale == 100:
|
|
293
290
|
float(amount) # validate amount is float
|
|
294
|
-
if unit in
|
|
291
|
+
if unit in {'', 'px'}:
|
|
295
292
|
res = r'%s\sphinxpxdimen' % amount
|
|
296
293
|
elif unit == 'pt':
|
|
297
294
|
res = '%sbp' % amount # convert to 'bp'
|
|
@@ -299,7 +296,7 @@ def rstdim_to_latexdim(width_str: str, scale: int = 100) -> str:
|
|
|
299
296
|
res = r'%.3f\linewidth' % (float(amount) / 100.0)
|
|
300
297
|
else:
|
|
301
298
|
amount_float = float(amount) * scale / 100.0
|
|
302
|
-
if unit in
|
|
299
|
+
if unit in {'', 'px'}:
|
|
303
300
|
res = r'%.5f\sphinxpxdimen' % amount_float
|
|
304
301
|
elif unit == 'pt':
|
|
305
302
|
res = '%.5fbp' % amount_float
|
|
@@ -326,7 +323,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
326
323
|
|
|
327
324
|
# flags
|
|
328
325
|
self.in_title = 0
|
|
329
|
-
self.in_production_list =
|
|
326
|
+
self.in_production_list = False
|
|
330
327
|
self.in_footnote = 0
|
|
331
328
|
self.in_caption = 0
|
|
332
329
|
self.in_term = 0
|
|
@@ -564,7 +561,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
564
561
|
indices_config = frozenset(indices_config)
|
|
565
562
|
else:
|
|
566
563
|
check_names = False
|
|
567
|
-
for domain in self.
|
|
564
|
+
for domain in self._domains.sorted():
|
|
568
565
|
for index_cls in domain.indices:
|
|
569
566
|
index_name = f'{domain.name}-{index_cls.name}'
|
|
570
567
|
if check_names and index_name not in indices_config:
|
|
@@ -583,18 +580,19 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
583
580
|
def render(self, template_name: str, variables: dict[str, Any]) -> str:
|
|
584
581
|
renderer = LaTeXRenderer(latex_engine=self.config.latex_engine)
|
|
585
582
|
for template_dir in self.config.templates_path:
|
|
586
|
-
template =
|
|
587
|
-
if
|
|
588
|
-
return renderer.render(template, variables)
|
|
589
|
-
elif template.
|
|
590
|
-
|
|
591
|
-
|
|
583
|
+
template = self.builder.confdir / template_dir / template_name
|
|
584
|
+
if template.exists():
|
|
585
|
+
return renderer.render(str(template), variables)
|
|
586
|
+
elif template.suffix == '.jinja':
|
|
587
|
+
legacy_template_name = template.name.removesuffix('.jinja') + '_t'
|
|
588
|
+
legacy_template = template.with_name(legacy_template_name)
|
|
589
|
+
if legacy_template.exists():
|
|
592
590
|
logger.warning(
|
|
593
591
|
__('template %s not found; loading from legacy %s instead'),
|
|
594
592
|
template_name,
|
|
595
593
|
legacy_template,
|
|
596
594
|
)
|
|
597
|
-
return renderer.render(legacy_template, variables)
|
|
595
|
+
return renderer.render(str(legacy_template), variables)
|
|
598
596
|
|
|
599
597
|
return renderer.render(template_name, variables)
|
|
600
598
|
|
|
@@ -673,22 +671,20 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
673
671
|
def visit_productionlist(self, node: Element) -> None:
|
|
674
672
|
self.body.append(BLANKLINE)
|
|
675
673
|
self.body.append(r'\begin{productionlist}' + CR)
|
|
676
|
-
self.in_production_list =
|
|
674
|
+
self.in_production_list = True
|
|
677
675
|
|
|
678
676
|
def depart_productionlist(self, node: Element) -> None:
|
|
677
|
+
self.in_production_list = False
|
|
679
678
|
self.body.append(r'\end{productionlist}' + BLANKLINE)
|
|
680
|
-
self.in_production_list = 0
|
|
681
679
|
|
|
682
680
|
def visit_production(self, node: Element) -> None:
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
else:
|
|
688
|
-
self.body.append(r'\productioncont{')
|
|
681
|
+
# Nothing to do, the productionlist LaTeX environment
|
|
682
|
+
# is configured to render the nodes line-by-line
|
|
683
|
+
# But see also visit_literal_strong special clause.
|
|
684
|
+
pass
|
|
689
685
|
|
|
690
686
|
def depart_production(self, node: Element) -> None:
|
|
691
|
-
|
|
687
|
+
pass
|
|
692
688
|
|
|
693
689
|
def visit_transition(self, node: Element) -> None:
|
|
694
690
|
self.body.append(self.elements['transition'])
|
|
@@ -956,6 +952,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
956
952
|
self.required_params_left = sum(self.list_is_required_param)
|
|
957
953
|
self.param_separator = r'\sphinxparamcomma '
|
|
958
954
|
self.multi_line_parameter_list = node.get('multi_line_parameter_list', False)
|
|
955
|
+
self.trailing_comma = node.get('multi_line_trailing_comma', False)
|
|
959
956
|
|
|
960
957
|
def visit_desc_parameterlist(self, node: Element) -> None:
|
|
961
958
|
if self.has_tp_list:
|
|
@@ -1015,7 +1012,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1015
1012
|
if (
|
|
1016
1013
|
opt_param_left_at_level
|
|
1017
1014
|
or is_required
|
|
1018
|
-
and (
|
|
1015
|
+
and (next_is_required or self.trailing_comma)
|
|
1019
1016
|
):
|
|
1020
1017
|
self.body.append(self.param_separator)
|
|
1021
1018
|
|
|
@@ -1057,13 +1054,20 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1057
1054
|
|
|
1058
1055
|
def depart_desc_optional(self, node: Element) -> None:
|
|
1059
1056
|
self.optional_param_level -= 1
|
|
1057
|
+
level = self.optional_param_level
|
|
1060
1058
|
if self.multi_line_parameter_list:
|
|
1059
|
+
max_level = self.max_optional_param_level
|
|
1060
|
+
len_lirp = len(self.list_is_required_param)
|
|
1061
|
+
is_last_group = self.param_group_index + 1 == len_lirp
|
|
1061
1062
|
# If it's the first time we go down one level, add the separator before the
|
|
1062
|
-
# bracket
|
|
1063
|
-
|
|
1063
|
+
# bracket, except if this is the last parameter and the parameter list
|
|
1064
|
+
# should not feature a trailing comma.
|
|
1065
|
+
if level == max_level - 1 and (
|
|
1066
|
+
not is_last_group or level > 0 or self.trailing_comma
|
|
1067
|
+
):
|
|
1064
1068
|
self.body.append(self.param_separator)
|
|
1065
1069
|
self.body.append('}')
|
|
1066
|
-
if
|
|
1070
|
+
if level == 0:
|
|
1067
1071
|
self.param_group_index += 1
|
|
1068
1072
|
|
|
1069
1073
|
def visit_desc_annotation(self, node: Element) -> None:
|
|
@@ -1090,7 +1094,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1090
1094
|
self.no_latex_floats -= 1
|
|
1091
1095
|
|
|
1092
1096
|
def visit_rubric(self, node: nodes.rubric) -> None:
|
|
1093
|
-
if len(node) == 1 and node.astext() in
|
|
1097
|
+
if len(node) == 1 and node.astext() in {'Footnotes', _('Footnotes')}:
|
|
1094
1098
|
raise nodes.SkipNode
|
|
1095
1099
|
tag = 'subsubsection'
|
|
1096
1100
|
if 'heading-level' in node:
|
|
@@ -1115,7 +1119,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1115
1119
|
|
|
1116
1120
|
def visit_footnote(self, node: Element) -> None:
|
|
1117
1121
|
self.in_footnote += 1
|
|
1118
|
-
label = cast(nodes.label, node[0])
|
|
1122
|
+
label = cast('nodes.label', node[0])
|
|
1119
1123
|
if self.in_parsed_literal:
|
|
1120
1124
|
self.body.append(r'\begin{footnote}[%s]' % label.astext())
|
|
1121
1125
|
else:
|
|
@@ -1337,7 +1341,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1337
1341
|
if (
|
|
1338
1342
|
len(node) == 1
|
|
1339
1343
|
and isinstance(node[0], nodes.paragraph)
|
|
1340
|
-
and node.astext()
|
|
1344
|
+
and not node.astext()
|
|
1341
1345
|
):
|
|
1342
1346
|
pass
|
|
1343
1347
|
else:
|
|
@@ -1386,8 +1390,8 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1386
1390
|
def visit_acks(self, node: Element) -> None:
|
|
1387
1391
|
# this is a list in the source, but should be rendered as a
|
|
1388
1392
|
# comma-separated list here
|
|
1389
|
-
bullet_list = cast(nodes.bullet_list, node[0])
|
|
1390
|
-
list_items = cast(Iterable[nodes.list_item], bullet_list)
|
|
1393
|
+
bullet_list = cast('nodes.bullet_list', node[0])
|
|
1394
|
+
list_items = cast('Iterable[nodes.list_item]', bullet_list)
|
|
1391
1395
|
self.body.append(BLANKLINE)
|
|
1392
1396
|
self.body.append(', '.join(n.astext() for n in list_items) + '.')
|
|
1393
1397
|
self.body.append(BLANKLINE)
|
|
@@ -1420,8 +1424,9 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1420
1424
|
else:
|
|
1421
1425
|
return get_nested_level(node.parent)
|
|
1422
1426
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1427
|
+
nested_level = get_nested_level(node)
|
|
1428
|
+
enum = f'enum{RomanNumeral(nested_level).to_lowercase()}'
|
|
1429
|
+
enumnext = f'enum{RomanNumeral(nested_level + 1).to_lowercase()}'
|
|
1425
1430
|
style = ENUMERATE_LIST_STYLE.get(get_enumtype(node))
|
|
1426
1431
|
prefix = node.get('prefix', '')
|
|
1427
1432
|
suffix = node.get('suffix', '.')
|
|
@@ -1648,7 +1653,9 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1648
1653
|
options = ''
|
|
1649
1654
|
if include_graphics_options:
|
|
1650
1655
|
options = '[%s]' % ','.join(include_graphics_options)
|
|
1651
|
-
|
|
1656
|
+
img_path = Path(uri)
|
|
1657
|
+
base = img_path.with_suffix('')
|
|
1658
|
+
ext = img_path.suffix
|
|
1652
1659
|
|
|
1653
1660
|
if self.in_title and base:
|
|
1654
1661
|
# Lowercase tokens forcely because some fncychap themes capitalize
|
|
@@ -1657,8 +1664,8 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1657
1664
|
else:
|
|
1658
1665
|
cmd = rf'\sphinxincludegraphics{options}{{{{{base}}}{ext}}}'
|
|
1659
1666
|
# escape filepath for includegraphics, https://tex.stackexchange.com/a/202714/41112
|
|
1660
|
-
if '#' in base:
|
|
1661
|
-
cmd =
|
|
1667
|
+
if '#' in str(base):
|
|
1668
|
+
cmd = rf'{{\catcode`\#=12{cmd}}}'
|
|
1662
1669
|
self.body.append(cmd)
|
|
1663
1670
|
self.body.extend(post)
|
|
1664
1671
|
|
|
@@ -1684,7 +1691,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1684
1691
|
if any(isinstance(child, nodes.caption) for child in node):
|
|
1685
1692
|
self.body.append(r'\capstart')
|
|
1686
1693
|
self.context.append(r'\end{sphinxfigure-in-table}\relax' + CR)
|
|
1687
|
-
elif node.get('align', '') in
|
|
1694
|
+
elif node.get('align', '') in {'left', 'right'}:
|
|
1688
1695
|
length = None
|
|
1689
1696
|
if 'width' in node:
|
|
1690
1697
|
length = self.latex_image_length(node['width'])
|
|
@@ -1816,7 +1823,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1816
1823
|
while isinstance(next_node, nodes.target):
|
|
1817
1824
|
next_node = next_node.next_node(ascend=True)
|
|
1818
1825
|
|
|
1819
|
-
domain = self.
|
|
1826
|
+
domain = self._domains.standard_domain
|
|
1820
1827
|
if isinstance(next_node, HYPERLINK_SUPPORT_NODES):
|
|
1821
1828
|
return
|
|
1822
1829
|
if (
|
|
@@ -1840,7 +1847,8 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
1840
1847
|
else:
|
|
1841
1848
|
add_target(node['refid'])
|
|
1842
1849
|
# Temporary fix for https://github.com/sphinx-doc/sphinx/issues/11093
|
|
1843
|
-
# TODO: investigate if a more elegant solution exists
|
|
1850
|
+
# TODO: investigate if a more elegant solution exists
|
|
1851
|
+
# (see comments of https://github.com/sphinx-doc/sphinx/issues/11093)
|
|
1844
1852
|
if node.get('ismod', False):
|
|
1845
1853
|
# Detect if the previous nodes are label targets. If so, remove
|
|
1846
1854
|
# the refid thereof from node['ids'] to avoid duplicated ids.
|
|
@@ -2061,17 +2069,25 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
2061
2069
|
self.body.append('}')
|
|
2062
2070
|
|
|
2063
2071
|
def visit_literal_strong(self, node: Element) -> None:
|
|
2072
|
+
if self.in_production_list:
|
|
2073
|
+
ctx = [r'\phantomsection']
|
|
2074
|
+
ctx += [self.hypertarget(id_, anchor=False) for id_ in node['ids']]
|
|
2075
|
+
self.body.append(''.join(ctx))
|
|
2076
|
+
return
|
|
2064
2077
|
self.body.append(r'\sphinxstyleliteralstrong{\sphinxupquote{')
|
|
2065
2078
|
|
|
2066
2079
|
def depart_literal_strong(self, node: Element) -> None:
|
|
2080
|
+
if self.in_production_list:
|
|
2081
|
+
return
|
|
2067
2082
|
self.body.append('}}')
|
|
2068
2083
|
|
|
2069
2084
|
def visit_abbreviation(self, node: Element) -> None:
|
|
2085
|
+
explanation = node.get('explanation', '')
|
|
2070
2086
|
abbr = node.astext()
|
|
2071
2087
|
self.body.append(r'\sphinxstyleabbreviation{')
|
|
2072
2088
|
# spell out the explanation once
|
|
2073
|
-
if
|
|
2074
|
-
self.context.append('} (%s)' % self.encode(
|
|
2089
|
+
if explanation and abbr not in self.handled_abbrs:
|
|
2090
|
+
self.context.append('} (%s)' % self.encode(explanation))
|
|
2075
2091
|
self.handled_abbrs.add(abbr)
|
|
2076
2092
|
else:
|
|
2077
2093
|
self.context.append('}')
|
|
@@ -2092,8 +2108,8 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
2092
2108
|
self.body.append('}')
|
|
2093
2109
|
|
|
2094
2110
|
def visit_thebibliography(self, node: Element) -> None:
|
|
2095
|
-
citations = cast(Iterable[nodes.citation], node)
|
|
2096
|
-
labels = (cast(nodes.label, citation[0]) for citation in citations)
|
|
2111
|
+
citations = cast('Iterable[nodes.citation]', node)
|
|
2112
|
+
labels = (cast('nodes.label', citation[0]) for citation in citations)
|
|
2097
2113
|
longest_label = max((label.astext() for label in labels), key=len)
|
|
2098
2114
|
if len(longest_label) > MAX_CITATION_LABEL_LENGTH:
|
|
2099
2115
|
# adjust max width of citation labels not to break the layout
|
|
@@ -2107,7 +2123,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
2107
2123
|
self.body.append(r'\end{sphinxthebibliography}' + CR)
|
|
2108
2124
|
|
|
2109
2125
|
def visit_citation(self, node: Element) -> None:
|
|
2110
|
-
label = cast(nodes.label, node[0])
|
|
2126
|
+
label = cast('nodes.label', node[0])
|
|
2111
2127
|
self.body.append(
|
|
2112
2128
|
rf'\bibitem[{self.encode(label.astext())}]'
|
|
2113
2129
|
rf'{{{node["docname"]}:{node["ids"][0]}}}'
|
|
@@ -2160,7 +2176,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
2160
2176
|
self.body.append(']')
|
|
2161
2177
|
|
|
2162
2178
|
def visit_footnotetext(self, node: Element) -> None:
|
|
2163
|
-
label = cast(nodes.label, node[0])
|
|
2179
|
+
label = cast('nodes.label', node[0])
|
|
2164
2180
|
self.body.append('%' + CR)
|
|
2165
2181
|
self.body.append(r'\begin{footnotetext}[%s]' % label.astext())
|
|
2166
2182
|
self.body.append(r'\sphinxAtStartFootnote' + CR)
|
|
@@ -2443,20 +2459,20 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
2443
2459
|
def depart_system_message(self, node: Element) -> None:
|
|
2444
2460
|
self.body.append(CR)
|
|
2445
2461
|
|
|
2446
|
-
def visit_math(self, node:
|
|
2462
|
+
def visit_math(self, node: nodes.math) -> None:
|
|
2447
2463
|
if self.in_title:
|
|
2448
2464
|
self.body.append(r'\protect\(%s\protect\)' % node.astext())
|
|
2449
2465
|
else:
|
|
2450
2466
|
self.body.append(r'\(%s\)' % node.astext())
|
|
2451
2467
|
raise nodes.SkipNode
|
|
2452
2468
|
|
|
2453
|
-
def visit_math_block(self, node:
|
|
2469
|
+
def visit_math_block(self, node: nodes.math_block) -> None:
|
|
2454
2470
|
if node.get('label'):
|
|
2455
|
-
label = f
|
|
2471
|
+
label = f'equation:{node["docname"]}:{node["label"]}'
|
|
2456
2472
|
else:
|
|
2457
2473
|
label = None
|
|
2458
2474
|
|
|
2459
|
-
if node.get('nowrap'):
|
|
2475
|
+
if node.get('no-wrap', node.get('nowrap', False)):
|
|
2460
2476
|
if label:
|
|
2461
2477
|
self.body.append(r'\label{%s}' % label)
|
|
2462
2478
|
self.body.append(node.astext())
|
|
@@ -2469,7 +2485,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
2469
2485
|
raise nodes.SkipNode
|
|
2470
2486
|
|
|
2471
2487
|
def visit_math_reference(self, node: Element) -> None:
|
|
2472
|
-
label = f
|
|
2488
|
+
label = f'equation:{node["docname"]}:{node["target"]}'
|
|
2473
2489
|
eqref_format = self.config.math_eqref_format
|
|
2474
2490
|
if eqref_format:
|
|
2475
2491
|
try:
|
|
@@ -2486,7 +2502,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|
|
2486
2502
|
|
|
2487
2503
|
|
|
2488
2504
|
# FIXME: Workaround to avoid circular import
|
|
2489
|
-
#
|
|
2505
|
+
# See: https://github.com/sphinx-doc/sphinx/issues/5433
|
|
2490
2506
|
from sphinx.builders.latex.nodes import ( # NoQA: E402 # isort:skip
|
|
2491
2507
|
HYPERLINK_SUPPORT_NODES,
|
|
2492
2508
|
captioned_literal_block,
|
sphinx/writers/manpage.py
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
from typing import TYPE_CHECKING, Any, cast
|
|
5
|
+
from typing import TYPE_CHECKING, cast
|
|
7
6
|
|
|
8
7
|
from docutils import nodes
|
|
9
8
|
from docutils.writers.manpage import Translator as BaseTranslator
|
|
@@ -17,6 +16,9 @@ from sphinx.util.i18n import format_date
|
|
|
17
16
|
from sphinx.util.nodes import NodeMatcher
|
|
18
17
|
|
|
19
18
|
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Iterable
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
20
22
|
from docutils.nodes import Element
|
|
21
23
|
|
|
22
24
|
from sphinx.builders import Builder
|
|
@@ -33,14 +35,13 @@ class ManualPageWriter(Writer): # type: ignore[misc]
|
|
|
33
35
|
transform = NestedInlineTransform(self.document)
|
|
34
36
|
transform.apply()
|
|
35
37
|
visitor = self.builder.create_translator(self.document, self.builder)
|
|
36
|
-
self.visitor = cast(ManualPageTranslator, visitor)
|
|
38
|
+
self.visitor = cast('ManualPageTranslator', visitor)
|
|
37
39
|
self.document.walkabout(visitor)
|
|
38
40
|
self.output = self.visitor.astext()
|
|
39
41
|
|
|
40
42
|
|
|
41
43
|
class NestedInlineTransform:
|
|
42
|
-
"""
|
|
43
|
-
Flatten nested inline nodes:
|
|
44
|
+
"""Flatten nested inline nodes:
|
|
44
45
|
|
|
45
46
|
Before:
|
|
46
47
|
<strong>foo=<emphasis>1</emphasis>
|
|
@@ -71,17 +72,13 @@ class NestedInlineTransform:
|
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[misc]
|
|
74
|
-
"""
|
|
75
|
-
Custom man page translator.
|
|
76
|
-
"""
|
|
75
|
+
"""Custom man page translator."""
|
|
77
76
|
|
|
78
77
|
_docinfo: dict[str, Any] = {}
|
|
79
78
|
|
|
80
79
|
def __init__(self, document: nodes.document, builder: Builder) -> None:
|
|
81
80
|
super().__init__(document, builder)
|
|
82
81
|
|
|
83
|
-
self.in_productionlist = 0
|
|
84
|
-
|
|
85
82
|
# first title is the manpage title
|
|
86
83
|
self.section_level = -1
|
|
87
84
|
|
|
@@ -117,7 +114,7 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
|
|
|
117
114
|
' "%(date)s" "%(version)s" "%(manual_group)s"\n'
|
|
118
115
|
)
|
|
119
116
|
if self._docinfo['subtitle']:
|
|
120
|
-
tmpl += '.SH NAME\n
|
|
117
|
+
tmpl += '.SH NAME\n%(title)s \\- %(subtitle)s\n'
|
|
121
118
|
return tmpl % self._docinfo
|
|
122
119
|
|
|
123
120
|
def visit_start_of_file(self, node: Element) -> None:
|
|
@@ -259,7 +256,7 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
|
|
|
259
256
|
# overwritten -- handle footnotes rubric
|
|
260
257
|
def visit_rubric(self, node: Element) -> None:
|
|
261
258
|
self.ensure_eol()
|
|
262
|
-
if len(node) == 1 and node.astext() in
|
|
259
|
+
if len(node) == 1 and node.astext() in {'Footnotes', _('Footnotes')}:
|
|
263
260
|
self.body.append('.SH ' + self.deunicode(node.astext()).upper() + '\n')
|
|
264
261
|
raise nodes.SkipNode
|
|
265
262
|
self.body.append('.sp\n')
|
|
@@ -275,26 +272,10 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
|
|
|
275
272
|
|
|
276
273
|
def visit_productionlist(self, node: Element) -> None:
|
|
277
274
|
self.ensure_eol()
|
|
278
|
-
self.in_productionlist += 1
|
|
279
275
|
self.body.append('.sp\n.nf\n')
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
maxlen = max(len(name) for name in names)
|
|
283
|
-
lastname = None
|
|
284
|
-
for production in productionlist:
|
|
285
|
-
if production['tokenname']:
|
|
286
|
-
lastname = production['tokenname'].ljust(maxlen)
|
|
287
|
-
self.body.append(self.defs['strong'][0])
|
|
288
|
-
self.body.append(self.deunicode(lastname))
|
|
289
|
-
self.body.append(self.defs['strong'][1])
|
|
290
|
-
self.body.append(' ::= ')
|
|
291
|
-
elif lastname is not None:
|
|
292
|
-
self.body.append('%s ' % (' ' * len(lastname)))
|
|
293
|
-
production.walkabout(self)
|
|
294
|
-
self.body.append('\n')
|
|
276
|
+
|
|
277
|
+
def depart_productionlist(self, node: Element) -> None:
|
|
295
278
|
self.body.append('\n.fi\n')
|
|
296
|
-
self.in_productionlist -= 1
|
|
297
|
-
raise nodes.SkipNode
|
|
298
279
|
|
|
299
280
|
def visit_production(self, node: Element) -> None:
|
|
300
281
|
pass
|
|
@@ -379,11 +360,11 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
|
|
|
379
360
|
pass
|
|
380
361
|
|
|
381
362
|
def visit_acks(self, node: Element) -> None:
|
|
382
|
-
bullet_list = cast(nodes.bullet_list, node[0])
|
|
383
|
-
list_items = cast(Iterable[nodes.list_item], bullet_list)
|
|
363
|
+
bullet_list = cast('nodes.bullet_list', node[0])
|
|
364
|
+
list_items = cast('Iterable[nodes.list_item]', bullet_list)
|
|
384
365
|
self.ensure_eol()
|
|
385
|
-
bullet_list = cast(nodes.bullet_list, node[0])
|
|
386
|
-
list_items = cast(Iterable[nodes.list_item], bullet_list)
|
|
366
|
+
bullet_list = cast('nodes.bullet_list', node[0])
|
|
367
|
+
list_items = cast('Iterable[nodes.list_item]', bullet_list)
|
|
387
368
|
self.body.append(', '.join(n.astext() for n in list_items) + '.')
|
|
388
369
|
self.body.append('\n')
|
|
389
370
|
raise nodes.SkipNode
|
|
@@ -477,14 +458,14 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): # type: ignore[mi
|
|
|
477
458
|
def depart_inline(self, node: Element) -> None:
|
|
478
459
|
pass
|
|
479
460
|
|
|
480
|
-
def visit_math(self, node:
|
|
461
|
+
def visit_math(self, node: nodes.math) -> None:
|
|
481
462
|
pass
|
|
482
463
|
|
|
483
|
-
def depart_math(self, node:
|
|
464
|
+
def depart_math(self, node: nodes.math) -> None:
|
|
484
465
|
pass
|
|
485
466
|
|
|
486
|
-
def visit_math_block(self, node:
|
|
467
|
+
def visit_math_block(self, node: nodes.math_block) -> None:
|
|
487
468
|
self.visit_centered(node)
|
|
488
469
|
|
|
489
|
-
def depart_math_block(self, node:
|
|
470
|
+
def depart_math_block(self, node: nodes.math_block) -> None:
|
|
490
471
|
self.depart_centered(node)
|