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/builders/_epub_base.py
CHANGED
|
@@ -4,10 +4,11 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import html
|
|
6
6
|
import os
|
|
7
|
+
import os.path
|
|
7
8
|
import re
|
|
8
9
|
import time
|
|
9
|
-
from
|
|
10
|
-
from typing import TYPE_CHECKING,
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import TYPE_CHECKING, NamedTuple
|
|
11
12
|
from urllib.parse import quote
|
|
12
13
|
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
|
|
13
14
|
|
|
@@ -19,11 +20,14 @@ from sphinx.builders.html import StandaloneHTMLBuilder
|
|
|
19
20
|
from sphinx.builders.html._build_info import BuildInfo
|
|
20
21
|
from sphinx.locale import __
|
|
21
22
|
from sphinx.util import logging
|
|
23
|
+
from sphinx.util._pathlib import _StrPath
|
|
22
24
|
from sphinx.util.display import status_iterator
|
|
23
25
|
from sphinx.util.fileutil import copy_asset_file
|
|
24
26
|
from sphinx.util.osutil import copyfile, ensuredir, relpath
|
|
25
27
|
|
|
26
28
|
if TYPE_CHECKING:
|
|
29
|
+
from typing import Any
|
|
30
|
+
|
|
27
31
|
from docutils.nodes import Element, Node
|
|
28
32
|
|
|
29
33
|
try:
|
|
@@ -123,8 +127,7 @@ ssp = sphinx_smarty_pants
|
|
|
123
127
|
|
|
124
128
|
|
|
125
129
|
class EpubBuilder(StandaloneHTMLBuilder):
|
|
126
|
-
"""
|
|
127
|
-
Builder that outputs epub files.
|
|
130
|
+
"""Builder that outputs epub files.
|
|
128
131
|
|
|
129
132
|
It creates the metainfo files container.opf, toc.ncx, mimetype, and
|
|
130
133
|
META-INF/container.xml. Afterwards, all necessary files are zipped to an
|
|
@@ -156,7 +159,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
156
159
|
guide_titles = GUIDE_TITLES
|
|
157
160
|
media_types = MEDIA_TYPES
|
|
158
161
|
refuri_re = REFURI_RE
|
|
159
|
-
template_dir =
|
|
162
|
+
template_dir: _StrPath = _StrPath()
|
|
160
163
|
doctype = ''
|
|
161
164
|
|
|
162
165
|
def init(self) -> None:
|
|
@@ -226,18 +229,16 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
226
229
|
appeared.add(node['refuri'])
|
|
227
230
|
|
|
228
231
|
def get_toc(self) -> None:
|
|
229
|
-
"""Get the total table of contents, containing the
|
|
230
|
-
and pre and post files not managed by
|
|
232
|
+
"""Get the total table of contents, containing the master_doc
|
|
233
|
+
and pre and post files not managed by Sphinx.
|
|
231
234
|
"""
|
|
232
235
|
doctree = self.env.get_and_resolve_doctree(
|
|
233
|
-
self.config.
|
|
236
|
+
self.config.master_doc, self, prune_toctrees=False, includehidden=True
|
|
234
237
|
)
|
|
235
238
|
self.refnodes = self.get_refnodes(doctree, [])
|
|
236
|
-
master_dir =
|
|
237
|
-
|
|
238
|
-
master_dir
|
|
239
|
-
for item in self.refnodes:
|
|
240
|
-
item['refuri'] = master_dir + item['refuri']
|
|
239
|
+
master_dir = Path(self.config.master_doc).parent
|
|
240
|
+
for item in self.refnodes:
|
|
241
|
+
item['refuri'] = str(master_dir / item['refuri'])
|
|
241
242
|
self.toc_add_files(self.refnodes)
|
|
242
243
|
|
|
243
244
|
def toc_add_files(self, refnodes: list[dict[str, Any]]) -> None:
|
|
@@ -407,7 +408,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
407
408
|
|
|
408
409
|
def is_vector_graphics(self, filename: str) -> bool:
|
|
409
410
|
"""Does the filename extension indicate a vector graphic format?"""
|
|
410
|
-
ext = path.splitext(filename)[-1]
|
|
411
|
+
ext = os.path.splitext(filename)[-1]
|
|
411
412
|
return ext in VECTOR_GRAPHICS_EXTENSIONS
|
|
412
413
|
|
|
413
414
|
def copy_image_files_pil(self) -> None:
|
|
@@ -415,7 +416,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
415
416
|
The method tries to read and write the files with Pillow, converting
|
|
416
417
|
the format and resizing the image if necessary/possible.
|
|
417
418
|
"""
|
|
418
|
-
ensuredir(
|
|
419
|
+
ensuredir(self.outdir / self.imagedir)
|
|
419
420
|
for src in status_iterator(
|
|
420
421
|
self.images,
|
|
421
422
|
__('copying images... '),
|
|
@@ -425,12 +426,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
425
426
|
):
|
|
426
427
|
dest = self.images[src]
|
|
427
428
|
try:
|
|
428
|
-
img = Image.open(
|
|
429
|
+
img = Image.open(self.srcdir / src)
|
|
429
430
|
except OSError:
|
|
430
431
|
if not self.is_vector_graphics(src):
|
|
431
432
|
logger.warning(
|
|
432
433
|
__('cannot read image file %r: copying it instead'),
|
|
433
|
-
|
|
434
|
+
self.srcdir / src,
|
|
434
435
|
)
|
|
435
436
|
try:
|
|
436
437
|
copyfile(
|
|
@@ -441,7 +442,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
441
442
|
except OSError as err:
|
|
442
443
|
logger.warning(
|
|
443
444
|
__('cannot copy image file %r: %s'),
|
|
444
|
-
|
|
445
|
+
self.srcdir / src,
|
|
445
446
|
err,
|
|
446
447
|
)
|
|
447
448
|
continue
|
|
@@ -457,11 +458,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
457
458
|
nh = round((height * nw) / width)
|
|
458
459
|
img = img.resize((nw, nh), Image.BICUBIC)
|
|
459
460
|
try:
|
|
460
|
-
img.save(
|
|
461
|
+
img.save(self.outdir / self.imagedir / dest)
|
|
461
462
|
except OSError as err:
|
|
462
463
|
logger.warning(
|
|
463
464
|
__('cannot write image file %r: %s'),
|
|
464
|
-
|
|
465
|
+
self.srcdir / src,
|
|
465
466
|
err,
|
|
466
467
|
)
|
|
467
468
|
|
|
@@ -487,7 +488,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
487
488
|
pagename: str,
|
|
488
489
|
addctx: dict[str, Any],
|
|
489
490
|
templatename: str = 'page.html',
|
|
490
|
-
|
|
491
|
+
*,
|
|
492
|
+
outfilename: Path | None = None,
|
|
491
493
|
event_arg: Any = None,
|
|
492
494
|
) -> None:
|
|
493
495
|
"""Create a rendered page.
|
|
@@ -500,13 +502,15 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
500
502
|
return
|
|
501
503
|
self.fix_genindex(addctx['genindexentries'])
|
|
502
504
|
addctx['doctype'] = self.doctype
|
|
503
|
-
super().handle_page(
|
|
505
|
+
super().handle_page(
|
|
506
|
+
pagename, addctx, templatename, outfilename=outfilename, event_arg=event_arg
|
|
507
|
+
)
|
|
504
508
|
|
|
505
509
|
def build_mimetype(self) -> None:
|
|
506
510
|
"""Write the metainfo file mimetype."""
|
|
507
511
|
logger.info(__('writing mimetype file...'))
|
|
508
512
|
copyfile(
|
|
509
|
-
|
|
513
|
+
self.template_dir / 'mimetype',
|
|
510
514
|
self.outdir / 'mimetype',
|
|
511
515
|
force=True,
|
|
512
516
|
)
|
|
@@ -517,7 +521,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
517
521
|
outdir = self.outdir / 'META-INF'
|
|
518
522
|
ensuredir(outdir)
|
|
519
523
|
copyfile(
|
|
520
|
-
|
|
524
|
+
self.template_dir / 'container.xml',
|
|
521
525
|
outdir / 'container.xml',
|
|
522
526
|
force=True,
|
|
523
527
|
)
|
|
@@ -531,19 +535,20 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
531
535
|
else:
|
|
532
536
|
time_tuple = time.gmtime()
|
|
533
537
|
|
|
534
|
-
metadata: dict[str, Any] = {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
538
|
+
metadata: dict[str, Any] = {
|
|
539
|
+
'title': html.escape(self.config.epub_title),
|
|
540
|
+
'author': html.escape(self.config.epub_author),
|
|
541
|
+
'uid': html.escape(self.config.epub_uid),
|
|
542
|
+
'lang': html.escape(self.config.epub_language),
|
|
543
|
+
'publisher': html.escape(self.config.epub_publisher),
|
|
544
|
+
'copyright': html.escape(self.config.epub_copyright),
|
|
545
|
+
'scheme': html.escape(self.config.epub_scheme),
|
|
546
|
+
'id': html.escape(self.config.epub_identifier),
|
|
547
|
+
'date': html.escape(time.strftime('%Y-%m-%d', time_tuple)),
|
|
548
|
+
'manifest_items': [],
|
|
549
|
+
'spines': [],
|
|
550
|
+
'guides': [],
|
|
551
|
+
}
|
|
547
552
|
return metadata
|
|
548
553
|
|
|
549
554
|
def build_content(self) -> None:
|
|
@@ -571,16 +576,17 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
571
576
|
if not self.use_index:
|
|
572
577
|
self.ignored_files.append('genindex' + self.out_suffix)
|
|
573
578
|
for root, dirs, files in os.walk(self.outdir):
|
|
579
|
+
root_path = Path(root)
|
|
574
580
|
dirs.sort()
|
|
575
581
|
for fn in sorted(files):
|
|
576
|
-
filename = relpath(
|
|
582
|
+
filename = relpath(root_path / fn, self.outdir)
|
|
577
583
|
if filename in self.ignored_files:
|
|
578
584
|
continue
|
|
579
|
-
ext = path.splitext(filename)[-1]
|
|
585
|
+
ext = os.path.splitext(filename)[-1]
|
|
580
586
|
if ext not in self.media_types:
|
|
581
587
|
# we always have JS and potentially OpenSearch files, don't
|
|
582
588
|
# always warn about them
|
|
583
|
-
if ext not in
|
|
589
|
+
if ext not in {'.js', '.xml'}:
|
|
584
590
|
logger.warning(
|
|
585
591
|
__('unknown mimetype for %s, ignoring'),
|
|
586
592
|
filename,
|
|
@@ -631,7 +637,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
631
637
|
spine = Spine(html.escape(self.make_id(self.coverpage_name)), True)
|
|
632
638
|
metadata['spines'].insert(0, spine)
|
|
633
639
|
if self.coverpage_name not in self.files:
|
|
634
|
-
ext = path.splitext(self.coverpage_name)[-1]
|
|
640
|
+
ext = os.path.splitext(self.coverpage_name)[-1]
|
|
635
641
|
self.files.append(self.coverpage_name)
|
|
636
642
|
item = ManifestItem(
|
|
637
643
|
html.escape(self.coverpage_name),
|
|
@@ -640,7 +646,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
640
646
|
)
|
|
641
647
|
metadata['manifest_items'].append(item)
|
|
642
648
|
ctx = {'image': html.escape(image), 'title': self.config.project}
|
|
643
|
-
self.handle_page(
|
|
649
|
+
self.handle_page(
|
|
650
|
+
os.path.splitext(self.coverpage_name)[0], ctx, html_tmpl
|
|
651
|
+
)
|
|
644
652
|
spinefiles.add(self.coverpage_name)
|
|
645
653
|
|
|
646
654
|
auto_add_cover = True
|
|
@@ -676,7 +684,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
676
684
|
|
|
677
685
|
# write the project file
|
|
678
686
|
copy_asset_file(
|
|
679
|
-
|
|
687
|
+
self.template_dir / 'content.opf.jinja',
|
|
680
688
|
self.outdir,
|
|
681
689
|
context=metadata,
|
|
682
690
|
force=True,
|
|
@@ -700,8 +708,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
700
708
|
Subelements of a node are nested inside the navpoint. For nested nodes
|
|
701
709
|
the parent node is reinserted in the subnav.
|
|
702
710
|
"""
|
|
703
|
-
navstack: list[NavPoint] = []
|
|
704
|
-
navstack.append(NavPoint('dummy', 0, '', '', []))
|
|
711
|
+
navstack: list[NavPoint] = [NavPoint('dummy', 0, '', '', [])]
|
|
705
712
|
level = 0
|
|
706
713
|
lastnode = None
|
|
707
714
|
for node in nodes:
|
|
@@ -735,7 +742,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
735
742
|
navstack[-1].children.append(navpoint)
|
|
736
743
|
navstack.append(navpoint)
|
|
737
744
|
else:
|
|
738
|
-
|
|
745
|
+
msg = __('node has an invalid level')
|
|
746
|
+
raise ValueError(msg)
|
|
739
747
|
lastnode = node
|
|
740
748
|
|
|
741
749
|
return navstack[0].children
|
|
@@ -744,11 +752,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
744
752
|
"""Create a dictionary with all metadata for the toc.ncx file
|
|
745
753
|
properly escaped.
|
|
746
754
|
"""
|
|
747
|
-
metadata: dict[str, Any] = {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
755
|
+
metadata: dict[str, Any] = {
|
|
756
|
+
'uid': self.config.epub_uid,
|
|
757
|
+
'title': html.escape(self.config.epub_title),
|
|
758
|
+
'level': level,
|
|
759
|
+
'navpoints': navpoints,
|
|
760
|
+
}
|
|
752
761
|
return metadata
|
|
753
762
|
|
|
754
763
|
def build_toc(self) -> None:
|
|
@@ -769,7 +778,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
769
778
|
level = max(item['level'] for item in self.refnodes)
|
|
770
779
|
level = min(level, self.config.epub_tocdepth)
|
|
771
780
|
copy_asset_file(
|
|
772
|
-
|
|
781
|
+
self.template_dir / 'toc.ncx.jinja',
|
|
773
782
|
self.outdir,
|
|
774
783
|
context=self.toc_metadata(level, navpoints),
|
|
775
784
|
force=True,
|
|
@@ -783,10 +792,10 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
783
792
|
"""
|
|
784
793
|
outname = self.config.epub_basename + '.epub'
|
|
785
794
|
logger.info(__('writing %s file...'), outname)
|
|
786
|
-
epub_filename =
|
|
795
|
+
epub_filename = self.outdir / outname
|
|
787
796
|
with ZipFile(epub_filename, 'w', ZIP_DEFLATED) as epub:
|
|
788
|
-
epub.write(
|
|
797
|
+
epub.write(self.outdir / 'mimetype', 'mimetype', ZIP_STORED)
|
|
789
798
|
for filename in ('META-INF/container.xml', 'content.opf', 'toc.ncx'):
|
|
790
|
-
epub.write(
|
|
799
|
+
epub.write(self.outdir / filename, filename, ZIP_DEFLATED)
|
|
791
800
|
for filename in self.files:
|
|
792
|
-
epub.write(
|
|
801
|
+
epub.write(self.outdir / filename, filename, ZIP_DEFLATED)
|
sphinx/builders/changes.py
CHANGED
|
@@ -3,17 +3,15 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import html
|
|
6
|
-
from os import path
|
|
7
6
|
from typing import TYPE_CHECKING
|
|
8
7
|
|
|
9
8
|
from sphinx import package_dir
|
|
9
|
+
from sphinx._cli.util.colour import bold
|
|
10
10
|
from sphinx.builders import Builder
|
|
11
11
|
from sphinx.locale import _, __
|
|
12
12
|
from sphinx.theming import HTMLThemeFactory
|
|
13
13
|
from sphinx.util import logging
|
|
14
|
-
from sphinx.util.console import bold
|
|
15
14
|
from sphinx.util.fileutil import copy_asset_file
|
|
16
|
-
from sphinx.util.osutil import ensuredir, os_path
|
|
17
15
|
|
|
18
16
|
if TYPE_CHECKING:
|
|
19
17
|
from collections.abc import Set
|
|
@@ -25,9 +23,7 @@ logger = logging.getLogger(__name__)
|
|
|
25
23
|
|
|
26
24
|
|
|
27
25
|
class ChangesBuilder(Builder):
|
|
28
|
-
"""
|
|
29
|
-
Write a summary with all versionadded/changed/deprecated/removed directives.
|
|
30
|
-
"""
|
|
26
|
+
"""Write a summary with all versionadded/changed/deprecated/removed directives."""
|
|
31
27
|
|
|
32
28
|
name = 'changes'
|
|
33
29
|
epilog = __('The overview file is in %(outdir)s.')
|
|
@@ -61,10 +57,7 @@ class ChangesBuilder(Builder):
|
|
|
61
57
|
return
|
|
62
58
|
logger.info(bold(__('writing summary file...')))
|
|
63
59
|
for changeset in changesets:
|
|
64
|
-
|
|
65
|
-
descname = changeset.descname[0]
|
|
66
|
-
else:
|
|
67
|
-
descname = changeset.descname
|
|
60
|
+
descname = changeset.descname
|
|
68
61
|
ttext = self.typemap[changeset.type]
|
|
69
62
|
context = changeset.content.replace('\n', ' ')
|
|
70
63
|
if descname and changeset.docname.startswith('c-api'):
|
|
@@ -108,9 +101,9 @@ class ChangesBuilder(Builder):
|
|
|
108
101
|
'show_copyright': self.config.html_show_copyright,
|
|
109
102
|
'show_sphinx': self.config.html_show_sphinx,
|
|
110
103
|
}
|
|
111
|
-
with open(
|
|
104
|
+
with open(self.outdir / 'index.html', 'w', encoding='utf8') as f:
|
|
112
105
|
f.write(self.templates.render('changes/frameset.html', ctx))
|
|
113
|
-
with open(
|
|
106
|
+
with open(self.outdir / 'changes.html', 'w', encoding='utf8') as f:
|
|
114
107
|
f.write(self.templates.render('changes/versionchanges.html', ctx))
|
|
115
108
|
|
|
116
109
|
hltext = [
|
|
@@ -131,7 +124,7 @@ class ChangesBuilder(Builder):
|
|
|
131
124
|
logger.info(bold(__('copying source files...')))
|
|
132
125
|
for docname in self.env.all_docs:
|
|
133
126
|
with open(
|
|
134
|
-
self.env.doc2path(docname), encoding=self.
|
|
127
|
+
self.env.doc2path(docname), encoding=self.config.source_encoding
|
|
135
128
|
) as f:
|
|
136
129
|
try:
|
|
137
130
|
lines = f.readlines()
|
|
@@ -140,27 +133,28 @@ class ChangesBuilder(Builder):
|
|
|
140
133
|
__('could not read %r for changelog creation'), docname
|
|
141
134
|
)
|
|
142
135
|
continue
|
|
143
|
-
|
|
144
|
-
|
|
136
|
+
text = ''.join(hl(i + 1, line) for (i, line) in enumerate(lines))
|
|
137
|
+
ctx = {
|
|
138
|
+
'filename': str(self.env.doc2path(docname, False)),
|
|
139
|
+
'text': text,
|
|
140
|
+
}
|
|
141
|
+
rendered = self.templates.render('changes/rstsource.html', ctx)
|
|
142
|
+
targetfn = self.outdir / 'rst' / f'{docname}.html'
|
|
143
|
+
targetfn.parent.mkdir(parents=True, exist_ok=True)
|
|
145
144
|
with open(targetfn, 'w', encoding='utf-8') as f:
|
|
146
|
-
|
|
147
|
-
ctx = {
|
|
148
|
-
'filename': str(self.env.doc2path(docname, False)),
|
|
149
|
-
'text': text,
|
|
150
|
-
}
|
|
151
|
-
f.write(self.templates.render('changes/rstsource.html', ctx))
|
|
145
|
+
f.write(rendered)
|
|
152
146
|
themectx = {
|
|
153
147
|
'theme_' + key: val for (key, val) in self.theme.get_options({}).items()
|
|
154
148
|
}
|
|
155
149
|
copy_asset_file(
|
|
156
|
-
|
|
150
|
+
package_dir.joinpath('themes', 'default', 'static', 'default.css.jinja'),
|
|
157
151
|
self.outdir,
|
|
158
152
|
context=themectx,
|
|
159
153
|
renderer=self.templates,
|
|
160
154
|
force=True,
|
|
161
155
|
)
|
|
162
156
|
copy_asset_file(
|
|
163
|
-
|
|
157
|
+
package_dir.joinpath('themes', 'basic', 'static', 'basic.css'),
|
|
164
158
|
self.outdir / 'basic.css',
|
|
165
159
|
force=True,
|
|
166
160
|
)
|
sphinx/builders/dirhtml.py
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from pathlib import Path
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
8
|
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
9
9
|
from sphinx.util import logging
|
|
10
|
-
from sphinx.util.osutil import SEP
|
|
10
|
+
from sphinx.util.osutil import SEP
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
13
|
from sphinx.application import Sphinx
|
|
@@ -17,8 +17,7 @@ logger = logging.getLogger(__name__)
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
|
|
20
|
-
"""
|
|
21
|
-
A StandaloneHTMLBuilder that creates all HTML pages as "index.html" in
|
|
20
|
+
"""A StandaloneHTMLBuilder that creates all HTML pages as "index.html" in
|
|
22
21
|
a directory given by their pagename, so that generated URLs don't have
|
|
23
22
|
``.html`` in them.
|
|
24
23
|
"""
|
|
@@ -32,15 +31,11 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
|
|
|
32
31
|
return docname[:-5] # up to sep
|
|
33
32
|
return docname + SEP
|
|
34
33
|
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
self.outdir, os_path(pagename), 'index' + self.out_suffix
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
return outfilename
|
|
34
|
+
def get_output_path(self, page_name: str, /) -> Path:
|
|
35
|
+
page_parts = page_name.split(SEP)
|
|
36
|
+
if page_parts[-1] == 'index':
|
|
37
|
+
page_parts.pop()
|
|
38
|
+
return Path(self.outdir, *page_parts, f'index{self.out_suffix}')
|
|
44
39
|
|
|
45
40
|
|
|
46
41
|
def setup(app: Sphinx) -> ExtensionMetadata:
|
sphinx/builders/epub3.py
CHANGED
|
@@ -7,14 +7,14 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
import html
|
|
9
9
|
import os
|
|
10
|
+
import os.path
|
|
10
11
|
import re
|
|
11
12
|
import time
|
|
12
|
-
from
|
|
13
|
-
from typing import TYPE_CHECKING, Any, NamedTuple
|
|
13
|
+
from typing import TYPE_CHECKING, NamedTuple
|
|
14
14
|
|
|
15
15
|
from sphinx import package_dir
|
|
16
16
|
from sphinx.builders import _epub_base
|
|
17
|
-
from sphinx.config import ENUM
|
|
17
|
+
from sphinx.config import ENUM
|
|
18
18
|
from sphinx.locale import __
|
|
19
19
|
from sphinx.util import logging
|
|
20
20
|
from sphinx.util.fileutil import copy_asset_file
|
|
@@ -22,8 +22,10 @@ from sphinx.util.osutil import make_filename
|
|
|
22
22
|
|
|
23
23
|
if TYPE_CHECKING:
|
|
24
24
|
from collections.abc import Set
|
|
25
|
+
from typing import Any
|
|
25
26
|
|
|
26
27
|
from sphinx.application import Sphinx
|
|
28
|
+
from sphinx.config import Config
|
|
27
29
|
from sphinx.util.typing import ExtensionMetadata
|
|
28
30
|
|
|
29
31
|
logger = logging.getLogger(__name__)
|
|
@@ -65,14 +67,13 @@ _xml_name_start_char = (
|
|
|
65
67
|
'|[\ufdf0-\ufffd]|[\U00010000-\U000effff]'
|
|
66
68
|
)
|
|
67
69
|
_xml_name_char = (
|
|
68
|
-
_xml_name_start_char + r'
|
|
70
|
+
_xml_name_start_char + r'\-|\.|[0-9]|\u00b7|[\u0300-\u036f]|[\u203f-\u2040]'
|
|
69
71
|
)
|
|
70
72
|
_XML_NAME_PATTERN = re.compile(f'({_xml_name_start_char})({_xml_name_char})*')
|
|
71
73
|
|
|
72
74
|
|
|
73
75
|
class Epub3Builder(_epub_base.EpubBuilder):
|
|
74
|
-
"""
|
|
75
|
-
Builder that outputs epub3 files.
|
|
76
|
+
"""Builder that outputs epub3 files.
|
|
76
77
|
|
|
77
78
|
It creates the metainfo files content.opf, nav.xhtml, toc.ncx, mimetype,
|
|
78
79
|
and META-INF/container.xml. Afterwards, all necessary files are zipped to
|
|
@@ -83,7 +84,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
|
|
83
84
|
epilog = __('The ePub file is in %(outdir)s.')
|
|
84
85
|
|
|
85
86
|
supported_remote_images = False
|
|
86
|
-
template_dir =
|
|
87
|
+
template_dir = package_dir.joinpath('templates', 'epub3')
|
|
87
88
|
doctype = DOCTYPE
|
|
88
89
|
html_tag = HTML_TAG
|
|
89
90
|
use_meta_charset = True
|
|
@@ -141,8 +142,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
|
|
141
142
|
The difference from build_navpoints method is templates which are used
|
|
142
143
|
when generating navigation documents.
|
|
143
144
|
"""
|
|
144
|
-
navstack: list[NavPoint] = []
|
|
145
|
-
navstack.append(NavPoint('', '', []))
|
|
145
|
+
navstack: list[NavPoint] = [NavPoint('', '', [])]
|
|
146
146
|
level = 0
|
|
147
147
|
for node in navnodes:
|
|
148
148
|
if not node['text']:
|
|
@@ -199,7 +199,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
|
|
199
199
|
refnodes = self.refnodes
|
|
200
200
|
navlist = self.build_navlist(refnodes)
|
|
201
201
|
copy_asset_file(
|
|
202
|
-
|
|
202
|
+
self.template_dir / 'nav.xhtml.jinja',
|
|
203
203
|
self.outdir,
|
|
204
204
|
context=self.navigation_doc_metadata(navlist),
|
|
205
205
|
force=True,
|
|
@@ -286,35 +286,67 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|
|
286
286
|
app.add_builder(Epub3Builder)
|
|
287
287
|
|
|
288
288
|
# config values
|
|
289
|
-
app.add_config_value('epub_basename', lambda self: make_filename(self.project), '')
|
|
290
|
-
app.add_config_value('epub_version', 3.0, 'epub') # experimental
|
|
291
|
-
app.add_config_value('epub_theme', 'epub', 'epub')
|
|
292
|
-
app.add_config_value('epub_theme_options', {}, 'epub')
|
|
293
|
-
app.add_config_value('epub_title', lambda self: self.project, 'epub')
|
|
294
|
-
app.add_config_value('epub_author', lambda self: self.author, 'epub')
|
|
295
|
-
app.add_config_value('epub_language', lambda self: self.language or 'en', 'epub')
|
|
296
|
-
app.add_config_value('epub_publisher', lambda self: self.author, 'epub')
|
|
297
|
-
app.add_config_value('epub_copyright', lambda self: self.copyright, 'epub')
|
|
298
|
-
app.add_config_value('epub_identifier', 'unknown', 'epub')
|
|
299
|
-
app.add_config_value('epub_scheme', 'unknown', 'epub')
|
|
300
|
-
app.add_config_value('epub_uid', 'unknown', 'env')
|
|
301
|
-
app.add_config_value('epub_cover', (), 'env')
|
|
302
|
-
app.add_config_value('epub_guide', (), 'env')
|
|
303
|
-
app.add_config_value('epub_pre_files', [], 'env')
|
|
304
|
-
app.add_config_value('epub_post_files', [], 'env')
|
|
305
|
-
app.add_config_value('epub_css_files', lambda config: config.html_css_files, 'epub')
|
|
306
|
-
app.add_config_value('epub_exclude_files', [], 'env')
|
|
307
|
-
app.add_config_value('epub_tocdepth', 3, 'env')
|
|
308
|
-
app.add_config_value('epub_tocdup', True, 'env')
|
|
309
|
-
app.add_config_value('epub_tocscope', 'default', 'env')
|
|
310
|
-
app.add_config_value('epub_fix_images', False, 'env')
|
|
311
|
-
app.add_config_value('epub_max_image_width', 0, 'env')
|
|
312
|
-
app.add_config_value('epub_show_urls', 'inline', 'epub')
|
|
313
|
-
app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'epub')
|
|
314
|
-
app.add_config_value('epub_description', 'unknown', 'epub')
|
|
315
|
-
app.add_config_value('epub_contributor', 'unknown', 'epub')
|
|
316
289
|
app.add_config_value(
|
|
317
|
-
'
|
|
290
|
+
'epub_basename',
|
|
291
|
+
lambda self: make_filename(self.project),
|
|
292
|
+
'',
|
|
293
|
+
types=frozenset({str}),
|
|
294
|
+
)
|
|
295
|
+
app.add_config_value(
|
|
296
|
+
'epub_version', 3.0, 'epub', types=frozenset({float})
|
|
297
|
+
) # experimental
|
|
298
|
+
app.add_config_value('epub_theme', 'epub', 'epub', types=frozenset({str}))
|
|
299
|
+
app.add_config_value('epub_theme_options', {}, 'epub', types=frozenset({dict}))
|
|
300
|
+
app.add_config_value(
|
|
301
|
+
'epub_title', lambda self: self.project, 'epub', types=frozenset({str})
|
|
302
|
+
)
|
|
303
|
+
app.add_config_value(
|
|
304
|
+
'epub_author', lambda self: self.author, 'epub', types=frozenset({str})
|
|
305
|
+
)
|
|
306
|
+
app.add_config_value(
|
|
307
|
+
'epub_language',
|
|
308
|
+
lambda self: self.language or 'en',
|
|
309
|
+
'epub',
|
|
310
|
+
types=frozenset({str}),
|
|
311
|
+
)
|
|
312
|
+
app.add_config_value(
|
|
313
|
+
'epub_publisher', lambda self: self.author, 'epub', types=frozenset({str})
|
|
314
|
+
)
|
|
315
|
+
app.add_config_value(
|
|
316
|
+
'epub_copyright', lambda self: self.copyright, 'epub', types=frozenset({str})
|
|
317
|
+
)
|
|
318
|
+
app.add_config_value('epub_identifier', 'unknown', 'epub', types=frozenset({str}))
|
|
319
|
+
app.add_config_value('epub_scheme', 'unknown', 'epub', types=frozenset({str}))
|
|
320
|
+
app.add_config_value('epub_uid', 'unknown', 'env', types=frozenset({str}))
|
|
321
|
+
app.add_config_value('epub_cover', (), 'env', types=frozenset({list, tuple}))
|
|
322
|
+
app.add_config_value('epub_guide', (), 'env', types=frozenset({list, tuple}))
|
|
323
|
+
app.add_config_value('epub_pre_files', [], 'env', types=frozenset({list, tuple}))
|
|
324
|
+
app.add_config_value('epub_post_files', [], 'env', types=frozenset({list, tuple}))
|
|
325
|
+
app.add_config_value(
|
|
326
|
+
'epub_css_files',
|
|
327
|
+
lambda config: config.html_css_files,
|
|
328
|
+
'epub',
|
|
329
|
+
types=frozenset({list, tuple}),
|
|
330
|
+
)
|
|
331
|
+
app.add_config_value(
|
|
332
|
+
'epub_exclude_files', [], 'env', types=frozenset({list, tuple})
|
|
333
|
+
)
|
|
334
|
+
app.add_config_value('epub_tocdepth', 3, 'env', types=frozenset({int}))
|
|
335
|
+
app.add_config_value('epub_tocdup', True, 'env', types=frozenset({bool}))
|
|
336
|
+
app.add_config_value('epub_tocscope', 'default', 'env', types=frozenset({str}))
|
|
337
|
+
app.add_config_value('epub_fix_images', False, 'env', types=frozenset({bool}))
|
|
338
|
+
app.add_config_value('epub_max_image_width', 0, 'env', types=frozenset({int}))
|
|
339
|
+
app.add_config_value('epub_show_urls', 'inline', 'epub', types=frozenset({str}))
|
|
340
|
+
app.add_config_value(
|
|
341
|
+
'epub_use_index',
|
|
342
|
+
lambda self: self.html_use_index,
|
|
343
|
+
'epub',
|
|
344
|
+
types=frozenset({bool}),
|
|
345
|
+
)
|
|
346
|
+
app.add_config_value('epub_description', 'unknown', 'epub', types=frozenset({str}))
|
|
347
|
+
app.add_config_value('epub_contributor', 'unknown', 'epub', types=frozenset({str}))
|
|
348
|
+
app.add_config_value(
|
|
349
|
+
'epub_writing_mode', 'horizontal', 'epub', types=ENUM('horizontal', 'vertical')
|
|
318
350
|
)
|
|
319
351
|
|
|
320
352
|
# event handlers
|