Merge branch 'master' into 5394_meaningful_annotations_for_mock

This commit is contained in:
Takeshi KOMIYA 2019-02-11 01:38:26 +09:00
commit 453ed5e29a
755 changed files with 134906 additions and 30381 deletions

View File

@ -35,7 +35,7 @@ test_script:
if (-not $tests) { $tests = '' } if (-not $tests) { $tests = '' }
& "C:\Python$($env:PYTHON)\python.exe" -m pytest $test_ignore.Split(' ') --junitxml .junit.xml $tests.Split(' ') & "C:\Python$($env:PYTHON)\python.exe" -m pytest $test_ignore.Split(' ') --junitxml .junit.xml $tests.Split(' ')
Pop-Location Pop-Location
if ($LastExitCode -eq 1) { Write-Host "Test Failures Occurred, leaving for test result parsing" } if ($LastExitCode -eq 1) { Write-Host "Test Failures Occurred, leaving for test result parsing"; exit $LastExitCode }
elseif ($LastExitCode -ne 0) { Write-Host "Other Error Occurred, aborting"; exit $LastExitCode } elseif ($LastExitCode -ne 0) { Write-Host "Other Error Occurred, aborting"; exit $LastExitCode }
after_test: after_test:

View File

@ -1,35 +0,0 @@
Subject: <what happen when you do on which document project>
<!--
Important: This is a list of issues for Sphinx, not a forum.
If you'd like to post a question, please move to sphinx-users group.
https://groups.google.com/forum/#!forum/sphinx-users
Thanks,
-->
### Problem
- <Detail of problem>
#### Procedure to reproduce the problem
```
<Paste your command-line here which cause the problem>
```
#### Error logs / results
```
<Paste your error log here>
```
- <public link of unexpected result if you have>
#### Expected results
<Describe what to actually do>
### Reproducible project / your project
- <link to your project, or attach zipped small project sample>
### Environment info
- OS: <Unix/Linux/Mac/Win/other with version>
- Python version:
- Sphinx version:
- <Extra tools e.g.: Browser, tex or something else>

46
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,46 @@
---
name: Bug report
about: Create a report to help us improve
title: '<what happen when you do on which document project>'
labels: 'bug'
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
```
<Paste your command-line here which cause the problem>
$ git clone htps://github.com/.../some_project
$ cd some_project
$ pip install -r requirements.txt
$ cd docs
$ make html SPHINXOPTS="-D language=de"
$ # open _build/html/index and see bla bla
```
**Expected behavior**
A clear and concise description of what you expected to happen.
**Your project**
Link to your sphinx project, or attach zipped small project sample.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment info**
- OS: [e.g. Unix/Linux/Mac/Win/other with version]
- Python version: [e.g. 3.7.1]
- Sphinx version: [e.g. 1.8.2]
- Sphinx extensions: [e.g. sphinx.ext.autodoc, recommonmark]
- Extra tools: [e.g. Browser, tex or something else]
**Additional context**
Add any other context about the problem here.
- [e.g. URL or Ticket]

View File

@ -0,0 +1,23 @@
---
name: Feature request
about: Suggest an idea for this project
title: '<short description for the feature>'
labels: 'enhancement'
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
- [e.g. URL or Ticket]

17
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@ -0,0 +1,17 @@
---
name: Question
about: For Q&A purpose, please use https://groups.google.com/forum/#!forum/sphinx-users
title: For Q&A purpose, please use sphinx-users group
labels: 'question'
assignees: ''
---
# Important
This is a list of issues for Sphinx, **not a forum**.
If you'd like to post a question, please move to sphinx-users group.
https://groups.google.com/forum/#!forum/sphinx-users
Thanks,

View File

@ -1,6 +1,6 @@
language: python language: python
sudo: false sudo: false
dist: trusty dist: xenial
cache: pip cache: pip
env: env:
@ -13,19 +13,16 @@ matrix:
include: include:
- python: '3.5' - python: '3.5'
env: env:
- TOXENV=du13 - TOXENV=du12
- python: '3.6' - python: '3.6'
env: env:
- TOXENV=py36 - TOXENV=du13
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
- python: '3.7' - python: '3.7'
env: TOXENV=py37 env:
dist: xenial - TOXENV=py37
sudo: true - PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
- python: 'nightly' - python: 'nightly'
env: TOXENV=py38 env: TOXENV=py38
dist: xenial
sudo: true
- python: '3.6' - python: '3.6'
env: TOXENV=docs env: TOXENV=docs
- python: '3.6' - python: '3.6'
@ -37,9 +34,7 @@ matrix:
node_js: node_js:
- 10.7 - 10.7
env: IS_PYTHON=false env: IS_PYTHON=false
before_script: services: xvfb
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
install: install:
- if [ $IS_PYTHON = true ]; then pip install -U tox codecov; fi - if [ $IS_PYTHON = true ]; then pip install -U tox codecov; fi

View File

@ -38,6 +38,7 @@ Other contributors, listed alphabetically, are:
* Zac Hatfield-Dodds -- doctest reporting improvements * Zac Hatfield-Dodds -- doctest reporting improvements
* Doug Hellmann -- graphviz improvements * Doug Hellmann -- graphviz improvements
* Tim Hoffmann -- theme improvements * Tim Hoffmann -- theme improvements
* Antti Kaihola -- doctest extension (skipif option)
* Dave Kuhlman -- original LaTeX writer * Dave Kuhlman -- original LaTeX writer
* Blaise Laflamme -- pyramid theme * Blaise Laflamme -- pyramid theme
* Chris Lamb -- reproducibility fixes * Chris Lamb -- reproducibility fixes
@ -56,6 +57,7 @@ Other contributors, listed alphabetically, are:
* Ezio Melotti -- collapsible sidebar JavaScript * Ezio Melotti -- collapsible sidebar JavaScript
* Bruce Mitchener -- Minor epub improvement * Bruce Mitchener -- Minor epub improvement
* Daniel Neuhäuser -- JavaScript domain, Python 3 support (GSOC) * Daniel Neuhäuser -- JavaScript domain, Python 3 support (GSOC)
* Julien Palard -- Colspan and rowspan in text builder
* Christopher Perkins -- autosummary integration * Christopher Perkins -- autosummary integration
* Benjamin Peterson -- unittests * Benjamin Peterson -- unittests
* \T. Powers -- HTML output improvements * \T. Powers -- HTML output improvements
@ -67,6 +69,7 @@ Other contributors, listed alphabetically, are:
* Antonio Valentino -- qthelp builder, docstring inheritance * Antonio Valentino -- qthelp builder, docstring inheritance
* Filip Vavera -- napoleon todo directive * Filip Vavera -- napoleon todo directive
* Pauli Virtanen -- autodoc improvements, autosummary extension * Pauli Virtanen -- autodoc improvements, autosummary extension
* Eric N. Vander Weele -- autodoc improvements
* Stefan van der Walt -- autosummary extension * Stefan van der Walt -- autosummary extension
* Thomas Waldmann -- apidoc module fixes * Thomas Waldmann -- apidoc module fixes
* John Waltman -- Texinfo builder * John Waltman -- Texinfo builder
@ -78,6 +81,7 @@ Other contributors, listed alphabetically, are:
* Hong Xu -- svg support in imgmath extension and various bug fixes * Hong Xu -- svg support in imgmath extension and various bug fixes
* Stephen Finucane -- setup command improvements and documentation * Stephen Finucane -- setup command improvements and documentation
* Daniel Pizetta -- inheritance diagram improvements * Daniel Pizetta -- inheritance diagram improvements
* KINEBUCHI Tomohiko -- typing Sphinx as well as docutils
Many thanks for all contributions! Many thanks for all contributions!

481
CHANGES
View File

@ -4,38 +4,211 @@ Release 2.0.0 (in development)
Dependencies Dependencies
------------ ------------
* LaTeX builder now depends on TeX Live 2015 or above * LaTeX builder now depends on TeX Live 2015 or above.
* LaTeX builder (with ``'pdflatex'`` :confval:`latex_engine`) will process
Unicode Greek letters in text (not in math mark-up) via the text font and
will not escape them to math mark-up. See the discussion of the
``'fontenc'`` key of :confval:`latex_elements`; such (optional) support for
Greek adds, for example on Ubuntu xenial, the ``texlive-lang-greek`` and (if
default font set-up is not modified) ``cm-super(-minimal)`` as additional
Sphinx LaTeX requirements.
* LaTeX builder with :confval:`latex_engine` set to ``'xelatex'`` or to
``'lualatex'`` requires (by default) the ``FreeFont`` fonts,
which in Ubuntu xenial are provided by package ``fonts-freefont-otf``, and
e.g. in Fedora 29 via package ``texlive-gnu-freefont``.
* requests 2.5.0 or above
* The six package is no longer a dependency
* The sphinxcontrib-websupport package is no longer a dependency
* Some packages are separated to sub packages:
- sphinxcontrib.applehelp
- sphinxcontrib.devhelp
- sphinxcontrib.jsmath
- sphinxcontrib.qthelp
Incompatible changes Incompatible changes
-------------------- --------------------
* Drop python 2.7 and 3.4 support * Drop python 2.7 and 3.4 support
* Drop docutils 0.11 support * Drop docutils 0.11 support
* The default setting for :confval:`master_doc` is changed to ``'index'`` which
has been longly used as default of sphinx-quickstart.
* LaTeX: Move message resources to ``sphinxmessage.sty``
* LaTeX: Stop using ``\captions<lang>`` macro for some labels
* LaTeX: for ``'xelatex'`` and ``'lualatex'``, use the ``FreeFont`` OpenType
fonts as default choice (refs: #5645)
* LaTeX: ``'xelatex'`` and ``'lualatex'`` now use ``\small`` in code-blocks
(due to ``FreeMono`` character width) like ``'pdflatex'`` already did (due
to ``Courier`` character width). You may need to adjust this via
:confval:`latex_elements` ``'fvset'`` key, in case of usage of some other
OpenType fonts (refs: #5768)
* LaTeX: Greek letters in text are not escaped to math mode mark-up, and they
will use the text font not the math font. The ``LGR`` font encoding must be
added to the ``'fontenc'`` key of :confval:`latex_elements` for this to work
(only if it is needed by the document, of course).
* LaTeX: setting the :confval:`language` to ``'en'`` triggered ``Sonny`` option
of ``fncychap``, now it is ``Bjarne`` to match case of no language specified.
(refs: #5772)
* #5770: doctest: Follow :confval:`highlight_language` on highlighting doctest
block. As a result, they are highlighted as python3 by default.
* The order of argument for ``HTMLTranslator``, ``HTML5Translator`` and
``ManualPageTranslator`` are changed
* LaTeX: hard-coded redefinitions of ``\l@section`` and ``\l@subsection``
formerly done during loading of ``'manual'`` docclass get executed later, at
time of ``\sphinxtableofcontents``. This means that custom user definitions
from LaTeX preamble now get overwritten. Use ``\sphinxtableofcontentshook``
to insert custom user definitions. See :ref:`latex-macros`.
* quickstart: Simplify generated ``conf.py``
* websupport: unbundled from sphinx core. Please use sphinxcontrib-websupport
* C++, the visibility of base classes is now always rendered as present in the
input. That is, ``private`` is now shown, where it was ellided before.
* LaTeX: graphics inclusion of oversized images rescales to not exceed
the text width and height, even if width and/or height option were used.
(refs: #5956)
* #4550: All tables and figures without ``align`` option are displayed to center
Deprecated Deprecated
---------- ----------
* Support for evaluating Python 2 syntax is deprecated. This includes
configuration files which should be converted to Python 3.
* The arguments of ``EpubBuilder.build_mimetype()``,
``EpubBuilder.build_container()``, ``EpubBuilder.bulid_content()``,
``EpubBuilder.build_toc()`` and ``EpubBuilder.build_epub()``
* The arguments of ``Epub3Builder.build_navigation_doc()``
* The ``encoding`` argument of ``autodoc.Documenter.get_doc()``,
``autodoc.DocstringSignatureMixin.get_doc()``,
``autodoc.DocstringSignatureMixin._find_signature()``, and
``autodoc.ClassDocumenter.get_doc()`` are deprecated.
* The ``importer`` argument of ``sphinx.ext.autodoc.importer._MockModule``
* The ``nodetype`` argument of ``sphinx.search.WordCollector.
is_meta_keywords()``
* The ``suffix`` argument of ``env.doc2path()`` is deprecated.
* The string style ``base`` argument of ``env.doc2path()`` is deprecated.
* The fallback to allow omitting the ``filename`` argument from an overridden
``IndexBuilder.feed()`` method is deprecated.
* ``sphinx.addnodes.abbreviation``
* ``sphinx.application.Sphinx._setting_up_extension``
* ``sphinx.builders.epub3.Epub3Builder.validate_config_value()``
* ``sphinx.builders.html.SingleFileHTMLBuilder``
* ``sphinx.builders.htmlhelp.HTMLHelpBuilder.open_file()``
* ``sphinx.cmd.quickstart.term_decode()``
* ``sphinx.cmd.quickstart.TERM_ENCODING``
* ``sphinx.config.check_unicode()``
* ``sphinx.config.string_classes``
* ``sphinx.domains.cpp.DefinitionError.description``
* ``sphinx.domains.cpp.NoOldIdError.description``
* ``sphinx.domains.cpp.UnsupportedMultiCharacterCharLiteral.decoded``
* ``sphinx.ext.autodoc.importer._MockImporter``
* ``sphinx.ext.autosummary.Autosummary.warn()``
* ``sphinx.ext.autosummary.Autosummary.genopt``
* ``sphinx.ext.autosummary.Autosummary.warnings``
* ``sphinx.ext.autosummary.Autosummary.result``
* ``sphinx.ext.doctest.doctest_encode()``
* ``sphinx.io.SphinxBaseFileInput``
* ``sphinx.io.SphinxFileInput.supported``
* ``sphinx.io.SphinxRSTFileInput``
* ``sphinx.registry.SphinxComponentRegistry.add_source_input()``
* ``sphinx.testing.util.remove_unicode_literal()``
* ``sphinx.util.attrdict``
* ``sphinx.util.force_decode()``
* ``sphinx.util.get_matching_docs()``
* ``sphinx.util.inspect.Parameter``
* ``sphinx.util.osutil.EEXIST``
* ``sphinx.util.osutil.EINVAL``
* ``sphinx.util.osutil.ENOENT``
* ``sphinx.util.osutil.EPIPE``
* ``sphinx.util.osutil.walk()``
* ``sphinx.util.PeekableIterator``
* ``sphinx.util.pycompat.TextIOWrapper``
* ``sphinx.util.pycompat.UnicodeMixin``
* ``sphinx.util.pycompat.htmlescape``
* ``sphinx.util.pycompat.indent``
* ``sphinx.util.pycompat.u``
* ``sphinx.writers.latex.ExtBabel``
* ``sphinx.writers.latex.LaTeXTranslator._make_visit_admonition()``
* ``sphinx.writers.latex.LaTeXTranslator.babel_defmacro()``
* ``sphinx.writers.latex.LaTeXTranslator.collect_footnotes()``
* ``sphinx.writers.latex.LaTeXTranslator.generate_numfig_format()``
* ``sphinx.writers.texinfo.TexinfoTranslator._make_visit_admonition()``
* ``sphinx.writers.text.TextTranslator._make_depart_admonition()``
* template variables for LaTeX template
- ``logo``
- ``numfig_format``
- ``pageautorefname``
- ``translatablestrings``
For more details, see :ref:`deprecation APIs list <dev-deprecated-apis>`.
Features added Features added
-------------- --------------
* #1618: The search results preview of generated HTML documentation is * #1618: The search results preview of generated HTML documentation is
reader-friendlier: instead of showing the snippets as raw reStructuredText reader-friendlier: instead of showing the snippets as raw reStructuredText
markup, Sphinx now renders the corresponding HTML. This means the Sphinx markup, Sphinx now renders the corresponding HTML. This means the Sphinx
extension `Sphinx: pretty search results`__ is no longer necessary. Note that extension `Sphinx: pretty search results`__ is no longer necessary. Note that
changes to the search function of your custom or 3rd-pary HTML template might changes to the search function of your custom or 3rd-party HTML template might
overwrite this improvement. overwrite this improvement.
__ https://github.com/sphinx-contrib/sphinx-pretty-searchresults __ https://github.com/sphinx-contrib/sphinx-pretty-searchresults
* #4182: autodoc: Support :confval:`suppress_warnings` * #4182: autodoc: Support :confval:`suppress_warnings`
* #5533: autodoc: :confval:`autodoc_default_options` supports ``member-order``
* #4018: htmlhelp: Add :confval:`htmlhelp_file_suffix` and
:confval:`htmlhelp_link_suffix`
* #5559: text: Support complex tables (colspan and rowspan)
* LaTeX: support rendering (not in math, yet) of Greek and Cyrillic Unicode
letters in non-Cyrillic document even with ``'pdflatex'`` as
:confval:`latex_engine` (refs: #5645)
* #5660: The ``versionadded``, ``versionchanged`` and ``deprecated`` directives
are now generated with their own specific CSS classes
(``added``, ``changed`` and ``deprecated``, respectively) in addition to the
generic ``versionmodified`` class.
* #5841: apidoc: Add --extensions option to sphinx-apidoc
* #4981: C++, added an alias directive for inserting lists of declarations,
that references existing declarations (e.g., for making a synopsis).
* C++: add ``cpp:struct`` to complement ``cpp:class``.
* #1341 the HTML search considers words that contain a search term of length
three or longer a match.
* #4611: epub: Show warning for duplicated ToC entries
* #1851: Allow to omit an argument for :rst:dir:`code-block` directive. If
omitted, it follows :rst:dir:`highlight` or :confval:`highlight_language`
* #6016: HTML search: A placeholder for the search summary prevents search
result links from changing their position when the search terminates. This
makes navigating search results easier.
Bugs fixed Bugs fixed
---------- ----------
* #1682: LaTeX: writer should not translate Greek unicode, but use textgreek
package
* #5247: LaTeX: PDF does not build with default font config for Russian
language and ``'xelatex'`` or ``'lualatex'`` as :confval:`latex_engine`
(refs: #5251)
* #5248: LaTeX: Greek letters in section titles disappear from PDF bookmarks
* #5249: LaTeX: Unicode Greek letters in math directive break PDF build
(fix requires extra set-up, see :confval:`latex_elements` ``'textgreek'`` key
and/or :confval:`latex_engine` setting)
* #5772: LaTeX: should the Bjarne style of fncychap be used for English also
if passed as language option?
* #5179: LaTeX: (lualatex only) escaping of ``>`` by ``\textgreater{}`` is not
enough as ``\textgreater{}\textgreater{}`` applies TeX-ligature
* LaTeX: project name is not escaped if :confval:`latex_documents` omitted
* LaTeX: authors are not shown if :confval:`latex_documents` omitted
* HTML: Invalid HTML5 file is generated for a glossary having multiple terms for
one description (refs: #4611)
* QtHelp: OS dependent path separator is used in .qhp file
* HTML search: search always returns nothing when multiple search terms are
used and one term is shorter than three characters
Testing Testing
-------- --------
Release 1.8.0 beta2 (in development) * Stop to use ``SPHINX_TEST_TEMPDIR`` envvar
====================================
Release 1.8.5 (in development)
==============================
Dependencies Dependencies
------------ ------------
@ -43,48 +216,174 @@ Dependencies
Incompatible changes Incompatible changes
-------------------- --------------------
* #5282: html theme: refer ``pygments_style`` settings of HTML themes
preferentially
Deprecated Deprecated
---------- ----------
* ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()`` is deprecated
* ``sphinx.io.SphinxI18nReader.line`` is deprecated
Features added Features added
-------------- --------------
Bugs fixed Bugs fixed
---------- ----------
* html: search box overrides to other elements if scrolled * LaTeX: Remove extraneous space after author names on PDF title page (refs: #6004)
* i18n: warnings for translation catalogs have wrong line numbers (refs: #5321)
* #5325: latex: cross references has been broken by multiply labeled objects
* C++, fixes for symbol addition and lookup. Lookup should no longer break
in partial builds. See also #5337.
* #5348: download reference to remote file is not displayed
* #5282: html theme: ``pygments_style`` of theme was overrided by ``conf.py``
by default
* #4379: toctree shows confusible warning when document is excluded
Testing Testing
-------- --------
Release 1.8.0 beta1 (in development) Release 1.8.4 (released Feb 03, 2019)
==================================== =====================================
Bugs fixed
----------
* #3707: latex: no bold checkmark (✔) available.
* #5605: with the documentation language set to Chinese, English words could not
be searched.
* #5889: LaTeX: user ``numfig_format`` is stripped of spaces and may cause
build failure
* C++, fix hyperlinks for declarations involving east cv-qualifiers.
* #5755: C++, fix duplicate declaration error on function templates with constraints
in the return type.
* C++, parse unary right fold expressions and binary fold expressions.
* pycode could not handle egg files on windows
* #5928: KeyError: 'DOCUTILSCONFIG' when running build
* #5936: LaTeX: PDF build broken by inclusion of image taller than page height
in an admonition
* #5231: "make html" does not read and build "po" files in "locale" dir
* #5954: ``:scale:`` image option may break PDF build if image in an admonition
* #5966: mathjax has not been loaded on incremental build
* #5960: LaTeX: modified PDF layout since September 2018 TeXLive update of
:file:`parskip.sty`
* #5948: LaTeX: duplicated labels are generated for sections
* #5958: versionadded directive causes crash with Python 3.5.0
* #5995: autodoc: autodoc_mock_imports conflict with metaclass on Python 3.7
* #5871: texinfo: a section title ``.`` is not allowed
Release 1.8.3 (released Dec 26, 2018)
=====================================
Features added
--------------
* LaTeX: it is possible to insert custom material to appear on back of title
page, see discussion of ``'maketitle'`` key of :confval:`latex_elements`
(``'manual'`` docclass only)
Bugs fixed
----------
* #5725: mathjax: Use CDN URL for "latest" version by default
* #5460: html search does not work with some 3rd party themes
* #5520: LaTeX, caption package incompatibility since Sphinx 1.6
* #5614: autodoc: incremental build is broken when builtin modules are imported
* #5627: qthelp: index.html missing in QtHelp
* #5659: linkcheck: crashes for a hyperlink containing multibyte character
* #5754: DOC: Fix some mistakes in :doc:`/latex`
* #5810: LaTeX: sphinxVerbatim requires explicit "hllines" set-up since 1.6.6
(refs: #1238)
* #5636: C++, fix parsing of floating point literals.
* #5496 (again): C++, fix assertion in partial builds with duplicates.
* #5724: quickstart: sphinx-quickstart fails when $LC_ALL is empty
* #1956: Default conf.py is not PEP8-compliant
* #5849: LaTeX: document class ``\maketitle`` is overwritten with no
possibility to use original meaning in place of Sphinx custom one
* #5834: apidoc: wrong help for ``--tocfile``
* #5800: todo: crashed if todo is defined in TextElement
* #5846: htmlhelp: convert hex escaping to decimal escaping in .hhc/.hhk files
* htmlhelp: broken .hhk file generated when title contains a double quote
Release 1.8.2 (released Nov 11, 2018)
=====================================
Incompatible changes
--------------------
* #5497: Do not include MathJax.js and jsmath.js unless it is really needed
Features added
--------------
* #5471: Show appropriate deprecation warnings
Bugs fixed
----------
* #5490: latex: enumerated list causes a crash with recommonmark
* #5492: sphinx-build fails to build docs w/ Python < 3.5.2
* #3704: latex: wrong ``\label`` positioning for figures with a legend
* #5496: C++, fix assertion when a symbol is declared more than twice.
* #5493: gettext: crashed with broken template
* #5495: csv-table directive with file option in included file is broken (refs:
#4821)
* #5498: autodoc: unable to find type hints for a ``functools.partial``
* #5480: autodoc: unable to find type hints for unresolvable Forward references
* #5419: incompatible math_block node has been generated
* #5548: Fix ensuredir() in case of pre-existing file
* #5549: graphviz Correctly deal with non-existing static dir
* #3002: i18n: multiple footnote_references referring same footnote cause
duplicated node_ids
* #5563: latex: footnote_references generated by extension causes a LaTeX
builder crash
* #5561: make all-pdf fails with old xindy version
* #5557: quickstart: --no-batchfile isn't honored
* #3080: texinfo: multiline rubrics are broken
* #3080: texinfo: multiline citations are broken
Release 1.8.1 (released Sep 22, 2018)
=====================================
Incompatible changes
--------------------
* LaTeX ``\pagestyle`` commands have been moved to the LaTeX template. No
changes in PDF, except possibly if ``\sphinxtableofcontents``, which
contained them, had been customized in :file:`conf.py`. (refs: #5455)
Bugs fixed
----------
* #5418: Incorrect default path for sphinx-build -d/doctrees files
* #5421: autodoc emits deprecation warning for :confval:`autodoc_default_flags`
* #5422: lambda object causes PicklingError on storing environment
* #5417: Sphinx fails to build with syntax error in Python 2.7.5
* #4911: add latexpdf to make.bat for non make-mode
* #5436: Autodoc does not work with enum subclasses with properties/methods
* #5437: autodoc: crashed on modules importing eggs
* #5433: latex: ImportError: cannot import name 'DEFAULT_SETTINGS'
* #5431: autodoc: ``autofunction`` emits a warning for callable objects
* #5457: Fix TypeError in error message when override is prohibited
* #5453: PDF builds of 'howto' documents have no page numbers
* #5463: mathbase: math_role and MathDirective was disappeared in 1.8.0
* #5454: latex: Index has disappeared from PDF for Japanese documents
* #5432: py domain: ``:type:`` field can't process ``:term:`` references
* #5426: py domain: TypeError has been raised for class attribute
Release 1.8.0 (released Sep 13, 2018)
=====================================
Dependencies Dependencies
------------ ------------
1.8.0b1
* LaTeX: :confval:`latex_use_xindy`, if ``True`` (default for * LaTeX: :confval:`latex_use_xindy`, if ``True`` (default for
``xelatex/lualatex``), instructs ``make latexpdf`` to use :program:`xindy` ``xelatex/lualatex``), instructs ``make latexpdf`` to use :program:`xindy`
for general index. Make sure your LaTeX distribution includes it. for general index. Make sure your LaTeX distribution includes it.
(refs: #5134) (refs: #5134)
* LaTeX: ``latexmk`` is required for ``make latexpdf`` on Windows
Incompatible changes Incompatible changes
-------------------- --------------------
1.8.0b2
* #5282: html theme: refer ``pygments_style`` settings of HTML themes
preferentially
* The URL of download files are changed
* #5127: quickstart: ``Makefile`` and ``make.bat`` are not overwritten if exists
1.8.0b1
* #5156: the :py:mod:`sphinx.ext.graphviz: extension runs `dot` in the * #5156: the :py:mod:`sphinx.ext.graphviz: extension runs `dot` in the
directory of the document being built instead of in the root directory of directory of the document being built instead of in the root directory of
the documentation. the documentation.
@ -104,8 +403,8 @@ Incompatible changes
:py:meth:`.Sphinx.add_transform()` :py:meth:`.Sphinx.add_transform()`
* #4827: All ``substitution_definition`` nodes are removed from doctree on * #4827: All ``substitution_definition`` nodes are removed from doctree on
reading phase reading phase
* ``docutils.conf`` on ``$HOME`` and ``/etc`` directories are ignored. Only * ``docutils.conf`` in ``$HOME`` or ``/etc`` directories are ignored. Only
``docutils.conf`` on confdir is refered. ``docutils.conf`` from confdir is obeyed.
* #789: ``:samp:`` role supports to escape curly braces with backslash * #789: ``:samp:`` role supports to escape curly braces with backslash
* #4811: The files under :confval:`html_static_path` are excluded from source * #4811: The files under :confval:`html_static_path` are excluded from source
files. files.
@ -126,8 +425,7 @@ Incompatible changes
before new build. before new build.
* #5163: html: hlist items are now aligned to top * #5163: html: hlist items are now aligned to top
* ``highlightlang`` directive is processed on resolving phase * ``highlightlang`` directive is processed on resolving phase
* #4000: latex: LaTeX template has been chaned. Following elements are moved * #4000: LaTeX: template changed. Following elements moved to it:
into the template:
- ``\begin{document}`` - ``\begin{document}``
- ``shorthandoff`` variable - ``shorthandoff`` variable
@ -137,11 +435,22 @@ Incompatible changes
Deprecated Deprecated
---------- ----------
1.8.0b2
* ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()`` is deprecated
* ``sphinx.io.SphinxI18nReader.line`` is deprecated
* ``sphinx.util.i18n.find_catalog_source_file()`` has changed; the
*gettext_compact* argument has been deprecated
* #5403: ``sphinx.util.images.guess_mimetype()`` has changed; the *content*
argument has been deprecated
1.8.0b1
* :confval:`source_parsers` is deprecated * :confval:`source_parsers` is deprecated
* :confval:`autodoc_default_flags` is deprecated * :confval:`autodoc_default_flags` is deprecated
* quickstart: ``--epub`` option becomes default, so it is deprecated * quickstart: ``--epub`` option becomes default, so it is deprecated
* Drop function based directive support. For now, Sphinx only supports class * Drop function based directive support. For now, Sphinx only supports class
based directives. based directives (see :class:`~Directive`)
* ``sphinx.util.docutils.directive_helper()`` is deprecated * ``sphinx.util.docutils.directive_helper()`` is deprecated
* ``sphinx.cmdline`` is deprecated * ``sphinx.cmdline`` is deprecated
* ``sphinx.make_mode`` is deprecated * ``sphinx.make_mode`` is deprecated
@ -202,6 +511,8 @@ Deprecated
* ``sphinx.ext.mathbase.eqref`` node is deprecated * ``sphinx.ext.mathbase.eqref`` node is deprecated
* ``sphinx.ext.mathbase.is_in_section_title()`` is deprecated * ``sphinx.ext.mathbase.is_in_section_title()`` is deprecated
* ``sphinx.ext.mathbase.MathDomain`` is deprecated * ``sphinx.ext.mathbase.MathDomain`` is deprecated
* ``sphinx.ext.mathbase.MathDirective`` is deprecated
* ``sphinx.ext.mathbase.math_role`` is deprecated
* ``sphinx.ext.mathbase.setup_math()`` is deprecated * ``sphinx.ext.mathbase.setup_math()`` is deprecated
* ``sphinx.directives.other.VersionChanges`` is deprecated * ``sphinx.directives.other.VersionChanges`` is deprecated
* ``sphinx.highlighting.PygmentsBridge.unhighlight()`` is deprecated * ``sphinx.highlighting.PygmentsBridge.unhighlight()`` is deprecated
@ -216,6 +527,13 @@ For more details, see `deprecation APIs list
Features added Features added
-------------- --------------
1.8.0b2
* #5388: Ensure frozen object descriptions are reproducible
* #5362: apidoc: Add ``--tocfile`` option to change the filename of ToC
1.8.0b1
* Add :event:`config-inited` event * Add :event:`config-inited` event
* Add ``sphinx.config.Any`` to represent the config value accepts any type of * Add ``sphinx.config.Any`` to represent the config value accepts any type of
value value
@ -290,6 +608,26 @@ Features added
Bugs fixed Bugs fixed
---------- ----------
1.8.0b2
* html: search box overrides to other elements if scrolled
* i18n: warnings for translation catalogs have wrong line numbers (refs: #5321)
* #5325: latex: cross references has been broken by multiply labeled objects
* C++, fixes for symbol addition and lookup. Lookup should no longer break
in partial builds. See also #5337.
* #5348: download reference to remote file is not displayed
* #5282: html theme: ``pygments_style`` of theme was overridden by ``conf.py``
by default
* #4379: toctree shows confusing warning when document is excluded
* #2401: autodoc: ``:members:`` causes ``:special-members:`` not to be shown
* autodoc: ImportError is replaced by AttributeError for deeper module
* #2720, #4034: Incorrect links with ``:download:``, duplicate names, and
parallel builds
* #5290: autodoc: failed to analyze source code in egg package
* #5399: Sphinx crashes if unknown po file exists
1.8.0b1
* i18n: message catalogs were reset on each initialization * i18n: message catalogs were reset on each initialization
* #4850: latex: footnote inside footnote was not rendered * #4850: latex: footnote inside footnote was not rendered
* #4945: i18n: fix lang_COUNTRY not fallback correctly for IndexBuilder. Thanks * #4945: i18n: fix lang_COUNTRY not fallback correctly for IndexBuilder. Thanks
@ -302,45 +640,25 @@ Bugs fixed
* #344: autosummary does not understand docstring of module level attributes * #344: autosummary does not understand docstring of module level attributes
* #5191: C++, prevent nested declarations in functions to avoid lookup problems. * #5191: C++, prevent nested declarations in functions to avoid lookup problems.
* #5126: C++, add missing isPack method for certain template parameter types. * #5126: C++, add missing isPack method for certain template parameter types.
* #5187: C++, parse attributes on declerators as well. * #5187: C++, parse attributes on declarators as well.
* C++, parse delete expressions and basic new expressions as well. * C++, parse delete expressions and basic new expressions as well.
* #5002: graphviz: SVGs do not adapt to the column width * #5002: graphviz: SVGs do not adapt to the column width
Testing
--------
Features removed Features removed
---------------- ----------------
1.8.0b1
* ``sphinx.ext.pngmath`` extension * ``sphinx.ext.pngmath`` extension
Documentation Documentation
------------- -------------
1.8.0b1
* #5083: Fix wrong make.bat option for internationalization. * #5083: Fix wrong make.bat option for internationalization.
* #5115: napoleon: add admonitions added by #4613 to the docs. * #5115: napoleon: add admonitions added by #4613 to the docs.
Release 1.7.10 (in development)
===============================
Dependencies
------------
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
Testing
--------
Release 1.7.9 (released Sep 05, 2018) Release 1.7.9 (released Sep 05, 2018)
===================================== =====================================
@ -447,7 +765,7 @@ Bugs fixed
* #4924: html search: Upper characters problem in any other languages * #4924: html search: Upper characters problem in any other languages
* #4932: apidoc: some subpackage is ignored if sibling subpackage contains a * #4932: apidoc: some subpackage is ignored if sibling subpackage contains a
module starting with underscore module starting with underscore
* #4863, #4938, #4939: i18n doesn't handle node.title correctly tat used for * #4863, #4938, #4939: i18n doesn't handle correctly node.title as used for
contents, topic, admonition, table and section. contents, topic, admonition, table and section.
* #4913: i18n: literal blocks in bullet list are not translated * #4913: i18n: literal blocks in bullet list are not translated
* #4962: C++, raised TypeError on duplicate declaration. * #4962: C++, raised TypeError on duplicate declaration.
@ -481,7 +799,7 @@ Bugs fixed
---------- ----------
* #4885, #4887: domains: Crashed with duplicated objects * #4885, #4887: domains: Crashed with duplicated objects
* #4889: latex: sphinx.writers.latex causes recusrive import * #4889: latex: sphinx.writers.latex causes recursive import
Release 1.7.3 (released Apr 23, 2018) Release 1.7.3 (released Apr 23, 2018)
===================================== =====================================
@ -612,7 +930,7 @@ Incompatible changes
mock them, please specify the name of ancestors explicitly. mock them, please specify the name of ancestors explicitly.
* #3620: html theme: move DOCUMENTATION_OPTIONS to independent JavaScript file * #3620: html theme: move DOCUMENTATION_OPTIONS to independent JavaScript file
(refs: #4295) (refs: #4295)
* #4246: Limit width of text body for all themes. Conifigurable via theme * #4246: Limit width of text body for all themes. Configurable via theme
options ``body_min_width`` and ``body_max_width``. options ``body_min_width`` and ``body_max_width``.
* #4771: apidoc: The ``exclude_patterns`` arguments are ignored if they are * #4771: apidoc: The ``exclude_patterns`` arguments are ignored if they are
placed just after command line options placed just after command line options
@ -768,7 +1086,7 @@ Bugs fixed
1.7.0b3 1.7.0b3
* #4019: inheritance_diagram AttributeError stoping make process * #4019: inheritance_diagram AttributeError stopping make process
* #4531: autosummary: methods are not treated as attributes * #4531: autosummary: methods are not treated as attributes
* #4538: autodoc: ``sphinx.ext.autodoc.Options`` has been moved * #4538: autodoc: ``sphinx.ext.autodoc.Options`` has been moved
* #4539: autodoc emits warnings for partialmethods * #4539: autodoc emits warnings for partialmethods
@ -801,7 +1119,7 @@ Bugs fixed
* #4434: pure numbers as link targets produce warning * #4434: pure numbers as link targets produce warning
* #4477: Build fails after building specific files * #4477: Build fails after building specific files
* #4449: apidoc: include "empty" packages that contain modules * #4449: apidoc: include "empty" packages that contain modules
* #3917: citation labels are tranformed to ellipsis * #3917: citation labels are transformed to ellipsis
* #4501: graphviz: epub3 validation error caused if graph is not clickable * #4501: graphviz: epub3 validation error caused if graph is not clickable
* #4514: graphviz: workaround for wrong map ID which graphviz generates * #4514: graphviz: workaround for wrong map ID which graphviz generates
* #4525: autosectionlabel does not support parallel build * #4525: autosectionlabel does not support parallel build
@ -1268,7 +1586,7 @@ Bugs fixed
* #3614: Sphinx crashes with requests-2.5.0 * #3614: Sphinx crashes with requests-2.5.0
* #3618: autodoc crashes with tupled arguments * #3618: autodoc crashes with tupled arguments
* #3664: No space after the bullet in items of a latex list produced by Sphinx * #3664: No space after the bullet in items of a latex list produced by Sphinx
* #3657: EPUB builder crashes if document startswith genindex exists * #3657: EPUB builder crashes if a document starting with genindex exists
* #3588: No compact (p tag) html output in the i18n document build even when * #3588: No compact (p tag) html output in the i18n document build even when
:confval:`html_compact_lists` is True. :confval:`html_compact_lists` is True.
* #3685: AttributeError when using 3rd party domains * #3685: AttributeError when using 3rd party domains
@ -1286,7 +1604,7 @@ Bugs fixed
---------- ----------
* #3597: python domain raises UnboundLocalError if invalid name given * #3597: python domain raises UnboundLocalError if invalid name given
* #3599: Move to new Mathjax CDN * #3599: Move to new MathJax CDN
Release 1.5.4 (released Apr 02, 2017) Release 1.5.4 (released Apr 02, 2017)
===================================== =====================================
@ -1449,7 +1767,7 @@ Incompatible changes
1.5a1 1.5a1
* latex, package fancybox is not longer a dependency of sphinx.sty * latex, package fancybox is not any longer a dependency of sphinx.sty
* Use ``'locales'`` as a default value of `locale_dirs` * Use ``'locales'`` as a default value of `locale_dirs`
* latex, package ifthen is not any longer a dependency of sphinx.sty * latex, package ifthen is not any longer a dependency of sphinx.sty
* latex, style file does not modify fancyvrb's Verbatim (also available as * latex, style file does not modify fancyvrb's Verbatim (also available as
@ -1472,7 +1790,7 @@ Incompatible changes
(ref: #2510, #2753) (ref: #2510, #2753)
* Internet Explorer 6-8, Opera 12.1x or Safari 5.1+ support is dropped * Internet Explorer 6-8, Opera 12.1x or Safari 5.1+ support is dropped
because jQuery version is updated from 1.11.0 to 3.1.0 (ref: #2634, #2773) because jQuery version is updated from 1.11.0 to 3.1.0 (ref: #2634, #2773)
* QtHelpBuilder doens't generate search page (ref: #2352) * QtHelpBuilder doesn't generate search page (ref: #2352)
* QtHelpBuilder uses ``nonav`` theme instead of default one * QtHelpBuilder uses ``nonav`` theme instead of default one
to improve readability. to improve readability.
* latex: To provide good default settings to Japanese documents, Sphinx uses * latex: To provide good default settings to Japanese documents, Sphinx uses
@ -1767,12 +2085,12 @@ Bugs fixed
* #2890: Quickstart should return an error consistently on all error conditions * #2890: Quickstart should return an error consistently on all error conditions
* #2870: flatten genindex columns' heights. * #2870: flatten genindex columns' heights.
* #2856: Search on generated HTML site doesnt find some symbols * #2856: Search on generated HTML site doesn't find some symbols
* #2882: Fall back to a GET request on 403 status in linkcheck * #2882: Fall back to a GET request on 403 status in linkcheck
* #2902: jsdump.loads fails to load search index if keywords starts with * #2902: jsdump.loads fails to load search index if keywords starts with
underscore underscore
* #2900: Fix epub content.opf: add auto generated orphan files to spine. * #2900: Fix epub content.opf: add auto generated orphan files to spine.
* #2899: Fix ``hasdoc()`` function in Jinja2 template. It can detect ``genindex``, ``search`` collectly. * #2899: Fix ``hasdoc()`` function in Jinja2 template. It will detect ``genindex``, ``search`` also.
* #2901: Fix epub result: skip creating links from image tags to original image files. * #2901: Fix epub result: skip creating links from image tags to original image files.
* #2917: inline code is hyphenated on HTML * #2917: inline code is hyphenated on HTML
* #1462: autosummary warns for namedtuple with attribute with trailing underscore * #1462: autosummary warns for namedtuple with attribute with trailing underscore
@ -1782,7 +2100,7 @@ Bugs fixed
paths are used in `intersphinx_mapping` paths are used in `intersphinx_mapping`
* #2931: code-block directive with same :caption: causes warning of duplicate * #2931: code-block directive with same :caption: causes warning of duplicate
target. Now `code-block` and `literalinclude` does not define hyperlink target. Now `code-block` and `literalinclude` does not define hyperlink
target using its caption automatially. target using its caption automatically.
* #2962: latex: missing label of longtable * #2962: latex: missing label of longtable
* #2968: autodoc: show-inheritance option breaks docstrings * #2968: autodoc: show-inheritance option breaks docstrings
@ -1808,7 +2126,7 @@ Bugs fixed
* #2778: Fix autodoc crashes if obj.__dict__ is a property method and raises exception * #2778: Fix autodoc crashes if obj.__dict__ is a property method and raises exception
* Fix duplicated toc in epub3 output. * Fix duplicated toc in epub3 output.
* #2775: Fix failing linkcheck with servers not supporting identidy encoding * #2775: Fix failing linkcheck with servers not supporting identity encoding
* #2833: Fix formatting instance annotations in ext.autodoc. * #2833: Fix formatting instance annotations in ext.autodoc.
* #1911: ``-D`` option of ``sphinx-build`` does not override the ``extensions`` variable * #1911: ``-D`` option of ``sphinx-build`` does not override the ``extensions`` variable
* #2789: `sphinx.ext.intersphinx` generates wrong hyperlinks if the inventory is given * #2789: `sphinx.ext.intersphinx` generates wrong hyperlinks if the inventory is given
@ -1875,7 +2193,7 @@ Release 1.4.4 (released Jun 12, 2016)
Bugs fixed Bugs fixed
---------- ----------
* #2630: Latex sphinx.sty Notice Enviroment formatting problem * #2630: latex: sphinx.sty notice environment formatting problem
* #2632: Warning directives fail in quote environment latex build * #2632: Warning directives fail in quote environment latex build
* #2633: Sphinx crashes with old styled indices * #2633: Sphinx crashes with old styled indices
* Fix a ``\begin{\minipage}`` typo in sphinx.sty from 1.4.2 (ref: 68becb1) * Fix a ``\begin{\minipage}`` typo in sphinx.sty from 1.4.2 (ref: 68becb1)
@ -1949,7 +2267,7 @@ Bugs fixed
* #1817, #2077: suppress pep8 warnings on conf.py generated by sphinx-quickstart * #1817, #2077: suppress pep8 warnings on conf.py generated by sphinx-quickstart
* #2407: building docs crash if document includes large data image URIs * #2407: building docs crash if document includes large data image URIs
* #2436: Sphinx does not check version by :confval:`needs_sphinx` if loading extensions failed * #2436: Sphinx does not check version by :confval:`needs_sphinx` if loading extensions failed
* #2397: Setup shorthandoff for turkish documents * #2397: Setup shorthandoff for Turkish documents
* #2447: VerbatimBorderColor wrongly used also for captions of PDF * #2447: VerbatimBorderColor wrongly used also for captions of PDF
* #2456: C++, fix crash related to document merging (e.g., singlehtml and Latex builders). * #2456: C++, fix crash related to document merging (e.g., singlehtml and Latex builders).
* #2446: latex(pdf) sets local tables of contents (or more generally topic * #2446: latex(pdf) sets local tables of contents (or more generally topic
@ -1986,7 +2304,7 @@ Bugs fixed
* #2576: ``sphinx.ext.imgmath`` crashes if subprocess raises error * #2576: ``sphinx.ext.imgmath`` crashes if subprocess raises error
* #2577: ``sphinx.ext.imgmath``: Invalid argument are passed to dvisvgm * #2577: ``sphinx.ext.imgmath``: Invalid argument are passed to dvisvgm
* #2556: Xapian search does not work with Python 3 * #2556: Xapian search does not work with Python 3
* #2581: The search doesn't work if language="es" (spanish) * #2581: The search doesn't work if language="es" (Spanish)
* #2382: Adjust spacing after abbreviations on figure numbers in LaTeX writer * #2382: Adjust spacing after abbreviations on figure numbers in LaTeX writer
* #2383: The generated footnote by `latex_show_urls` overflows lines * #2383: The generated footnote by `latex_show_urls` overflows lines
* #2497, #2552: The label of search button does not fit for the button itself * #2497, #2552: The label of search button does not fit for the button itself
@ -2062,7 +2380,7 @@ Incompatible changes
parsing is attempted to distinguish valid code. To get the old behavior back, parsing is attempted to distinguish valid code. To get the old behavior back,
add ``highlight_language = "python"`` to conf.py. add ``highlight_language = "python"`` to conf.py.
* `Locale Date Markup Language * `Locale Date Markup Language
<http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns>`_ like <https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns>`_ like
``"MMMM dd, YYYY"`` is default format for `today_fmt` and `html_last_updated_fmt`. ``"MMMM dd, YYYY"`` is default format for `today_fmt` and `html_last_updated_fmt`.
However strftime format like ``"%B %d, %Y"`` is also supported for backward However strftime format like ``"%B %d, %Y"`` is also supported for backward
compatibility until Sphinx-1.5. Later format will be disabled from Sphinx-1.5. compatibility until Sphinx-1.5. Later format will be disabled from Sphinx-1.5.
@ -2123,7 +2441,7 @@ Features added
* #1921: Support figure substitutions by :confval:`language` and :confval:`figure_language_filename` * #1921: Support figure substitutions by :confval:`language` and :confval:`figure_language_filename`
* #2245: Add ``latex_elements["passoptionstopackages"]`` option to call PassOptionsToPackages * #2245: Add ``latex_elements["passoptionstopackages"]`` option to call PassOptionsToPackages
in early stage of preambles. in early stage of preambles.
* #2340: Math extension: support alignment of multiple equations for MathJAX. * #2340: Math extension: support alignment of multiple equations for MathJax.
* #2338: Define ``\titleref`` macro to redefine the style of ``title-reference`` roles. * #2338: Define ``\titleref`` macro to redefine the style of ``title-reference`` roles.
* Define ``\menuselection`` and ``\accelerator`` macros to redefine the style of `menuselection` roles. * Define ``\menuselection`` and ``\accelerator`` macros to redefine the style of `menuselection` roles.
* Define ``\crossref`` macro to redefine the style of references * Define ``\crossref`` macro to redefine the style of references
@ -2162,7 +2480,7 @@ Bugs fixed
* The default highlight language is now ``default``. This means that source code * The default highlight language is now ``default``. This means that source code
is highlighted as Python 3 (which is mostly a superset of Python 2) if possible. is highlighted as Python 3 (which is mostly a superset of Python 2) if possible.
To get the old behavior back, add ``highlight_language = "python"`` to conf.py. To get the old behavior back, add ``highlight_language = "python"`` to conf.py.
* #2329: Refresh environment forcely if source directory has changed. * #2329: Refresh environment forcedly if source directory has changed.
* #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from * #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from
xcolor package xcolor package
* Fix the confval type checker emits warnings if unicode is given to confvals which expects string value * Fix the confval type checker emits warnings if unicode is given to confvals which expects string value
@ -2172,11 +2490,11 @@ Bugs fixed
* #2348: Move amsmath and amssymb to before fontpkg on LaTeX writer. * #2348: Move amsmath and amssymb to before fontpkg on LaTeX writer.
* #2368: Ignore emacs lock files like ``.#foo.rst`` by default. * #2368: Ignore emacs lock files like ``.#foo.rst`` by default.
* #2262: literal_block and its caption has been separated by pagebreak in LaTeX output. * #2262: literal_block and its caption has been separated by pagebreak in LaTeX output.
* #2319: Fix table counter is overrided by code-block's in LaTeX. Thanks to jfbu. * #2319: Fix table counter is overridden by code-block's in LaTeX. Thanks to jfbu.
* Fix unpack warning if combinated with 3rd party domain extensions. * Fix unpack warning if combined with 3rd party domain extensions.
* #1153: Fix figures in sidebar causes latex build error. * #1153: Fix figures in sidebar causes latex build error.
* #2358: Fix user-preamble could not override the tocdepth definition. * #2358: Fix user-preamble could not override the tocdepth definition.
* #2358: Redece tocdepth if ``part`` or ``chapter`` is used for top_sectionlevel. * #2358: Reduce tocdepth if ``part`` or ``chapter`` is used for top_sectionlevel.
* #2351: Fix footnote spacing * #2351: Fix footnote spacing
* #2363: Fix ``toctree()`` in templates generates broken links in SingleHTMLBuilder. * #2363: Fix ``toctree()`` in templates generates broken links in SingleHTMLBuilder.
* #2366: Fix empty hyperref is generated on toctree in HTML builder. * #2366: Fix empty hyperref is generated on toctree in HTML builder.
@ -2210,7 +2528,7 @@ Bugs fixed
* #2290: Fix ``sphinx.ext.mathbase`` use of amsfonts may break user choice of math fonts * #2290: Fix ``sphinx.ext.mathbase`` use of amsfonts may break user choice of math fonts
* #2324: Print a hint how to increase the recursion limit when it is hit. * #2324: Print a hint how to increase the recursion limit when it is hit.
* #1565, #2229: Revert new warning; the new warning will be triggered from version 1.4 on. * #1565, #2229: Revert new warning; the new warning will be triggered from version 1.4 on.
* #2329: Refresh environment forcely if source directory has changed. * #2329: Refresh environment forcedly if source directory has changed.
* #2019: Fix the domain objects in search result are not escaped * #2019: Fix the domain objects in search result are not escaped
Release 1.3.5 (released Jan 24, 2016) Release 1.3.5 (released Jan 24, 2016)
@ -2259,7 +2577,7 @@ Bugs fixed
* #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug * #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug
* #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters * #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters
* #2193: Fix shutil.SameFileError if source directory and destination directory are same * #2193: Fix shutil.SameFileError if source directory and destination directory are same
* #2178: Fix unparseable C++ cross-reference when referencing a function with :cpp:any: * #2178: Fix unparsable C++ cross-reference when referencing a function with :cpp:any:
* #2206: Fix Sphinx latex doc build failed due to a footnotes * #2206: Fix Sphinx latex doc build failed due to a footnotes
* #2201: Fix wrong table caption for tables with over 30 rows * #2201: Fix wrong table caption for tables with over 30 rows
* #2213: Set <blockquote> in the classic theme to fit with <p> * #2213: Set <blockquote> in the classic theme to fit with <p>
@ -2276,10 +2594,11 @@ Bugs fixed
* #1580: Fix paragraphs in longtable don't work in Latex output * #1580: Fix paragraphs in longtable don't work in Latex output
* #1366: Fix centered image not centered in latex * #1366: Fix centered image not centered in latex
* #1860: Fix man page using ``:samp:`` with braces - font doesn't reset * #1860: Fix man page using ``:samp:`` with braces - font doesn't reset
* #1610: Sphinx crashes in japanese indexing in some systems * #1610: Sphinx crashes in Japanese indexing in some systems
* Fix Sphinx crashes if mecab initialization failed * Fix Sphinx crashes if mecab initialization failed
* #2160: Fix broken TOC of PDFs if section includes an image * #2160: Fix broken TOC of PDFs if section includes an image
* #2172: Fix dysfunctional admonition \py@lightbox in sphinx.sty. Thanks to jfbu. * #2172: Fix dysfunctional admonition ``\py@lightbox`` in sphinx.sty. Thanks to
jfbu.
* #2198,#2205: ``make gettext`` generate broken msgid for definition lists. * #2198,#2205: ``make gettext`` generate broken msgid for definition lists.
* #2062: Escape characters in doctests are treated incorrectly with Python 2. * #2062: Escape characters in doctests are treated incorrectly with Python 2.
* #2225: Fix if the option does not begin with dash, linking is not performed * #2225: Fix if the option does not begin with dash, linking is not performed
@ -2436,7 +2755,7 @@ Bugs fixed
* #1753: C++, added missing support for more complex declarations. * #1753: C++, added missing support for more complex declarations.
* #1700: Add ``:caption:`` option for :rst:dir:`toctree`. * #1700: Add ``:caption:`` option for :rst:dir:`toctree`.
* #1742: ``:name:`` option is provided for :rst:dir:`toctree`, :rst:dir:`code-block` and * #1742: ``:name:`` option is provided for :rst:dir:`toctree`, :rst:dir:`code-block` and
:rst:dir:`literalinclude` dirctives. :rst:dir:`literalinclude` directives.
* #1756: Incorrect section titles in search that was introduced from 1.3b3. * #1756: Incorrect section titles in search that was introduced from 1.3b3.
* #1746: C++, fixed name lookup procedure, and added missing lookups in declarations. * #1746: C++, fixed name lookup procedure, and added missing lookups in declarations.
* #1765: C++, fix old id generation to use fully qualified names. * #1765: C++, fix old id generation to use fully qualified names.
@ -2444,7 +2763,7 @@ Bugs fixed
Documentation Documentation
------------- -------------
* #1651: Add ``vartype`` field descritpion for python domain. * #1651: Add ``vartype`` field description for python domain.
Release 1.3b3 (released Feb 24, 2015) Release 1.3b3 (released Feb 24, 2015)
@ -2644,7 +2963,7 @@ Features added
the order of documents before they are read by the environment. the order of documents before they are read by the environment.
* #1284: Program options documented with :rst:dir:`option` can now start with * #1284: Program options documented with :rst:dir:`option` can now start with
``+``. ``+``.
* PR#291: The caption of :rst:dir:`code-block` is recognised as a title of ref * PR#291: The caption of :rst:dir:`code-block` is recognized as a title of ref
target. Thanks to Takeshi Komiya. target. Thanks to Takeshi Komiya.
* PR#298: Add new API: :meth:`~sphinx.application.Sphinx.add_latex_package`. * PR#298: Add new API: :meth:`~sphinx.application.Sphinx.add_latex_package`.
Thanks to Takeshi Komiya. Thanks to Takeshi Komiya.

View File

@ -61,8 +61,8 @@ of the core developers before it is merged into the main repository.
#. If you feel uncomfortable or uncertain about an issue or your changes, feel #. If you feel uncomfortable or uncertain about an issue or your changes, feel
free to email the *sphinx-dev* mailing list. free to email the *sphinx-dev* mailing list.
#. Fork `the repository`_ on GitHub to start making your changes to the #. Fork `the repository`_ on GitHub to start making your changes to the
``master`` branch for next major version, or ``X.Y`` branch for next ``master`` branch for next MAJOR version, or ``X.Y`` branch for next
minor version (see `Branch Model`_). MINOR version (see `Branch Model`_).
#. Write a test which shows that the bug was fixed or that the feature works #. Write a test which shows that the bug was fixed or that the feature works
as expected. as expected.
#. Send a pull request and bug the maintainer until it gets merged and #. Send a pull request and bug the maintainer until it gets merged and
@ -91,14 +91,19 @@ These are the basic steps needed to start developing on Sphinx.
#. Checkout the appropriate branch. #. Checkout the appropriate branch.
For changes that should be included in the next minor release (namely bug Sphinx adopts Semantic Versioning 2.0.0 (refs: https://semver.org/ ).
fixes), use the ``X.Y`` branch. ::
For changes that preserves backwards-compatibility of API and features,
they should be included in the next MINOR release, use the ``X.Y`` branch.
::
git checkout X.Y git checkout X.Y
For new features or other substantial changes that should wait until the For incompatible or other substantial changes that should wait until the
next major release, use the ``master`` branch (see `Branch Model`_ for next MAJOR release, use the ``master`` branch.
detail).
For urgent release, a new PATCH branch must be branched from the newest
release tag (see `Branch Model`_ for detail).
#. Setup a virtual environment. #. Setup a virtual environment.
@ -272,10 +277,7 @@ Coding Guide
generated output. generated output.
* When adding a new configuration variable, be sure to document it and update * When adding a new configuration variable, be sure to document it and update
:file:`sphinx/quickstart.py` if it's important enough. :file:`sphinx/cmd/quickstart.py` if it's important enough.
* Use the included :program:`utils/check_sources.py` script to check for
common formatting issues (trailing whitespace, lengthy lines, etc).
* Add appropriate unit tests. * Add appropriate unit tests.
@ -315,18 +317,32 @@ Debugging Tips
Branch Model Branch Model
------------ ------------
Sphinx project uses following branches for developing. Sphinx project uses following branches for developing that conforms to Semantic
Versioning 2.0.0 (refs: https://semver.org/ ).
``master`` ``master``
Used for main development. All improvement and refactoring, bug fixes Development for MAJOR version.
are allowed. All changes including incompatible behaviors and public API updates are
allowed.
``X.Y`` ``X.Y``
Where ``X.Y`` is the ``MAJOR.MINOR`` release. Used to maintain current Where ``X.Y`` is the ``MAJOR.MINOR`` release. Used to maintain current
stable release. Only bug fixes and stable changes are allowed. Only the MINOR release. All changes are allowed if the change preserves
most recent stable release is currently retained. When a new version is backwards-compatibility of API and features.
released, the old release branch will be deleted and replaced by an
equivalent tag. Only the most recent ``MAJOR.MINOR`` branch is currently retained. When a
new MAJOR version is released, the old ``MAJOR.MINOR`` branch will be
deleted and replaced by an equivalent tag.
``X.Y.Z``
Where ``X.Y.Z`` is the ``MAJOR.MINOR.PATCH`` release. Only
backwards-compatible bug fixes are allowed. In Sphinx project, PATCH
version is used for urgent bug fix.
``MAJOR.MINOR.PATCH`` branch will be branched from the ``v`` prefixed
release tag (ex. make 2.3.1 that branched from v2.3.0) when a urgent
release is needed. When new PATCH version is released, the branch will be
deleted and replaced by an equivalent tag (ex. v2.3.1).
Deprecating a feature Deprecating a feature
@ -359,23 +375,22 @@ silence any warnings generated when running the tests.
Deprecation policy Deprecation policy
------------------ ------------------
A feature release may deprecate certain features from previous releases. If a MAJOR and MINOR releases may deprecate certain features from previous
feature is deprecated in feature release 1.A, it will continue to work in all releases. If a feature is deprecated in a release A.x, it will continue to
1.A.x versions (for all versions of x) but raise warnings. Deprecated features work in all A.x.x versions (for all versions of x). It will continue to work
will be removed in the first 1.B release, or 1.B.1 for features deprecated in in all B.x.x versions but raise deprecation warnings. Deprecated features
the last 1.A.x feature release to ensure deprecations are done over at least 2 will be removed at the C.0.0. It means the deprecated feature will work during
feature releases. 2 MAJOR releases at least.
So, for example, if we decided to start the deprecation of a function in So, for example, if we decided to start the deprecation of a function in
Sphinx 1.4: Sphinx 2.x:
* Sphinx 1.4.x will contain a backwards-compatible replica of the function * Sphinx 2.x will contain a backwards-compatible replica of the function
which will raise a ``RemovedInSphinx16Warning``. which will raise a ``RemovedInSphinx40Warning``.
* Sphinx 1.5 (the version that follows 1.4) will still contain the * Sphinx 3.x will still contain the backwards-compatible replica.
backwards-compatible replica.
* Sphinx 1.6 will remove the feature outright. * Sphinx 4.0 will remove the feature outright.
The warnings are displayed by default. You can turn off display of these The warnings are displayed by default. You can turn off display of these
warnings with: warnings with:

135
EXAMPLES
View File

@ -18,16 +18,18 @@ Documentation using the alabaster theme
* `Click <http://click.pocoo.org/>`__ (customized) * `Click <http://click.pocoo.org/>`__ (customized)
* `coala <https://docs.coala.io/>`__ (customized) * `coala <https://docs.coala.io/>`__ (customized)
* `CodePy <https://documen.tician.de/codepy/>`__ * `CodePy <https://documen.tician.de/codepy/>`__
* `Fabric <http://docs.fabfile.org/>`__ * `Eve <https://docs.python-eve.org/>`__ (Python REST API framework)
* `Fityk <http://fityk.nieto.pl/>`__ * `Fabric <https://docs.fabfile.org/>`__
* `Fityk <https://fityk.nieto.pl/>`__
* `Flask <http://flask.pocoo.org/docs/>`__ * `Flask <http://flask.pocoo.org/docs/>`__
* `Flask-OpenID <https://pythonhosted.org/Flask-OpenID/>`__ * `Flask-OpenID <https://pythonhosted.org/Flask-OpenID/>`__
* `Invoke <http://docs.pyinvoke.org/>`__ * `Invoke <https://docs.pyinvoke.org/>`__
* `Jinja <http://jinja.pocoo.org/docs/>`__ * `Jinja <http://jinja.pocoo.org/docs/>`__
* `Lino <http://www.lino-framework.org/>`__ (customized) * `Lino <http://www.lino-framework.org/>`__ (customized)
* `marbl <https://getmarbl.readthedocs.io/>`__ * `marbl <https://getmarbl.readthedocs.io/>`__
* `MDAnalysis <http://www.mdanalysis.org/docs/>`__ (customized) * `MDAnalysis <https://www.mdanalysis.org/docs/>`__ (customized)
* `MeshPy <https://documen.tician.de/meshpy/>`__ * `MeshPy <https://documen.tician.de/meshpy/>`__
* `Molecule <https://molecule.readthedocs.io/>`__
* `PyCUDA <https://documen.tician.de/pycuda/>`__ * `PyCUDA <https://documen.tician.de/pycuda/>`__
* `PyOpenCL <https://documen.tician.de/pyopencl/>`__ * `PyOpenCL <https://documen.tician.de/pyopencl/>`__
* `PyLangAcq <http://pylangacq.org/>`__ * `PyLangAcq <http://pylangacq.org/>`__
@ -54,27 +56,29 @@ Documentation using the classic theme
* `Bugzilla <https://bugzilla.readthedocs.io/>`__ * `Bugzilla <https://bugzilla.readthedocs.io/>`__
* `Buildbot <https://docs.buildbot.net/latest/>`__ * `Buildbot <https://docs.buildbot.net/latest/>`__
* `CMake <https://cmake.org/documentation/>`__ (customized) * `CMake <https://cmake.org/documentation/>`__ (customized)
* `Chaco <http://docs.enthought.com/chaco/>`__ (customized) * `Chaco <https://docs.enthought.com/chaco/>`__ (customized)
* `CORE <https://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/>`__
* `CORE Python modules <https://downloads.pf.itd.nrl.navy.mil/docs/core/core-python-html/>`__
* `Cormoran <http://cormoran.nhopkg.org/docs/>`__ * `Cormoran <http://cormoran.nhopkg.org/docs/>`__
* `DEAP <https://deap.readthedocs.io/>`__ (customized) * `DEAP <https://deap.readthedocs.io/>`__ (customized)
* `Director <https://pythonhosted.org/director/>`__ * `Director <https://pythonhosted.org/director/>`__
* `EZ-Draw <https://pageperso.lif.univ-mrs.fr/~edouard.thiel/ez-draw/doc/en/html/ez-manual.html>`__ (customized) * `EZ-Draw <https://pageperso.lif.univ-mrs.fr/~edouard.thiel/ez-draw/doc/en/html/ez-manual.html>`__ (customized)
* `F2py <http://f2py.sourceforge.net/docs/>`__ * `F2py <http://f2py.sourceforge.net/docs/>`__
* `Generic Mapping Tools (GMT) <http://gmt.soest.hawaii.edu/doc/latest/>`__ (customized) * `Generic Mapping Tools (GMT) <https://gmt.soest.hawaii.edu/doc/latest/>`__ (customized)
* `Genomedata <https://noble.gs.washington.edu/proj/genomedata/doc/1.3.3/>`__ * `Genomedata <https://noble.gs.washington.edu/proj/genomedata/doc/1.3.3/>`__
* `GetFEM++ <http://getfem.org/>`__ (customized) * `GetFEM++ <http://getfem.org/>`__ (customized)
* `Glasgow Haskell Compiler <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/>`__ (customized) * `Glasgow Haskell Compiler <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/>`__ (customized)
* `Grok <http://grok.zope.org/doc/current/>`__ (customized) * `Grok <http://grok.zope.org/doc/current/>`__ (customized)
* `GROMACS <http://manual.gromacs.org/documentation/>`__ * `GROMACS <http://manual.gromacs.org/documentation/>`__
* `GSL Shell <http://www.nongnu.org/gsl-shell/>`__ * `GSL Shell <https://www.nongnu.org/gsl-shell/>`__
* `Hands-on Python Tutorial <http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/>`__ * `Hands-on Python Tutorial <https://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/>`__
* `Kaa <http://api.freevo.org/kaa-base/>`__ (customized) * `Kaa <https://api.freevo.org/kaa-base/>`__ (customized)
* `Leo <http://leoeditor.com/>`__ * `Leo <https://leoeditor.com/>`__
* `LEPL <http://www.acooke.org/lepl/>`__ (customized) * `LEPL <http://www.acooke.org/lepl/>`__ (customized)
* `Mayavi <http://docs.enthought.com/mayavi/mayavi/>`__ (customized) * `Mayavi <https://docs.enthought.com/mayavi/mayavi/>`__ (customized)
* `MediaGoblin <https://mediagoblin.readthedocs.io/>`__ (customized) * `MediaGoblin <https://mediagoblin.readthedocs.io/>`__ (customized)
* `mpmath <http://mpmath.org/doc/current/>`__ * `mpmath <http://mpmath.org/doc/current/>`__
* `OpenCV <http://docs.opencv.org/>`__ (customized) * `OpenCV <https://docs.opencv.org/>`__ (customized)
* `OpenEXR <http://excamera.com/articles/26/doc/index.html>`__ * `OpenEXR <http://excamera.com/articles/26/doc/index.html>`__
* `OpenGDA <http://www.opengda.org/gdadoc/html/>`__ * `OpenGDA <http://www.opengda.org/gdadoc/html/>`__
* `Peach^3 <https://peach3.nl/doc/latest/userdoc/>`__ (customized) * `Peach^3 <https://peach3.nl/doc/latest/userdoc/>`__ (customized)
@ -90,32 +94,34 @@ Documentation using the classic theme
* `Python Packaging Authority <https://www.pypa.io/>`__ (customized) * `Python Packaging Authority <https://www.pypa.io/>`__ (customized)
* `Ring programming language <http://ring-lang.sourceforge.net/doc/>`__ (customized) * `Ring programming language <http://ring-lang.sourceforge.net/doc/>`__ (customized)
* `SageMath <https://doc.sagemath.org/>`__ (customized) * `SageMath <https://doc.sagemath.org/>`__ (customized)
* `Segway <http://noble.gs.washington.edu/proj/segway/doc/1.1.0/segway.html>`__ * `Segway <https://noble.gs.washington.edu/proj/segway/doc/1.1.0/segway.html>`__
* `simuPOP <http://simupop.sourceforge.net/manual_release/build/userGuide.html>`__ (customized) * `simuPOP <http://simupop.sourceforge.net/manual_release/build/userGuide.html>`__ (customized)
* `Sprox <http://sprox.org/>`__ (customized) * `Sprox <http://sprox.org/>`__ (customized)
* `SymPy <http://docs.sympy.org/>`__ * `SymPy <https://docs.sympy.org/>`__
* `TurboGears <https://turbogears.readthedocs.io/>`__ (customized) * `TurboGears <https://turbogears.readthedocs.io/>`__ (customized)
* `tvtk <http://docs.enthought.com/mayavi/tvtk/>`__ * `tvtk <https://docs.enthought.com/mayavi/tvtk/>`__
* `Varnish <https://www.varnish-cache.org/docs/>`__ (customized, alabaster for index) * `Varnish <https://www.varnish-cache.org/docs/>`__ (customized, alabaster for index)
* `Waf <https://waf.io/apidocs/>`__ * `Waf <https://waf.io/apidocs/>`__
* `wxPython Phoenix <https://wxpython.org/Phoenix/docs/html/main.html>`__ (customized * `wxPython Phoenix <https://wxpython.org/Phoenix/docs/html/main.html>`__ (customized)
* `z3c <http://www.ibiblio.org/paulcarduner/z3ctutorial/>`__ * `Yum <http://yum.baseurl.org/api/yum/>`__
* `z3c <https://www.ibiblio.org/paulcarduner/z3ctutorial/>`__
* `zc.async <https://pythonhosted.org/zc.async/>`__ (customized) * `zc.async <https://pythonhosted.org/zc.async/>`__ (customized)
* `Zope <https://docs.zope.org/zope2/>`__ (customized) * `Zope <https://docs.zope.org/zope2/>`__ (customized)
Documentation using the sphinxdoc theme Documentation using the sphinxdoc theme
--------------------------------------- ---------------------------------------
* `cartopy <http://scitools.org.uk/cartopy/docs/latest/>`__ * `ABRT <https://abrt.readthedocs.io/>`__
* `cartopy <https://scitools.org.uk/cartopy/docs/latest/>`__
* `Jython <http://www.jython.org/docs/>`__ * `Jython <http://www.jython.org/docs/>`__
* `Matplotlib <https://matplotlib.org/>`__ * `Matplotlib <https://matplotlib.org/>`__
* `MDAnalysis Tutorial <http://www.mdanalysis.org/MDAnalysisTutorial/>`__ * `MDAnalysis Tutorial <https://www.mdanalysis.org/MDAnalysisTutorial/>`__
* `NetworkX <https://networkx.github.io/>`__ * `NetworkX <https://networkx.github.io/>`__
* `PyCantonese <http://pycantonese.org/>`__ * `PyCantonese <http://pycantonese.org/>`__
* `Pyre <http://docs.danse.us/pyre/sphinx/>`__ * `Pyre <http://docs.danse.us/pyre/sphinx/>`__
* `pySPACE <https://pyspace.github.io/pyspace/>`__ * `pySPACE <https://pyspace.github.io/pyspace/>`__
* `Pysparse <http://pysparse.sourceforge.net/>`__ * `Pysparse <http://pysparse.sourceforge.net/>`__
* `PyTango <http://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/pytango/latest/>`__ * `PyTango <https://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/pytango/latest/>`__
* `Python Wild Magic <https://vmlaker.github.io/pythonwildmagic/>`__ (customized) * `Python Wild Magic <https://vmlaker.github.io/pythonwildmagic/>`__ (customized)
* `Reteisi <http://www.reteisi.org/contents.html>`__ (customized) * `Reteisi <http://www.reteisi.org/contents.html>`__ (customized)
* `Sqlkit <http://sqlkit.argolinux.org/>`__ (customized) * `Sqlkit <http://sqlkit.argolinux.org/>`__ (customized)
@ -130,12 +136,12 @@ Documentation using the nature theme
* `jsFiddle <http://doc.jsfiddle.net/>`__ * `jsFiddle <http://doc.jsfiddle.net/>`__
* `libLAS <https://www.liblas.org/>`__ (customized) * `libLAS <https://www.liblas.org/>`__ (customized)
* `Lmod <https://lmod.readthedocs.io/>`__ * `Lmod <https://lmod.readthedocs.io/>`__
* `MapServer <http://mapserver.org/>`__ (customized) * `MapServer <https://mapserver.org/>`__ (customized)
* `Pandas <https://pandas.pydata.org/pandas-docs/stable/>`__ * `Pandas <https://pandas.pydata.org/pandas-docs/stable/>`__
* `pyglet <https://pyglet.readthedocs.io/>`__ (customized) * `pyglet <https://pyglet.readthedocs.io/>`__ (customized)
* `Setuptools <https://setuptools.readthedocs.io/>`__ * `Setuptools <https://setuptools.readthedocs.io/>`__
* `Spring Python <https://docs.spring.io/spring-python/1.2.x/sphinx/html/>`__ * `Spring Python <https://docs.spring.io/spring-python/1.2.x/sphinx/html/>`__
* `StatsModels <http://www.statsmodels.org/>`__ (customized) * `StatsModels <https://www.statsmodels.org/>`__ (customized)
* `Sylli <http://sylli.sourceforge.net/>`__ * `Sylli <http://sylli.sourceforge.net/>`__
Documentation using another builtin theme Documentation using another builtin theme
@ -143,13 +149,13 @@ Documentation using another builtin theme
* `Breathe <https://breathe.readthedocs.io/>`__ (haiku) * `Breathe <https://breathe.readthedocs.io/>`__ (haiku)
* `MPipe <https://vmlaker.github.io/mpipe/>`__ (sphinx13) * `MPipe <https://vmlaker.github.io/mpipe/>`__ (sphinx13)
* `NLTK <http://www.nltk.org/>`__ (agogo) * `NLTK <https://www.nltk.org/>`__ (agogo)
* `Programmieren mit PyGTK und Glade (German) <http://www.florian-diesch.de/doc/python-und-glade/online/>`__ (agogo, customized) * `Programmieren mit PyGTK und Glade (German) <https://www.florian-diesch.de/doc/python-und-glade/online/>`__ (agogo, customized)
* `PyPubSub <https://pypubsub.readthedocs.io/>`__ (bizstyle) * `PyPubSub <https://pypubsub.readthedocs.io/>`__ (bizstyle)
* `Pylons <http://docs.pylonsproject.org/projects/pylons-webframework/>`__ (pyramid) * `Pylons <https://docs.pylonsproject.org/projects/pylons-webframework/>`__ (pyramid)
* `Pyramid web framework <https://docs.pylonsproject.org/projects/pyramid/>`__ (pyramid) * `Pyramid web framework <https://docs.pylonsproject.org/projects/pyramid/>`__ (pyramid)
* `Sphinx <http://www.sphinx-doc.org/>`__ (sphinx13) :-) * `Sphinx <http://www.sphinx-doc.org/>`__ (sphinx13) :-)
* `Valence <http://docs.valence.desire2learn.com/>`__ (haiku, customized) * `Valence <https://docs.valence.desire2learn.com/>`__ (haiku, customized)
Documentation using sphinx_rtd_theme Documentation using sphinx_rtd_theme
------------------------------------ ------------------------------------
@ -165,21 +171,28 @@ Documentation using sphinx_rtd_theme
* `bootstrap-datepicker <https://bootstrap-datepicker.readthedocs.io/>`__ * `bootstrap-datepicker <https://bootstrap-datepicker.readthedocs.io/>`__
* `Certbot <https://letsencrypt.readthedocs.io/>`__ * `Certbot <https://letsencrypt.readthedocs.io/>`__
* `Chainer <https://docs.chainer.org/>`__ (customized) * `Chainer <https://docs.chainer.org/>`__ (customized)
* `CherryPy <http://docs.cherrypy.org/>`__ * `CherryPy <https://docs.cherrypy.org/>`__
* `cloud-init <https://cloudinit.readthedocs.io/>`__
* `CodeIgniter <https://www.codeigniter.com/user_guide/>`__ * `CodeIgniter <https://www.codeigniter.com/user_guide/>`__
* `Conda <https://conda.io/docs/>`__ * `Conda <https://conda.io/docs/>`__
* `Corda <https://docs.corda.net/>`__ * `Corda <https://docs.corda.net/>`__
* `Dask <https://dask.pydata.org/>`__ * `Dask <https://dask.pydata.org/>`__
* `Databricks <https://docs.databricks.com/>`__ (customized) * `Databricks <https://docs.databricks.com/>`__ (customized)
* `Dataiku DSS <https://doc.dataiku.com/>`__ * `Dataiku DSS <https://doc.dataiku.com/>`__
* `edX <http://docs.edx.org/>`__ * `DNF <https://dnf.readthedocs.io/>`__
* `edX <https://docs.edx.org/>`__
* `Electrum <http://docs.electrum.org/>`__ * `Electrum <http://docs.electrum.org/>`__
* `Elemental <http://libelemental.org/documentation/dev/>`__ * `Elemental <http://libelemental.org/documentation/dev/>`__
* `ESWP3 <https://eswp3.readthedocs.io/>`__ * `ESWP3 <https://eswp3.readthedocs.io/>`__
* `Ethereum Homestead <http://www.ethdocs.org/>`__ * `Ethereum Homestead <http://www.ethdocs.org/>`__
* `Faker <https://faker.readthedocs.io/>`__
* `Fidimag <https://fidimag.readthedocs.io/>`__ * `Fidimag <https://fidimag.readthedocs.io/>`__
* `Flake8 <http://flake8.pycqa.org/>`__ * `Flake8 <http://flake8.pycqa.org/>`__
* `Flatpak <http://docs.flatpak.org/>`__
* `FluidDyn <https://fluiddyn.readthedocs.io/>`__
* `Fluidsim <https://fluidsim.readthedocs.io/>`__
* `GeoNode <http://docs.geonode.org/>`__ * `GeoNode <http://docs.geonode.org/>`__
* `Glances <https://glances.readthedocs.io/>`__
* `Godot <https://godot.readthedocs.io/>`__ * `Godot <https://godot.readthedocs.io/>`__
* `Graylog <http://docs.graylog.org/>`__ * `Graylog <http://docs.graylog.org/>`__
* `GPAW <https://wiki.fysik.dtu.dk/gpaw/>`__ (customized) * `GPAW <https://wiki.fysik.dtu.dk/gpaw/>`__ (customized)
@ -217,6 +230,7 @@ Documentation using sphinx_rtd_theme
* `Phinx <http://docs.phinx.org/>`__ * `Phinx <http://docs.phinx.org/>`__
* `phpMyAdmin <https://docs.phpmyadmin.net/>`__ * `phpMyAdmin <https://docs.phpmyadmin.net/>`__
* `PROS <https://pros.cs.purdue.edu/v5/>`__ (customized) * `PROS <https://pros.cs.purdue.edu/v5/>`__ (customized)
* `Pushkin <http://docs.pushkin.io/>`__
* `Pweave <http://mpastell.com/pweave/>`__ * `Pweave <http://mpastell.com/pweave/>`__
* `PyPy <http://doc.pypy.org/>`__ * `PyPy <http://doc.pypy.org/>`__
* `python-sqlparse <https://sqlparse.readthedocs.io/>`__ * `python-sqlparse <https://sqlparse.readthedocs.io/>`__
@ -228,36 +242,42 @@ Documentation using sphinx_rtd_theme
* `Quex <http://quex.sourceforge.net/doc/html/main.html>`__ * `Quex <http://quex.sourceforge.net/doc/html/main.html>`__
* `Satchmo <http://docs.satchmoproject.com/>`__ * `Satchmo <http://docs.satchmoproject.com/>`__
* `Scapy <https://scapy.readthedocs.io/>`__ * `Scapy <https://scapy.readthedocs.io/>`__
* `SimPy <http://simpy.readthedocs.io/>`__ * `SimGrid <http://simgrid.gforge.inria.fr/simgrid/latest/doc/>`__
* `SlamData <http://docs.slamdata.com/>`__ * `SimPy <https://simpy.readthedocs.io/>`__
* `six <https://six.readthedocs.io/>`__
* `SlamData <https://newdocs.slamdata.com>`__
* `Solidity <https://solidity.readthedocs.io/>`__ * `Solidity <https://solidity.readthedocs.io/>`__
* `Sonos Controller (SoCo) <http://docs.python-soco.com/>`__ * `Sonos Controller (SoCo) <http://docs.python-soco.com/>`__
* `Sphinx AutoAPI <https://sphinx-autoapi.readthedocs.io/>`__ * `Sphinx AutoAPI <https://sphinx-autoapi.readthedocs.io/>`__
* `sphinx-argparse <https://sphinx-argparse.readthedocs.io/>`__ * `sphinx-argparse <https://sphinx-argparse.readthedocs.io/>`__
* `Sphinx-Gallery <https://sphinx-gallery.readthedocs.io/>`__ (customized) * `Sphinx-Gallery <https://sphinx-gallery.readthedocs.io/>`__ (customized)
* `SpotBugs <https://spotbugs.readthedocs.io/>`__ * `SpotBugs <https://spotbugs.readthedocs.io/>`__
* `StarUML <http://docs.staruml.io/>`__ * `StarUML <https://docs.staruml.io/>`__
* `Sublime Text Unofficial Documentation <http://docs.sublimetext.info/>`__ * `Sublime Text Unofficial Documentation <http://docs.sublimetext.info/>`__
* `SunPy <http://docs.sunpy.org/>`__ * `SunPy <https://docs.sunpy.org/>`__
* `Sylius <http://docs.sylius.org/>`__ * `Sylius <http://docs.sylius.org/>`__
* `Syncthing <https://docs.syncthing.net/>`__
* `Tango Controls <https://tango-controls.readthedocs.io/>`__ (customized) * `Tango Controls <https://tango-controls.readthedocs.io/>`__ (customized)
* `Topshelf <http://docs.topshelf-project.com/>`__ * `Topshelf <http://docs.topshelf-project.com/>`__
* `Theano <http://www.deeplearning.net/software/theano/>`__ * `Theano <http://www.deeplearning.net/software/theano/>`__
* `ThreatConnect <https://docs.threatconnect.com/>`__ * `ThreatConnect <https://docs.threatconnect.com/>`__
* `Tuleap <https://tuleap.net/doc/en/>`__ * `Tuleap <https://tuleap.net/doc/en/>`__
* `TYPO3 <https://docs.typo3.org/>`__ (customized) * `TYPO3 <https://docs.typo3.org/>`__ (customized)
* `Veyon <https://docs.veyon.io/>`__
* `uWSGI <https://uwsgi-docs.readthedocs.io/>`__ * `uWSGI <https://uwsgi-docs.readthedocs.io/>`__
* `Wagtail <http://docs.wagtail.io/>`__ * `virtualenv <https://virtualenv.readthedocs.io/>`__
* `Wagtail <https://docs.wagtail.io/>`__
* `Web Application Attack and Audit Framework (w3af) <http://docs.w3af.org/>`__ * `Web Application Attack and Audit Framework (w3af) <http://docs.w3af.org/>`__
* `Weblate <https://docs.weblate.org/>`__ * `Weblate <https://docs.weblate.org/>`__
* `x265 <https://x265.readthedocs.io/>`__ * `x265 <https://x265.readthedocs.io/>`__
* `ZeroNet <https://zeronet.readthedocs.io/>`__ * `ZeroNet <https://zeronet.readthedocs.io/>`__
* `Zulip <https://zulip.readthedocs.io/>`__
Documentation using sphinx_bootstrap_theme Documentation using sphinx_bootstrap_theme
------------------------------------------ ------------------------------------------
* `Bootstrap Theme <https://ryan-roemer.github.io/sphinx-bootstrap-theme/>`__ * `Bootstrap Theme <https://ryan-roemer.github.io/sphinx-bootstrap-theme/>`__
* `C/C++ Software Development with Eclipse <http://eclipsebook.in/>`__ * `C/C++ Software Development with Eclipse <https://eclipsebook.in/>`__
* `Dataverse <http://guides.dataverse.org/>`__ * `Dataverse <http://guides.dataverse.org/>`__
* `e-cidadania <https://e-cidadania.readthedocs.io/>`__ * `e-cidadania <https://e-cidadania.readthedocs.io/>`__
* `Hangfire <http://docs.hangfire.io/>`__ * `Hangfire <http://docs.hangfire.io/>`__
@ -279,36 +299,37 @@ Documentation using a custom theme or integrated in a website
* `CasperJS <http://docs.casperjs.org/>`__ * `CasperJS <http://docs.casperjs.org/>`__
* `Ceph <http://docs.ceph.com/docs/master/>`__ * `Ceph <http://docs.ceph.com/docs/master/>`__
* `Chef <https://docs.chef.io/>`__ * `Chef <https://docs.chef.io/>`__
* `CKAN <http://docs.ckan.org/>`__ * `CKAN <https://docs.ckan.org/>`__
* `Confluent Platform <http://docs.confluent.io/>`__ * `Confluent Platform <https://docs.confluent.io/>`__
* `Django <https://docs.djangoproject.com/>`__ * `Django <https://docs.djangoproject.com/>`__
* `Doctrine <http://docs.doctrine-project.org/>`__ * `Doctrine <https://www.doctrine-project.org/>`__
* `Enterprise Toolkit for Acrobat products <https://www.adobe.com/devnet-docs/acrobatetk/>`__ * `Enterprise Toolkit for Acrobat products <https://www.adobe.com/devnet-docs/acrobatetk/>`__
* `Gameduino <http://excamera.com/sphinx/gameduino/>`__ * `Gameduino <http://excamera.com/sphinx/gameduino/>`__
* `gensim <https://radimrehurek.com/gensim/>`__ * `gensim <https://radimrehurek.com/gensim/>`__
* `GeoServer <http://docs.geoserver.org/>`__ * `GeoServer <http://docs.geoserver.org/>`__
* `gevent <http://www.gevent.org/>`__ * `gevent <http://www.gevent.org/>`__
* `GHC - Glasgow Haskell Compiler <http://downloads.haskell.org/~ghc/master/users-guide/>`__ * `GHC - Glasgow Haskell Compiler <https://downloads.haskell.org/~ghc/master/users-guide/>`__
* `Guzzle <http://docs.guzzlephp.org/en/stable/>`__ * `Guzzle <http://docs.guzzlephp.org/>`__
* `H2O.ai <http://docs.h2o.ai/>`__ * `H2O.ai <http://docs.h2o.ai/>`__
* `Heka <https://hekad.readthedocs.io/>`__
* `Istihza (Turkish Python documentation project) <https://belgeler.yazbel.com/python-istihza/>`__ * `Istihza (Turkish Python documentation project) <https://belgeler.yazbel.com/python-istihza/>`__
* `Kombu <http://docs.kombu.me/>`__ * `Kombu <http://docs.kombu.me/>`__
* `Lasso <http://lassoguide.com/>`__ * `Lasso <http://lassoguide.com/>`__
* `Mako <http://docs.makotemplates.org/>`__ * `Mako <http://docs.makotemplates.org/>`__
* `MirrorBrain <http://mirrorbrain.org/docs/>`__ * `MirrorBrain <http://mirrorbrain.org/docs/>`__
* `MongoDB <https://docs.mongodb.com/>`__ * `MongoDB <https://docs.mongodb.com/>`__
* `Music21 <http://web.mit.edu/music21/doc/>`__ * `Music21 <https://web.mit.edu/music21/doc/>`__
* `MyHDL <http://docs.myhdl.org/en/latest/>`__ * `MyHDL <http://docs.myhdl.org/>`__
* `nose <https://nose.readthedocs.io/>`__ * `nose <https://nose.readthedocs.io/>`__
* `ns-3 <https://www.nsnam.org/documentation/>`__ * `ns-3 <https://www.nsnam.org/documentation/>`__
* `NumPy <https://docs.scipy.org/doc/numpy/reference/>`__ * `NumPy <https://docs.scipy.org/doc/numpy/reference/>`__
* `ObjectListView <http://objectlistview.sourceforge.net/python/>`__ * `ObjectListView <http://objectlistview.sourceforge.net/python/>`__
* `OpenERP <https://doc.odoo.com/>`__ * `OpenERP <https://doc.odoo.com/>`__
* `OpenCV <http://docs.opencv.org/>`__ * `OpenCV <https://docs.opencv.org/>`__
* `OpenLayers <http://docs.openlayers.org/>`__ * `OpenLayers <http://docs.openlayers.org/>`__
* `OpenTURNS <http://openturns.github.io/openturns/master/>`__ * `OpenTURNS <https://openturns.github.io/openturns/master/>`__
* `Open vSwitch <http://docs.openvswitch.org/>`__ * `Open vSwitch <http://docs.openvswitch.org/>`__
* `PlatformIO <http://docs.platformio.org/>`__ * `PlatformIO <https://docs.platformio.org/>`__
* `PyEphem <http://rhodesmill.org/pyephem/>`__ * `PyEphem <http://rhodesmill.org/pyephem/>`__
* `Pygments <http://pygments.org/docs/>`__ * `Pygments <http://pygments.org/docs/>`__
* `Plone User Manual (German) <https://www.hasecke.com/plone-benutzerhandbuch/4.0/>`__ * `Plone User Manual (German) <https://www.hasecke.com/plone-benutzerhandbuch/4.0/>`__
@ -316,20 +337,20 @@ Documentation using a custom theme or integrated in a website
* `PyMOTW <https://pymotw.com/2/>`__ * `PyMOTW <https://pymotw.com/2/>`__
* `python-aspectlib <https://python-aspectlib.readthedocs.io/>`__ (`sphinx_py3doc_enhanced_theme <https://pypi.org/project/sphinx_py3doc_enhanced_theme/>`__) * `python-aspectlib <https://python-aspectlib.readthedocs.io/>`__ (`sphinx_py3doc_enhanced_theme <https://pypi.org/project/sphinx_py3doc_enhanced_theme/>`__)
* `QGIS <https://qgis.org/en/docs/index.html>`__ * `QGIS <https://qgis.org/en/docs/index.html>`__
* `qooxdoo <http://www.qooxdoo.org/current/>`__ * `qooxdoo <https://www.qooxdoo.org/current/>`__
* `Roundup <http://www.roundup-tracker.org/>`__ * `Roundup <http://www.roundup-tracker.org/>`__
* `SaltStack <https://docs.saltstack.com/>`__ * `SaltStack <https://docs.saltstack.com/>`__
* `scikit-learn <http://scikit-learn.org/stable/>`__ * `scikit-learn <http://scikit-learn.org/stable/>`__
* `SciPy <https://docs.scipy.org/doc/scipy/refrence/>`__ * `SciPy <https://docs.scipy.org/doc/scipy/refrence/>`__
* `Scrapy <https://doc.scrapy.org/>`__ * `Scrapy <https://doc.scrapy.org/>`__
* `Seaborn <https://seaborn.pydata.org/>`__ * `Seaborn <https://seaborn.pydata.org/>`__
* `Selenium <http://docs.seleniumhq.org/docs/>`__ * `Selenium <https://docs.seleniumhq.org/docs/>`__
* `Self <http://www.selflanguage.org/>`__ * `Self <http://www.selflanguage.org/>`__
* `Substance D <https://docs.pylonsproject.org/projects/substanced/>`__ * `Substance D <https://docs.pylonsproject.org/projects/substanced/>`__
* `Sulu <http://docs.sulu.io/>`__ * `Sulu <http://docs.sulu.io/>`__
* `SQLAlchemy <https://docs.sqlalchemy.org/>`__ * `SQLAlchemy <https://docs.sqlalchemy.org/>`__
* `tinyTiM <http://tinytim.sourceforge.net/docs/2.0/>`__ * `tinyTiM <http://tinytim.sourceforge.net/docs/2.0/>`__
* `Twisted <http://twistedmatrix.com/documents/current/>`__ * `Twisted <https://twistedmatrix.com/documents/current/>`__
* `Ubuntu Packaging Guide <http://packaging.ubuntu.com/html/>`__ * `Ubuntu Packaging Guide <http://packaging.ubuntu.com/html/>`__
* `WebFaction <https://docs.webfaction.com/>`__ * `WebFaction <https://docs.webfaction.com/>`__
* `WTForms <https://wtforms.readthedocs.io/>`__ * `WTForms <https://wtforms.readthedocs.io/>`__
@ -341,32 +362,44 @@ Homepages and other non-documentation sites
* `Benoit Boissinot <https://bboissin.appspot.com/>`__ (classic, customized) * `Benoit Boissinot <https://bboissin.appspot.com/>`__ (classic, customized)
* `Computer Networks, Parallelization, and Simulation Laboratory (CNPSLab) <https://lab.miletic.net/>`__ (sphinx_rtd_theme) * `Computer Networks, Parallelization, and Simulation Laboratory (CNPSLab) <https://lab.miletic.net/>`__ (sphinx_rtd_theme)
* `Deep Learning Tutorials <http://www.deeplearning.net/tutorial/>`__ (sphinxdoc) * `Deep Learning Tutorials <http://www.deeplearning.net/tutorial/>`__ (sphinxdoc)
* `Loyola University Chicago COMP 339-439 Distributed Systems course <http://books.cs.luc.edu/distributedsystems/>`__ (sphinx_bootstrap_theme) * `Eric Holscher <http://ericholscher.com/>`__ (alabaster)
* `Lei Ma's Statistical Mechanics lecture notes <http://statisticalphysics.openmetric.org/>`__ (sphinx_bootstrap_theme)
* `Loyola University Chicago COMP 339-439 Distributed Systems course <https://books.cs.luc.edu/distributedsystems/>`__ (sphinx_bootstrap_theme)
* `Pylearn2 <http://www.deeplearning.net/software/pylearn2/>`__ (sphinxdoc, customized) * `Pylearn2 <http://www.deeplearning.net/software/pylearn2/>`__ (sphinxdoc, customized)
* `PyXLL <https://www.pyxll.com/>`__ (sphinx_bootstrap_theme, customized) * `PyXLL <https://www.pyxll.com/>`__ (sphinx_bootstrap_theme, customized)
* `SciPy Cookbook <https://scipy-cookbook.readthedocs.io/>`__ (sphinx_rtd_theme) * `SciPy Cookbook <https://scipy-cookbook.readthedocs.io/>`__ (sphinx_rtd_theme)
* `The Wine Cellar Book <https://www.thewinecellarbook.com/doc/en/>`__ (sphinxdoc) * `The Wine Cellar Book <https://www.thewinecellarbook.com/doc/en/>`__ (sphinxdoc)
* `Thomas Cokelaer's Python, Sphinx and reStructuredText tutorials <http://thomas-cokelaer.info/tutorials/>`__ (standard) * `Thomas Cokelaer's Python, Sphinx and reStructuredText tutorials <https://thomas-cokelaer.info/tutorials/>`__ (standard)
* `UC Berkeley ME233 Advanced Control Systems II course <https://berkeley-me233.github.io/>`__ (sphinxdoc) * `UC Berkeley ME233 Advanced Control Systems II course <https://berkeley-me233.github.io/>`__ (sphinxdoc)
* `Željko Svedružić's Biomolecular Structure and Function Laboratory (BioSFLab) <https://www.svedruziclab.com/>`__ (sphinx_bootstrap_theme)
Books produced using Sphinx Books produced using Sphinx
--------------------------- ---------------------------
* `"The Art of Community" (Japanese translation) <https://www.oreilly.co.jp/books/9784873114958/>`__
* `"Die Wahrheit des Sehens. Der DEKALOG von Krzysztof Kieślowski" <https://literatur.hasecke.com/post/die-wahrheit-des-sehens-dekalog-kieslowski/>`__ * `"Die Wahrheit des Sehens. Der DEKALOG von Krzysztof Kieślowski" <https://literatur.hasecke.com/post/die-wahrheit-des-sehens-dekalog-kieslowski/>`__
* `"Expert Python Programming" <https://www.packtpub.com/application-development/expert-python-programming>`__ * `"Expert Python Programming" <https://www.packtpub.com/application-development/expert-python-programming>`__
* `"Expert Python Programming" (Japanese translation) <https://www.amazon.co.jp/dp/4048686291/>`__ * `"Expert Python Programming" (Japanese translation) <https://www.amazon.co.jp/dp/4048686291/>`__
* `"The Hitchhiker's Guide to Python" <http://docs.python-guide.org/en/latest/>`__ * `"Expert Python Programming 2nd Edition" (Japanese translation) <https://www.amazon.co.jp/dp/4048930613/>`__
* `"The Hitchhiker's Guide to Python" <https://docs.python-guide.org/>`__
* `"LassoGuide" <http://www.lassosoft.com/Lasso-Documentation>`__ * `"LassoGuide" <http://www.lassosoft.com/Lasso-Documentation>`__
* `"Learning Sphinx" (in Japanese) <https://www.oreilly.co.jp/books/9784873116488/>`__ * `"Learning Sphinx" (in Japanese) <https://www.oreilly.co.jp/books/9784873116488/>`__
* `"Learning System Programming with Go (Japanese)" <https://www.lambdanote.com/products/go>`__
* `"Mercurial: the definitive guide (Second edition)" <https://book.mercurial-scm.org/>`__ * `"Mercurial: the definitive guide (Second edition)" <https://book.mercurial-scm.org/>`__
* `"Mithril -- The fastest clientside MVC (Japanese)" <https://www.oreilly.co.jp/books/9784873117447/>`__
* `"Pioneers and Prominent Men of Utah" <http://pioneers.rstebbing.com/>`__ * `"Pioneers and Prominent Men of Utah" <http://pioneers.rstebbing.com/>`__
* `"Pomodoro Technique Illustrated" (Japanese translation) <https://www.amazon.co.jp/dp/4048689525/>`__ * `"Pomodoro Technique Illustrated" (Japanese translation) <https://www.amazon.co.jp/dp/4048689525/>`__
* `"Professional Software Development" <https://mixmastamyk.bitbucket.io/pro_soft_dev/>`__
* `"Python Professional Programming" (in Japanese) <http://www.amazon.co.jp/dp/4798032948/>`__ * `"Python Professional Programming" (in Japanese) <http://www.amazon.co.jp/dp/4798032948/>`__
* `"Python Professional Programming 2nd Edition" (in Japanese) <https://www.amazon.co.jp/dp/479804315X/>`__
* `"Python Professional Programming 3rd Edition" (in Japanese) <https://www.amazon.co.jp/dp/4798053821/>`__
* `"Real World HTTP -- Learning The Internet and Web Technology via its history and code (Japanese)" <https://www.oreilly.co.jp/books/9784873118048/>`__
* `"Redmine Primer 5th Edition (in Japanese)" <https://www.shuwasystem.co.jp/products/7980html/4825.html>`__ * `"Redmine Primer 5th Edition (in Japanese)" <https://www.shuwasystem.co.jp/products/7980html/4825.html>`__
* `"The repoze.bfg Web Application Framework" <https://www.amazon.com/repoze-bfg-Web-Application-Framework-Version/dp/0615345379>`__ * `"The repoze.bfg Web Application Framework" <https://www.amazon.com/repoze-bfg-Web-Application-Framework-Version/dp/0615345379>`__
* `"The Self-Taught Programmer" (Japanese translation) <https://www.amazon.co.jp/dp/4822292274/>`__
* `"Simple and Steady Way of Learning for Software Engineering" (in Japanese) <https://www.amazon.co.jp/dp/477414259X/>`__ * `"Simple and Steady Way of Learning for Software Engineering" (in Japanese) <https://www.amazon.co.jp/dp/477414259X/>`__
* `"Software-Dokumentation mit Sphinx" <https://www.amazon.de/dp/1497448689/>`__ * `"Software-Dokumentation mit Sphinx" <https://www.amazon.de/dp/1497448689/>`__
* `"Theoretical Physics Reference" <http://www.theoretical-physics.net/>`__ * `"Theoretical Physics Reference" <https://www.theoretical-physics.net/>`__
* `"The Varnish Book" <https://info.varnish-software.com/the-varnish-book>`__ * `"The Varnish Book" <https://info.varnish-software.com/the-varnish-book>`__
Theses produced using Sphinx Theses produced using Sphinx

View File

@ -1,7 +1,7 @@
License for Sphinx License for Sphinx
================== ==================
Copyright (c) 2007-2018 by the Sphinx team (see AUTHORS file). Copyright (c) 2007-2019 by the Sphinx team (see AUTHORS file).
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View File

@ -57,7 +57,7 @@ style-check:
.PHONY: type-check .PHONY: type-check
type-check: type-check:
mypy sphinx/ mypy sphinx
.PHONY: pylint .PHONY: pylint
pylint: pylint:

View File

@ -4,7 +4,7 @@
.. image:: https://img.shields.io/pypi/v/sphinx.svg .. image:: https://img.shields.io/pypi/v/sphinx.svg
:target: https://pypi.org/project/Sphinx/ :target: https://pypi.org/project/Sphinx/
:alt: Package on PyPi :alt: Package on PyPI
.. image:: https://readthedocs.org/projects/sphinx/badge/?version=master .. image:: https://readthedocs.org/projects/sphinx/badge/?version=master
:target: http://www.sphinx-doc.org/ :target: http://www.sphinx-doc.org/

View File

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
#
# test documentation build configuration file, created by # test documentation build configuration file, created by
# sphinx-quickstart on Sun Jun 26 00:00:43 2016. # sphinx-quickstart on Sun Jun 26 00:00:43 2016.
# #

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View File

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -4,7 +4,7 @@
Sphinx layout template for the sphinxdoc theme. Sphinx layout template for the sphinxdoc theme.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
#} #}
{%- extends "basic/layout.html" %} {%- extends "basic/layout.html" %}

View File

@ -4,7 +4,7 @@
* *
* Sphinx stylesheet -- sphinx13 theme. * Sphinx stylesheet -- sphinx13 theme.
* *
* :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details. * :license: BSD, see LICENSE for details.
* *
*/ */

View File

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
#
# Sphinx documentation build configuration file # Sphinx documentation build configuration file
import re import re
@ -16,7 +14,7 @@ templates_path = ['_templates']
exclude_patterns = ['_build'] exclude_patterns = ['_build']
project = 'Sphinx' project = 'Sphinx'
copyright = '2007-2018, Georg Brandl and the Sphinx team' copyright = '2007-2019, Georg Brandl and the Sphinx team'
version = sphinx.__display_version__ version = sphinx.__display_version__
release = version release = version
show_authors = True show_authors = True
@ -44,6 +42,7 @@ epub_post_files = [('usage/installation.xhtml', 'Installing Sphinx'),
epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js', epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
'_static/jquery.js', '_static/searchtools.js', '_static/jquery.js', '_static/searchtools.js',
'_static/underscore.js', '_static/basic.css', '_static/underscore.js', '_static/basic.css',
'_static/language_data.js',
'search.html', '_static/websupport.js'] 'search.html', '_static/websupport.js']
epub_fix_images = False epub_fix_images = False
epub_max_image_width = 0 epub_max_image_width = 0
@ -56,10 +55,17 @@ latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
'Georg Brandl', 'manual', 1)] 'Georg Brandl', 'manual', 1)]
latex_logo = '_static/sphinx.png' latex_logo = '_static/sphinx.png'
latex_elements = { latex_elements = {
'fontenc': r'\usepackage[LGR,X2,T1]{fontenc}',
'fontpkg': r''' 'fontpkg': r'''
\usepackage[sc]{mathpazo} \usepackage[sc]{mathpazo}
\usepackage[scaled]{helvet} \usepackage[scaled]{helvet}
\usepackage{courier} \usepackage{courier}
\substitutefont{LGR}{\rmdefault}{cmr}
\substitutefont{LGR}{\sfdefault}{cmss}
\substitutefont{LGR}{\ttdefault}{cmtt}
\substitutefont{X2}{\rmdefault}{cmr}
\substitutefont{X2}{\sfdefault}{cmss}
\substitutefont{X2}{\ttdefault}{cmtt}
''', ''',
'passoptionstopackages': '\\PassOptionsToPackage{svgnames}{xcolor}', 'passoptionstopackages': '\\PassOptionsToPackage{svgnames}{xcolor}',
'preamble': '\\DeclareUnicodeCharacter{229E}{\\ensuremath{\\boxplus}}', 'preamble': '\\DeclareUnicodeCharacter{229E}{\\ensuremath{\\boxplus}}',
@ -144,3 +150,10 @@ def setup(app):
names=['param'], can_collapse=True) names=['param'], can_collapse=True)
app.add_object_type('event', 'event', 'pair: %s; event', parse_event, app.add_object_type('event', 'event', 'pair: %s; event', parse_event,
doc_field_types=[fdesc]) doc_field_types=[fdesc])
# workaround for RTD
from sphinx.util import logging
logger = logging.getLogger(__name__)
app.info = lambda *args, **kwargs: logger.info(*args, **kwargs)
app.warn = lambda *args, **kwargs: logger.warning(*args, **kwargs)
app.debug = lambda *args, **kwargs: logger.debug(*args, **kwargs)

View File

@ -7,6 +7,8 @@ Sphinx documentation contents
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
intro
usage/installation usage/installation
usage/quickstart usage/quickstart
usage/restructuredtext/index usage/restructuredtext/index
@ -14,16 +16,17 @@ Sphinx documentation contents
usage/configuration usage/configuration
usage/builders/index usage/builders/index
usage/extensions/index usage/extensions/index
usage/theming
usage/advanced/intl
usage/advanced/setuptools
usage/advanced/websupport/index
intro
man/index man/index
intl
theming theming
setuptools
templating templating
latex latex
extdev/index extdev/index
websupport development/tutorials/index
faq faq
glossary glossary

View File

@ -100,7 +100,7 @@ This is the current list of contributed extensions in that repository:
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_ - zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_
See the :ref:`extension tutorial <exttut>` on getting started with writing your See the :doc:`extension tutorials <../development/tutorials/index>` on getting started with writing your
own extensions. own extensions.
@ -127,7 +127,7 @@ own extensions.
.. _NumPy style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt .. _NumPy style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
.. _hyphenator: https://github.com/mnater/hyphenator .. _hyphenator: https://github.com/mnater/hyphenator
.. _exceltable: https://pythonhosted.org/sphinxcontrib-exceltable/ .. _exceltable: https://pythonhosted.org/sphinxcontrib-exceltable/
.. _YouTube: http://www.youtube.com/ .. _YouTube: https://www.youtube.com/
.. _ClearQuest: https://www.ibm.com/us-en/marketplace/rational-clearquest .. _ClearQuest: https://www.ibm.com/us-en/marketplace/rational-clearquest
.. _Zope interfaces: https://zopeinterface.readthedocs.io/en/latest/README.html .. _Zope interfaces: https://zopeinterface.readthedocs.io/en/latest/README.html
.. _slideshare: https://www.slideshare.net/ .. _slideshare: https://www.slideshare.net/

View File

@ -0,0 +1,162 @@
Developing a "Hello world" directive
====================================
The objective of this tutorial is to create a very basic extension that adds a new
directive that outputs a paragraph containing `hello world`.
Only basic information is provided in this tutorial. For more information,
refer to the :doc:`other tutorials <index>` that go into more
details.
.. warning:: For this extension, you will need some basic understanding of docutils_
and Python.
Creating a new extension file
-----------------------------
Your extension file could be in any folder of your project. In our case,
let's do the following:
#. Create an :file:`_ext` folder in :file:`source`.
#. Create a new Python file in the :file:`_ext` folder called
:file:`helloworld.py`.
Here is an example of the folder structure you might obtain:
.. code-block:: text
└── source
   ├── _ext
  └── helloworld.py
   ├── _static
   ├── _themes
   ├── conf.py
   ├── somefolder
   ├── somefile.rst
   └── someotherfile.rst
Writing the extension
---------------------
Open :file:`helloworld.py` and paste the following code in it:
.. code-block:: python
from docutils import nodes
from docutils.parsers.rst import Directive
class HelloWorld(Directive):
def run(self):
paragraph_node = nodes.paragraph(text='Hello World!')
return [paragraph_node]
def setup(app):
app.add_directive("helloworld", HelloWorld)
Some essential things are happening in this example, and you will see them
in all directives:
.. rubric:: Directive declaration
Our new directive is declared in the ``HelloWorld`` class, it extends
docutils_' ``Directive`` class. All extensions that create directives
should extend this class.
.. rubric:: ``run`` method
This method is a requirement and it is part of every directive. It contains
the main logic of the directive and it returns a list of docutils nodes to
be processed by Sphinx.
.. seealso::
:doc:`todo`
.. rubric:: docutils nodes
The ``run`` method returns a list of nodes. Nodes are docutils' way of
representing the content of a document. There are many types of nodes
available: text, paragraph, reference, table, etc.
.. seealso::
`The docutils documentation on nodes <docutils nodes>`_
The ``nodes.paragraph`` class creates a new paragraph node. A paragraph
node typically contains some text that we can set during instantiation using
the ``text`` parameter.
.. rubric:: ``setup`` function
This function is a requirement. We use it to plug our new directive into
Sphinx.
The simplest thing you can do it call the ``app.add_directive`` method.
.. note::
The first argument is the name of the directive itself as used in an rST file.
In our case, we would use ``helloworld``:
.. code-block:: rst
Some intro text here...
.. helloworld::
Some more text here...
Updating the conf.py file
-------------------------
The extension file has to be declared in your :file:`conf.py` file to make
Sphinx aware of it:
#. Open :file:`conf.py`. It is in the :file:`source` folder by default.
#. Add ``sys.path.append(os.path.abspath("./_ext"))`` before
the ``extensions`` variable declaration (if it exists).
#. Update or create the ``extensions`` list and add the
extension file name to the list:
.. code-block:: python
extensions.append('helloworld')
You can now use the extension.
.. admonition:: Example
.. code-block:: rst
Some intro text here...
.. helloworld::
Some more text here...
The sample above would generate:
.. code-block:: text
Some intro text here...
Hello World!
Some more text here...
This is the very basic principle of an extension that creates a new directive.
For a more advanced example, refer to :doc:`todo`.
Further reading
---------------
You can create your own nodes if needed, refer to the
:doc:`todo` for more information.
.. _docutils: http://docutils.sourceforge.net/
.. _`docutils nodes`: http://docutils.sourceforge.net/docs/ref/doctree.html

View File

@ -0,0 +1,11 @@
Extension tutorials
===================
Refer to the following tutorials to get started with extension development.
.. toctree::
:caption: Directive tutorials
:maxdepth: 1
helloworld
todo

View File

@ -1,7 +1,5 @@
.. _exttut: Developing a "TODO" extension
=============================
Tutorial: Writing a simple extension
====================================
This section is intended as a walkthrough for the creation of custom extensions. This section is intended as a walkthrough for the creation of custom extensions.
It covers the basics of writing and activating an extension, as well as It covers the basics of writing and activating an extension, as well as
@ -12,112 +10,12 @@ include todo entries in the documentation, and to collect these in a central
place. (A similar "todo" extension is distributed with Sphinx.) place. (A similar "todo" extension is distributed with Sphinx.)
Important objects
-----------------
There are several key objects whose API you will use while writing an
extension. These are:
**Application**
The application object (usually called ``app``) is an instance of
:class:`.Sphinx`. It controls most high-level functionality, such as the
setup of extensions, event dispatching and producing output (logging).
If you have the environment object, the application is available as
``env.app``.
**Environment**
The build environment object (usually called ``env``) is an instance of
:class:`.BuildEnvironment`. It is responsible for parsing the source
documents, stores all metadata about the document collection and is
serialized to disk after each build.
Its API provides methods to do with access to metadata, resolving references,
etc. It can also be used by extensions to cache information that should
persist for incremental rebuilds.
If you have the application or builder object, the environment is available
as ``app.env`` or ``builder.env``.
**Builder**
The builder object (usually called ``builder``) is an instance of a specific
subclass of :class:`.Builder`. Each builder class knows how to convert the
parsed documents into an output format, or otherwise process them (e.g. check
external links).
If you have the application object, the builder is available as
``app.builder``.
**Config**
The config object (usually called ``config``) provides the values of
configuration values set in :file:`conf.py` as attributes. It is an instance
of :class:`.Config`.
The config is available as ``app.config`` or ``env.config``.
Build Phases
------------
One thing that is vital in order to understand extension mechanisms is the way
in which a Sphinx project is built: this works in several phases.
**Phase 0: Initialization**
In this phase, almost nothing of interest to us happens. The source
directory is searched for source files, and extensions are initialized.
Should a stored build environment exist, it is loaded, otherwise a new one is
created.
**Phase 1: Reading**
In Phase 1, all source files (and on subsequent builds, those that are new or
changed) are read and parsed. This is the phase where directives and roles
are encountered by docutils, and the corresponding code is executed. The
output of this phase is a *doctree* for each source file; that is a tree of
docutils nodes. For document elements that aren't fully known until all
existing files are read, temporary nodes are created.
There are nodes provided by docutils, which are documented `in the docutils
documentation <http://docutils.sourceforge.net/docs/ref/doctree.html>`__.
Additional nodes are provided by Sphinx and :ref:`documented here <nodes>`.
During reading, the build environment is updated with all meta- and cross
reference data of the read documents, such as labels, the names of headings,
described Python objects and index entries. This will later be used to
replace the temporary nodes.
The parsed doctrees are stored on the disk, because it is not possible to
hold all of them in memory.
**Phase 2: Consistency checks**
Some checking is done to ensure no surprises in the built documents.
**Phase 3: Resolving**
Now that the metadata and cross-reference data of all existing documents is
known, all temporary nodes are replaced by nodes that can be converted into
output using components called tranform. For example, links are created for
object references that exist, and simple literal nodes are created for those
that don't.
**Phase 4: Writing**
This phase converts the resolved doctrees to the desired output format, such
as HTML or LaTeX. This happens via a so-called docutils writer that visits
the individual nodes of each doctree and produces some output in the process.
.. note::
Some builders deviate from this general build plan, for example, the builder
that checks external links does not need anything more than the parsed
doctrees and therefore does not have phases 2--4.
Extension Design Extension Design
---------------- ----------------
.. note:: To understand the design this extension, refer to
:ref:`important-objects` and :ref:`build-phases`.
We want the extension to add the following to Sphinx: We want the extension to add the following to Sphinx:
* A "todo" directive, containing some content that is marked with "TODO", and * A "todo" directive, containing some content that is marked with "TODO", and
@ -174,12 +72,13 @@ the individual calls do is the following:
If the third argument was ``'html'``, HTML documents would be full rebuild if the If the third argument was ``'html'``, HTML documents would be full rebuild if the
config value changed its value. This is needed for config values that config value changed its value. This is needed for config values that
influence reading (build phase 1). influence reading (build :ref:`phase 1 <build-phases>`).
* :meth:`~Sphinx.add_node` adds a new *node class* to the build system. It also * :meth:`~Sphinx.add_node` adds a new *node class* to the build system. It also
can specify visitor functions for each supported output format. These visitor can specify visitor functions for each supported output format. These visitor
functions are needed when the new nodes stay until phase 4 -- since the functions are needed when the new nodes stay until :ref:`phase 4 <build-phases>`
``todolist`` node is always replaced in phase 3, it doesn't need any. -- since the ``todolist`` node is always replaced in :ref:`phase 3 <build-phases>`,
it doesn't need any.
We need to create the two node classes ``todo`` and ``todolist`` later. We need to create the two node classes ``todo`` and ``todolist`` later.
@ -276,7 +175,7 @@ The ``todo`` directive function looks like this::
return [targetnode, todo_node] return [targetnode, todo_node]
Several important things are covered here. First, as you can see, you can refer Several important things are covered here. First, as you can see, you can refer
to the build environment instance using ``self.state.document.settings.env``. to the :ref:`build environment instance <important-objects>` using ``self.state.document.settings.env``.
Then, to act as a link target (from the todolist), the todo directive needs to Then, to act as a link target (from the todolist), the todo directive needs to
return a target node in addition to the todo node. The target ID (in HTML, this return a target node in addition to the todo node. The target ID (in HTML, this
@ -340,7 +239,8 @@ Here we clear out all todos whose docname matches the given one from the
added again during parsing. added again during parsing.
The other handler belongs to the :event:`doctree-resolved` event. This event is The other handler belongs to the :event:`doctree-resolved` event. This event is
emitted at the end of phase 3 and allows custom resolving to be done:: emitted at the end of :ref:`phase 3 <build-phases>` and allows custom resolving
to be done::
def process_todo_nodes(app, doctree, fromdocname): def process_todo_nodes(app, doctree, fromdocname):
if not app.config.todo_include_todos: if not app.config.todo_include_todos:

View File

@ -120,6 +120,10 @@ Sphinx runtime information
The application object also provides runtime information as attributes. The application object also provides runtime information as attributes.
.. attribute:: Sphinx.project
Target project. See :class:`.Project`.
.. attribute:: Sphinx.srcdir .. attribute:: Sphinx.srcdir
Source directory. Source directory.

View File

@ -15,6 +15,10 @@ Build environment API
Reference to the :class:`.Config` object. Reference to the :class:`.Config` object.
.. attribute:: project
Target project. See :class:`.Project`.
.. attribute:: srcdir .. attribute:: srcdir
Source directory. Source directory.

View File

@ -52,6 +52,115 @@ Note that it is still necessary to register the builder using
.. _entry points: https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins .. _entry points: https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins
.. _important-objects:
Important objects
-----------------
There are several key objects whose API you will use while writing an
extension. These are:
**Application**
The application object (usually called ``app``) is an instance of
:class:`.Sphinx`. It controls most high-level functionality, such as the
setup of extensions, event dispatching and producing output (logging).
If you have the environment object, the application is available as
``env.app``.
**Environment**
The build environment object (usually called ``env``) is an instance of
:class:`.BuildEnvironment`. It is responsible for parsing the source
documents, stores all metadata about the document collection and is
serialized to disk after each build.
Its API provides methods to do with access to metadata, resolving references,
etc. It can also be used by extensions to cache information that should
persist for incremental rebuilds.
If you have the application or builder object, the environment is available
as ``app.env`` or ``builder.env``.
**Builder**
The builder object (usually called ``builder``) is an instance of a specific
subclass of :class:`.Builder`. Each builder class knows how to convert the
parsed documents into an output format, or otherwise process them (e.g. check
external links).
If you have the application object, the builder is available as
``app.builder``.
**Config**
The config object (usually called ``config``) provides the values of
configuration values set in :file:`conf.py` as attributes. It is an instance
of :class:`.Config`.
The config is available as ``app.config`` or ``env.config``.
To see an example of use of these objects, refer to :doc:`../development/tutorials/index`.
.. _build-phases:
Build Phases
------------
One thing that is vital in order to understand extension mechanisms is the way
in which a Sphinx project is built: this works in several phases.
**Phase 0: Initialization**
In this phase, almost nothing of interest to us happens. The source
directory is searched for source files, and extensions are initialized.
Should a stored build environment exist, it is loaded, otherwise a new one is
created.
**Phase 1: Reading**
In Phase 1, all source files (and on subsequent builds, those that are new or
changed) are read and parsed. This is the phase where directives and roles
are encountered by docutils, and the corresponding code is executed. The
output of this phase is a *doctree* for each source file; that is a tree of
docutils nodes. For document elements that aren't fully known until all
existing files are read, temporary nodes are created.
There are nodes provided by docutils, which are documented `in the docutils
documentation <http://docutils.sourceforge.net/docs/ref/doctree.html>`__.
Additional nodes are provided by Sphinx and :ref:`documented here <nodes>`.
During reading, the build environment is updated with all meta- and cross
reference data of the read documents, such as labels, the names of headings,
described Python objects and index entries. This will later be used to
replace the temporary nodes.
The parsed doctrees are stored on the disk, because it is not possible to
hold all of them in memory.
**Phase 2: Consistency checks**
Some checking is done to ensure no surprises in the built documents.
**Phase 3: Resolving**
Now that the metadata and cross-reference data of all existing documents is
known, all temporary nodes are replaced by nodes that can be converted into
output using components called transforms. For example, links are created for
object references that exist, and simple literal nodes are created for those
that don't.
**Phase 4: Writing**
This phase converts the resolved doctrees to the desired output format, such
as HTML or LaTeX. This happens via a so-called docutils writer that visits
the individual nodes of each doctree and produces some output in the process.
.. note::
Some builders deviate from this general build plan, for example, the builder
that checks external links does not need anything more than the parsed
doctrees and therefore does not have phases 2--4.
To see an example of application, refer to :doc:`../development/tutorials/todo`.
.. _ext-metadata: .. _ext-metadata:
Extension metadata Extension metadata
@ -82,9 +191,10 @@ APIs used for writing extensions
-------------------------------- --------------------------------
.. toctree:: .. toctree::
:maxdepth: 2
tutorial
appapi appapi
projectapi
envapi envapi
builderapi builderapi
collectorapi collectorapi
@ -96,6 +206,8 @@ APIs used for writing extensions
i18n i18n
utils utils
.. _dev-deprecated-apis:
Deprecated APIs Deprecated APIs
--------------- ---------------
@ -104,7 +216,13 @@ But, sometimes, the change of interface are needed for some reasons. In such
cases, we've marked them as deprecated. And they are kept during the two cases, we've marked them as deprecated. And they are kept during the two
major versions (for more details, please see :ref:`deprecation-policy`). major versions (for more details, please see :ref:`deprecation-policy`).
The following is a list of deprecated interface. The following is a list of deprecated interfaces.
.. tabularcolumns:: |>{\raggedright}\Y{.4}|>{\centering}\Y{.1}|>{\centering}\Y{.12}|>{\raggedright\arraybackslash}\Y{.38}|
.. |LaTeXHyphenate| raw:: latex
\hspace{0pt}
.. list-table:: deprecated APIs .. list-table:: deprecated APIs
:header-rows: 1 :header-rows: 1
@ -112,10 +230,302 @@ The following is a list of deprecated interface.
:widths: 40, 10, 10, 40 :widths: 40, 10, 10, 40
* - Target * - Target
- Deprecated - |LaTeXHyphenate|\ Deprecated
- (will be) Removed - (will be) Removed
- Alternatives - Alternatives
* - ``encoding`` argument of ``autodoc.Documenter.get_doc()``,
``autodoc.DocstringSignatureMixin.get_doc()``,
``autodoc.DocstringSignatureMixin._find_signature()``, and
``autodoc.ClassDocumenter.get_doc()``
- 2.0
- 4.0
- N/A
* - arguments of ``EpubBuilder.build_mimetype()``,
``EpubBuilder.build_container()``, ``EpubBuilder.build_content()``,
``EpubBuilder.build_toc()`` and ``EpubBuilder.build_epub()``
- 2.0
- 4.0
- N/A
* - arguments of ``Epub3Builder.build_navigation_doc()``
- 2.0
- 4.0
- N/A
* - ``nodetype`` argument of
``sphinx.search.WordCollector.is_meta_keywords()``
- 2.0
- 4.0
- N/A
* - ``suffix`` argument of ``BuildEnvironment.doc2path()``
- 2.0
- 4.0
- N/A
* - string style ``base`` argument of ``BuildEnvironment.doc2path()``
- 2.0
- 4.0
- ``os.path.join()``
* - ``sphinx.addnodes.abbreviation``
- 2.0
- 4.0
- ``docutils.nodes.abbreviation``
* - ``sphinx.builders.applehelp``
- 2.0
- 4.0
- ``sphinxcontrib.applehelp``
* - ``sphinx.builders.devhelp``
- 2.0
- 4.0
- ``sphinxcontrib.devhelp``
* - ``sphinx.builders.epub3.Epub3Builder.validate_config_value()``
- 2.0
- 4.0
- ``sphinx.builders.epub3.validate_config_values()``
* - ``sphinx.builders.html.SingleFileHTMLBuilder``
- 2.0
- 4.0
- ``sphinx.builders.singlehtml.SingleFileHTMLBuilder``
* - ``sphinx.builders.htmlhelp.HTMLHelpBuilder.open_file()``
- 2.0
- 4.0
- ``open()``
* - ``sphinx.builders.qthelp``
- 2.0
- 4.0
- ``sphinxcontrib.qthelp``
* - ``sphinx.cmd.quickstart.term_decode()``
- 2.0
- 4.0
- N/A
* - ``sphinx.cmd.quickstart.TERM_ENCODING``
- 2.0
- 4.0
- ``sys.stdin.encoding``
* - ``sphinx.config.check_unicode()``
- 2.0
- 4.0
- N/A
* - ``sphinx.config.string_classes``
- 2.0
- 4.0
- ``[str]``
* - ``sphinx.domains.cpp.DefinitionError.description``
- 2.0
- 4.0
- ``str(exc)``
* - ``sphinx.domains.cpp.NoOldIdError.description``
- 2.0
- 4.0
- ``str(exc)``
* - ``sphinx.domains.cpp.UnsupportedMultiCharacterCharLiteral.decoded``
- 2.0
- 4.0
- ``str(exc)``
* - ``sphinx.ext.autosummary.Autosummary.warn()``
- 2.0
- 4.0
- N/A
* - ``sphinx.ext.autosummary.Autosummary.genopt``
- 2.0
- 4.0
- N/A
* - ``sphinx.ext.autosummary.Autosummary.warnings``
- 2.0
- 4.0
- N/A
* - ``sphinx.ext.autosummary.Autosummary.result``
- 2.0
- 4.0
- N/A
* - ``sphinx.ext.doctest.doctest_encode()``
- 2.0
- 4.0
- N/A
* - ``sphinx.ext.jsmath``
- 2.0
- 4.0
- ``sphinxcontrib.jsmath``
* - ``sphinx.testing.util.remove_unicode_literal()``
- 2.0
- 4.0
- N/A
* - ``sphinx.util.attrdict``
- 2.0
- 4.0
- N/A
* - ``sphinx.util.force_decode()``
- 2.0
- 4.0
- N/A
* - ``sphinx.util.get_matching_docs()``
- 2.0
- 4.0
- ``sphinx.util.get_matching_files()``
* - ``sphinx.util.inspect.Parameter``
- 2.0
- 3.0
- N/A
* - ``sphinx.util.osutil.EEXIST``
- 2.0
- 4.0
- ``errno.EEXIST`` or ``FileExistsError``
* - ``sphinx.util.osutil.EINVAL``
- 2.0
- 4.0
- ``errno.EINVAL``
* - ``sphinx.util.osutil.ENOENT``
- 2.0
- 4.0
- ``errno.ENOENT`` or ``FileNotFoundError``
* - ``sphinx.util.osutil.EPIPE``
- 2.0
- 4.0
- ``errno.ENOENT`` or ``BrokenPipeError``
* - ``sphinx.util.osutil.walk()``
- 2.0
- 4.0
- ``os.walk()``
* - ``sphinx.util.pycompat.TextIOWrapper``
- 2.0
- 4.0
- ``io.TextIOWrapper``
* - ``sphinx.util.pycompat.UnicodeMixin``
- 2.0
- 4.0
- N/A
* - ``sphinx.util.pycompat.htmlescape()``
- 2.0
- 4.0
- ``html.escape()``
* - ``sphinx.util.pycompat.indent()``
- 2.0
- 4.0
- ``textwrap.indent()``
* - ``sphinx.util.pycompat.u``
- 2.0
- 4.0
- N/A
* - ``sphinx.util.PeekableIterator``
- 2.0
- 4.0
- N/A
* - Omitting the ``filename`` argument in an overriddent
``IndexBuilder.feed()`` method.
- 2.0
- 4.0
- ``IndexBuilder.feed(docname, filename, title, doctree)``
* - ``sphinx.writers.latex.ExtBabel``
- 2.0
- 4.0
- ``sphinx.builders.latex.util.ExtBabel``
* - ``sphinx.writers.latex.LaTeXTranslator.babel_defmacro()``
- 2.0
- 4.0
- N/A
* - ``sphinx.application.Sphinx._setting_up_extension``
- 2.0
- 3.0
- N/A
* - The ``importer`` argument of ``sphinx.ext.autodoc.importer._MockModule``
- 2.0
- 3.0
- N/A
* - ``sphinx.ext.autodoc.importer._MockImporter``
- 2.0
- 3.0
- N/A
* - ``sphinx.io.SphinxBaseFileInput``
- 2.0
- 3.0
- N/A
* - ``sphinx.io.SphinxFileInput.supported``
- 2.0
- 3.0
- N/A
* - ``sphinx.io.SphinxRSTFileInput``
- 2.0
- 3.0
- N/A
* - ``sphinx.registry.SphinxComponentRegistry.add_source_input()``
- 2.0
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXTranslator._make_visit_admonition()``
- 2.0
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXTranslator.collect_footnotes()``
- 2.0
- 4.0
- N/A
* - ``sphinx.writers.texinfo.TexinfoTranslator._make_visit_admonition()``
- 2.0
- 3.0
- N/A
* - ``sphinx.writers.text.TextTranslator._make_depart_admonition()``
- 2.0
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXTranslator.generate_numfig_format()``
- 2.0
- 4.0
- N/A
* - :rst:dir:`highlightlang` * - :rst:dir:`highlightlang`
- 1.8 - 1.8
- 4.0 - 4.0
@ -136,6 +546,17 @@ The following is a list of deprecated interface.
- 4.0 - 4.0
- :confval:`autodoc_default_options` - :confval:`autodoc_default_options`
* - ``content`` arguments of ``sphinx.util.image.guess_mimetype()``
- 1.8
- 3.0
- N/A
* - ``gettext_compact`` arguments of
``sphinx.util.i18n.find_catalog_source_files()``
- 1.8
- 3.0
- N/A
* - ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()`` * - ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()``
- 1.8 - 1.8
- 3.0 - 3.0
@ -172,6 +593,16 @@ The following is a list of deprecated interface.
- 3.0 - 3.0
- ``sphinx.domains.math.MathDomain`` - ``sphinx.domains.math.MathDomain``
* - ``sphinx.ext.mathbase.MathDirective``
- 1.8
- 3.0
- ``sphinx.directives.patches.MathDirective``
* - ``sphinx.ext.mathbase.math_role()``
- 1.8
- 3.0
- ``docutils.parsers.rst.roles.math_role()``
* - ``sphinx.ext.mathbase.setup_math()`` * - ``sphinx.ext.mathbase.setup_math()``
- 1.8 - 1.8
- 3.0 - 3.0

View File

@ -57,8 +57,10 @@ Logging API
**color** **color**
The color of logs. By default, info and verbose level logs are not colored, The color of logs. By default, info and verbose level logs are not colored,
and deug level ones are colored as ``"darkgray"``. and debug level ones are colored as ``"darkgray"``.
.. autofunction:: pending_logging() .. autofunction:: pending_logging()
.. autofunction:: pending_warnings() .. autofunction:: pending_warnings()
.. autofunction:: prefixed_warnings()

View File

@ -0,0 +1,9 @@
.. _project-api:
Project API
===========
.. currentmodule:: sphinx.project
.. autoclass:: Project
:members:

View File

@ -20,7 +20,7 @@ How do I...
the :rst:dir:`toctree` directive where you want to start numbering. the :rst:dir:`toctree` directive where you want to start numbering.
... customize the look of the built HTML files? ... customize the look of the built HTML files?
Use themes, see :doc:`theming`. Use themes, see :doc:`/usage/theming`.
... add global substitutions or includes? ... add global substitutions or includes?
Add them in the :confval:`rst_prolog` or :confval:`rst_epilog` config value. Add them in the :confval:`rst_prolog` or :confval:`rst_epilog` config value.
@ -30,7 +30,7 @@ How do I...
``sidebartoc`` block. ``sidebartoc`` block.
... write my own extension? ... write my own extension?
See the :ref:`extension tutorial <exttut>`. See the :doc:`/development/tutorials/index`.
... convert from my existing docs using MoinMoin markup? ... convert from my existing docs using MoinMoin markup?
The easiest way is to convert to xhtml, then convert `xhtml to reST`_. The easiest way is to convert to xhtml, then convert `xhtml to reST`_.
@ -205,7 +205,7 @@ The following list gives some hints for the creation of epub files:
.. _Epubcheck: https://github.com/IDPF/epubcheck .. _Epubcheck: https://github.com/IDPF/epubcheck
.. _Calibre: https://calibre-ebook.com/ .. _Calibre: https://calibre-ebook.com/
.. _FBreader: https://fbreader.org/ .. _FBreader: https://fbreader.org/
.. _Bookworm: http://www.oreilly.com/bookworm/index.html .. _Bookworm: https://www.oreilly.com/bookworm/index.html
.. _kindlegen: https://www.amazon.com/gp/feature.html?docId=1000765211 .. _kindlegen: https://www.amazon.com/gp/feature.html?docId=1000765211
.. _texinfo-faq: .. _texinfo-faq:

View File

@ -55,15 +55,13 @@ See the :ref:`pertinent section in the FAQ list <usingwith>`.
Prerequisites Prerequisites
------------- -------------
Sphinx needs at least **Python 2.7** or **Python 3.4** to run, as well as the Sphinx needs at least **Python 3.5** to run, as well as the docutils_ and
docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.10 Jinja2_ libraries. Sphinx should work with docutils version 0.12 or some (not
or some (not broken) SVN trunk snapshot. If you like to have source code broken) SVN trunk snapshot.
highlighting support, you must also install the Pygments_ library.
.. _reStructuredText: http://docutils.sourceforge.net/rst.html .. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _docutils: http://docutils.sourceforge.net/ .. _docutils: http://docutils.sourceforge.net/
.. _Jinja2: http://jinja.pocoo.org/ .. _Jinja2: http://jinja.pocoo.org/
.. _Pygments: http://pygments.org/
Usage Usage

View File

@ -8,9 +8,6 @@ LaTeX customization
.. module:: latex .. module:: latex
:synopsis: LaTeX specifics. :synopsis: LaTeX specifics.
For details of the LaTeX/PDF builder command line invocation, refer to
:py:class:`~sphinx.builders.latex.LaTeXBuilder`.
.. raw:: latex .. raw:: latex
\begingroup \begingroup
@ -29,15 +26,24 @@ For details of the LaTeX/PDF builder command line invocation, refer to
cautionBgColor={named}{LightCyan}} cautionBgColor={named}{LightCyan}}
\relax \relax
.. _latex-basic:
Basic customization
-------------------
The *latex* target does not benefit from prepared themes. The *latex* target does not benefit from prepared themes.
Basic customization is obtained via usage of the :ref:`latex-options`. For The :ref:`latex-options`, and particularly among them the
example:: :ref:`latex_elements <latex_elements_confval>` variable
provides much of the interface for customization.
For some details of the LaTeX/PDF builder command line
invocation, refer to :py:class:`~sphinx.builders.latex.LaTeXBuilder`.
.. _latex-basic:
Example
-------
Keep in mind that backslashes must be doubled in Python string literals to
avoid interpretation as escape sequences, or use raw strings (as is done here).
::
# inside conf.py # inside conf.py
latex_engine = 'xelatex' latex_engine = 'xelatex'
@ -59,49 +65,412 @@ example::
} }
latex_show_urls = 'footnote' latex_show_urls = 'footnote'
.. the above was tested on Sphinx's own 1.5a2 documentation with good effect!
.. highlight:: latex .. highlight:: latex
If the size of the ``'preamble'`` contents becomes inconvenient, one may move .. _latex_elements_confval:
all needed macros into some file :file:`mystyle.tex.txt` of the project source
repertory, and get LaTeX to import it at run time:: The latex_elements configuration setting
----------------------------------------
A dictionary that contains LaTeX snippets overriding those Sphinx usually puts
into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described
:ref:`separately <latexsphinxsetup>`.
* Keys that you may want to override include:
``'papersize'``
Paper size option of the document class (``'a4paper'`` or
``'letterpaper'``), default ``'letterpaper'``.
``'pointsize'``
Point size option of the document class (``'10pt'``, ``'11pt'`` or
``'12pt'``), default ``'10pt'``.
``'pxunit'``
the value of the ``px`` when used in image attributes ``width`` and
``height``. The default value is ``'0.75bp'`` which achieves
``96px=1in`` (in TeX ``1in = 72bp = 72.27pt``.) To obtain for
example ``100px=1in`` use ``'0.01in'`` or ``'0.7227pt'`` (the latter
leads to TeX computing a more precise value, due to the smaller unit
used in the specification); for ``72px=1in``, simply use ``'1bp'``; for
``90px=1in``, use ``'0.8bp'`` or ``'0.803pt'``.
.. versionadded:: 1.5
``'passoptionstopackages'``
A string which will be positioned early in the preamble, designed to
contain ``\\PassOptionsToPackage{options}{foo}`` commands. Default empty.
.. versionadded:: 1.4
``'babel'``
"babel" package inclusion, default ``'\\usepackage{babel}'`` (the
suitable document language string is passed as class option, and
``english`` is used if no language.) For Japanese documents, the
default is the empty string.
With XeLaTeX and LuaLaTeX, Sphinx configures the LaTeX document to use
`polyglossia`_, but one should be aware that current `babel`_ has
improved its support for Unicode engines in recent years and for some
languages it may make sense to prefer ``babel`` over ``polyglossia``.
.. hint::
After modifiying a core LaTeX key like this one, clean up the LaTeX
build repertory before next PDF build, else left-over auxiliary
files are likely to break the build.
.. _`polyglossia`: https://ctan.org/pkg/polyglossia
.. _`babel`: https://ctan.org/pkg/babel
.. versionchanged:: 1.5
For :confval:`latex_engine` set to ``'xelatex'``, the default
is ``'\\usepackage{polyglossia}\n\\setmainlanguage{<language>}'``.
.. versionchanged:: 1.6
``'lualatex'`` uses same default setting as ``'xelatex'``
.. versionchanged:: 1.7.6
For French, ``xelatex`` and ``lualatex`` default to using
``babel``, not ``polyglossia``.
``'fontpkg'``
Font package inclusion, the default is ``'\\usepackage{times}'`` which
uses Times for text, Helvetica for sans serif and Courier for monospace.
.. versionchanged:: 1.2
Defaults to ``''`` when the :confval:`language` uses the Cyrillic
script.
.. versionchanged:: 2.0
Support for individual Greek and Cyrillic letters:
- In order to support occasional Cyrillic (физика частиц)
or Greek letters (Σωματιδιακή φυσική) in
a document whose language is English or a Latin European
one, the default set-up is enhanced (only for ``'pdflatex'``
engine) to do:
.. code-block:: latex
\substitutefont{LGR}{\rmdefault}{cmr}
\substitutefont{LGR}{\sfdefault}{cmss}
\substitutefont{LGR}{\ttdefault}{cmtt}
\substitutefont{X2}{\rmdefault}{cmr}
\substitutefont{X2}{\sfdefault}{cmss}
\substitutefont{X2}{\ttdefault}{cmtt}
but this is activated only under the condition that the
``'fontenc'`` key is configured to load the ``LGR`` (Greek)
and/or ``X2`` (Cyrillic) pdflatex-font encodings (if the
:confval:`language` is set to a Cyrillic language, this
``'fontpkg'`` key must be used as "times" package has no direct
support for it; then keep only ``LGR`` lines from the above,
if support is needed for Greek in the text).
The ``\substitutefont`` command is from the eponymous LaTeX
package, which is loaded by Sphinx if needed (on Ubuntu xenial it
is part of ``texlive-latex-extra`` which is a Sphinx
requirement).
Only if the document actually does contain Unicode Greek letters
(in text) or Cyrillic letters, will the above default set-up
cause additional requirements for the PDF build. On Ubuntu
xenial, ``texlive-lang-greek``, ``texlive-lang-cyrillic``, and
(with the above choice of fonts) the ``cm-super`` (or
``cm-super-minimal``) package.
- For ``'xelatex'`` and ``'lualatex'``, the default is to
use the FreeFont family: this OpenType font family
supports both Cyrillic and Greek scripts and is available as
separate Ubuntu xenial package ``fonts-freefont-otf``, it is not
needed to install the big package ``texlive-fonts-extra``.
- ``'platex'`` (Japanese documents) engine supports individual
Cyrillic and Greek letters with no need of extra user set-up.
``'fncychap'``
Inclusion of the "fncychap" package (which makes fancy chapter titles),
default ``'\\usepackage[Bjarne]{fncychap}'`` for English documentation
(this option is slightly customized by Sphinx),
``'\\usepackage[Sonny]{fncychap}'`` for internationalized docs (because
the "Bjarne" style uses numbers spelled out in English). Other
"fncychap" styles you can try are "Lenny", "Glenn", "Conny", "Rejne" and
"Bjornstrup". You can also set this to ``''`` to disable fncychap.
The default is ``''`` for Japanese documents.
``'preamble'``
Additional preamble content, default empty. One may move all needed
macros into some file :file:`mystyle.tex.txt` of the project source
repertory, and get LaTeX to import it at run time::
'preamble': r'\input{mystyle.tex.txt}', 'preamble': r'\input{mystyle.tex.txt}',
# or, if the \ProvidesPackage LaTeX macro is used in a file mystyle.sty # or, if the \ProvidesPackage LaTeX macro is used in a file mystyle.sty
'preamble': r'\usepackage{mystyle}', 'preamble': r'\usepackage{mystyle}',
It is then needed to set appropriately :confval:`latex_additional_files`, for It is then needed to set appropriately
example:: :confval:`latex_additional_files`, for example::
latex_additional_files = ["mystyle.sty"] latex_additional_files = ["mystyle.sty"]
``'figure_align'``
Latex figure float alignment, default 'htbp' (here, top, bottom, page).
Whenever an image doesn't fit into the current page, it will be
'floated' into the next page but may be preceded by any other text.
If you don't like this behavior, use 'H' which will disable floating
and position figures strictly in the order they appear in the source.
.. versionadded:: 1.3
``'atendofbody'``
Additional document content (right before the indices), default empty.
.. versionadded:: 1.5
``'footer'``
Additional footer content (before the indices), default empty.
.. deprecated:: 1.5
Use ``'atendofbody'`` key instead.
* Keys that don't need to be overridden unless in special cases are:
``'extraclassoptions'``
The default is the empty string. Example: ``'extraclassoptions':
'openany'`` will allow chapters (for documents of the ``'manual'``
type) to start on any page.
.. versionadded:: 1.2
.. versionchanged:: 1.6
Added this documentation.
``'maxlistdepth'``
LaTeX allows by default at most 6 levels for nesting list and
quote-like environments, with at most 4 enumerated lists, and 4 bullet
lists. Setting this key for example to ``'10'`` (as a string) will
allow up to 10 nested levels (of all sorts). Leaving it to the empty
string means to obey the LaTeX default.
.. warning::
- Using this key may prove incompatible with some LaTeX packages
or special document classes which do their own list customization.
- The key setting is silently *ignored* if ``\usepackage{enumitem}``
is executed inside the document preamble. Use then rather the
dedicated commands of this LaTeX package.
.. versionadded:: 1.5
``'inputenc'``
"inputenc" package inclusion, defaults to
``'\\usepackage[utf8]{inputenc}'`` when using pdflatex.
Otherwise empty.
.. versionchanged:: 1.4.3
Previously ``'\\usepackage[utf8]{inputenc}'`` was used for all
compilers.
``'cmappkg'``
"cmap" package inclusion, default ``'\\usepackage{cmap}'``.
.. versionadded:: 1.2
``'fontenc'``
"fontenc" package inclusion, defaults to
``'\\usepackage[T1]{fontenc}'``.
If ``'pdflatex'`` is the :confval:`latex_engine`, one can add ``LGR``
for support of Greek letters in the document, and also ``X2`` (or
``T2A``) for Cyrillic letters, like this:
.. code-block:: latex
r'\usepackage[LGR,X2,T1]{fontenc}'
.. attention::
Prior to 2.0, Unicode Greek letters were escaped to use LaTeX math
mark-up. This is not the case anymore, and the above must be used
(only in case of ``'pdflatex'`` engine) if the source contains such
Unicode Greek.
On Ubuntu xenial, packages ``texlive-lang-greek`` and ``cm-super``
(for the latter, only if the ``'fontpkg'`` setting is left to its
default) are needed for ``LGR`` to work. In place of ``cm-super``
one can install smaller ``cm-super-minimal``, but it requires the
LaTeX document to execute ``\usepackage[10pt]{type1ec}`` before
loading ``fontenc``. Thus, use this key with this extra at its
start if needed.
.. versionchanged:: 1.5
Defaults to ``'\\usepackage{fontspec}'`` when
:confval:`latex_engine` is ``'xelatex'``.
.. versionchanged:: 1.6
``'lualatex'`` uses ``fontspec`` per default like ``'xelatex'``.
.. versionchanged:: 2.0
``'lualatex'`` executes
``\defaultfontfeatures[\rmfamily,\sffamily]{}`` to disable TeX
ligatures.
.. versionchanged:: 2.0
Detection of ``LGR``, ``T2A``, ``X2`` to trigger support of
occasional Greek or Cyrillic (``'pdflatex'`` only, as this support
is provided natively by ``'platex'`` and only requires suitable
font with ``'xelatex'/'lualatex'``).
``'textgreek'``
The default (``'pdflatex'`` only) is
``'\\usepackage{textalpha}'``, but only if ``'fontenc'`` was
modified by user to include ``LGR`` option. If not, the key
value will be forced to be the empty string.
This is needed for ``pdfLaTeX`` to support Unicode input of Greek
letters such as φύσις. Expert users may want to load the ``textalpha``
package with its option ``normalize-symbols``.
.. hint::
Unicode Greek (but no further Unicode symbols) in :rst:dir:`math`
can be supported by ``'pdflatex'`` from setting this key to
``r'\usepackage{textalpha,alphabeta}'``. Then ``:math:`α``` (U+03B1)
will render as :math:`\alpha`. For wider Unicode support in math
input, see the discussion of :confval:`latex_engine`.
With ``'platex'`` (Japanese), ``'xelatex'`` or ``'lualatex'``, this
key is ignored.
.. versionadded:: 2.0
``'geometry'``
"geometry" package inclusion, the default definition is:
``'\\usepackage{geometry}'``
with an additional ``[dvipdfm]`` for Japanese documents.
The Sphinx LaTeX style file executes:
``\PassOptionsToPackage{hmargin=1in,vmargin=1in,marginpar=0.5in}{geometry}``
which can be customized via corresponding :ref:`'sphinxsetup' options
<latexsphinxsetup>`.
.. versionadded:: 1.5
.. versionchanged:: 1.5.2
``dvipdfm`` option if :confval:`latex_engine` is ``'platex'``.
.. versionadded:: 1.5.3
The :ref:`'sphinxsetup' keys for the margins
<latexsphinxsetuphmargin>`.
.. versionchanged:: 1.5.3
The location in the LaTeX file has been moved to after
``\usepackage{sphinx}`` and ``\sphinxsetup{..}``, hence also after
insertion of ``'fontpkg'`` key. This is in order to handle the paper
layout options in a special way for Japanese documents: the text
width will be set to an integer multiple of the *zenkaku* width, and
the text height to an integer multiple of the baseline. See the
:ref:`hmargin <latexsphinxsetuphmargin>` documentation for more.
``'hyperref'``
"hyperref" package inclusion; also loads package "hypcap" and issues
``\urlstyle{same}``. This is done after :file:`sphinx.sty` file is
loaded and before executing the contents of ``'preamble'`` key.
.. attention::
Loading of packages "hyperref" and "hypcap" is mandatory.
.. versionadded:: 1.5
Previously this was done from inside :file:`sphinx.sty`.
``'maketitle'``
"maketitle" call, default ``'\\sphinxmaketitle'``. Override
if you want to generate a differently styled title page.
.. hint::
If the key value is set to
``r'\newcommand\sphinxbackoftitlepage{<Extra
material>}\sphinxmaketitle'``, then ``<Extra material>`` will be
typeset on back of title page (``'manual'`` docclass only).
.. versionchanged:: 1.8.3
Original ``\maketitle`` from document class is not overwritten,
hence is re-usable as part of some custom setting for this key.
.. versionadded:: 1.8.3
``\sphinxbackoftitlepage`` optional macro. It can also be defined
inside ``'preamble'`` key rather than this one.
``'releasename'``
value that prefixes ``'release'`` element on title page, default
``'Release'``. As for *title* and *author* used in the tuples of
:confval:`latex_documents`, it is inserted as LaTeX markup.
``'tableofcontents'``
"tableofcontents" call, default ``'\\sphinxtableofcontents'`` (it is a
wrapper of unmodified ``\tableofcontents``, which may itself be
customized by user loaded packages.)
Override if
you want to generate a different table of contents or put content
between the title page and the TOC.
.. versionchanged:: 1.5
Previously the meaning of ``\tableofcontents`` itself was modified
by Sphinx. This created an incompatibility with dedicated packages
modifying it also such as "tocloft" or "etoc".
``'transition'``
Commands used to display transitions, default
``'\n\n\\bigskip\\hrule\\bigskip\n\n'``. Override if you want to
display transitions differently.
.. versionadded:: 1.2
.. versionchanged:: 1.6
Remove unneeded ``{}`` after ``\\hrule``.
``'printindex'``
"printindex" call, the last thing in the file, default
``'\\printindex'``. Override if you want to generate the index
differently or append some content after the index. For example
``'\\footnotesize\\raggedright\\printindex'`` is advisable when the
index is full of long entries.
``'fvset'``
Customization of ``fancyvrb`` LaTeX package. Sphinx does by default
``'fvset': '\\fvset{fontsize=\\small}'``, to adjust for the large
character width of the monospace font, used in code-blocks.
You may need to modify this if you use custom fonts.
.. versionadded:: 1.8
.. versionchanged:: 2.0
Due to new default font choice for ``'xelatex'`` and ``'lualatex'``
(FreeFont), Sphinx does ``\\fvset{fontsize=\\small}`` also with these
engines (and not ``\\fvset{fontsize=auto}``).
* Keys that are set by other options and therefore should not be overridden
are:
``'docclass'``
``'classoptions'``
``'title'``
``'release'``
``'author'``
``'makeindex'``
.. _latexsphinxsetup: .. _latexsphinxsetup:
The LaTeX style file options \\'sphinxsetup\\' key
---------------------------- ---------------------
Additional customization is possible via LaTeX options of the Sphinx style The ``'sphinxsetup'`` key of :ref:`latex_elements <latex_elements_confval>`
file. provides a LaTeX-type customization interface::
The sphinxsetup interface
~~~~~~~~~~~~~~~~~~~~~~~~~
The ``'sphinxsetup'`` key of :confval:`latex_elements` provides a convenient
interface::
latex_elements = { latex_elements = {
'sphinxsetup': 'key1=value1, key2=value2, ...', 'sphinxsetup': 'key1=value1, key2=value2, ...',
} }
- some values may be LaTeX macros, then the backslashes must be It defaults to empty. If non-empty, it will be passed as argument to the
Python-escaped, or the whole must be a Python raw string, ``\sphinxsetup`` macro inside the document preamble, like this::
- LaTeX boolean keys require *lowercase* ``true`` or ``false`` values,
- spaces around the commas and equal signs are ignored, spaces inside LaTeX
macros may be significant.
If non-empty, it will be passed as argument to the ``\sphinxsetup`` macro
inside the document preamble, like this::
\usepackage{sphinx} \usepackage{sphinx}
\sphinxsetup{key1=value1, key2=value2,...} \sphinxsetup{key1=value1, key2=value2,...}
@ -112,7 +481,7 @@ inside the document preamble, like this::
It is possible to insert further uses of the ``\sphinxsetup`` LaTeX macro It is possible to insert further uses of the ``\sphinxsetup`` LaTeX macro
directly into the body of the document, via the help of the :rst:dir:`raw` directly into the body of the document, via the help of the :rst:dir:`raw`
directive. Here is how this present chapter in PDF is styled:: directive. Here is how this present chapter is styled in the PDF output::
.. raw:: latex .. raw:: latex
@ -147,8 +516,9 @@ inside the document preamble, like this::
} }
The available styling options LaTeX boolean keys require *lowercase* ``true`` or ``false`` values.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Spaces around the commas and equal signs are ignored, spaces inside LaTeX
macros may be significant.
.. _latexsphinxsetuphmargin: .. _latexsphinxsetuphmargin:
@ -209,7 +579,7 @@ The available styling options
the default changed from ``false`` to ``true``. the default changed from ``false`` to ``true``.
``verbatimcontinuedalign``, ``verbatimcontinuesalign`` ``verbatimcontinuedalign``, ``verbatimcontinuesalign``
default ``c``. Horizontal position relative to the framed contents: default ``r``. Horizontal position relative to the framed contents:
either ``l`` (left aligned), ``r`` (right aligned) or ``c`` (centered). either ``l`` (left aligned), ``r`` (right aligned) or ``c`` (centered).
.. versionadded:: 1.7 .. versionadded:: 1.7
@ -354,9 +724,9 @@ The available styling options
``attentionBgColor``, ``dangerBgColor``, ``attentionBgColor``, ``dangerBgColor``,
``errorBgColor`` ``errorBgColor``
.. |warningborders| replace:: ``warningBorder``, ``cautionBorder``, .. |warningborders| replace:: ``warningborder``, ``cautionborder``,
``attentionBorder``, ``dangerBorder``, ``attentionborder``, ``dangerborder``,
``errorBorder`` ``errorborder``
LaTeX macros and environments LaTeX macros and environments
----------------------------- -----------------------------
@ -365,6 +735,8 @@ Here are some macros from the package file :file:`sphinx.sty` and class files
:file:`sphinxhowto.cls`, :file:`sphinxmanual.cls`, which have public names :file:`sphinxhowto.cls`, :file:`sphinxmanual.cls`, which have public names
thus allowing redefinitions. Check the respective files for the defaults. thus allowing redefinitions. Check the respective files for the defaults.
.. _latex-macros:
Macros Macros
~~~~~~ ~~~~~~
@ -390,13 +762,32 @@ Macros
.. versionadded:: 1.6.3 .. versionadded:: 1.6.3
``\sphinxstylecodecontinued`` and ``\sphinxstylecodecontinues``. ``\sphinxstylecodecontinued`` and ``\sphinxstylecodecontinues``.
- the table of contents is typeset via ``\sphinxtableofcontents`` which is a - the table of contents is typeset via ``\sphinxtableofcontents`` which is a
wrapper (whose definition can be found in :file:`sphinxhowto.cls` or in wrapper (defined differently in :file:`sphinxhowto.cls` and in
:file:`sphinxmanual.cls`) of standard ``\tableofcontents``. :file:`sphinxmanual.cls`) of standard ``\tableofcontents``. The macro
``\sphinxtableofcontentshook`` is executed during its expansion right before
``\tableofcontents`` itself.
.. versionchanged:: 1.5 .. versionchanged:: 1.5
formerly, the meaning of ``\tableofcontents`` was modified by Sphinx. formerly, the meaning of ``\tableofcontents`` was modified by Sphinx.
- the ``\maketitle`` command is redefined by the class files .. versionchanged:: 2.0
:file:`sphinxmanual.cls` and :file:`sphinxhowto.cls`. hard-coded redefinitions of ``\l@section`` and ``\l@subsection`` formerly
done during loading of ``'manual'`` docclass are now executed later via
``\sphinxtableofcontentshook``. This macro is also executed by the
``'howto'`` docclass, but defaults to empty with it.
- a custom ``\sphinxmaketitle`` is defined in the class files
:file:`sphinxmanual.cls` and :file:`sphinxhowto.cls` and is used as
default setting of ``'maketitle'`` :confval:`latex_elements` key.
.. versionchanged:: 1.8.3
formerly, ``\maketitle`` from LaTeX document class was modified by
Sphinx.
- for ``'manual'`` docclass a macro ``\sphinxbackoftitlepage``, if it is
defined, gets executed at end of ``\sphinxmaketitle``, before the final
``\clearpage``. Use either the ``'maketitle'`` key or the ``'preamble'`` key
of :confval:`latex_elements` to add a custom definition of
``\sphinxbackoftitlepage``.
.. versionadded:: 1.8.3
- the citation reference is typeset via ``\sphinxcite`` which is a wrapper - the citation reference is typeset via ``\sphinxcite`` which is a wrapper
of standard ``\cite``. of standard ``\cite``.

View File

@ -40,7 +40,7 @@ Options
.. option:: -f, --force .. option:: -f, --force
Force overwritting of any existing generated files. Force overwriting of any existing generated files.
.. option:: -l, --follow-links .. option:: -l, --follow-links
@ -58,6 +58,10 @@ Options
Maximum depth for the generated table of contents file. Maximum depth for the generated table of contents file.
.. option:: --tocfile
Filename for a table of contents file. Defaults to ``modules``.
.. option:: -T, --no-toc .. option:: -T, --no-toc
Do not create a table of contents file. Ignored when :option:`--full` is Do not create a table of contents file. Ignored when :option:`--full` is

View File

@ -70,10 +70,6 @@ Options
Master document name. (see :confval:`master_doc`). Master document name. (see :confval:`master_doc`).
.. option:: --epub
Use epub.
.. rubric:: Extension Options .. rubric:: Extension Options
.. option:: --ext-autodoc .. option:: --ext-autodoc

View File

@ -200,6 +200,10 @@ Overriding works like this::
{% set script_files = script_files + ["_static/myscript.js"] %} {% set script_files = script_files + ["_static/myscript.js"] %}
.. deprecated:: 1.8.0
Please use ``.Sphinx.add_js_file()`` instead.
Helper Functions Helper Functions
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~

View File

@ -5,6 +5,12 @@ HTML theming support
.. versionadded:: 0.6 .. versionadded:: 0.6
.. note::
This document provides information about creating your own theme. If you
simply wish to use a pre-existing HTML themes, refer to
:doc:`/usage/theming`.
Sphinx supports changing the appearance of its HTML output via *themes*. A Sphinx supports changing the appearance of its HTML output via *themes*. A
theme is a collection of HTML templates, stylesheet(s) and other static files. theme is a collection of HTML templates, stylesheet(s) and other static files.
Additionally, it has a configuration file which specifies from which theme to Additionally, it has a configuration file which specifies from which theme to
@ -15,265 +21,13 @@ Themes are meant to be project-unaware, so they can be used for different
projects without change. projects without change.
Using a theme
-------------
Using an existing theme is easy. If the theme is builtin to Sphinx, you only
need to set the :confval:`html_theme` config value. With the
:confval:`html_theme_options` config value you can set theme-specific options
that change the look and feel. For example, you could have the following in
your :file:`conf.py`::
html_theme = "classic"
html_theme_options = {
"rightsidebar": "true",
"relbarbgcolor": "black"
}
That would give you the classic theme, but with a sidebar on the right side and
a black background for the relation bar (the bar with the navigation links at
the page's top and bottom).
If the theme does not come with Sphinx, it can be in two static forms: either a
directory (containing :file:`theme.conf` and other needed files), or a zip file
with the same contents. Either of them must be put where Sphinx can find it;
for this there is the config value :confval:`html_theme_path`. It gives a list
of directories, relative to the directory containing :file:`conf.py`, that can
contain theme directories or zip files. For example, if you have a theme in the
file :file:`blue.zip`, you can put it right in the directory containing
:file:`conf.py` and use this configuration::
html_theme = "blue"
html_theme_path = ["."]
The third form is a python package. If a theme you want to use is distributed
as a python package, you can use it after installing
.. code-block:: bash
# installing theme package
$ pip install sphinxjp.themes.dotted
# use it in your conf.py
html_theme = "dotted"
.. _builtin-themes:
Builtin themes
--------------
.. cssclass:: longtable
+--------------------+--------------------+
| **Theme overview** | |
+--------------------+--------------------+
| |alabaster| | |classic| |
| | |
| *alabaster* | *classic* |
+--------------------+--------------------+
| |sphinxdoc| | |scrolls| |
| | |
| *sphinxdoc* | *scrolls* |
+--------------------+--------------------+
| |agogo| | |traditional| |
| | |
| *agogo* | *traditional* |
+--------------------+--------------------+
| |nature| | |haiku| |
| | |
| *nature* | *haiku* |
+--------------------+--------------------+
| |pyramid| | |bizstyle| |
| | |
| *pyramid* | *bizstyle* |
+--------------------+--------------------+
.. |alabaster| image:: themes/alabaster.png
.. |classic| image:: themes/classic.png
.. |sphinxdoc| image:: themes/sphinxdoc.png
.. |scrolls| image:: themes/scrolls.png
.. |agogo| image:: themes/agogo.png
.. |traditional| image:: themes/traditional.png
.. |nature| image:: themes/nature.png
.. |haiku| image:: themes/haiku.png
.. |pyramid| image:: themes/pyramid.png
.. |bizstyle| image:: themes/bizstyle.png
Sphinx comes with a selection of themes to choose from.
.. cssclass:: clear
These themes are:
* **basic** -- This is a basically unstyled layout used as the base for the
other themes, and usable as the base for custom themes as well. The HTML
contains all important elements like sidebar and relation bar. There are
these options (which are inherited by the other themes):
- **nosidebar** (true or false): Don't include the sidebar. Defaults to
``False``.
- **sidebarwidth** (int or str): Width of the sidebar in pixels.
This can be an int, which is interpreted as pixels or a valid CSS
dimension string such as '70em' or '50%'. Defaults to 230 pixels.
- **body_min_width** (int or str): Minimal width of the document body.
This can be an int, which is interpreted as pixels or a valid CSS
dimension string such as '70em' or '50%'. Use 0 if you don't want
a width limit. Defaults may depend on the theme (often 450px).
- **body_max_width** (int or str): Maximal width of the document body.
This can be an int, which is interpreted as pixels or a valid CSS
dimension string such as '70em' or '50%'. Use 'none' if you don't
want a width limit. Defaults may depend on the theme (often 800px).
* **alabaster** -- `Alabaster theme`_ is a modified "Kr" Sphinx theme from @kennethreitz
(especially as used in his Requests project), which was itself originally based on
@mitsuhiko's theme used for Flask & related projects.
Check out at its `installation page`_ how to set up properly
:confval:`html_sidebars` for its use.
.. _Alabaster theme: https://pypi.org/project/alabaster/
.. _installation page: https://alabaster.readthedocs.io/en/latest/installation.html
* **classic** -- This is the classic theme, which looks like `the Python 2
documentation <https://docs.python.org/2/>`_. It can be customized via
these options:
- **rightsidebar** (true or false): Put the sidebar on the right side.
Defaults to ``False``.
- **stickysidebar** (true or false): Make the sidebar "fixed" so that it
doesn't scroll out of view for long body content. This may not work well
with all browsers. Defaults to ``False``.
- **collapsiblesidebar** (true or false): Add an *experimental* JavaScript
snippet that makes the sidebar collapsible via a button on its side.
Defaults to ``False``.
- **externalrefs** (true or false): Display external links differently from
internal links. Defaults to ``False``.
There are also various color and font options that can change the color scheme
without having to write a custom stylesheet:
- **footerbgcolor** (CSS color): Background color for the footer line.
- **footertextcolor** (CSS color): Text color for the footer line.
- **sidebarbgcolor** (CSS color): Background color for the sidebar.
- **sidebarbtncolor** (CSS color): Background color for the sidebar collapse
button (used when *collapsiblesidebar* is ``True``).
- **sidebartextcolor** (CSS color): Text color for the sidebar.
- **sidebarlinkcolor** (CSS color): Link color for the sidebar.
- **relbarbgcolor** (CSS color): Background color for the relation bar.
- **relbartextcolor** (CSS color): Text color for the relation bar.
- **relbarlinkcolor** (CSS color): Link color for the relation bar.
- **bgcolor** (CSS color): Body background color.
- **textcolor** (CSS color): Body text color.
- **linkcolor** (CSS color): Body link color.
- **visitedlinkcolor** (CSS color): Body color for visited links.
- **headbgcolor** (CSS color): Background color for headings.
- **headtextcolor** (CSS color): Text color for headings.
- **headlinkcolor** (CSS color): Link color for headings.
- **codebgcolor** (CSS color): Background color for code blocks.
- **codetextcolor** (CSS color): Default text color for code blocks, if not
set differently by the highlighting style.
- **bodyfont** (CSS font-family): Font for normal text.
- **headfont** (CSS font-family): Font for headings.
* **sphinxdoc** -- The theme originally used by this documentation. It features
a sidebar on the right side. There are currently no options beyond
*nosidebar* and *sidebarwidth*.
.. note::
The Sphinx documentation now uses
`an adjusted version of the sphinxdoc theme
<https://github.com/sphinx-doc/sphinx/tree/master/doc/_themes/sphinx13>`_.
* **scrolls** -- A more lightweight theme, based on `the Jinja documentation
<http://jinja.pocoo.org/>`_. The following color options are available:
- **headerbordercolor**
- **subheadlinecolor**
- **linkcolor**
- **visitedlinkcolor**
- **admonitioncolor**
* **agogo** -- A theme created by Andi Albrecht. The following options are
supported:
- **bodyfont** (CSS font family): Font for normal text.
- **headerfont** (CSS font family): Font for headings.
- **pagewidth** (CSS length): Width of the page content, default 70em.
- **documentwidth** (CSS length): Width of the document (without sidebar),
default 50em.
- **sidebarwidth** (CSS length): Width of the sidebar, default 20em.
- **bgcolor** (CSS color): Background color.
- **headerbg** (CSS value for "background"): background for the header area,
default a grayish gradient.
- **footerbg** (CSS value for "background"): background for the footer area,
default a light gray gradient.
- **linkcolor** (CSS color): Body link color.
- **headercolor1**, **headercolor2** (CSS color): colors for <h1> and <h2>
headings.
- **headerlinkcolor** (CSS color): Color for the backreference link in
headings.
- **textalign** (CSS *text-align* value): Text alignment for the body, default
is ``justify``.
* **nature** -- A greenish theme. There are currently no options beyond
*nosidebar* and *sidebarwidth*.
* **pyramid** -- A theme from the Pyramid web framework project, designed by
Blaise Laflamme. There are currently no options beyond *nosidebar* and
*sidebarwidth*.
* **haiku** -- A theme without sidebar inspired by the `Haiku OS user guide
<https://www.haiku-os.org/docs/userguide/en/contents.html>`_. The following
options are supported:
- **full_logo** (true or false, default ``False``): If this is true, the
header will only show the :confval:`html_logo`. Use this for large logos.
If this is false, the logo (if present) will be shown floating right, and
the documentation title will be put in the header.
- **textcolor**, **headingcolor**, **linkcolor**, **visitedlinkcolor**,
**hoverlinkcolor** (CSS colors): Colors for various body elements.
* **traditional** -- A theme resembling the old Python documentation. There are
currently no options beyond *nosidebar* and *sidebarwidth*.
* **epub** -- A theme for the epub builder. This theme tries to save visual
space which is a sparse resource on ebook readers. The following options
are supported:
- **relbar1** (true or false, default ``True``): If this is true, the
`relbar1` block is inserted in the epub output, otherwise it is omitted.
- **footer** (true or false, default ``True``): If this is true, the
`footer` block is inserted in the epub output, otherwise it is omitted.
- **bizstyle** -- A simple bluish theme. The following options are supported
beyond *nosidebar* and *sidebarwidth*:
- **rightsidebar** (true or false): Put the sidebar on the right side.
Defaults to ``False``.
.. versionadded:: 1.3
'alabaster', 'sphinx_rtd_theme' and 'bizstyle' theme.
.. versionchanged:: 1.3
The 'default' theme has been renamed to 'classic'. 'default' is still
available, however it will emit a notice that it is an alias for the new
'alabaster' theme.
Creating themes Creating themes
--------------- ---------------
As said, themes are either a directory or a zipfile (whose name is the theme Themes take the form of either a directory or a zipfile (whose name is the
name), containing the following: theme name), containing the following:
* A :file:`theme.conf` file, see below. * A :file:`theme.conf` file.
* HTML templates, if needed. * HTML templates, if needed.
* A ``static/`` directory containing any static files that will be copied to the * A ``static/`` directory containing any static files that will be copied to the
output static directory on build. These can be images, styles, script files. output static directory on build. These can be images, styles, script files.
@ -295,7 +49,8 @@ Python :mod:`ConfigParser` module) and has the following structure:
* The **inherit** setting gives the name of a "base theme", or ``none``. The * The **inherit** setting gives the name of a "base theme", or ``none``. The
base theme will be used to locate missing templates (most themes will not have base theme will be used to locate missing templates (most themes will not have
to supply most templates if they use ``basic`` as the base theme), its options to supply most templates if they use ``basic`` as the base theme), its options
will be inherited, and all of its static files will be used as well. will be inherited, and all of its static files will be used as well. If you want
to also inherit the stylesheet, include it via CSS' ``@import`` in your own.
* The **stylesheet** setting gives the name of a CSS file which will be * The **stylesheet** setting gives the name of a CSS file which will be
referenced in the HTML header. If you need more than one CSS file, either referenced in the HTML header. If you need more than one CSS file, either
@ -318,16 +73,17 @@ Python :mod:`ConfigParser` module) and has the following structure:
.. versionadded:: 1.7 .. versionadded:: 1.7
sidebar settings sidebar settings
.. _distribute-your-theme: .. _distribute-your-theme:
Distribute your theme as a python package Distribute your theme as a Python package
----------------------------------------- -----------------------------------------
As a way to distribute your theme, you can use python package. Python package As a way to distribute your theme, you can use Python package. Python package
brings to users easy setting up ways. brings to users easy setting up ways.
To distribute your theme as a python package, please define an entry point To distribute your theme as a Python package, please define an entry point
called ``sphinx.html_themes`` in your setup.py file, and write a ``setup()`` called ``sphinx.html_themes`` in your ``setup.py`` file, and write a ``setup()``
function to register your themes using ``add_html_theme()`` API in it:: function to register your themes using ``add_html_theme()`` API in it::
# 'setup.py' # 'setup.py'
@ -347,9 +103,8 @@ function to register your themes using ``add_html_theme()`` API in it::
def setup(app): def setup(app):
app.add_html_theme('name_of_theme', path.abspath(path.dirname(__file__))) app.add_html_theme('name_of_theme', path.abspath(path.dirname(__file__)))
If your theme package contains two or more themes, please call
If your theme package contains two or more themes, please call ``add_html_theme()`` ``add_html_theme()`` twice or more.
twice or more.
.. versionadded:: 1.2 .. versionadded:: 1.2
'sphinx_themes' entry_points feature. 'sphinx_themes' entry_points feature.
@ -360,8 +115,9 @@ twice or more.
.. versionadded:: 1.6 .. versionadded:: 1.6
``sphinx.html_themes`` entry_points feature. ``sphinx.html_themes`` entry_points feature.
Templating Templating
~~~~~~~~~~ ----------
The :doc:`guide to templating <templating>` is helpful if you want to write your The :doc:`guide to templating <templating>` is helpful if you want to write your
own templates. What is important to keep in mind is the order in which Sphinx own templates. What is important to keep in mind is the order in which Sphinx
@ -376,7 +132,6 @@ name as an explicit directory: ``{% extends "basic/layout.html" %}``. From a
user ``templates_path`` template, you can still use the "exclamation mark" user ``templates_path`` template, you can still use the "exclamation mark"
syntax as described in the templating document. syntax as described in the templating document.
Static templates Static templates
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
@ -393,40 +148,6 @@ templating to put the color options into the stylesheet. When a documentation
is built with the classic theme, the output directory will contain a is built with the classic theme, the output directory will contain a
``_static/classic.css`` file where all template tags have been processed. ``_static/classic.css`` file where all template tags have been processed.
.. [1] It is not an executable Python file, as opposed to :file:`conf.py`, .. [1] It is not an executable Python file, as opposed to :file:`conf.py`,
because that would pose an unnecessary security risk if themes are because that would pose an unnecessary security risk if themes are
shared. shared.
Third Party Themes
------------------
.. cssclass:: longtable
+--------------------+--------------------+
| **Theme overview** | |
+--------------------+--------------------+
| |sphinx_rtd_theme| | |
| | |
| *sphinx_rtd_theme* | |
+--------------------+--------------------+
.. |sphinx_rtd_theme| image:: themes/sphinx_rtd_theme.png
* **sphinx_rtd_theme** -- `Read the Docs Sphinx Theme`_.
This is a mobile-friendly sphinx theme that was made for readthedocs.org.
View a working demo over on readthedocs.org. You can get install and options
information at `Read the Docs Sphinx Theme`_ page.
.. _Read the Docs Sphinx Theme: https://pypi.org/project/sphinx_rtd_theme/
.. versionchanged:: 1.4
**sphinx_rtd_theme** has become optional.
Besides this, there are a lot of third party themes. You can find them on
PyPI__, GitHub__, sphinx-themes.org__ and so on.
.. __: https://pypi.org/search/?q=&o=&c=Framework+%3A%3A+Sphinx+%3A%3A+Theme
.. __: https://github.com/search?utf8=%E2%9C%93&q=sphinx+theme&type=
.. __: https://sphinx-themes.org/

View File

@ -9,7 +9,7 @@ Complementary to translations provided for Sphinx-generated messages such as
navigation bars, Sphinx provides mechanisms facilitating *document* translations navigation bars, Sphinx provides mechanisms facilitating *document* translations
in itself. See the :ref:`intl-options` for details on configuration. in itself. See the :ref:`intl-options` for details on configuration.
.. figure:: translation.png .. figure:: /_static/translation.png
:width: 100% :width: 100%
Workflow visualization of translations in Sphinx. (The stick-figure is taken Workflow visualization of translations in Sphinx. (The stick-figure is taken
@ -46,14 +46,14 @@ They can be delivered to translators which will transform them to ``.po`` files
--- so called **message catalogs** --- containing a mapping from the original --- so called **message catalogs** --- containing a mapping from the original
messages to foreign-language strings. messages to foreign-language strings.
Gettext compiles them into a binary format known as **binary catalogs** through *gettext* compiles them into a binary format known as **binary catalogs**
:program:`msgfmt` for efficiency reasons. If you make these files discoverable through :program:`msgfmt` for efficiency reasons. If you make these files
with :confval:`locale_dirs` for your :confval:`language`, Sphinx will pick them discoverable with :confval:`locale_dirs` for your :confval:`language`, Sphinx
up automatically. will pick them up automatically.
An example: you have a document ``usage.rst`` in your Sphinx project. The An example: you have a document ``usage.rst`` in your Sphinx project. The
gettext builder will put its messages into ``usage.pot``. Imagine you have *gettext* builder will put its messages into ``usage.pot``. Imagine you have
Spanish translations [2]_ on your hands in ``usage.po`` --- for your builds to Spanish translations [2]_ stored in ``usage.po`` --- for your builds to
be translated you need to follow these instructions: be translated you need to follow these instructions:
* Compile your message catalog to a locale directory, say ``locale``, so it * Compile your message catalog to a locale directory, say ``locale``, so it
@ -63,7 +63,8 @@ be translated you need to follow these instructions:
msgfmt "usage.po" -o "locale/es/LC_MESSAGES/usage.mo" msgfmt "usage.po" -o "locale/es/LC_MESSAGES/usage.mo"
* Set :confval:`locale_dirs` to ``["locale/"]``. * Set :confval:`locale_dirs` to ``["locale/"]``.
* Set :confval:`language` to ``es`` (also possible via :option:`-D <sphinx-build -D>`). * Set :confval:`language` to ``es`` (also possible via
:option:`-D <sphinx-build -D>`).
* Run your desired build. * Run your desired build.
@ -71,97 +72,66 @@ Translating with sphinx-intl
---------------------------- ----------------------------
Quick guide Quick guide
^^^^^^^^^^^ ~~~~~~~~~~~
`sphinx-intl`_ is a useful tool to work with Sphinx translation flow. `sphinx-intl`_ is a useful tool to work with Sphinx translation flow. This
This section describe an easy way to translate with sphinx-intl. section describe an easy way to translate with *sphinx-intl*.
#. Install `sphinx-intl`_ by :command:`pip install sphinx-intl` or #. Install `sphinx-intl`_.
:command:`easy_install sphinx-intl`.
#. Add configurations to your `conf.py`:: .. code-block:: console
$ pip install sphinx-intl
#. Add configurations to ``conf.py``.
::
locale_dirs = ['locale/'] # path is example but recommended. locale_dirs = ['locale/'] # path is example but recommended.
gettext_compact = False # optional. gettext_compact = False # optional.
This case-study assumes that :confval:`locale_dirs` is set to 'locale/' and This case-study assumes that :confval:`locale_dirs` is set to ``locale/`` and
:confval:`gettext_compact` is set to `False` (the Sphinx document is :confval:`gettext_compact` is set to ``False`` (the Sphinx document is
already configured as such). already configured as such).
#. Extract document's translatable messages into pot files: #. Extract translatable messages into pot files.
.. code-block:: console .. code-block:: console
$ make gettext $ make gettext
As a result, many pot files are generated under ``_build/gettext`` The generated pot files will be placed in the ``_build/gettext`` directory.
directory.
#. Setup/Update your `locale_dir`: #. Generate po files.
We'll use the pot files generated in the above step.
.. code-block:: console .. code-block:: console
$ sphinx-intl update -p _build/gettext -l de -l ja $ sphinx-intl update -p _build/gettext -l de -l ja
Done. You got these directories that contain po files: Once completed, the generated po files will be placed in the below
directories:
* `./locale/de/LC_MESSAGES/` * ``./locale/de/LC_MESSAGES/``
* `./locale/ja/LC_MESSAGES/` * ``./locale/ja/LC_MESSAGES/``
#. Translate your po files under `./locale/<lang>/LC_MESSAGES/`. #. Translate po files.
#. make translated document. AS noted above, these are located in the ``./locale/<lang>/LC_MESSAGES``
directory. An example of one such file, from Sphinx, ``builders.po``, is
given below.
You need a :confval:`language` parameter in ``conf.py`` or you may also .. code-block:: po
specify the parameter on the command line (for BSD/GNU make):
.. code-block:: console
$ make -e SPHINXOPTS="-D language='de'" html
command line (for Windows cmd.exe):
.. code-block:: console
> set SPHINXOPTS=-D language=de
> .\make.bat html
command line (for PowerShell):
.. code-block:: console
> Set-Item env:SPHINXOPTS "-D language=de"
> .\make.bat html
Congratulations! You got the translated documentation in the ``_build/html``
directory.
.. versionadded:: 1.3
sphinx-build that is invoked by make command will build po files into mo files.
If you are using 1.2.x or earlier, please invoke ``sphinx-intl build`` command
before make command.
Translating
^^^^^^^^^^^
Translate po file under ``./locale/de/LC_MESSAGES`` directory.
The case of builders.po file for sphinx document:
.. code-block:: po
# a5600c3d2e3d48fc8c261ea0284db79b # a5600c3d2e3d48fc8c261ea0284db79b
#: ../../builders.rst:4 #: ../../builders.rst:4
msgid "Available builders" msgid "Available builders"
msgstr "<FILL HERE BY TARGET LANGUAGE>" msgstr "<FILL HERE BY TARGET LANGUAGE>"
Another case, msgid is multi-line text and contains reStructuredText Another case, msgid is multi-line text and contains reStructuredText syntax:
syntax:
.. code-block:: po .. code-block:: po
# 302558364e1d41c69b3277277e34b184 # 302558364e1d41c69b3277277e34b184
#: ../../builders.rst:9 #: ../../builders.rst:9
@ -172,17 +142,54 @@ syntax:
"FILL HERE BY TARGET LANGUAGE FILL HERE BY TARGET LANGUAGE FILL HERE " "FILL HERE BY TARGET LANGUAGE FILL HERE BY TARGET LANGUAGE FILL HERE "
"BY TARGET LANGUAGE :ref:`EXTENSIONS <extensions>` FILL HERE." "BY TARGET LANGUAGE :ref:`EXTENSIONS <extensions>` FILL HERE."
Please be careful not to break reST notation. Most po-editors will help you Please be careful not to break reST notation. Most po-editors will help you
with that. with that.
#. Build translated document.
You need a :confval:`language` parameter in ``conf.py`` or you may also
specify the parameter on the command line.
For for BSD/GNU make, run:
.. code-block:: console
$ make -e SPHINXOPTS="-D language='de'" html
For Windows :command:`cmd.exe`, run:
.. code-block:: console
> set SPHINXOPTS=-D language=de
> .\make.bat html
For PowerShell, run:
.. code-block:: console
> Set-Item env:SPHINXOPTS "-D language=de"
> .\make.bat html
Congratulations! You got the translated documentation in the ``_build/html``
directory.
.. versionadded:: 1.3
:program:`sphinx-build` that is invoked by make command will build po files
into mo files.
If you are using 1.2.x or earlier, please invoke :command:`sphinx-intl build`
command before :command:`make` command.
Translating
~~~~~~~~~~~
Update your po files by new pot files Update your po files by new pot files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If a document is updated, it is necessary to generate updated pot files If a document is updated, it is necessary to generate updated pot files and to
and to apply differences to translated po files. apply differences to translated po files. In order to apply the updates from a
In order to apply the updating difference of a pot file to po file, pot file to the po file, use the :command:`sphinx-intl update` command.
use the :command:`sphinx-intl update` command.
.. code-block:: console .. code-block:: console
@ -199,7 +206,7 @@ easy to fetch and push translations.
.. TODO: why use transifex? .. TODO: why use transifex?
#. Install `transifex-client`_ #. Install `transifex-client`_.
You need :command:`tx` command to upload resources (pot files). You need :command:`tx` command to upload resources (pot files).
@ -209,8 +216,7 @@ easy to fetch and push translations.
.. seealso:: `Transifex Client documentation`_ .. seealso:: `Transifex Client documentation`_
#. Create your transifex_ account and create new project for your document.
#. Create your transifex_ account and create new project for your document
Currently, transifex does not allow for a translation project to have more Currently, transifex does not allow for a translation project to have more
than one version of the document, so you'd better include a version number in than one version of the document, so you'd better include a version number in
@ -221,8 +227,7 @@ easy to fetch and push translations.
:Project ID: ``sphinx-document-test_1_0`` :Project ID: ``sphinx-document-test_1_0``
:Project URL: ``https://www.transifex.com/projects/p/sphinx-document-test_1_0/`` :Project URL: ``https://www.transifex.com/projects/p/sphinx-document-test_1_0/``
#. Create config files for :command:`tx` command.
#. Create config files for tx command
This process will create ``.tx/config`` in the current directory, as well as This process will create ``.tx/config`` in the current directory, as well as
a ``~/.transifexrc`` file that includes auth information. a ``~/.transifexrc`` file that includes auth information.
@ -238,7 +243,7 @@ easy to fetch and push translations.
... ...
Done. Done.
#. Upload pot files to transifex service #. Upload pot files to transifex service.
Register pot files to ``.tx/config`` file: Register pot files to ``.tx/config`` file:
@ -259,15 +264,14 @@ easy to fetch and push translations.
... ...
Done. Done.
#. Forward the translation on transifex.
#. Forward the translation on transifex
.. TODO: write this section .. TODO: write this section
#. Pull translated po files and make translated HTML.
#. Pull translated po files and make translated html Get translated catalogs and build mo files. For example, to build mo files
for German (de):
Get translated catalogs and build mo files (ex. for 'de'):
.. code-block:: console .. code-block:: console
@ -278,32 +282,29 @@ easy to fetch and push translations.
... ...
Done. Done.
Invoke make html (for BSD/GNU make): Invoke :command:`make html` (for BSD/GNU make):
.. code-block:: console .. code-block:: console
$ make -e SPHINXOPTS="-D language='de'" html $ make -e SPHINXOPTS="-D language='de'" html
That's all! That's all!
.. tip:: Translating locally and on Transifex .. tip:: Translating locally and on Transifex
If you want to push all language's po files, you can be done by using If you want to push all language's po files, you can be done by using
:command:`tx push -t` command. :command:`tx push -t` command. Watch out! This operation overwrites
Watch out! This operation overwrites translations in transifex. translations in transifex.
In other words, if you have updated each in the service and local po files, In other words, if you have updated each in the service and local po files,
it would take much time and effort to integrate them. it would take much time and effort to integrate them.
Contributing to Sphinx reference translation Contributing to Sphinx reference translation
-------------------------------------------- --------------------------------------------
The recommended way for new contributors to translate Sphinx reference The recommended way for new contributors to translate Sphinx reference is to
is to join the translation team on Transifex. join the translation team on Transifex.
There is `sphinx translation page`_ for Sphinx (master) documentation. There is `sphinx translation page`_ for Sphinx (master) documentation.
@ -311,8 +312,7 @@ There is `sphinx translation page`_ for Sphinx (master) documentation.
2. Go to `sphinx translation page`_. 2. Go to `sphinx translation page`_.
3. Click ``Request language`` and fill form. 3. Click ``Request language`` and fill form.
4. Wait acceptance by transifex sphinx translation maintainers. 4. Wait acceptance by transifex sphinx translation maintainers.
5. (after acceptance) translate on transifex. 5. (After acceptance) Translate on transifex.
.. rubric:: Footnotes .. rubric:: Footnotes
@ -321,9 +321,8 @@ There is `sphinx translation page`_ for Sphinx (master) documentation.
for details on that software suite. for details on that software suite.
.. [2] Because nobody expects the Spanish Inquisition! .. [2] Because nobody expects the Spanish Inquisition!
.. _`transifex-client`: https://pypi.org/project/transifex-client/ .. _`transifex-client`: https://pypi.org/project/transifex-client/
.. _`sphinx-intl`: https://pypi.org/project/sphinx-intl/ .. _`sphinx-intl`: https://pypi.org/project/sphinx-intl/
.. _Transifex: https://www.transifex.com/ .. _Transifex: https://www.transifex.com/
.. _`sphinx translation page`: https://www.transifex.com/sphinx-doc/sphinx-doc/ .. _`sphinx translation page`: https://www.transifex.com/sphinx-doc/sphinx-doc/
.. _`Transifex Client documentation`: http://docs.transifex.com/developer/client/ .. _`Transifex Client documentation`: https://docs.transifex.com/client/introduction/

View File

@ -65,7 +65,7 @@ The WebSupport Class
Methods Methods
~~~~~~~ -------
.. automethod:: sphinxcontrib.websupport.WebSupport.build .. automethod:: sphinxcontrib.websupport.WebSupport.build

View File

@ -10,7 +10,7 @@ web application. To learn more read the :ref:`websupportquickstart`.
.. toctree:: .. toctree::
web/quickstart quickstart
web/api api
web/searchadapters searchadapters
web/storagebackends storagebackends

View File

@ -4,7 +4,7 @@ Web Support Quick Start
======================= =======================
Building Documentation Data Building Documentation Data
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ----------------------------
To make use of the web support package in your application you'll need to build To make use of the web support package in your application you'll need to build
the data it uses. This data includes pickle files representing documents, the data it uses. This data includes pickle files representing documents,
@ -20,11 +20,11 @@ things are in a document. To do this you will need to create an instance of the
support.build() support.build()
This will read reStructuredText sources from `srcdir` and place the necessary This will read reStructuredText sources from ``srcdir`` and place the necessary
data in `builddir`. The `builddir` will contain two sub-directories: one named data in ``builddir``. The ``builddir`` will contain two sub-directories: one
"data" that contains all the data needed to display documents, search through named "data" that contains all the data needed to display documents, search
documents, and add comments to documents. The other directory will be called through documents, and add comments to documents. The other directory will be
"static" and contains static files that should be served from "/static". called "static" and contains static files that should be served from "/static".
.. note:: .. note::
@ -34,7 +34,7 @@ documents, and add comments to documents. The other directory will be called
Integrating Sphinx Documents Into Your Webapp Integrating Sphinx Documents Into Your Webapp
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ----------------------------------------------
Now that the data is built, it's time to do something useful with it. Start off Now that the data is built, it's time to do something useful with it. Start off
by creating a :class:`~.WebSupport` object for your application:: by creating a :class:`~.WebSupport` object for your application::
@ -96,7 +96,7 @@ integrate with your existing templating system. An example using `Jinja2
Authentication Authentication
-------------- ~~~~~~~~~~~~~~
To use certain features such as voting, it must be possible to authenticate To use certain features such as voting, it must be possible to authenticate
users. The details of the authentication are left to your application. Once a users. The details of the authentication are left to your application. Once a
@ -146,13 +146,14 @@ add this data to the ``COMMENT_OPTIONS`` that are used in the template.
Performing Searches Performing Searches
~~~~~~~~~~~~~~~~~~~ -------------------
To use the search form built-in to the Sphinx sidebar, create a function to To use the search form built-in to the Sphinx sidebar, create a function to
handle requests to the url 'search' relative to the documentation root. The handle requests to the URL 'search' relative to the documentation root. The
user's search query will be in the GET parameters, with the key `q`. Then use user's search query will be in the GET parameters, with the key `q`. Then use
the :meth:`~sphinxcontrib.websupport.WebSupport.get_search_results` method to retrieve the :meth:`~sphinxcontrib.websupport.WebSupport.get_search_results` method to
search results. In `Flask <http://flask.pocoo.org/>`_ that would be like this:: retrieve search results. In `Flask <http://flask.pocoo.org/>`_ that would be
like this::
@app.route('/search') @app.route('/search')
def search(): def search():
@ -167,7 +168,7 @@ does.
Comments & Proposals Comments & Proposals
~~~~~~~~~~~~~~~~~~~~ --------------------
Now that this is done it's time to define the functions that handle the AJAX Now that this is done it's time to define the functions that handle the AJAX
calls from the script. You will need three functions. The first function is calls from the script. You will need three functions. The first function is
@ -186,9 +187,9 @@ used to add a new comment, and will call the web support method
username=username, proposal=proposal) username=username, proposal=proposal)
return jsonify(comment=comment) return jsonify(comment=comment)
You'll notice that both a `parent_id` and `node_id` are sent with the You'll notice that both a ``parent_id`` and ``node_id`` are sent with the
request. If the comment is being attached directly to a node, `parent_id` request. If the comment is being attached directly to a node, ``parent_id``
will be empty. If the comment is a child of another comment, then `node_id` will be empty. If the comment is a child of another comment, then ``node_id``
will be empty. Then next function handles the retrieval of comments for a will be empty. Then next function handles the retrieval of comments for a
specific node, and is aptly named specific node, and is aptly named
:meth:`~sphinxcontrib.websupport.WebSupport.get_data`:: :meth:`~sphinxcontrib.websupport.WebSupport.get_data`::
@ -217,11 +218,11 @@ and will handle user votes on comments::
Comment Moderation Comment Moderation
~~~~~~~~~~~~~~~~~~ ------------------
By default, all comments added through :meth:`~.WebSupport.add_comment` are By default, all comments added through :meth:`~.WebSupport.add_comment` are
automatically displayed. If you wish to have some form of moderation, you can automatically displayed. If you wish to have some form of moderation, you can
pass the `displayed` keyword argument:: pass the ``displayed`` keyword argument::
comment = support.add_comment(text, node_id='node_id', comment = support.add_comment(text, node_id='node_id',
parent_id='parent_id', parent_id='parent_id',

View File

@ -26,13 +26,13 @@ documentation of the :class:`BaseSearch` class below.
BaseSearch class is moved to sphinxcontrib.websupport.search from BaseSearch class is moved to sphinxcontrib.websupport.search from
sphinx.websupport.search. sphinx.websupport.search.
BaseSearch Methods Methods
~~~~~~~~~~~~~~~~~~ -------
The following methods are defined in the BaseSearch class. Some methods do The following methods are defined in the BaseSearch class. Some methods do not
not need to be overridden, but some (:meth:`~BaseSearch.add_document` and need to be overridden, but some (:meth:`~BaseSearch.add_document` and
:meth:`~BaseSearch.handle_query`) must be overridden in your subclass. For a :meth:`~BaseSearch.handle_query`) must be overridden in your subclass. For a
working example, look at the built-in adapter for whoosh. working example, look at the built-in adapter for whoosh.
.. automethod:: BaseSearch.init_indexing .. automethod:: BaseSearch.init_indexing

View File

@ -27,8 +27,8 @@ documentation of the :class:`StorageBackend` class below.
sphinx.websupport.storage. sphinx.websupport.storage.
StorageBackend Methods Methods
~~~~~~~~~~~~~~~~~~~~~~ -------
.. automethod:: StorageBackend.pre_build .. automethod:: StorageBackend.pre_build

View File

@ -72,13 +72,17 @@ The builder's "name" must be given to the **-b** command-line option of
.. autoattribute:: supported_image_types .. autoattribute:: supported_image_types
.. module:: sphinx.builders.qthelp .. module:: sphinxcontrib.qthelp
.. class:: QtHelpBuilder .. class:: QtHelpBuilder
This builder produces the same output as the standalone HTML builder, but This builder produces the same output as the standalone HTML builder, but
also generates `Qt help`_ collection support files that allow the Qt also generates `Qt help`_ collection support files that allow the Qt
collection generator to compile them. collection generator to compile them.
.. versionchanged:: 2.0
Moved to sphinxcontrib.qthelp from sphinx.builders package.
.. autoattribute:: name .. autoattribute:: name
.. autoattribute:: format .. autoattribute:: format
@ -87,7 +91,7 @@ The builder's "name" must be given to the **-b** command-line option of
.. _Qt help: https://doc.qt.io/qt-4.8/qthelp-framework.html .. _Qt help: https://doc.qt.io/qt-4.8/qthelp-framework.html
.. module:: sphinx.builders.applehelp .. module:: sphinxcontrib.applehelp
.. class:: AppleHelpBuilder .. class:: AppleHelpBuilder
This builder produces an Apple Help Book based on the same output as the This builder produces an Apple Help Book based on the same output as the
@ -113,7 +117,11 @@ The builder's "name" must be given to the **-b** command-line option of
.. versionadded:: 1.3 .. versionadded:: 1.3
.. module:: sphinx.builders.devhelp .. versionchanged:: 2.0
Moved to sphinxcontrib.applehelp from sphinx.builders package.
.. module:: sphinxcontrib.devhelp
.. class:: DevhelpBuilder .. class:: DevhelpBuilder
This builder produces the same output as the standalone HTML builder, but This builder produces the same output as the standalone HTML builder, but
@ -126,6 +134,10 @@ The builder's "name" must be given to the **-b** command-line option of
.. autoattribute:: supported_image_types .. autoattribute:: supported_image_types
.. versionchanged:: 2.0
Moved to sphinxcontrib.devhelp from sphinx.builders package.
.. module:: sphinx.builders.epub3 .. module:: sphinx.builders.epub3
.. class:: Epub3Builder .. class:: Epub3Builder
@ -158,17 +170,34 @@ The builder's "name" must be given to the **-b** command-line option of
chapter :ref:`latex-options` for details. chapter :ref:`latex-options` for details.
The produced LaTeX file uses several LaTeX packages that may not be present The produced LaTeX file uses several LaTeX packages that may not be present
in a "minimal" TeX distribution installation. For example, on Ubuntu, the in a "minimal" TeX distribution installation.
following packages need to be installed for successful PDF builds:
On Ubuntu xenial, the following packages need to be installed for
successful PDF builds:
* ``texlive-latex-recommended`` * ``texlive-latex-recommended``
* ``texlive-fonts-recommended`` * ``texlive-fonts-recommended``
* ``texlive-latex-extra`` * ``texlive-latex-extra``
* ``latexmk`` (for ``make latexpdf`` on GNU/Linux and MacOS X) * ``latexmk`` (this is a Sphinx requirement on GNU/Linux and MacOS X
* ``texlive-luatex``, ``texlive-xetex`` (see :confval:`latex_engine`) for functioning of ``make latexpdf``)
The testing of Sphinx LaTeX is done on Ubuntu xenial with the above mentioned Additional packages are needed in some circumstances (see the discussion of
packages, which are from a TeXLive 2015 snapshot dated March 2016. the ``'fontpkg'`` key of :confval:`latex_elements` for more information):
* to support occasional Cyrillic letters or words, and a fortiori if
:confval:`language` is set to a Cyrillic language, the package
``texlive-lang-cyrillic`` is required, and, with unmodified ``'fontpkg'``,
also ``cm-super`` or ``cm-super-minimal``,
* to support occasional Greek letters or words (in text, not in
:rst:dir:`math` directive contents), ``texlive-lang-greek`` is required,
and, with unmodified ``'fontpkg'``, also ``cm-super`` or
``cm-super-minimal``,
* for ``'xelatex'`` or ``'lualatex'`` (see :confval:`latex_engine`),
``texlive-xetex`` resp. ``texlive-luatex``, and, if leaving unchanged
``'fontpkg'``, ``fonts-freefont-otf``.
The testing of Sphinx LaTeX is done on Ubuntu xenial whose TeX distribution
is based on a TeXLive 2015 snapshot dated March 2016.
.. versionchanged:: 1.6 .. versionchanged:: 1.6
Formerly, testing had been done on Ubuntu precise (TeXLive 2009). Formerly, testing had been done on Ubuntu precise (TeXLive 2009).
@ -191,20 +220,16 @@ The builder's "name" must be given to the **-b** command-line option of
reduces console output to a minimum. reduces console output to a minimum.
Also, if ``latexmk`` version is 4.52b or higher (Jan 17) Also, if ``latexmk`` is at version 4.52b or higher (January 2017)
``LATEXMKOPTS="-xelatex"`` will speed up PDF builds via XeLateX in case ``LATEXMKOPTS="-xelatex"`` speeds up PDF builds via XeLateX in case
of numerous graphics inclusions. of numerous graphics inclusions.
.. code-block:: console To pass options directly to the ``(pdf|xe|lua)latex`` binary, use
variable ``LATEXOPTS``, for example:
make latexpdf LATEXMKOPTS="-xelatex"
To pass options directly to the ``(pdf|xe|lua)latex`` executable, use
variable ``LATEXOPTS``.
.. code-block:: console .. code-block:: console
make latexpdf LATEXOPTS="--interaction=nonstopmode" make latexpdf LATEXOPTS="--halt-on-error"
.. autoattribute:: name .. autoattribute:: name
@ -216,7 +241,7 @@ Note that a direct PDF builder is being provided by `rinohtype`_. The builder's
name is ``rinoh``. Refer to the `rinohtype manual`_ for details. name is ``rinoh``. Refer to the `rinohtype manual`_ for details.
.. _rinohtype: https://github.com/brechtm/rinohtype .. _rinohtype: https://github.com/brechtm/rinohtype
.. _rinohtype manual: http://www.mos6581.org/rinohtype/quickstart.html#sphinx-builder .. _rinohtype manual: https://www.mos6581.org/rinohtype/quickstart.html#sphinx-builder
.. module:: sphinx.builders.text .. module:: sphinx.builders.text
.. class:: TextBuilder .. class:: TextBuilder

View File

@ -40,9 +40,7 @@ Important points to note:
contain the file name extension. contain the file name extension.
* Since :file:`conf.py` is read as a Python file, the usual rules apply for * Since :file:`conf.py` is read as a Python file, the usual rules apply for
encodings and Unicode support: declare the encoding using an encoding cookie encodings and Unicode support.
(a comment like ``# -*- coding: utf-8 -*-``) and use Unicode string literals
when you include non-ASCII characters in configuration values.
* The contents of the config namespace are pickled (so that Sphinx can find out * The contents of the config namespace are pickled (so that Sphinx can find out
when configuration changes), so it may not contain unpickleable values -- when configuration changes), so it may not contain unpickleable values --
@ -60,6 +58,36 @@ Important points to note:
created *after* the builder is initialized. created *after* the builder is initialized.
Project information
-------------------
.. confval:: project
The documented project's name.
.. confval:: author
The author name(s) of the document. The default value is ``'unknown'``.
.. confval:: copyright
A copyright statement in the style ``'2008, Author Name'``.
.. confval:: version
The major project version, used as the replacement for ``|version|``. For
example, for the Python documentation, this may be something like ``2.6``.
.. confval:: release
The full project version, used as the replacement for ``|release|`` and
e.g. in the HTML templates. For example, for the Python documentation, this
may be something like ``2.6.0rc1``.
If you don't need the separation provided between :confval:`version` and
:confval:`release`, just set them both to the same value.
General configuration General configuration
--------------------- ---------------------
@ -89,7 +117,7 @@ General configuration
.. confval:: source_suffix .. confval:: source_suffix
The file extensions of source files. Sphinx considers the files with this The file extensions of source files. Sphinx considers the files with this
suffix as sources. This value can be a dictionary mapping file extensions suffix as sources. The value can be a dictionary mapping file extensions
to file types. For example:: to file types. For example::
source_suffix = { source_suffix = {
@ -98,15 +126,16 @@ General configuration
'.md': 'markdown', '.md': 'markdown',
} }
By default, Sphinx only supports ``'restrcturedtext'`` file type. You can By default, Sphinx only supports ``'restructuredtext'`` file type. You can
add a new file type using source parser extensions. Please read a document add a new file type using source parser extensions. Please read a document
of the extension to know what file type the extension supports. of the extension to know which file type the extension supports.
This also allows a list of file extensions. In that case, Sphinx conciders The value may also be a list of file extensions: then Sphinx will consider
that all they are ``'restructuredtext'``. Default is that they all map to the ``'restructuredtext'`` file type.
``{'.rst': 'restructuredtext'}``.
.. note:: file extensions have to start with dot (like ``.rst``). Default is ``{'.rst': 'restructuredtext'}``.
.. note:: file extensions have to start with a dot (e.g. ``.rst``).
.. versionchanged:: 1.3 .. versionchanged:: 1.3
Can now be a list of extensions. Can now be a list of extensions.
@ -149,7 +178,10 @@ General configuration
.. confval:: master_doc .. confval:: master_doc
The document name of the "master" document, that is, the document that The document name of the "master" document, that is, the document that
contains the root :rst:dir:`toctree` directive. Default is ``'contents'``. contains the root :rst:dir:`toctree` directive. Default is ``'index'``.
.. versionchanged:: 2.0
The default is changed to ``'index'`` from ``'contents'``.
.. confval:: exclude_patterns .. confval:: exclude_patterns
@ -477,36 +509,6 @@ General configuration
.. versionadded:: 1.5 .. versionadded:: 1.5
Project information
-------------------
.. confval:: project
The documented project's name.
.. confval:: author
The author name(s) of the document. The default value is ``'unknown'``.
.. confval:: copyright
A copyright statement in the style ``'2008, Author Name'``.
.. confval:: version
The major project version, used as the replacement for ``|version|``. For
example, for the Python documentation, this may be something like ``2.6``.
.. confval:: release
The full project version, used as the replacement for ``|release|`` and
e.g. in the HTML templates. For example, for the Python documentation, this
may be something like ``2.6.0rc1``.
If you don't need the separation provided between :confval:`version` and
:confval:`release`, just set them both to the same value.
.. confval:: today .. confval:: today
today_fmt today_fmt
@ -787,10 +789,10 @@ These options influence Math notations.
.. confval:: math_eqref_format .. confval:: math_eqref_format
A string that are used for format of label of references to equations. A string used for formatting the labels of references to equations.
As a special character, ``{number}`` will be replaced to equaition number. The ``{number}`` place-holder stands for the equation number.
Example: ``'Eq.{number}'`` is rendered as ``Eq.10`` Example: ``'Eq.{number}'`` gets rendered as, for example, ``Eq.10``.
.. confval:: math_numfig .. confval:: math_numfig
@ -813,7 +815,7 @@ that use Sphinx's HTMLWriter class.
.. confval:: html_theme .. confval:: html_theme
The "theme" that the HTML output should use. See the :doc:`section about The "theme" that the HTML output should use. See the :doc:`section about
theming </theming>`. The default is ``'alabaster'``. theming </usage/theming>`. The default is ``'alabaster'``.
.. versionadded:: 0.6 .. versionadded:: 0.6
@ -862,6 +864,8 @@ that use Sphinx's HTMLWriter class.
The URL which points to the root of the HTML documentation. It is used to The URL which points to the root of the HTML documentation. It is used to
indicate the location of document like ``canonical_url``. indicate the location of document like ``canonical_url``.
.. versionadded:: 1.8
.. confval:: html_context .. confval:: html_context
A dictionary of values to pass into the template engine's context for all A dictionary of values to pass into the template engine's context for all
@ -1347,6 +1351,19 @@ Options for HTML help output
Output file base name for HTML help builder. Default is ``'pydoc'``. Output file base name for HTML help builder. Default is ``'pydoc'``.
.. confval:: htmlhelp_file_suffix
This is the file name suffix for generated HTML help files. The
default is ``".html"``.
.. versionadded:: 2.0
.. confval:: htmlhelp_link_suffix
Suffix for generated links to HTML files. The default is ``".html"``.
.. versionadded:: 2.0
.. _applehelp-options: .. _applehelp-options:
@ -1698,9 +1715,9 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
This flag determines if sphinx should try to fix image formats that are not This flag determines if sphinx should try to fix image formats that are not
supported by some epub readers. At the moment palette images with a small supported by some epub readers. At the moment palette images with a small
color table are upgraded. You need the Python Image Library (Pillow the color table are upgraded. You need Pillow, the Python Image Library,
successor of the PIL) installed to use this option. The default value is installed to use this option. The default value is ``False`` because the
``False`` because the automatic conversion may lose information. automatic conversion may lose information.
.. versionadded:: 1.2 .. versionadded:: 1.2
@ -1767,8 +1784,7 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
Options for LaTeX output Options for LaTeX output
------------------------ ------------------------
These options influence LaTeX output. Refer to :doc:`/latex` for more These options influence LaTeX output.
information.
.. confval:: latex_engine .. confval:: latex_engine
@ -1780,42 +1796,29 @@ information.
* ``'lualatex'`` -- LuaLaTeX * ``'lualatex'`` -- LuaLaTeX
* ``'platex'`` -- pLaTeX (default if :confval:`language` is ``'ja'``) * ``'platex'`` -- pLaTeX (default if :confval:`language` is ``'ja'``)
PDFLaTeX's support for Unicode characters covers those from the document ``'pdflatex'``\ 's support for Unicode characters is limited.
language (the LaTeX ``babel`` and ``inputenc`` packages map them to glyph
slots in the document font, at various encodings allowing each only 256
characters; Sphinx uses by default (except for Cyrillic languages) the
``times`` package), but stray characters from other scripts or special
symbols may require adding extra LaTeX packages or macros to the LaTeX
preamble.
If your project uses such extra Unicode characters, switching the engine to .. note::
XeLaTeX or LuaLaTeX and setting up the document to use an OpenType font
with wide-enough glyph coverage is often easier than sticking with PDFLaTeX
and trying to get it to work with the Unicode characters.
The :confval:`latex_elements` ``'fontpkg'`` key allows to set up the 2.0 adds to ``'pdflatex'`` support in Latin language document of
document fonts, see :ref:`this example <latex-basic>`. Currently, for occasional Cyrillic or Greek letters or words. This is not automatic,
XeLaTeX and LuaLaTeX, Sphinx leaves this key empty and LaTeX then defaults see the discussion of the :confval:`latex_elements` ``'fontenc'`` key.
to the `Latin Modern`_ font family (from the TeX distribution fonts). This
font family provides good coverage of Latin scripts (European languages,
Vietnamese) but Cyrillic requires some other OpenType font; for example
Computer Modern Unicode (see `babel-russian`_ documentation on how to load
it in the LaTeX document). In future, it is planned Sphinx will provide
another default choice of OpenType font than `Latin Modern`_, perhaps
`Libertinus`_, which is included in recent TeX distributions and supports
Latin and Cyrillic and also has an accompanying math font.
With XeLaTeX and LuaLaTeX, Sphinx configures the LaTeX document to use If your project uses Unicode characters, setting the engine to
`polyglossia`_. For some languages the `babel`_ support appears ``'xelatex'`` or ``'lualatex'`` and making sure to use an OpenType font
preferable; Sphinx uses currently `babel`_ for French and perhaps will also with wide-enough glyph coverage is often easier than trying to make
for some more languages in future. One can use the ``'pdflatex'`` work with the extra Unicode characters. Since Sphinx 2.0
:confval:`latex_elements` ``'babel'`` key to override Sphinx's default. the default is the GNU FreeFont which covers well Latin, Cyrillic and Greek.
.. _`Latin Modern`: http://www.gust.org.pl/projects/e-foundry/latin-modern Contrarily to :ref:`MathJaX math rendering in HTML output <math-support>`,
.. _`polyglossia`: https://ctan.org/pkg/polyglossia LaTeX requires some extra configuration to support Unicode literals in
.. _`babel`: https://ctan.org/pkg/babel :rst:dir:`math`: the only comprehensive solution (as far as we know) is to
.. _`babel-russian`: https://ctan.org/pkg/babel-russian use ``'xelatex'`` or ``'lualatex'`` *and* to add
.. _`Libertinus`: https://ctan.org/pkg/libertinus ``r'\usepackage{unicode-math}'`` (e.g. via the :confval:`latex_elements`
``'preamble'`` key). You may prefer
``r'\usepackage[math-style=literal]{unicode-math}'`` to keep a Unicode
literal such as ``α`` (U+03B1) for example as is in output, rather than
being rendered as :math:`\alpha`.
.. confval:: latex_documents .. confval:: latex_documents
@ -1972,265 +1975,7 @@ information.
.. versionadded:: 0.5 .. versionadded:: 0.5
A dictionary that contains LaTeX snippets that override those Sphinx usually Its :ref:`documentation <latex_elements_confval>` has moved to :doc:`/latex`.
puts into the generated ``.tex`` files.
Keep in mind that backslashes must be doubled in Python string literals to
avoid interpretation as escape sequences.
* Keys that you may want to override include:
``'papersize'``
Paper size option of the document class (``'a4paper'`` or
``'letterpaper'``), default ``'letterpaper'``.
``'pointsize'``
Point size option of the document class (``'10pt'``, ``'11pt'`` or
``'12pt'``), default ``'10pt'``.
``'pxunit'``
the value of the ``px`` when used in image attributes ``width`` and
``height``. The default value is ``'0.75bp'`` which achieves
``96px=1in`` (in TeX ``1in = 72bp = 72.27pt``.) To obtain for
example ``100px=1in`` use ``'0.01in'`` or ``'0.7227pt'`` (the latter
leads to TeX computing a more precise value, due to the smaller unit
used in the specification); for ``72px=1in``, simply use ``'1bp'``; for
``90px=1in``, use ``'0.8bp'`` or ``'0.803pt'``.
.. versionadded:: 1.5
``'sphinxsetup'``
A comma separated list of ``key=value`` package options for the Sphinx
LaTeX style, default empty. See :doc:`/latex`.
.. versionadded:: 1.5
``'passoptionstopackages'``
A string which will be positioned early in the preamble, designed to
contain ``\\PassOptionsToPackage{options}{foo}`` commands. Default empty.
.. versionadded:: 1.4
``'babel'``
"babel" package inclusion, default ``'\\usepackage{babel}'`` (the
suitable document language string is passed as class option, and
``english`` is used if no language.) For Japanese documents, the
default is the empty string.
.. versionchanged:: 1.5
For :confval:`latex_engine` set to ``'xelatex'``, the default
is ``'\\usepackage{polyglossia}\n\\setmainlanguage{<language>}'``.
.. versionchanged:: 1.6
``'lualatex'`` uses same default setting as ``'xelatex'``
.. versionchanged:: 1.7.6
For French, ``xelatex`` and ``lualatex`` default to using
``babel``, not ``polyglossia``.
``'fontpkg'``
Font package inclusion, default ``'\\usepackage{times}'`` (which uses
Times for text, Helvetica for sans serif and Courier for code-blocks).
.. versionchanged:: 1.2
Defaults to ``''`` when the :confval:`language` uses the Cyrillic
script.
.. versionchanged:: 1.5
Defaults to ``''`` when :confval:`latex_engine` is ``'xelatex'``.
.. versionchanged:: 1.6
Defaults to ``''`` also with ``'lualatex'``.
``'fncychap'``
Inclusion of the "fncychap" package (which makes fancy chapter titles),
default ``'\\usepackage[Bjarne]{fncychap}'`` for English documentation
(this option is slightly customized by Sphinx),
``'\\usepackage[Sonny]{fncychap}'`` for internationalized docs (because
the "Bjarne" style uses numbers spelled out in English). Other
"fncychap" styles you can try are "Lenny", "Glenn", "Conny", "Rejne" and
"Bjornstrup". You can also set this to ``''`` to disable fncychap.
``'preamble'``
Additional preamble content, default empty. See :doc:`/latex`.
``'atendofbody'``
Additional document content (right before the indices), default empty.
.. versionadded:: 1.5
``'figure_align'``
Latex figure float alignment, default 'htbp' (here, top, bottom, page).
Whenever an image doesn't fit into the current page, it will be
'floated' into the next page but may be preceded by any other text.
If you don't like this behavior, use 'H' which will disable floating
and position figures strictly in the order they appear in the source.
.. versionadded:: 1.3
``'footer'``
Additional footer content (before the indices), default empty.
.. deprecated:: 1.5
Use ``'atendofbody'`` key instead.
* Keys that don't need to be overridden unless in special cases are:
``'extraclassoptions'``
The default is the empty string. Example: ``'extraclassoptions':
'openany'`` will allow chapters (for documents of the ``'manual'``
type) to start on any page.
.. versionadded:: 1.2
.. versionchanged:: 1.6
Added this documentation.
``'maxlistdepth'``
LaTeX allows by default at most 6 levels for nesting list and
quote-like environments, with at most 4 enumerated lists, and 4 bullet
lists. Setting this key for example to ``'10'`` (as a string) will
allow up to 10 nested levels (of all sorts). Leaving it to the empty
string means to obey the LaTeX default.
.. warning::
- Using this key may prove incompatible with some LaTeX packages
or special document classes which do their own list customization.
- The key setting is silently *ignored* if ``\usepackage{enumitem}``
is executed inside the document preamble. Use then rather the
dedicated commands of this LaTeX package.
.. versionadded:: 1.5
``'inputenc'``
"inputenc" package inclusion, defaults to
``'\\usepackage[utf8]{inputenc}'`` when using pdflatex.
Otherwise empty.
.. versionchanged:: 1.4.3
Previously ``'\\usepackage[utf8]{inputenc}'`` was used for all
compilers.
``'cmappkg'``
"cmap" package inclusion, default ``'\\usepackage{cmap}'``.
.. versionadded:: 1.2
``'fontenc'``
"fontenc" package inclusion, default ``'\\usepackage[T1]{fontenc}'``.
.. versionchanged:: 1.5
Defaults to ``'\\usepackage{fontspec}'`` when
:confval:`latex_engine` is ``'xelatex'``.
.. versionchanged:: 1.6
``'lualatex'`` also uses ``fontspec`` per default.
``'geometry'``
"geometry" package inclusion, the default definition is:
``'\\usepackage{geometry}'``
with an additional ``[dvipdfm]`` for Japanese documents.
The Sphinx LaTeX style file executes:
``\PassOptionsToPackage{hmargin=1in,vmargin=1in,marginpar=0.5in}{geometry}``
which can be customized via corresponding :ref:`'sphinxsetup' options
<latexsphinxsetup>`.
.. versionadded:: 1.5
.. versionchanged:: 1.5.2
``dvipdfm`` option if :confval:`latex_engine` is ``'platex'``.
.. versionadded:: 1.5.3
The :ref:`'sphinxsetup' keys for the margins
<latexsphinxsetuphmargin>`.
.. versionchanged:: 1.5.3
The location in the LaTeX file has been moved to after
``\usepackage{sphinx}`` and ``\sphinxsetup{..}``, hence also after
insertion of ``'fontpkg'`` key. This is in order to handle the paper
layout options in a special way for Japanese documents: the text
width will be set to an integer multiple of the *zenkaku* width, and
the text height to an integer multiple of the baseline. See the
:ref:`hmargin <latexsphinxsetuphmargin>` documentation for more.
``'hyperref'``
"hyperref" package inclusion; also loads package "hypcap" and issues
``\urlstyle{same}``. This is done after :file:`sphinx.sty` file is
loaded and before executing the contents of ``'preamble'`` key.
.. attention::
Loading of packages "hyperref" and "hypcap" is mandatory.
.. versionadded:: 1.5
Previously this was done from inside :file:`sphinx.sty`.
``'maketitle'``
"maketitle" call, default ``'\\maketitle'`` (but it has been
redefined by the Sphinx ``manual`` and ``howto`` classes.) Override
if you want to generate a differently-styled title page.
``'releasename'``
value that prefixes ``'release'`` element on title page, default
``'Release'``. As for *title* and *author* used in the tuples of
:confval:`latex_documents`, it is inserted as LaTeX markup.
``'tableofcontents'``
"tableofcontents" call, default ``'\\sphinxtableofcontents'`` (it is a
wrapper of unmodified ``\tableofcontents``, which may itself be
customized by user loaded packages.)
Override if
you want to generate a different table of contents or put content
between the title page and the TOC.
.. versionchanged:: 1.5
Previously the meaning of ``\tableofcontents`` itself was modified
by Sphinx. This created an incompatibility with dedicated packages
modifying it also such as "tocloft" or "etoc".
``'transition'``
Commands used to display transitions, default
``'\n\n\\bigskip\\hrule\\bigskip\n\n'``. Override if you want to
display transitions differently.
.. versionadded:: 1.2
.. versionchanged:: 1.6
Remove unneeded ``{}`` after ``\\hrule``.
``'printindex'``
"printindex" call, the last thing in the file, default
``'\\printindex'``. Override if you want to generate the index
differently or append some content after the index. For example
``'\\footnotesize\\raggedright\\printindex'`` is advisable when the
index is full of long entries.
``'fvset'``
Customization of ``fancyvrb`` LaTeX package. Currently, Sphinx uses
this key to set the fontsize in code-blocks according to the
:confval:`latex_engine`.
- ``'pdflatex'`` uses ``'fvset': '\\fvset{fontsize=\\small}'``,
to mitigate the size difference between the default monospaced font
(Courier) and the default text font (Times). You may need to modify
this if you use custom fonts.
- ``'xelatex'`` and ``'lualatex'`` use ``'\\fvset{fontsize=auto}'``,
as there is no size difference between the regular and the
monospaced fonts used by default by Sphinx with these engines.
.. versionadded:: 1.8
* Keys that are set by other options and therefore should not be overridden
are:
``'docclass'``
``'classoptions'``
``'title'``
``'date'``
``'release'``
``'author'``
``'logo'``
``'makeindex'``
.. confval:: latex_docclass .. confval:: latex_docclass
@ -2612,7 +2357,7 @@ Options for the C++ domain
A list of strings that the parser additionally should accept as attributes A list of strings that the parser additionally should accept as attributes
with one argument. That is, if ``my_align_as`` is in the list, then with one argument. That is, if ``my_align_as`` is in the list, then
``my_align_as(X)`` is parsed as an attribute for all strings ``X`` that have ``my_align_as(X)`` is parsed as an attribute for all strings ``X`` that have
balanced brances (``()``, ``[]``, and ``{}``). This can for example be used balanced braces (``()``, ``[]``, and ``{}``). This can for example be used
when attributes have been ``#define`` d for portability. when attributes have been ``#define`` d for portability.
.. versionadded:: 1.5 .. versionadded:: 1.5

View File

@ -383,9 +383,10 @@ There are also new config values that you can set:
Setting ``None`` is equivalent to giving the option name in the list format Setting ``None`` is equivalent to giving the option name in the list format
(i.e. it means "yes/true/on"). (i.e. it means "yes/true/on").
The supported options are ``'members'``, ``'undoc-members'``, The supported options are ``'members'``, ``'member-order'``,
``'private-members'``, ``'special-members'``, ``'inherited-members'``, ``'undoc-members'``, ``'private-members'``, ``'special-members'``,
``'show-inheritance'``, ``'ignore-module-all'`` and ``'exclude-members'``. ``'inherited-members'``, ``'show-inheritance'``, ``'ignore-module-all'`` and
``'exclude-members'``.
.. versionadded:: 1.8 .. versionadded:: 1.8
@ -426,7 +427,7 @@ There are also new config values that you can set:
This value controls the behavior of :option:`sphinx-build -W` during This value controls the behavior of :option:`sphinx-build -W` during
importing modules. importing modules.
If ``False`` is given, autodoc forcely suppresses the error if the imported If ``False`` is given, autodoc forcedly suppresses the error if the imported
module emits warnings. By default, ``True``. module emits warnings. By default, ``True``.
.. confval:: autodoc_inherit_docstrings .. confval:: autodoc_inherit_docstrings

View File

@ -75,7 +75,7 @@ a comma-separated list of group names.
* ``pyversion``, a string option, can be used to specify the required Python * ``pyversion``, a string option, can be used to specify the required Python
version for the example to be tested. For instance, in the following case version for the example to be tested. For instance, in the following case
the example will be tested only for Python versions greather than 3.3:: the example will be tested only for Python versions greater than 3.3::
.. doctest:: .. doctest::
:pyversion: > 3.3 :pyversion: > 3.3

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Example Google style docstrings. """Example Google style docstrings.
This module demonstrates documentation as specified by the `Google Python This module demonstrates documentation as specified by the `Google Python
@ -178,7 +177,7 @@ class ExampleError(Exception):
self.code = code self.code = code
class ExampleClass(object): class ExampleClass:
"""The summary line for a class docstring should fit on one line. """The summary line for a class docstring should fit on one line.
If the class has public attributes, they may be documented here If the class has public attributes, they may be documented here

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Example NumPy style docstrings. """Example NumPy style docstrings.
This module demonstrates documentation as specified by the `NumPy This module demonstrates documentation as specified by the `NumPy
@ -223,7 +222,7 @@ class ExampleError(Exception):
self.code = code self.code = code
class ExampleClass(object): class ExampleClass:
"""The summary line for a class docstring should fit on one line. """The summary line for a class docstring should fit on one line.
If the class has public attributes, they may be documented here If the class has public attributes, they may be documented here

View File

@ -54,7 +54,7 @@ It adds this directive:
E D F E D F
""" """
class A(object): class A:
pass pass
class B(A): class B(A):

View File

@ -183,7 +183,7 @@ Sphinx.
The default is empty (not configured). The default is empty (not configured).
.. _Using in-line configuration options: http://docs.mathjax.org/en/latest/configuration.html#using-in-line-configuration-options .. _Using in-line configuration options: https://docs.mathjax.org/en/latest/configuration.html#using-in-line-configuration-options
:mod:`sphinx.ext.jsmath` -- Render math via JavaScript :mod:`sphinx.ext.jsmath` -- Render math via JavaScript
------------------------------------------------------ ------------------------------------------------------

View File

@ -130,7 +130,7 @@ Google vs NumPy
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
Napoleon supports two styles of docstrings: `Google`_ and `NumPy`_. The Napoleon supports two styles of docstrings: `Google`_ and `NumPy`_. The
main difference between the two styles is that Google uses indention to main difference between the two styles is that Google uses indentation to
separate sections, whereas NumPy uses underlines. separate sections, whereas NumPy uses underlines.
Google style: Google style:
@ -409,10 +409,10 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
.. attribute:: attr1 .. attribute:: attr1
*int*
Description of `attr1` Description of `attr1`
:type: int
.. confval:: napoleon_use_param .. confval:: napoleon_use_param
True to use a ``:param:`` role for each function parameter. False to True to use a ``:param:`` role for each function parameter. False to

View File

@ -41,10 +41,9 @@ Configuration
.. confval:: viewcode_follow_imported_members .. confval:: viewcode_follow_imported_members
If this is ``True``, viewcode extension will follow alias objects that If this is ``True``, viewcode extension will emit
imported from another module such as functions, classes and attributes. As :event:`viewcode-follow-imported` event to resolve the name of the module
side effects, this option else they produce nothing. The default is by other extensions. The default is ``True``.
``True``.
.. versionadded:: 1.3 .. versionadded:: 1.3

View File

@ -12,10 +12,9 @@ Installing Sphinx
Overview Overview
-------- --------
Sphinx is written in `Python`__ and supports both Python 2.7 and Python 3.3+. Sphinx is written in `Python`__ and supports Python 3.5+.
We recommend the latter.
__ http://docs.python-guide.org/en/latest/ __ https://docs.python-guide.org/
Linux Linux
@ -73,7 +72,7 @@ Homebrew
For more information, refer to the `package overview`__. For more information, refer to the `package overview`__.
__ http://formulae.brew.sh/formula/sphinx-doc __ https://formulae.brew.sh/formula/sphinx-doc
MacPorts MacPorts
~~~~~~~~ ~~~~~~~~
@ -114,16 +113,14 @@ Prompt* (:kbd:`⊞Win-r` and type :command:`cmd`). Once the command prompt is
open, type :command:`python --version` and press Enter. If Python is open, type :command:`python --version` and press Enter. If Python is
available, you will see the version of Python printed to the screen. If you do available, you will see the version of Python printed to the screen. If you do
not have Python installed, refer to the `Hitchhikers Guide to Python's`__ not have Python installed, refer to the `Hitchhikers Guide to Python's`__
Python on Windows installation guides. You can install either `Python 3`__ or Python on Windows installation guides. You must install `Python 3`__.
`Python 2.7`__. Python 3 is recommended.
Once Python is installed, you can install Sphinx using :command:`pip`. Refer Once Python is installed, you can install Sphinx using :command:`pip`. Refer
to the :ref:`pip installation instructions <install-pypi>` below for more to the :ref:`pip installation instructions <install-pypi>` below for more
information. information.
__ http://docs.python-guide.org/en/latest/ __ https://docs.python-guide.org/
__ http://docs.python-guide.org/en/latest/starting/install3/win/ __ https://docs.python-guide.org/starting/install3/win/
__ http://docs.python-guide.org/en/latest/starting/install/win/
.. _install-pypi: .. _install-pypi:

View File

@ -15,31 +15,42 @@ parsing the `CommonMark`__ Markdown flavor.
__ https://daringfireball.net/projects/markdown/ __ https://daringfireball.net/projects/markdown/
__ https://recommonmark.readthedocs.io/en/latest/index.html __ https://recommonmark.readthedocs.io/en/latest/index.html
__ https://github.com/rtfd/CommonMark-py __ https://github.com/rtfd/CommonMark-py
__ http://commonmark.org/ __ https://commonmark.org/
Configuration Configuration
------------- -------------
To configure your Sphinx project for Markdown support, proceed as follows: To configure your Sphinx project for Markdown support, proceed as follows:
#. Install *recommonmark*:: #. Install the Markdown parser *recommonmark*::
pip install recommonmark pip install --upgrade recommonmark
#. Add the Markdown parser to the ``source_parsers`` configuration variable in .. note::
your Sphinx configuration file::
source_parsers = { The configuration as explained here requires recommonmark version
'.md': 'recommonmark.parser.CommonMarkParser', 0.5.0 or later.
#. Add *recommonmark* to the
:confval:`list of configured extensions <extensions>`::
extensions = ['recommonmark']
.. versionchanged:: 1.8
Version 1.8 deprecates and version 3.0 removes the ``source_parsers``
configuration variable that was used by older *recommonmark* versions.
#. If you want to use Markdown files with extensions other than ``.md``, adjust
the :confval:`source_suffix` variable. The following example configures
Sphinx to parse all files with the extensions ``.md`` and ``.txt`` as
Markdown::
source_suffix = {
'.rst': 'restructuredtext',
'.txt': 'markdown',
'.md': 'markdown',
} }
You can replace ``.md`` with a filename extension of your choice.
#. Add the Markdown filename extension to the ``source_suffix`` configuration
variable::
source_suffix = ['.rst', '.md']
#. You can further configure *recommonmark* to allow custom syntax that #. You can further configure *recommonmark* to allow custom syntax that
standard *CommonMark* doesn't support. Read more in the `recommonmark standard *CommonMark* doesn't support. Read more in the `recommonmark
documentation`__. documentation`__.

View File

@ -289,7 +289,7 @@ Intersphinx
----------- -----------
Many Sphinx documents including the `Python documentation`_ are published on Many Sphinx documents including the `Python documentation`_ are published on
the internet. When you want to make links to such documents from your the Internet. When you want to make links to such documents from your
documentation, you can do it with :mod:`sphinx.ext.intersphinx`. documentation, you can do it with :mod:`sphinx.ext.intersphinx`.
.. _Python documentation: https://docs.python.org/3 .. _Python documentation: https://docs.python.org/3
@ -320,8 +320,8 @@ More topics to be covered
- :doc:`Other extensions </usage/extensions/index>`: - :doc:`Other extensions </usage/extensions/index>`:
- Static files - Static files
- :doc:`Selecting a theme </theming>` - :doc:`Selecting a theme </usage/theming>`
- :doc:`/setuptools` - :doc:`/usage/advanced/setuptools`
- :ref:`Templating <templating>` - :ref:`Templating <templating>`
- Using extensions - Using extensions
- :ref:`Writing extensions <dev-extensions>` - :ref:`Writing extensions <dev-extensions>`

View File

@ -463,7 +463,7 @@ __ http://pygments.org/docs/lexers/
This will produce line numbers for all code blocks longer than five lines. This will produce line numbers for all code blocks longer than five lines.
.. rst:directive:: .. code-block:: language .. rst:directive:: .. code-block:: [language]
Example:: Example::
@ -471,9 +471,11 @@ __ http://pygments.org/docs/lexers/
Some Ruby code. Some Ruby code.
The directive's alias name :rst:dir:`sourcecode` works as well. As with The directive's alias name :rst:dir:`sourcecode` works as well. This
:rst:dir:`highlight`\ 's ``language`` option, ``language`` can be any lexer directive takes a language name as an argument. It can be any lexer alias
alias supported by Pygments. supported by Pygments. If it is not given, the setting of
:rst:dir:`highlight` directive will be used. If not set,
:confval:`highlight_language` will be used.
**Additional options** **Additional options**
@ -533,6 +535,9 @@ __ http://pygments.org/docs/lexers/
.. versionchanged:: 1.6.6 .. versionchanged:: 1.6.6
LaTeX supports the ``emphasize-lines`` option. LaTeX supports the ``emphasize-lines`` option.
.. versionchanged:: 2.0
The ``language`` argument becomes optional.
.. rst:directive:: .. literalinclude:: filename .. rst:directive:: .. literalinclude:: filename
Longer displays of verbatim text may be included by storing the example text Longer displays of verbatim text may be included by storing the example text
@ -654,7 +659,7 @@ Glossary
.. rst:directive:: .. glossary:: .. rst:directive:: .. glossary::
This directive must contain a reST definition-list-like markup with terms and This directive must contain a reST definition-list-like markup with terms and
definitions. The definitions will then be referencable with the definitions. The definitions will then be referenceable with the
:rst:role:`term` role. Example:: :rst:role:`term` role. Example::
.. glossary:: .. glossary::
@ -1063,6 +1068,15 @@ or use Python raw strings (``r"raw"``).
.. _AmSMath LaTeX package: https://www.ams.org/publications/authors/tex/amslatex .. _AmSMath LaTeX package: https://www.ams.org/publications/authors/tex/amslatex
.. seealso::
:ref:`math-support`
Rendering options for math with HTML builders.
:confval:`latex_engine`
Explains how to configure LaTeX builder to support Unicode literals in
math mark-up.
Grammar production displays Grammar production displays
--------------------------- ---------------------------

View File

@ -541,18 +541,23 @@ The C++ Domain
The C++ domain (name **cpp**) supports documenting C++ projects. The C++ domain (name **cpp**) supports documenting C++ projects.
Directives Directives for Declaring Entities
~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following directives are available. All declarations can start with a The following directives are available. All declarations can start with a
visibility statement (``public``, ``private`` or ``protected``). visibility statement (``public``, ``private`` or ``protected``).
.. rst:directive:: .. cpp:class:: class specifier .. rst:directive:: .. cpp:class:: class specifier
.. cpp:struct:: class specifier
Describe a class/struct, possibly with specification of inheritance, e.g.,:: Describe a class/struct, possibly with specification of inheritance, e.g.,::
.. cpp:class:: MyClass : public MyBase, MyOtherBase .. cpp:class:: MyClass : public MyBase, MyOtherBase
The difference between :rst:dir:`cpp:class` and :rst:dir:`cpp:struct` is
only cosmetic: the prefix rendered in the output, and the specifier shown
in the index.
The class can be directly declared inside a nested scope, e.g.,:: The class can be directly declared inside a nested scope, e.g.,::
.. cpp:class:: OuterScope::MyClass : public MyBase, MyOtherBase .. cpp:class:: OuterScope::MyClass : public MyBase, MyOtherBase
@ -574,6 +579,9 @@ visibility statement (``public``, ``private`` or ``protected``).
.. cpp:class:: template<typename T> \ .. cpp:class:: template<typename T> \
std::array<T, 42> std::array<T, 42>
.. versionadded:: 2.0
The :rst:dir:`cpp:struct` directive.
.. rst:directive:: .. cpp:function:: (member) function prototype .. rst:directive:: .. cpp:function:: (member) function prototype
Describe a function or member function, e.g.,:: Describe a function or member function, e.g.,::
@ -706,6 +714,8 @@ visibility statement (``public``, ``private`` or ``protected``).
Describe a union. Describe a union.
.. versionadded:: 1.8
.. rst:directive:: .. cpp:concept:: template-parameter-list name .. rst:directive:: .. cpp:concept:: template-parameter-list name
.. warning:: The support for concepts is experimental. It is based on the .. warning:: The support for concepts is experimental. It is based on the
@ -750,6 +760,9 @@ visibility statement (``public``, ``private`` or ``protected``).
- :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` - :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r`
is incrementable. is incrementable.
.. versionadded:: 1.5
Options Options
^^^^^^^ ^^^^^^^
@ -759,10 +772,12 @@ Some directives support options:
- ``:tparam-line-spec:``, for templated declarations. - ``:tparam-line-spec:``, for templated declarations.
If specified, each template parameter will be rendered on a separate line. If specified, each template parameter will be rendered on a separate line.
.. versionadded:: 1.6
Anonymous Entities Anonymous Entities
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
C++ supposrts anonymous namespaces, classes, enums, and unions. C++ supports anonymous namespaces, classes, enums, and unions.
For the sake of documentation they must be given some name that starts with ``@``, For the sake of documentation they must be given some name that starts with ``@``,
e.g., ``@42`` or ``@data``. e.g., ``@42`` or ``@data``.
These names can also be used in cross-references and (type) expressions, These names can also be used in cross-references and (type) expressions,
@ -793,6 +808,45 @@ This will be rendered as:
Explicit ref: :cpp:var:`Data::@data::a`. Short-hand ref: :cpp:var:`Data::a`. Explicit ref: :cpp:var:`Data::@data::a`. Short-hand ref: :cpp:var:`Data::a`.
.. versionadded:: 1.8
Aliasing Declarations
~~~~~~~~~~~~~~~~~~~~~
Sometimes it may be helpful list declarations elsewhere than their main documentation,
e.g., when creating a synopsis of a class interface.
The following directive can be used for this purpose.
.. rst:directive:: .. cpp:alias:: name or function signature
Insert one or more alias declarations. Each entity can be specified
as they can in the :rst:role:`cpp:any` role.
If the name of a function is given (as opposed to the complete signature),
then all overloads of the function will be listed.
For example::
.. cpp:alias:: Data::a
overload_example::C::f
becomes
.. cpp:alias:: Data::a
overload_example::C::f
whereas::
.. cpp:alias:: void overload_example::C::f(double d) const
void overload_example::C::f(double d)
becomes
.. cpp:alias:: void overload_example::C::f(double d) const
void overload_example::C::f(double d)
.. versionadded:: 2.0
Constrained Templates Constrained Templates
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
@ -850,8 +904,8 @@ Note however that no checking is performed with respect to parameter
compatibility. E.g., ``Iterator{A, B, C}`` will be accepted as an introduction compatibility. E.g., ``Iterator{A, B, C}`` will be accepted as an introduction
even though it would not be valid C++. even though it would not be valid C++.
Inline Expressions and Tpes Inline Expressions and Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. rst:role:: cpp:expr .. rst:role:: cpp:expr
cpp:texpr cpp:texpr
@ -879,6 +933,11 @@ Inline Expressions and Tpes
A type: :cpp:expr:`const MySortedContainer<int>&` A type: :cpp:expr:`const MySortedContainer<int>&`
(or as text :cpp:texpr:`const MySortedContainer<int>&`). (or as text :cpp:texpr:`const MySortedContainer<int>&`).
.. versionadded:: 1.7
The :rst:role:`cpp:expr` role.
.. versionadded:: 1.8
The :rst:role:`cpp:texpr` role.
Namespacing Namespacing
~~~~~~~~~~~ ~~~~~~~~~~~
@ -941,6 +1000,8 @@ The ``cpp:namespace-pop`` directive undoes the most recent
the current scope will be ``A::B::C::D``. the current scope will be ``A::B::C::D``.
.. versionadded:: 1.4
.. rst:directive:: .. cpp:namespace-pop:: .. rst:directive:: .. cpp:namespace-pop::
Undo the previous ``cpp:namespace-push`` directive (*not* just pop a scope). Undo the previous ``cpp:namespace-push`` directive (*not* just pop a scope).
@ -962,6 +1023,8 @@ The ``cpp:namespace-pop`` directive undoes the most recent
.. cpp:namespace-push:: A::B .. cpp:namespace-push:: A::B
.. versionadded:: 1.4
Info field lists Info field lists
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
@ -982,6 +1045,7 @@ These roles link to the given declaration types:
.. rst:role:: cpp:any .. rst:role:: cpp:any
cpp:class cpp:class
cpp:struct
cpp:func cpp:func
cpp:member cpp:member
cpp:var cpp:var
@ -993,6 +1057,9 @@ These roles link to the given declaration types:
Reference a C++ declaration by name (see below for details). The name must Reference a C++ declaration by name (see below for details). The name must
be properly qualified relative to the position of the link. be properly qualified relative to the position of the link.
.. versionadded:: 2.0
The :rst:role:`cpp:struct` role as alias for the :rst:role:`cpp:class` role.
.. admonition:: Note on References with Templates Parameters/Arguments .. admonition:: Note on References with Templates Parameters/Arguments
These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must be These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must be
@ -1155,7 +1222,7 @@ There is a set of directives allowing documenting command-line programs:
Run a module as a script. Run a module as a script.
The directive will create cross-reference targets for the given options, The directive will create cross-reference targets for the given options,
referencable by :rst:role:`option` (in the example case, you'd use something referenceable by :rst:role:`option` (in the example case, you'd use something
like ``:option:`dest_dir```, ``:option:`-m```, or ``:option:`--module```). like ``:option:`dest_dir```, ``:option:`-m```, or ``:option:`--module```).
``cmdoption`` directive is a deprecated alias for the ``option`` directive. ``cmdoption`` directive is a deprecated alias for the ``option`` directive.
@ -1163,7 +1230,7 @@ There is a set of directives allowing documenting command-line programs:
.. rst:directive:: .. envvar:: name .. rst:directive:: .. envvar:: name
Describes an environment variable that the documented code or program uses Describes an environment variable that the documented code or program uses
or defines. Referencable by :rst:role:`envvar`. or defines. Referenceable by :rst:role:`envvar`.
.. rst:directive:: .. program:: name .. rst:directive:: .. program:: name

339
doc/usage/theming.rst Normal file
View File

@ -0,0 +1,339 @@
.. highlight:: python
HTML
====
Sphinx provides a number of builders for HTML and HTML-based formats.
Builders
--------
.. todo:: Populate when the 'builders' document is split up.
Themes
------
.. versionadded:: 0.6
.. note::
This section provides information about using pre-existing HTML themes. If
you wish to create your own theme, refer to :doc:`/theming`.
Sphinx supports changing the appearance of its HTML output via *themes*. A
theme is a collection of HTML templates, stylesheet(s) and other static files.
Additionally, it has a configuration file which specifies from which theme to
inherit, which highlighting style to use, and what options exist for customizing
the theme's look and feel.
Themes are meant to be project-unaware, so they can be used for different
projects without change.
Using a theme
~~~~~~~~~~~~~
Using a :ref:`theme provided with Sphinx <builtin-themes>` is easy. Since these
do not need to be installed, you only need to set the :confval:`html_theme`
config value. For example, to enable the ``classic`` theme, add the following
to :file:`conf.py`::
html_theme = "classic"
You can also set theme-specific options using the :confval:`html_theme_options`
config value. These options are generally used to change the look and feel of
the theme. For example, to place the sidebar on the right side and a black
background for the relation bar (the bar with the navigation links at the
page's top and bottom), add the following :file:`conf.py`::
html_theme_options = {
"rightsidebar": "true",
"relbarbgcolor": "black"
}
If the theme does not come with Sphinx, it can be in two static forms or as a
Python package. For the static forms, either a directory (containing
:file:`theme.conf` and other needed files), or a zip file with the same
contents is supported. The directory or zipfile must be put where Sphinx can
find it; for this there is the config value :confval:`html_theme_path`. This
can be a list of directories, relative to the directory containing
:file:`conf.py`, that can contain theme directories or zip files. For example,
if you have a theme in the file :file:`blue.zip`, you can put it right in the
directory containing :file:`conf.py` and use this configuration::
html_theme = "blue"
html_theme_path = ["."]
The third form is a Python package. If a theme you want to use is distributed
as a Python package, you can use it after installing
.. code-block:: bash
# installing theme package
$ pip install sphinxjp.themes.dotted
Once installed, this can be used in the same manner as a directory or
zipfile-based theme::
html_theme = "dotted"
For more information on the design of themes, including information about
writing your own themes, refer to :doc:`/theming`.
.. _builtin-themes:
Builtin themes
~~~~~~~~~~~~~~
.. cssclass:: longtable
+--------------------+--------------------+
| **Theme overview** | |
+--------------------+--------------------+
| |alabaster| | |classic| |
| | |
| *alabaster* | *classic* |
+--------------------+--------------------+
| |sphinxdoc| | |scrolls| |
| | |
| *sphinxdoc* | *scrolls* |
+--------------------+--------------------+
| |agogo| | |traditional| |
| | |
| *agogo* | *traditional* |
+--------------------+--------------------+
| |nature| | |haiku| |
| | |
| *nature* | *haiku* |
+--------------------+--------------------+
| |pyramid| | |bizstyle| |
| | |
| *pyramid* | *bizstyle* |
+--------------------+--------------------+
.. |alabaster| image:: /_static/themes/alabaster.png
.. |classic| image:: /_static/themes/classic.png
.. |sphinxdoc| image:: /_static/themes/sphinxdoc.png
.. |scrolls| image:: /_static/themes/scrolls.png
.. |agogo| image:: /_static/themes/agogo.png
.. |traditional| image:: /_static/themes/traditional.png
.. |nature| image:: /_static/themes/nature.png
.. |haiku| image:: /_static/themes/haiku.png
.. |pyramid| image:: /_static/themes/pyramid.png
.. |bizstyle| image:: /_static/themes/bizstyle.png
Sphinx comes with a selection of themes to choose from.
.. cssclass:: clear
These themes are:
**basic**
This is a basically unstyled layout used as the base for the
other themes, and usable as the base for custom themes as well. The HTML
contains all important elements like sidebar and relation bar. There are
these options (which are inherited by the other themes):
- **nosidebar** (true or false): Don't include the sidebar. Defaults to
``False``.
- **sidebarwidth** (int or str): Width of the sidebar in pixels.
This can be an int, which is interpreted as pixels or a valid CSS
dimension string such as '70em' or '50%'. Defaults to 230 pixels.
- **body_min_width** (int or str): Minimal width of the document body.
This can be an int, which is interpreted as pixels or a valid CSS
dimension string such as '70em' or '50%'. Use 0 if you don't want
a width limit. Defaults may depend on the theme (often 450px).
- **body_max_width** (int or str): Maximal width of the document body.
This can be an int, which is interpreted as pixels or a valid CSS
dimension string such as '70em' or '50%'. Use 'none' if you don't
want a width limit. Defaults may depend on the theme (often 800px).
**alabaster**
`Alabaster theme`_ is a modified "Kr" Sphinx theme from @kennethreitz
(especially as used in his Requests project), which was itself originally
based on @mitsuhiko's theme used for Flask & related projects. Refer to its
`installation page`_ for information on how to configure
:confval:`html_sidebars` for its use.
.. _Alabaster theme: https://pypi.org/project/alabaster/
.. _installation page: https://alabaster.readthedocs.io/en/latest/installation.html
**classic**
This is the classic theme, which looks like `the Python 2
documentation <https://docs.python.org/2/>`_. It can be customized via
these options:
- **rightsidebar** (true or false): Put the sidebar on the right side.
Defaults to ``False``.
- **stickysidebar** (true or false): Make the sidebar "fixed" so that it
doesn't scroll out of view for long body content. This may not work well
with all browsers. Defaults to ``False``.
- **collapsiblesidebar** (true or false): Add an *experimental* JavaScript
snippet that makes the sidebar collapsible via a button on its side.
Defaults to ``False``.
- **externalrefs** (true or false): Display external links differently from
internal links. Defaults to ``False``.
There are also various color and font options that can change the color scheme
without having to write a custom stylesheet:
- **footerbgcolor** (CSS color): Background color for the footer line.
- **footertextcolor** (CSS color): Text color for the footer line.
- **sidebarbgcolor** (CSS color): Background color for the sidebar.
- **sidebarbtncolor** (CSS color): Background color for the sidebar collapse
button (used when *collapsiblesidebar* is ``True``).
- **sidebartextcolor** (CSS color): Text color for the sidebar.
- **sidebarlinkcolor** (CSS color): Link color for the sidebar.
- **relbarbgcolor** (CSS color): Background color for the relation bar.
- **relbartextcolor** (CSS color): Text color for the relation bar.
- **relbarlinkcolor** (CSS color): Link color for the relation bar.
- **bgcolor** (CSS color): Body background color.
- **textcolor** (CSS color): Body text color.
- **linkcolor** (CSS color): Body link color.
- **visitedlinkcolor** (CSS color): Body color for visited links.
- **headbgcolor** (CSS color): Background color for headings.
- **headtextcolor** (CSS color): Text color for headings.
- **headlinkcolor** (CSS color): Link color for headings.
- **codebgcolor** (CSS color): Background color for code blocks.
- **codetextcolor** (CSS color): Default text color for code blocks, if not
set differently by the highlighting style.
- **bodyfont** (CSS font-family): Font for normal text.
- **headfont** (CSS font-family): Font for headings.
**sphinxdoc**
The theme originally used by this documentation. It features
a sidebar on the right side. There are currently no options beyond
*nosidebar* and *sidebarwidth*.
.. note::
The Sphinx documentation now uses
`an adjusted version of the sphinxdoc theme
<https://github.com/sphinx-doc/sphinx/tree/master/doc/_themes/sphinx13>`_.
**scrolls**
A more lightweight theme, based on `the Jinja documentation
<http://jinja.pocoo.org/>`_. The following color options are available:
- **headerbordercolor**
- **subheadlinecolor**
- **linkcolor**
- **visitedlinkcolor**
- **admonitioncolor**
**agogo**
A theme created by Andi Albrecht. The following options are supported:
- **bodyfont** (CSS font family): Font for normal text.
- **headerfont** (CSS font family): Font for headings.
- **pagewidth** (CSS length): Width of the page content, default 70em.
- **documentwidth** (CSS length): Width of the document (without sidebar),
default 50em.
- **sidebarwidth** (CSS length): Width of the sidebar, default 20em.
- **bgcolor** (CSS color): Background color.
- **headerbg** (CSS value for "background"): background for the header area,
default a grayish gradient.
- **footerbg** (CSS value for "background"): background for the footer area,
default a light gray gradient.
- **linkcolor** (CSS color): Body link color.
- **headercolor1**, **headercolor2** (CSS color): colors for <h1> and <h2>
headings.
- **headerlinkcolor** (CSS color): Color for the backreference link in
headings.
- **textalign** (CSS *text-align* value): Text alignment for the body, default
is ``justify``.
**nature**
A greenish theme. There are currently no options beyond
*nosidebar* and *sidebarwidth*.
**pyramid**
A theme from the Pyramid web framework project, designed by Blaise Laflamme.
There are currently no options beyond *nosidebar* and *sidebarwidth*.
**haiku**
A theme without sidebar inspired by the `Haiku OS user guide
<https://www.haiku-os.org/docs/userguide/en/contents.html>`_. The following
options are supported:
- **full_logo** (true or false, default ``False``): If this is true, the
header will only show the :confval:`html_logo`. Use this for large logos.
If this is false, the logo (if present) will be shown floating right, and
the documentation title will be put in the header.
- **textcolor**, **headingcolor**, **linkcolor**, **visitedlinkcolor**,
**hoverlinkcolor** (CSS colors): Colors for various body elements.
**traditional**
A theme resembling the old Python documentation. There are
currently no options beyond *nosidebar* and *sidebarwidth*.
**epub**
A theme for the epub builder. This theme tries to save visual
space which is a sparse resource on ebook readers. The following options
are supported:
- **relbar1** (true or false, default ``True``): If this is true, the
`relbar1` block is inserted in the epub output, otherwise it is omitted.
- **footer** (true or false, default ``True``): If this is true, the
`footer` block is inserted in the epub output, otherwise it is omitted.
**bizstyle**
A simple bluish theme. The following options are supported
beyond *nosidebar* and *sidebarwidth*:
- **rightsidebar** (true or false): Put the sidebar on the right side.
Defaults to ``False``.
.. versionadded:: 1.3
'alabaster', 'sphinx_rtd_theme' and 'bizstyle' theme.
.. versionchanged:: 1.3
The 'default' theme has been renamed to 'classic'. 'default' is still
available, however it will emit a notice that it is an alias for the new
'alabaster' theme.
Third Party Themes
~~~~~~~~~~~~~~~~~~
.. cssclass:: longtable
+--------------------+--------------------+
| **Theme overview** | |
+--------------------+--------------------+
| |sphinx_rtd_theme| | |
| | |
| *sphinx_rtd_theme* | |
+--------------------+--------------------+
.. |sphinx_rtd_theme| image:: /_static/themes/sphinx_rtd_theme.png
There are many third-party themes available. Some of these are general use,
while others are specific to an individual project. A section of third-party
themes is listed below. Many more can be found on PyPI__, GitHub__ and
sphinx-themes.org__.
.. cssclass:: clear
**sphinx_rtd_theme**
`Read the Docs Sphinx Theme`_.
This is a mobile-friendly sphinx theme that was made for readthedocs.org.
View a working demo over on readthedocs.org. You can get install and options
information at `Read the Docs Sphinx Theme`_ page.
.. _Read the Docs Sphinx Theme: https://pypi.org/project/sphinx_rtd_theme/
.. versionchanged:: 1.4
**sphinx_rtd_theme** has become optional.
.. __: https://pypi.org/search/?q=&o=&c=Framework+%3A%3A+Sphinx+%3A%3A+Theme
.. __: https://github.com/search?utf8=%E2%9C%93&q=sphinx+theme&type=
.. __: https://sphinx-themes.org/

376
package-lock.json generated
View File

@ -84,9 +84,9 @@
"dev": true "dev": true
}, },
"atob": { "atob": {
"version": "2.1.1", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
"dev": true "dev": true
}, },
"backo2": { "backo2": {
@ -178,21 +178,21 @@
} }
}, },
"binary-extensions": { "binary-extensions": {
"version": "1.11.0", "version": "1.12.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz",
"integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==",
"dev": true "dev": true
}, },
"blob": { "blob": {
"version": "0.0.4", "version": "0.0.5",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
"dev": true "dev": true
}, },
"bluebird": { "bluebird": {
"version": "3.5.1", "version": "3.5.3",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
"dev": true "dev": true
}, },
"body-parser": { "body-parser": {
@ -364,9 +364,9 @@
} }
}, },
"colors": { "colors": {
"version": "1.3.1", "version": "1.3.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.3.1.tgz", "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
"integrity": "sha512-jg/vxRmv430jixZrC+La5kMbUWqIg32/JsYNZb94+JEmzceYbWKTsv1OuTp+7EaqiaWRR2tPcykibwCRgclIsw==", "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==",
"dev": true "dev": true
}, },
"combine-lists": { "combine-lists": {
@ -433,9 +433,9 @@
"dev": true "dev": true
}, },
"core-js": { "core-js": {
"version": "2.5.7", "version": "2.6.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.2.tgz",
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", "integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g==",
"dev": true "dev": true
}, },
"core-util-is": { "core-util-is": {
@ -549,9 +549,9 @@
"dev": true "dev": true
}, },
"engine.io": { "engine.io": {
"version": "3.2.0", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.0.tgz", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
"integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
"dev": true, "dev": true,
"requires": { "requires": {
"accepts": "~1.3.4", "accepts": "~1.3.4",
@ -604,15 +604,15 @@
} }
}, },
"engine.io-parser": { "engine.io-parser": {
"version": "2.1.2", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
"integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
"dev": true, "dev": true,
"requires": { "requires": {
"after": "0.8.2", "after": "0.8.2",
"arraybuffer.slice": "~0.0.7", "arraybuffer.slice": "~0.0.7",
"base64-arraybuffer": "0.1.5", "base64-arraybuffer": "0.1.5",
"blob": "0.0.4", "blob": "0.0.5",
"has-binary2": "~1.0.2" "has-binary2": "~1.0.2"
} }
}, },
@ -859,13 +859,19 @@
} }
} }
}, },
"flatted": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz",
"integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==",
"dev": true
},
"follow-redirects": { "follow-redirects": {
"version": "1.5.5", "version": "1.6.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.5.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz",
"integrity": "sha512-GHjtHDlY/ehslqv0Gr5N0PUJppgg/q0rOBvX0na1s7y1A3LWxPqCYU76s3Z1bM4+UZB4QF0usaXLT5wFpof5PA==", "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"debug": "^3.1.0" "debug": "=3.1.0"
}, },
"dependencies": { "dependencies": {
"debug": { "debug": {
@ -922,24 +928,28 @@
"dependencies": { "dependencies": {
"abbrev": { "abbrev": {
"version": "1.1.1", "version": "1.1.1",
"bundled": true, "resolved": false,
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "resolved": false,
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true "dev": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
"bundled": true, "resolved": false,
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"are-we-there-yet": { "are-we-there-yet": {
"version": "1.1.4", "version": "1.1.4",
"bundled": true, "resolved": false,
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -949,12 +959,14 @@
}, },
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": false,
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true "dev": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "resolved": false,
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true, "dev": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
@ -963,34 +975,40 @@
}, },
"chownr": { "chownr": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "resolved": false,
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "resolved": false,
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true "dev": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "resolved": false,
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true "dev": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "resolved": false,
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
"dev": true "dev": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": false,
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"debug": { "debug": {
"version": "2.6.9", "version": "2.6.9",
"bundled": true, "resolved": false,
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -999,25 +1017,29 @@
}, },
"deep-extend": { "deep-extend": {
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "resolved": false,
"integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"delegates": { "delegates": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": false,
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"detect-libc": { "detect-libc": {
"version": "1.0.3", "version": "1.0.3",
"bundled": true, "resolved": false,
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"fs-minipass": { "fs-minipass": {
"version": "1.2.5", "version": "1.2.5",
"bundled": true, "resolved": false,
"integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1026,13 +1048,15 @@
}, },
"fs.realpath": { "fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": false,
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"gauge": { "gauge": {
"version": "2.7.4", "version": "2.7.4",
"bundled": true, "resolved": false,
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1048,7 +1072,8 @@
}, },
"glob": { "glob": {
"version": "7.1.2", "version": "7.1.2",
"bundled": true, "resolved": false,
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1062,13 +1087,15 @@
}, },
"has-unicode": { "has-unicode": {
"version": "2.0.1", "version": "2.0.1",
"bundled": true, "resolved": false,
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"iconv-lite": { "iconv-lite": {
"version": "0.4.21", "version": "0.4.21",
"bundled": true, "resolved": false,
"integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1077,7 +1104,8 @@
}, },
"ignore-walk": { "ignore-walk": {
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "resolved": false,
"integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1086,7 +1114,8 @@
}, },
"inflight": { "inflight": {
"version": "1.0.6", "version": "1.0.6",
"bundled": true, "resolved": false,
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1096,18 +1125,21 @@
}, },
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "resolved": false,
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true "dev": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
"bundled": true, "resolved": false,
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": false,
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true, "dev": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
@ -1115,13 +1147,15 @@
}, },
"isarray": { "isarray": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": false,
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "resolved": false,
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true, "dev": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
@ -1129,12 +1163,14 @@
}, },
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "resolved": false,
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true "dev": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "resolved": false,
"integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
"dev": true, "dev": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
@ -1143,7 +1179,8 @@
}, },
"minizlib": { "minizlib": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "resolved": false,
"integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1152,7 +1189,8 @@
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "resolved": false,
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true, "dev": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
@ -1160,13 +1198,15 @@
}, },
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"bundled": true, "resolved": false,
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"needle": { "needle": {
"version": "2.2.0", "version": "2.2.0",
"bundled": true, "resolved": false,
"integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1177,7 +1217,8 @@
}, },
"node-pre-gyp": { "node-pre-gyp": {
"version": "0.10.0", "version": "0.10.0",
"bundled": true, "resolved": false,
"integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1195,7 +1236,8 @@
}, },
"nopt": { "nopt": {
"version": "4.0.1", "version": "4.0.1",
"bundled": true, "resolved": false,
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1205,13 +1247,15 @@
}, },
"npm-bundled": { "npm-bundled": {
"version": "1.0.3", "version": "1.0.3",
"bundled": true, "resolved": false,
"integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"npm-packlist": { "npm-packlist": {
"version": "1.1.10", "version": "1.1.10",
"bundled": true, "resolved": false,
"integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1221,7 +1265,8 @@
}, },
"npmlog": { "npmlog": {
"version": "4.1.2", "version": "4.1.2",
"bundled": true, "resolved": false,
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1233,18 +1278,21 @@
}, },
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "resolved": false,
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true "dev": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
"bundled": true, "resolved": false,
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"once": { "once": {
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "resolved": false,
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true, "dev": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
@ -1252,19 +1300,22 @@
}, },
"os-homedir": { "os-homedir": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": false,
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"os-tmpdir": { "os-tmpdir": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": false,
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"osenv": { "osenv": {
"version": "0.1.5", "version": "0.1.5",
"bundled": true, "resolved": false,
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1274,19 +1325,22 @@
}, },
"path-is-absolute": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "resolved": false,
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"process-nextick-args": { "process-nextick-args": {
"version": "2.0.0", "version": "2.0.0",
"bundled": true, "resolved": false,
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"rc": { "rc": {
"version": "1.2.7", "version": "1.2.7",
"bundled": true, "resolved": false,
"integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1298,7 +1352,8 @@
"dependencies": { "dependencies": {
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"bundled": true, "resolved": false,
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true, "dev": true,
"optional": true "optional": true
} }
@ -1306,7 +1361,8 @@
}, },
"readable-stream": { "readable-stream": {
"version": "2.3.6", "version": "2.3.6",
"bundled": true, "resolved": false,
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1321,7 +1377,8 @@
}, },
"rimraf": { "rimraf": {
"version": "2.6.2", "version": "2.6.2",
"bundled": true, "resolved": false,
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1330,42 +1387,49 @@
}, },
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "resolved": false,
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
"dev": true "dev": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
"bundled": true, "resolved": false,
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"sax": { "sax": {
"version": "1.2.4", "version": "1.2.4",
"bundled": true, "resolved": false,
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"semver": { "semver": {
"version": "5.5.0", "version": "5.5.0",
"bundled": true, "resolved": false,
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"set-blocking": { "set-blocking": {
"version": "2.0.0", "version": "2.0.0",
"bundled": true, "resolved": false,
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"signal-exit": { "signal-exit": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "resolved": false,
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": false,
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true, "dev": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
@ -1375,7 +1439,8 @@
}, },
"string_decoder": { "string_decoder": {
"version": "1.1.1", "version": "1.1.1",
"bundled": true, "resolved": false,
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1384,7 +1449,8 @@
}, },
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "resolved": false,
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true, "dev": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
@ -1392,13 +1458,15 @@
}, },
"strip-json-comments": { "strip-json-comments": {
"version": "2.0.1", "version": "2.0.1",
"bundled": true, "resolved": false,
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"tar": { "tar": {
"version": "4.4.1", "version": "4.4.1",
"bundled": true, "resolved": false,
"integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1413,13 +1481,15 @@
}, },
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": false,
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"wide-align": { "wide-align": {
"version": "1.1.2", "version": "1.1.2",
"bundled": true, "resolved": false,
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -1428,12 +1498,14 @@
}, },
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": false,
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true "dev": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "resolved": false,
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
"dev": true "dev": true
} }
} }
@ -1445,9 +1517,9 @@
"dev": true "dev": true
}, },
"glob": { "glob": {
"version": "7.1.2", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"fs.realpath": "^1.0.0", "fs.realpath": "^1.0.0",
@ -1480,9 +1552,9 @@
} }
}, },
"graceful-fs": { "graceful-fs": {
"version": "4.1.11", "version": "4.1.15",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
"dev": true "dev": true
}, },
"has-binary2": { "has-binary2": {
@ -1758,9 +1830,9 @@
"dev": true "dev": true
}, },
"karma": { "karma": {
"version": "3.0.0", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/karma/-/karma-3.0.0.tgz", "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz",
"integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==", "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==",
"dev": true, "dev": true,
"requires": { "requires": {
"bluebird": "^3.3.0", "bluebird": "^3.3.0",
@ -1773,11 +1845,12 @@
"di": "^0.0.1", "di": "^0.0.1",
"dom-serialize": "^2.2.0", "dom-serialize": "^2.2.0",
"expand-braces": "^0.1.1", "expand-braces": "^0.1.1",
"flatted": "^2.0.0",
"glob": "^7.1.1", "glob": "^7.1.1",
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"http-proxy": "^1.13.0", "http-proxy": "^1.13.0",
"isbinaryfile": "^3.0.0", "isbinaryfile": "^3.0.0",
"lodash": "^4.17.4", "lodash": "^4.17.5",
"log4js": "^3.0.0", "log4js": "^3.0.0",
"mime": "^2.3.1", "mime": "^2.3.1",
"minimatch": "^3.0.2", "minimatch": "^3.0.2",
@ -1789,7 +1862,7 @@
"socket.io": "2.1.1", "socket.io": "2.1.1",
"source-map": "^0.6.1", "source-map": "^0.6.1",
"tmp": "0.0.33", "tmp": "0.0.33",
"useragent": "2.2.1" "useragent": "2.3.0"
} }
}, },
"karma-chrome-launcher": { "karma-chrome-launcher": {
@ -1821,9 +1894,9 @@
"dev": true "dev": true
}, },
"lodash": { "lodash": {
"version": "4.17.10", "version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
"dev": true "dev": true
}, },
"lodash.debounce": { "lodash.debounce": {
@ -1857,10 +1930,14 @@
} }
}, },
"lru-cache": { "lru-cache": {
"version": "2.2.4", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
"integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
"dev": true "dev": true,
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
}, },
"map-cache": { "map-cache": {
"version": "0.2.2", "version": "0.2.2",
@ -1911,18 +1988,18 @@
"dev": true "dev": true
}, },
"mime-db": { "mime-db": {
"version": "1.35.0", "version": "1.37.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
"integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==",
"dev": true "dev": true
}, },
"mime-types": { "mime-types": {
"version": "2.1.19", "version": "2.1.21",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
"integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
"dev": true, "dev": true,
"requires": { "requires": {
"mime-db": "~1.35.0" "mime-db": "~1.37.0"
} }
}, },
"minimatch": { "minimatch": {
@ -1977,9 +2054,9 @@
"dev": true "dev": true
}, },
"nan": { "nan": {
"version": "2.10.0", "version": "2.12.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
@ -2166,6 +2243,12 @@
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true "dev": true
}, },
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
"dev": true
},
"qjobs": { "qjobs": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
@ -2212,15 +2295,14 @@
} }
}, },
"readdirp": { "readdirp": {
"version": "2.1.0", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
"integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.11",
"minimatch": "^3.0.2", "micromatch": "^3.1.10",
"readable-stream": "^2.0.2", "readable-stream": "^2.0.2"
"set-immediate-shim": "^1.0.1"
} }
}, },
"regex-not": { "regex-not": {
@ -2240,9 +2322,9 @@
"dev": true "dev": true
}, },
"repeat-element": { "repeat-element": {
"version": "1.1.2", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
"integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
"dev": true "dev": true
}, },
"repeat-string": { "repeat-string": {
@ -2276,12 +2358,12 @@
"dev": true "dev": true
}, },
"rimraf": { "rimraf": {
"version": "2.6.2", "version": "2.6.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"dev": true, "dev": true,
"requires": { "requires": {
"glob": "^7.0.5" "glob": "^7.1.3"
} }
}, },
"safe-buffer": { "safe-buffer": {
@ -2305,12 +2387,6 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true "dev": true
}, },
"set-immediate-shim": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
"dev": true
},
"set-value": { "set-value": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
@ -2811,12 +2887,12 @@
"dev": true "dev": true
}, },
"useragent": { "useragent": {
"version": "2.2.1", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
"integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
"dev": true, "dev": true,
"requires": { "requires": {
"lru-cache": "2.2.x", "lru-cache": "4.1.x",
"tmp": "0.0.x" "tmp": "0.0.x"
} }
}, },
@ -2876,6 +2952,12 @@
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
"dev": true "dev": true
}, },
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true
},
"yeast": { "yeast": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",

View File

@ -43,18 +43,17 @@ paths =
. .
[mypy] [mypy]
python_version = 2.7
show_column_numbers = True show_column_numbers = True
show_error_context = True show_error_context = True
ignore_missing_imports = True ignore_missing_imports = True
follow_imports = skip follow_imports = skip
incremental = True
check_untyped_defs = True check_untyped_defs = True
warn_unused_ignores = True warn_unused_ignores = True
strict_optional = False strict_optional = False
[tool:pytest] [tool:pytest]
filterwarnings = filterwarnings =
all
ignore::DeprecationWarning:docutils.io ignore::DeprecationWarning:docutils.io
[coverage:run] [coverage:run]

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import os import os
import sys import sys
from distutils import log from distutils import log
@ -16,7 +15,10 @@ if sys.version_info < (3, 5):
sys.exit(1) sys.exit(1)
install_requires = [ install_requires = [
'six>=1.5', 'sphinxcontrib-applehelp',
'sphinxcontrib-devhelp',
'sphinxcontrib-jsmath',
'sphinxcontrib-qthelp',
'Jinja2>=2.3', 'Jinja2>=2.3',
'Pygments>=2.0', 'Pygments>=2.0',
'docutils>=0.12', 'docutils>=0.12',
@ -24,7 +26,7 @@ install_requires = [
'babel>=1.3,!=2.0', 'babel>=1.3,!=2.0',
'alabaster>=0.7,<0.8', 'alabaster>=0.7,<0.8',
'imagesize', 'imagesize',
'requests>=2.0.0', 'requests>=2.5.0',
'setuptools', 'setuptools',
'packaging', 'packaging',
] ]
@ -34,10 +36,6 @@ extras_require = {
':sys_platform=="win32"': [ ':sys_platform=="win32"': [
'colorama>=0.3.5', 'colorama>=0.3.5',
], ],
'websupport': [
'sqlalchemy>=0.9',
'whoosh>=2.0',
],
'test': [ 'test': [
'mock', 'mock',
'pytest', 'pytest',
@ -45,8 +43,8 @@ extras_require = {
'html5lib', 'html5lib',
'flake8>=3.5.0', 'flake8>=3.5.0',
'flake8-import-order', 'flake8-import-order',
'mypy', 'mypy>=0.590',
'typed_ast', 'docutils-stubs',
], ],
} }
@ -56,7 +54,7 @@ extras_require = {
cmdclass = {} cmdclass = {}
class Tee(object): class Tee:
def __init__(self, stream): def __init__(self, stream):
self.stream = stream self.stream = stream
self.buffer = StringIO() self.buffer = StringIO()
@ -133,7 +131,7 @@ else:
domain + '.js')) domain + '.js'))
for js_file, (locale, po_file) in zip(js_files, po_files): for js_file, (locale, po_file) in zip(js_files, po_files):
with open(po_file, 'r') as infile: with open(po_file) as infile:
catalog = read_po(infile, locale) catalog = read_po(infile, locale)
if catalog.fuzzy and not self.use_fuzzy: if catalog.fuzzy and not self.use_fuzzy:
@ -153,11 +151,11 @@ else:
with open(js_file, 'wt') as outfile: with open(js_file, 'wt') as outfile:
outfile.write('Documentation.addTranslations(') outfile.write('Documentation.addTranslations(')
dump(dict( dump({
messages=jscatalog, 'messages': jscatalog,
plural_expr=catalog.plural_expr, 'plural_expr': catalog.plural_expr,
locale=str(catalog.locale) 'locale': str(catalog.locale)
), outfile, sort_keys=True) }, outfile, sort_keys=True)
outfile.write(');') outfile.write(');')
cmdclass['compile_catalog'] = compile_catalog_plusjs cmdclass['compile_catalog'] = compile_catalog_plusjs

View File

@ -1,36 +1,33 @@
# -*- coding: utf-8 -*-
""" """
Sphinx Sphinx
~~~~~~ ~~~~~~
The Sphinx documentation toolchain. The Sphinx documentation toolchain.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
# Keep this file executable as-is in Python 3! # Keep this file executable as-is in Python 3!
# (Otherwise getting the version out of it from setup.py is impossible.) # (Otherwise getting the version out of it from setup.py is impossible.)
from __future__ import absolute_import
import os import os
import subprocess
import warnings import warnings
from os import path from os import path
from subprocess import PIPE
from .deprecation import RemovedInNextVersionWarning from .deprecation import RemovedInNextVersionWarning
if False: if False:
# For type annotation # For type annotation
# note: Don't use typing.TYPE_CHECK here (for py27 and py34).
from typing import Any # NOQA from typing import Any # NOQA
# by default, all DeprecationWarning under sphinx package will be emit. # by default, all DeprecationWarning under sphinx package will be emit.
# Users can avoid this by using environment variable: PYTHONWARNINGS= # Users can avoid this by using environment variable: PYTHONWARNINGS=
if 'PYTHONWARNINGS' not in os.environ: if 'PYTHONWARNINGS' not in os.environ:
warnings.filterwarnings('default', warnings.filterwarnings('default', category=RemovedInNextVersionWarning)
category=RemovedInNextVersionWarning, module='sphinx')
# docutils.io using mode='rU' for open # docutils.io using mode='rU' for open
warnings.filterwarnings('ignore', "'U' mode is deprecated", warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io') DeprecationWarning, module='docutils.io')
@ -58,11 +55,9 @@ if __version__.endswith('+'):
__display_version__ = __version__ __display_version__ = __version__
__version__ = __version__[:-1] # remove '+' for PEP-440 version spec. __version__ = __version__[:-1] # remove '+' for PEP-440 version spec.
try: try:
import subprocess ret = subprocess.run(['git', 'show', '-s', '--pretty=format:%h'],
p = subprocess.Popen(['git', 'show', '-s', '--pretty=format:%h'], stdout=PIPE, stderr=PIPE, encoding='ascii')
stdout=subprocess.PIPE, stderr=subprocess.PIPE) if ret.stdout:
out, err = p.communicate() __display_version__ += '/' + ret.stdout.strip()
if out:
__display_version__ += '/' + out.decode().strip()
except Exception: except Exception:
pass pass

View File

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
""" """
sphinx.__main__ sphinx.__main__
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
The Sphinx documentation toolchain. The Sphinx documentation toolchain.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -13,4 +12,4 @@ import sys
from sphinx.cmd.build import main from sphinx.cmd.build import main
sys.exit(main(sys.argv[1:])) # type: ignore sys.exit(main(sys.argv[1:]))

View File

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
""" """
sphinx.addnodes sphinx.addnodes
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
Additional docutils nodes. Additional docutils nodes.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -13,14 +12,15 @@ import warnings
from docutils import nodes from docutils import nodes
from sphinx.deprecation import RemovedInSphinx30Warning from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
if False: if False:
# For type annotation # For type annotation
from typing import List, Sequence # NOQA from typing import Any, Dict, List, Sequence # NOQA
from sphinx.application import Sphinx # NOQA
class translatable(object): class translatable(nodes.Node):
"""Node which supports translation. """Node which supports translation.
The translation goes forward with following steps: The translation goes forward with following steps:
@ -40,12 +40,12 @@ class translatable(object):
raise NotImplementedError raise NotImplementedError
def apply_translated_message(self, original_message, translated_message): def apply_translated_message(self, original_message, translated_message):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Apply translated message.""" """Apply translated message."""
raise NotImplementedError raise NotImplementedError
def extract_original_messages(self): def extract_original_messages(self):
# type: () -> Sequence[unicode] # type: () -> Sequence[str]
"""Extract translation messages. """Extract translation messages.
:returns: list of extracted messages or messages generator :returns: list of extracted messages or messages generator
@ -53,7 +53,7 @@ class translatable(object):
raise NotImplementedError raise NotImplementedError
class not_smartquotable(object): class not_smartquotable:
"""A node which does not support smart-quotes.""" """A node which does not support smart-quotes."""
support_smartquotes = False support_smartquotes = False
@ -67,12 +67,12 @@ class toctree(nodes.General, nodes.Element, translatable):
self['rawcaption'] = self['caption'] self['rawcaption'] = self['caption']
def apply_translated_message(self, original_message, translated_message): def apply_translated_message(self, original_message, translated_message):
# type: (unicode, unicode) -> None # type: (str, str) -> None
if self.get('rawcaption') == original_message: if self.get('rawcaption') == original_message:
self['caption'] = translated_message self['caption'] = translated_message
def extract_original_messages(self): def extract_original_messages(self):
# type: () -> List[unicode] # type: () -> List[str]
if 'rawcaption' in self: if 'rawcaption' in self:
return [self['rawcaption']] return [self['rawcaption']]
else: else:
@ -106,6 +106,7 @@ class desc_signature_line(nodes.Part, nodes.Inline, nodes.FixedTextElement):
It should only be used in a ``desc_signature`` with ``is_multiline`` set. It should only be used in a ``desc_signature`` with ``is_multiline`` set.
Set ``add_permalink = True`` for the line that should get the permalink. Set ``add_permalink = True`` for the line that should get the permalink.
""" """
sphinx_cpp_tagname = ''
# nodes to use within a desc_signature or desc_signature_line # nodes to use within a desc_signature or desc_signature_line
@ -125,8 +126,8 @@ class desc_type(nodes.Part, nodes.Inline, nodes.FixedTextElement):
class desc_returns(desc_type): class desc_returns(desc_type):
"""Node for a "returns" annotation (a la -> in Python).""" """Node for a "returns" annotation (a la -> in Python)."""
def astext(self): def astext(self):
# type: () -> unicode # type: () -> str
return ' -> ' + nodes.TextElement.astext(self) return ' -> ' + super().astext()
class desc_name(nodes.Part, nodes.Inline, nodes.FixedTextElement): class desc_name(nodes.Part, nodes.Inline, nodes.FixedTextElement):
@ -147,8 +148,8 @@ class desc_optional(nodes.Part, nodes.Inline, nodes.FixedTextElement):
child_text_separator = ', ' child_text_separator = ', '
def astext(self): def astext(self):
# type: () -> unicode # type: () -> str
return '[' + nodes.TextElement.astext(self) + ']' return '[' + super().astext() + ']'
class desc_annotation(nodes.Part, nodes.Inline, nodes.FixedTextElement): class desc_annotation(nodes.Part, nodes.Inline, nodes.FixedTextElement):
@ -205,10 +206,10 @@ class math(nodes.math):
if key == 'latex' and 'latex' not in self.attributes: if key == 'latex' and 'latex' not in self.attributes:
warnings.warn("math node for Sphinx was replaced by docutils'. " warnings.warn("math node for Sphinx was replaced by docutils'. "
"Therefore please use ``node.astext()`` to get an equation instead.", "Therefore please use ``node.astext()`` to get an equation instead.",
RemovedInSphinx30Warning) RemovedInSphinx30Warning, stacklevel=2)
return self.astext() return self.astext()
else: else:
return nodes.math.__getitem__(self, key) return super().__getitem__(key)
class math_block(nodes.math_block): class math_block(nodes.math_block):
@ -224,10 +225,10 @@ class math_block(nodes.math_block):
if key == 'latex' and 'latex' not in self.attributes: if key == 'latex' and 'latex' not in self.attributes:
warnings.warn("displaymath node for Sphinx was replaced by docutils'. " warnings.warn("displaymath node for Sphinx was replaced by docutils'. "
"Therefore please use ``node.astext()`` to get an equation instead.", "Therefore please use ``node.astext()`` to get an equation instead.",
RemovedInSphinx30Warning) RemovedInSphinx30Warning, stacklevel=2)
return self.astext() return self.astext()
else: else:
return nodes.math_block.__getitem__(self, key) return super().__getitem__(key)
class displaymath(math_block): class displaymath(math_block):
@ -251,8 +252,8 @@ class index(nodes.Invisible, nodes.Inline, nodes.TextElement):
*entrytype* is one of "single", "pair", "double", "triple". *entrytype* is one of "single", "pair", "double", "triple".
*key* is categolziation characters (usually it is single character) for *key* is categorization characters (usually a single character) for
general index page. For the detail of this, please see also: general index page. For the details of this, please see also:
:rst:dir:`glossary` and issue #2320. :rst:dir:`glossary` and issue #2320.
""" """
@ -307,6 +308,7 @@ class meta(nodes.Special, nodes.PreBibliographic, nodes.Element):
"""Node for meta directive -- same as docutils' standard meta node, """Node for meta directive -- same as docutils' standard meta node,
but pickleable. but pickleable.
""" """
rawcontent = None
# inline nodes # inline nodes
@ -340,15 +342,65 @@ class literal_strong(nodes.strong, not_smartquotable):
""" """
class abbreviation(nodes.Inline, nodes.TextElement): class abbreviation(nodes.abbreviation):
"""Node for abbreviations with explanations.""" """Node for abbreviations with explanations.
.. deprecated:: 2.0
"""
def __init__(self, rawsource='', text='', *children, **attributes):
# type: (str, str, *nodes.Node, **Any) -> None
warnings.warn("abbrevition node for Sphinx was replaced by docutils'.",
RemovedInSphinx40Warning, stacklevel=2)
super().__init__(rawsource, text, *children, **attributes)
class manpage(nodes.Inline, nodes.FixedTextElement): class manpage(nodes.Inline, nodes.FixedTextElement):
"""Node for references to manpages.""" """Node for references to manpages."""
# make the new nodes known to docutils; needed because the HTML writer will def setup(app):
# choke at some point if these are not added # type: (Sphinx) -> Dict[str, Any]
nodes._add_node_class_names(k for k in globals().keys() app.add_node(toctree)
if k != 'nodes' and k[0] != '_') app.add_node(desc)
app.add_node(desc_signature)
app.add_node(desc_signature_line)
app.add_node(desc_addname)
app.add_node(desc_type)
app.add_node(desc_returns)
app.add_node(desc_name)
app.add_node(desc_parameterlist)
app.add_node(desc_parameter)
app.add_node(desc_optional)
app.add_node(desc_annotation)
app.add_node(desc_content)
app.add_node(versionmodified)
app.add_node(seealso)
app.add_node(productionlist)
app.add_node(production)
app.add_node(displaymath)
app.add_node(index)
app.add_node(centered)
app.add_node(acks)
app.add_node(hlist)
app.add_node(hlistcol)
app.add_node(compact_paragraph)
app.add_node(glossary)
app.add_node(only)
app.add_node(start_of_file)
app.add_node(highlightlang)
app.add_node(tabular_col_spec)
app.add_node(meta)
app.add_node(pending_xref)
app.add_node(number_reference)
app.add_node(download_reference)
app.add_node(literal_emphasis)
app.add_node(literal_strong)
app.add_node(manpage)
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
sphinx.application sphinx.application
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
@ -7,26 +6,24 @@
Gracefully adapted from the TextPress system by Armin. Gracefully adapted from the TextPress system by Armin.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
from __future__ import print_function
import os import os
import pickle
import sys import sys
import warnings import warnings
from collections import deque from collections import deque
from inspect import isclass from inspect import isclass
from io import StringIO
from os import path from os import path
from docutils.parsers.rst import Directive, directives, roles from docutils.parsers.rst import Directive, roles
from six import itervalues
from six.moves import cPickle as pickle
from six.moves import cStringIO
import sphinx import sphinx
from sphinx import package_dir, locale from sphinx import package_dir, locale
from sphinx.config import Config, check_unicode from sphinx.config import Config
from sphinx.config import CONFIG_FILENAME # NOQA # for compatibility (RemovedInSphinx30) from sphinx.config import CONFIG_FILENAME # NOQA # for compatibility (RemovedInSphinx30)
from sphinx.deprecation import ( from sphinx.deprecation import (
RemovedInSphinx30Warning, RemovedInSphinx40Warning RemovedInSphinx30Warning, RemovedInSphinx40Warning
@ -35,15 +32,17 @@ from sphinx.environment import BuildEnvironment
from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
from sphinx.events import EventManager from sphinx.events import EventManager
from sphinx.locale import __ from sphinx.locale import __
from sphinx.project import Project
from sphinx.registry import SphinxComponentRegistry from sphinx.registry import SphinxComponentRegistry
from sphinx.util import docutils from sphinx.util import docutils
from sphinx.util import import_object from sphinx.util import import_object, progress_message
from sphinx.util import logging from sphinx.util import logging
from sphinx.util import pycompat # noqa: F401 from sphinx.util import pycompat # noqa: F401
from sphinx.util.build_phase import BuildPhase from sphinx.util.build_phase import BuildPhase
from sphinx.util.console import bold # type: ignore from sphinx.util.console import bold # type: ignore
from sphinx.util.docutils import directive_helper from sphinx.util.docutils import directive_helper
from sphinx.util.i18n import find_catalog_source_files from sphinx.util.i18n import find_catalog_source_files
from sphinx.util.logging import prefixed_warnings
from sphinx.util.osutil import abspath, ensuredir, relpath from sphinx.util.osutil import abspath, ensuredir, relpath
from sphinx.util.tags import Tags from sphinx.util.tags import Tags
@ -62,10 +61,10 @@ if False:
from sphinx.util.typing import RoleFunction, TitleGetter # NOQA from sphinx.util.typing import RoleFunction, TitleGetter # NOQA
builtin_extensions = ( builtin_extensions = (
'sphinx.builders.applehelp', 'sphinx.addnodes',
'sphinx.builders.changes', 'sphinx.builders.changes',
'sphinx.builders.epub3', 'sphinx.builders.epub3',
'sphinx.builders.devhelp', 'sphinx.builders.dirhtml',
'sphinx.builders.dummy', 'sphinx.builders.dummy',
'sphinx.builders.gettext', 'sphinx.builders.gettext',
'sphinx.builders.html', 'sphinx.builders.html',
@ -73,10 +72,9 @@ builtin_extensions = (
'sphinx.builders.latex', 'sphinx.builders.latex',
'sphinx.builders.linkcheck', 'sphinx.builders.linkcheck',
'sphinx.builders.manpage', 'sphinx.builders.manpage',
'sphinx.builders.qthelp', 'sphinx.builders.singlehtml',
'sphinx.builders.texinfo', 'sphinx.builders.texinfo',
'sphinx.builders.text', 'sphinx.builders.text',
'sphinx.builders.websupport',
'sphinx.builders.xml', 'sphinx.builders.xml',
'sphinx.config', 'sphinx.config',
'sphinx.domains.c', 'sphinx.domains.c',
@ -92,7 +90,6 @@ builtin_extensions = (
'sphinx.directives.other', 'sphinx.directives.other',
'sphinx.directives.patches', 'sphinx.directives.patches',
'sphinx.extension', 'sphinx.extension',
'sphinx.io',
'sphinx.parsers', 'sphinx.parsers',
'sphinx.registry', 'sphinx.registry',
'sphinx.roles', 'sphinx.roles',
@ -108,17 +105,21 @@ builtin_extensions = (
'sphinx.environment.collectors.title', 'sphinx.environment.collectors.title',
'sphinx.environment.collectors.toctree', 'sphinx.environment.collectors.toctree',
'sphinx.environment.collectors.indexentries', 'sphinx.environment.collectors.indexentries',
# 1st party extensions
'sphinxcontrib.applehelp',
'sphinxcontrib.devhelp',
'sphinxcontrib.qthelp',
# Strictly, alabaster theme is not a builtin extension, # Strictly, alabaster theme is not a builtin extension,
# but it is loaded automatically to use it as default theme. # but it is loaded automatically to use it as default theme.
'alabaster', 'alabaster',
) # type: Tuple[unicode, ...] )
ENV_PICKLE_FILENAME = 'environment.pickle' ENV_PICKLE_FILENAME = 'environment.pickle'
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Sphinx(object): class Sphinx:
"""The main application class and extensibility interface. """The main application class and extensibility interface.
:ivar srcdir: Directory containing source. :ivar srcdir: Directory containing source.
@ -131,20 +132,20 @@ class Sphinx(object):
confoverrides=None, status=sys.stdout, warning=sys.stderr, confoverrides=None, status=sys.stdout, warning=sys.stderr,
freshenv=False, warningiserror=False, tags=None, verbosity=0, freshenv=False, warningiserror=False, tags=None, verbosity=0,
parallel=0, keep_going=False): parallel=0, keep_going=False):
# type: (unicode, unicode, unicode, unicode, unicode, Dict, IO, IO, bool, bool, List[unicode], int, int, bool) -> None # NOQA # type: (str, str, str, str, str, Dict, IO, IO, bool, bool, List[str], int, int, bool) -> None # NOQA
self.phase = BuildPhase.INITIALIZATION self.phase = BuildPhase.INITIALIZATION
self.verbosity = verbosity self.verbosity = verbosity
self.extensions = {} # type: Dict[unicode, Extension] self.extensions = {} # type: Dict[str, Extension]
self._setting_up_extension = ['?'] # type: List[unicode]
self.builder = None # type: Builder self.builder = None # type: Builder
self.env = None # type: BuildEnvironment self.env = None # type: BuildEnvironment
self.project = None # type: Project
self.registry = SphinxComponentRegistry() self.registry = SphinxComponentRegistry()
self.html_themes = {} # type: Dict[unicode, unicode] self.html_themes = {} # type: Dict[str, str]
# validate provided directories # validate provided directories
self.srcdir = abspath(srcdir) # type: unicode self.srcdir = abspath(srcdir)
self.outdir = abspath(outdir) # type: unicode self.outdir = abspath(outdir)
self.doctreedir = abspath(doctreedir) # type: unicode self.doctreedir = abspath(doctreedir)
self.confdir = confdir self.confdir = confdir
if self.confdir: # confdir is optional if self.confdir: # confdir is optional
self.confdir = abspath(self.confdir) self.confdir = abspath(self.confdir)
@ -163,14 +164,14 @@ class Sphinx(object):
self.parallel = parallel self.parallel = parallel
if status is None: if status is None:
self._status = cStringIO() # type: IO self._status = StringIO() # type: IO
self.quiet = True self.quiet = True
else: else:
self._status = status self._status = status
self.quiet = False self.quiet = False
if warning is None: if warning is None:
self._warning = cStringIO() # type: IO self._warning = StringIO() # type: IO
else: else:
self._warning = warning self._warning = warning
self._warncount = 0 self._warncount = 0
@ -199,7 +200,6 @@ class Sphinx(object):
self.config = Config({}, confoverrides or {}) self.config = Config({}, confoverrides or {})
else: else:
self.config = Config.read(self.confdir, confoverrides or {}, self.tags) self.config = Config.read(self.confdir, confoverrides or {}, self.tags)
check_unicode(self.config)
# initialize some limited config variables before initialize i18n and loading # initialize some limited config variables before initialize i18n and loading
# extensions # extensions
@ -231,30 +231,28 @@ class Sphinx(object):
self.preload_builder(buildername) self.preload_builder(buildername)
if not path.isdir(outdir): if not path.isdir(outdir):
logger.info(__('making output directory...')) with progress_message(__('making output directory')):
ensuredir(outdir) ensuredir(outdir)
# the config file itself can be an extension # the config file itself can be an extension
if self.config.setup: if self.config.setup:
self._setting_up_extension = ['conf.py'] prefix = __('while setting up extension %s:') % "conf.py"
with prefixed_warnings(prefix):
if callable(self.config.setup): if callable(self.config.setup):
self.config.setup(self) self.config.setup(self)
else: else:
raise ConfigError( raise ConfigError(
__("'setup' as currently defined in conf.py isn't a Python callable. " __("'setup' as currently defined in conf.py isn't a Python callable. "
"Please modify its definition to make it a callable function. This is " "Please modify its definition to make it a callable function. "
"needed for conf.py to behave as a Sphinx extension.") "This is needed for conf.py to behave as a Sphinx extension.")
) )
# now that we know all config values, collect them from conf.py # now that we know all config values, collect them from conf.py
self.config.init_values() self.config.init_values()
self.emit('config-inited', self.config) self.emit('config-inited', self.config)
# check primary_domain if requested # create the project
primary_domain = self.config.primary_domain self.project = Project(self.srcdir, self.config.source_suffix)
if primary_domain and not self.registry.has_domain(primary_domain):
logger.warning(__('primary_domain %r not found, ignored.'), primary_domain)
# create the builder # create the builder
self.builder = self.create_builder(buildername) self.builder = self.create_builder(buildername)
# set up the build environment # set up the build environment
@ -277,10 +275,10 @@ class Sphinx(object):
user_locale_dirs, self.config.language, domains=['sphinx'], user_locale_dirs, self.config.language, domains=['sphinx'],
charset=self.config.source_encoding): charset=self.config.source_encoding):
catinfo.write_mo(self.config.language) catinfo.write_mo(self.config.language)
locale_dirs = [None, path.join(package_dir, 'locale')] + user_locale_dirs # type: ignore # NOQA locale_dirs = [None, path.join(package_dir, 'locale')] + user_locale_dirs
else: else:
locale_dirs = [] locale_dirs = []
self.translator, has_translation = locale.init(locale_dirs, self.config.language) # type: ignore # NOQA self.translator, has_translation = locale.init(locale_dirs, self.config.language)
if self.config.language is not None: if self.config.language is not None:
if has_translation or self.config.language == 'en': if has_translation or self.config.language == 'en':
# "en" never needs to be translated # "en" never needs to be translated
@ -297,21 +295,20 @@ class Sphinx(object):
self.env.find_files(self.config, self.builder) self.env.find_files(self.config, self.builder)
else: else:
try: try:
logger.info(bold(__('loading pickled environment... ')), nonl=True) with progress_message(__('loading pickled environment')):
with open(filename, 'rb') as f: with open(filename, 'rb') as f:
self.env = pickle.load(f) self.env = pickle.load(f)
self.env.setup(self) self.env.setup(self)
logger.info(__('done'))
except Exception as err: except Exception as err:
logger.info(__('failed: %s'), err) logger.info(__('failed: %s'), err)
self._init_env(freshenv=True) self._init_env(freshenv=True)
def preload_builder(self, name): def preload_builder(self, name):
# type: (unicode) -> None # type: (str) -> None
self.registry.preload_builder(self, name) self.registry.preload_builder(self, name)
def create_builder(self, name): def create_builder(self, name):
# type: (unicode) -> Builder # type: (str) -> Builder
if name is None: if name is None:
logger.info(__('No builder selected, using default: html')) logger.info(__('No builder selected, using default: html'))
name = 'html' name = 'html'
@ -327,7 +324,7 @@ class Sphinx(object):
# ---- main "build" method ------------------------------------------------- # ---- main "build" method -------------------------------------------------
def build(self, force_all=False, filenames=None): def build(self, force_all=False, filenames=None):
# type: (bool, List[unicode]) -> None # type: (bool, List[str]) -> None
self.phase = BuildPhase.READING self.phase = BuildPhase.READING
try: try:
if force_all: if force_all:
@ -372,7 +369,7 @@ class Sphinx(object):
# ---- general extensibility interface ------------------------------------- # ---- general extensibility interface -------------------------------------
def setup_extension(self, extname): def setup_extension(self, extname):
# type: (unicode) -> None # type: (str) -> None
"""Import and setup a Sphinx extension module. """Import and setup a Sphinx extension module.
Load the extension given by the module *name*. Use this if your Load the extension given by the module *name*. Use this if your
@ -383,7 +380,7 @@ class Sphinx(object):
self.registry.load_extension(self, extname) self.registry.load_extension(self, extname)
def require_sphinx(self, version): def require_sphinx(self, version):
# type: (unicode) -> None # type: (str) -> None
"""Check the Sphinx version if requested. """Check the Sphinx version if requested.
Compare *version* (which must be a ``major.minor`` version string, e.g. Compare *version* (which must be a ``major.minor`` version string, e.g.
@ -396,7 +393,7 @@ class Sphinx(object):
raise VersionRequirementError(version) raise VersionRequirementError(version)
def import_object(self, objname, source=None): def import_object(self, objname, source=None):
# type: (str, unicode) -> Any # type: (str, str) -> Any
"""Import an object from a ``module.name`` string. """Import an object from a ``module.name`` string.
.. deprecated:: 1.8 .. deprecated:: 1.8
@ -404,12 +401,12 @@ class Sphinx(object):
""" """
warnings.warn('app.import_object() is deprecated. ' warnings.warn('app.import_object() is deprecated. '
'Use sphinx.util.add_object_type() instead.', 'Use sphinx.util.add_object_type() instead.',
RemovedInSphinx30Warning) RemovedInSphinx30Warning, stacklevel=2)
return import_object(objname, source=None) return import_object(objname, source=None)
# event interface # event interface
def connect(self, event, callback): def connect(self, event, callback):
# type: (unicode, Callable) -> int # type: (str, Callable) -> int
"""Register *callback* to be called when *event* is emitted. """Register *callback* to be called when *event* is emitted.
For details on available core events and the arguments of callback For details on available core events and the arguments of callback
@ -429,7 +426,7 @@ class Sphinx(object):
self.events.disconnect(listener_id) self.events.disconnect(listener_id)
def emit(self, event, *args): def emit(self, event, *args):
# type: (unicode, Any) -> List # type: (str, Any) -> List
"""Emit *event* and pass *arguments* to the callback functions. """Emit *event* and pass *arguments* to the callback functions.
Return the return values of all callbacks as a list. Do not emit core Return the return values of all callbacks as a list. Do not emit core
@ -444,7 +441,7 @@ class Sphinx(object):
return self.events.emit(event, self, *args) return self.events.emit(event, self, *args)
def emit_firstresult(self, event, *args): def emit_firstresult(self, event, *args):
# type: (unicode, Any) -> Any # type: (str, Any) -> Any
"""Emit *event* and pass *arguments* to the callback functions. """Emit *event* and pass *arguments* to the callback functions.
Return the result of the first callback that doesn't return ``None``. Return the result of the first callback that doesn't return ``None``.
@ -469,7 +466,7 @@ class Sphinx(object):
# TODO(stephenfin): Describe 'types' parameter # TODO(stephenfin): Describe 'types' parameter
def add_config_value(self, name, default, rebuild, types=()): def add_config_value(self, name, default, rebuild, types=()):
# type: (unicode, Any, Union[bool, unicode], Any) -> None # type: (str, Any, Union[bool, str], Any) -> None
"""Register a configuration value. """Register a configuration value.
This is necessary for Sphinx to recognize new values and set default This is necessary for Sphinx to recognize new values and set default
@ -502,7 +499,7 @@ class Sphinx(object):
self.config.add(name, default, rebuild, types) self.config.add(name, default, rebuild, types)
def add_event(self, name): def add_event(self, name):
# type: (unicode) -> None # type: (str) -> None
"""Register an event called *name*. """Register an event called *name*.
This is needed to be able to emit it. This is needed to be able to emit it.
@ -511,7 +508,7 @@ class Sphinx(object):
self.events.add(name) self.events.add(name)
def set_translator(self, name, translator_class, override=False): def set_translator(self, name, translator_class, override=False):
# type: (unicode, Type[nodes.NodeVisitor], bool) -> None # type: (str, Type[nodes.NodeVisitor], bool) -> None
"""Register or override a Docutils translator class. """Register or override a Docutils translator class.
This is used to register a custom output translator or to replace a This is used to register a custom output translator or to replace a
@ -525,7 +522,7 @@ class Sphinx(object):
self.registry.add_translator(name, translator_class, override=override) self.registry.add_translator(name, translator_class, override=override)
def add_node(self, node, override=False, **kwds): def add_node(self, node, override=False, **kwds):
# type: (nodes.Node, bool, Any) -> None # type: (Type[nodes.Element], bool, Any) -> None
"""Register a Docutils node class. """Register a Docutils node class.
This is necessary for Docutils internals. It may also be used in the This is necessary for Docutils internals. It may also be used in the
@ -557,15 +554,14 @@ class Sphinx(object):
""" """
logger.debug('[app] adding node: %r', (node, kwds)) logger.debug('[app] adding node: %r', (node, kwds))
if not override and docutils.is_node_registered(node): if not override and docutils.is_node_registered(node):
logger.warning(__('while setting up extension %s: node class %r is ' logger.warning(__('node class %r is already registered, '
'already registered, its visitors will be overridden'), 'its visitors will be overridden'),
self._setting_up_extension, node.__name__, node.__name__, type='app', subtype='add_node')
type='app', subtype='add_node')
docutils.register_node(node) docutils.register_node(node)
self.registry.add_translation_handlers(node, **kwds) self.registry.add_translation_handlers(node, **kwds)
def add_enumerable_node(self, node, figtype, title_getter=None, override=False, **kwds): def add_enumerable_node(self, node, figtype, title_getter=None, override=False, **kwds):
# type: (nodes.Node, unicode, TitleGetter, bool, Any) -> None # type: (Type[nodes.Element], str, TitleGetter, bool, Any) -> None
"""Register a Docutils node class as a numfig target. """Register a Docutils node class as a numfig target.
Sphinx numbers the node automatically. And then the users can refer it Sphinx numbers the node automatically. And then the users can refer it
@ -594,14 +590,14 @@ class Sphinx(object):
@property @property
def enumerable_nodes(self): def enumerable_nodes(self):
# type: () -> Dict[nodes.Node, Tuple[unicode, TitleGetter]] # type: () -> Dict[Type[nodes.Node], Tuple[str, TitleGetter]]
warnings.warn('app.enumerable_nodes() is deprecated. ' warnings.warn('app.enumerable_nodes() is deprecated. '
'Use app.get_domain("std").enumerable_nodes instead.', 'Use app.get_domain("std").enumerable_nodes instead.',
RemovedInSphinx30Warning) RemovedInSphinx30Warning, stacklevel=2)
return self.registry.enumerable_nodes return self.registry.enumerable_nodes
def add_directive(self, name, obj, content=None, arguments=None, override=False, **options): # NOQA def add_directive(self, name, obj, content=None, arguments=None, override=False, **options): # NOQA
# type: (unicode, Any, bool, Tuple[int, int, bool], bool, Any) -> None # type: (str, Any, bool, Tuple[int, int, bool], bool, Any) -> None
"""Register a Docutils directive. """Register a Docutils directive.
*name* must be the prospective directive name. There are two possible *name* must be the prospective directive name. There are two possible
@ -654,20 +650,18 @@ class Sphinx(object):
""" """
logger.debug('[app] adding directive: %r', logger.debug('[app] adding directive: %r',
(name, obj, content, arguments, options)) (name, obj, content, arguments, options))
if name in directives._directives and not override: if not override and docutils.is_directive_registered(name):
logger.warning(__('while setting up extension %s: directive %r is ' logger.warning(__('directive %r is already registered, it will be overridden'),
'already registered, it will be overridden'), name, type='app', subtype='add_directive')
self._setting_up_extension[-1], name,
type='app', subtype='add_directive')
if not isclass(obj) or not issubclass(obj, Directive): if not isclass(obj) or not issubclass(obj, Directive):
directive = directive_helper(obj, content, arguments, **options) directive = directive_helper(obj, content, arguments, **options)
directives.register_directive(name, directive) docutils.register_directive(name, directive)
else: else:
directives.register_directive(name, obj) docutils.register_directive(name, obj)
def add_role(self, name, role, override=False): def add_role(self, name, role, override=False):
# type: (unicode, Any, bool) -> None # type: (str, Any, bool) -> None
"""Register a Docutils role. """Register a Docutils role.
*name* must be the role name that occurs in the source, *role* the role *name* must be the role name that occurs in the source, *role* the role
@ -679,15 +673,13 @@ class Sphinx(object):
Add *override* keyword. Add *override* keyword.
""" """
logger.debug('[app] adding role: %r', (name, role)) logger.debug('[app] adding role: %r', (name, role))
if name in roles._roles and not override: if not override and docutils.is_role_registered(name):
logger.warning(__('while setting up extension %s: role %r is ' logger.warning(__('role %r is already registered, it will be overridden'),
'already registered, it will be overridden'), name, type='app', subtype='add_role')
self._setting_up_extension[-1], name, docutils.register_role(name, role)
type='app', subtype='add_role')
roles.register_local_role(name, role)
def add_generic_role(self, name, nodeclass, override=False): def add_generic_role(self, name, nodeclass, override=False):
# type: (unicode, Any, bool) -> None # type: (str, Any, bool) -> None
"""Register a generic Docutils role. """Register a generic Docutils role.
Register a Docutils role that does nothing but wrap its contents in the Register a Docutils role that does nothing but wrap its contents in the
@ -700,13 +692,11 @@ class Sphinx(object):
# Don't use ``roles.register_generic_role`` because it uses # Don't use ``roles.register_generic_role`` because it uses
# ``register_canonical_role``. # ``register_canonical_role``.
logger.debug('[app] adding generic role: %r', (name, nodeclass)) logger.debug('[app] adding generic role: %r', (name, nodeclass))
if name in roles._roles and not override: if not override and docutils.is_role_registered(name):
logger.warning(__('while setting up extension %s: role %r is ' logger.warning(__('role %r is already registered, it will be overridden'),
'already registered, it will be overridden'), name, type='app', subtype='add_generic_role')
self._setting_up_extension[-1], name,
type='app', subtype='add_generic_role')
role = roles.GenericRole(name, nodeclass) role = roles.GenericRole(name, nodeclass)
roles.register_local_role(name, role) docutils.register_role(name, role)
def add_domain(self, domain, override=False): def add_domain(self, domain, override=False):
# type: (Type[Domain], bool) -> None # type: (Type[Domain], bool) -> None
@ -735,12 +725,12 @@ class Sphinx(object):
""" """
warnings.warn('app.override_domain() is deprecated. ' warnings.warn('app.override_domain() is deprecated. '
'Use app.add_domain() with override option instead.', 'Use app.add_domain() with override option instead.',
RemovedInSphinx30Warning) RemovedInSphinx30Warning, stacklevel=2)
self.registry.add_domain(domain, override=True) self.registry.add_domain(domain, override=True)
def add_directive_to_domain(self, domain, name, obj, has_content=None, argument_spec=None, def add_directive_to_domain(self, domain, name, obj, has_content=None, argument_spec=None,
override=False, **option_spec): override=False, **option_spec):
# type: (unicode, unicode, Any, bool, Any, bool, Any) -> None # type: (str, str, Any, bool, Any, bool, Any) -> None
"""Register a Docutils directive in a domain. """Register a Docutils directive in a domain.
Like :meth:`add_directive`, but the directive is added to the domain Like :meth:`add_directive`, but the directive is added to the domain
@ -755,7 +745,7 @@ class Sphinx(object):
**option_spec) **option_spec)
def add_role_to_domain(self, domain, name, role, override=False): def add_role_to_domain(self, domain, name, role, override=False):
# type: (unicode, unicode, Union[RoleFunction, XRefRole], bool) -> None # type: (str, str, Union[RoleFunction, XRefRole], bool) -> None
"""Register a Docutils role in a domain. """Register a Docutils role in a domain.
Like :meth:`add_role`, but the role is added to the domain named Like :meth:`add_role`, but the role is added to the domain named
@ -768,7 +758,7 @@ class Sphinx(object):
self.registry.add_role_to_domain(domain, name, role, override=override) self.registry.add_role_to_domain(domain, name, role, override=override)
def add_index_to_domain(self, domain, index, override=False): def add_index_to_domain(self, domain, index, override=False):
# type: (unicode, Type[Index], bool) -> None # type: (str, Type[Index], bool) -> None
"""Register a custom index for a domain. """Register a custom index for a domain.
Add a custom *index* class to the domain named *domain*. *index* must Add a custom *index* class to the domain named *domain*. *index* must
@ -783,7 +773,7 @@ class Sphinx(object):
def add_object_type(self, directivename, rolename, indextemplate='', def add_object_type(self, directivename, rolename, indextemplate='',
parse_node=None, ref_nodeclass=None, objname='', parse_node=None, ref_nodeclass=None, objname='',
doc_field_types=[], override=False): doc_field_types=[], override=False):
# type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List, bool) -> None # type: (str, str, str, Callable, Type[nodes.TextElement], str, List, bool) -> None
"""Register a new object type. """Register a new object type.
This method is a very convenient way to add a new :term:`object` type This method is a very convenient way to add a new :term:`object` type
@ -849,7 +839,7 @@ class Sphinx(object):
def add_crossref_type(self, directivename, rolename, indextemplate='', def add_crossref_type(self, directivename, rolename, indextemplate='',
ref_nodeclass=None, objname='', override=False): ref_nodeclass=None, objname='', override=False):
# type: (unicode, unicode, unicode, nodes.Node, unicode, bool) -> None # type: (str, str, str, Type[nodes.TextElement], str, bool) -> None
"""Register a new crossref object type. """Register a new crossref object type.
This method is very similar to :meth:`add_object_type` except that the This method is very similar to :meth:`add_object_type` except that the
@ -928,15 +918,15 @@ class Sphinx(object):
self.registry.add_post_transform(transform) self.registry.add_post_transform(transform)
def add_javascript(self, filename, **kwargs): def add_javascript(self, filename, **kwargs):
# type: (unicode, **unicode) -> None # type: (str, **str) -> None
"""An alias of :meth:`add_js_file`.""" """An alias of :meth:`add_js_file`."""
warnings.warn('The app.add_javascript() is deprecated. ' warnings.warn('The app.add_javascript() is deprecated. '
'Please use app.add_js_file() instead.', 'Please use app.add_js_file() instead.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
self.add_js_file(filename, **kwargs) self.add_js_file(filename, **kwargs)
def add_js_file(self, filename, **kwargs): def add_js_file(self, filename, **kwargs):
# type: (unicode, **unicode) -> None # type: (str, **str) -> None
"""Register a JavaScript file to include in the HTML output. """Register a JavaScript file to include in the HTML output.
Add *filename* to the list of JavaScript files that the default HTML Add *filename* to the list of JavaScript files that the default HTML
@ -947,10 +937,10 @@ class Sphinx(object):
Example:: Example::
app.add_js_file('example.js') app.add_js_file('example.js')
# => <scrtipt src="_static/example.js"></script> # => <script src="_static/example.js"></script>
app.add_js_file('example.js', async="async") app.add_js_file('example.js', async="async")
# => <scrtipt src="_static/example.js" async="async"></script> # => <script src="_static/example.js" async="async"></script>
.. versionadded:: 0.5 .. versionadded:: 0.5
@ -963,7 +953,7 @@ class Sphinx(object):
self.builder.add_js_file(filename, **kwargs) # type: ignore self.builder.add_js_file(filename, **kwargs) # type: ignore
def add_css_file(self, filename, **kwargs): def add_css_file(self, filename, **kwargs):
# type: (unicode, **unicode) -> None # type: (str, **str) -> None
"""Register a stylesheet to include in the HTML output. """Register a stylesheet to include in the HTML output.
Add *filename* to the list of CSS files that the default HTML template Add *filename* to the list of CSS files that the default HTML template
@ -1003,13 +993,13 @@ class Sphinx(object):
self.builder.add_css_file(filename, **kwargs) # type: ignore self.builder.add_css_file(filename, **kwargs) # type: ignore
def add_stylesheet(self, filename, alternate=False, title=None): def add_stylesheet(self, filename, alternate=False, title=None):
# type: (unicode, bool, unicode) -> None # type: (str, bool, str) -> None
"""An alias of :meth:`add_css_file`.""" """An alias of :meth:`add_css_file`."""
warnings.warn('The app.add_stylesheet() is deprecated. ' warnings.warn('The app.add_stylesheet() is deprecated. '
'Please use app.add_css_file() instead.', 'Please use app.add_css_file() instead.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
attributes = {} # type: Dict[unicode, unicode] attributes = {} # type: Dict[str, str]
if alternate: if alternate:
attributes['rel'] = 'alternate stylesheet' attributes['rel'] = 'alternate stylesheet'
else: else:
@ -1021,7 +1011,7 @@ class Sphinx(object):
self.add_css_file(filename, **attributes) self.add_css_file(filename, **attributes)
def add_latex_package(self, packagename, options=None): def add_latex_package(self, packagename, options=None):
# type: (unicode, unicode) -> None # type: (str, str) -> None
r"""Register a package to include in the LaTeX source code. r"""Register a package to include in the LaTeX source code.
Add *packagename* to the list of packages that LaTeX source code will Add *packagename* to the list of packages that LaTeX source code will
@ -1040,7 +1030,7 @@ class Sphinx(object):
self.registry.add_latex_package(packagename, options) self.registry.add_latex_package(packagename, options)
def add_lexer(self, alias, lexer): def add_lexer(self, alias, lexer):
# type: (unicode, Any) -> None # type: (str, Any) -> None
"""Register a new lexer for source code. """Register a new lexer for source code.
Use *lexer*, which must be an instance of a Pygments lexer class, to Use *lexer*, which must be an instance of a Pygments lexer class, to
@ -1074,7 +1064,7 @@ class Sphinx(object):
self.add_directive('auto' + cls.objtype, AutodocDirective) self.add_directive('auto' + cls.objtype, AutodocDirective)
def add_autodoc_attrgetter(self, typ, getter): def add_autodoc_attrgetter(self, typ, getter):
# type: (Type, Callable[[Any, unicode, Any], Any]) -> None # type: (Type, Callable[[Any, str, Any], Any]) -> None
"""Register a new ``getattr``-like function for the autodoc extension. """Register a new ``getattr``-like function for the autodoc extension.
Add *getter*, which must be a function with an interface compatible to Add *getter*, which must be a function with an interface compatible to
@ -1106,7 +1096,7 @@ class Sphinx(object):
languages[cls.lang] = cls languages[cls.lang] = cls
def add_source_suffix(self, suffix, filetype, override=False): def add_source_suffix(self, suffix, filetype, override=False):
# type: (unicode, unicode, bool) -> None # type: (str, str, bool) -> None
"""Register a suffix of source files. """Register a suffix of source files.
Same as :confval:`source_suffix`. The users can override this Same as :confval:`source_suffix`. The users can override this
@ -1141,7 +1131,7 @@ class Sphinx(object):
collector().enable(self) collector().enable(self)
def add_html_theme(self, name, theme_path): def add_html_theme(self, name, theme_path):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Register a HTML Theme. """Register a HTML Theme.
The *name* is a name of theme, and *path* is a full path to the theme The *name* is a name of theme, and *path* is a full path to the theme
@ -1153,21 +1143,22 @@ class Sphinx(object):
self.html_themes[name] = theme_path self.html_themes[name] = theme_path
def add_html_math_renderer(self, name, inline_renderers=None, block_renderers=None): def add_html_math_renderer(self, name, inline_renderers=None, block_renderers=None):
# type: (unicode, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None # type: (str, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
"""Register a math renderer for HTML. """Register a math renderer for HTML.
The *name* is a name of the math renderer. Both *inline_renderers* and The *name* is a name of math renderer. Both *inline_renderers* and
*block_renderes* are used as visitor functions for HTML writer. *block_renderers* are used as visitor functions for the HTML writer:
*inline_renderers* is used for inline math node (``nodes.math`)). The the former for inline math node (``nodes.math``), the latter for
another is used for block math node (``nodes.math_block``). About block math node (``nodes.math_block``). Regarding visitor functions,
visitor functions, see :meth:`add_node` for more details. see :meth:`add_node` for details.
.. versionadded:: 1.8 .. versionadded:: 1.8
""" """
self.registry.add_html_math_renderer(name, inline_renderers, block_renderers) self.registry.add_html_math_renderer(name, inline_renderers, block_renderers)
def add_message_catalog(self, catalog, locale_dir): def add_message_catalog(self, catalog, locale_dir):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Register a message catalog. """Register a message catalog.
The *catalog* is a name of catalog, and *locale_dir* is a base path The *catalog* is a name of catalog, and *locale_dir* is a base path
@ -1181,7 +1172,7 @@ class Sphinx(object):
# ---- other methods ------------------------------------------------- # ---- other methods -------------------------------------------------
def is_parallel_allowed(self, typ): def is_parallel_allowed(self, typ):
# type: (unicode) -> bool # type: (str) -> bool
"""Check parallel processing is allowed or not. """Check parallel processing is allowed or not.
``typ`` is a type of processing; ``'read'`` or ``'write'``. ``typ`` is a type of processing; ``'read'`` or ``'write'``.
@ -1201,7 +1192,7 @@ class Sphinx(object):
else: else:
raise ValueError('parallel type %s is not supported' % typ) raise ValueError('parallel type %s is not supported' % typ)
for ext in itervalues(self.extensions): for ext in self.extensions.values():
allowed = getattr(ext, attrname, None) allowed = getattr(ext, attrname, None)
if allowed is None: if allowed is None:
logger.warning(message, ext.name) logger.warning(message, ext.name)
@ -1212,15 +1203,22 @@ class Sphinx(object):
return True return True
@property
def _setting_up_extension(self):
# type: () -> List[str]
warnings.warn('app._setting_up_extension is deprecated.',
RemovedInSphinx30Warning)
return ['?']
class TemplateBridge(object):
class TemplateBridge:
""" """
This class defines the interface for a "template bridge", that is, a class This class defines the interface for a "template bridge", that is, a class
that renders templates given a template name and a context. that renders templates given a template name and a context.
""" """
def init(self, builder, theme=None, dirs=None): def init(self, builder, theme=None, dirs=None):
# type: (Builder, Theme, List[unicode]) -> None # type: (Builder, Theme, List[str]) -> None
"""Called by the builder to initialize the template system. """Called by the builder to initialize the template system.
*builder* is the builder object; you'll probably want to look at the *builder* is the builder object; you'll probably want to look at the
@ -1240,14 +1238,14 @@ class TemplateBridge(object):
return 0 return 0
def render(self, template, context): def render(self, template, context):
# type: (unicode, Dict) -> None # type: (str, Dict) -> None
"""Called by the builder to render a template given as a filename with """Called by the builder to render a template given as a filename with
a specified context (a Python dictionary). a specified context (a Python dictionary).
""" """
raise NotImplementedError('must be implemented in subclasses') raise NotImplementedError('must be implemented in subclasses')
def render_string(self, template, context): def render_string(self, template, context):
# type: (unicode, Dict) -> unicode # type: (str, Dict) -> str
"""Called by the builder to render a template given as a string with a """Called by the builder to render a template given as a string with a
specified context (a Python dictionary). specified context (a Python dictionary).
""" """

View File

@ -1,19 +1,18 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders sphinx.builders
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
Builder superclass for all builders. Builder superclass for all builders.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import pickle
import time import time
from os import path from os import path
from docutils import nodes from docutils import nodes
from six.moves import cPickle as pickle
from sphinx.environment import CONFIG_OK, CONFIG_CHANGED_REASON from sphinx.environment import CONFIG_OK, CONFIG_CHANGED_REASON
from sphinx.environment.adapters.asset import ImageAdapter from sphinx.environment.adapters.asset import ImageAdapter
@ -41,7 +40,7 @@ except ImportError:
if False: if False:
# For type annotation # For type annotation
from typing import Any, Callable, Dict, Iterable, List, Sequence, Set, Tuple, Union # NOQA from typing import Any, Callable, Dict, Iterable, List, Sequence, Set, Tuple, Type, Union # NOQA
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA from sphinx.environment import BuildEnvironment # NOQA
@ -52,25 +51,25 @@ if False:
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Builder(object): class Builder:
""" """
Builds target formats from the reST sources. Builds target formats from the reST sources.
""" """
#: The builder's name, for the -b command line option. #: The builder's name, for the -b command line option.
name = '' # type: unicode name = ''
#: The builder's output format, or '' if no document output is produced. #: The builder's output format, or '' if no document output is produced.
format = '' # type: unicode format = ''
#: The message emitted upon successful build completion. This can be a #: The message emitted upon successful build completion. This can be a
#: printf-style template string with the following keys: ``outdir``, #: printf-style template string with the following keys: ``outdir``,
#: ``project`` #: ``project``
epilog = '' # type: unicode epilog = ''
#: default translator class for the builder. This can be overrided by #: default translator class for the builder. This can be overridden by
#: :py:meth:`app.set_translator()`. #: :py:meth:`app.set_translator()`.
default_translator_class = None # type: nodes.NodeVisitor default_translator_class = None # type: Type[nodes.NodeVisitor]
# doctree versioning method # doctree versioning method
versioning_method = 'none' # type: unicode versioning_method = 'none'
versioning_compare = False versioning_compare = False
# allow parallel write_doc() calls # allow parallel write_doc() calls
allow_parallel = False allow_parallel = False
@ -79,7 +78,7 @@ class Builder(object):
#: The list of MIME types of image formats supported by the builder. #: The list of MIME types of image formats supported by the builder.
#: Image files are searched in the order in which they appear here. #: Image files are searched in the order in which they appear here.
supported_image_types = [] # type: List[unicode] supported_image_types = [] # type: List[str]
#: The builder supports remote images or not. #: The builder supports remote images or not.
supported_remote_images = False supported_remote_images = False
#: The builder supports data URIs or not. #: The builder supports data URIs or not.
@ -103,11 +102,11 @@ class Builder(object):
self.tags.add("builder_%s" % self.name) self.tags.add("builder_%s" % self.name)
# images that need to be copied over (source -> dest) # images that need to be copied over (source -> dest)
self.images = {} # type: Dict[unicode, unicode] self.images = {} # type: Dict[str, str]
# basename of images directory # basename of images directory
self.imagedir = "" self.imagedir = ""
# relative path to image directory from current docname (used at writing docs) # relative path to image directory from current docname (used at writing docs)
self.imgpath = "" # type: unicode self.imgpath = ""
# these get set later # these get set later
self.parallel_ok = False self.parallel_ok = False
@ -121,7 +120,7 @@ class Builder(object):
self.versioning_compare) self.versioning_compare)
def get_translator_class(self, *args): def get_translator_class(self, *args):
# type: (Any) -> nodes.NodeVisitor # type: (Any) -> Type[nodes.NodeVisitor]
"""Return a class of translator.""" """Return a class of translator."""
return self.app.registry.get_translator_class(self) return self.app.registry.get_translator_class(self)
@ -153,7 +152,7 @@ class Builder(object):
self.templates = BuiltinTemplateLoader() self.templates = BuiltinTemplateLoader()
def get_target_uri(self, docname, typ=None): def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode # type: (str, str) -> str
"""Return the target URI for a document name. """Return the target URI for a document name.
*typ* can be used to qualify the link characteristic for individual *typ* can be used to qualify the link characteristic for individual
@ -162,7 +161,7 @@ class Builder(object):
raise NotImplementedError raise NotImplementedError
def get_relative_uri(self, from_, to, typ=None): def get_relative_uri(self, from_, to, typ=None):
# type: (unicode, unicode, unicode) -> unicode # type: (str, str, str) -> str
"""Return a relative URI between two source filenames. """Return a relative URI between two source filenames.
May raise environment.NoUri if there's no way to return a sensible URI. May raise environment.NoUri if there's no way to return a sensible URI.
@ -171,7 +170,7 @@ class Builder(object):
self.get_target_uri(to, typ)) self.get_target_uri(to, typ))
def get_outdated_docs(self): def get_outdated_docs(self):
# type: () -> Union[unicode, Iterable[unicode]] # type: () -> Union[str, Iterable[str]]
"""Return an iterable of output files that are outdated, or a string """Return an iterable of output files that are outdated, or a string
describing what an update build will build. describing what an update build will build.
@ -182,7 +181,7 @@ class Builder(object):
raise NotImplementedError raise NotImplementedError
def get_asset_paths(self): def get_asset_paths(self):
# type: () -> List[unicode] # type: () -> List[str]
"""Return list of paths for assets (ex. templates, CSS, etc.).""" """Return list of paths for assets (ex. templates, CSS, etc.)."""
return [] return []
@ -221,12 +220,12 @@ class Builder(object):
# compile po methods # compile po methods
def compile_catalogs(self, catalogs, message): def compile_catalogs(self, catalogs, message):
# type: (Set[CatalogInfo], unicode) -> None # type: (Set[CatalogInfo], str) -> None
if not self.config.gettext_auto_build: if not self.config.gettext_auto_build:
return return
def cat2relpath(cat): def cat2relpath(cat):
# type: (CatalogInfo) -> unicode # type: (CatalogInfo) -> str
return relpath(cat.mo_path, self.env.srcdir).replace(path.sep, SEP) return relpath(cat.mo_path, self.env.srcdir).replace(path.sep, SEP)
logger.info(bold(__('building [mo]: ')) + message) logger.info(bold(__('building [mo]: ')) + message)
@ -241,16 +240,15 @@ class Builder(object):
[path.join(self.srcdir, x) for x in self.config.locale_dirs], [path.join(self.srcdir, x) for x in self.config.locale_dirs],
self.config.language, self.config.language,
charset=self.config.source_encoding, charset=self.config.source_encoding,
gettext_compact=self.config.gettext_compact,
force_all=True, force_all=True,
excluded=Matcher(['**/.?**'])) excluded=Matcher(['**/.?**']))
message = __('all of %d po files') % len(catalogs) message = __('all of %d po files') % len(catalogs)
self.compile_catalogs(catalogs, message) self.compile_catalogs(catalogs, message)
def compile_specific_catalogs(self, specified_files): def compile_specific_catalogs(self, specified_files):
# type: (List[unicode]) -> None # type: (List[str]) -> None
def to_domain(fpath): def to_domain(fpath):
# type: (unicode) -> unicode # type: (str) -> str
docname = self.env.path2doc(path.abspath(fpath)) docname = self.env.path2doc(path.abspath(fpath))
if docname: if docname:
return find_catalog(docname, self.config.gettext_compact) return find_catalog(docname, self.config.gettext_compact)
@ -264,7 +262,6 @@ class Builder(object):
self.config.language, self.config.language,
domains=list(specified_domains), domains=list(specified_domains),
charset=self.config.source_encoding, charset=self.config.source_encoding,
gettext_compact=self.config.gettext_compact,
excluded=Matcher(['**/.?**'])) excluded=Matcher(['**/.?**']))
message = __('targets for %d po files that are specified') % len(catalogs) message = __('targets for %d po files that are specified') % len(catalogs)
self.compile_catalogs(catalogs, message) self.compile_catalogs(catalogs, message)
@ -275,7 +272,6 @@ class Builder(object):
[path.join(self.srcdir, x) for x in self.config.locale_dirs], [path.join(self.srcdir, x) for x in self.config.locale_dirs],
self.config.language, self.config.language,
charset=self.config.source_encoding, charset=self.config.source_encoding,
gettext_compact=self.config.gettext_compact,
excluded=Matcher(['**/.?**'])) excluded=Matcher(['**/.?**']))
message = __('targets for %d po files that are out of date') % len(catalogs) message = __('targets for %d po files that are out of date') % len(catalogs)
self.compile_catalogs(catalogs, message) self.compile_catalogs(catalogs, message)
@ -288,13 +284,13 @@ class Builder(object):
self.build(None, summary=__('all source files'), method='all') self.build(None, summary=__('all source files'), method='all')
def build_specific(self, filenames): def build_specific(self, filenames):
# type: (List[unicode]) -> None # type: (List[str]) -> None
"""Only rebuild as much as needed for changes in the *filenames*.""" """Only rebuild as much as needed for changes in the *filenames*."""
# bring the filenames to the canonical format, that is, # bring the filenames to the canonical format, that is,
# relative to the source directory and without source_suffix. # relative to the source directory and without source_suffix.
dirlen = len(self.srcdir) + 1 dirlen = len(self.srcdir) + 1
to_write = [] to_write = []
suffixes = None # type: Tuple[unicode] suffixes = None # type: Tuple[str]
suffixes = tuple(self.config.source_suffix) # type: ignore suffixes = tuple(self.config.source_suffix) # type: ignore
for filename in filenames: for filename in filenames:
filename = path.normpath(path.abspath(filename)) filename = path.normpath(path.abspath(filename))
@ -330,7 +326,7 @@ class Builder(object):
len(to_build)) len(to_build))
def build(self, docnames, summary=None, method='update'): def build(self, docnames, summary=None, method='update'):
# type: (Iterable[unicode], unicode, unicode) -> None # type: (Iterable[str], str, str) -> None
"""Main build method. """Main build method.
First updates the environment, and then calls :meth:`write`. First updates the environment, and then calls :meth:`write`.
@ -343,7 +339,7 @@ class Builder(object):
updated_docnames = set(self.read()) updated_docnames = set(self.read())
doccount = len(updated_docnames) doccount = len(updated_docnames)
logger.info(bold(__('looking for now-outdated files... ')), nonl=1) logger.info(bold(__('looking for now-outdated files... ')), nonl=True)
for docname in self.env.check_dependents(self.app, updated_docnames): for docname in self.env.check_dependents(self.app, updated_docnames):
updated_docnames.add(docname) updated_docnames.add(docname)
outdated = len(updated_docnames) - doccount outdated = len(updated_docnames) - doccount
@ -352,6 +348,7 @@ class Builder(object):
else: else:
logger.info(__('none found')) logger.info(__('none found'))
if updated_docnames:
# save the environment # save the environment
from sphinx.application import ENV_PICKLE_FILENAME from sphinx.application import ENV_PICKLE_FILENAME
logger.info(bold(__('pickling environment... ')), nonl=True) logger.info(bold(__('pickling environment... ')), nonl=True)
@ -359,7 +356,6 @@ class Builder(object):
pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL) pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL)
logger.info(__('done')) logger.info(__('done'))
if updated_docnames:
# global actions # global actions
self.app.phase = BuildPhase.CONSISTENCY_CHECK self.app.phase = BuildPhase.CONSISTENCY_CHECK
logger.info(bold(__('checking consistency... ')), nonl=True) logger.info(bold(__('checking consistency... ')), nonl=True)
@ -401,13 +397,13 @@ class Builder(object):
self.finish_tasks.join() self.finish_tasks.join()
def read(self): def read(self):
# type: () -> List[unicode] # type: () -> List[str]
"""(Re-)read all files new or changed since last update. """(Re-)read all files new or changed since last update.
Store all environment docnames in the canonical format (ie using SEP as Store all environment docnames in the canonical format (ie using SEP as
a separator in place of os.path.sep). a separator in place of os.path.sep).
""" """
logger.info(bold('updating environment: '), nonl=True) logger.info(bold(__('updating environment: ')), nonl=True)
self.env.find_files(self.config, self) self.env.find_files(self.config, self)
updated = (self.env.config_status != CONFIG_OK) updated = (self.env.config_status != CONFIG_OK)
@ -426,7 +422,7 @@ class Builder(object):
if changed: if changed:
reason = CONFIG_CHANGED_REASON.get(self.env.config_status, '') reason = CONFIG_CHANGED_REASON.get(self.env.config_status, '')
logger.info('[%s] ', reason, nonl=True) logger.info('[%s] ', reason, nonl=True)
logger.info('%s added, %s changed, %s removed', logger.info(__('%s added, %s changed, %s removed'),
len(added), len(changed), len(removed)) len(added), len(changed), len(removed))
# clear all files no longer present # clear all files no longer present
@ -464,8 +460,8 @@ class Builder(object):
return sorted(docnames) return sorted(docnames)
def _read_serial(self, docnames): def _read_serial(self, docnames):
# type: (List[unicode]) -> None # type: (List[str]) -> None
for docname in status_iterator(docnames, 'reading sources... ', "purple", for docname in status_iterator(docnames, __('reading sources... '), "purple",
len(docnames), self.app.verbosity): len(docnames), self.app.verbosity):
# remove all inventory entries for that file # remove all inventory entries for that file
self.app.emit('env-purge-doc', self.env, docname) self.app.emit('env-purge-doc', self.env, docname)
@ -473,14 +469,14 @@ class Builder(object):
self.read_doc(docname) self.read_doc(docname)
def _read_parallel(self, docnames, nproc): def _read_parallel(self, docnames, nproc):
# type: (List[unicode], int) -> None # type: (List[str], int) -> None
# clear all outdated docs at once # clear all outdated docs at once
for docname in docnames: for docname in docnames:
self.app.emit('env-purge-doc', self.env, docname) self.app.emit('env-purge-doc', self.env, docname)
self.env.clear_doc(docname) self.env.clear_doc(docname)
def read_process(docs): def read_process(docs):
# type: (List[unicode]) -> bytes # type: (List[str]) -> bytes
self.env.app = self.app self.env.app = self.app
for docname in docs: for docname in docs:
self.read_doc(docname) self.read_doc(docname)
@ -488,23 +484,23 @@ class Builder(object):
return pickle.dumps(self.env, pickle.HIGHEST_PROTOCOL) return pickle.dumps(self.env, pickle.HIGHEST_PROTOCOL)
def merge(docs, otherenv): def merge(docs, otherenv):
# type: (List[unicode], bytes) -> None # type: (List[str], bytes) -> None
env = pickle.loads(otherenv) env = pickle.loads(otherenv)
self.env.merge_info_from(docs, env, self.app) self.env.merge_info_from(docs, env, self.app)
tasks = ParallelTasks(nproc) tasks = ParallelTasks(nproc)
chunks = make_chunks(docnames, nproc) chunks = make_chunks(docnames, nproc)
for chunk in status_iterator(chunks, 'reading sources... ', "purple", for chunk in status_iterator(chunks, __('reading sources... '), "purple",
len(chunks), self.app.verbosity): len(chunks), self.app.verbosity):
tasks.add_task(read_process, chunk, merge) tasks.add_task(read_process, chunk, merge)
# make sure all threads have finished # make sure all threads have finished
logger.info(bold('waiting for workers...')) logger.info(bold(__('waiting for workers...')))
tasks.join() tasks.join()
def read_doc(self, docname): def read_doc(self, docname):
# type: (unicode) -> None # type: (str) -> None
"""Parse a file and add/update inventory entries for the doctree.""" """Parse a file and add/update inventory entries for the doctree."""
self.env.prepare_settings(docname) self.env.prepare_settings(docname)
@ -530,7 +526,7 @@ class Builder(object):
self.write_doctree(docname, doctree) self.write_doctree(docname, doctree)
def write_doctree(self, docname, doctree): def write_doctree(self, docname, doctree):
# type: (unicode, nodes.Node) -> None # type: (str, nodes.document) -> None
"""Write the doctree to a file.""" """Write the doctree to a file."""
# make it picklable # make it picklable
doctree.reporter = None doctree.reporter = None
@ -539,13 +535,13 @@ class Builder(object):
doctree.settings.env = None doctree.settings.env = None
doctree.settings.record_dependencies = None doctree.settings.record_dependencies = None
doctree_filename = self.env.doc2path(docname, self.env.doctreedir, '.doctree') doctree_filename = path.join(self.doctreedir, docname + '.doctree')
ensuredir(path.dirname(doctree_filename)) ensuredir(path.dirname(doctree_filename))
with open(doctree_filename, 'wb') as f: with open(doctree_filename, 'wb') as f:
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL) pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
def write(self, build_docnames, updated_docnames, method='update'): def write(self, build_docnames, updated_docnames, method='update'):
# type: (Iterable[unicode], Sequence[unicode], unicode) -> None # type: (Iterable[str], Sequence[str], str) -> None
if build_docnames is None or build_docnames == ['__all__']: if build_docnames is None or build_docnames == ['__all__']:
# build_all # build_all
build_docnames = self.env.found_docs build_docnames = self.env.found_docs
@ -576,7 +572,7 @@ class Builder(object):
self._write_serial(sorted(docnames)) self._write_serial(sorted(docnames))
def _write_serial(self, docnames): def _write_serial(self, docnames):
# type: (Sequence[unicode]) -> None # type: (Sequence[str]) -> None
with logging.pending_warnings(): with logging.pending_warnings():
for docname in status_iterator(docnames, __('writing output... '), "darkgreen", for docname in status_iterator(docnames, __('writing output... '), "darkgreen",
len(docnames), self.app.verbosity): len(docnames), self.app.verbosity):
@ -587,9 +583,9 @@ class Builder(object):
self.write_doc(docname, doctree) self.write_doc(docname, doctree)
def _write_parallel(self, docnames, nproc): def _write_parallel(self, docnames, nproc):
# type: (Sequence[unicode], int) -> None # type: (Sequence[str], int) -> None
def write_process(docs): def write_process(docs):
# type: (List[Tuple[unicode, nodes.Node]]) -> None # type: (List[Tuple[str, nodes.document]]) -> None
self.app.phase = BuildPhase.WRITING self.app.phase = BuildPhase.WRITING
for docname, doctree in docs: for docname, doctree in docs:
self.write_doc(docname, doctree) self.write_doc(docname, doctree)
@ -620,17 +616,17 @@ class Builder(object):
tasks.join() tasks.join()
def prepare_writing(self, docnames): def prepare_writing(self, docnames):
# type: (Set[unicode]) -> None # type: (Set[str]) -> None
"""A place where you can add logic before :meth:`write_doc` is run""" """A place where you can add logic before :meth:`write_doc` is run"""
raise NotImplementedError raise NotImplementedError
def write_doc(self, docname, doctree): def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None # type: (str, nodes.document) -> None
"""Where you actually write something to the filesystem.""" """Where you actually write something to the filesystem."""
raise NotImplementedError raise NotImplementedError
def write_doc_serialized(self, docname, doctree): def write_doc_serialized(self, docname, doctree):
# type: (unicode, nodes.Node) -> None # type: (str, nodes.document) -> None
"""Handle parts of write_doc that must be called in the main process """Handle parts of write_doc that must be called in the main process
if parallel build is active. if parallel build is active.
""" """
@ -653,7 +649,7 @@ class Builder(object):
pass pass
def get_builder_config(self, option, default): def get_builder_config(self, option, default):
# type: (unicode, unicode) -> Any # type: (str, str) -> Any
"""Return a builder specific option. """Return a builder specific option.
This method allows customization of common builder settings by This method allows customization of common builder settings by

View File

@ -1,16 +1,16 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders._epub_base sphinx.builders._epub_base
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
Base class of epub2/epub3 builders. Base class of epub2/epub3 builders.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import os import os
import re import re
import warnings
from collections import namedtuple from collections import namedtuple
from os import path from os import path
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
@ -20,6 +20,7 @@ from docutils.utils import smartquotes
from sphinx import addnodes from sphinx import addnodes
from sphinx.builders.html import BuildInfo, StandaloneHTMLBuilder from sphinx.builders.html import BuildInfo, StandaloneHTMLBuilder
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.locale import __ from sphinx.locale import __
from sphinx.util import logging from sphinx.util import logging
from sphinx.util import status_iterator from sphinx.util import status_iterator
@ -30,14 +31,11 @@ from sphinx.util.osutil import ensuredir, copyfile
try: try:
from PIL import Image from PIL import Image
except ImportError: except ImportError:
try:
import Image
except ImportError:
Image = None Image = None
if False: if False:
# For type annotation # For type annotation
from typing import Any, Dict, List, Tuple # NOQA from typing import Any, Dict, List, Set, Tuple # NOQA
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
@ -50,22 +48,22 @@ logger = logging.getLogger(__name__)
# output but that may be customized by (re-)setting module attributes, # output but that may be customized by (re-)setting module attributes,
# e.g. from conf.py. # e.g. from conf.py.
COVERPAGE_NAME = u'epub-cover.xhtml' COVERPAGE_NAME = 'epub-cover.xhtml'
TOCTREE_TEMPLATE = u'toctree-l%d' TOCTREE_TEMPLATE = 'toctree-l%d'
LINK_TARGET_TEMPLATE = u' [%(uri)s]' LINK_TARGET_TEMPLATE = ' [%(uri)s]'
FOOTNOTE_LABEL_TEMPLATE = u'#%d' FOOTNOTE_LABEL_TEMPLATE = '#%d'
FOOTNOTES_RUBRIC_NAME = u'Footnotes' FOOTNOTES_RUBRIC_NAME = 'Footnotes'
CSS_LINK_TARGET_CLASS = u'link-target' CSS_LINK_TARGET_CLASS = 'link-target'
# XXX These strings should be localized according to epub_language # XXX These strings should be localized according to epub_language
GUIDE_TITLES = { GUIDE_TITLES = {
'toc': u'Table of Contents', 'toc': 'Table of Contents',
'cover': u'Cover' 'cover': 'Cover'
} }
MEDIA_TYPES = { MEDIA_TYPES = {
@ -79,7 +77,7 @@ MEDIA_TYPES = {
'.otf': 'application/x-font-otf', '.otf': 'application/x-font-otf',
'.ttf': 'application/x-font-ttf', '.ttf': 'application/x-font-ttf',
'.woff': 'application/font-woff', '.woff': 'application/font-woff',
} # type: Dict[unicode, unicode] }
VECTOR_GRAPHICS_EXTENSIONS = ('.svg',) VECTOR_GRAPHICS_EXTENSIONS = ('.svg',)
@ -96,7 +94,7 @@ NavPoint = namedtuple('NavPoint', ['navpoint', 'playorder', 'text', 'refuri', 'c
def sphinx_smarty_pants(t, language='en'): def sphinx_smarty_pants(t, language='en'):
# type: (unicode, str) -> unicode # type: (str, str) -> str
t = t.replace('&quot;', '"') t = t.replace('&quot;', '"')
t = smartquotes.educateDashesOldSchool(t) t = smartquotes.educateDashesOldSchool(t)
t = smartquotes.educateQuotes(t, language) t = smartquotes.educateQuotes(t, language)
@ -151,26 +149,27 @@ class EpubBuilder(StandaloneHTMLBuilder):
def init(self): def init(self):
# type: () -> None # type: () -> None
StandaloneHTMLBuilder.init(self) super().init()
# the output files for epub must be .html only # the output files for epub must be .html only
self.out_suffix = '.xhtml' self.out_suffix = '.xhtml'
self.link_suffix = '.xhtml' self.link_suffix = '.xhtml'
self.playorder = 0 self.playorder = 0
self.tocid = 0 self.tocid = 0
self.id_cache = {} # type: Dict[unicode, unicode] self.id_cache = {} # type: Dict[str, str]
self.use_index = self.get_builder_config('use_index', 'epub') self.use_index = self.get_builder_config('use_index', 'epub')
self.refnodes = [] # type: List[Dict[str, Any]]
def create_build_info(self): def create_build_info(self):
# type: () -> BuildInfo # type: () -> BuildInfo
return BuildInfo(self.config, self.tags, ['html', 'epub']) return BuildInfo(self.config, self.tags, ['html', 'epub'])
def get_theme_config(self): def get_theme_config(self):
# type: () -> Tuple[unicode, Dict] # type: () -> Tuple[str, Dict]
return self.config.epub_theme, self.config.epub_theme_options return self.config.epub_theme, self.config.epub_theme_options
# generic support functions # generic support functions
def make_id(self, name): def make_id(self, name):
# type: (unicode) -> unicode # type: (str) -> str
# id_cache is intentionally mutable # id_cache is intentionally mutable
"""Return a unique id for name.""" """Return a unique id for name."""
id = self.id_cache.get(name) id = self.id_cache.get(name)
@ -180,7 +179,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return id return id
def esc(self, name): def esc(self, name):
# type: (unicode) -> unicode # type: (str) -> str
"""Replace all characters not allowed in text an attribute values.""" """Replace all characters not allowed in text an attribute values."""
# Like cgi.escape, but also replace apostrophe # Like cgi.escape, but also replace apostrophe
name = name.replace('&', '&amp;') name = name.replace('&', '&amp;')
@ -191,7 +190,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return name return name
def get_refnodes(self, doctree, result): def get_refnodes(self, doctree, result):
# type: (nodes.Node, List[Dict[unicode, Any]]) -> List[Dict[unicode, Any]] # type: (nodes.Node, List[Dict[str, Any]]) -> List[Dict[str, Any]]
"""Collect section titles, their depth in the toc and the refuri.""" """Collect section titles, their depth in the toc and the refuri."""
# XXX: is there a better way than checking the attribute # XXX: is there a better way than checking the attribute
# toctree-l[1-8] on the parent node? # toctree-l[1-8] on the parent node?
@ -209,11 +208,20 @@ class EpubBuilder(StandaloneHTMLBuilder):
'text': ssp(self.esc(doctree.astext())) 'text': ssp(self.esc(doctree.astext()))
}) })
break break
else: elif isinstance(doctree, nodes.Element):
for elem in doctree.children: for elem in doctree:
result = self.get_refnodes(elem, result) result = self.get_refnodes(elem, result)
return result return result
def check_refnodes(self, nodes):
# type: (List[Dict[str, Any]]) -> None
appeared = set() # type: Set[str]
for node in nodes:
if node['refuri'] in appeared:
logger.warning(__('duplicated ToC entry found: %s'), node['refuri'])
else:
appeared.add(node['refuri'])
def get_toc(self): def get_toc(self):
# type: () -> None # type: () -> None
"""Get the total table of contents, containing the master_doc """Get the total table of contents, containing the master_doc
@ -231,7 +239,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.toc_add_files(self.refnodes) self.toc_add_files(self.refnodes)
def toc_add_files(self, refnodes): def toc_add_files(self, refnodes):
# type: (List[nodes.Node]) -> None # type: (List[Dict[str, Any]]) -> None
"""Add the master_doc, pre and post files to a list of refnodes. """Add the master_doc, pre and post files to a list of refnodes.
""" """
refnodes.insert(0, { refnodes.insert(0, {
@ -254,47 +262,49 @@ class EpubBuilder(StandaloneHTMLBuilder):
}) })
def fix_fragment(self, prefix, fragment): def fix_fragment(self, prefix, fragment):
# type: (unicode, unicode) -> unicode # type: (str, str) -> str
"""Return a href/id attribute with colons replaced by hyphens.""" """Return a href/id attribute with colons replaced by hyphens."""
return prefix + fragment.replace(':', '-') return prefix + fragment.replace(':', '-')
def fix_ids(self, tree): def fix_ids(self, tree):
# type: (nodes.Node) -> None # type: (nodes.document) -> None
"""Replace colons with hyphens in href and id attributes. """Replace colons with hyphens in href and id attributes.
Some readers crash because they interpret the part as a Some readers crash because they interpret the part as a
transport protocol specification. transport protocol specification.
""" """
for node in tree.traverse(nodes.reference): for reference in tree.traverse(nodes.reference):
if 'refuri' in node: if 'refuri' in reference:
m = self.refuri_re.match(node['refuri']) m = self.refuri_re.match(reference['refuri'])
if m: if m:
node['refuri'] = self.fix_fragment(m.group(1), m.group(2)) reference['refuri'] = self.fix_fragment(m.group(1), m.group(2))
if 'refid' in node: if 'refid' in reference:
node['refid'] = self.fix_fragment('', node['refid']) reference['refid'] = self.fix_fragment('', reference['refid'])
for node in tree.traverse(nodes.target):
for i, node_id in enumerate(node['ids']):
if ':' in node_id:
node['ids'][i] = self.fix_fragment('', node_id)
next_node = node.next_node(siblings=True) for target in tree.traverse(nodes.target):
if next_node and isinstance(next_node, nodes.Element): for i, node_id in enumerate(target['ids']):
if ':' in node_id:
target['ids'][i] = self.fix_fragment('', node_id)
next_node = target.next_node(siblings=True) # type: nodes.Node
if isinstance(next_node, nodes.Element):
for i, node_id in enumerate(next_node['ids']): for i, node_id in enumerate(next_node['ids']):
if ':' in node_id: if ':' in node_id:
next_node['ids'][i] = self.fix_fragment('', node_id) next_node['ids'][i] = self.fix_fragment('', node_id)
for node in tree.traverse(addnodes.desc_signature):
ids = node.attributes['ids'] for desc_signature in tree.traverse(addnodes.desc_signature):
ids = desc_signature.attributes['ids']
newids = [] newids = []
for id in ids: for id in ids:
newids.append(self.fix_fragment('', id)) newids.append(self.fix_fragment('', id))
node.attributes['ids'] = newids desc_signature.attributes['ids'] = newids
def add_visible_links(self, tree, show_urls='inline'): def add_visible_links(self, tree, show_urls='inline'):
# type: (nodes.Node, unicode) -> None # type: (nodes.document, str) -> None
"""Add visible link targets for external links""" """Add visible link targets for external links"""
def make_footnote_ref(doc, label): def make_footnote_ref(doc, label):
# type: (nodes.Node, unicode) -> nodes.footnote_reference # type: (nodes.document, str) -> nodes.footnote_reference
"""Create a footnote_reference node with children""" """Create a footnote_reference node with children"""
footnote_ref = nodes.footnote_reference('[#]_') footnote_ref = nodes.footnote_reference('[#]_')
footnote_ref.append(nodes.Text(label)) footnote_ref.append(nodes.Text(label))
@ -302,7 +312,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return footnote_ref return footnote_ref
def make_footnote(doc, label, uri): def make_footnote(doc, label, uri):
# type: (nodes.Node, unicode, unicode) -> nodes.footnote # type: (nodes.document, str, str) -> nodes.footnote
"""Create a footnote node with children""" """Create a footnote node with children"""
footnote = nodes.footnote(uri) footnote = nodes.footnote(uri)
para = nodes.paragraph() para = nodes.paragraph()
@ -313,7 +323,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return footnote return footnote
def footnote_spot(tree): def footnote_spot(tree):
# type: (nodes.Node) -> Tuple[nodes.Node, int] # type: (nodes.document) -> Tuple[nodes.Element, int]
"""Find or create a spot to place footnotes. """Find or create a spot to place footnotes.
The function returns the tuple (parent, index).""" The function returns the tuple (parent, index)."""
@ -326,8 +336,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
fn = fns[-1] fn = fns[-1]
return fn.parent, fn.parent.index(fn) + 1 return fn.parent, fn.parent.index(fn) + 1
for node in tree.traverse(nodes.rubric): for node in tree.traverse(nodes.rubric):
if len(node.children) == 1 and \ if len(node) == 1 and node.astext() == FOOTNOTES_RUBRIC_NAME:
node.children[0].astext() == FOOTNOTES_RUBRIC_NAME:
return node.parent, node.parent.index(node) + 1 return node.parent, node.parent.index(node) + 1
doc = tree.traverse(nodes.document)[0] doc = tree.traverse(nodes.document)[0]
rub = nodes.rubric() rub = nodes.rubric()
@ -363,7 +372,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
fn_idx += 1 fn_idx += 1
def write_doc(self, docname, doctree): def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None # type: (str, nodes.document) -> None
"""Write one document file. """Write one document file.
This method is overwritten in order to fix fragment identifiers This method is overwritten in order to fix fragment identifiers
@ -371,10 +380,10 @@ class EpubBuilder(StandaloneHTMLBuilder):
""" """
self.fix_ids(doctree) self.fix_ids(doctree)
self.add_visible_links(doctree, self.config.epub_show_urls) self.add_visible_links(doctree, self.config.epub_show_urls)
StandaloneHTMLBuilder.write_doc(self, docname, doctree) super().write_doc(docname, doctree)
def fix_genindex(self, tree): def fix_genindex(self, tree):
# type: (nodes.Node) -> None # type: (List[Tuple[str, List[Tuple[str, Any]]]]) -> None
"""Fix href attributes for genindex pages.""" """Fix href attributes for genindex pages."""
# XXX: modifies tree inline # XXX: modifies tree inline
# Logic modeled from themes/basic/genindex.html # Logic modeled from themes/basic/genindex.html
@ -393,37 +402,38 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.fix_fragment(m.group(1), m.group(2))) self.fix_fragment(m.group(1), m.group(2)))
def is_vector_graphics(self, filename): def is_vector_graphics(self, filename):
# type: (unicode) -> bool # type: (str) -> bool
"""Does the filename extension indicate a vector graphic format?""" """Does the filename extension indicate a vector graphic format?"""
ext = path.splitext(filename)[-1] ext = path.splitext(filename)[-1]
return ext in VECTOR_GRAPHICS_EXTENSIONS return ext in VECTOR_GRAPHICS_EXTENSIONS
def copy_image_files_pil(self): def copy_image_files_pil(self):
# type: () -> None # type: () -> None
"""Copy images using the PIL. """Copy images using Pillow, the Python Imaging Libary.
The method tries to read and write the files with the PIL, The method tries to read and write the files with Pillow, converting
converting the format and resizing the image if necessary/possible. the format and resizing the image if necessary/possible.
""" """
ensuredir(path.join(self.outdir, self.imagedir)) ensuredir(path.join(self.outdir, self.imagedir))
for src in status_iterator(self.images, 'copying images... ', "brown", for src in status_iterator(self.images, __('copying images... '), "brown",
len(self.images), self.app.verbosity): len(self.images), self.app.verbosity):
dest = self.images[src] dest = self.images[src]
try: try:
img = Image.open(path.join(self.srcdir, src)) img = Image.open(path.join(self.srcdir, src))
except IOError: except OSError:
if not self.is_vector_graphics(src): if not self.is_vector_graphics(src):
logger.warning(__('cannot read image file %r: copying it instead'), logger.warning(__('cannot read image file %r: copying it instead'),
path.join(self.srcdir, src)) path.join(self.srcdir, src))
try: try:
copyfile(path.join(self.srcdir, src), copyfile(path.join(self.srcdir, src),
path.join(self.outdir, self.imagedir, dest)) path.join(self.outdir, self.imagedir, dest))
except (IOError, OSError) as err: except OSError as err:
logger.warning(__('cannot copy image file %r: %s'), logger.warning(__('cannot copy image file %r: %s'),
path.join(self.srcdir, src), err) path.join(self.srcdir, src), err)
continue continue
if self.config.epub_fix_images: if self.config.epub_fix_images:
if img.mode in ('P',): if img.mode in ('P',):
# See PIL documentation for Image.convert() # See the Pillow documentation for Image.convert()
# https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.convert
img = img.convert() img = img.convert()
if self.config.epub_max_image_width > 0: if self.config.epub_max_image_width > 0:
(width, height) = img.size (width, height) = img.size
@ -433,24 +443,24 @@ class EpubBuilder(StandaloneHTMLBuilder):
img = img.resize((nw, nh), Image.BICUBIC) img = img.resize((nw, nh), Image.BICUBIC)
try: try:
img.save(path.join(self.outdir, self.imagedir, dest)) img.save(path.join(self.outdir, self.imagedir, dest))
except (IOError, OSError) as err: except OSError as err:
logger.warning(__('cannot write image file %r: %s'), logger.warning(__('cannot write image file %r: %s'),
path.join(self.srcdir, src), err) path.join(self.srcdir, src), err)
def copy_image_files(self): def copy_image_files(self):
# type: () -> None # type: () -> None
"""Copy image files to destination directory. """Copy image files to destination directory.
This overwritten method can use the PIL to convert image files. This overwritten method can use Pillow to convert image files.
""" """
if self.images: if self.images:
if self.config.epub_fix_images or self.config.epub_max_image_width: if self.config.epub_fix_images or self.config.epub_max_image_width:
if not Image: if not Image:
logger.warning(__('PIL not found - copying image files')) logger.warning(__('Pillow not found - copying image files'))
super(EpubBuilder, self).copy_image_files() super().copy_image_files()
else: else:
self.copy_image_files_pil() self.copy_image_files_pil()
else: else:
super(EpubBuilder, self).copy_image_files() super().copy_image_files()
def copy_download_files(self): def copy_download_files(self):
# type: () -> None # type: () -> None
@ -458,7 +468,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
def handle_page(self, pagename, addctx, templatename='page.html', def handle_page(self, pagename, addctx, templatename='page.html',
outfilename=None, event_arg=None): outfilename=None, event_arg=None):
# type: (unicode, Dict, unicode, unicode, Any) -> None # type: (str, Dict, str, str, Any) -> None
"""Create a rendered page. """Create a rendered page.
This method is overwritten for genindex pages in order to fix href link This method is overwritten for genindex pages in order to fix href link
@ -469,30 +479,41 @@ class EpubBuilder(StandaloneHTMLBuilder):
return return
self.fix_genindex(addctx['genindexentries']) self.fix_genindex(addctx['genindexentries'])
addctx['doctype'] = self.doctype addctx['doctype'] = self.doctype
StandaloneHTMLBuilder.handle_page(self, pagename, addctx, templatename, super().handle_page(pagename, addctx, templatename, outfilename, event_arg)
outfilename, event_arg)
def build_mimetype(self, outdir, outname): def build_mimetype(self, outdir=None, outname='mimetype'):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Write the metainfo file mimetype.""" """Write the metainfo file mimetype."""
if outdir:
warnings.warn('The arguments of EpubBuilder.build_mimetype() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
else:
outdir = self.outdir
logger.info(__('writing %s file...'), outname) logger.info(__('writing %s file...'), outname)
copy_asset_file(path.join(self.template_dir, 'mimetype'), copy_asset_file(path.join(self.template_dir, 'mimetype'),
path.join(outdir, outname)) path.join(outdir, outname))
def build_container(self, outdir, outname): def build_container(self, outdir=None, outname='META-INF/container.xml'):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Write the metainfo file META-INF/container.xml.""" """Write the metainfo file META-INF/container.xml."""
if outdir:
warnings.warn('The arguments of EpubBuilder.build_container() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
else:
outdir = self.outdir
logger.info(__('writing %s file...'), outname) logger.info(__('writing %s file...'), outname)
filename = path.join(outdir, outname) filename = path.join(outdir, outname)
ensuredir(path.dirname(filename)) ensuredir(path.dirname(filename))
copy_asset_file(path.join(self.template_dir, 'container.xml'), filename) copy_asset_file(path.join(self.template_dir, 'container.xml'), filename)
def content_metadata(self): def content_metadata(self):
# type: () -> Dict[unicode, Any] # type: () -> Dict[str, Any]
"""Create a dictionary with all metadata for the content.opf """Create a dictionary with all metadata for the content.opf
file properly escaped. file properly escaped.
""" """
metadata = {} # type: Dict[unicode, Any] metadata = {} # type: Dict[str, Any]
metadata['title'] = self.esc(self.config.epub_title) metadata['title'] = self.esc(self.config.epub_title)
metadata['author'] = self.esc(self.config.epub_author) metadata['author'] = self.esc(self.config.epub_author)
metadata['uid'] = self.esc(self.config.epub_uid) metadata['uid'] = self.esc(self.config.epub_uid)
@ -507,11 +528,17 @@ class EpubBuilder(StandaloneHTMLBuilder):
metadata['guides'] = [] metadata['guides'] = []
return metadata return metadata
def build_content(self, outdir, outname): def build_content(self, outdir=None, outname='content.opf'):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Write the metainfo file content.opf It contains bibliographic data, """Write the metainfo file content.opf It contains bibliographic data,
a file list and the spine (the reading order). a file list and the spine (the reading order).
""" """
if outdir:
warnings.warn('The arguments of EpubBuilder.build_content() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
else:
outdir = self.outdir
logger.info(__('writing %s file...'), outname) logger.info(__('writing %s file...'), outname)
metadata = self.content_metadata() metadata = self.content_metadata()
@ -519,7 +546,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
if not outdir.endswith(os.sep): if not outdir.endswith(os.sep):
outdir += os.sep outdir += os.sep
olen = len(outdir) olen = len(outdir)
self.files = [] # type: List[unicode] self.files = [] # type: List[str]
self.ignored_files = ['.buildinfo', 'mimetype', 'content.opf', self.ignored_files = ['.buildinfo', 'mimetype', 'content.opf',
'toc.ncx', 'META-INF/container.xml', 'toc.ncx', 'META-INF/container.xml',
'Thumbs.db', 'ehthumbs.db', '.DS_Store', 'Thumbs.db', 'ehthumbs.db', '.DS_Store',
@ -622,7 +649,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
metadata) metadata)
def new_navpoint(self, node, level, incr=True): def new_navpoint(self, node, level, incr=True):
# type: (nodes.Node, int, bool) -> NavPoint # type: (Dict[str, Any], int, bool) -> NavPoint
"""Create a new entry in the toc from the node at given level.""" """Create a new entry in the toc from the node at given level."""
# XXX Modifies the node # XXX Modifies the node
if incr: if incr:
@ -632,7 +659,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
node['text'], node['refuri'], []) node['text'], node['refuri'], [])
def build_navpoints(self, nodes): def build_navpoints(self, nodes):
# type: (nodes.Node) -> List[NavPoint] # type: (List[Dict[str, Any]]) -> List[NavPoint]
"""Create the toc navigation structure. """Create the toc navigation structure.
Subelements of a node are nested inside the navpoint. For nested nodes Subelements of a node are nested inside the navpoint. For nested nodes
@ -677,20 +704,26 @@ class EpubBuilder(StandaloneHTMLBuilder):
return navstack[0].children return navstack[0].children
def toc_metadata(self, level, navpoints): def toc_metadata(self, level, navpoints):
# type: (int, List[NavPoint]) -> Dict[unicode, Any] # type: (int, List[NavPoint]) -> Dict[str, Any]
"""Create a dictionary with all metadata for the toc.ncx file """Create a dictionary with all metadata for the toc.ncx file
properly escaped. properly escaped.
""" """
metadata = {} # type: Dict[unicode, Any] metadata = {} # type: Dict[str, Any]
metadata['uid'] = self.config.epub_uid metadata['uid'] = self.config.epub_uid
metadata['title'] = self.esc(self.config.epub_title) metadata['title'] = self.esc(self.config.epub_title)
metadata['level'] = level metadata['level'] = level
metadata['navpoints'] = navpoints metadata['navpoints'] = navpoints
return metadata return metadata
def build_toc(self, outdir, outname): def build_toc(self, outdir=None, outname='toc.ncx'):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Write the metainfo file toc.ncx.""" """Write the metainfo file toc.ncx."""
if outdir:
warnings.warn('The arguments of EpubBuilder.build_toc() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
else:
outdir = self.outdir
logger.info(__('writing %s file...'), outname) logger.info(__('writing %s file...'), outname)
if self.config.epub_tocscope == 'default': if self.config.epub_tocscope == 'default':
@ -702,6 +735,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
else: else:
# 'includehidden' # 'includehidden'
refnodes = self.refnodes refnodes = self.refnodes
self.check_refnodes(refnodes)
navpoints = self.build_navpoints(refnodes) navpoints = self.build_navpoints(refnodes)
level = max(item['level'] for item in self.refnodes) level = max(item['level'] for item in self.refnodes)
level = min(level, self.config.epub_tocdepth) level = min(level, self.config.epub_tocdepth)
@ -709,18 +743,25 @@ class EpubBuilder(StandaloneHTMLBuilder):
path.join(outdir, outname), path.join(outdir, outname),
self.toc_metadata(level, navpoints)) self.toc_metadata(level, navpoints))
def build_epub(self, outdir, outname): def build_epub(self, outdir=None, outname=None):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Write the epub file. """Write the epub file.
It is a zip file with the mimetype file stored uncompressed as the first It is a zip file with the mimetype file stored uncompressed as the first
entry. entry.
""" """
if outdir:
warnings.warn('The arguments of EpubBuilder.build_epub() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
else:
outdir = self.outdir
outname = self.config.epub_basename + '.epub'
logger.info(__('writing %s file...'), outname) logger.info(__('writing %s file...'), outname)
epub_filename = path.join(outdir, outname) epub_filename = path.join(outdir, outname)
with ZipFile(epub_filename, 'w', ZIP_DEFLATED) as epub: with ZipFile(epub_filename, 'w', ZIP_DEFLATED) as epub:
epub.write(path.join(outdir, 'mimetype'), 'mimetype', ZIP_STORED) epub.write(path.join(outdir, 'mimetype'), 'mimetype', ZIP_STORED)
for filename in [u'META-INF/container.xml', u'content.opf', u'toc.ncx']: for filename in ['META-INF/container.xml', 'content.opf', 'toc.ncx']:
epub.write(path.join(outdir, filename), filename, ZIP_DEFLATED) epub.write(path.join(outdir, filename), filename, ZIP_DEFLATED)
for filename in self.files: for filename in self.files:
epub.write(path.join(outdir, filename), filename, ZIP_DEFLATED) epub.write(path.join(outdir, filename), filename, ZIP_DEFLATED)

View File

@ -1,32 +1,22 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.applehelp sphinx.builders.applehelp
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
Build Apple help books. Build Apple help books.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
from __future__ import print_function
import codecs import warnings
import pipes
import plistlib
import shlex
import subprocess
from os import path, environ
from sphinx.builders.html import StandaloneHTMLBuilder from sphinxcontrib.applehelp import (
from sphinx.config import string_classes AppleHelpCodeSigningFailed,
from sphinx.errors import SphinxError AppleHelpIndexerFailed,
from sphinx.locale import __ AppleHelpBuilder,
from sphinx.util import logging )
from sphinx.util.console import bold # type: ignore
from sphinx.util.fileutil import copy_asset from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.util.matching import Matcher
from sphinx.util.osutil import copyfile, ensuredir, make_filename
from sphinx.util.pycompat import htmlescape
if False: if False:
# For type annotation # For type annotation
@ -34,279 +24,20 @@ if False:
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__) deprecated_alias('sphinx.builders.applehelp',
{
# Use plistlib.dump in 3.4 and above 'AppleHelpCodeSigningFailed': AppleHelpCodeSigningFailed,
try: 'AppleHelpIndexerFailed': AppleHelpIndexerFailed,
write_plist = plistlib.dump # type: ignore 'AppleHelpBuilder': AppleHelpBuilder,
except AttributeError: },
write_plist = plistlib.writePlist RemovedInSphinx40Warning)
# False access page (used because helpd expects strict XHTML)
access_page_template = '''\
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>%(title)s</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="robots" content="noindex" />
<meta http-equiv="refresh" content="0;url=%(toc)s" />
</head>
<body>
</body>
</html>
'''
class AppleHelpIndexerFailed(SphinxError):
category = __('Help indexer failed')
class AppleHelpCodeSigningFailed(SphinxError):
category = __('Code signing failed')
class AppleHelpBuilder(StandaloneHTMLBuilder):
"""
Builder that outputs an Apple help book. Requires Mac OS X as it relies
on the ``hiutil`` command line tool.
"""
name = 'applehelp'
epilog = __('The help book is in %(outdir)s.\n'
'Note that won\'t be able to view it unless you put it in '
'~/Library/Documentation/Help or install it in your application '
'bundle.')
# don't copy the reST source
copysource = False
supported_image_types = ['image/png', 'image/gif', 'image/jpeg',
'image/tiff', 'image/jp2', 'image/svg+xml']
# don't add links
add_permalinks = False
# this is an embedded HTML format
embedded = True
# don't generate the search index or include the search page
search = False
def init(self):
# type: () -> None
super(AppleHelpBuilder, self).init()
# the output files for HTML help must be .html only
self.out_suffix = '.html'
self.link_suffix = '.html'
if self.config.applehelp_bundle_id is None:
raise SphinxError(__('You must set applehelp_bundle_id before '
'building Apple Help output'))
self.bundle_path = path.join(self.outdir,
self.config.applehelp_bundle_name +
'.help')
self.outdir = path.join(self.bundle_path,
'Contents',
'Resources',
self.config.applehelp_locale + '.lproj')
def handle_finish(self):
# type: () -> None
super(AppleHelpBuilder, self).handle_finish()
self.finish_tasks.add_task(self.copy_localized_files)
self.finish_tasks.add_task(self.build_helpbook)
def copy_localized_files(self):
# type: () -> None
source_dir = path.join(self.confdir, self.config.applehelp_locale + '.lproj')
target_dir = self.outdir
if path.isdir(source_dir):
logger.info(bold(__('copying localized files... ')), nonl=True)
excluded = Matcher(self.config.exclude_patterns + ['**/.*'])
copy_asset(source_dir, target_dir, excluded,
context=self.globalcontext, renderer=self.templates)
logger.info(__('done'))
def build_helpbook(self):
# type: () -> None
contents_dir = path.join(self.bundle_path, 'Contents')
resources_dir = path.join(contents_dir, 'Resources')
language_dir = path.join(resources_dir,
self.config.applehelp_locale + '.lproj')
for d in [contents_dir, resources_dir, language_dir]:
ensuredir(d)
# Construct the Info.plist file
toc = self.config.master_doc + self.out_suffix
info_plist = {
'CFBundleDevelopmentRegion': self.config.applehelp_dev_region,
'CFBundleIdentifier': self.config.applehelp_bundle_id,
'CFBundleInfoDictionaryVersion': '6.0',
'CFBundlePackageType': 'BNDL',
'CFBundleShortVersionString': self.config.release,
'CFBundleSignature': 'hbwr',
'CFBundleVersion': self.config.applehelp_bundle_version,
'HPDBookAccessPath': '_access.html',
'HPDBookIndexPath': 'search.helpindex',
'HPDBookTitle': self.config.applehelp_title,
'HPDBookType': '3',
'HPDBookUsesExternalViewer': False,
}
if self.config.applehelp_icon is not None:
info_plist['HPDBookIconPath'] \
= path.basename(self.config.applehelp_icon)
if self.config.applehelp_kb_url is not None:
info_plist['HPDBookKBProduct'] = self.config.applehelp_kb_product
info_plist['HPDBookKBURL'] = self.config.applehelp_kb_url
if self.config.applehelp_remote_url is not None:
info_plist['HPDBookRemoteURL'] = self.config.applehelp_remote_url
logger.info(bold(__('writing Info.plist... ')), nonl=True)
with open(path.join(contents_dir, 'Info.plist'), 'wb') as f:
write_plist(info_plist, f)
logger.info(__('done'))
# Copy the icon, if one is supplied
if self.config.applehelp_icon:
logger.info(bold(__('copying icon... ')), nonl=True)
try:
copyfile(path.join(self.srcdir, self.config.applehelp_icon),
path.join(resources_dir, info_plist['HPDBookIconPath']))
logger.info(__('done'))
except Exception as err:
logger.warning(__('cannot copy icon file %r: %s'),
path.join(self.srcdir, self.config.applehelp_icon), err)
del info_plist['HPDBookIconPath']
# Build the access page
logger.info(bold(__('building access page...')), nonl=True)
with codecs.open(path.join(language_dir, '_access.html'), 'w') as f: # type: ignore
f.write(access_page_template % {
'toc': htmlescape(toc, quote=True),
'title': htmlescape(self.config.applehelp_title)
})
logger.info(__('done'))
# Generate the help index
logger.info(bold(__('generating help index... ')), nonl=True)
args = [
self.config.applehelp_indexer_path,
'-Cf',
path.join(language_dir, 'search.helpindex'),
language_dir
]
if self.config.applehelp_index_anchors is not None:
args.append('-a')
if self.config.applehelp_min_term_length is not None:
args += ['-m', '%s' % self.config.applehelp_min_term_length]
if self.config.applehelp_stopwords is not None:
args += ['-s', self.config.applehelp_stopwords]
if self.config.applehelp_locale is not None:
args += ['-l', self.config.applehelp_locale]
if self.config.applehelp_disable_external_tools:
logger.info(__('skipping'))
logger.warning(__('you will need to index this help book with:\n %s'),
' '.join([pipes.quote(arg) for arg in args]))
else:
try:
p = subprocess.Popen(args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
output = p.communicate()[0]
if p.returncode != 0:
raise AppleHelpIndexerFailed(output)
else:
logger.info(__('done'))
except OSError:
raise AppleHelpIndexerFailed(__('Command not found: %s') % args[0])
# If we've been asked to, sign the bundle
if self.config.applehelp_codesign_identity:
logger.info(bold(__('signing help book... ')), nonl=True)
args = [
self.config.applehelp_codesign_path,
'-s', self.config.applehelp_codesign_identity,
'-f'
]
args += self.config.applehelp_codesign_flags
args.append(self.bundle_path)
if self.config.applehelp_disable_external_tools:
logger.info(__('skipping'))
logger.warning(__('you will need to sign this help book with:\n %s'),
' '.join([pipes.quote(arg) for arg in args]))
else:
try:
p = subprocess.Popen(args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
output = p.communicate()[0]
if p.returncode != 0:
raise AppleHelpCodeSigningFailed(output)
else:
logger.info(__('done'))
except OSError:
raise AppleHelpCodeSigningFailed(__('Command not found: %s') % args[0])
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[str, Any]
app.setup_extension('sphinx.builders.html') warnings.warn('sphinx.builders.applehelp has been moved to sphinxcontrib-applehelp.',
app.add_builder(AppleHelpBuilder) RemovedInSphinx40Warning)
app.setup_extension('sphinxcontrib.applehelp')
app.add_config_value('applehelp_bundle_name',
lambda self: make_filename(self.project), 'applehelp')
app.add_config_value('applehelp_bundle_id', None, 'applehelp', string_classes)
app.add_config_value('applehelp_dev_region', 'en-us', 'applehelp')
app.add_config_value('applehelp_bundle_version', '1', 'applehelp')
app.add_config_value('applehelp_icon', None, 'applehelp', string_classes)
app.add_config_value('applehelp_kb_product',
lambda self: '%s-%s' % (make_filename(self.project), self.release),
'applehelp')
app.add_config_value('applehelp_kb_url', None, 'applehelp', string_classes)
app.add_config_value('applehelp_remote_url', None, 'applehelp', string_classes)
app.add_config_value('applehelp_index_anchors', False, 'applehelp', string_classes)
app.add_config_value('applehelp_min_term_length', None, 'applehelp', string_classes)
app.add_config_value('applehelp_stopwords',
lambda self: self.language or 'en', 'applehelp')
app.add_config_value('applehelp_locale', lambda self: self.language or 'en', 'applehelp')
app.add_config_value('applehelp_title', lambda self: self.project + ' Help', 'applehelp')
app.add_config_value('applehelp_codesign_identity',
lambda self: environ.get('CODE_SIGN_IDENTITY', None),
'applehelp')
app.add_config_value('applehelp_codesign_flags',
lambda self: shlex.split(environ.get('OTHER_CODE_SIGN_FLAGS', '')),
'applehelp')
app.add_config_value('applehelp_indexer_path', '/usr/bin/hiutil', 'applehelp')
app.add_config_value('applehelp_codesign_path', '/usr/bin/codesign', 'applehelp')
app.add_config_value('applehelp_disable_external_tools', False, None)
return { return {
'version': 'builtin', 'version': 'builtin',

View File

@ -1,20 +1,17 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.changes sphinx.builders.changes
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
Changelog builder. Changelog builder.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import codecs import html
from os import path from os import path
from typing import cast from typing import cast
from six import iteritems
from sphinx import package_dir from sphinx import package_dir
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.domains.changeset import ChangeSetDomain from sphinx.domains.changeset import ChangeSetDomain
@ -24,7 +21,6 @@ from sphinx.util import logging
from sphinx.util.console import bold # type: ignore from sphinx.util.console import bold # type: ignore
from sphinx.util.fileutil import copy_asset_file from sphinx.util.fileutil import copy_asset_file
from sphinx.util.osutil import ensuredir, os_path from sphinx.util.osutil import ensuredir, os_path
from sphinx.util.pycompat import htmlescape
if False: if False:
# For type annotation # For type annotation
@ -50,27 +46,29 @@ class ChangesBuilder(Builder):
self.templates.init(self, self.theme) self.templates.init(self, self.theme)
def get_outdated_docs(self): def get_outdated_docs(self):
# type: () -> unicode # type: () -> str
return self.outdir return self.outdir
typemap = { typemap = {
'versionadded': 'added', 'versionadded': 'added',
'versionchanged': 'changed', 'versionchanged': 'changed',
'deprecated': 'deprecated', 'deprecated': 'deprecated',
} # type: Dict[unicode, unicode] }
def write(self, *ignored): def write(self, *ignored):
# type: (Any) -> None # type: (Any) -> None
version = self.config.version version = self.config.version
domain = cast(ChangeSetDomain, self.env.get_domain('changeset')) domain = cast(ChangeSetDomain, self.env.get_domain('changeset'))
libchanges = {} # type: Dict[unicode, List[Tuple[unicode, unicode, int]]] libchanges = {} # type: Dict[str, List[Tuple[str, str, int]]]
apichanges = [] # type: List[Tuple[unicode, unicode, int]] apichanges = [] # type: List[Tuple[str, str, int]]
otherchanges = {} # type: Dict[Tuple[unicode, unicode], List[Tuple[unicode, unicode, int]]] # NOQA otherchanges = {} # type: Dict[Tuple[str, str], List[Tuple[str, str, int]]]
if version not in self.env.versionchanges:
changesets = domain.get_changesets_for(version)
if not changesets:
logger.info(bold(__('no changes in version %s.') % version)) logger.info(bold(__('no changes in version %s.') % version))
return return
logger.info(bold('writing summary file...')) logger.info(bold(__('writing summary file...')))
for changeset in domain.get_changesets_for(version): for changeset in changesets:
if isinstance(changeset.descname, tuple): if isinstance(changeset.descname, tuple):
descname = changeset.descname[0] descname = changeset.descname[0]
else: else:
@ -109,15 +107,15 @@ class ChangesBuilder(Builder):
'version': version, 'version': version,
'docstitle': self.config.html_title, 'docstitle': self.config.html_title,
'shorttitle': self.config.html_short_title, 'shorttitle': self.config.html_short_title,
'libchanges': sorted(iteritems(libchanges)), 'libchanges': sorted(libchanges.items()),
'apichanges': sorted(apichanges), 'apichanges': sorted(apichanges),
'otherchanges': sorted(iteritems(otherchanges)), 'otherchanges': sorted(otherchanges.items()),
'show_copyright': self.config.html_show_copyright, 'show_copyright': self.config.html_show_copyright,
'show_sphinx': self.config.html_show_sphinx, 'show_sphinx': self.config.html_show_sphinx,
} }
with codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8') as f: # type: ignore # NOQA with open(path.join(self.outdir, 'index.html'), 'w', encoding='utf8') as f:
f.write(self.templates.render('changes/frameset.html', ctx)) f.write(self.templates.render('changes/frameset.html', ctx))
with codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8') as f: # type: ignore # NOQA with open(path.join(self.outdir, 'changes.html'), 'w', encoding='utf8') as f:
f.write(self.templates.render('changes/versionchanges.html', ctx)) f.write(self.templates.render('changes/versionchanges.html', ctx))
hltext = ['.. versionadded:: %s' % version, hltext = ['.. versionadded:: %s' % version,
@ -125,8 +123,8 @@ class ChangesBuilder(Builder):
'.. deprecated:: %s' % version] '.. deprecated:: %s' % version]
def hl(no, line): def hl(no, line):
# type: (int, unicode) -> unicode # type: (int, str) -> str
line = '<a name="L%s"> </a>' % no + htmlescape(line) line = '<a name="L%s"> </a>' % no + html.escape(line)
for x in hltext: for x in hltext:
if x in line: if x in line:
line = '<span class="hl">%s</span>' % line line = '<span class="hl">%s</span>' % line
@ -135,8 +133,8 @@ class ChangesBuilder(Builder):
logger.info(bold(__('copying source files...'))) logger.info(bold(__('copying source files...')))
for docname in self.env.all_docs: for docname in self.env.all_docs:
with codecs.open(self.env.doc2path(docname), 'r', # type: ignore with open(self.env.doc2path(docname),
self.env.config.source_encoding) as f: encoding=self.env.config.source_encoding) as f:
try: try:
lines = f.readlines() lines = f.readlines()
except UnicodeDecodeError: except UnicodeDecodeError:
@ -144,7 +142,7 @@ class ChangesBuilder(Builder):
continue continue
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html' targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
ensuredir(path.dirname(targetfn)) ensuredir(path.dirname(targetfn))
with codecs.open(targetfn, 'w', 'utf-8') as f: # type: ignore with open(targetfn, 'w', encoding='utf-8') as f:
text = ''.join(hl(i + 1, line) for (i, line) in enumerate(lines)) text = ''.join(hl(i + 1, line) for (i, line) in enumerate(lines))
ctx = { ctx = {
'filename': self.env.doc2path(docname, None), 'filename': self.env.doc2path(docname, None),
@ -152,15 +150,15 @@ class ChangesBuilder(Builder):
} }
f.write(self.templates.render('changes/rstsource.html', ctx)) f.write(self.templates.render('changes/rstsource.html', ctx))
themectx = dict(('theme_' + key, val) for (key, val) in themectx = dict(('theme_' + key, val) for (key, val) in
iteritems(self.theme.get_options({}))) self.theme.get_options({}).items())
copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'), copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'),
self.outdir, context=themectx, renderer=self.templates) self.outdir, context=themectx, renderer=self.templates)
copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'), copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
self.outdir) self.outdir)
def hl(self, text, version): def hl(self, text, version):
# type: (unicode, unicode) -> unicode # type: (str, str) -> str
text = htmlescape(text) text = html.escape(text)
for directive in ['versionchanged', 'versionadded', 'deprecated']: for directive in ['versionchanged', 'versionadded', 'deprecated']:
text = text.replace('.. %s:: %s' % (directive, version), text = text.replace('.. %s:: %s' % (directive, version),
'<b>.. %s:: %s</b>' % (directive, version)) '<b>.. %s:: %s</b>' % (directive, version))
@ -172,7 +170,7 @@ class ChangesBuilder(Builder):
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[str, Any]
app.add_builder(ChangesBuilder) app.add_builder(ChangesBuilder)
return { return {

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.devhelp sphinx.builders.devhelp
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@ -7,144 +6,35 @@
.. _Devhelp: https://wiki.gnome.org/Apps/Devhelp .. _Devhelp: https://wiki.gnome.org/Apps/Devhelp
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
from __future__ import absolute_import
import gzip import warnings
import re
from os import path
from typing import Any
from docutils import nodes from sphinxcontrib.devhelp import DevhelpBuilder
from sphinx import addnodes from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.nodes import NodeMatcher
from sphinx.util.osutil import make_filename
try:
import xml.etree.ElementTree as etree
except ImportError:
import lxml.etree as etree # type: ignore
if False: if False:
# For type annotation # For type annotation
from typing import Dict, List # NOQA from typing import Any, Dict # NOQA
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__) deprecated_alias('sphinx.builders.devhelp',
{
'DevhelpBuilder': DevhelpBuilder,
class DevhelpBuilder(StandaloneHTMLBuilder): },
""" RemovedInSphinx40Warning)
Builder that also outputs GNOME Devhelp file.
"""
name = 'devhelp'
epilog = __('To view the help file:\n'
'$ mkdir -p $HOME/.local/share/devhelp/books\n'
'$ ln -s $PWD/%(outdir)s $HOME/.local/share/devhelp/books/%(project)s\n'
'$ devhelp')
# don't copy the reST source
copysource = False
supported_image_types = ['image/png', 'image/gif', 'image/jpeg']
# don't add links
add_permalinks = False
# don't add sidebar etc.
embedded = True
def init(self):
# type: () -> None
StandaloneHTMLBuilder.init(self)
self.out_suffix = '.html'
self.link_suffix = '.html'
def handle_finish(self):
# type: () -> None
self.build_devhelp(self.outdir, self.config.devhelp_basename)
def build_devhelp(self, outdir, outname):
# type: (unicode, unicode) -> None
logger.info(__('dumping devhelp index...'))
# Basic info
root = etree.Element('book',
title=self.config.html_title,
name=self.config.project,
link="index.html",
version=self.config.version)
tree = etree.ElementTree(root)
# TOC
chapters = etree.SubElement(root, 'chapters')
tocdoc = self.env.get_and_resolve_doctree(
self.config.master_doc, self, prune_toctrees=False)
def write_toc(node, parent):
# type: (nodes.Node, nodes.Node) -> None
if isinstance(node, addnodes.compact_paragraph) or \
isinstance(node, nodes.bullet_list):
for subnode in node:
write_toc(subnode, parent)
elif isinstance(node, nodes.list_item):
item = etree.SubElement(parent, 'sub')
for subnode in node:
write_toc(subnode, item)
elif isinstance(node, nodes.reference):
parent.attrib['link'] = node['refuri']
parent.attrib['name'] = node.astext()
matcher = NodeMatcher(addnodes.compact_paragraph, toctree=Any)
for node in tocdoc.traverse(matcher):
write_toc(node, chapters)
# Index
functions = etree.SubElement(root, 'functions')
index = IndexEntries(self.env).create_index(self)
def write_index(title, refs, subitems):
# type: (unicode, List[Any], Any) -> None
if len(refs) == 0:
pass
elif len(refs) == 1:
etree.SubElement(functions, 'function',
name=title, link=refs[0][1])
else:
for i, ref in enumerate(refs):
etree.SubElement(functions, 'function',
name="[%d] %s" % (i, title),
link=ref[1])
if subitems:
parent_title = re.sub(r'\s*\(.*\)\s*$', '', title)
for subitem in subitems:
write_index("%s %s" % (parent_title, subitem[0]),
subitem[1], [])
for (key, group) in index:
for title, (refs, subitems, key) in group:
write_index(title, refs, subitems)
# Dump the XML file
xmlfile = path.join(outdir, outname + '.devhelp.gz')
with gzip.open(xmlfile, 'w') as f: # type: ignore
tree.write(f, 'utf-8')
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[str, Any]
app.setup_extension('sphinx.builders.html') warnings.warn('sphinx.builders.devhelp has been moved to sphinxcontrib-devhelp.',
app.add_builder(DevhelpBuilder) RemovedInSphinx40Warning)
app.setup_extension('sphinxcontrib.devhelp')
app.add_config_value('devhelp_basename', lambda self: make_filename(self.project), None)
return { return {
'version': 'builtin', 'version': 'builtin',

View File

@ -0,0 +1,68 @@
"""
sphinx.builders.dirhtml
~~~~~~~~~~~~~~~~~~~~~~~
Directory HTML builders.
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from os import path
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util import logging
from sphinx.util.osutil import SEP, os_path
if False:
# For type annotation
from typing import Any, Dict, Set # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
"""
A StandaloneHTMLBuilder that creates all HTML pages as "index.html" in
a directory given by their pagename, so that generated URLs don't have
``.html`` in them.
"""
name = 'dirhtml'
def get_target_uri(self, docname, typ=None):
# type: (str, str) -> str
if docname == 'index':
return ''
if docname.endswith(SEP + 'index'):
return docname[:-5] # up to sep
return docname + SEP
def get_outfilename(self, pagename):
# type: (str) -> str
if pagename == 'index' or pagename.endswith(SEP + 'index'):
outfilename = path.join(self.outdir, os_path(pagename) +
self.out_suffix)
else:
outfilename = path.join(self.outdir, os_path(pagename),
'index' + self.out_suffix)
return outfilename
def prepare_writing(self, docnames):
# type: (Set[str]) -> None
super().prepare_writing(docnames)
self.globalcontext['no_search_suffix'] = True
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
app.setup_extension('sphinx.builders.html')
app.add_builder(DirectoryHTMLBuilder)
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.dummy sphinx.builders.dummy
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
@ -31,19 +30,19 @@ class DummyBuilder(Builder):
pass pass
def get_outdated_docs(self): def get_outdated_docs(self):
# type: () -> Set[unicode] # type: () -> Set[str]
return self.env.found_docs return self.env.found_docs
def get_target_uri(self, docname, typ=None): def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode # type: (str, str) -> str
return '' return ''
def prepare_writing(self, docnames): def prepare_writing(self, docnames):
# type: (Set[unicode]) -> None # type: (Set[str]) -> None
pass pass
def write_doc(self, docname, doctree): def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None # type: (str, nodes.Node) -> None
pass pass
def finish(self): def finish(self):
@ -52,7 +51,7 @@ class DummyBuilder(Builder):
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[str, Any]
app.add_builder(DummyBuilder) app.add_builder(DummyBuilder)
return { return {

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.epub3 sphinx.builders.epub3
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
@ -10,14 +9,14 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import warnings
from collections import namedtuple from collections import namedtuple
from os import path from os import path
from six import string_types
from sphinx import package_dir from sphinx import package_dir
from sphinx.builders import _epub_base from sphinx.builders import _epub_base
from sphinx.config import string_classes, ENUM from sphinx.config import ENUM
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.locale import __ from sphinx.locale import __
from sphinx.util import logging, xmlname_checker from sphinx.util import logging, xmlname_checker
from sphinx.util.fileutil import copy_asset_file from sphinx.util.fileutil import copy_asset_file
@ -26,7 +25,7 @@ from sphinx.util.osutil import make_filename
if False: if False:
# For type annotation # For type annotation
from typing import Any, Dict, Iterable, List, Tuple # NOQA from typing import Any, Dict, Iterable, List, Set, Tuple # NOQA
from docutils import nodes # NOQA from docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA from sphinx.config import Config # NOQA
@ -53,8 +52,8 @@ THEME_WRITING_MODES = {
DOCTYPE = '''<!DOCTYPE html>''' DOCTYPE = '''<!DOCTYPE html>'''
HTML_TAG = ( HTML_TAG = (
u'<html xmlns="http://www.w3.org/1999/xhtml" ' '<html xmlns="http://www.w3.org/1999/xhtml" '
u'xmlns:epub="http://www.idpf.org/2007/ops">' 'xmlns:epub="http://www.idpf.org/2007/ops">'
) )
@ -79,50 +78,18 @@ class Epub3Builder(_epub_base.EpubBuilder):
def handle_finish(self): def handle_finish(self):
# type: () -> None # type: () -> None
"""Create the metainfo files and finally the epub.""" """Create the metainfo files and finally the epub."""
self.validate_config_value()
self.get_toc() self.get_toc()
self.build_mimetype(self.outdir, 'mimetype') self.build_mimetype()
self.build_container(self.outdir, 'META-INF/container.xml') self.build_container()
self.build_content(self.outdir, 'content.opf') self.build_content()
self.build_navigation_doc(self.outdir, 'nav.xhtml') self.build_navigation_doc()
self.build_toc(self.outdir, 'toc.ncx') self.build_toc()
self.build_epub(self.outdir, self.config.epub_basename + '.epub') self.build_epub()
def validate_config_value(self): def validate_config_value(self):
# type: () -> None # type: () -> None
# <package> lang attribute, dc:language warnings.warn('Epub3Builder.validate_config_value() is deprecated.',
if not self.app.config.epub_language: RemovedInSphinx40Warning, stacklevel=2)
logger.warning(__('conf value "epub_language" (or "language") '
'should not be empty for EPUB3'))
# <package> unique-identifier attribute
if not xmlname_checker().match(self.app.config.epub_uid):
logger.warning(__('conf value "epub_uid" should be XML NAME for EPUB3'))
# dc:title
if not self.app.config.epub_title:
logger.warning(__('conf value "epub_title" (or "html_title") '
'should not be empty for EPUB3'))
# dc:creator
if not self.app.config.epub_author:
logger.warning(__('conf value "epub_author" should not be empty for EPUB3'))
# dc:contributor
if not self.app.config.epub_contributor:
logger.warning(__('conf value "epub_contributor" should not be empty for EPUB3'))
# dc:description
if not self.app.config.epub_description:
logger.warning(__('conf value "epub_description" should not be empty for EPUB3'))
# dc:publisher
if not self.app.config.epub_publisher:
logger.warning(__('conf value "epub_publisher" should not be empty for EPUB3'))
# dc:rights
if not self.app.config.epub_copyright:
logger.warning(__('conf value "epub_copyright" (or "copyright")'
'should not be empty for EPUB3'))
# dc:identifier
if not self.app.config.epub_identifier:
logger.warning(__('conf value "epub_identifier" should not be empty for EPUB3'))
# meta ibooks:version
if not self.app.config.version:
logger.warning(__('conf value "version" should not be empty for EPUB3'))
def content_metadata(self): def content_metadata(self):
# type: () -> Dict # type: () -> Dict
@ -131,7 +98,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
""" """
writing_mode = self.config.epub_writing_mode writing_mode = self.config.epub_writing_mode
metadata = super(Epub3Builder, self).content_metadata() metadata = super().content_metadata()
metadata['description'] = self.esc(self.config.epub_description) metadata['description'] = self.esc(self.config.epub_description)
metadata['contributor'] = self.esc(self.config.epub_contributor) metadata['contributor'] = self.esc(self.config.epub_contributor)
metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(writing_mode) metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(writing_mode)
@ -142,8 +109,8 @@ class Epub3Builder(_epub_base.EpubBuilder):
return metadata return metadata
def prepare_writing(self, docnames): def prepare_writing(self, docnames):
# type: (Iterable[unicode]) -> None # type: (Set[str]) -> None
super(Epub3Builder, self).prepare_writing(docnames) super().prepare_writing(docnames)
writing_mode = self.config.epub_writing_mode writing_mode = self.config.epub_writing_mode
self.globalcontext['theme_writing_mode'] = THEME_WRITING_MODES.get(writing_mode) self.globalcontext['theme_writing_mode'] = THEME_WRITING_MODES.get(writing_mode)
@ -152,7 +119,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
self.globalcontext['skip_ua_compatible'] = True self.globalcontext['skip_ua_compatible'] = True
def build_navlist(self, navnodes): def build_navlist(self, navnodes):
# type: (List[nodes.Node]) -> List[NavPoint] # type: (List[Dict[str, Any]]) -> List[NavPoint]
"""Create the toc navigation structure. """Create the toc navigation structure.
This method is almost same as build_navpoints method in epub.py. This method is almost same as build_navpoints method in epub.py.
@ -205,9 +172,15 @@ class Epub3Builder(_epub_base.EpubBuilder):
metadata['navlist'] = navlist metadata['navlist'] = navlist
return metadata return metadata
def build_navigation_doc(self, outdir, outname): def build_navigation_doc(self, outdir=None, outname='nav.xhtml'):
# type: (unicode, unicode) -> None # type: (str, str) -> None
"""Write the metainfo file nav.xhtml.""" """Write the metainfo file nav.xhtml."""
if outdir:
warnings.warn('The arguments of Epub3Builder.build_navigation_doc() '
'is deprecated.', RemovedInSphinx40Warning, stacklevel=2)
else:
outdir = self.outdir
logger.info(__('writing %s file...'), outname) logger.info(__('writing %s file...'), outname)
if self.config.epub_tocscope == 'default': if self.config.epub_tocscope == 'default':
@ -229,12 +202,52 @@ class Epub3Builder(_epub_base.EpubBuilder):
self.files.append(outname) self.files.append(outname)
def validate_config_values(app):
# type: (Sphinx) -> None
if app.builder.name != 'epub':
return
# <package> lang attribute, dc:language
if not app.config.epub_language:
logger.warning(__('conf value "epub_language" (or "language") '
'should not be empty for EPUB3'))
# <package> unique-identifier attribute
if not xmlname_checker().match(app.config.epub_uid):
logger.warning(__('conf value "epub_uid" should be XML NAME for EPUB3'))
# dc:title
if not app.config.epub_title:
logger.warning(__('conf value "epub_title" (or "html_title") '
'should not be empty for EPUB3'))
# dc:creator
if not app.config.epub_author:
logger.warning(__('conf value "epub_author" should not be empty for EPUB3'))
# dc:contributor
if not app.config.epub_contributor:
logger.warning(__('conf value "epub_contributor" should not be empty for EPUB3'))
# dc:description
if not app.config.epub_description:
logger.warning(__('conf value "epub_description" should not be empty for EPUB3'))
# dc:publisher
if not app.config.epub_publisher:
logger.warning(__('conf value "epub_publisher" should not be empty for EPUB3'))
# dc:rights
if not app.config.epub_copyright:
logger.warning(__('conf value "epub_copyright" (or "copyright")'
'should not be empty for EPUB3'))
# dc:identifier
if not app.config.epub_identifier:
logger.warning(__('conf value "epub_identifier" should not be empty for EPUB3'))
# meta ibooks:version
if not app.config.version:
logger.warning(__('conf value "version" should not be empty for EPUB3'))
def convert_epub_css_files(app, config): def convert_epub_css_files(app, config):
# type: (Sphinx, Config) -> None # type: (Sphinx, Config) -> None
"""This converts string styled epub_css_files to tuple styled one.""" """This converts string styled epub_css_files to tuple styled one."""
epub_css_files = [] # type: List[Tuple[unicode, Dict]] epub_css_files = [] # type: List[Tuple[str, Dict]]
for entry in config.epub_css_files: for entry in config.epub_css_files:
if isinstance(entry, string_types): if isinstance(entry, str):
epub_css_files.append((entry, {})) epub_css_files.append((entry, {}))
else: else:
try: try:
@ -248,7 +261,7 @@ def convert_epub_css_files(app, config):
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[str, Any]
app.add_builder(Epub3Builder) app.add_builder(Epub3Builder)
# config values # config values
@ -277,13 +290,14 @@ def setup(app):
app.add_config_value('epub_max_image_width', 0, 'env') app.add_config_value('epub_max_image_width', 0, 'env')
app.add_config_value('epub_show_urls', 'inline', 'epub') app.add_config_value('epub_show_urls', 'inline', 'epub')
app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'epub') app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'epub')
app.add_config_value('epub_description', 'unknown', 'epub', string_classes) app.add_config_value('epub_description', 'unknown', 'epub')
app.add_config_value('epub_contributor', 'unknown', 'epub', string_classes) app.add_config_value('epub_contributor', 'unknown', 'epub')
app.add_config_value('epub_writing_mode', 'horizontal', 'epub', app.add_config_value('epub_writing_mode', 'horizontal', 'epub',
ENUM('horizontal', 'vertical')) ENUM('horizontal', 'vertical'))
# event handlers # event handlers
app.connect('config-inited', convert_epub_css_files) app.connect('config-inited', convert_epub_css_files)
app.connect('builder-inited', validate_config_values)
return { return {
'version': 'builtin', 'version': 'builtin',

View File

@ -1,27 +1,24 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.gettext sphinx.builders.gettext
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
The MessageCatalogBuilder class. The MessageCatalogBuilder class.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
from __future__ import unicode_literals
from codecs import open from codecs import open
from collections import defaultdict, OrderedDict from collections import defaultdict, OrderedDict
from datetime import datetime, tzinfo, timedelta from datetime import datetime, tzinfo, timedelta
from io import StringIO
from os import path, walk, getenv from os import path, walk, getenv
from time import time from time import time
from uuid import uuid4 from uuid import uuid4
from six import iteritems, StringIO
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.domains.python import pairindextypes from sphinx.domains.python import pairindextypes
from sphinx.errors import ThemeError
from sphinx.locale import __ from sphinx.locale import __
from sphinx.util import split_index_msg, logging, status_iterator from sphinx.util import split_index_msg, logging, status_iterator
from sphinx.util.console import bold # type: ignore from sphinx.util.console import bold # type: ignore
@ -32,10 +29,10 @@ from sphinx.util.tags import Tags
if False: if False:
# For type annotation # For type annotation
from typing import Any, DefaultDict, Dict, Iterable, List, Set, Tuple # NOQA from typing import Any, DefaultDict, Dict, Iterable, List, Set, Tuple, Union # NOQA
from docutils import nodes # NOQA from docutils import nodes # NOQA
from sphinx.util.i18n import CatalogInfo # NOQA
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
from sphinx.util.i18n import CatalogInfo # NOQA
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -62,18 +59,18 @@ msgstr ""
"""[1:] """[1:]
class Catalog(object): class Catalog:
"""Catalog of translatable messages.""" """Catalog of translatable messages."""
def __init__(self): def __init__(self):
# type: () -> None # type: () -> None
self.messages = [] # type: List[unicode] self.messages = [] # type: List[str]
# retain insertion order, a la OrderedDict # retain insertion order, a la OrderedDict
self.metadata = OrderedDict() # type: Dict[unicode, List[Tuple[unicode, int, unicode]]] # NOQA self.metadata = OrderedDict() # type: Dict[str, List[Tuple[str, int, str]]]
# msgid -> file, line, uid # msgid -> file, line, uid
def add(self, msg, origin): def add(self, msg, origin):
# type: (unicode, MsgOrigin) -> None # type: (str, Union[nodes.Element, MsgOrigin]) -> None
if not hasattr(origin, 'uid'): if not hasattr(origin, 'uid'):
# Nodes that are replicated like todo don't have a uid, # Nodes that are replicated like todo don't have a uid,
# however i18n is also unnecessary. # however i18n is also unnecessary.
@ -81,16 +78,16 @@ class Catalog(object):
if msg not in self.metadata: # faster lookup in hash if msg not in self.metadata: # faster lookup in hash
self.messages.append(msg) self.messages.append(msg)
self.metadata[msg] = [] self.metadata[msg] = []
self.metadata[msg].append((origin.source, origin.line, origin.uid)) self.metadata[msg].append((origin.source, origin.line, origin.uid)) # type: ignore
class MsgOrigin(object): class MsgOrigin:
""" """
Origin holder for Catalog message origin. Origin holder for Catalog message origin.
""" """
def __init__(self, source, line): def __init__(self, source, line):
# type: (unicode, int) -> None # type: (str, int) -> None
self.source = source self.source = source
self.line = line self.line = line
self.uid = uuid4().hex self.uid = uuid4().hex
@ -119,32 +116,31 @@ class I18nBuilder(Builder):
def init(self): def init(self):
# type: () -> None # type: () -> None
Builder.init(self) super().init()
self.env.set_versioning_method(self.versioning_method, self.env.set_versioning_method(self.versioning_method,
self.env.config.gettext_uuid) self.env.config.gettext_uuid)
self.tags = I18nTags() self.tags = I18nTags()
self.catalogs = defaultdict(Catalog) # type: DefaultDict[unicode, Catalog] self.catalogs = defaultdict(Catalog) # type: DefaultDict[str, Catalog]
def get_target_uri(self, docname, typ=None): def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode # type: (str, str) -> str
return '' return ''
def get_outdated_docs(self): def get_outdated_docs(self):
# type: () -> Set[unicode] # type: () -> Set[str]
return self.env.found_docs return self.env.found_docs
def prepare_writing(self, docnames): def prepare_writing(self, docnames):
# type: (Set[unicode]) -> None # type: (Set[str]) -> None
return return
def compile_catalogs(self, catalogs, message): def compile_catalogs(self, catalogs, message):
# type: (Set[CatalogInfo], unicode) -> None # type: (Set[CatalogInfo], str) -> None
return return
def write_doc(self, docname, doctree): def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None # type: (str, nodes.document) -> None
catalog = self.catalogs[find_catalog(docname, catalog = self.catalogs[find_catalog(docname, self.config.gettext_compact)]
self.config.gettext_compact)]
for node, msg in extract_messages(doctree): for node, msg in extract_messages(doctree):
catalog.add(msg, node) catalog.add(msg, node)
@ -177,7 +173,7 @@ class LocalTimeZone(tzinfo):
def __init__(self, *args, **kw): def __init__(self, *args, **kw):
# type: (Any, Any) -> None # type: (Any, Any) -> None
super(LocalTimeZone, self).__init__(*args, **kw) # type: ignore super().__init__(*args, **kw) # type: ignore
self.tzdelta = tzdelta self.tzdelta = tzdelta
def utcoffset(self, dt): def utcoffset(self, dt):
@ -193,11 +189,11 @@ ltz = LocalTimeZone()
def should_write(filepath, new_content): def should_write(filepath, new_content):
# type: (unicode, unicode) -> bool # type: (str, str) -> bool
if not path.exists(filepath): if not path.exists(filepath):
return True return True
try: try:
with open(filepath, 'r', encoding='utf-8') as oldpot: # type: ignore with open(filepath, encoding='utf-8') as oldpot:
old_content = oldpot.read() old_content = oldpot.read()
old_header_index = old_content.index('"POT-Creation-Date:') old_header_index = old_content.index('"POT-Creation-Date:')
new_header_index = new_content.index('"POT-Creation-Date:') new_header_index = new_content.index('"POT-Creation-Date:')
@ -220,12 +216,12 @@ class MessageCatalogBuilder(I18nBuilder):
def init(self): def init(self):
# type: () -> None # type: () -> None
I18nBuilder.init(self) super().init()
self.create_template_bridge() self.create_template_bridge()
self.templates.init(self) self.templates.init(self)
def _collect_templates(self): def _collect_templates(self):
# type: () -> Set[unicode] # type: () -> Set[str]
template_files = set() template_files = set()
for template_path in self.config.templates_path: for template_path in self.config.templates_path:
tmpl_abs_path = path.join(self.app.srcdir, template_path) tmpl_abs_path = path.join(self.app.srcdir, template_path)
@ -240,35 +236,38 @@ class MessageCatalogBuilder(I18nBuilder):
# type: () -> None # type: () -> None
files = list(self._collect_templates()) files = list(self._collect_templates())
files.sort() files.sort()
logger.info(bold(__('building [%s]: ') % self.name), nonl=1) logger.info(bold(__('building [%s]: ') % self.name), nonl=True)
logger.info(__('targets for %d template files'), len(files)) logger.info(__('targets for %d template files'), len(files))
extract_translations = self.templates.environment.extract_translations extract_translations = self.templates.environment.extract_translations
for template in status_iterator(files, __('reading templates... '), "purple", # type: ignore # NOQA for template in status_iterator(files, __('reading templates... '), "purple",
len(files), self.app.verbosity): len(files), self.app.verbosity):
with open(template, 'r', encoding='utf-8') as f: # type: ignore try:
with open(template, encoding='utf-8') as f:
context = f.read() context = f.read()
for line, meth, msg in extract_translations(context): for line, meth, msg in extract_translations(context):
origin = MsgOrigin(template, line) origin = MsgOrigin(template, line)
self.catalogs['sphinx'].add(msg, origin) self.catalogs['sphinx'].add(msg, origin)
except Exception as exc:
raise ThemeError('%s: %r' % (template, exc))
def build(self, docnames, summary=None, method='update'): def build(self, docnames, summary=None, method='update'):
# type: (Iterable[unicode], unicode, unicode) -> None # type: (Iterable[str], str, str) -> None
self._extract_from_template() self._extract_from_template()
I18nBuilder.build(self, docnames, summary, method) super().build(docnames, summary, method)
def finish(self): def finish(self):
# type: () -> None # type: () -> None
I18nBuilder.finish(self) super().finish()
data = dict( data = {
version = self.config.version, 'version': self.config.version,
copyright = self.config.copyright, 'copyright': self.config.copyright,
project = self.config.project, 'project': self.config.project,
ctime = datetime.fromtimestamp( 'ctime': datetime.fromtimestamp(
timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'), timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
) }
for textdomain, catalog in status_iterator(iteritems(self.catalogs), # type: ignore for textdomain, catalog in status_iterator(self.catalogs.items(),
__("writing message catalogs... "), __("writing message catalogs... "),
"darkgreen", len(self.catalogs), "darkgreen", len(self.catalogs),
self.app.verbosity, self.app.verbosity,
@ -278,36 +277,35 @@ class MessageCatalogBuilder(I18nBuilder):
pofn = path.join(self.outdir, textdomain + '.pot') pofn = path.join(self.outdir, textdomain + '.pot')
output = StringIO() output = StringIO()
output.write(POHEADER % data) # type: ignore output.write(POHEADER % data)
for message in catalog.messages: for message in catalog.messages:
positions = catalog.metadata[message] positions = catalog.metadata[message]
if self.config.gettext_location: if self.config.gettext_location:
# generate "#: file1:line1\n#: file2:line2 ..." # generate "#: file1:line1\n#: file2:line2 ..."
output.write("#: %s\n" % "\n#: ".join( # type: ignore output.write("#: %s\n" % "\n#: ".join(
"%s:%s" % (canon_path(relpath(source, self.outdir)), line) "%s:%s" % (canon_path(relpath(source, self.outdir)), line)
for source, line, _ in positions)) for source, line, _ in positions))
if self.config.gettext_uuid: if self.config.gettext_uuid:
# generate "# uuid1\n# uuid2\n ..." # generate "# uuid1\n# uuid2\n ..."
output.write("# %s\n" % "\n# ".join( # type: ignore output.write("# %s\n" % "\n# ".join(uid for _, _, uid in positions))
uid for _, _, uid in positions))
# message contains *one* line of text ready for translation # message contains *one* line of text ready for translation
message = message.replace('\\', r'\\'). \ message = message.replace('\\', r'\\'). \
replace('"', r'\"'). \ replace('"', r'\"'). \
replace('\n', '\\n"\n"') replace('\n', '\\n"\n"')
output.write('msgid "%s"\nmsgstr ""\n\n' % message) # type: ignore output.write('msgid "%s"\nmsgstr ""\n\n' % message)
content = output.getvalue() content = output.getvalue()
if should_write(pofn, content): if should_write(pofn, content):
with open(pofn, 'w', encoding='utf-8') as pofile: # type: ignore with open(pofn, 'w', encoding='utf-8') as pofile:
pofile.write(content) pofile.write(content)
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[str, Any]
app.add_builder(MessageCatalogBuilder) app.add_builder(MessageCatalogBuilder)
app.add_config_value('gettext_compact', True, 'gettext') app.add_config_value('gettext_compact', True, 'gettext')

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.htmlhelp sphinx.builders.htmlhelp
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
@ -6,33 +5,41 @@
Build HTML help support files. Build HTML help support files.
Parts adapted from Python's Doc/tools/prechm.py. Parts adapted from Python's Doc/tools/prechm.py.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
from __future__ import print_function
import codecs import html
import os import os
import warnings
from os import path from os import path
from docutils import nodes from docutils import nodes
from sphinx import addnodes from sphinx import addnodes
from sphinx import package_dir
from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.environment.adapters.indexentries import IndexEntries from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.locale import __ from sphinx.locale import __
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.osutil import make_filename from sphinx.util import progress_message
from sphinx.util.pycompat import htmlescape from sphinx.util.fileutil import copy_asset_file
from sphinx.util.nodes import NodeMatcher
from sphinx.util.osutil import make_filename_from_project, relpath
from sphinx.util.template import SphinxRenderer
if False: if False:
# For type annotation # For type annotation
from typing import Any, Dict, IO, List, Tuple # NOQA from typing import Any, Dict, IO, List, Match, Tuple # NOQA
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
template_dir = path.join(package_dir, 'templates', 'htmlhelp')
# Project file (*.hhp) template. 'outname' is the file basename (like # Project file (*.hhp) template. 'outname' is the file basename (like
# the pythlp in pythlp.hhp); 'version' is the doc version number (like # the pythlp in pythlp.hhp); 'version' is the doc version number (like
@ -68,46 +75,6 @@ logger = logging.getLogger(__name__)
# 0x200000 TOC Next # 0x200000 TOC Next
# 0x400000 TOC Prev # 0x400000 TOC Prev
project_template = '''\
[OPTIONS]
Binary TOC=No
Binary Index=No
Compiled file=%(outname)s.chm
Contents file=%(outname)s.hhc
Default Window=%(outname)s
Default topic=%(master_doc)s
Display compile progress=No
Full text search stop list file=%(outname)s.stp
Full-text search=Yes
Index file=%(outname)s.hhk
Language=%(lcid)#x
Title=%(title)s
[WINDOWS]
%(outname)s="%(title)s","%(outname)s.hhc","%(outname)s.hhk",\
"%(master_doc)s","%(master_doc)s",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
[FILES]
'''
contents_header = '''\
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1">
<!-- Sitemap 1.0 -->
</HEAD><BODY>
<OBJECT type="text/site properties">
<param name="Window Styles" value="0x801227">
<param name="ImageType" value="Folder">
</OBJECT>
<UL>
'''
contents_footer = '''\
</UL></BODY></HTML>
'''
object_sitemap = '''\ object_sitemap = '''\
<OBJECT type="text/sitemap"> <OBJECT type="text/sitemap">
<param name="Name" value="%s"> <param name="Name" value="%s">
@ -115,26 +82,9 @@ object_sitemap = '''\
</OBJECT> </OBJECT>
''' '''
# List of words the full text search facility shouldn't index. This # The following list includes only languages supported by Sphinx. See
# becomes file outname.stp. Note that this list must be pretty small! # https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms930130(v=msdn.10)
# Different versions of the MS docs claim the file has a maximum size of # for more.
# 256 or 512 bytes (including \r\n at the end of each line).
# Note that "and", "or", "not" and "near" are operators in the search
# language, so no point indexing them even if we wanted to.
stopwords = """
a and are as at
be but by
for
if in into is it
near no not
of on or
such
that the their then there these they this to
was will with
""".split()
# The following list includes only languages supported by Sphinx.
# See http://msdn.microsoft.com/en-us/library/ms930130.aspx for more.
chm_locales = { chm_locales = {
# lang: LCID, encoding # lang: LCID, encoding
'ca': (0x403, 'cp1252'), 'ca': (0x403, 'cp1252'),
@ -169,6 +119,77 @@ chm_locales = {
} }
def chm_htmlescape(s, quote=True):
# type: (str, bool) -> str
"""
chm_htmlescape() is a wrapper of html.escape().
.hhc/.hhk files don't recognize hex escaping, we need convert
hex escaping to decimal escaping. for example: ``&#x27;`` -> ``&#39;``
html.escape() may generates a hex escaping ``&#x27;`` for single
quote ``'``, this wrapper fixes this.
"""
s = html.escape(s, quote)
s = s.replace('&#x27;', '&#39;') # re-escape as decimal
return s
class ToCTreeVisitor(nodes.NodeVisitor):
def __init__(self, document):
# type: (nodes.document) -> None
super().__init__(document)
self.body = [] # type: List[str]
self.depth = 0
def append(self, text):
# type: (str) -> None
indent = ' ' * (self.depth - 1)
self.body.append(indent + text)
def astext(self):
# type: () -> str
return '\n'.join(self.body)
def unknown_visit(self, node):
# type: (nodes.Node) -> None
pass
def unknown_departure(self, node):
# type: (nodes.Node) -> None
pass
def visit_bullet_list(self, node):
# type: (nodes.Element) -> None
if self.depth > 0:
self.append('<UL>')
self.depth += 1
def depart_bullet_list(self, node):
# type: (nodes.Element) -> None
self.depth -= 1
if self.depth > 0:
self.append('</UL>')
def visit_list_item(self, node):
# type: (nodes.Element) -> None
self.append('<LI>')
self.depth += 1
def depart_list_item(self, node):
# type: (nodes.Element) -> None
self.depth -= 1
self.append('</LI>')
def visit_reference(self, node):
# type: (nodes.Element) -> None
title = chm_htmlescape(node.astext(), True)
self.append('<OBJECT type="text/sitemap">')
self.append(' <PARAM name="Name" value="%s" />' % title)
self.append(' <PARAM name="Local" value="%s" />' % node['refuri'])
self.append('</OBJECT>')
raise nodes.SkipNode
class HTMLHelpBuilder(StandaloneHTMLBuilder): class HTMLHelpBuilder(StandaloneHTMLBuilder):
""" """
Builder that also outputs Windows HTML help project, contents and Builder that also outputs Windows HTML help project, contents and
@ -195,123 +216,130 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
def init(self): def init(self):
# type: () -> None # type: () -> None
StandaloneHTMLBuilder.init(self) # the output files for HTML help is .html by default
# the output files for HTML help must be .html only
self.out_suffix = '.html' self.out_suffix = '.html'
self.link_suffix = '.html' self.link_suffix = '.html'
super().init()
# determine the correct locale setting # determine the correct locale setting
locale = chm_locales.get(self.config.language) locale = chm_locales.get(self.config.language)
if locale is not None: if locale is not None:
self.lcid, self.encoding = locale self.lcid, self.encoding = locale
def open_file(self, outdir, basename, mode='w'): def open_file(self, outdir, basename, mode='w'):
# type: (unicode, unicode, unicode) -> IO # type: (str, str, str) -> IO
# open a file with the correct encoding for the selected language # open a file with the correct encoding for the selected language
return codecs.open(path.join(outdir, basename), mode, # type: ignore warnings.warn('HTMLHelpBuilder.open_file() is deprecated.',
self.encoding, 'xmlcharrefreplace') RemovedInSphinx40Warning)
return open(path.join(outdir, basename), mode, encoding=self.encoding,
errors='xmlcharrefreplace')
def update_page_context(self, pagename, templatename, ctx, event_arg): def update_page_context(self, pagename, templatename, ctx, event_arg):
# type: (unicode, unicode, Dict, unicode) -> None # type: (str, str, Dict, str) -> None
ctx['encoding'] = self.encoding ctx['encoding'] = self.encoding
def handle_finish(self): def handle_finish(self):
# type: () -> None # type: () -> None
self.copy_stopword_list()
self.build_project_file()
self.build_toc_file()
self.build_hhx(self.outdir, self.config.htmlhelp_basename) self.build_hhx(self.outdir, self.config.htmlhelp_basename)
def write_doc(self, docname, doctree): def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None # type: (str, nodes.document) -> None
for node in doctree.traverse(nodes.reference): for node in doctree.traverse(nodes.reference):
# add ``target=_blank`` attributes to external links # add ``target=_blank`` attributes to external links
if node.get('internal') is None and 'refuri' in node: if node.get('internal') is None and 'refuri' in node:
node['target'] = '_blank' node['target'] = '_blank'
StandaloneHTMLBuilder.write_doc(self, docname, doctree) super().write_doc(docname, doctree)
def build_hhx(self, outdir, outname): def render(self, name, context):
# type: (unicode, unicode) -> None # type: (str, Dict) -> str
logger.info(__('dumping stopword list...')) template = SphinxRenderer(template_dir)
with self.open_file(outdir, outname + '.stp') as f: return template.render(name, context)
for word in sorted(stopwords):
print(word, file=f)
logger.info(__('writing project file...')) @progress_message(__('copying stopword list'))
with self.open_file(outdir, outname + '.hhp') as f: def copy_stopword_list(self):
f.write(project_template % { # type: () -> None
'outname': outname, """Copy a stopword list (.stp) to outdir.
The stopword list contains a list of words the full text search facility
shouldn't index. Note that this list must be pretty small. Different
versions of the MS docs claim the file has a maximum size of 256 or 512
bytes (including \r\n at the end of each line). Note that "and", "or",
"not" and "near" are operators in the search language, so no point
indexing them even if we wanted to.
"""
template = path.join(template_dir, 'project.stp')
filename = path.join(self.outdir, self.config.htmlhelp_basename + '.stp')
copy_asset_file(template, filename)
@progress_message(__('writing project file'))
def build_project_file(self):
# type: () -> None
"""Create a project file (.hhp) on outdir."""
# scan project files
project_files = [] # type: List[str]
for root, dirs, files in os.walk(self.outdir):
dirs.sort()
files.sort()
in_staticdir = root.startswith(path.join(self.outdir, '_static'))
for fn in sorted(files):
if (in_staticdir and not fn.endswith('.js')) or fn.endswith('.html'):
fn = relpath(path.join(root, fn), self.outdir)
project_files.append(fn.replace(os.sep, '\\'))
filename = path.join(self.outdir, self.config.htmlhelp_basename + '.hhp')
with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
context = {
'outname': self.config.htmlhelp_basename,
'title': self.config.html_title, 'title': self.config.html_title,
'version': self.config.version, 'version': self.config.version,
'project': self.config.project, 'project': self.config.project,
'lcid': self.lcid, 'lcid': self.lcid,
'master_doc': self.config.master_doc + self.out_suffix 'master_doc': self.config.master_doc + self.out_suffix,
}) 'files': project_files,
if not outdir.endswith(os.sep): }
outdir += os.sep body = self.render('project.hhp', context)
olen = len(outdir) f.write(body)
for root, dirs, files in os.walk(outdir):
dirs.sort()
files.sort()
staticdir = root.startswith(path.join(outdir, '_static'))
for fn in sorted(files):
if (staticdir and not fn.endswith('.js')) or \
fn.endswith('.html'):
print(path.join(root, fn)[olen:].replace(os.sep, '\\'),
file=f)
logger.info(__('writing TOC file...')) @progress_message(__('writing TOC file'))
with self.open_file(outdir, outname + '.hhc') as f: def build_toc_file(self):
f.write(contents_header) # type: () -> None
# special books """Create a ToC file (.hhp) on outdir."""
f.write('<LI> ' + object_sitemap % (self.config.html_short_title, filename = path.join(self.outdir, self.config.htmlhelp_basename + '.hhc')
self.config.master_doc + self.out_suffix)) with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
for indexname, indexcls, content, collapse in self.domain_indices: toctree = self.env.get_and_resolve_doctree(self.config.master_doc, self,
f.write('<LI> ' + object_sitemap % (indexcls.localname, prune_toctrees=False)
'%s.html' % indexname)) visitor = ToCTreeVisitor(toctree)
# the TOC matcher = NodeMatcher(addnodes.compact_paragraph, toctree=True)
tocdoc = self.env.get_and_resolve_doctree( for node in toctree.traverse(matcher): # type: addnodes.compact_paragraph
self.config.master_doc, self, prune_toctrees=False) node.walkabout(visitor)
def write_toc(node, ullevel=0): context = {
# type: (nodes.Node, int) -> None 'body': visitor.astext(),
if isinstance(node, nodes.list_item): 'suffix': self.out_suffix,
f.write('<LI> ') 'short_title': self.config.html_short_title,
for subnode in node: 'master_doc': self.config.master_doc,
write_toc(subnode, ullevel) 'domain_indices': self.domain_indices,
elif isinstance(node, nodes.reference): }
link = node['refuri'] f.write(self.render('project.hhc', context))
title = htmlescape(node.astext()).replace('"', '&quot;')
f.write(object_sitemap % (title, link))
elif isinstance(node, nodes.bullet_list):
if ullevel != 0:
f.write('<UL>\n')
for subnode in node:
write_toc(subnode, ullevel + 1)
if ullevel != 0:
f.write('</UL>\n')
elif isinstance(node, addnodes.compact_paragraph):
for subnode in node:
write_toc(subnode, ullevel)
def istoctree(node):
# type: (nodes.Node) -> bool
return isinstance(node, addnodes.compact_paragraph) and \
'toctree' in node
for node in tocdoc.traverse(istoctree):
write_toc(node)
f.write(contents_footer)
def build_hhx(self, outdir, outname):
# type: (str, str) -> None
logger.info(__('writing index file...')) logger.info(__('writing index file...'))
index = IndexEntries(self.env).create_index(self) index = IndexEntries(self.env).create_index(self)
with self.open_file(outdir, outname + '.hhk') as f: filename = path.join(outdir, outname + '.hhk')
with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
f.write('<UL>\n') f.write('<UL>\n')
def write_index(title, refs, subitems): def write_index(title, refs, subitems):
# type: (unicode, List[Tuple[unicode, unicode]], List[Tuple[unicode, List[Tuple[unicode, unicode]]]]) -> None # NOQA # type: (str, List[Tuple[str, str]], List[Tuple[str, List[Tuple[str, str]]]]) -> None # NOQA
def write_param(name, value): def write_param(name, value):
# type: (unicode, unicode) -> None # type: (str, str) -> None
item = ' <param name="%s" value="%s">\n' % \ item = ' <param name="%s" value="%s">\n' % (name, value)
(name, value)
f.write(item) f.write(item)
title = htmlescape(title) title = chm_htmlescape(title, True)
f.write('<LI> <OBJECT type="text/sitemap">\n') f.write('<LI> <OBJECT type="text/sitemap">\n')
write_param('Keyword', title) write_param('Keyword', title)
if len(refs) == 0: if len(refs) == 0:
@ -335,12 +363,20 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
f.write('</UL>\n') f.write('</UL>\n')
def default_htmlhelp_basename(config):
# type: (Config) -> str
"""Better default htmlhelp_basename setting."""
return make_filename_from_project(config.project) + 'doc'
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[str, Any]
app.setup_extension('sphinx.builders.html') app.setup_extension('sphinx.builders.html')
app.add_builder(HTMLHelpBuilder) app.add_builder(HTMLHelpBuilder)
app.add_config_value('htmlhelp_basename', lambda self: make_filename(self.project), None) app.add_config_value('htmlhelp_basename', default_htmlhelp_basename, None)
app.add_config_value('htmlhelp_file_suffix', None, 'html', [str])
app.add_config_value('htmlhelp_link_suffix', None, 'html', [str])
return { return {
'version': 'builtin', 'version': 'builtin',

View File

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.latex sphinx.builders.latex
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
LaTeX builder. LaTeX builder.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -13,8 +12,8 @@ import os
from os import path from os import path
from docutils.frontend import OptionParser from docutils.frontend import OptionParser
from six import text_type
import sphinx.builders.latex.nodes # NOQA # Workaround: import this before writer to avoid ImportError
from sphinx import package_dir, addnodes, highlighting from sphinx import package_dir, addnodes, highlighting
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.builders.latex.transforms import ( from sphinx.builders.latex.transforms import (
@ -22,19 +21,24 @@ from sphinx.builders.latex.transforms import (
FootnoteDocnameUpdater, LaTeXFootnoteTransform, LiteralBlockTransform, FootnoteDocnameUpdater, LaTeXFootnoteTransform, LiteralBlockTransform,
ShowUrlsTransform, DocumentTargetTransform, ShowUrlsTransform, DocumentTargetTransform,
) )
from sphinx.config import string_classes, ENUM from sphinx.builders.latex.util import ExtBabel
from sphinx.config import ENUM
from sphinx.environment import NoUri from sphinx.environment import NoUri
from sphinx.environment.adapters.asset import ImageAdapter from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import SphinxError, ConfigError from sphinx.errors import SphinxError
from sphinx.locale import _, __ from sphinx.locale import _, __
from sphinx.transforms import SphinxTransformer from sphinx.transforms import SphinxTransformer
from sphinx.util import texescape, logging, status_iterator from sphinx.util import texescape, logging, status_iterator
from sphinx.util.console import bold, darkgreen # type: ignore from sphinx.util.console import bold, darkgreen # type: ignore
from sphinx.util.docutils import SphinxFileOutput, new_document from sphinx.util.docutils import SphinxFileOutput, new_document
from sphinx.util.fileutil import copy_asset_file from sphinx.util.fileutil import copy_asset_file
from sphinx.util.i18n import format_date
from sphinx.util.nodes import inline_all_toctrees from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, make_filename from sphinx.util.osutil import SEP, make_filename_from_project
from sphinx.writers.latex import DEFAULT_SETTINGS, LaTeXWriter, LaTeXTranslator from sphinx.util.template import LaTeXRenderer
from sphinx.writers.latex import (
ADDITIONAL_SETTINGS, DEFAULT_SETTINGS, LaTeXWriter, LaTeXTranslator
)
if False: if False:
# For type annotation # For type annotation
@ -99,11 +103,11 @@ XINDY_LANG_OPTIONS = {
'el': '-L greek -C utf8 ', 'el': '-L greek -C utf8 ',
# FIXME, not compatible with [:2] slice but does Sphinx support Greek ? # FIXME, not compatible with [:2] slice but does Sphinx support Greek ?
'el-polyton': '-L greek -C polytonic-utf8 ', 'el-polyton': '-L greek -C polytonic-utf8 ',
} # type: Dict[unicode, unicode] }
XINDY_CYRILLIC_SCRIPTS = [ XINDY_CYRILLIC_SCRIPTS = [
'be', 'bg', 'mk', 'mn', 'ru', 'sr', 'sh', 'uk', 'be', 'bg', 'mk', 'mn', 'ru', 'sr', 'sh', 'uk',
] # type: List[unicode] ]
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -126,24 +130,29 @@ class LaTeXBuilder(Builder):
def init(self): def init(self):
# type: () -> None # type: () -> None
self.docnames = [] # type: Iterable[unicode] self.babel = None # type: ExtBabel
self.document_data = [] # type: List[Tuple[unicode, unicode, unicode, unicode, unicode, bool]] # NOQA self.context = {} # type: Dict[str, Any]
self.docnames = [] # type: Iterable[str]
self.document_data = [] # type: List[Tuple[str, str, str, str, str, bool]]
self.usepackages = self.app.registry.latex_packages self.usepackages = self.app.registry.latex_packages
texescape.init() texescape.init()
self.init_context()
self.init_babel()
def get_outdated_docs(self): def get_outdated_docs(self):
# type: () -> Union[unicode, List[unicode]] # type: () -> Union[str, List[str]]
return 'all documents' # for now return 'all documents' # for now
def get_target_uri(self, docname, typ=None): def get_target_uri(self, docname, typ=None):
# type: (unicode, unicode) -> unicode # type: (str, str) -> str
if docname not in self.docnames: if docname not in self.docnames:
raise NoUri raise NoUri
else: else:
return '%' + docname return '%' + docname
def get_relative_uri(self, from_, to, typ=None): def get_relative_uri(self, from_, to, typ=None):
# type: (unicode, unicode, unicode) -> unicode # type: (str, str, str) -> str
# ignore source path # ignore source path
return self.get_target_uri(to, typ) return self.get_target_uri(to, typ)
@ -155,7 +164,7 @@ class LaTeXBuilder(Builder):
'will be written')) 'will be written'))
return return
# assign subdirs to titles # assign subdirs to titles
self.titles = [] # type: List[Tuple[unicode, unicode]] self.titles = [] # type: List[Tuple[str, str]]
for entry in preliminary_document_data: for entry in preliminary_document_data:
docname = entry[0] docname = entry[0]
if docname not in self.env.all_docs: if docname not in self.env.all_docs:
@ -167,6 +176,52 @@ class LaTeXBuilder(Builder):
docname = docname[:-5] docname = docname[:-5]
self.titles.append((docname, entry[2])) self.titles.append((docname, entry[2]))
def init_context(self):
# type: () -> None
self.context = DEFAULT_SETTINGS.copy()
# Add special settings for latex_engine
self.context.update(ADDITIONAL_SETTINGS.get(self.config.latex_engine, {}))
# for xelatex+French, don't use polyglossia by default
if self.config.latex_engine == 'xelatex':
if self.config.language:
if self.config.language[:2] == 'fr':
self.context['polyglossia'] = ''
self.context['babel'] = r'\usepackage{babel}'
# Apply extension settings to context
self.context['packages'] = self.usepackages
# Apply user settings to context
self.context.update(self.config.latex_elements)
self.context['release'] = self.config.release
self.context['use_xindy'] = self.config.latex_use_xindy
if self.config.today:
self.context['date'] = self.config.today
else:
self.context['date'] = format_date(self.config.today_fmt or _('%b %d, %Y'),
language=self.config.language)
if self.config.latex_logo:
self.context['logofilename'] = path.basename(self.config.latex_logo)
# for compatibilities
self.context['indexname'] = _('Index')
if self.config.release:
# Show the release label only if release value exists
self.context['releasename'] = _('Release')
def init_babel(self):
# type: () -> None
self.babel = ExtBabel(self.config.language, not self.context['babel'])
if self.config.language and not self.babel.is_supported_language():
# emit warning if specified language is invalid
# (only emitting, nothing changed to processing)
logger.warning(__('no Babel option known for language %r'),
self.config.language)
def write_stylesheet(self): def write_stylesheet(self):
# type: () -> None # type: () -> None
highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style) highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
@ -175,7 +230,7 @@ class LaTeXBuilder(Builder):
f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n') f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n')
f.write('\\ProvidesPackage{sphinxhighlight}' f.write('\\ProvidesPackage{sphinxhighlight}'
'[2016/05/29 stylesheet for highlighting with pygments]\n\n') '[2016/05/29 stylesheet for highlighting with pygments]\n\n')
f.write(highlighter.get_stylesheet()) # type: ignore f.write(highlighter.get_stylesheet())
def write(self, *ignored): def write(self, *ignored):
# type: (Any) -> None # type: (Any) -> None
@ -183,7 +238,7 @@ class LaTeXBuilder(Builder):
docsettings = OptionParser( docsettings = OptionParser(
defaults=self.env.settings, defaults=self.env.settings,
components=(docwriter,), components=(docwriter,),
read_config_files=True).get_default_values() read_config_files=True).get_default_values() # type: Any
self.init_document_data() self.init_document_data()
self.write_stylesheet() self.write_stylesheet()
@ -195,7 +250,7 @@ class LaTeXBuilder(Builder):
toctree_only = entry[5] toctree_only = entry[5]
destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname), destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname),
encoding='utf-8', overwrite_if_changed=True) encoding='utf-8', overwrite_if_changed=True)
logger.info(__("processing %s..."), targetname, nonl=1) logger.info(__("processing %s..."), targetname, nonl=True)
toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree) toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree)
if toctrees: if toctrees:
if toctrees[0].get('maxdepth') > 0: if toctrees[0].get('maxdepth') > 0:
@ -210,18 +265,21 @@ class LaTeXBuilder(Builder):
doctree['tocdepth'] = tocdepth doctree['tocdepth'] = tocdepth
self.apply_transforms(doctree) self.apply_transforms(doctree)
self.post_process_images(doctree) self.post_process_images(doctree)
logger.info(__("writing... "), nonl=1) self.update_doc_context(title, author)
logger.info(__("writing... "), nonl=True)
docsettings.author = author
docsettings.title = title
docsettings.contentsname = self.get_contentsname(docname)
docsettings.docname = docname
docsettings.docclass = docclass
doctree.settings = docsettings doctree.settings = docsettings
doctree.settings.author = author
doctree.settings.title = title
doctree.settings.contentsname = self.get_contentsname(docname)
doctree.settings.docname = docname
doctree.settings.docclass = docclass
docwriter.write(doctree, destination) docwriter.write(doctree, destination)
logger.info("done") logger.info(__("done"))
def get_contentsname(self, indexfile): def get_contentsname(self, indexfile):
# type: (unicode) -> unicode # type: (str) -> str
tree = self.env.get_doctree(indexfile) tree = self.env.get_doctree(indexfile)
contentsname = None contentsname = None
for toctree in tree.traverse(addnodes.toctree): for toctree in tree.traverse(addnodes.toctree):
@ -231,11 +289,16 @@ class LaTeXBuilder(Builder):
return contentsname return contentsname
def update_doc_context(self, title, author):
# type: (str, str) -> None
self.context['title'] = title
self.context['author'] = author
def assemble_doctree(self, indexfile, toctree_only, appendices): def assemble_doctree(self, indexfile, toctree_only, appendices):
# type: (unicode, bool, List[unicode]) -> nodes.Node # type: (str, bool, List[str]) -> nodes.document
from docutils import nodes # NOQA from docutils import nodes # NOQA
self.docnames = set([indexfile] + appendices) self.docnames = set([indexfile] + appendices)
logger.info(darkgreen(indexfile) + " ", nonl=1) logger.info(darkgreen(indexfile) + " ", nonl=True)
tree = self.env.get_doctree(indexfile) tree = self.env.get_doctree(indexfile)
tree['docname'] = indexfile tree['docname'] = indexfile
if toctree_only: if toctree_only:
@ -243,8 +306,8 @@ class LaTeXBuilder(Builder):
# fresh document # fresh document
new_tree = new_document('<latex output>') new_tree = new_document('<latex output>')
new_sect = nodes.section() new_sect = nodes.section()
new_sect += nodes.title(u'<Set title in conf.py>', new_sect += nodes.title('<Set title in conf.py>',
u'<Set title in conf.py>') '<Set title in conf.py>')
new_tree += new_sect new_tree += new_sect
for node in tree.traverse(addnodes.toctree): for node in tree.traverse(addnodes.toctree):
new_sect += node new_sect += node
@ -264,7 +327,7 @@ class LaTeXBuilder(Builder):
for pendingnode in largetree.traverse(addnodes.pending_xref): for pendingnode in largetree.traverse(addnodes.pending_xref):
docname = pendingnode['refdocname'] docname = pendingnode['refdocname']
sectname = pendingnode['refsectname'] sectname = pendingnode['refsectname']
newnodes = [nodes.emphasis(sectname, sectname)] newnodes = [nodes.emphasis(sectname, sectname)] # type: List[nodes.Node]
for subdir, title in self.titles: for subdir, title in self.titles:
if docname.startswith(subdir): if docname.startswith(subdir):
newnodes.append(nodes.Text(_(' (in '), _(' (in '))) newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
@ -290,6 +353,7 @@ class LaTeXBuilder(Builder):
def finish(self): def finish(self):
# type: () -> None # type: () -> None
self.copy_image_files() self.copy_image_files()
self.write_message_catalog()
# copy TeX support files from texinputs # copy TeX support files from texinputs
# configure usage of xindy (impacts Makefile and latexmkrc) # configure usage of xindy (impacts Makefile and latexmkrc)
@ -324,9 +388,9 @@ class LaTeXBuilder(Builder):
# copy additional files # copy additional files
if self.config.latex_additional_files: if self.config.latex_additional_files:
logger.info(bold(__('copying additional files...')), nonl=1) logger.info(bold(__('copying additional files...')), nonl=True)
for filename in self.config.latex_additional_files: for filename in self.config.latex_additional_files:
logger.info(' ' + filename, nonl=1) logger.info(' ' + filename, nonl=True)
copy_asset_file(path.join(self.confdir, filename), self.outdir) copy_asset_file(path.join(self.confdir, filename), self.outdir)
logger.info('') logger.info('')
@ -353,26 +417,25 @@ class LaTeXBuilder(Builder):
logger.warning(__('cannot copy image file %r: %s'), logger.warning(__('cannot copy image file %r: %s'),
path.join(self.srcdir, src), err) path.join(self.srcdir, src), err)
def write_message_catalog(self):
# type: () -> None
formats = self.config.numfig_format
context = {
'addtocaptions': r'\@iden',
'figurename': formats.get('figure', '').split('%s', 1),
'tablename': formats.get('table', '').split('%s', 1),
'literalblockname': formats.get('code-block', '').split('%s', 1)
}
if self.context['babel'] or self.context['polyglossia']:
context['addtocaptions'] = r'\addto\captions%s' % self.babel.get_language()
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t')
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
def validate_config_values(app, config): def validate_config_values(app, config):
# type: (Sphinx, Config) -> None # type: (Sphinx, Config) -> None
for document in config.latex_documents:
try:
text_type(document[2])
except UnicodeDecodeError:
raise ConfigError(
__('Invalid latex_documents.title found (might contain non-ASCII chars. '
'Please use u"..." notation instead): %r') % (document,)
)
try:
text_type(document[3])
except UnicodeDecodeError:
raise ConfigError(
__('Invalid latex_documents.author found (might contain non-ASCII chars. '
'Please use u"..." notation instead): %r') % (document,)
)
for key in list(config.latex_elements): for key in list(config.latex_elements):
if key not in DEFAULT_SETTINGS: if key not in DEFAULT_SETTINGS:
msg = __("Unknown configure key: latex_elements[%r]. ignored.") msg = __("Unknown configure key: latex_elements[%r]. ignored.")
@ -381,7 +444,7 @@ def validate_config_values(app, config):
def default_latex_engine(config): def default_latex_engine(config):
# type: (Config) -> unicode # type: (Config) -> str
""" Better default latex_engine settings for specific languages. """ """ Better default latex_engine settings for specific languages. """
if config.language == 'ja': if config.language == 'ja':
return 'platex' return 'platex'
@ -390,7 +453,7 @@ def default_latex_engine(config):
def default_latex_docclass(config): def default_latex_docclass(config):
# type: (Config) -> Dict[unicode, unicode] # type: (Config) -> Dict[str, str]
""" Better default latex_docclass settings for specific languages. """ """ Better default latex_docclass settings for specific languages. """
if config.language == 'ja': if config.language == 'ja':
return {'manual': 'jsbook', return {'manual': 'jsbook',
@ -405,8 +468,18 @@ def default_latex_use_xindy(config):
return config.latex_engine in {'xelatex', 'lualatex'} return config.latex_engine in {'xelatex', 'lualatex'}
def default_latex_documents(config):
# type: (Config) -> List[Tuple[str, str, str, str, str]]
""" Better default latex_documents settings. """
return [(config.master_doc,
make_filename_from_project(config.project) + '.tex',
texescape.escape_abbr(texescape.escape(config.project)),
texescape.escape_abbr(texescape.escape(config.author)),
'manual')]
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[str, Any]
app.add_builder(LaTeXBuilder) app.add_builder(LaTeXBuilder)
app.add_post_transform(CitationReferenceTransform) app.add_post_transform(CitationReferenceTransform)
app.add_post_transform(MathReferenceTransform) app.add_post_transform(MathReferenceTransform)
@ -415,11 +488,8 @@ def setup(app):
app.add_config_value('latex_engine', default_latex_engine, None, app.add_config_value('latex_engine', default_latex_engine, None,
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex')) ENUM('pdflatex', 'xelatex', 'lualatex', 'platex'))
app.add_config_value('latex_documents', app.add_config_value('latex_documents', default_latex_documents, None)
lambda self: [(self.master_doc, make_filename(self.project) + '.tex', app.add_config_value('latex_logo', None, None, [str])
self.project, '', 'manual')],
None)
app.add_config_value('latex_logo', None, None, string_classes)
app.add_config_value('latex_appendices', [], None) app.add_config_value('latex_appendices', [], None)
app.add_config_value('latex_use_latex_multicolumn', False, None) app.add_config_value('latex_use_latex_multicolumn', False, None)
app.add_config_value('latex_use_xindy', default_latex_use_xindy, None) app.add_config_value('latex_use_xindy', default_latex_use_xindy, None)

View File

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
""" """
sphinx.builders.latex.nodes sphinx.builders.latex.nodes
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
Additional nodes for LaTeX writer. Additional nodes for LaTeX writer.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -35,3 +34,12 @@ class math_reference(nodes.Inline, nodes.Referential, nodes.TextElement):
class thebibliography(nodes.container): class thebibliography(nodes.container):
"""A node for wrapping bibliographies.""" """A node for wrapping bibliographies."""
pass pass
HYPERLINK_SUPPORT_NODES = (
nodes.figure,
nodes.literal_block,
nodes.table,
nodes.section,
captioned_literal_block,
)

Some files were not shown because too many files have changed in this diff Show More