Sphinx 8.0.2__py3-none-any.whl → 8.1.1__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 +6 -3
- sphinx/_cli/__init__.py +40 -20
- sphinx/_cli/util/colour.py +5 -4
- sphinx/_cli/util/errors.py +28 -11
- sphinx/application.py +361 -38
- sphinx/builders/__init__.py +229 -83
- sphinx/builders/_epub_base.py +118 -71
- sphinx/builders/changes.py +39 -21
- sphinx/builders/dirhtml.py +4 -4
- sphinx/builders/dummy.py +2 -5
- sphinx/builders/epub3.py +43 -22
- sphinx/builders/gettext.py +43 -25
- sphinx/builders/html/__init__.py +284 -218
- sphinx/builders/html/_assets.py +62 -26
- sphinx/builders/html/_build_info.py +76 -0
- sphinx/builders/html/transforms.py +11 -9
- sphinx/builders/latex/__init__.py +139 -81
- sphinx/builders/latex/constants.py +7 -7
- sphinx/builders/latex/nodes.py +3 -2
- sphinx/builders/latex/theming.py +7 -5
- sphinx/builders/latex/transforms.py +27 -19
- sphinx/builders/linkcheck.py +146 -72
- sphinx/builders/manpage.py +30 -13
- sphinx/builders/singlehtml.py +22 -14
- sphinx/builders/texinfo.py +67 -37
- sphinx/builders/text.py +5 -5
- sphinx/builders/xml.py +6 -9
- sphinx/cmd/build.py +282 -103
- sphinx/cmd/make_mode.py +106 -63
- sphinx/cmd/quickstart.py +341 -145
- sphinx/config.py +45 -12
- sphinx/deprecation.py +8 -2
- sphinx/directives/__init__.py +28 -19
- sphinx/directives/code.py +86 -56
- sphinx/directives/other.py +50 -36
- sphinx/directives/patches.py +29 -19
- sphinx/domains/__init__.py +20 -120
- sphinx/domains/_domains_container.py +281 -0
- sphinx/domains/_index.py +110 -0
- sphinx/domains/c/__init__.py +3 -3
- sphinx/domains/c/_parser.py +10 -6
- sphinx/domains/changeset.py +5 -3
- sphinx/domains/citation.py +5 -3
- sphinx/domains/cpp/__init__.py +9 -11
- sphinx/domains/cpp/_parser.py +8 -7
- sphinx/domains/index.py +3 -3
- sphinx/domains/javascript.py +12 -7
- sphinx/domains/math.py +2 -2
- sphinx/domains/python/__init__.py +10 -5
- sphinx/domains/python/_object.py +1 -1
- sphinx/domains/rst.py +5 -5
- sphinx/domains/std/__init__.py +16 -11
- sphinx/environment/__init__.py +202 -146
- sphinx/environment/adapters/asset.py +3 -2
- sphinx/environment/adapters/indexentries.py +74 -33
- sphinx/environment/adapters/toctree.py +100 -43
- sphinx/environment/collectors/__init__.py +19 -8
- sphinx/environment/collectors/asset.py +47 -15
- sphinx/environment/collectors/dependencies.py +8 -4
- sphinx/environment/collectors/metadata.py +7 -2
- sphinx/environment/collectors/title.py +7 -2
- sphinx/environment/collectors/toctree.py +54 -22
- sphinx/errors.py +4 -1
- sphinx/events.py +314 -7
- sphinx/ext/apidoc.py +42 -18
- sphinx/ext/autodoc/__init__.py +52 -24
- sphinx/ext/autodoc/importer.py +6 -9
- sphinx/ext/autosectionlabel.py +1 -2
- sphinx/ext/autosummary/__init__.py +3 -1
- sphinx/ext/autosummary/generate.py +28 -14
- sphinx/ext/coverage.py +7 -7
- sphinx/ext/doctest.py +4 -8
- sphinx/ext/duration.py +6 -5
- sphinx/ext/inheritance_diagram.py +1 -1
- sphinx/ext/intersphinx/_cli.py +6 -4
- sphinx/ext/intersphinx/_load.py +77 -32
- sphinx/ext/intersphinx/_resolve.py +173 -79
- sphinx/ext/intersphinx/_shared.py +7 -5
- sphinx/ext/linkcode.py +7 -1
- sphinx/ext/mathjax.py +1 -2
- sphinx/ext/napoleon/__init__.py +37 -24
- sphinx/ext/napoleon/docstring.py +202 -134
- sphinx/ext/todo.py +5 -3
- sphinx/highlighting.py +9 -2
- sphinx/io.py +1 -1
- sphinx/jinja2glue.py +27 -6
- sphinx/locale/__init__.py +6 -2
- sphinx/locale/ar/LC_MESSAGES/sphinx.js +8 -1
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +2246 -2288
- sphinx/locale/bg/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/bn/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +2349 -2395
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +2846 -2892
- sphinx/locale/cak/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +2213 -2259
- sphinx/locale/cs/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +2225 -2269
- sphinx/locale/cy/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +2403 -2447
- sphinx/locale/da/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +2214 -2260
- sphinx/locale/de/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +2230 -2276
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/el/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +2619 -2665
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2519 -2565
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/eo/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +2232 -2278
- sphinx/locale/es/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +2516 -2561
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2114 -2159
- sphinx/locale/et/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +2317 -2363
- sphinx/locale/eu/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +2218 -2264
- sphinx/locale/fa/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +2505 -2551
- sphinx/locale/fi/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +2303 -2349
- sphinx/locale/fr/LC_MESSAGES/sphinx.js +6 -2
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +2863 -2908
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +2114 -2159
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +2571 -2617
- sphinx/locale/he/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +2307 -2352
- sphinx/locale/hi/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +2580 -2626
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/hr/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +2238 -2283
- sphinx/locale/hu/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +2228 -2274
- sphinx/locale/id/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +2787 -2834
- sphinx/locale/is/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +2224 -2270
- sphinx/locale/it/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +2231 -2276
- sphinx/locale/ja/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +2507 -2554
- sphinx/locale/ka/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +2428 -2474
- sphinx/locale/ko/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +2516 -2563
- sphinx/locale/lt/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +2425 -2469
- sphinx/locale/lv/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +2362 -2407
- sphinx/locale/mk/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +2121 -2167
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2220 -2266
- sphinx/locale/ne/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +2221 -2267
- sphinx/locale/nl/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +2240 -2286
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +2319 -2363
- sphinx/locale/pt/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +2114 -2159
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2854 -2899
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2224 -2269
- sphinx/locale/ro/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +2226 -2271
- sphinx/locale/ru/LC_MESSAGES/sphinx.js +8 -3
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +2841 -2885
- sphinx/locale/si/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +2294 -2340
- sphinx/locale/sk/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +2497 -2541
- sphinx/locale/sl/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +2331 -2375
- sphinx/locale/sphinx.pot +2121 -2167
- sphinx/locale/sq/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +2855 -2901
- sphinx/locale/sr/LC_MESSAGES/sphinx.js +5 -1
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +2203 -2248
- sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +2423 -2469
- sphinx/locale/te/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/tr/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +2443 -2489
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.js +6 -1
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2329 -2373
- sphinx/locale/ur/LC_MESSAGES/sphinx.js +4 -1
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +2113 -2159
- sphinx/locale/vi/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +2199 -2246
- sphinx/locale/yue/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +2112 -2159
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2112 -2159
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2845 -2892
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.js +3 -1
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2112 -2159
- sphinx/parsers.py +3 -1
- sphinx/project.py +6 -2
- sphinx/pycode/__init__.py +11 -4
- sphinx/pycode/ast.py +58 -58
- sphinx/pycode/parser.py +49 -28
- sphinx/pygments_styles.py +49 -49
- sphinx/registry.py +8 -3
- sphinx/roles.py +136 -13
- sphinx/search/__init__.py +146 -87
- sphinx/search/da.py +2 -4
- sphinx/search/de.py +2 -4
- sphinx/search/en.py +4 -4
- sphinx/search/es.py +2 -4
- sphinx/search/fi.py +2 -4
- sphinx/search/fr.py +2 -4
- sphinx/search/hu.py +2 -4
- sphinx/search/it.py +2 -4
- sphinx/search/ja.py +55 -32
- sphinx/search/nl.py +2 -4
- sphinx/search/no.py +2 -4
- sphinx/search/pt.py +2 -4
- sphinx/search/ro.py +0 -2
- sphinx/search/ru.py +2 -4
- sphinx/search/sv.py +2 -4
- sphinx/search/tr.py +0 -2
- sphinx/search/zh.py +18 -13
- sphinx/templates/graphviz/graphviz.css +0 -7
- sphinx/testing/fixtures.py +6 -5
- sphinx/testing/path.py +7 -5
- sphinx/testing/util.py +63 -29
- sphinx/texinputs/sphinx.sty +115 -50
- sphinx/texinputs/sphinxlatexadmonitions.sty +56 -38
- sphinx/texinputs/sphinxlatexcontainers.sty +1 -1
- sphinx/texinputs/sphinxlatexgraphics.sty +3 -2
- sphinx/texinputs/sphinxlatexindbibtoc.sty +1 -1
- sphinx/texinputs/sphinxlatexlists.sty +1 -1
- sphinx/texinputs/sphinxlatexliterals.sty +4 -1
- sphinx/texinputs/sphinxlatexnumfig.sty +22 -9
- sphinx/texinputs/sphinxlatexobjects.sty +1 -1
- sphinx/texinputs/sphinxlatexshadowbox.sty +72 -10
- sphinx/texinputs/sphinxlatexstyleheadings.sty +7 -2
- sphinx/texinputs/sphinxlatexstylepage.sty +2 -8
- sphinx/texinputs/sphinxlatexstyletext.sty +2 -4
- sphinx/texinputs/sphinxlatextables.sty +1 -1
- sphinx/texinputs/sphinxoptionsgeometry.sty +1 -1
- sphinx/texinputs/sphinxoptionshyperref.sty +1 -1
- sphinx/themes/agogo/layout.html +1 -10
- sphinx/themes/agogo/static/agogo.css.jinja +0 -7
- sphinx/themes/basic/defindex.html +1 -8
- sphinx/themes/basic/domainindex.html +1 -9
- sphinx/themes/basic/genindex-single.html +1 -9
- sphinx/themes/basic/genindex-split.html +1 -9
- sphinx/themes/basic/genindex.html +1 -9
- sphinx/themes/basic/globaltoc.html +1 -9
- sphinx/themes/basic/layout.html +1 -9
- sphinx/themes/basic/localtoc.html +1 -9
- sphinx/themes/basic/page.html +1 -9
- sphinx/themes/basic/relations.html +1 -9
- sphinx/themes/basic/search.html +1 -9
- sphinx/themes/basic/searchbox.html +1 -9
- sphinx/themes/basic/searchfield.html +4 -10
- sphinx/themes/basic/sourcelink.html +1 -9
- sphinx/themes/basic/static/basic.css.jinja +2 -13
- sphinx/themes/basic/static/doctools.js +0 -7
- sphinx/themes/basic/static/language_data.js.jinja +0 -7
- sphinx/themes/basic/static/searchtools.js +25 -13
- sphinx/themes/bizstyle/layout.html +1 -9
- sphinx/themes/bizstyle/static/bizstyle.css.jinja +0 -7
- sphinx/themes/bizstyle/static/bizstyle.js.jinja +5 -11
- sphinx/themes/classic/layout.html +1 -9
- sphinx/themes/classic/static/classic.css.jinja +0 -7
- sphinx/themes/classic/static/sidebar.js.jinja +0 -6
- sphinx/themes/epub/epub-cover.html +1 -9
- sphinx/themes/epub/layout.html +1 -9
- sphinx/themes/epub/static/epub.css.jinja +0 -7
- sphinx/themes/haiku/layout.html +1 -9
- sphinx/themes/haiku/static/haiku.css.jinja +0 -6
- sphinx/themes/nature/static/nature.css.jinja +0 -7
- sphinx/themes/nonav/layout.html +1 -9
- sphinx/themes/nonav/static/nonav.css.jinja +0 -7
- sphinx/themes/pyramid/static/epub.css.jinja +0 -7
- sphinx/themes/pyramid/static/pyramid.css.jinja +0 -7
- sphinx/themes/scrolls/layout.html +1 -10
- sphinx/themes/scrolls/static/scrolls.css.jinja +0 -7
- sphinx/themes/sphinxdoc/static/sphinxdoc.css.jinja +2 -7
- sphinx/themes/traditional/static/traditional.css.jinja +0 -7
- sphinx/theming.py +18 -6
- sphinx/transforms/__init__.py +56 -35
- sphinx/transforms/compact_bullet_list.py +3 -2
- sphinx/transforms/i18n.py +132 -50
- sphinx/transforms/post_transforms/__init__.py +94 -43
- sphinx/transforms/post_transforms/code.py +7 -6
- sphinx/transforms/post_transforms/images.py +71 -54
- sphinx/transforms/references.py +1 -2
- sphinx/util/__init__.py +23 -194
- sphinx/util/_files.py +80 -0
- sphinx/util/_importer.py +27 -0
- sphinx/util/_io.py +1 -2
- sphinx/util/_lines.py +26 -0
- sphinx/util/_pathlib.py +5 -2
- sphinx/util/_serialise.py +53 -0
- sphinx/util/_timestamps.py +2 -1
- sphinx/util/_uri.py +16 -0
- sphinx/util/cfamily.py +48 -25
- sphinx/util/console.py +1 -0
- sphinx/util/display.py +1 -1
- sphinx/util/docfields.py +125 -45
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +118 -44
- sphinx/util/exceptions.py +11 -5
- sphinx/util/fileutil.py +53 -32
- sphinx/util/http_date.py +9 -7
- sphinx/util/i18n.py +49 -16
- sphinx/util/images.py +7 -6
- sphinx/util/inspect.py +29 -12
- sphinx/util/inventory.py +47 -29
- sphinx/util/logging.py +58 -85
- sphinx/util/matching.py +3 -3
- sphinx/util/math.py +1 -1
- sphinx/util/nodes.py +176 -108
- sphinx/util/osutil.py +13 -10
- sphinx/util/parallel.py +5 -4
- sphinx/util/parsing.py +5 -3
- sphinx/util/png.py +3 -3
- sphinx/util/requests.py +8 -4
- sphinx/util/rst.py +5 -3
- sphinx/util/tags.py +5 -2
- sphinx/util/template.py +26 -11
- sphinx/util/texescape.py +2 -2
- sphinx/util/typing.py +89 -38
- sphinx/versioning.py +3 -1
- sphinx/writers/html.py +22 -7
- sphinx/writers/html5.py +113 -64
- sphinx/writers/latex.py +408 -221
- sphinx/writers/manpage.py +25 -15
- sphinx/writers/texinfo.py +94 -82
- sphinx/writers/text.py +87 -53
- sphinx/writers/xml.py +5 -4
- sphinx-8.1.1.dist-info/LICENSE.rst +31 -0
- {sphinx-8.0.2.dist-info → sphinx-8.1.1.dist-info}/METADATA +13 -11
- sphinx-8.1.1.dist-info/RECORD +598 -0
- sphinx-8.0.2.dist-info/LICENSE.rst +0 -67
- sphinx-8.0.2.dist-info/RECORD +0 -590
- {sphinx-8.0.2.dist-info → sphinx-8.1.1.dist-info}/WHEEL +0 -0
- {sphinx-8.0.2.dist-info → sphinx-8.1.1.dist-info}/entry_points.txt +0 -0
sphinx/builders/_epub_base.py
CHANGED
|
@@ -15,7 +15,8 @@ from docutils import nodes
|
|
|
15
15
|
from docutils.utils import smartquotes
|
|
16
16
|
|
|
17
17
|
from sphinx import addnodes
|
|
18
|
-
from sphinx.builders.html import
|
|
18
|
+
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
19
|
+
from sphinx.builders.html._build_info import BuildInfo
|
|
19
20
|
from sphinx.locale import __
|
|
20
21
|
from sphinx.util import logging
|
|
21
22
|
from sphinx.util.display import status_iterator
|
|
@@ -27,6 +28,7 @@ if TYPE_CHECKING:
|
|
|
27
28
|
|
|
28
29
|
try:
|
|
29
30
|
from PIL import Image
|
|
31
|
+
|
|
30
32
|
PILLOW_AVAILABLE = True
|
|
31
33
|
except ImportError:
|
|
32
34
|
PILLOW_AVAILABLE = False
|
|
@@ -78,7 +80,7 @@ VECTOR_GRAPHICS_EXTENSIONS = ('.svg',)
|
|
|
78
80
|
# Regular expression to match colons only in local fragment identifiers.
|
|
79
81
|
# If the URI contains a colon before the #,
|
|
80
82
|
# it is an external link that should not change.
|
|
81
|
-
REFURI_RE = re.compile(
|
|
83
|
+
REFURI_RE = re.compile('([^#:]*#)(.*)')
|
|
82
84
|
|
|
83
85
|
|
|
84
86
|
class ManifestItem(NamedTuple):
|
|
@@ -119,6 +121,7 @@ ssp = sphinx_smarty_pants
|
|
|
119
121
|
|
|
120
122
|
# The epub publisher
|
|
121
123
|
|
|
124
|
+
|
|
122
125
|
class EpubBuilder(StandaloneHTMLBuilder):
|
|
123
126
|
"""
|
|
124
127
|
Builder that outputs epub files.
|
|
@@ -130,8 +133,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
130
133
|
|
|
131
134
|
# don't copy the reST source
|
|
132
135
|
copysource = False
|
|
133
|
-
supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
|
|
134
|
-
'image/jpeg']
|
|
136
|
+
supported_image_types = ['image/svg+xml', 'image/png', 'image/gif', 'image/jpeg']
|
|
135
137
|
supported_remote_images = False
|
|
136
138
|
|
|
137
139
|
# don't add links
|
|
@@ -154,8 +156,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
154
156
|
guide_titles = GUIDE_TITLES
|
|
155
157
|
media_types = MEDIA_TYPES
|
|
156
158
|
refuri_re = REFURI_RE
|
|
157
|
-
template_dir =
|
|
158
|
-
doctype =
|
|
159
|
+
template_dir = ''
|
|
160
|
+
doctype = ''
|
|
159
161
|
|
|
160
162
|
def init(self) -> None:
|
|
161
163
|
super().init()
|
|
@@ -185,7 +187,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
185
187
|
return id
|
|
186
188
|
|
|
187
189
|
def get_refnodes(
|
|
188
|
-
self,
|
|
190
|
+
self,
|
|
191
|
+
doctree: Node,
|
|
192
|
+
result: list[dict[str, Any]],
|
|
189
193
|
) -> list[dict[str, Any]]:
|
|
190
194
|
"""Collect section titles, their depth in the toc and the refuri."""
|
|
191
195
|
# XXX: is there a better way than checking the attribute
|
|
@@ -215,8 +219,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
215
219
|
logger.warning(
|
|
216
220
|
__('duplicated ToC entry found: %s'),
|
|
217
221
|
node['refuri'],
|
|
218
|
-
type=
|
|
219
|
-
subtype=
|
|
222
|
+
type='epub',
|
|
223
|
+
subtype='duplicated_toc_entry',
|
|
220
224
|
)
|
|
221
225
|
else:
|
|
222
226
|
appeared.add(node['refuri'])
|
|
@@ -225,9 +229,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
225
229
|
"""Get the total table of contents, containing the root_doc
|
|
226
230
|
and pre and post files not managed by sphinx.
|
|
227
231
|
"""
|
|
228
|
-
doctree = self.env.get_and_resolve_doctree(
|
|
229
|
-
|
|
230
|
-
|
|
232
|
+
doctree = self.env.get_and_resolve_doctree(
|
|
233
|
+
self.config.root_doc, self, prune_toctrees=False, includehidden=True
|
|
234
|
+
)
|
|
231
235
|
self.refnodes = self.get_refnodes(doctree, [])
|
|
232
236
|
master_dir = path.dirname(self.config.root_doc)
|
|
233
237
|
if master_dir:
|
|
@@ -237,20 +241,26 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
237
241
|
self.toc_add_files(self.refnodes)
|
|
238
242
|
|
|
239
243
|
def toc_add_files(self, refnodes: list[dict[str, Any]]) -> None:
|
|
240
|
-
"""Add the root_doc, pre and post files to a list of refnodes.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
'refuri': html.escape(self.config.root_doc + self.out_suffix),
|
|
245
|
-
'text': ssp(html.escape(
|
|
246
|
-
self.env.titles[self.config.root_doc].astext())),
|
|
247
|
-
})
|
|
248
|
-
for file, text in reversed(self.config.epub_pre_files):
|
|
249
|
-
refnodes.insert(0, {
|
|
244
|
+
"""Add the root_doc, pre and post files to a list of refnodes."""
|
|
245
|
+
refnodes.insert(
|
|
246
|
+
0,
|
|
247
|
+
{
|
|
250
248
|
'level': 1,
|
|
251
|
-
'refuri': html.escape(
|
|
252
|
-
'text': ssp(
|
|
253
|
-
|
|
249
|
+
'refuri': html.escape(self.config.root_doc + self.out_suffix),
|
|
250
|
+
'text': ssp(
|
|
251
|
+
html.escape(self.env.titles[self.config.root_doc].astext())
|
|
252
|
+
),
|
|
253
|
+
},
|
|
254
|
+
)
|
|
255
|
+
for file, text in reversed(self.config.epub_pre_files):
|
|
256
|
+
refnodes.insert(
|
|
257
|
+
0,
|
|
258
|
+
{
|
|
259
|
+
'level': 1,
|
|
260
|
+
'refuri': html.escape(file),
|
|
261
|
+
'text': ssp(html.escape(text)),
|
|
262
|
+
},
|
|
263
|
+
)
|
|
254
264
|
for file, text in self.config.epub_post_files:
|
|
255
265
|
refnodes.append({
|
|
256
266
|
'level': 1,
|
|
@@ -268,6 +278,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
268
278
|
Some readers crash because they interpret the part as a
|
|
269
279
|
transport protocol specification.
|
|
270
280
|
"""
|
|
281
|
+
|
|
271
282
|
def update_node_id(node: Element) -> None:
|
|
272
283
|
"""Update IDs of given *node*."""
|
|
273
284
|
new_ids: list[str] = []
|
|
@@ -295,10 +306,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
295
306
|
for desc_signature in tree.findall(addnodes.desc_signature):
|
|
296
307
|
update_node_id(desc_signature)
|
|
297
308
|
|
|
298
|
-
def add_visible_links(
|
|
309
|
+
def add_visible_links(
|
|
310
|
+
self, tree: nodes.document, show_urls: str = 'inline'
|
|
311
|
+
) -> None:
|
|
299
312
|
"""Add visible link targets for external links"""
|
|
300
313
|
|
|
301
|
-
def make_footnote_ref(
|
|
314
|
+
def make_footnote_ref(
|
|
315
|
+
doc: nodes.document, label: str
|
|
316
|
+
) -> nodes.footnote_reference:
|
|
302
317
|
"""Create a footnote_reference node with children"""
|
|
303
318
|
footnote_ref = nodes.footnote_reference('[#]_')
|
|
304
319
|
footnote_ref.append(nodes.Text(label))
|
|
@@ -379,17 +394,16 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
379
394
|
# Logic modeled from themes/basic/genindex.html
|
|
380
395
|
for _key, columns in tree:
|
|
381
396
|
for _entryname, (links, subitems, _key) in columns:
|
|
382
|
-
for
|
|
383
|
-
m
|
|
384
|
-
|
|
385
|
-
links[i] = (ismain,
|
|
386
|
-
self.fix_fragment(m.group(1), m.group(2)))
|
|
397
|
+
for i, (ismain, link) in enumerate(links):
|
|
398
|
+
if m := self.refuri_re.match(link):
|
|
399
|
+
links[i] = ismain, self.fix_fragment(m.group(1), m.group(2))
|
|
387
400
|
for _subentryname, subentrylinks in subitems:
|
|
388
|
-
for
|
|
389
|
-
m
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
401
|
+
for i, (ismain, link) in enumerate(subentrylinks):
|
|
402
|
+
if m := self.refuri_re.match(link):
|
|
403
|
+
subentrylinks[i] = (
|
|
404
|
+
ismain,
|
|
405
|
+
self.fix_fragment(m.group(1), m.group(2)),
|
|
406
|
+
)
|
|
393
407
|
|
|
394
408
|
def is_vector_graphics(self, filename: str) -> bool:
|
|
395
409
|
"""Does the filename extension indicate a vector graphic format?"""
|
|
@@ -402,15 +416,22 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
402
416
|
the format and resizing the image if necessary/possible.
|
|
403
417
|
"""
|
|
404
418
|
ensuredir(path.join(self.outdir, self.imagedir))
|
|
405
|
-
for src in status_iterator(
|
|
406
|
-
|
|
419
|
+
for src in status_iterator(
|
|
420
|
+
self.images,
|
|
421
|
+
__('copying images... '),
|
|
422
|
+
'brown',
|
|
423
|
+
len(self.images),
|
|
424
|
+
self.app.verbosity,
|
|
425
|
+
):
|
|
407
426
|
dest = self.images[src]
|
|
408
427
|
try:
|
|
409
428
|
img = Image.open(path.join(self.srcdir, src))
|
|
410
429
|
except OSError:
|
|
411
430
|
if not self.is_vector_graphics(src):
|
|
412
|
-
logger.warning(
|
|
413
|
-
|
|
431
|
+
logger.warning(
|
|
432
|
+
__('cannot read image file %r: copying it instead'),
|
|
433
|
+
path.join(self.srcdir, src),
|
|
434
|
+
)
|
|
414
435
|
try:
|
|
415
436
|
copyfile(
|
|
416
437
|
self.srcdir / src,
|
|
@@ -418,8 +439,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
418
439
|
force=True,
|
|
419
440
|
)
|
|
420
441
|
except OSError as err:
|
|
421
|
-
logger.warning(
|
|
422
|
-
|
|
442
|
+
logger.warning(
|
|
443
|
+
__('cannot copy image file %r: %s'),
|
|
444
|
+
path.join(self.srcdir, src),
|
|
445
|
+
err,
|
|
446
|
+
)
|
|
423
447
|
continue
|
|
424
448
|
if self.config.epub_fix_images:
|
|
425
449
|
if img.mode == 'P':
|
|
@@ -435,8 +459,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
435
459
|
try:
|
|
436
460
|
img.save(path.join(self.outdir, self.imagedir, dest))
|
|
437
461
|
except OSError as err:
|
|
438
|
-
logger.warning(
|
|
439
|
-
|
|
462
|
+
logger.warning(
|
|
463
|
+
__('cannot write image file %r: %s'),
|
|
464
|
+
path.join(self.srcdir, src),
|
|
465
|
+
err,
|
|
466
|
+
)
|
|
440
467
|
|
|
441
468
|
def copy_image_files(self) -> None:
|
|
442
469
|
"""Copy image files to destination directory.
|
|
@@ -554,13 +581,19 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
554
581
|
# we always have JS and potentially OpenSearch files, don't
|
|
555
582
|
# always warn about them
|
|
556
583
|
if ext not in ('.js', '.xml'):
|
|
557
|
-
logger.warning(
|
|
558
|
-
|
|
584
|
+
logger.warning(
|
|
585
|
+
__('unknown mimetype for %s, ignoring'),
|
|
586
|
+
filename,
|
|
587
|
+
type='epub',
|
|
588
|
+
subtype='unknown_project_files',
|
|
589
|
+
)
|
|
559
590
|
continue
|
|
560
591
|
filename = filename.replace(os.sep, '/')
|
|
561
|
-
item = ManifestItem(
|
|
562
|
-
|
|
563
|
-
|
|
592
|
+
item = ManifestItem(
|
|
593
|
+
html.escape(quote(filename)),
|
|
594
|
+
html.escape(self.make_id(filename)),
|
|
595
|
+
html.escape(self.media_types[ext]),
|
|
596
|
+
)
|
|
564
597
|
metadata['manifest_items'].append(item)
|
|
565
598
|
self.files.append(filename)
|
|
566
599
|
|
|
@@ -600,13 +633,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
600
633
|
if self.coverpage_name not in self.files:
|
|
601
634
|
ext = path.splitext(self.coverpage_name)[-1]
|
|
602
635
|
self.files.append(self.coverpage_name)
|
|
603
|
-
item = ManifestItem(
|
|
604
|
-
|
|
605
|
-
|
|
636
|
+
item = ManifestItem(
|
|
637
|
+
html.escape(self.coverpage_name),
|
|
638
|
+
html.escape(self.make_id(self.coverpage_name)),
|
|
639
|
+
html.escape(self.media_types[ext]),
|
|
640
|
+
)
|
|
606
641
|
metadata['manifest_items'].append(item)
|
|
607
642
|
ctx = {'image': html.escape(image), 'title': self.config.project}
|
|
608
|
-
self.handle_page(
|
|
609
|
-
path.splitext(self.coverpage_name)[0], ctx, html_tmpl)
|
|
643
|
+
self.handle_page(path.splitext(self.coverpage_name)[0], ctx, html_tmpl)
|
|
610
644
|
spinefiles.add(self.coverpage_name)
|
|
611
645
|
|
|
612
646
|
auto_add_cover = True
|
|
@@ -620,17 +654,25 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
620
654
|
auto_add_cover = False
|
|
621
655
|
if type == 'toc':
|
|
622
656
|
auto_add_toc = False
|
|
623
|
-
metadata['guides'].append(
|
|
624
|
-
|
|
625
|
-
|
|
657
|
+
metadata['guides'].append(
|
|
658
|
+
Guide(html.escape(type), html.escape(title), html.escape(uri))
|
|
659
|
+
)
|
|
626
660
|
if auto_add_cover and html_tmpl:
|
|
627
|
-
metadata['guides'].append(
|
|
628
|
-
|
|
629
|
-
|
|
661
|
+
metadata['guides'].append(
|
|
662
|
+
Guide(
|
|
663
|
+
'cover',
|
|
664
|
+
self.guide_titles['cover'],
|
|
665
|
+
html.escape(self.coverpage_name),
|
|
666
|
+
)
|
|
667
|
+
)
|
|
630
668
|
if auto_add_toc and self.refnodes:
|
|
631
|
-
metadata['guides'].append(
|
|
632
|
-
|
|
633
|
-
|
|
669
|
+
metadata['guides'].append(
|
|
670
|
+
Guide(
|
|
671
|
+
'toc',
|
|
672
|
+
self.guide_titles['toc'],
|
|
673
|
+
html.escape(self.refnodes[0]['refuri']),
|
|
674
|
+
)
|
|
675
|
+
)
|
|
634
676
|
|
|
635
677
|
# write the project file
|
|
636
678
|
copy_asset_file(
|
|
@@ -640,14 +682,17 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
640
682
|
force=True,
|
|
641
683
|
)
|
|
642
684
|
|
|
643
|
-
def new_navpoint(
|
|
685
|
+
def new_navpoint(
|
|
686
|
+
self, node: dict[str, Any], level: int, incr: bool = True
|
|
687
|
+
) -> NavPoint:
|
|
644
688
|
"""Create a new entry in the toc from the node at given level."""
|
|
645
689
|
# XXX Modifies the node
|
|
646
690
|
if incr:
|
|
647
691
|
self.playorder += 1
|
|
648
692
|
self.tocid += 1
|
|
649
|
-
return NavPoint(
|
|
650
|
-
|
|
693
|
+
return NavPoint(
|
|
694
|
+
f'navPoint{self.tocid}', self.playorder, node['text'], node['refuri'], []
|
|
695
|
+
)
|
|
651
696
|
|
|
652
697
|
def build_navpoints(self, nodes: list[dict[str, Any]]) -> list[NavPoint]:
|
|
653
698
|
"""Create the toc navigation structure.
|
|
@@ -676,7 +721,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
676
721
|
level += 1
|
|
677
722
|
if lastnode and self.config.epub_tocdup:
|
|
678
723
|
# Insert starting point in subtoc with same playOrder
|
|
679
|
-
navstack[-1].children.append(
|
|
724
|
+
navstack[-1].children.append(
|
|
725
|
+
self.new_navpoint(lastnode, level, False)
|
|
726
|
+
)
|
|
680
727
|
navpoint = self.new_navpoint(node, level)
|
|
681
728
|
navstack[-1].children.append(navpoint)
|
|
682
729
|
navstack.append(navpoint)
|
|
@@ -709,9 +756,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|
|
709
756
|
logger.info(__('writing toc.ncx file...'))
|
|
710
757
|
|
|
711
758
|
if self.config.epub_tocscope == 'default':
|
|
712
|
-
doctree = self.env.get_and_resolve_doctree(
|
|
713
|
-
|
|
714
|
-
|
|
759
|
+
doctree = self.env.get_and_resolve_doctree(
|
|
760
|
+
self.config.root_doc, self, prune_toctrees=False, includehidden=False
|
|
761
|
+
)
|
|
715
762
|
refnodes = self.get_refnodes(doctree, [])
|
|
716
763
|
self.toc_add_files(refnodes)
|
|
717
764
|
else:
|
sphinx/builders/changes.py
CHANGED
|
@@ -4,11 +4,10 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import html
|
|
6
6
|
from os import path
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
9
|
from sphinx import package_dir
|
|
10
10
|
from sphinx.builders import Builder
|
|
11
|
-
from sphinx.domains.changeset import ChangeSetDomain
|
|
12
11
|
from sphinx.locale import _, __
|
|
13
12
|
from sphinx.theming import HTMLThemeFactory
|
|
14
13
|
from sphinx.util import logging
|
|
@@ -17,6 +16,8 @@ from sphinx.util.fileutil import copy_asset_file
|
|
|
17
16
|
from sphinx.util.osutil import ensuredir, os_path
|
|
18
17
|
|
|
19
18
|
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Set
|
|
20
|
+
|
|
20
21
|
from sphinx.application import Sphinx
|
|
21
22
|
from sphinx.util.typing import ExtensionMetadata
|
|
22
23
|
|
|
@@ -47,9 +48,9 @@ class ChangesBuilder(Builder):
|
|
|
47
48
|
'versionremoved': 'removed',
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
def
|
|
51
|
+
def write_documents(self, _docnames: Set[str]) -> None:
|
|
51
52
|
version = self.config.version
|
|
52
|
-
domain =
|
|
53
|
+
domain = self.env.domains.changeset_domain
|
|
53
54
|
libchanges: dict[str, list[tuple[str, str, int]]] = {}
|
|
54
55
|
apichanges: list[tuple[str, str, int]] = []
|
|
55
56
|
otherchanges: dict[tuple[str, str], list[tuple[str, str, int]]] = {}
|
|
@@ -80,15 +81,21 @@ class ChangesBuilder(Builder):
|
|
|
80
81
|
entry = f'<b>{descname}</b>: <i>{ttext}:</i> {context}'
|
|
81
82
|
else:
|
|
82
83
|
entry = f'<b>{descname}</b>: <i>{ttext}</i>.'
|
|
83
|
-
libchanges.setdefault(module, []).append((
|
|
84
|
-
|
|
84
|
+
libchanges.setdefault(module, []).append((
|
|
85
|
+
entry,
|
|
86
|
+
changeset.docname,
|
|
87
|
+
changeset.lineno,
|
|
88
|
+
))
|
|
85
89
|
else:
|
|
86
90
|
if not context:
|
|
87
91
|
continue
|
|
88
92
|
entry = f'<i>{ttext.capitalize()}:</i> {context}'
|
|
89
93
|
title = self.env.titles[changeset.docname].astext()
|
|
90
|
-
otherchanges.setdefault((changeset.docname, title), []).append(
|
|
91
|
-
|
|
94
|
+
otherchanges.setdefault((changeset.docname, title), []).append((
|
|
95
|
+
entry,
|
|
96
|
+
changeset.docname,
|
|
97
|
+
changeset.lineno,
|
|
98
|
+
))
|
|
92
99
|
|
|
93
100
|
ctx = {
|
|
94
101
|
'project': self.config.project,
|
|
@@ -106,11 +113,12 @@ class ChangesBuilder(Builder):
|
|
|
106
113
|
with open(path.join(self.outdir, 'changes.html'), 'w', encoding='utf8') as f:
|
|
107
114
|
f.write(self.templates.render('changes/versionchanges.html', ctx))
|
|
108
115
|
|
|
109
|
-
hltext = [
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
hltext = [
|
|
117
|
+
f'.. versionadded:: {version}',
|
|
118
|
+
f'.. versionchanged:: {version}',
|
|
119
|
+
f'.. deprecated:: {version}',
|
|
120
|
+
f'.. versionremoved:: {version}',
|
|
121
|
+
]
|
|
114
122
|
|
|
115
123
|
def hl(no: int, line: str) -> str:
|
|
116
124
|
line = '<a name="L%s"> </a>' % no + html.escape(line)
|
|
@@ -122,12 +130,15 @@ class ChangesBuilder(Builder):
|
|
|
122
130
|
|
|
123
131
|
logger.info(bold(__('copying source files...')))
|
|
124
132
|
for docname in self.env.all_docs:
|
|
125
|
-
with open(
|
|
126
|
-
|
|
133
|
+
with open(
|
|
134
|
+
self.env.doc2path(docname), encoding=self.env.config.source_encoding
|
|
135
|
+
) as f:
|
|
127
136
|
try:
|
|
128
137
|
lines = f.readlines()
|
|
129
138
|
except UnicodeDecodeError:
|
|
130
|
-
logger.warning(
|
|
139
|
+
logger.warning(
|
|
140
|
+
__('could not read %r for changelog creation'), docname
|
|
141
|
+
)
|
|
131
142
|
continue
|
|
132
143
|
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
|
|
133
144
|
ensuredir(path.dirname(targetfn))
|
|
@@ -138,8 +149,9 @@ class ChangesBuilder(Builder):
|
|
|
138
149
|
'text': text,
|
|
139
150
|
}
|
|
140
151
|
f.write(self.templates.render('changes/rstsource.html', ctx))
|
|
141
|
-
themectx = {
|
|
142
|
-
|
|
152
|
+
themectx = {
|
|
153
|
+
'theme_' + key: val for (key, val) in self.theme.get_options({}).items()
|
|
154
|
+
}
|
|
143
155
|
copy_asset_file(
|
|
144
156
|
path.join(package_dir, 'themes', 'default', 'static', 'default.css.jinja'),
|
|
145
157
|
self.outdir,
|
|
@@ -155,9 +167,15 @@ class ChangesBuilder(Builder):
|
|
|
155
167
|
|
|
156
168
|
def hl(self, text: str, version: str) -> str:
|
|
157
169
|
text = html.escape(text)
|
|
158
|
-
for directive in (
|
|
159
|
-
|
|
160
|
-
|
|
170
|
+
for directive in (
|
|
171
|
+
'versionchanged',
|
|
172
|
+
'versionadded',
|
|
173
|
+
'deprecated',
|
|
174
|
+
'versionremoved',
|
|
175
|
+
):
|
|
176
|
+
text = text.replace(
|
|
177
|
+
f'.. {directive}:: {version}', f'<b>.. {directive}:: {version}</b>'
|
|
178
|
+
)
|
|
161
179
|
return text
|
|
162
180
|
|
|
163
181
|
def finish(self) -> None:
|
sphinx/builders/dirhtml.py
CHANGED
|
@@ -34,11 +34,11 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
|
|
|
34
34
|
|
|
35
35
|
def get_outfilename(self, pagename: str) -> str:
|
|
36
36
|
if pagename == 'index' or pagename.endswith(SEP + 'index'):
|
|
37
|
-
outfilename = path.join(self.outdir, os_path(pagename) +
|
|
38
|
-
self.out_suffix)
|
|
37
|
+
outfilename = path.join(self.outdir, os_path(pagename) + self.out_suffix)
|
|
39
38
|
else:
|
|
40
|
-
outfilename = path.join(
|
|
41
|
-
|
|
39
|
+
outfilename = path.join(
|
|
40
|
+
self.outdir, os_path(pagename), 'index' + self.out_suffix
|
|
41
|
+
)
|
|
42
42
|
|
|
43
43
|
return outfilename
|
|
44
44
|
|
sphinx/builders/dummy.py
CHANGED
|
@@ -8,7 +8,7 @@ from sphinx.builders import Builder
|
|
|
8
8
|
from sphinx.locale import __
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
-
from docutils
|
|
11
|
+
from docutils import nodes
|
|
12
12
|
|
|
13
13
|
from sphinx.application import Sphinx
|
|
14
14
|
from sphinx.util.typing import ExtensionMetadata
|
|
@@ -29,10 +29,7 @@ class DummyBuilder(Builder):
|
|
|
29
29
|
def get_target_uri(self, docname: str, typ: str | None = None) -> str:
|
|
30
30
|
return ''
|
|
31
31
|
|
|
32
|
-
def
|
|
33
|
-
pass
|
|
34
|
-
|
|
35
|
-
def write_doc(self, docname: str, doctree: Node) -> None:
|
|
32
|
+
def write_doc(self, docname: str, doctree: nodes.document) -> None:
|
|
36
33
|
pass
|
|
37
34
|
|
|
38
35
|
def finish(self) -> None:
|
sphinx/builders/epub3.py
CHANGED
|
@@ -21,6 +21,8 @@ from sphinx.util.fileutil import copy_asset_file
|
|
|
21
21
|
from sphinx.util.osutil import make_filename
|
|
22
22
|
|
|
23
23
|
if TYPE_CHECKING:
|
|
24
|
+
from collections.abc import Set
|
|
25
|
+
|
|
24
26
|
from sphinx.application import Sphinx
|
|
25
27
|
from sphinx.util.typing import ExtensionMetadata
|
|
26
28
|
|
|
@@ -47,7 +49,7 @@ THEME_WRITING_MODES = {
|
|
|
47
49
|
'horizontal': 'horizontal-tb',
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
DOCTYPE =
|
|
52
|
+
DOCTYPE = """<!DOCTYPE html>"""
|
|
51
53
|
|
|
52
54
|
HTML_TAG = (
|
|
53
55
|
'<html xmlns="http://www.w3.org/1999/xhtml" '
|
|
@@ -56,14 +58,14 @@ HTML_TAG = (
|
|
|
56
58
|
|
|
57
59
|
# https://www.w3.org/TR/REC-xml/#NT-Name
|
|
58
60
|
_xml_name_start_char = (
|
|
59
|
-
':|[A-Z]|_|[a-z]|[\
|
|
60
|
-
'|[\
|
|
61
|
-
'|[\
|
|
62
|
-
'|[\
|
|
63
|
-
'|[\
|
|
61
|
+
':|[A-Z]|_|[a-z]|[\u00c0-\u00d6]'
|
|
62
|
+
'|[\u00d8-\u00f6]|[\u00f8-\u02ff]|[\u0370-\u037d]'
|
|
63
|
+
'|[\u037f-\u1fff]|[\u200c-\u200d]|[\u2070-\u218f]'
|
|
64
|
+
'|[\u2c00-\u2fef]|[\u3001-\ud7ff]|[\uf900-\ufdcf]'
|
|
65
|
+
'|[\ufdf0-\ufffd]|[\U00010000-\U000effff]'
|
|
64
66
|
)
|
|
65
67
|
_xml_name_char = (
|
|
66
|
-
_xml_name_start_char + r'\-|\.' '|[0-9]|\
|
|
68
|
+
_xml_name_start_char + r'\-|\.' '|[0-9]|\u00b7|[\u0300-\u036f]|[\u203f-\u2040]'
|
|
67
69
|
)
|
|
68
70
|
_XML_NAME_PATTERN = re.compile(f'({_xml_name_start_char})({_xml_name_char})*')
|
|
69
71
|
|
|
@@ -111,14 +113,16 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
|
|
111
113
|
metadata = super().content_metadata()
|
|
112
114
|
metadata['description'] = html.escape(self.config.epub_description)
|
|
113
115
|
metadata['contributor'] = html.escape(self.config.epub_contributor)
|
|
114
|
-
metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(
|
|
116
|
+
metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(
|
|
117
|
+
writing_mode
|
|
118
|
+
)
|
|
115
119
|
metadata['ibook_scroll_axis'] = IBOOK_SCROLL_AXIS.get(writing_mode)
|
|
116
|
-
metadata['date'] = html.escape(time.strftime(
|
|
120
|
+
metadata['date'] = html.escape(time.strftime('%Y-%m-%dT%H:%M:%SZ', time_tuple))
|
|
117
121
|
metadata['version'] = html.escape(self.config.version)
|
|
118
122
|
metadata['epub_version'] = self.config.epub_version
|
|
119
123
|
return metadata
|
|
120
124
|
|
|
121
|
-
def prepare_writing(self, docnames:
|
|
125
|
+
def prepare_writing(self, docnames: Set[str]) -> None:
|
|
122
126
|
super().prepare_writing(docnames)
|
|
123
127
|
|
|
124
128
|
writing_mode = self.config.epub_writing_mode
|
|
@@ -186,8 +190,8 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
|
|
186
190
|
|
|
187
191
|
if self.config.epub_tocscope == 'default':
|
|
188
192
|
doctree = self.env.get_and_resolve_doctree(
|
|
189
|
-
self.config.root_doc, self,
|
|
190
|
-
|
|
193
|
+
self.config.root_doc, self, prune_toctrees=False, includehidden=False
|
|
194
|
+
)
|
|
191
195
|
refnodes = self.get_refnodes(doctree, [])
|
|
192
196
|
self.toc_add_files(refnodes)
|
|
193
197
|
else:
|
|
@@ -212,31 +216,47 @@ def validate_config_values(app: Sphinx) -> None:
|
|
|
212
216
|
|
|
213
217
|
# <package> lang attribute, dc:language
|
|
214
218
|
if not app.config.epub_language:
|
|
215
|
-
logger.warning(
|
|
216
|
-
|
|
219
|
+
logger.warning(
|
|
220
|
+
__(
|
|
221
|
+
'conf value "epub_language" (or "language") '
|
|
222
|
+
'should not be empty for EPUB3'
|
|
223
|
+
)
|
|
224
|
+
)
|
|
217
225
|
# <package> unique-identifier attribute
|
|
218
226
|
if not _XML_NAME_PATTERN.match(app.config.epub_uid):
|
|
219
227
|
logger.warning(__('conf value "epub_uid" should be XML NAME for EPUB3'))
|
|
220
228
|
# dc:title
|
|
221
229
|
if not app.config.epub_title:
|
|
222
|
-
logger.warning(
|
|
223
|
-
|
|
230
|
+
logger.warning(
|
|
231
|
+
__(
|
|
232
|
+
'conf value "epub_title" (or "html_title") '
|
|
233
|
+
'should not be empty for EPUB3'
|
|
234
|
+
)
|
|
235
|
+
)
|
|
224
236
|
# dc:creator
|
|
225
237
|
if not app.config.epub_author:
|
|
226
238
|
logger.warning(__('conf value "epub_author" should not be empty for EPUB3'))
|
|
227
239
|
# dc:contributor
|
|
228
240
|
if not app.config.epub_contributor:
|
|
229
|
-
logger.warning(
|
|
241
|
+
logger.warning(
|
|
242
|
+
__('conf value "epub_contributor" should not be empty for EPUB3')
|
|
243
|
+
)
|
|
230
244
|
# dc:description
|
|
231
245
|
if not app.config.epub_description:
|
|
232
|
-
logger.warning(
|
|
246
|
+
logger.warning(
|
|
247
|
+
__('conf value "epub_description" should not be empty for EPUB3')
|
|
248
|
+
)
|
|
233
249
|
# dc:publisher
|
|
234
250
|
if not app.config.epub_publisher:
|
|
235
251
|
logger.warning(__('conf value "epub_publisher" should not be empty for EPUB3'))
|
|
236
252
|
# dc:rights
|
|
237
253
|
if not app.config.epub_copyright:
|
|
238
|
-
logger.warning(
|
|
239
|
-
|
|
254
|
+
logger.warning(
|
|
255
|
+
__(
|
|
256
|
+
'conf value "epub_copyright" (or "copyright")'
|
|
257
|
+
'should not be empty for EPUB3'
|
|
258
|
+
)
|
|
259
|
+
)
|
|
240
260
|
# dc:identifier
|
|
241
261
|
if not app.config.epub_identifier:
|
|
242
262
|
logger.warning(__('conf value "epub_identifier" should not be empty for EPUB3'))
|
|
@@ -293,8 +313,9 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|
|
293
313
|
app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'epub')
|
|
294
314
|
app.add_config_value('epub_description', 'unknown', 'epub')
|
|
295
315
|
app.add_config_value('epub_contributor', 'unknown', 'epub')
|
|
296
|
-
app.add_config_value(
|
|
297
|
-
|
|
316
|
+
app.add_config_value(
|
|
317
|
+
'epub_writing_mode', 'horizontal', 'epub', ENUM('horizontal', 'vertical')
|
|
318
|
+
)
|
|
298
319
|
|
|
299
320
|
# event handlers
|
|
300
321
|
app.connect('config-inited', convert_epub_css_files, priority=800)
|