mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into refactor_config
This commit is contained in:
commit
5897d45cc6
1
AUTHORS
1
AUTHORS
@ -40,6 +40,7 @@ Other contributors, listed alphabetically, are:
|
||||
* Timotheus Kampik - JS theme & search enhancements
|
||||
* Dave Kuhlman -- original LaTeX writer
|
||||
* Blaise Laflamme -- pyramid theme
|
||||
* Chris Lamb -- reproducibility fixes
|
||||
* Thomas Lamb -- linkcheck builder
|
||||
* Łukasz Langa -- partial support for autodoc
|
||||
* Ian Lee -- quickstart improvements
|
||||
|
36
CHANGES
36
CHANGES
@ -15,12 +15,19 @@ Incompatible changes
|
||||
* The default value of :confval:`epub_author` and :confval:`epub_publisher` are
|
||||
changed from ``'unknown'`` to the value of :confval:`author`. This is same as
|
||||
a ``conf.py`` file sphinx-build generates.
|
||||
* The ``gettext_compact`` attribute is removed from ``document.settings``
|
||||
object. Please use ``config.gettext_compact`` instead.
|
||||
* The processing order on reading phase is changed. smart_quotes, sphinx
|
||||
domains, :event:`doctree-read` event and versioning doctrees are invoked
|
||||
earlier than so far. For more details, please read a description of
|
||||
:py:meth:`.Sphinx.add_transform()`
|
||||
* #4827: All ``substitution_definition`` nodes are removed from doctree on
|
||||
reading phase
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
* :confval:`source_parsers` is deprecated
|
||||
instead.
|
||||
* ``Application.import_object()`` is deprecated
|
||||
* Drop function based directive support. For now, Sphinx only supports class
|
||||
based directives.
|
||||
@ -34,6 +41,8 @@ Deprecated
|
||||
* #2157: helper function ``warn()`` for HTML themes is deprecated
|
||||
* ``env._nitpick_ignore`` is deprecated
|
||||
* ``app.override_domain()`` is deprecated
|
||||
* ``app.add_stylesheet()`` is deprecated
|
||||
* ``sphinx.versioning.prepare()`` is deprecated
|
||||
* ``Config.__init__()`` has changed; the *dirname*, *filename* and *tags*
|
||||
argument has been deprecated
|
||||
* ``Config.check_types()`` is deprecated
|
||||
@ -61,6 +70,11 @@ Features added
|
||||
* LaTeX: new key ``'fvset'`` for :confval:`latex_elements`. For
|
||||
XeLaTeX/LuaLaTeX its default sets ``fanvyvrb`` to use normal, not small,
|
||||
fontsize in code-blocks (refs: #4793)
|
||||
* Add :confval:`html_css_files` and :confval:`epub_css_files` for adding CSS
|
||||
files from configuration
|
||||
* #4834: Ensure set object descriptions are reproducible.
|
||||
* #4828: Allow to override :confval:`numfig_format` partially. Full definition
|
||||
is not needed.
|
||||
* Add ``Config.from_conf_py()`` classmethod to create a new config object from
|
||||
configuration file
|
||||
|
||||
@ -95,6 +109,23 @@ Features added
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #4769: autodoc loses the first staticmethod parameter
|
||||
* #4790: autosummary: too wide two column tables in PDF builds
|
||||
* #4795: Latex customization via ``_templates/longtable.tex_t`` is broken
|
||||
* #4789: imgconverter: confused by convert.exe of Windows
|
||||
* #4783: On windows, Sphinx crashed when drives of srcdir and outdir are
|
||||
different
|
||||
* #4812: autodoc ignores type annotated variables
|
||||
* #4817: wrong URLs on warning messages
|
||||
* #4784: latex: :confval:`latex_show_urls` assigns incorrect footnote numbers if
|
||||
hyperlinks exists inside substitutions
|
||||
* #4837: latex with class memoir Error: Font command ``\sf`` is not supported
|
||||
* #4803: latex: too slow in proportion to number of auto numbered footnotes
|
||||
* #4838: htmlhelp: The entries in .hhp file is not ordered
|
||||
* toctree directive tries to glob for URL having query_string
|
||||
* #4871: html search: Upper characters problem in German
|
||||
* #4717: latex: Compilation for German docs failed with LuaLaTeX and XeLaTeX
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
@ -128,6 +159,7 @@ Bugs fixed
|
||||
* #1435: qthelp builder should htmlescape keywords
|
||||
* epub: Fix docTitle elements of toc.ncx is not escaped
|
||||
* #4520: apidoc: Subpackage not in toc (introduced in 1.6.6) now fixed
|
||||
* #4767: html: search highlighting breaks mathjax equations
|
||||
|
||||
Release 1.7.1 (released Feb 23, 2018)
|
||||
=====================================
|
||||
@ -203,6 +235,8 @@ Incompatible changes
|
||||
(refs: #4295)
|
||||
* #4246: Limit width of text body for all themes. Conifigurable via theme
|
||||
options ``body_min_width`` and ``body_max_width``.
|
||||
* #4771: apidoc: The ``exclude_patterns`` arguments are ignored if they are
|
||||
placed just after command line options
|
||||
|
||||
1.7.0b2
|
||||
|
||||
|
2
EXAMPLES
2
EXAMPLES
@ -317,7 +317,7 @@ Documentation using a custom theme or integrated in a website
|
||||
* PSI4: http://www.psicode.org/psi4manual/master/index.html
|
||||
* PyMOTW: https://pymotw.com/2/
|
||||
* python-aspectlib: https://python-aspectlib.readthedocs.io/
|
||||
(`sphinx_py3doc_enhanced_theme <https://pypi.python.org/pypi/sphinx_py3doc_enhanced_theme>`__)
|
||||
(`sphinx_py3doc_enhanced_theme <https://pypi.org/project/sphinx_py3doc_enhanced_theme/>`__)
|
||||
* QGIS: https://qgis.org/en/docs/index.html
|
||||
* qooxdoo: http://www.qooxdoo.org/current/
|
||||
* Roundup: http://www.roundup-tracker.org/
|
||||
|
@ -3,7 +3,7 @@
|
||||
========
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/sphinx.svg
|
||||
:target: https://pypi.python.org/pypi/Sphinx
|
||||
:target: https://pypi.org/project/Sphinx/
|
||||
:alt: Package on PyPi
|
||||
|
||||
.. image:: https://readthedocs.org/projects/sphinx/badge/
|
||||
@ -71,7 +71,7 @@ We also publish beta releases::
|
||||
If you wish to install `Sphinx` for development purposes, refer to `the
|
||||
contributors guide`__.
|
||||
|
||||
__ https://pypi.python.org/pypi/Sphinx
|
||||
__ https://pypi.org/project/Sphinx/
|
||||
__ http://www.sphinx-doc.org/en/master/devguide.html
|
||||
|
||||
Documentation
|
||||
|
4
doc/_templates/indexsidebar.html
vendored
4
doc/_templates/indexsidebar.html
vendored
@ -8,11 +8,11 @@
|
||||
not released yet.{%endtrans%}</p>
|
||||
<p>{%trans%}You can use it from the
|
||||
<a href="https://github.com/sphinx-doc/sphinx/">Git repo</a> or look for
|
||||
released versions in the <a href="https://pypi.python.org/pypi/Sphinx">Python
|
||||
released versions in the <a href="https://pypi.org/project/Sphinx/">Python
|
||||
Package Index</a>.{%endtrans%}</p>
|
||||
{% else %}
|
||||
<p>{%trans%}Current version: <b><a href="changes.html">{{ version }}</a></b>{%endtrans%}</p>
|
||||
<p>{%trans%}Get Sphinx from the <a href="https://pypi.python.org/pypi/Sphinx">Python Package
|
||||
<p>{%trans%}Get Sphinx from the <a href="https://pypi.org/project/Sphinx/">Python Package
|
||||
Index</a>, or install it with:{%endtrans%}</p>
|
||||
<pre>pip install -U Sphinx</pre>
|
||||
{% endif %}
|
||||
|
2
doc/_themes/sphinx13/layout.html
vendored
2
doc/_themes/sphinx13/layout.html
vendored
@ -70,7 +70,7 @@
|
||||
<div class="pageheader">
|
||||
<ul>
|
||||
<li><a href="{{ pathto('index') }}">Home</a></li>
|
||||
<li><a href="{{ pathto('install') }}">Get it</a></li>
|
||||
<li><a href="{{ pathto('usage/installation') }}">Get it</a></li>
|
||||
<li><a href="{{ pathto('contents') }}">Docs</a></li>
|
||||
<li><a href="{{ pathto('develop') }}">Extend/Develop</a></li>
|
||||
</ul>
|
||||
|
@ -155,36 +155,30 @@ The builder's "name" must be given to the **-b** command-line option of
|
||||
configuration values that customize the output of this builder, see the
|
||||
chapter :ref:`latex-options` for details.
|
||||
|
||||
The produced LaTeX file uses several LaTeX packages that may not be present
|
||||
in a "minimal" TeX distribution installation. For example, on Ubuntu, the
|
||||
following packages need to be installed for successful PDF builds:
|
||||
|
||||
* texlive-latex-recommended
|
||||
* texlive-fonts-recommended
|
||||
* texlive-latex-extra
|
||||
* latexmk (for ``make latexpdf`` on GNU/Linux and MacOS X)
|
||||
* latex-xcolor (old Ubuntu)
|
||||
* texlive-luatex, texlive-xetex (see :confval:`latex_engine`)
|
||||
|
||||
The testing of Sphinx LaTeX is done on Ubuntu trusty with the above
|
||||
mentioned packages, which are from a TeXLive 2013 snapshot dated
|
||||
February 2014.
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
Formerly, testing had been done on Ubuntu precise (TeXLive 2009).
|
||||
|
||||
.. note::
|
||||
|
||||
The produced LaTeX file uses several LaTeX packages that may not be
|
||||
present in a "minimal" TeX distribution installation. For example, on
|
||||
Ubuntu, the following packages need to be installed for successful PDF
|
||||
builds:
|
||||
|
||||
* texlive-latex-recommended
|
||||
* texlive-fonts-recommended
|
||||
* texlive-latex-extra
|
||||
* latexmk (for ``make latexpdf``)
|
||||
|
||||
Sphinx will use ``xcolor.sty`` if present: recent Ubuntu distributions
|
||||
have ``xcolor.sty`` included in latex-recommended, earlier ones have it
|
||||
in latex-xcolor. Unicode engines will need texlive-luatex or
|
||||
texlive-xetex.
|
||||
|
||||
The testing of Sphinx LaTeX is done on Ubuntu trusty with the above
|
||||
mentioned packages, which are from a TeXLive 2013 snapshot dated
|
||||
February 2014.
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
Formerly, testing had been done for some years on Ubuntu precise
|
||||
(based on TeXLive 2009).
|
||||
.. versionchanged:: 1.6
|
||||
Use of ``latexmk`` for ``make latexpdf`` on GNU/Linux and Mac OS X
|
||||
|
||||
Since 1.6, ``make latexpdf`` (or
|
||||
``make -C "<builddir>/latex"`` after a ``sphinx-build`` run) uses
|
||||
``latexmk`` (not on Windows).
|
||||
Since 1.6, ``make latexpdf`` uses ``latexmk`` (not on Windows). This
|
||||
makes sure the needed number of runs is automatically executed to get
|
||||
the cross-references, bookmarks, indices, and tables of contents right.
|
||||
|
||||
One can pass to ``latexmk`` options via the ``LATEXMKOPTS``
|
||||
Makefile variable. For example:
|
||||
|
||||
@ -192,13 +186,22 @@ The builder's "name" must be given to the **-b** command-line option of
|
||||
|
||||
make latexpdf LATEXMKOPTS="-silent"
|
||||
|
||||
reduces console output to a minimum. Also, if ``latexmk`` version is
|
||||
4.52b or higher (Jan 17) and ``xelatex`` is the :confval:`latex_engine`,
|
||||
then ``LATEXMKOPTS="-xelatex"`` will speed up PDF builds.
|
||||
reduces console output to a minimum.
|
||||
|
||||
To pass options directly to the
|
||||
``(pdf|xe|lua)latex`` executable, use variable ``LATEXOPTS`` (for example
|
||||
``LATEXOPTS="--interaction=nonstopmode"``).
|
||||
Also, if ``latexmk`` version is 4.52b or higher (Jan 17)
|
||||
``LATEXMKOPTS="-xelatex"`` will speed up PDF builds via XeLateX in case
|
||||
of numerous graphics inclusions.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
make latexpdf LATEXMKOPTS="-xelatex"
|
||||
|
||||
To pass options directly to the ``(pdf|xe|lua)latex`` executable, use
|
||||
variable ``LATEXOPTS``.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
make latexpdf LATEXOPTS="--interaction=nonstopmode"
|
||||
|
||||
.. autoattribute:: name
|
||||
|
||||
@ -285,7 +288,7 @@ name is ``rinoh``. Refer to the `rinohtype manual`_ for details.
|
||||
globalcontext_filename = 'globalcontext.phpdump'
|
||||
searchindex_filename = 'searchindex.phpdump'
|
||||
|
||||
.. _PHP serialization: https://pypi.python.org/pypi/phpserialize
|
||||
.. _PHP serialization: https://pypi.org/project/phpserialize/
|
||||
|
||||
.. attribute:: implementation
|
||||
|
||||
|
@ -39,7 +39,7 @@ epub_uid = 'web-site'
|
||||
epub_scheme = 'url'
|
||||
epub_identifier = epub_publisher
|
||||
epub_pre_files = [('index.xhtml', 'Welcome')]
|
||||
epub_post_files = [('install.xhtml', 'Installing Sphinx'),
|
||||
epub_post_files = [('usage/installation.xhtml', 'Installing Sphinx'),
|
||||
('develop.xhtml', 'Sphinx development')]
|
||||
epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
|
||||
'_static/jquery.js', '_static/searchtools.js',
|
||||
@ -56,9 +56,14 @@ latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
|
||||
'Georg Brandl', 'manual', 1)]
|
||||
latex_logo = '_static/sphinx.png'
|
||||
latex_elements = {
|
||||
'fontpkg': '\\usepackage{palatino}',
|
||||
'fontpkg': r'''
|
||||
\usepackage[sc]{mathpazo}
|
||||
\usepackage[scaled]{helvet}
|
||||
\usepackage{courier}
|
||||
''',
|
||||
'passoptionstopackages': '\\PassOptionsToPackage{svgnames}{xcolor}',
|
||||
'preamble': '\\DeclareUnicodeCharacter{229E}{\\ensuremath{\\boxplus}}',
|
||||
'fvset': '\\fvset{fontsize=auto}',
|
||||
# fix missing index entry due to RTD doing only once pdflatex after makeindex
|
||||
'printindex': r'''
|
||||
\IfFileExists{\jobname.ind}
|
||||
|
@ -59,9 +59,6 @@ Important points to note:
|
||||
Note that the current builder tag is not available in ``conf.py``, as it is
|
||||
created *after* the builder is initialized.
|
||||
|
||||
.. seealso:: Additional configurations, such as adding stylesheets,
|
||||
javascripts, builders, etc. can be made through the :doc:`/extdev/appapi`.
|
||||
|
||||
|
||||
General configuration
|
||||
---------------------
|
||||
@ -195,8 +192,9 @@ General configuration
|
||||
.. index:: pair: global; substitutions
|
||||
|
||||
A string of reStructuredText that will be included at the end of every source
|
||||
file that is read. This is the right place to add substitutions that should
|
||||
be available in every file. An example::
|
||||
file that is read. This is a possible place to add substitutions that should
|
||||
be available in every file (another being :confval:`rst_prolog`). An
|
||||
example::
|
||||
|
||||
rst_epilog = """
|
||||
.. |psf| replace:: Python Software Foundation
|
||||
@ -206,8 +204,16 @@ General configuration
|
||||
|
||||
.. confval:: rst_prolog
|
||||
|
||||
.. index:: pair: global; substitutions
|
||||
|
||||
A string of reStructuredText that will be included at the beginning of every
|
||||
source file that is read.
|
||||
source file that is read. This is a possible place to add substitutions that
|
||||
should be available in every file (another being :confval:`rst_epilog`). An
|
||||
example::
|
||||
|
||||
rst_prolog = """
|
||||
.. |psf| replace:: Python Software Foundation
|
||||
"""
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
@ -846,6 +852,22 @@ that use Sphinx's HTMLWriter class.
|
||||
The image file will be copied to the ``_static`` directory of the output
|
||||
HTML, but only if the file does not already exist there.
|
||||
|
||||
.. confval:: html_css_files
|
||||
|
||||
A list of CSS files. The entry must be a *filename* string or a tuple
|
||||
containing the *filename* string and the *attributes* dictionary. The
|
||||
*filename* must be relative to the :confval:`html_static_path`, or a full URI
|
||||
with scheme like ``http://example.org/style.css``. The *attributes* is used
|
||||
for attributes of ``<link>`` tag. It defaults to an empty list.
|
||||
|
||||
Example::
|
||||
|
||||
html_css_files = ['custom.css'
|
||||
'https://example.com/css/custom.css',
|
||||
('print.css', {'media': 'print'})]
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. confval:: html_static_path
|
||||
|
||||
A list of paths that contain custom static files (such as style
|
||||
@ -1125,8 +1147,8 @@ that use Sphinx's HTMLWriter class.
|
||||
Sphinx uses a Python implementation by default. You can use a C
|
||||
implementation to accelerate building the index file.
|
||||
|
||||
* `PorterStemmer <https://pypi.python.org/pypi/PorterStemmer>`_ (``en``)
|
||||
* `PyStemmer <https://pypi.python.org/pypi/PyStemmer>`_ (all languages)
|
||||
* `PorterStemmer <https://pypi.org/project/PorterStemmer/>`_ (``en``)
|
||||
* `PyStemmer <https://pypi.org/project/PyStemmer/>`_ (all languages)
|
||||
|
||||
.. versionadded:: 1.1
|
||||
With support for ``en`` and ``ja``.
|
||||
@ -1158,7 +1180,7 @@ that use Sphinx's HTMLWriter class.
|
||||
library ('libmecab.so' for linux, 'libmecab.dll' for windows) is required.
|
||||
:'sphinx.search.ja.JanomeSplitter':
|
||||
Janome binding. To use this splitter,
|
||||
`Janome <https://pypi.python.org/pypi/Janome>`_ is required.
|
||||
`Janome <https://pypi.org/project/Janome/>`_ is required.
|
||||
|
||||
To keep compatibility, ``'mecab'``, ``'janome'`` and ``'default'`` are also
|
||||
acceptable. However it will be deprecated in Sphinx-1.6.
|
||||
@ -1511,6 +1533,14 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
.. confval:: epub_css_files
|
||||
|
||||
A list of CSS files. The entry must be a *filename* string or a tuple
|
||||
containing the *filename* string and the *attributes* dictionary. For more
|
||||
information, see :confval:`html_css_files`.
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. confval:: epub_guide
|
||||
|
||||
Meta data for the guide element of :file:`content.opf`. This is a
|
||||
@ -1837,8 +1867,15 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
``'lualatex'`` uses same default setting as ``'xelatex'``
|
||||
``'fontpkg'``
|
||||
Font package inclusion, default ``'\\usepackage{times}'`` (which uses
|
||||
Times and Helvetica). You can set this to ``''`` to use the Computer
|
||||
Modern fonts.
|
||||
Times for text, Helvetica for sans serif and Courier for code-blocks).
|
||||
|
||||
.. hint::
|
||||
|
||||
Courier is much wider than Times, and Sphinx emits LaTeX command
|
||||
``\small`` in code-blocks to compensate. Since ``1.5`` this is not
|
||||
hard-coded anymore: ``\fvset{fontsize=auto}`` can be added to
|
||||
preamble to not change font size in code-blocks. Since ``1.8`` a
|
||||
separate ``'fvset'`` key is provided for this.
|
||||
|
||||
.. versionchanged:: 1.2
|
||||
Defaults to ``''`` when the :confval:`language` uses the Cyrillic
|
||||
@ -1847,6 +1884,8 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
Defaults to ``''`` when :confval:`latex_engine` is ``'xelatex'``.
|
||||
.. versionchanged:: 1.6
|
||||
Defaults to ``''`` also with ``'lualatex'``.
|
||||
.. versionchanged:: 1.8
|
||||
``'xelatex'`` and ``'lualatex'`` do ``\fvset{fontsize=auto}``.
|
||||
``'fncychap'``
|
||||
Inclusion of the "fncychap" package (which makes fancy chapter titles),
|
||||
default ``'\\usepackage[Bjarne]{fncychap}'`` for English documentation
|
||||
|
@ -141,5 +141,5 @@ own extensions.
|
||||
.. _inlinesyntaxhighlight: https://sphinxcontrib-inlinesyntaxhighlight.readthedocs.io/
|
||||
.. _CMake: https://cmake.org
|
||||
.. _domaintools: https://bitbucket.org/klorenz/sphinxcontrib-domaintools
|
||||
.. _restbuilder: https://pypi.python.org/pypi/sphinxcontrib-restbuilder
|
||||
.. _restbuilder: https://pypi.org/project/sphinxcontrib-restbuilder/
|
||||
.. _Lasso: http://www.lassosoft.com/
|
||||
|
@ -1,7 +1,9 @@
|
||||
.. highlight:: rest
|
||||
|
||||
:mod:`sphinx.ext.imgconverter` -- Convert images to appropriate format for builders
|
||||
===================================================================================
|
||||
.. _sphinx.ext.imgconverter:
|
||||
|
||||
:mod:`sphinx.ext.imgconverter` -- A reference implementation for image converter using Imagemagick
|
||||
==================================================================================================
|
||||
|
||||
.. module:: sphinx.ext.imgconverter
|
||||
:synopsis: Convert images to appropriate format for builders
|
||||
@ -16,6 +18,12 @@ Internally, this extension uses Imagemagick_ to convert images.
|
||||
|
||||
.. _Imagemagick: https://www.imagemagick.org/script/index.php
|
||||
|
||||
.. note:: Imagemagick rasterizes a SVG image on conversion. As a result, the image
|
||||
becomes not scalable. To avoid that, please use other image converters
|
||||
like sphinxcontrib-svg2pdfconverter_ (which uses Inkscape or rsvg-convert).
|
||||
|
||||
.. _sphinxcontrib-svg2pdfconverter: https://github.com/missinglinkelectronics/sphinxcontrib-svg2pdfconverter
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
|
@ -94,6 +94,7 @@ APIs used for writing extensions
|
||||
nodes
|
||||
logging
|
||||
i18n
|
||||
utils
|
||||
|
||||
Deprecated APIs
|
||||
---------------
|
||||
@ -113,6 +114,11 @@ The following is a list of deprecated interface.
|
||||
- (will be) Removed
|
||||
- Alternatives
|
||||
|
||||
* - :meth:`~sphinx.application.Sphinx.add_stylesheet()`
|
||||
- 1.8
|
||||
- 4.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_css_file()`
|
||||
|
||||
* - ``Config.check_unicode()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
@ -129,6 +135,11 @@ The following is a list of deprecated interface.
|
||||
- 3.0
|
||||
- ``Config.from_conf_py()``
|
||||
|
||||
* - ``sphinx.versioning.prepare()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.versioning.UIDTransform``
|
||||
|
||||
* - ``sphinx.application.Sphinx.override_domain()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
@ -278,13 +289,18 @@ The following is a list of deprecated interface.
|
||||
* - ``sphinx.websupport``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- `sphinxcontrib-websupport <https://pypi.python.org/pypi/sphinxcontrib-websupport>`_
|
||||
- `sphinxcontrib-websupport <https://pypi.org/project/sphinxcontrib-websupport/>`_
|
||||
|
||||
* - ``StandaloneHTMLBuilder.css_files``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_stylesheet()`
|
||||
|
||||
* - ``document.settings.gettext_compact``
|
||||
- 1.8
|
||||
- 1.8
|
||||
- :confval:`gettext_compact`
|
||||
|
||||
* - ``Sphinx.status_iterator()``
|
||||
- 1.6
|
||||
- 1.7
|
||||
|
22
doc/extdev/utils.rst
Normal file
22
doc/extdev/utils.rst
Normal file
@ -0,0 +1,22 @@
|
||||
Utilities
|
||||
=========
|
||||
|
||||
Sphinx provides utility classes and functions to develop extensions.
|
||||
|
||||
Base classes for components
|
||||
---------------------------
|
||||
|
||||
These base classes are useful to allow your extensions to obtain Sphinx
|
||||
components (e.g. :class:`.Config`, :class:`.BuildEnvironment` and so on) easily.
|
||||
|
||||
.. note:: The subclasses of them might not work with bare docutils because they
|
||||
are strongly coupled with Sphinx.
|
||||
|
||||
.. autoclass:: sphinx.transforms.SphinxTransform
|
||||
:members:
|
||||
|
||||
.. autoclass:: sphinx.util.docutils.SphinxDirective
|
||||
:members:
|
||||
|
||||
.. autoclass:: sphinx.transforms.post_transforms.images.ImageConverter
|
||||
:members:
|
@ -23,7 +23,7 @@ How do I...
|
||||
Use themes, see :doc:`theming`.
|
||||
|
||||
... add global substitutions or includes?
|
||||
Add them in the :confval:`rst_epilog` config value.
|
||||
Add them in the :confval:`rst_prolog` or :confval:`rst_epilog` config value.
|
||||
|
||||
... display the whole TOC tree in the sidebar?
|
||||
Use the :data:`toctree` callable in a custom layout template, probably in the
|
||||
@ -72,7 +72,7 @@ SCons
|
||||
|
||||
PyPI
|
||||
Jannis Leidel wrote a `setuptools command
|
||||
<https://pypi.python.org/pypi/Sphinx-PyPI-upload>`_ that automatically
|
||||
<https://pypi.org/project/Sphinx-PyPI-upload/>`_ that automatically
|
||||
uploads Sphinx documentation to the PyPI package documentation area at
|
||||
https://pythonhosted.org/.
|
||||
|
||||
|
12
doc/intl.rst
12
doc/intl.rst
@ -207,7 +207,7 @@ easy to fetch and push translations.
|
||||
|
||||
$ pip install transifex-client
|
||||
|
||||
.. seealso:: `Transifex Client v0.8 — Transifex documentation`_
|
||||
.. seealso:: `Transifex Client documentation`_
|
||||
|
||||
|
||||
#. Create your transifex_ account and create new project for your document
|
||||
@ -305,7 +305,7 @@ Contributing to Sphinx reference translation
|
||||
The recommended way for new contributors to translate Sphinx reference
|
||||
is to join the translation team on Transifex.
|
||||
|
||||
There is `sphinx translation page`_ for Sphinx-1.3 documentation.
|
||||
There is `sphinx translation page`_ for Sphinx (master) documentation.
|
||||
|
||||
1. Login to transifex_ service.
|
||||
2. Go to `sphinx translation page`_.
|
||||
@ -322,8 +322,8 @@ There is `sphinx translation page`_ for Sphinx-1.3 documentation.
|
||||
.. [2] Because nobody expects the Spanish Inquisition!
|
||||
|
||||
|
||||
.. _`transifex-client`: https://pypi.python.org/pypi/transifex-client
|
||||
.. _`sphinx-intl`: https://pypi.python.org/pypi/sphinx-intl
|
||||
.. _`transifex-client`: https://pypi.org/project/transifex-client/
|
||||
.. _`sphinx-intl`: https://pypi.org/project/sphinx-intl/
|
||||
.. _Transifex: https://www.transifex.com/
|
||||
.. _`sphinx translation page`: https://www.transifex.com/sphinx-doc/sphinx-doc-1_3/
|
||||
.. _`Transifex Client v0.8 — Transifex documentation`: https://docs.transifex.com/client/introduction/
|
||||
.. _`sphinx translation page`: https://www.transifex.com/sphinx-doc/sphinx-doc/
|
||||
.. _`Transifex Client documentation`: http://docs.transifex.com/developer/client/
|
||||
|
@ -29,7 +29,7 @@ This section is intended to collect helpful hints for those wanting to migrate
|
||||
to reStructuredText/Sphinx from other documentation systems.
|
||||
|
||||
* Gerard Flanagan has written a script to convert pure HTML to reST; it can be
|
||||
found at the `Python Package Index <https://pypi.python.org/pypi/html2rest>`_.
|
||||
found at the `Python Package Index <https://pypi.org/project/html2rest/>`_.
|
||||
|
||||
* For converting the old Python docs to Sphinx, a converter was written which
|
||||
can be found at `the Python SVN repository
|
||||
@ -40,7 +40,7 @@ to reStructuredText/Sphinx from other documentation systems.
|
||||
markup; it is at `GitHub <https://github.com/wojdyr/db2rst>`_.
|
||||
|
||||
* Christophe de Vienne wrote a tool to convert from Open/LibreOffice documents
|
||||
to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_.
|
||||
to Sphinx: `odt2sphinx <https://pypi.org/project/odt2sphinx/>`_.
|
||||
|
||||
* To convert different markups, `Pandoc <https://pandoc.org/>`_ is
|
||||
a very helpful tool.
|
||||
|
@ -8,8 +8,8 @@ LaTeX customization
|
||||
.. module:: latex
|
||||
:synopsis: LaTeX specifics.
|
||||
|
||||
The *latex* target does not benefit from pre-prepared themes like the
|
||||
*html* target does (see :doc:`theming`).
|
||||
For details of the LaTeX/PDF builder command line invocation, refer to
|
||||
:py:class:`~sphinx.builders.latex.LaTeXBuilder`.
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
@ -34,8 +34,10 @@ The *latex* target does not benefit from pre-prepared themes like the
|
||||
Basic customization
|
||||
-------------------
|
||||
|
||||
It is achieved via usage of the
|
||||
:ref:`latex-options` as described in :doc:`config`. For example::
|
||||
The *latex* target does not benefit from prepared themes.
|
||||
|
||||
Basic customization is obtained via usage of the :ref:`latex-options`. For
|
||||
example::
|
||||
|
||||
# inside conf.py
|
||||
latex_engine = 'xelatex'
|
||||
@ -69,7 +71,7 @@ repertory, and get LaTeX to import it at run time::
|
||||
# or, if the \ProvidesPackage LaTeX macro is used in a file mystyle.sty
|
||||
'preamble': r'\usepackage{mystyle}',
|
||||
|
||||
It is needed to set appropriately :confval:`latex_additional_files`, for
|
||||
It is then needed to set appropriately :confval:`latex_additional_files`, for
|
||||
example::
|
||||
|
||||
latex_additional_files = ["mystyle.sty"]
|
||||
@ -79,11 +81,14 @@ example::
|
||||
The LaTeX style file options
|
||||
----------------------------
|
||||
|
||||
Additional customization is possible via LaTeX options of the Sphinx style
|
||||
file.
|
||||
|
||||
The sphinxsetup interface
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``'sphinxsetup'`` key of :confval:`latex_elements` provides a convenient
|
||||
interface to the package options of the Sphinx style file::
|
||||
interface::
|
||||
|
||||
latex_elements = {
|
||||
'sphinxsetup': 'key1=value1, key2=value2, ...',
|
||||
@ -103,40 +108,39 @@ inside the document preamble, like this::
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
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`
|
||||
directive. This is what is done for this documentation, for local styling
|
||||
of this chapter in the PDF output::
|
||||
.. hint::
|
||||
|
||||
.. raw:: latex
|
||||
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`
|
||||
directive. Here is how this present chapter in PDF is styled::
|
||||
|
||||
\begingroup
|
||||
\sphinxsetup{%
|
||||
verbatimwithframe=false,
|
||||
VerbatimColor={named}{OldLace},
|
||||
TitleColor={named}{DarkGoldenrod},
|
||||
hintBorderColor={named}{LightCoral},
|
||||
attentionborder=3pt,
|
||||
attentionBorderColor={named}{Crimson},
|
||||
attentionBgColor={named}{FloralWhite},
|
||||
noteborder=2pt,
|
||||
noteBorderColor={named}{Olive},
|
||||
cautionborder=3pt,
|
||||
cautionBorderColor={named}{Cyan},
|
||||
cautionBgColor={named}{LightCyan}}
|
||||
.. raw:: latex
|
||||
|
||||
at the start of the chapter and::
|
||||
\begingroup
|
||||
\sphinxsetup{%
|
||||
verbatimwithframe=false,
|
||||
VerbatimColor={named}{OldLace},
|
||||
TitleColor={named}{DarkGoldenrod},
|
||||
hintBorderColor={named}{LightCoral},
|
||||
attentionborder=3pt,
|
||||
attentionBorderColor={named}{Crimson},
|
||||
attentionBgColor={named}{FloralWhite},
|
||||
noteborder=2pt,
|
||||
noteBorderColor={named}{Olive},
|
||||
cautionborder=3pt,
|
||||
cautionBorderColor={named}{Cyan},
|
||||
cautionBgColor={named}{LightCyan}}
|
||||
|
||||
.. raw:: latex
|
||||
at the start of the chapter and::
|
||||
|
||||
\endgroup
|
||||
.. raw:: latex
|
||||
|
||||
at its end.
|
||||
\endgroup
|
||||
|
||||
.. note::
|
||||
at its end.
|
||||
|
||||
The colors above are made available via the ``svgnames`` option of
|
||||
the "xcolor" package::
|
||||
The colors used in the above are provided by the ``svgnames`` option of the
|
||||
"xcolor" package::
|
||||
|
||||
latex_elements = {
|
||||
'passoptionstopackages': r'\PassOptionsToPackage{svgnames}{xcolor}',
|
||||
@ -465,7 +469,6 @@ Miscellany
|
||||
.. versionchanged:: 1.5
|
||||
formerly, use of *fncychap* with other styles than ``Bjarne`` was
|
||||
dysfunctional.
|
||||
- check file :file:`sphinx.sty` for more...
|
||||
|
||||
.. hint::
|
||||
|
||||
|
@ -15,8 +15,10 @@ style of other automatic API documentation tools.
|
||||
|
||||
*MODULE_PATH* is the path to a Python package to document, and *OUTPUT_PATH* is
|
||||
the directory where the generated sources are placed. Any *EXCLUDE_PATTERN*\s
|
||||
given are `fnmatch-style <fnmatch>`_ file and/or directory patterns that will
|
||||
be excluded from generation.
|
||||
given are `fnmatch-style`_ file and/or directory patterns that will be excluded
|
||||
from generation.
|
||||
|
||||
.. _fnmatch-style: https://docs.python.org/3/library/fnmatch.html
|
||||
|
||||
.. warning::
|
||||
|
||||
|
@ -134,7 +134,7 @@ These themes are:
|
||||
Check out at its `installation page`_ how to set up properly
|
||||
:confval:`html_sidebars` for its use.
|
||||
|
||||
.. _Alabaster theme: https://pypi.python.org/pypi/alabaster
|
||||
.. _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
|
||||
@ -418,7 +418,7 @@ Third Party Themes
|
||||
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.python.org/pypi/sphinx_rtd_theme
|
||||
.. _Read the Docs Sphinx Theme: https://pypi.org/project/sphinx_rtd_theme/
|
||||
|
||||
.. versionchanged:: 1.4
|
||||
**sphinx_rtd_theme** has become optional.
|
||||
|
@ -7,6 +7,8 @@ Installing Sphinx
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
.. highlight:: console
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
@ -25,7 +27,7 @@ Debian/Ubuntu
|
||||
Install either ``python3-sphinx`` (Python 3) or ``python-sphinx`` (Python 2)
|
||||
using :command:`apt-get`:
|
||||
|
||||
.. code-block:: bash
|
||||
::
|
||||
|
||||
$ apt-get install python3-sphinx
|
||||
|
||||
@ -36,7 +38,7 @@ RHEL, CentOS
|
||||
|
||||
Install ``python-sphinx`` using :command:`yum`:
|
||||
|
||||
.. code-block:: bash
|
||||
::
|
||||
|
||||
$ yum install python-sphinx
|
||||
|
||||
@ -65,7 +67,7 @@ __ https://www.anaconda.com/download/#macos
|
||||
Homebrew
|
||||
~~~~~~~~
|
||||
|
||||
.. code-block:: bash
|
||||
::
|
||||
|
||||
$ brew install sphinx-doc
|
||||
|
||||
@ -79,13 +81,13 @@ MacPorts
|
||||
Install either ``python36-sphinx`` (Python 3) or ``python27-sphinx`` (Python 2)
|
||||
using :command:`port`:
|
||||
|
||||
.. code-block:: bash
|
||||
::
|
||||
|
||||
$ sudo port install py36-sphinx
|
||||
|
||||
To set up the executable paths, use the ``port select`` command:
|
||||
|
||||
.. code-block:: bash
|
||||
::
|
||||
|
||||
$ sudo port select --set python python36
|
||||
$ sudo port select --set sphinx py36-sphinx
|
||||
@ -97,7 +99,7 @@ __ https://www.macports.org/ports.php?by=library&substr=py36-sphinx
|
||||
Anaconda
|
||||
~~~~~~~~
|
||||
|
||||
.. code-block:: console
|
||||
::
|
||||
|
||||
$ conda install sphinx
|
||||
|
||||
@ -130,20 +132,20 @@ Installation from PyPI
|
||||
----------------------
|
||||
|
||||
Sphinx packages are published on the `Python Package Index
|
||||
<https://pypi.python.org/pypi/Sphinx>`_. The preferred tool for installing
|
||||
<https://pypi.org/project/Sphinx/>`_. The preferred tool for installing
|
||||
packages from *PyPI* is :command:`pip`. This tool is provided with all modern
|
||||
versions of Python.
|
||||
|
||||
On Linux or MacOS, you should open your terminal and run the following command.
|
||||
|
||||
.. code-block:: shell
|
||||
::
|
||||
|
||||
$ pip install -U sphinx
|
||||
|
||||
On Windows, you should open *Command Prompt* (:kbd:`⊞Win-r` and type
|
||||
:command:`cmd`) and run the same command.
|
||||
|
||||
.. code-block:: bat
|
||||
.. code-block:: doscon
|
||||
|
||||
C:\> pip install -U sphinx
|
||||
|
||||
@ -156,7 +158,7 @@ release. You will not generally need (or want) to do this, but it can be
|
||||
useful if you see a possible bug in the latest stable release. To do this, use
|
||||
the ``--pre`` flag.
|
||||
|
||||
.. code-block:: shell
|
||||
::
|
||||
|
||||
$ pip install -U --pre sphinx
|
||||
|
||||
@ -168,13 +170,13 @@ You can install Sphinx directly from a clone of the `Git repository`__. This
|
||||
can be done either by cloning the repo and installing from the local clone, on
|
||||
simply installing directly via :command:`git`.
|
||||
|
||||
.. code-block:: shell
|
||||
::
|
||||
|
||||
$ git clone https://github.com/sphinx-doc/sphinx
|
||||
$ cd sphinx
|
||||
$ pip install .
|
||||
|
||||
.. code-block:: shell
|
||||
::
|
||||
|
||||
$ pip install git+https://github.com/sphinx-doc/sphinx
|
||||
|
||||
@ -182,6 +184,8 @@ You can also download a snapshot of the Git repo in either `tar.gz`__ or
|
||||
`zip`__ format. Once downloaded and extracted, these can be installed with
|
||||
:command:`pip` as above.
|
||||
|
||||
.. highlight:: default
|
||||
|
||||
__ https://github.com/sphinx-doc/sphinx
|
||||
__ https://github.com/sphinx-doc/sphinx/archive/master.tar.gz
|
||||
__ https://github.com/sphinx-doc/sphinx/archive/master.zip
|
||||
|
@ -1,5 +1,7 @@
|
||||
.. highlightlang:: rst
|
||||
|
||||
.. _rst-primer:
|
||||
|
||||
=======================
|
||||
reStructuredText Primer
|
||||
=======================
|
||||
@ -506,11 +508,14 @@ or this::
|
||||
See the :duref:`reST reference for substitutions <substitution-definitions>`
|
||||
for details.
|
||||
|
||||
.. index:: ! pair: global; substitutions
|
||||
|
||||
If you want to use some substitutions for all documents, put them into
|
||||
:confval:`rst_prolog` or put them into a separate file and include it into all
|
||||
documents you want to use them in, using the :rst:dir:`include` directive. (Be
|
||||
sure to give the include file a file name extension differing from that of
|
||||
other source files, to avoid Sphinx finding it as a standalone document.)
|
||||
:confval:`rst_prolog` or :confval:`rst_epilog` or put them into a separate file
|
||||
and include it into all documents you want to use them in, using the
|
||||
:rst:dir:`include` directive. (Be sure to give the include file a file name
|
||||
extension differing from that of other source files, to avoid Sphinx finding it
|
||||
as a standalone document.)
|
||||
|
||||
Sphinx defines some default substitutions, see :ref:`default-substitutions`.
|
||||
|
||||
|
@ -596,7 +596,8 @@ __ http://pygments.org/docs/lexers/
|
||||
``start-after`` is given as a string option, only lines that follow the
|
||||
first line containing that string are included. If ``end-before`` is given
|
||||
as a string option, only lines that precede the first lines containing that
|
||||
string are included.
|
||||
string are included. The ``start-at`` and ``end-at`` options behave in a
|
||||
similar way, but the lines containing the matched string are included.
|
||||
|
||||
With lines selected using ``start-after`` it is still possible to use
|
||||
``lines``, the first allowed line having by convention the line number
|
||||
@ -638,6 +639,9 @@ __ http://pygments.org/docs/lexers/
|
||||
Added the ``diff``, ``lineno-match``, ``caption``, ``name``, and
|
||||
``dedent`` options.
|
||||
|
||||
.. versionchanged:: 1.5
|
||||
Added the ``start-at``, and ``end-at`` options.
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
With both ``start-after`` and ``lines`` in use, the first line as per
|
||||
``start-after`` is considered to be with line number ``1`` for ``lines``.
|
||||
|
@ -1287,18 +1287,18 @@ Jinja_, Operation_, and Scala_.
|
||||
|
||||
.. _sphinx-contrib: https://bitbucket.org/birkenfeld/sphinx-contrib/
|
||||
|
||||
.. _Ada: https://pypi.python.org/pypi/sphinxcontrib-adadomain
|
||||
.. _Chapel: https://pypi.python.org/pypi/sphinxcontrib-chapeldomain
|
||||
.. _CoffeeScript: https://pypi.python.org/pypi/sphinxcontrib-coffee
|
||||
.. _Common Lisp: https://pypi.python.org/pypi/sphinxcontrib-cldomain
|
||||
.. _dqn: https://pypi.python.org/pypi/sphinxcontrib-dqndomain
|
||||
.. _Erlang: https://pypi.python.org/pypi/sphinxcontrib-erlangdomain
|
||||
.. _Go: https://pypi.python.org/pypi/sphinxcontrib-golangdomain
|
||||
.. _HTTP: https://pypi.python.org/pypi/sphinxcontrib-httpdomain
|
||||
.. _Jinja: https://pypi.python.org/pypi/sphinxcontrib-jinjadomain
|
||||
.. _Lasso: https://pypi.python.org/pypi/sphinxcontrib-lassodomain
|
||||
.. _MATLAB: https://pypi.python.org/pypi/sphinxcontrib-matlabdomain
|
||||
.. _Operation: https://pypi.python.org/pypi/sphinxcontrib-operationdomain
|
||||
.. _PHP: https://pypi.python.org/pypi/sphinxcontrib-phpdomain
|
||||
.. _Ada: https://pypi.org/project/sphinxcontrib-adadomain/
|
||||
.. _Chapel: https://pypi.org/project/sphinxcontrib-chapeldomain/
|
||||
.. _CoffeeScript: https://pypi.org/project/sphinxcontrib-coffee/
|
||||
.. _Common Lisp: https://pypi.org/project/sphinxcontrib-cldomain/
|
||||
.. _dqn: https://pypi.org/project/sphinxcontrib-dqndomain/
|
||||
.. _Erlang: https://pypi.org/project/sphinxcontrib-erlangdomain/
|
||||
.. _Go: https://pypi.org/project/sphinxcontrib-golangdomain/
|
||||
.. _HTTP: https://pypi.org/project/sphinxcontrib-httpdomain/
|
||||
.. _Jinja: https://pypi.org/project/sphinxcontrib-jinjadomain/
|
||||
.. _Lasso: https://pypi.org/project/sphinxcontrib-lassodomain/
|
||||
.. _MATLAB: https://pypi.org/project/sphinxcontrib-matlabdomain/
|
||||
.. _Operation: https://pypi.org/project/sphinxcontrib-operationdomain/
|
||||
.. _PHP: https://pypi.org/project/sphinxcontrib-phpdomain/
|
||||
.. _Ruby: https://bitbucket.org/birkenfeld/sphinx-contrib/src/default/rubydomain
|
||||
.. _Scala: https://pypi.python.org/pypi/sphinxcontrib-scaladomain
|
||||
.. _Scala: https://pypi.org/project/sphinxcontrib-scaladomain/
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. _rst-index:
|
||||
|
||||
================
|
||||
reStructuredText
|
||||
================
|
||||
|
@ -40,9 +40,17 @@ The WebSupport Class
|
||||
comment that was added.
|
||||
|
||||
staticdir
|
||||
If static files are served from a location besides ``'/static'``, this
|
||||
should be a string with the name of that location
|
||||
(e.g. ``'/static_files'``).
|
||||
If the static files should be created in a different location
|
||||
**and not in** ``'/static'``, this should be a string with the name of
|
||||
that location (e.g. ``builddir + '/static_files'``).
|
||||
|
||||
.. note::
|
||||
If you specify ``staticdir``, you will typically want to adjust
|
||||
``staticroot`` accordingly.
|
||||
|
||||
staticroot
|
||||
If the static files are not served from ``'/static'``, this should be a
|
||||
string with the name of that location (e.g. ``'/static_files'``).
|
||||
|
||||
docroot
|
||||
If the documentation is not served from the base path of a URL, this
|
||||
|
15
setup.py
15
setup.py
@ -176,7 +176,7 @@ setup(
|
||||
name='Sphinx',
|
||||
version=sphinx.__version__,
|
||||
url='http://sphinx-doc.org/',
|
||||
download_url='https://pypi.python.org/pypi/Sphinx',
|
||||
download_url='https://pypi.org/project/Sphinx/',
|
||||
license='BSD',
|
||||
author='Georg Brandl',
|
||||
author_email='georg@python.org',
|
||||
@ -189,6 +189,9 @@ setup(
|
||||
'Environment :: Web Environment',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Education',
|
||||
'Intended Audience :: End Users/Desktop',
|
||||
'Intended Audience :: Science/Research',
|
||||
'Intended Audience :: System Administrators',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
@ -200,12 +203,22 @@ setup(
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: Implementation :: CPython',
|
||||
'Programming Language :: Python :: Implementation :: PyPy',
|
||||
'Framework :: Setuptools Plugin',
|
||||
'Framework :: Sphinx',
|
||||
'Framework :: Sphinx :: Extension',
|
||||
'Framework :: Sphinx :: Theme',
|
||||
'Topic :: Documentation',
|
||||
'Topic :: Documentation :: Sphinx',
|
||||
'Topic :: Internet :: WWW/HTTP :: Site Management',
|
||||
'Topic :: Printing',
|
||||
'Topic :: Software Development',
|
||||
'Topic :: Software Development :: Documentation',
|
||||
'Topic :: Text Processing',
|
||||
'Topic :: Text Processing :: General',
|
||||
'Topic :: Text Processing :: Indexing',
|
||||
'Topic :: Text Processing :: Markup',
|
||||
'Topic :: Text Processing :: Markup :: HTML',
|
||||
'Topic :: Text Processing :: Markup :: LaTeX',
|
||||
'Topic :: Utilities',
|
||||
],
|
||||
platforms='any',
|
||||
|
@ -27,7 +27,9 @@ from six.moves import cStringIO
|
||||
import sphinx
|
||||
from sphinx import package_dir, locale
|
||||
from sphinx.config import Config, check_unicode
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warning
|
||||
from sphinx.deprecation import (
|
||||
RemovedInSphinx20Warning, RemovedInSphinx30Warning, RemovedInSphinx40Warning
|
||||
)
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
|
||||
from sphinx.events import EventManager
|
||||
@ -41,7 +43,7 @@ from sphinx.util.build_phase import BuildPhase
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import directive_helper
|
||||
from sphinx.util.i18n import find_catalog_source_files
|
||||
from sphinx.util.osutil import abspath, ensuredir
|
||||
from sphinx.util.osutil import abspath, ensuredir, relpath
|
||||
from sphinx.util.tags import Tags
|
||||
|
||||
if False:
|
||||
@ -349,7 +351,7 @@ class Sphinx(object):
|
||||
if self.statuscode == 0 and self.builder.epilog:
|
||||
logger.info('')
|
||||
logger.info(self.builder.epilog % {
|
||||
'outdir': path.relpath(self.outdir),
|
||||
'outdir': relpath(self.outdir),
|
||||
'project': self.config.project
|
||||
})
|
||||
except Exception as err:
|
||||
@ -964,7 +966,30 @@ class Sphinx(object):
|
||||
Add the standard docutils :class:`Transform` subclass *transform* to
|
||||
the list of transforms that are applied after Sphinx parses a reST
|
||||
document.
|
||||
"""
|
||||
|
||||
.. list-table:: priority range categories for Sphinx transforms
|
||||
|
||||
* - Priority
|
||||
- Main purpose in Sphinx
|
||||
* - 0-99
|
||||
- Fix invalid nodes by docutils. Translate a doctree.
|
||||
* - 100-299
|
||||
- Preparation
|
||||
* - 300-399
|
||||
- early
|
||||
* - 400-699
|
||||
- main
|
||||
* - 700-799
|
||||
- Post processing. Deadline to modify text and referencing.
|
||||
* - 800-899
|
||||
- Collect referencing and referenced nodes. Domain processing.
|
||||
* - 900-999
|
||||
- Finalize and clean up.
|
||||
|
||||
refs: `Transform Priority Range Categories`__
|
||||
|
||||
__ http://docutils.sourceforge.net/docs/ref/transforms.html#transform-priority-range-categories
|
||||
""" # NOQA
|
||||
self.registry.add_transform(transform)
|
||||
|
||||
def add_post_transform(self, transform):
|
||||
@ -997,13 +1022,27 @@ class Sphinx(object):
|
||||
StandaloneHTMLBuilder.script_files.append(
|
||||
posixpath.join('_static', filename))
|
||||
|
||||
def add_stylesheet(self, filename, alternate=False, title=None):
|
||||
# type: (unicode, bool, unicode) -> None
|
||||
def add_css_file(self, filename, **kwargs):
|
||||
# type: (unicode, **unicode) -> None
|
||||
"""Register a stylesheet to include in the HTML output.
|
||||
|
||||
Add *filename* to the list of CSS files that the default HTML template
|
||||
will include. Like for :meth:`add_javascript`, the filename must be
|
||||
relative to the HTML static path, or a full URI with scheme.
|
||||
will include. The filename must be relative to the HTML static path,
|
||||
or a full URI with scheme. The keyword arguments are also accepted for
|
||||
attributes of ``<link>`` tag.
|
||||
|
||||
Example::
|
||||
|
||||
app.add_css_file('custom.css')
|
||||
# => <link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
app.add_css_file('print.css', media='print')
|
||||
# => <link rel="stylesheet" href="_static/print.css"
|
||||
# type="text/css" media="print" />
|
||||
|
||||
app.add_css_file('fancy.css', rel='alternate stylesheet', title='fancy')
|
||||
# => <link rel="alternate stylesheet" href="_static/fancy.css"
|
||||
# type="text/css" title="fancy" />
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
@ -1013,17 +1052,33 @@ class Sphinx(object):
|
||||
arguments. The default is no title and *alternate* = ``False``. For
|
||||
more information, refer to the `documentation
|
||||
<https://mdn.io/Web/CSS/Alternative_style_sheets>`__.
|
||||
|
||||
.. versionchanged:: 1.8
|
||||
Renamed from ``app.add_stylesheet()``.
|
||||
And it allows keyword arguments as attributes of link tag.
|
||||
"""
|
||||
logger.debug('[app] adding stylesheet: %r', filename)
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder, Stylesheet
|
||||
if '://' not in filename:
|
||||
filename = posixpath.join('_static', filename)
|
||||
self.registry.add_css_files(filename, **kwargs)
|
||||
|
||||
def add_stylesheet(self, filename, alternate=False, title=None):
|
||||
# type: (unicode, bool, unicode) -> None
|
||||
"""An alias of :meth:`add_css_file`."""
|
||||
warnings.warn('The app.add_stylesheet() is deprecated. '
|
||||
'Please use app.add_css_file() instead.',
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
attributes = {} # type: Dict[unicode, unicode]
|
||||
if alternate:
|
||||
rel = u'alternate stylesheet'
|
||||
attributes['rel'] = 'alternate stylesheet'
|
||||
else:
|
||||
rel = u'stylesheet'
|
||||
css = Stylesheet(filename, title, rel) # type: ignore
|
||||
StandaloneHTMLBuilder.css_files.append(css)
|
||||
attributes['rel'] = 'stylesheet'
|
||||
|
||||
if title:
|
||||
attributes['title'] = title
|
||||
|
||||
self.add_css_file(filename, **attributes)
|
||||
|
||||
def add_latex_package(self, packagename, options=None):
|
||||
# type: (unicode, unicode) -> None
|
||||
|
@ -23,7 +23,7 @@ from sphinx.util import i18n, import_object, logging, status_iterator
|
||||
from sphinx.util.build_phase import BuildPhase
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.i18n import find_catalog
|
||||
from sphinx.util.osutil import SEP, ensuredir, relative_uri
|
||||
from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
|
||||
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
|
||||
parallel_available
|
||||
|
||||
@ -242,7 +242,7 @@ class Builder(object):
|
||||
|
||||
def cat2relpath(cat):
|
||||
# type: (CatalogInfo) -> unicode
|
||||
return path.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)
|
||||
for catalog in status_iterator(catalogs, __('writing output... '), "darkgreen",
|
||||
|
@ -708,9 +708,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
"""
|
||||
logger.info(__('writing %s file...'), outname)
|
||||
epub_filename = path.join(outdir, outname)
|
||||
with ZipFile(epub_filename, 'w', ZIP_DEFLATED) as epub: # type: ignore
|
||||
epub.write(path.join(outdir, 'mimetype'), 'mimetype', ZIP_STORED) # type: ignore
|
||||
with ZipFile(epub_filename, 'w', ZIP_DEFLATED) as epub:
|
||||
epub.write(path.join(outdir, 'mimetype'), 'mimetype', ZIP_STORED)
|
||||
for filename in [u'META-INF/container.xml', u'content.opf', u'toc.ncx']:
|
||||
epub.write(path.join(outdir, filename), filename, ZIP_DEFLATED) # type: ignore
|
||||
epub.write(path.join(outdir, filename), filename, ZIP_DEFLATED)
|
||||
for filename in self.files:
|
||||
epub.write(path.join(outdir, filename), filename, ZIP_DEFLATED) # type: ignore
|
||||
epub.write(path.join(outdir, filename), filename, ZIP_DEFLATED)
|
||||
|
@ -247,6 +247,7 @@ def setup(app):
|
||||
app.add_config_value('epub_guide', (), 'env')
|
||||
app.add_config_value('epub_pre_files', [], 'env')
|
||||
app.add_config_value('epub_post_files', [], 'env')
|
||||
app.add_config_value('epub_css_files', lambda config: config.html_css_files, 'epub')
|
||||
app.add_config_value('epub_exclude_files', [], 'env')
|
||||
app.add_config_value('epub_tocdepth', 3, 'env')
|
||||
app.add_config_value('epub_tocdup', True, 'env')
|
||||
|
@ -27,7 +27,7 @@ from sphinx.util import split_index_msg, logging, status_iterator
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.i18n import find_catalog
|
||||
from sphinx.util.nodes import extract_messages, traverse_translatable_index
|
||||
from sphinx.util.osutil import safe_relpath, ensuredir, canon_path
|
||||
from sphinx.util.osutil import relpath, ensuredir, canon_path
|
||||
from sphinx.util.tags import Tags
|
||||
|
||||
if False:
|
||||
@ -286,8 +286,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
if self.config.gettext_location:
|
||||
# generate "#: file1:line1\n#: file2:line2 ..."
|
||||
output.write("#: %s\n" % "\n#: ".join( # type: ignore
|
||||
"%s:%s" % (canon_path(
|
||||
safe_relpath(source, self.outdir)), line)
|
||||
"%s:%s" % (canon_path(relpath(source, self.outdir)), line)
|
||||
for source, line, _ in positions))
|
||||
if self.config.gettext_uuid:
|
||||
# generate "# uuid1\n# uuid2\n ..."
|
||||
|
@ -50,6 +50,7 @@ from sphinx.util.matching import patmatch, Matcher, DOTFILES
|
||||
from sphinx.util.nodes import inline_all_toctrees
|
||||
from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \
|
||||
movefile, copyfile
|
||||
from sphinx.util.pycompat import htmlescape
|
||||
from sphinx.writers.html import HTMLWriter, HTMLTranslator
|
||||
|
||||
if False:
|
||||
@ -101,7 +102,7 @@ class CSSContainer(list):
|
||||
if isinstance(obj, Stylesheet):
|
||||
super(CSSContainer, self).append(obj)
|
||||
else:
|
||||
super(CSSContainer, self).append(Stylesheet(obj, None, 'stylesheet')) # type: ignore # NOQA
|
||||
super(CSSContainer, self).append(Stylesheet(obj))
|
||||
|
||||
def insert(self, index, obj):
|
||||
# type: (int, Union[unicode, Stylesheet]) -> None
|
||||
@ -111,7 +112,7 @@ class CSSContainer(list):
|
||||
if isinstance(obj, Stylesheet):
|
||||
super(CSSContainer, self).insert(index, obj)
|
||||
else:
|
||||
super(CSSContainer, self).insert(index, Stylesheet(obj, None, 'stylesheet')) # type: ignore # NOQA
|
||||
super(CSSContainer, self).insert(index, Stylesheet(obj))
|
||||
|
||||
def extend(self, other): # type: ignore
|
||||
# type: (List[Union[unicode, Stylesheet]]) -> None
|
||||
@ -144,12 +145,19 @@ class Stylesheet(text_type):
|
||||
its filename (str).
|
||||
"""
|
||||
|
||||
def __new__(cls, filename, title, rel):
|
||||
attributes = None # type: Dict[unicode, unicode]
|
||||
filename = None # type: unicode
|
||||
|
||||
def __new__(cls, filename, *args, **attributes):
|
||||
# type: (unicode, unicode, unicode) -> None
|
||||
self = text_type.__new__(cls, filename) # type: ignore
|
||||
self.filename = filename
|
||||
self.title = title
|
||||
self.rel = rel
|
||||
self.attributes = attributes
|
||||
self.attributes.setdefault('rel', 'stylesheet')
|
||||
self.attributes.setdefault('type', 'text/css')
|
||||
if args: # old style arguments (rel, title)
|
||||
self.attributes['rel'] = args[0]
|
||||
self.attributes['title'] = args[1]
|
||||
|
||||
return self
|
||||
|
||||
@ -241,8 +249,6 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# This is a class attribute because it is mutated by Sphinx.add_javascript.
|
||||
script_files = ['_static/jquery.js', '_static/underscore.js',
|
||||
'_static/doctools.js'] # type: List[unicode]
|
||||
# Ditto for this one (Sphinx.add_stylesheet).
|
||||
css_files = CSSContainer() # type: List[Dict[unicode, unicode]]
|
||||
|
||||
imgpath = None # type: unicode
|
||||
domain_indices = [] # type: List[Tuple[unicode, Type[Index], List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool]] # NOQA
|
||||
@ -250,6 +256,13 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# cached publisher object for snippets
|
||||
_publisher = None
|
||||
|
||||
def __init__(self, app):
|
||||
# type: (Sphinx) -> None
|
||||
super(StandaloneHTMLBuilder, self).__init__(app)
|
||||
|
||||
# CSS files
|
||||
self.css_files = CSSContainer() # type: List[Dict[unicode, unicode]]
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
self.build_info = self.create_build_info()
|
||||
@ -262,6 +275,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
self.init_templates()
|
||||
self.init_highlighter()
|
||||
self.init_css_files()
|
||||
if self.config.html_file_suffix is not None:
|
||||
self.out_suffix = self.config.html_file_suffix
|
||||
|
||||
@ -324,6 +338,27 @@ class StandaloneHTMLBuilder(Builder):
|
||||
self.highlighter = PygmentsBridge('html', style,
|
||||
self.config.trim_doctest_flags)
|
||||
|
||||
def init_css_files(self):
|
||||
# type: () -> None
|
||||
for filename, attrs in self.app.registry.css_files:
|
||||
self.css_files.append(Stylesheet(filename, **attrs)) # type: ignore
|
||||
|
||||
for entry in self.get_builder_config('css_files', 'html'):
|
||||
if isinstance(entry, string_types):
|
||||
filename = entry
|
||||
attrs = {}
|
||||
else:
|
||||
try:
|
||||
filename, attrs = entry
|
||||
except (TypeError, ValueError):
|
||||
logger.warning('invalid css_file: %r', entry)
|
||||
continue
|
||||
|
||||
if '://' not in filename:
|
||||
filename = path.join('_static', filename)
|
||||
|
||||
self.css_files.append(Stylesheet(filename, **attrs)) # type: ignore
|
||||
|
||||
@property
|
||||
def default_translator_class(self):
|
||||
# type: () -> nodes.NodeVisitor
|
||||
@ -988,6 +1023,17 @@ class StandaloneHTMLBuilder(Builder):
|
||||
return uri
|
||||
ctx['pathto'] = pathto
|
||||
|
||||
def css_tag(css):
|
||||
# type: (Stylesheet) -> unicode
|
||||
attrs = []
|
||||
for key in sorted(css.attributes):
|
||||
value = css.attributes[key]
|
||||
if value is not None:
|
||||
attrs.append('%s="%s"' % (key, htmlescape(value, True)))
|
||||
attrs.append('href="%s"' % pathto(css.filename, resource=True))
|
||||
return '<link %s />' % ' '.join(attrs)
|
||||
ctx['css_tag'] = css_tag
|
||||
|
||||
def hasdoc(name):
|
||||
# type: (unicode) -> bool
|
||||
if name in self.env.all_docs:
|
||||
@ -1316,6 +1362,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
|
||||
self.templates = None # no template bridge necessary
|
||||
self.init_templates()
|
||||
self.init_highlighter()
|
||||
self.init_css_files()
|
||||
self.use_index = self.get_builder_config('use_index', 'html')
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
@ -1440,6 +1487,7 @@ def setup(app):
|
||||
app.add_config_value('html_style', None, 'html', string_classes)
|
||||
app.add_config_value('html_logo', None, 'html', string_classes)
|
||||
app.add_config_value('html_favicon', None, 'html', string_classes)
|
||||
app.add_config_value('html_css_files', [], 'html')
|
||||
app.add_config_value('html_static_path', [], 'html')
|
||||
app.add_config_value('html_extra_path', [], 'html')
|
||||
app.add_config_value('html_last_updated_fmt', None, 'html', string_classes)
|
||||
|
@ -248,6 +248,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
|
||||
outdir += os.sep
|
||||
olen = len(outdir)
|
||||
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 \
|
||||
|
@ -24,6 +24,7 @@ from sphinx.environment import NoUri
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import SphinxError, ConfigError
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.util import texescape, logging, status_iterator
|
||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
||||
from sphinx.util.docutils import new_document
|
||||
@ -144,6 +145,7 @@ class LaTeXBuilder(Builder):
|
||||
docname, toctree_only,
|
||||
appendices=((docclass != 'howto') and self.config.latex_appendices or []))
|
||||
doctree['tocdepth'] = tocdepth
|
||||
self.apply_transforms(doctree)
|
||||
self.post_process_images(doctree)
|
||||
logger.info(__("writing... "), nonl=1)
|
||||
doctree.settings = docsettings
|
||||
@ -210,6 +212,12 @@ class LaTeXBuilder(Builder):
|
||||
pendingnode.replace_self(newnodes)
|
||||
return largetree
|
||||
|
||||
def apply_transforms(self, doctree):
|
||||
# type: (nodes.document) -> None
|
||||
transformer = SphinxTransformer(doctree)
|
||||
transformer.set_environment(self.env)
|
||||
transformer.apply_transforms()
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
self.copy_image_files()
|
161
sphinx/builders/latex/transforms.py
Normal file
161
sphinx/builders/latex/transforms.py
Normal file
@ -0,0 +1,161 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinx.builders.latex.transforms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Transforms for LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx.transforms import SphinxTransform
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Dict, List, Set, Union # NOQA
|
||||
|
||||
URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:')
|
||||
|
||||
|
||||
class ShowUrlsTransform(SphinxTransform):
|
||||
"""Expand references to inline text or footnotes.
|
||||
|
||||
For more information, see :confval:`latex_show_urls`.
|
||||
"""
|
||||
default_priority = 400
|
||||
|
||||
# references are expanded to footnotes (or not)
|
||||
expanded = False
|
||||
|
||||
def apply(self):
|
||||
# type: () -> None
|
||||
# replace id_prefix temporarily
|
||||
id_prefix = self.document.settings.id_prefix
|
||||
self.document.settings.id_prefix = 'show_urls'
|
||||
|
||||
self.expand_show_urls()
|
||||
if self.expanded:
|
||||
self.renumber_footnotes()
|
||||
|
||||
# restore id_prefix
|
||||
self.document.settings.id_prefix = id_prefix
|
||||
|
||||
def expand_show_urls(self):
|
||||
# type: () -> None
|
||||
show_urls = self.document.settings.env.config.latex_show_urls
|
||||
if show_urls is False or show_urls == 'no':
|
||||
return
|
||||
|
||||
for node in self.document.traverse(nodes.reference):
|
||||
uri = node.get('refuri', '')
|
||||
if uri.startswith(URI_SCHEMES):
|
||||
if uri.startswith('mailto:'):
|
||||
uri = uri[7:]
|
||||
if node.astext() != uri:
|
||||
index = node.parent.index(node)
|
||||
if show_urls == 'footnote':
|
||||
footnote_nodes = self.create_footnote(uri)
|
||||
for i, fn in enumerate(footnote_nodes):
|
||||
node.parent.insert(index + i + 1, fn)
|
||||
|
||||
self.expanded = True
|
||||
else: # all other true values (b/w compat)
|
||||
textnode = nodes.Text(" (%s)" % uri)
|
||||
node.parent.insert(index + 1, textnode)
|
||||
|
||||
def create_footnote(self, uri):
|
||||
# type: (unicode) -> List[Union[nodes.footnote, nodes.footnote_ref]]
|
||||
label = nodes.label('', '#')
|
||||
para = nodes.paragraph()
|
||||
para.append(nodes.reference('', nodes.Text(uri), refuri=uri, nolinkurl=True))
|
||||
footnote = nodes.footnote(uri, label, para, auto=1)
|
||||
footnote['names'].append('#')
|
||||
self.document.note_autofootnote(footnote)
|
||||
|
||||
label = nodes.Text('#')
|
||||
footnote_ref = nodes.footnote_reference('[#]_', label, auto=1,
|
||||
refid=footnote['ids'][0])
|
||||
self.document.note_autofootnote_ref(footnote_ref)
|
||||
footnote.add_backref(footnote_ref['ids'][0])
|
||||
|
||||
return [footnote, footnote_ref]
|
||||
|
||||
def renumber_footnotes(self):
|
||||
# type: () -> None
|
||||
collector = FootnoteCollector(self.document)
|
||||
self.document.walkabout(collector)
|
||||
|
||||
num = 0
|
||||
for document, footnote in collector.auto_footnotes:
|
||||
# search unused footnote number
|
||||
while True:
|
||||
num += 1
|
||||
if str(num) not in collector.used_footnote_numbers:
|
||||
break
|
||||
|
||||
# assign new footnote number
|
||||
old_label = footnote[0].astext()
|
||||
footnote[0].replace_self(nodes.label('', str(num)))
|
||||
if old_label in footnote['names']:
|
||||
footnote['names'].remove(old_label)
|
||||
footnote['names'].append(str(num))
|
||||
|
||||
# update footnote_references by new footnote number
|
||||
for ref in collector.footnote_refs.get(document, []):
|
||||
if footnote['ids'][0] == ref['refid']:
|
||||
ref.remove(ref[0])
|
||||
ref += nodes.Text(str(num))
|
||||
|
||||
|
||||
class FootnoteCollector(nodes.NodeVisitor):
|
||||
"""Collect footnotes and footnote references on the document"""
|
||||
|
||||
def __init__(self, document):
|
||||
# type: (nodes.document) -> None
|
||||
self.auto_footnotes = [] # type: List[nodes.footnote]
|
||||
self.used_footnote_numbers = set() # type: Set[unicode]
|
||||
self.footnote_refs = {} # type: Dict[nodes.Node, List[nodes.footnote_reference]] # NOQA
|
||||
self.current_document = [] # type: List[nodes.Node]
|
||||
nodes.NodeVisitor.__init__(self, document)
|
||||
|
||||
def visit_document(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
self.current_document.append(node)
|
||||
|
||||
def depart_document(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
self.current_document.pop()
|
||||
|
||||
def visit_start_of_file(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
self.current_document.append(node)
|
||||
|
||||
def depart_start_of_file(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
self.current_document.pop()
|
||||
|
||||
def unknown_visit(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
pass
|
||||
|
||||
def visit_footnote(self, node):
|
||||
# type: (nodes.footnote) -> None
|
||||
document = self.current_document[-1]
|
||||
if node.get('auto'):
|
||||
self.auto_footnotes.append((document, node))
|
||||
else:
|
||||
for name in node['names']:
|
||||
self.used_footnote_numbers.add(name)
|
||||
|
||||
def visit_footnote_reference(self, node):
|
||||
# type: (nodes.footnote_reference) -> None
|
||||
document = self.current_document[-1]
|
||||
footnote_refs = self.footnote_refs.setdefault(document, [])
|
||||
footnote_refs.append(node)
|
||||
|
||||
def unknown_departure(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
pass
|
@ -132,11 +132,7 @@ class Config(object):
|
||||
nitpick_ignore = ([], None),
|
||||
numfig = (False, 'env'),
|
||||
numfig_secnum_depth = (1, 'env'),
|
||||
numfig_format = ({'section': _('Section %s'),
|
||||
'figure': _('Fig. %s'),
|
||||
'table': _('Table %s'),
|
||||
'code-block': _('Listing %s')},
|
||||
'env'),
|
||||
numfig_format = ({}, 'env'), # will be initialized in init_numfig_format()
|
||||
|
||||
tls_verify = (True, 'env'),
|
||||
tls_cacerts = (None, 'env'),
|
||||
@ -364,6 +360,19 @@ def convert_source_suffix(app, config):
|
||||
"But `%r' is given." % source_suffix))
|
||||
|
||||
|
||||
def init_numfig_format(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
"""Initialize :confval:`numfig_format`."""
|
||||
numfig_format = {'section': _('Section %s'),
|
||||
'figure': _('Fig. %s'),
|
||||
'table': _('Table %s'),
|
||||
'code-block': _('Listing %s')}
|
||||
|
||||
# override default labels by configuration
|
||||
numfig_format.update(config.numfig_format)
|
||||
config.numfig_format = numfig_format # type: ignore
|
||||
|
||||
|
||||
def correct_copyright_year(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
"""correct values of copyright year that are not coherent with
|
||||
@ -446,6 +455,7 @@ def check_unicode(config):
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
app.connect('config-inited', convert_source_suffix)
|
||||
app.connect('config-inited', init_numfig_format)
|
||||
app.connect('config-inited', correct_copyright_year)
|
||||
app.connect('config-inited', check_confval_types)
|
||||
|
||||
|
@ -33,6 +33,10 @@ class RemovedInSphinx30Warning(PendingDeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
class RemovedInSphinx40Warning(PendingDeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
RemovedInNextVersionWarning = RemovedInSphinx18Warning
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@ from docutils.parsers.rst import Directive, directives, roles
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.util.docfields import DocFieldTransformer
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
|
||||
# import all directives sphinx provides
|
||||
from sphinx.directives.code import ( # noqa
|
||||
@ -33,6 +34,7 @@ if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
|
||||
|
||||
@ -41,7 +43,7 @@ nl_escape_re = re.compile(r'\\\n')
|
||||
strip_backslash_re = re.compile(r'\\(.)')
|
||||
|
||||
|
||||
class ObjectDescription(Directive):
|
||||
class ObjectDescription(SphinxDirective):
|
||||
"""
|
||||
Directive to describe a class, function or similar object. Not used
|
||||
directly, but subclassed (in domain-specific directives) to add custom
|
||||
@ -135,7 +137,6 @@ class ObjectDescription(Directive):
|
||||
self.domain, self.objtype = self.name.split(':', 1)
|
||||
else:
|
||||
self.domain, self.objtype = '', self.name
|
||||
self.env = self.state.document.settings.env # type: BuildEnvironment
|
||||
self.indexnode = addnodes.index(entries=[])
|
||||
|
||||
node = addnodes.desc()
|
||||
@ -187,7 +188,7 @@ class ObjectDescription(Directive):
|
||||
DescDirective = ObjectDescription
|
||||
|
||||
|
||||
class DefaultRole(Directive):
|
||||
class DefaultRole(SphinxDirective):
|
||||
"""
|
||||
Set the default interpreted text role. Overridden from docutils.
|
||||
"""
|
||||
@ -212,7 +213,7 @@ class DefaultRole(Directive):
|
||||
line=self.lineno)
|
||||
return messages + [error]
|
||||
roles._roles[''] = role
|
||||
self.state.document.settings.env.temp_data['default_role'] = role_name
|
||||
self.env.temp_data['default_role'] = role_name
|
||||
return messages
|
||||
|
||||
|
||||
@ -229,7 +230,6 @@ class DefaultDomain(Directive):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
domain_name = self.arguments[0].lower()
|
||||
# if domain_name not in env.domains:
|
||||
# # try searching by label
|
||||
@ -237,7 +237,7 @@ class DefaultDomain(Directive):
|
||||
# if domain.label.lower() == domain_name:
|
||||
# domain_name = domain.name
|
||||
# break
|
||||
env.temp_data['default_domain'] = env.domains.get(domain_name)
|
||||
self.env.temp_data['default_domain'] = self.env.domains.get(domain_name)
|
||||
return []
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@ import sys
|
||||
from difflib import unified_diff
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.statemachine import ViewList
|
||||
from six import text_type
|
||||
|
||||
@ -20,6 +20,7 @@ from sphinx import addnodes
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util import parselinenos
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.nodes import set_source_info
|
||||
|
||||
if False:
|
||||
@ -31,7 +32,7 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Highlight(Directive):
|
||||
class Highlight(SphinxDirective):
|
||||
"""
|
||||
Directive to set the highlighting language for code blocks, as well
|
||||
as the threshold for line numbers.
|
||||
@ -77,7 +78,7 @@ def dedent_lines(lines, dedent, location=None):
|
||||
|
||||
|
||||
def container_wrapper(directive, literal_node, caption):
|
||||
# type: (Directive, nodes.Node, unicode) -> nodes.container
|
||||
# type: (SphinxDirective, nodes.Node, unicode) -> nodes.container
|
||||
container_node = nodes.container('', literal_block=True,
|
||||
classes=['literal-block-wrapper'])
|
||||
parsed = nodes.Element()
|
||||
@ -95,7 +96,7 @@ def container_wrapper(directive, literal_node, caption):
|
||||
return container_node
|
||||
|
||||
|
||||
class CodeBlock(Directive):
|
||||
class CodeBlock(SphinxDirective):
|
||||
"""
|
||||
Directive for a code block with special highlighting or line numbering
|
||||
settings.
|
||||
@ -372,7 +373,7 @@ class LiteralIncludeReader(object):
|
||||
return lines
|
||||
|
||||
|
||||
class LiteralInclude(Directive):
|
||||
class LiteralInclude(SphinxDirective):
|
||||
"""
|
||||
Like ``.. include:: :literal:``, but only warns if the include file is
|
||||
not found, and does not raise errors. Also has several options for
|
||||
@ -412,19 +413,17 @@ class LiteralInclude(Directive):
|
||||
if not document.settings.file_insertion_enabled:
|
||||
return [document.reporter.warning('File insertion disabled',
|
||||
line=self.lineno)]
|
||||
env = document.settings.env
|
||||
|
||||
# convert options['diff'] to absolute path
|
||||
if 'diff' in self.options:
|
||||
_, path = env.relfn2path(self.options['diff'])
|
||||
_, path = self.env.relfn2path(self.options['diff'])
|
||||
self.options['diff'] = path
|
||||
|
||||
try:
|
||||
location = self.state_machine.get_source_and_line(self.lineno)
|
||||
rel_filename, filename = env.relfn2path(self.arguments[0])
|
||||
env.note_dependency(rel_filename)
|
||||
rel_filename, filename = self.env.relfn2path(self.arguments[0])
|
||||
self.env.note_dependency(rel_filename)
|
||||
|
||||
reader = LiteralIncludeReader(filename, self.options, env.config)
|
||||
reader = LiteralIncludeReader(filename, self.options, self.config)
|
||||
text, lines = reader.read(location=location)
|
||||
|
||||
retnode = nodes.literal_block(text, text, source=filename)
|
||||
|
@ -7,8 +7,10 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
|
||||
from docutils.parsers.rst.directives.misc import Class
|
||||
from docutils.parsers.rst.directives.misc import Include as BaseInclude
|
||||
@ -18,13 +20,14 @@ from sphinx import addnodes, locale
|
||||
from sphinx.deprecation import DeprecatedDict, RemovedInSphinx30Warning
|
||||
from sphinx.locale import _
|
||||
from sphinx.util import url_re, docname_join
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.matching import patfilter
|
||||
from sphinx.util.nodes import explicit_title_re, set_source_info, \
|
||||
process_index_entry
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Tuple # NOQA
|
||||
from typing import Any, Dict, Generator, List, Tuple # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
@ -41,6 +44,8 @@ locale.versionlabels = DeprecatedDict(
|
||||
RemovedInSphinx30Warning
|
||||
)
|
||||
|
||||
glob_re = re.compile('.*[*?\[].*')
|
||||
|
||||
|
||||
def int_or_nothing(argument):
|
||||
# type: (unicode) -> int
|
||||
@ -49,7 +54,7 @@ def int_or_nothing(argument):
|
||||
return int(argument)
|
||||
|
||||
|
||||
class TocTree(Directive):
|
||||
class TocTree(SphinxDirective):
|
||||
"""
|
||||
Directive to notify Sphinx about the hierarchical structure of the docs,
|
||||
and to include a table-of-contents like tree in the current document.
|
||||
@ -72,30 +77,50 @@ class TocTree(Directive):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
suffixes = env.config.source_suffix
|
||||
glob = 'glob' in self.options
|
||||
subnode = addnodes.toctree()
|
||||
subnode['parent'] = self.env.docname
|
||||
|
||||
ret = []
|
||||
# (title, ref) pairs, where ref may be a document, or an external link,
|
||||
# and title may be None if the document's title is to be used
|
||||
entries = [] # type: List[Tuple[unicode, unicode]]
|
||||
includefiles = []
|
||||
all_docnames = env.found_docs.copy()
|
||||
# don't add the currently visited file in catch-all patterns
|
||||
all_docnames.remove(env.docname)
|
||||
subnode['entries'] = []
|
||||
subnode['includefiles'] = []
|
||||
subnode['maxdepth'] = self.options.get('maxdepth', -1)
|
||||
subnode['caption'] = self.options.get('caption')
|
||||
subnode['glob'] = 'glob' in self.options
|
||||
subnode['hidden'] = 'hidden' in self.options
|
||||
subnode['includehidden'] = 'includehidden' in self.options
|
||||
subnode['numbered'] = self.options.get('numbered', 0)
|
||||
subnode['titlesonly'] = 'titlesonly' in self.options
|
||||
set_source_info(self, subnode)
|
||||
wrappernode = nodes.compound(classes=['toctree-wrapper'])
|
||||
wrappernode.append(subnode)
|
||||
self.add_name(wrappernode)
|
||||
|
||||
ret = self.parse_content(subnode)
|
||||
ret.append(wrappernode)
|
||||
return ret
|
||||
|
||||
def parse_content(self, toctree):
|
||||
suffixes = self.config.source_suffix
|
||||
|
||||
# glob target documents
|
||||
all_docnames = self.env.found_docs.copy()
|
||||
all_docnames.remove(self.env.docname) # remove current document
|
||||
|
||||
ret = []
|
||||
for entry in self.content:
|
||||
if not entry:
|
||||
continue
|
||||
# look for explicit titles ("Some Title <document>")
|
||||
explicit = explicit_title_re.match(entry)
|
||||
if glob and ('*' in entry or '?' in entry or '[' in entry) and not explicit:
|
||||
patname = docname_join(env.docname, entry)
|
||||
if (toctree['glob'] and glob_re.match(entry) and
|
||||
not explicit and not url_re.match(entry)):
|
||||
patname = docname_join(self.env.docname, entry)
|
||||
docnames = sorted(patfilter(all_docnames, patname))
|
||||
for docname in docnames:
|
||||
all_docnames.remove(docname) # don't include it again
|
||||
entries.append((None, docname))
|
||||
includefiles.append(docname)
|
||||
toctree['entries'].append((None, docname))
|
||||
toctree['includefiles'].append(docname)
|
||||
if not docnames:
|
||||
ret.append(self.state.document.reporter.warning(
|
||||
'toctree glob pattern %r didn\'t match any documents'
|
||||
@ -114,42 +139,27 @@ class TocTree(Directive):
|
||||
docname = docname[:-len(suffix)]
|
||||
break
|
||||
# absolutize filenames
|
||||
docname = docname_join(env.docname, docname)
|
||||
docname = docname_join(self.env.docname, docname)
|
||||
if url_re.match(ref) or ref == 'self':
|
||||
entries.append((title, ref))
|
||||
elif docname not in env.found_docs:
|
||||
toctree['entries'].append((title, ref))
|
||||
elif docname not in self.env.found_docs:
|
||||
ret.append(self.state.document.reporter.warning(
|
||||
'toctree contains reference to nonexisting '
|
||||
'document %r' % docname, line=self.lineno))
|
||||
env.note_reread()
|
||||
self.env.note_reread()
|
||||
else:
|
||||
all_docnames.discard(docname)
|
||||
entries.append((title, docname))
|
||||
includefiles.append(docname)
|
||||
subnode = addnodes.toctree()
|
||||
subnode['parent'] = env.docname
|
||||
toctree['entries'].append((title, docname))
|
||||
toctree['includefiles'].append(docname)
|
||||
|
||||
# entries contains all entries (self references, external links etc.)
|
||||
if 'reversed' in self.options:
|
||||
entries.reverse()
|
||||
subnode['entries'] = entries
|
||||
# includefiles only entries that are documents
|
||||
subnode['includefiles'] = includefiles
|
||||
subnode['maxdepth'] = self.options.get('maxdepth', -1)
|
||||
subnode['caption'] = self.options.get('caption')
|
||||
subnode['glob'] = glob
|
||||
subnode['hidden'] = 'hidden' in self.options
|
||||
subnode['includehidden'] = 'includehidden' in self.options
|
||||
subnode['numbered'] = self.options.get('numbered', 0)
|
||||
subnode['titlesonly'] = 'titlesonly' in self.options
|
||||
set_source_info(self, subnode)
|
||||
wrappernode = nodes.compound(classes=['toctree-wrapper'])
|
||||
wrappernode.append(subnode)
|
||||
self.add_name(wrappernode)
|
||||
ret.append(wrappernode)
|
||||
toctree['entries'] = list(reversed(toctree['entries']))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class Author(Directive):
|
||||
class Author(SphinxDirective):
|
||||
"""
|
||||
Directive to give the name of the author of the current document
|
||||
or section. Shown in the output only if the show_authors option is on.
|
||||
@ -162,8 +172,7 @@ class Author(Directive):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
if not env.config.show_authors:
|
||||
if not self.config.show_authors:
|
||||
return []
|
||||
para = nodes.paragraph(translatable=False)
|
||||
emph = nodes.emphasis()
|
||||
@ -183,7 +192,7 @@ class Author(Directive):
|
||||
return [para] + messages
|
||||
|
||||
|
||||
class Index(Directive):
|
||||
class Index(SphinxDirective):
|
||||
"""
|
||||
Directive to add entries to the index.
|
||||
"""
|
||||
@ -196,8 +205,7 @@ class Index(Directive):
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
arguments = self.arguments[0].split('\n')
|
||||
env = self.state.document.settings.env
|
||||
targetid = 'index-%s' % env.new_serialno('index')
|
||||
targetid = 'index-%s' % self.env.new_serialno('index')
|
||||
targetnode = nodes.target('', '', ids=[targetid])
|
||||
self.state.document.note_explicit_target(targetnode)
|
||||
indexnode = addnodes.index()
|
||||
@ -209,7 +217,7 @@ class Index(Directive):
|
||||
return [indexnode, targetnode]
|
||||
|
||||
|
||||
class VersionChange(Directive):
|
||||
class VersionChange(SphinxDirective):
|
||||
"""
|
||||
Directive to describe a change/addition/deprecation in a specific version.
|
||||
"""
|
||||
@ -252,9 +260,8 @@ class VersionChange(Directive):
|
||||
classes=['versionmodified']),
|
||||
translatable=False)
|
||||
node.append(para)
|
||||
env = self.state.document.settings.env
|
||||
# XXX should record node.source as well
|
||||
env.note_versionchange(node['type'], node['version'], node, node.line)
|
||||
self.env.note_versionchange(node['type'], node['version'], node, node.line)
|
||||
return [node] + messages
|
||||
|
||||
|
||||
@ -265,7 +272,7 @@ class SeeAlso(BaseAdmonition):
|
||||
node_class = addnodes.seealso
|
||||
|
||||
|
||||
class TabularColumns(Directive):
|
||||
class TabularColumns(SphinxDirective):
|
||||
"""
|
||||
Directive to give an explicit tabulary column definition to LaTeX.
|
||||
"""
|
||||
@ -283,7 +290,7 @@ class TabularColumns(Directive):
|
||||
return [node]
|
||||
|
||||
|
||||
class Centered(Directive):
|
||||
class Centered(SphinxDirective):
|
||||
"""
|
||||
Directive to create a centered line of bold text.
|
||||
"""
|
||||
@ -304,7 +311,7 @@ class Centered(Directive):
|
||||
return [subnode] + messages
|
||||
|
||||
|
||||
class Acks(Directive):
|
||||
class Acks(SphinxDirective):
|
||||
"""
|
||||
Directive for a list of names.
|
||||
"""
|
||||
@ -326,7 +333,7 @@ class Acks(Directive):
|
||||
return [node]
|
||||
|
||||
|
||||
class HList(Directive):
|
||||
class HList(SphinxDirective):
|
||||
"""
|
||||
Directive for a list that gets compacted horizontally.
|
||||
"""
|
||||
@ -363,7 +370,7 @@ class HList(Directive):
|
||||
return [newnode]
|
||||
|
||||
|
||||
class Only(Directive):
|
||||
class Only(SphinxDirective):
|
||||
"""
|
||||
Directive to only include text if the given tag(s) are enabled.
|
||||
"""
|
||||
@ -421,7 +428,7 @@ class Only(Directive):
|
||||
self.state.memo.section_level = surrounding_section_level
|
||||
|
||||
|
||||
class Include(BaseInclude):
|
||||
class Include(BaseInclude, SphinxDirective):
|
||||
"""
|
||||
Like the standard "Include" directive, but interprets absolute paths
|
||||
"correctly", i.e. relative to source directory.
|
||||
@ -429,14 +436,13 @@ class Include(BaseInclude):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
if self.arguments[0].startswith('<') and \
|
||||
self.arguments[0].endswith('>'):
|
||||
# docutils "standard" includes, do not do path processing
|
||||
return BaseInclude.run(self)
|
||||
rel_filename, filename = env.relfn2path(self.arguments[0])
|
||||
rel_filename, filename = self.env.relfn2path(self.arguments[0])
|
||||
self.arguments[0] = filename
|
||||
env.note_included(filename)
|
||||
self.env.note_included(filename)
|
||||
return BaseInclude.run(self)
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@ from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst.directives import images, html, tables
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.nodes import set_source_info
|
||||
|
||||
if False:
|
||||
@ -44,16 +45,15 @@ class Figure(images.Figure):
|
||||
return [figure_node]
|
||||
|
||||
|
||||
class Meta(html.Meta):
|
||||
class Meta(html.Meta, SphinxDirective):
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
result = html.Meta.run(self)
|
||||
for node in result:
|
||||
if (isinstance(node, nodes.pending) and
|
||||
isinstance(node.details['nodes'][0], html.MetaBody.meta)):
|
||||
meta = node.details['nodes'][0]
|
||||
meta.source = env.doc2path(env.docname)
|
||||
meta.source = self.env.doc2path(self.env.docname)
|
||||
meta.line = self.lineno
|
||||
meta.rawcontent = meta['content']
|
||||
|
||||
|
@ -21,10 +21,10 @@ from os import path
|
||||
|
||||
from docutils.frontend import OptionParser
|
||||
from docutils.utils import Reporter, get_source_line
|
||||
from six import BytesIO, itervalues, class_types, next
|
||||
from six import BytesIO, class_types, next
|
||||
from six.moves import cPickle as pickle
|
||||
|
||||
from sphinx import addnodes, versioning
|
||||
from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warning
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
@ -38,7 +38,7 @@ from sphinx.util.docutils import sphinx_domains, WarningStream
|
||||
from sphinx.util.i18n import find_catalog_files
|
||||
from sphinx.util.matching import compile_matchers
|
||||
from sphinx.util.nodes import is_translatable
|
||||
from sphinx.util.osutil import SEP, ensuredir
|
||||
from sphinx.util.osutil import SEP, ensuredir, relpath
|
||||
from sphinx.util.websupport import is_commentable
|
||||
|
||||
if False:
|
||||
@ -354,7 +354,7 @@ class BuildEnvironment(object):
|
||||
*filename* should be absolute or relative to the source directory.
|
||||
"""
|
||||
if filename.startswith(self.srcdir):
|
||||
filename = os.path.relpath(filename, self.srcdir)
|
||||
filename = relpath(filename, self.srcdir)
|
||||
for suffix in self.config.source_suffix:
|
||||
if filename.endswith(suffix):
|
||||
return filename[:-len(suffix)]
|
||||
@ -540,7 +540,6 @@ class BuildEnvironment(object):
|
||||
"""Update settings by new config."""
|
||||
self.settings['input_encoding'] = config.source_encoding
|
||||
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
|
||||
self.settings['gettext_compact'] = config.gettext_compact
|
||||
self.settings['language_code'] = config.language or 'en'
|
||||
|
||||
# Allow to disable by 3rd party extension (workaround)
|
||||
@ -571,14 +570,6 @@ class BuildEnvironment(object):
|
||||
with sphinx_domains(self), rst.default_role(docname, self.config.default_role):
|
||||
doctree = read_doc(self.app, self, self.doc2path(docname))
|
||||
|
||||
# post-processing
|
||||
for domain in itervalues(self.domains):
|
||||
domain.process_doc(self, docname, doctree)
|
||||
|
||||
# allow extension-specific post-processing
|
||||
if app:
|
||||
app.emit('doctree-read', doctree)
|
||||
|
||||
# store time of reading, for outdated files detection
|
||||
# (Some filesystems have coarse timestamp resolution;
|
||||
# therefore time.time() can be older than filesystem's timestamp.
|
||||
@ -586,10 +577,6 @@ class BuildEnvironment(object):
|
||||
self.all_docs[docname] = max(
|
||||
time.time(), path.getmtime(self.doc2path(docname)))
|
||||
|
||||
if self.versioning_condition:
|
||||
# add uids for versioning
|
||||
versioning.prepare(doctree)
|
||||
|
||||
# cleanup
|
||||
self.temp_data.clear()
|
||||
self.ref_context.clear()
|
||||
|
@ -1301,7 +1301,10 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
||||
inspect.ismethoddescriptor(self.object):
|
||||
# can never get arguments of a C function or method
|
||||
return None
|
||||
args = Signature(self.object, bound_method=True).format_args()
|
||||
if isstaticmethod(self.object, cls=self.parent, name=self.object_name):
|
||||
args = Signature(self.object, bound_method=False).format_args()
|
||||
else:
|
||||
args = Signature(self.object, bound_method=True).format_args()
|
||||
# escape backslashes for reST
|
||||
args = args.replace('\\', '\\\\')
|
||||
return args
|
||||
|
@ -91,7 +91,7 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
periods_re = re.compile('\.(?:\s+)')
|
||||
periods_re = re.compile(r'\.(?:\s+)')
|
||||
|
||||
|
||||
# -- autosummary_toc node ------------------------------------------------------
|
||||
@ -361,7 +361,7 @@ class Autosummary(Directive):
|
||||
*items* is a list produced by :meth:`get_items`.
|
||||
"""
|
||||
table_spec = addnodes.tabular_col_spec()
|
||||
table_spec['spec'] = r'p{0.5\linewidth}p{0.5\linewidth}'
|
||||
table_spec['spec'] = r'\X{1}{2}\X{1}{2}'
|
||||
|
||||
table = autosummary_table('')
|
||||
real_table = nodes.table('', classes=['longtable'])
|
||||
|
@ -30,7 +30,7 @@ from sphinx.locale import __
|
||||
from sphinx.util import force_decode, logging
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.nodes import set_source_info
|
||||
from sphinx.util.osutil import fs_encoding
|
||||
from sphinx.util.osutil import fs_encoding, relpath
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -372,7 +372,7 @@ Doctest summary
|
||||
"""Try to get the file which actually contains the doctest, not the
|
||||
filename of the document it's included in."""
|
||||
try:
|
||||
filename = path.relpath(node.source, self.env.srcdir)\
|
||||
filename = relpath(node.source, self.env.srcdir)\
|
||||
.rsplit(':docstring of ', maxsplit=1)[0]
|
||||
except Exception:
|
||||
filename = self.env.doc2path(docname, base=None)
|
||||
|
@ -8,6 +8,7 @@
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import locale
|
||||
import subprocess
|
||||
|
||||
from sphinx.errors import ExtensionError
|
||||
@ -38,17 +39,29 @@ class ImagemagickConverter(ImageConverter):
|
||||
try:
|
||||
args = [self.config.image_converter, '-version']
|
||||
logger.debug('Invoking %r ...', args)
|
||||
ret = subprocess.call(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
if ret == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except (OSError, IOError):
|
||||
logger.warning(__('convert command %r cannot be run.'
|
||||
'check the image_converter setting'),
|
||||
self.config.image_converter)
|
||||
return False
|
||||
|
||||
try:
|
||||
stdout, stderr = p.communicate()
|
||||
except (OSError, IOError) as err:
|
||||
if err.errno not in (EPIPE, EINVAL):
|
||||
raise
|
||||
stdout, stderr = p.stdout.read(), p.stderr.read()
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
encoding = locale.getpreferredencoding()
|
||||
logger.warning(__('convert exited with error:\n'
|
||||
'[stderr]\n%s\n[stdout]\n%s'),
|
||||
stderr.decode(encoding), stdout.decode(encoding))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def convert(self, _from, _to):
|
||||
# type: (unicode, unicode) -> bool
|
||||
"""Converts the image to expected one."""
|
||||
@ -61,7 +74,7 @@ class ImagemagickConverter(ImageConverter):
|
||||
self.config.image_converter_args +
|
||||
[_from, _to])
|
||||
logger.debug('Invoking %r ...', args)
|
||||
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except OSError as err:
|
||||
if err.errno != ENOENT: # No such file or directory
|
||||
raise
|
||||
|
@ -26,7 +26,7 @@ if False:
|
||||
|
||||
def html_visit_math(self, node):
|
||||
# type: (nodes.NodeVisitor, nodes.Node) -> None
|
||||
self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate'))
|
||||
self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate nohighlight'))
|
||||
self.body.append(self.encode(node['latex']) + '</span>')
|
||||
raise nodes.SkipNode
|
||||
|
||||
@ -34,7 +34,7 @@ def html_visit_math(self, node):
|
||||
def html_visit_displaymath(self, node):
|
||||
# type: (nodes.NodeVisitor, nodes.Node) -> None
|
||||
if node['nowrap']:
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math notranslate nohighlight'))
|
||||
self.body.append(self.encode(node['latex']))
|
||||
self.body.append('</div>')
|
||||
raise nodes.SkipNode
|
||||
@ -47,7 +47,7 @@ def html_visit_displaymath(self, node):
|
||||
self.body.append('<span class="eqno">(%s)' % number)
|
||||
self.add_permalink_ref(node, _('Permalink to this equation'))
|
||||
self.body.append('</span>')
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math notranslate nohighlight'))
|
||||
else:
|
||||
# but only once!
|
||||
self.body.append('<div class="math">')
|
||||
|
@ -27,7 +27,7 @@ if False:
|
||||
|
||||
def html_visit_math(self, node):
|
||||
# type: (nodes.NodeVisitor, nodes.Node) -> None
|
||||
self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate'))
|
||||
self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate nohighlight'))
|
||||
self.body.append(self.builder.config.mathjax_inline[0] +
|
||||
self.encode(node['latex']) +
|
||||
self.builder.config.mathjax_inline[1] + '</span>')
|
||||
@ -36,7 +36,7 @@ def html_visit_math(self, node):
|
||||
|
||||
def html_visit_displaymath(self, node):
|
||||
# type: (nodes.NodeVisitor, nodes.Node) -> None
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math notranslate nohighlight'))
|
||||
if node['nowrap']:
|
||||
self.body.append(self.encode(node['latex']))
|
||||
self.body.append('</div>')
|
||||
|
11
sphinx/io.py
11
sphinx/io.py
@ -24,15 +24,17 @@ from sphinx.transforms import (
|
||||
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
||||
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds,
|
||||
AutoNumbering, AutoIndexUpgrader, FilterSystemMessages,
|
||||
UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink
|
||||
UnreferencedFootnotesDetector, SphinxSmartQuotes, DoctreeReadEvent, ManpageLink
|
||||
)
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.transforms.compact_bullet_list import RefOnlyBulletListTransform
|
||||
from sphinx.transforms.i18n import (
|
||||
PreserveTranslatableMessages, Locale, RemoveTranslatableInline,
|
||||
)
|
||||
from sphinx.transforms.references import SphinxDomains, SubstitutionDefinitionsRemover
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.docutils import LoggingReporter
|
||||
from sphinx.versioning import UIDTransform
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -93,7 +95,9 @@ class SphinxStandaloneReader(SphinxBaseReader):
|
||||
Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets,
|
||||
HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds,
|
||||
RemoveTranslatableInline, FilterSystemMessages, RefOnlyBulletListTransform,
|
||||
UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink
|
||||
UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink,
|
||||
SphinxDomains, SubstitutionDefinitionsRemover, DoctreeReadEvent,
|
||||
UIDTransform,
|
||||
] # type: List[Transform]
|
||||
|
||||
def __init__(self, app, *args, **kwargs):
|
||||
@ -116,7 +120,8 @@ class SphinxI18nReader(SphinxBaseReader):
|
||||
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
|
||||
AutoNumbering, SortIds, RemoveTranslatableInline,
|
||||
FilterSystemMessages, RefOnlyBulletListTransform,
|
||||
UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink]
|
||||
UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink,
|
||||
SubstitutionDefinitionsRemover]
|
||||
|
||||
def set_lineno_for_reporter(self, lineno):
|
||||
# type: (int) -> None
|
||||
|
@ -425,7 +425,7 @@ msgstr "行规范 %r:未能从包含文件 %r 中拉取行"
|
||||
|
||||
#: sphinx/directives/other.py:157
|
||||
msgid "Section author: "
|
||||
msgstr "节作者:"
|
||||
msgstr "章节作者:"
|
||||
|
||||
#: sphinx/directives/other.py:159
|
||||
msgid "Module author: "
|
||||
@ -878,7 +878,7 @@ msgstr "格式转换程序退出并报错:\n[stderr]\n%s\n[stdout]\n%s"
|
||||
|
||||
#: sphinx/ext/imgmath.py:338 sphinx/ext/jsmath.py:41 sphinx/ext/mathjax.py:42
|
||||
msgid "Permalink to this equation"
|
||||
msgstr "永久链接至公式"
|
||||
msgstr "公式的永久链接"
|
||||
|
||||
#: sphinx/ext/intersphinx.py:339
|
||||
#, python-format
|
||||
@ -1047,7 +1047,7 @@ msgstr "搜索"
|
||||
|
||||
#: sphinx/themes/agogo/layout.html:54 sphinx/themes/basic/searchbox.html:16
|
||||
msgid "Go"
|
||||
msgstr "转向"
|
||||
msgstr "搜"
|
||||
|
||||
#: sphinx/themes/agogo/layout.html:81 sphinx/themes/basic/sourcelink.html:15
|
||||
msgid "Show Source"
|
||||
@ -1250,13 +1250,13 @@ msgstr "其他更改"
|
||||
#: sphinx/writers/html.py:410 sphinx/writers/html5.py:351
|
||||
#: sphinx/writers/html5.py:356
|
||||
msgid "Permalink to this headline"
|
||||
msgstr "永久链接至标题"
|
||||
msgstr "标题的永久链接"
|
||||
|
||||
#: sphinx/themes/basic/static/doctools.js_t:199 sphinx/writers/html.py:126
|
||||
#: sphinx/writers/html.py:137 sphinx/writers/html5.py:95
|
||||
#: sphinx/writers/html5.py:106
|
||||
msgid "Permalink to this definition"
|
||||
msgstr "永久链接至目标"
|
||||
msgstr "定义的永久链接"
|
||||
|
||||
#: sphinx/themes/basic/static/doctools.js_t:232
|
||||
msgid "Hide Search Matches"
|
||||
@ -1313,19 +1313,19 @@ msgstr "当添加指令类时,不应该给定额外参数"
|
||||
|
||||
#: sphinx/writers/html.py:414 sphinx/writers/html5.py:360
|
||||
msgid "Permalink to this table"
|
||||
msgstr "永久链接至表格"
|
||||
msgstr "表格的永久链接"
|
||||
|
||||
#: sphinx/writers/html.py:466 sphinx/writers/html5.py:412
|
||||
msgid "Permalink to this code"
|
||||
msgstr "永久链接至代码"
|
||||
msgstr "代码的永久链接"
|
||||
|
||||
#: sphinx/writers/html.py:470 sphinx/writers/html5.py:416
|
||||
msgid "Permalink to this image"
|
||||
msgstr "永久链接至图片"
|
||||
msgstr "图片的永久链接"
|
||||
|
||||
#: sphinx/writers/html.py:472 sphinx/writers/html5.py:418
|
||||
msgid "Permalink to this toctree"
|
||||
msgstr "永久链接至目录树"
|
||||
msgstr "目录的永久链接"
|
||||
|
||||
#: sphinx/writers/latex.py:554
|
||||
msgid "Release"
|
||||
|
@ -1046,7 +1046,7 @@ msgstr "搜尋"
|
||||
|
||||
#: sphinx/themes/agogo/layout.html:54 sphinx/themes/basic/searchbox.html:16
|
||||
msgid "Go"
|
||||
msgstr "前往"
|
||||
msgstr "搜"
|
||||
|
||||
#: sphinx/themes/agogo/layout.html:81 sphinx/themes/basic/sourcelink.html:15
|
||||
msgid "Show Source"
|
||||
|
@ -12,6 +12,7 @@ import ast
|
||||
import inspect
|
||||
import itertools
|
||||
import re
|
||||
import sys
|
||||
import tokenize
|
||||
from token import NAME, NEWLINE, INDENT, DEDENT, NUMBER, OP, STRING
|
||||
from tokenize import COMMENT, NL
|
||||
@ -27,6 +28,21 @@ indent_re = re.compile(u'^\\s*$')
|
||||
emptyline_re = re.compile(u'^\\s*(#.*)?$')
|
||||
|
||||
|
||||
if sys.version_info >= (3, 6):
|
||||
ASSIGN_NODES = (ast.Assign, ast.AnnAssign)
|
||||
else:
|
||||
ASSIGN_NODES = (ast.Assign)
|
||||
|
||||
|
||||
def get_assign_targets(node):
|
||||
# type: (ast.AST) -> List[ast.expr]
|
||||
"""Get list of targets from Assign and AnnAssign node."""
|
||||
if isinstance(node, ast.Assign):
|
||||
return node.targets
|
||||
else:
|
||||
return [node.target] # type: ignore
|
||||
|
||||
|
||||
def get_lvar_names(node, self=None):
|
||||
# type: (ast.AST, ast.expr) -> List[unicode]
|
||||
"""Convert assignment-AST to variable names.
|
||||
@ -285,7 +301,8 @@ class VariableCommentPicker(ast.NodeVisitor):
|
||||
# type: (ast.Assign) -> None
|
||||
"""Handles Assign node and pick up a variable comment."""
|
||||
try:
|
||||
varnames = sum([get_lvar_names(t, self=self.get_self()) for t in node.targets], [])
|
||||
targets = get_assign_targets(node)
|
||||
varnames = sum([get_lvar_names(t, self=self.get_self()) for t in targets], [])
|
||||
current_line = self.get_line(node.lineno)
|
||||
except TypeError:
|
||||
return # this assignment is not new definition!
|
||||
@ -321,12 +338,18 @@ class VariableCommentPicker(ast.NodeVisitor):
|
||||
for varname in varnames:
|
||||
self.add_entry(varname)
|
||||
|
||||
def visit_AnnAssign(self, node):
|
||||
# type: (ast.AST) -> None
|
||||
"""Handles AnnAssign node and pick up a variable comment."""
|
||||
self.visit_Assign(node) # type: ignore
|
||||
|
||||
def visit_Expr(self, node):
|
||||
# type: (ast.Expr) -> None
|
||||
"""Handles Expr node and pick up a comment if string."""
|
||||
if (isinstance(self.previous, ast.Assign) and isinstance(node.value, ast.Str)):
|
||||
if (isinstance(self.previous, ASSIGN_NODES) and isinstance(node.value, ast.Str)):
|
||||
try:
|
||||
varnames = get_lvar_names(self.previous.targets[0], self.get_self())
|
||||
targets = get_assign_targets(self.previous)
|
||||
varnames = get_lvar_names(targets[0], self.get_self())
|
||||
for varname in varnames:
|
||||
if isinstance(node.value.s, text_type):
|
||||
docstring = node.value.s
|
||||
|
@ -65,6 +65,9 @@ class SphinxComponentRegistry(object):
|
||||
#: autodoc documenters; a dict of documenter name -> documenter class
|
||||
self.documenters = {} # type: Dict[unicode, Type[Documenter]]
|
||||
|
||||
#: css_files; a list of tuple of filename and attributes
|
||||
self.css_files = [] # type: List[Tuple[unicode, Dict[unicode, unicode]]]
|
||||
|
||||
#: domains; a dict of domain name -> domain class
|
||||
self.domains = {} # type: Dict[unicode, Type[Domain]]
|
||||
|
||||
@ -412,6 +415,9 @@ class SphinxComponentRegistry(object):
|
||||
# type: (Type, Callable[[Any, unicode, Any], Any]) -> None
|
||||
self.autodoc_attrgettrs[typ] = attrgetter
|
||||
|
||||
def add_css_files(self, filename, **attributes):
|
||||
self.css_files.append((filename, attributes))
|
||||
|
||||
def add_latex_package(self, name, options):
|
||||
# type: (unicode, unicode) -> None
|
||||
logger.debug('[app] adding latex package: %r', name)
|
||||
|
@ -318,4 +318,4 @@ class SearchGerman(SearchLanguage):
|
||||
|
||||
def stem(self, word):
|
||||
# type: (unicode) -> unicode
|
||||
return self.stemmer.stemWord(word)
|
||||
return self.stemmer.stemWord(word.lower())
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/stable/config
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
|
@ -23,6 +23,7 @@ from sphinx.builders.latex import LaTeXBuilder
|
||||
from sphinx.ext.autodoc import AutoDirective
|
||||
from sphinx.pycode import ModuleAnalyzer
|
||||
from sphinx.testing.path import path
|
||||
from sphinx.util.osutil import relpath
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -201,7 +202,7 @@ def find_files(root, suffix=None):
|
||||
dirpath = path(dirpath)
|
||||
for f in [f for f in files if not suffix or f.endswith(suffix)]: # type: ignore
|
||||
fpath = dirpath / f
|
||||
yield os.path.relpath(fpath, root)
|
||||
yield relpath(fpath, root)
|
||||
|
||||
|
||||
def strip_escseq(text):
|
||||
|
@ -97,8 +97,8 @@
|
||||
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
|
||||
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
|
||||
{%- for css in css_files %}
|
||||
{%- if css|attr("rel") %}
|
||||
<link rel="{{ css.rel }}" href="{{ pathto(css.filename, 1) }}" type="text/css"{% if css.title is not none %} title="{{ css.title }}"{% endif %} />
|
||||
{%- if css|attr("filename") %}
|
||||
{{ css_tag(css) }}
|
||||
{%- else %}
|
||||
<link rel="stylesheet" href="{{ pathto(css, 1) }}" type="text/css" />
|
||||
{%- endif %}
|
||||
|
@ -70,7 +70,9 @@ jQuery.fn.highlightText = function(text, className) {
|
||||
if (node.nodeType === 3) {
|
||||
var val = node.nodeValue;
|
||||
var pos = val.toLowerCase().indexOf(text);
|
||||
if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
|
||||
if (pos >= 0 &&
|
||||
!jQuery(node.parentNode).hasClass(className) &&
|
||||
!jQuery(node.parentNode).hasClass("nohighlight")) {
|
||||
var span;
|
||||
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
|
||||
if (isInSVG) {
|
||||
|
@ -43,7 +43,7 @@ def extract_zip(filename, targetdir):
|
||||
"""Extract zip file to target directory."""
|
||||
ensuredir(targetdir)
|
||||
|
||||
with ZipFile(filename) as archive: # type: ignore
|
||||
with ZipFile(filename) as archive:
|
||||
for name in archive.namelist():
|
||||
if name.endswith('/'):
|
||||
continue
|
||||
@ -155,7 +155,7 @@ def is_archived_theme(filename):
|
||||
# type: (unicode) -> bool
|
||||
"""Check the specified file is an archived theme file or not."""
|
||||
try:
|
||||
with ZipFile(filename) as f: # type: ignore
|
||||
with ZipFile(filename) as f:
|
||||
return THEMECONF in f.namelist()
|
||||
except Exception:
|
||||
return False
|
||||
|
@ -44,35 +44,28 @@ default_substitutions = set([
|
||||
|
||||
|
||||
class SphinxTransform(Transform):
|
||||
"""
|
||||
A base class of Transforms.
|
||||
"""A base class of Transforms.
|
||||
|
||||
Compared with ``docutils.transforms.Transform``, this class improves accessibility to
|
||||
Sphinx APIs.
|
||||
|
||||
The subclasses can access following objects and functions:
|
||||
|
||||
self.app
|
||||
The application object (:class:`sphinx.application.Sphinx`)
|
||||
self.config
|
||||
The config object (:class:`sphinx.config.Config`)
|
||||
self.env
|
||||
The environment object (:class:`sphinx.environment.BuildEnvironment`)
|
||||
"""
|
||||
|
||||
@property
|
||||
def app(self):
|
||||
# type: () -> Sphinx
|
||||
"""Reference to the :class:`.Sphinx` object."""
|
||||
return self.document.settings.env.app
|
||||
|
||||
@property
|
||||
def env(self):
|
||||
# type: () -> BuildEnvironment
|
||||
"""Reference to the :class:`.BuildEnvironment` object."""
|
||||
return self.document.settings.env
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
# type: () -> Config
|
||||
"""Reference to the :class:`.Config` object."""
|
||||
return self.document.settings.env.config
|
||||
|
||||
|
||||
@ -350,6 +343,8 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
|
||||
|
||||
refs: sphinx.parsers.RSTParser
|
||||
"""
|
||||
default_priority = 750
|
||||
|
||||
def apply(self):
|
||||
# type: () -> None
|
||||
if not self.is_available():
|
||||
@ -404,6 +399,15 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
|
||||
yield (texttype[notsmartquotable], txtnode.astext())
|
||||
|
||||
|
||||
class DoctreeReadEvent(SphinxTransform):
|
||||
"""Emit :event:`doctree-read` event."""
|
||||
default_priority = 880
|
||||
|
||||
def apply(self):
|
||||
# type: () -> None
|
||||
self.app.emit('doctree-read', self.document)
|
||||
|
||||
|
||||
class ManpageLink(SphinxTransform):
|
||||
"""Find manpage section numbers and names"""
|
||||
default_priority = 999
|
||||
|
@ -92,8 +92,7 @@ class Locale(SphinxTransform):
|
||||
assert source.startswith(self.env.srcdir)
|
||||
docname = path.splitext(relative_path(path.join(self.env.srcdir, 'dummy'),
|
||||
source))[0]
|
||||
textdomain = find_catalog(docname,
|
||||
self.document.settings.gettext_compact)
|
||||
textdomain = find_catalog(docname, self.config.gettext_compact)
|
||||
|
||||
# fetch translations
|
||||
dirs = [path.join(self.env.srcdir, directory)
|
||||
|
@ -165,19 +165,37 @@ def get_filename_for(filename, mimetype):
|
||||
|
||||
|
||||
class ImageConverter(BaseImageConverter):
|
||||
"""A base class images converter.
|
||||
"""A base class for image converters.
|
||||
|
||||
The concrete image converters should derive this class and
|
||||
overrides the following methods and attributes:
|
||||
An image converter is kind of Docutils transform module. It is used to
|
||||
convert image files which does not supported by builder to appropriate
|
||||
format for that builder.
|
||||
|
||||
* default_priority (if needed)
|
||||
* conversion_rules
|
||||
* is_available()
|
||||
* convert()
|
||||
For example, :py:class:`LaTeX builder <.LaTeXBuilder>` supports PDF,
|
||||
PNG and JPEG as image formats. However it does not support SVG images.
|
||||
For such case, to use image converters allows to embed these
|
||||
unsupported images into the document. One of image converters;
|
||||
:ref:`sphinx.ext. imgconverter <sphinx.ext.imgconverter>` can convert
|
||||
a SVG image to PNG format using Imagemagick internally.
|
||||
|
||||
There are three steps to make your custom image converter:
|
||||
|
||||
1. Make a subclass of ``ImageConverter`` class
|
||||
2. Override ``conversion_rules``, ``is_available()`` and ``convert()``
|
||||
3. Register your image converter to Sphinx using
|
||||
:py:meth:`.Sphinx.add_post_transform`
|
||||
"""
|
||||
default_priority = 200
|
||||
|
||||
#: A conversion rules between two mimetypes which this converters supports
|
||||
#: A conversion rules the image converter supports.
|
||||
#: It is represented as a list of pair of source image format (mimetype) and
|
||||
#: destination one::
|
||||
#:
|
||||
#: conversion_rules = [
|
||||
#: ('image/svg+xml', 'image/png'),
|
||||
#: ('image/gif', 'image/png'),
|
||||
#: ('application/pdf', 'image/png'),
|
||||
#: ]
|
||||
conversion_rules = [] # type: List[Tuple[unicode, unicode]]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -216,7 +234,7 @@ class ImageConverter(BaseImageConverter):
|
||||
|
||||
def is_available(self):
|
||||
# type: () -> bool
|
||||
"""Confirms the converter is available or not."""
|
||||
"""Return the image converter is available or not."""
|
||||
raise NotImplementedError()
|
||||
|
||||
def guess_mimetypes(self, node):
|
||||
@ -255,7 +273,11 @@ class ImageConverter(BaseImageConverter):
|
||||
|
||||
def convert(self, _from, _to):
|
||||
# type: (unicode, unicode) -> bool
|
||||
"""Converts the image to expected one."""
|
||||
"""Convert a image file to expected format.
|
||||
|
||||
*_from* is a path for source image file, and *_to* is a path for
|
||||
destination file.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
|
38
sphinx/transforms/references.py
Normal file
38
sphinx/transforms/references.py
Normal file
@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinx.transforms.references
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Docutils transforms used by Sphinx.
|
||||
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.transforms.references import Substitutions
|
||||
from six import itervalues
|
||||
|
||||
from sphinx.transforms import SphinxTransform
|
||||
|
||||
|
||||
class SubstitutionDefinitionsRemover(SphinxTransform):
|
||||
"""Remove ``substitution_definition node from doctrees."""
|
||||
|
||||
# should be invoked after Substitutions process
|
||||
default_priority = Substitutions.default_priority + 1
|
||||
|
||||
def apply(self):
|
||||
# type: () -> None
|
||||
for node in self.document.traverse(nodes.substitution_definition):
|
||||
node.parent.remove(node)
|
||||
|
||||
|
||||
class SphinxDomains(SphinxTransform):
|
||||
"""Collect objects to Sphinx domains for cross references."""
|
||||
default_priority = 850
|
||||
|
||||
def apply(self):
|
||||
# type: () -> None
|
||||
for domain in itervalues(self.env.domains):
|
||||
domain.process_doc(self, self.env.docname, self.document)
|
@ -20,7 +20,7 @@ from distutils.version import LooseVersion
|
||||
import docutils
|
||||
from docutils import nodes
|
||||
from docutils.languages import get_language
|
||||
from docutils.parsers.rst import directives, roles, convert_directive_function
|
||||
from docutils.parsers.rst import Directive, directives, roles, convert_directive_function
|
||||
from docutils.statemachine import StateMachine
|
||||
from docutils.utils import Reporter
|
||||
|
||||
@ -36,6 +36,7 @@ if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Generator, Iterator, List, Set, Tuple # NOQA
|
||||
from docutils.statemachine import State, ViewList # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
from sphinx.io import SphinxFileInput # NOQA
|
||||
|
||||
@ -273,6 +274,26 @@ def switch_source_input(state, content):
|
||||
state.memo.reporter.get_source_and_line = get_source_and_line
|
||||
|
||||
|
||||
class SphinxDirective(Directive):
|
||||
"""A base class for Directives.
|
||||
|
||||
Compared with ``docutils.parsers.rst.Directive``, this class improves
|
||||
accessibility to Sphinx APIs.
|
||||
"""
|
||||
|
||||
@property
|
||||
def env(self):
|
||||
# type: () -> BuildEnvironment
|
||||
"""Reference to the :class:`.BuildEnvironment` object."""
|
||||
return self.state.document.settings.env
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
# type: () -> Config
|
||||
"""Reference to the :class:`.Config` object."""
|
||||
return self.env.config
|
||||
|
||||
|
||||
# cache a vanilla instance of nodes.document
|
||||
# Used in new_document() function
|
||||
__document_cache__ = None # type: nodes.document
|
||||
|
@ -23,7 +23,7 @@ from babel.messages.pofile import read_po
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.osutil import SEP, walk
|
||||
from sphinx.util.osutil import SEP, relpath, walk
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -97,7 +97,7 @@ def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction):
|
||||
domain = find_catalog(docname, compaction)
|
||||
files = [gettext.find(domain, path.join(srcdir, dir_), [lang]) # type: ignore
|
||||
for dir_ in locale_dirs]
|
||||
files = [path.relpath(f, srcdir) for f in files if f] # type: ignore
|
||||
files = [relpath(f, srcdir) for f in files if f] # type: ignore
|
||||
return files # type: ignore
|
||||
|
||||
|
||||
@ -138,7 +138,7 @@ def find_catalog_source_files(locale_dirs, locale, domains=None, gettext_compact
|
||||
filenames = [f for f in filenames if f.endswith('.po')]
|
||||
for filename in filenames:
|
||||
base = path.splitext(filename)[0]
|
||||
domain = path.relpath(path.join(dirpath, base), base_dir)
|
||||
domain = relpath(path.join(dirpath, base), base_dir)
|
||||
if gettext_compact and path.sep in domain:
|
||||
domain = path.split(domain)[0]
|
||||
domain = domain.replace(path.sep, SEP)
|
||||
|
@ -244,8 +244,19 @@ def object_description(object):
|
||||
except TypeError:
|
||||
pass # Cannot sort dict keys, fall back to generic repr
|
||||
else:
|
||||
items = ("%r: %r" % (key, object[key]) for key in sorted_keys)
|
||||
items = ("%s: %s" %
|
||||
(object_description(key), object_description(object[key]))
|
||||
for key in sorted_keys)
|
||||
return "{%s}" % ", ".join(items)
|
||||
if isinstance(object, set):
|
||||
try:
|
||||
sorted_values = sorted(object)
|
||||
except TypeError:
|
||||
pass # Cannot sort set values, fall back to generic repr
|
||||
else:
|
||||
template = "{%s}" if PY3 else "set([%s])"
|
||||
return template % ", ".join(object_description(x)
|
||||
for x in sorted_values)
|
||||
try:
|
||||
s = repr(object)
|
||||
except Exception:
|
||||
@ -313,7 +324,10 @@ class Signature(object):
|
||||
try:
|
||||
self.signature = inspect.signature(subject)
|
||||
except IndexError:
|
||||
if hasattr(subject, '_partialmethod'): # partialmethod with no argument
|
||||
# Until python 3.6.4, cpython has been crashed on inspection for
|
||||
# partialmethods not having any arguments.
|
||||
# https://bugs.python.org/issue33009
|
||||
if hasattr(subject, '_partialmethod'):
|
||||
self.signature = None
|
||||
self.partialmethod_with_noargs = True
|
||||
else:
|
||||
|
@ -210,14 +210,21 @@ def ustrftime(format, *args):
|
||||
return r.encode().decode('unicode-escape')
|
||||
|
||||
|
||||
def safe_relpath(path, start=None):
|
||||
def relpath(path, start=os.curdir):
|
||||
# type: (unicode, unicode) -> unicode
|
||||
"""Return a relative filepath to *path* either from the current directory or
|
||||
from an optional *start* directory.
|
||||
|
||||
This is an alternative of ``os.path.relpath()``. This returns original path
|
||||
if *path* and *start* are on different drives (for Windows platform).
|
||||
"""
|
||||
try:
|
||||
return os.path.relpath(path, start)
|
||||
except ValueError:
|
||||
return path
|
||||
|
||||
|
||||
safe_relpath = relpath # for compatibility
|
||||
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() # type: unicode
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import warnings
|
||||
from itertools import product
|
||||
from operator import itemgetter
|
||||
from uuid import uuid4
|
||||
@ -17,6 +18,7 @@ from six import iteritems
|
||||
from six.moves import cPickle as pickle
|
||||
from six.moves import range, zip_longest
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.transforms import SphinxTransform
|
||||
|
||||
if False:
|
||||
@ -155,12 +157,15 @@ def levenshtein_distance(a, b):
|
||||
|
||||
class UIDTransform(SphinxTransform):
|
||||
"""Add UIDs to doctree for versioning."""
|
||||
default_priority = 100
|
||||
default_priority = 880
|
||||
|
||||
def apply(self):
|
||||
# type: () -> None
|
||||
env = self.env
|
||||
old_doctree = None
|
||||
if not env.versioning_condition:
|
||||
return
|
||||
|
||||
if env.versioning_compare:
|
||||
# get old doctree
|
||||
try:
|
||||
@ -180,5 +185,7 @@ class UIDTransform(SphinxTransform):
|
||||
def prepare(document):
|
||||
# type: (nodes.Node) -> None
|
||||
"""Simple wrapper for UIDTransform."""
|
||||
warnings.warn('versioning.prepare() is deprecated. Use UIDTransform instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
transform = UIDTransform(document)
|
||||
transform.apply()
|
||||
|
@ -876,7 +876,7 @@ class HTMLTranslator(BaseTranslator):
|
||||
# type: (nodes.Node, unicode) -> None
|
||||
logger.warning(__('using "math" markup without a Sphinx math extension '
|
||||
'active, please use one of the math extensions '
|
||||
'described at http://sphinx-doc.org/ext/math.html'),
|
||||
'described at http://sphinx-doc.org/en/master/ext/math.html'),
|
||||
location=(self.builder.current_docname, node.line))
|
||||
raise nodes.SkipNode
|
||||
|
||||
|
@ -827,7 +827,7 @@ class HTML5Translator(BaseTranslator):
|
||||
# type: (nodes.Node, unicode) -> None
|
||||
logger.warning(__('using "math" markup without a Sphinx math extension '
|
||||
'active, please use one of the math extensions '
|
||||
'described at http://sphinx-doc.org/ext/math.html'),
|
||||
'described at http://sphinx-doc.org/en/master/ext/math.html'),
|
||||
location=(self.builder.current_docname, node.line))
|
||||
raise nodes.SkipNode
|
||||
|
||||
|
@ -23,12 +23,12 @@ from six import itervalues, text_type
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx import highlighting
|
||||
from sphinx.builders.latex.transforms import URI_SCHEMES, ShowUrlsTransform # NOQA # for compatibility
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.locale import admonitionlabels, _, __
|
||||
from sphinx.transforms import SphinxTransform
|
||||
from sphinx.util import split_into, logging
|
||||
from sphinx.util.i18n import format_date
|
||||
from sphinx.util.nodes import clean_astext, traverse_parent
|
||||
from sphinx.util.nodes import clean_astext
|
||||
from sphinx.util.template import LaTeXRenderer
|
||||
from sphinx.util.texescape import tex_escape_map, tex_replace_map
|
||||
|
||||
@ -47,7 +47,6 @@ BEGIN_DOC = r'''
|
||||
'''
|
||||
|
||||
|
||||
URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:')
|
||||
LATEXSECTIONNAMES = ["part", "chapter", "section", "subsection",
|
||||
"subsubsection", "paragraph", "subparagraph"]
|
||||
|
||||
@ -190,10 +189,11 @@ class LaTeXWriter(writers.Writer):
|
||||
# Helper classes
|
||||
|
||||
class ExtBabel(Babel):
|
||||
def __init__(self, language_code):
|
||||
# type: (unicode) -> None
|
||||
def __init__(self, language_code, use_polyglossia=False):
|
||||
# type: (unicode, bool) -> None
|
||||
super(ExtBabel, self).__init__(language_code or '')
|
||||
self.language_code = language_code
|
||||
self.use_polyglossia = use_polyglossia
|
||||
|
||||
def get_shorthandoff(self):
|
||||
# type: () -> unicode
|
||||
@ -221,116 +221,27 @@ class ExtBabel(Babel):
|
||||
def get_language(self):
|
||||
# type: () -> unicode
|
||||
language = super(ExtBabel, self).get_language()
|
||||
if not language:
|
||||
if language == 'ngerman' and self.use_polyglossia:
|
||||
# polyglossia calls new orthography (Neue Rechtschreibung) as
|
||||
# german (with new spelling option).
|
||||
return 'german'
|
||||
elif not language:
|
||||
return 'english' # fallback to english
|
||||
else:
|
||||
return language
|
||||
|
||||
|
||||
class ShowUrlsTransform(SphinxTransform, object):
|
||||
def __init__(self, document, startnode=None):
|
||||
# type: (nodes.document, nodes.Node) -> None
|
||||
super(ShowUrlsTransform, self).__init__(document, startnode)
|
||||
self.expanded = False
|
||||
|
||||
def apply(self):
|
||||
# type: () -> None
|
||||
# replace id_prefix temporarily
|
||||
id_prefix = self.document.settings.id_prefix
|
||||
self.document.settings.id_prefix = 'show_urls'
|
||||
|
||||
self.expand_show_urls()
|
||||
if self.expanded:
|
||||
self.renumber_footnotes()
|
||||
|
||||
# restore id_prefix
|
||||
self.document.settings.id_prefix = id_prefix
|
||||
|
||||
def expand_show_urls(self):
|
||||
# type: () -> None
|
||||
show_urls = self.document.settings.env.config.latex_show_urls
|
||||
if show_urls is False or show_urls == 'no':
|
||||
return
|
||||
|
||||
for node in self.document.traverse(nodes.reference):
|
||||
uri = node.get('refuri', '')
|
||||
if uri.startswith(URI_SCHEMES):
|
||||
if uri.startswith('mailto:'):
|
||||
uri = uri[7:]
|
||||
if node.astext() != uri:
|
||||
index = node.parent.index(node)
|
||||
if show_urls == 'footnote':
|
||||
footnote_nodes = self.create_footnote(uri)
|
||||
for i, fn in enumerate(footnote_nodes):
|
||||
node.parent.insert(index + i + 1, fn)
|
||||
|
||||
self.expanded = True
|
||||
else: # all other true values (b/w compat)
|
||||
textnode = nodes.Text(" (%s)" % uri)
|
||||
node.parent.insert(index + 1, textnode)
|
||||
|
||||
def create_footnote(self, uri):
|
||||
# type: (unicode) -> List[Union[nodes.footnote, nodes.footnote_ref]]
|
||||
label = nodes.label('', '#')
|
||||
para = nodes.paragraph()
|
||||
para.append(nodes.reference('', nodes.Text(uri), refuri=uri, nolinkurl=True))
|
||||
footnote = nodes.footnote(uri, label, para, auto=1)
|
||||
footnote['names'].append('#')
|
||||
self.document.note_autofootnote(footnote)
|
||||
|
||||
label = nodes.Text('#')
|
||||
footnote_ref = nodes.footnote_reference('[#]_', label, auto=1,
|
||||
refid=footnote['ids'][0])
|
||||
self.document.note_autofootnote_ref(footnote_ref)
|
||||
footnote.add_backref(footnote_ref['ids'][0])
|
||||
|
||||
return [footnote, footnote_ref]
|
||||
|
||||
def renumber_footnotes(self):
|
||||
# type: () -> None
|
||||
def is_used_number(number):
|
||||
# type: (unicode) -> bool
|
||||
for node in self.document.traverse(nodes.footnote):
|
||||
if not node.get('auto') and number in node['names']:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def is_auto_footnote(node):
|
||||
# type: (nodes.Node) -> bool
|
||||
return isinstance(node, nodes.footnote) and node.get('auto')
|
||||
|
||||
def footnote_ref_by(node):
|
||||
# type: (nodes.Node) -> Callable[[nodes.Node], bool]
|
||||
ids = node['ids']
|
||||
parent = list(traverse_parent(node, (nodes.document, addnodes.start_of_file)))[0]
|
||||
|
||||
def is_footnote_ref(node):
|
||||
# type: (nodes.Node) -> bool
|
||||
return (isinstance(node, nodes.footnote_reference) and
|
||||
ids[0] == node['refid'] and
|
||||
parent in list(traverse_parent(node)))
|
||||
|
||||
return is_footnote_ref
|
||||
|
||||
startnum = 1
|
||||
for footnote in self.document.traverse(is_auto_footnote):
|
||||
while True:
|
||||
label = str(startnum)
|
||||
startnum += 1
|
||||
if not is_used_number(label):
|
||||
break
|
||||
|
||||
old_label = footnote[0].astext()
|
||||
footnote.remove(footnote[0])
|
||||
footnote.insert(0, nodes.label('', label))
|
||||
if old_label in footnote['names']:
|
||||
footnote['names'].remove(old_label)
|
||||
footnote['names'].append(label)
|
||||
|
||||
for footnote_ref in self.document.traverse(footnote_ref_by(footnote)):
|
||||
footnote_ref.remove(footnote_ref[0])
|
||||
footnote_ref += nodes.Text(label)
|
||||
def get_mainlanguage_options(self):
|
||||
# type: () -> unicode
|
||||
"""Return options for polyglossia's ``\setmainlanguage``."""
|
||||
language = super(ExtBabel, self).get_language()
|
||||
if self.use_polyglossia is False:
|
||||
return None
|
||||
elif language == 'ngerman':
|
||||
return 'spelling=new'
|
||||
elif language == 'german':
|
||||
return 'spelling=old'
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class Table(object):
|
||||
@ -618,9 +529,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
if builder.config.language \
|
||||
and 'fncychap' not in builder.config.latex_elements:
|
||||
# use Sonny style if any language specified
|
||||
self.elements['fncychap'] = '\\usepackage[Sonny]{fncychap}'
|
||||
self.elements['fncychap'] = ('\\usepackage[Sonny]{fncychap}\n'
|
||||
'\\ChNameVar{\\Large\\normalfont'
|
||||
'\\sffamily}\n\\ChTitleVar{\\Large'
|
||||
'\\normalfont\\sffamily}')
|
||||
|
||||
self.babel = ExtBabel(builder.config.language)
|
||||
self.babel = ExtBabel(builder.config.language,
|
||||
not self.elements['babel'])
|
||||
if builder.config.language and not self.babel.is_supported_language():
|
||||
# emit warning if specified language is invalid
|
||||
# (only emitting, nothing changed to processing)
|
||||
@ -654,8 +569,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# disable fncychap in Japanese documents
|
||||
self.elements['fncychap'] = ''
|
||||
elif self.elements['polyglossia']:
|
||||
self.elements['multilingual'] = '%s\n\\setmainlanguage{%s}' % \
|
||||
(self.elements['polyglossia'], self.babel.get_language())
|
||||
options = self.babel.get_mainlanguage_options()
|
||||
if options:
|
||||
mainlanguage = r'\setmainlanguage[%s]{%s}' % (options,
|
||||
self.babel.get_language())
|
||||
else:
|
||||
mainlanguage = r'\setmainlanguage{%s}' % self.babel.get_language()
|
||||
|
||||
self.elements['multilingual'] = '%s\n%s' % (self.elements['polyglossia'],
|
||||
mainlanguage)
|
||||
|
||||
if getattr(builder, 'usepackages', None):
|
||||
def declare_package(packagename, options=None):
|
||||
@ -930,8 +852,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
|
||||
def render(self, template_name, variables):
|
||||
# type: (unicode, Dict) -> unicode
|
||||
for template_path in self.builder.config.templates_path:
|
||||
template = path.join(template_path, template_name)
|
||||
for template_dir in self.builder.config.templates_path:
|
||||
template = path.join(self.builder.confdir, template_dir,
|
||||
template_name)
|
||||
if path.exists(template):
|
||||
return LaTeXRenderer().render(template, variables)
|
||||
|
||||
@ -2501,14 +2424,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# type: (nodes.Node) -> None
|
||||
self.body.append('}}$')
|
||||
|
||||
def visit_substitution_definition(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_substitution_reference(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_inline(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
classes = node.get('classes', [])
|
||||
@ -2634,7 +2549,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# type: (nodes.Node) -> None
|
||||
logger.warning(__('using "math" markup without a Sphinx math extension '
|
||||
'active, please use one of the math extensions '
|
||||
'described at http://sphinx-doc.org/ext/math.html'),
|
||||
'described at http://sphinx-doc.org/en/master/ext/math.html'),
|
||||
location=(self.curfilestack[-1], node.line))
|
||||
raise nodes.SkipNode
|
||||
|
||||
|
@ -515,7 +515,7 @@ class ManualPageTranslator(BaseTranslator):
|
||||
# type: (nodes.Node) -> None
|
||||
logger.warning(__('using "math" markup without a Sphinx math extension '
|
||||
'active, please use one of the math extensions '
|
||||
'described at http://sphinx-doc.org/ext/math.html'))
|
||||
'described at http://sphinx-doc.org/en/master/ext/math.html'))
|
||||
raise nodes.SkipNode
|
||||
|
||||
visit_math_block = visit_math
|
||||
|
@ -1385,18 +1385,6 @@ class TexinfoTranslator(nodes.NodeVisitor):
|
||||
# type: (nodes.Node) -> None
|
||||
pass
|
||||
|
||||
def visit_substitution_reference(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
pass
|
||||
|
||||
def depart_substitution_reference(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
pass
|
||||
|
||||
def visit_substitution_definition(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_system_message(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
self.body.append('\n@verbatim\n'
|
||||
@ -1745,7 +1733,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
|
||||
# type: (nodes.Node) -> None
|
||||
logger.warning(__('using "math" markup without a Sphinx math extension '
|
||||
'active, please use one of the math extensions '
|
||||
'described at http://sphinx-doc.org/ext/math.html'))
|
||||
'described at http://sphinx-doc.org/en/master/ext/math.html'))
|
||||
raise nodes.SkipNode
|
||||
|
||||
visit_math_block = visit_math
|
||||
|
@ -987,10 +987,6 @@ class TextTranslator(nodes.NodeVisitor):
|
||||
# type: (nodes.Node) -> None
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_substitution_definition(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_pending_xref(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
pass
|
||||
@ -1185,7 +1181,7 @@ class TextTranslator(nodes.NodeVisitor):
|
||||
# type: (nodes.Node) -> None
|
||||
logger.warning(__('using "math" markup without a Sphinx math extension '
|
||||
'active, please use one of the math extensions '
|
||||
'described at http://sphinx-doc.org/ext/math.html'),
|
||||
'described at http://sphinx-doc.org/en/master/ext/math.html'),
|
||||
location=(self.builder.current_docname, node.line))
|
||||
raise nodes.SkipNode
|
||||
|
||||
|
@ -6,4 +6,6 @@ version = '1.4.4'
|
||||
|
||||
html_static_path = ['static', 'subdir']
|
||||
html_extra_path = ['extra', 'subdir']
|
||||
html_css_files = ['css/style.css',
|
||||
('https://example.com/custom.css', {'title': 'title', 'media': 'print'})]
|
||||
exclude_patterns = ['**/_build', '**/.htpasswd']
|
||||
|
0
tests/roots/test-html_assets/static/js/custom.js
Normal file
0
tests/roots/test-html_assets/static/js/custom.js
Normal file
@ -4,7 +4,7 @@ References
|
||||
Translation Tips
|
||||
-----------------
|
||||
|
||||
.. _download Sphinx: https://pypi.python.org/pypi/sphinx
|
||||
.. _download Sphinx: https://pypi.org/project/Sphinx/
|
||||
.. _Docutils site: http://docutils.sourceforge.net/
|
||||
.. _Sphinx site: http://sphinx-doc.org/
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
SALUT LES COPAINS
|
@ -15,7 +15,7 @@ normal order
|
||||
hyperref <https://sphinx-doc.org/?q=sphinx>
|
||||
|
||||
reversed order
|
||||
-------------
|
||||
--------------
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
|
@ -804,7 +804,7 @@ def test_generate():
|
||||
' .. py:attribute:: Class._private_inst_attr',
|
||||
' .. py:classmethod:: Class.inheritedclassmeth()',
|
||||
' .. py:method:: Class.inheritedmeth()',
|
||||
' .. py:staticmethod:: Class.inheritedstaticmeth()',
|
||||
' .. py:staticmethod:: Class.inheritedstaticmeth(cls)',
|
||||
],
|
||||
'class', 'Class', member_order='bysource', all_members=True)
|
||||
del directive.env.ref_context['py:module']
|
||||
@ -952,7 +952,10 @@ def test_partialmethod():
|
||||
' Update state of cell to *state*.',
|
||||
' ',
|
||||
]
|
||||
if sys.version_info < (3, 5, 4):
|
||||
if (sys.version_info < (3, 5, 4) or
|
||||
(3, 6, 5) <= sys.version_info < (3, 7) or
|
||||
(3, 7, 0, 'beta', 3) <= sys.version_info):
|
||||
# TODO: this condition should be updated after 3.7-final release.
|
||||
expected = '\n'.join(expected).replace(' -> None', '').split('\n')
|
||||
|
||||
assert call_autodoc('class', 'target.partialmethod.Cell') == expected
|
||||
|
@ -317,6 +317,34 @@ def test_epub_writing_mode(app):
|
||||
assert 'writing-mode: vertical-rl;' in css
|
||||
|
||||
|
||||
@pytest.mark.sphinx('epub', testroot='html_assets')
|
||||
def test_epub_assets(app):
|
||||
app.builder.build_all()
|
||||
|
||||
# epub_sytlesheets (same as html_css_files)
|
||||
content = (app.outdir / 'index.xhtml').text()
|
||||
assert ('<link rel="stylesheet" type="text/css" href="_static/css/style.css" />'
|
||||
in content)
|
||||
assert ('<link media="print" rel="stylesheet" title="title" type="text/css" '
|
||||
'href="https://example.com/custom.css" />' in content)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('epub', testroot='html_assets',
|
||||
confoverrides={'epub_css_files': ['css/epub.css']})
|
||||
def test_epub_css_files(app):
|
||||
app.builder.build_all()
|
||||
|
||||
# epub_css_files
|
||||
content = (app.outdir / 'index.xhtml').text()
|
||||
assert '<link rel="stylesheet" type="text/css" href="_static/css/epub.css" />' in content
|
||||
|
||||
# files in html_css_files are not outputed
|
||||
assert ('<link rel="stylesheet" type="text/css" href="_static/css/style.css" />'
|
||||
not in content)
|
||||
assert ('<link media="print" rel="stylesheet" title="title" type="text/css" '
|
||||
'href="https://example.com/custom.css" />' not in content)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('epub')
|
||||
def test_run_epubcheck(app):
|
||||
app.build()
|
||||
|
@ -1094,9 +1094,10 @@ def test_html_assets(app):
|
||||
assert not (app.outdir / '_static' / '.htpasswd').exists()
|
||||
assert (app.outdir / '_static' / 'API.html').exists()
|
||||
assert (app.outdir / '_static' / 'API.html').text() == 'Sphinx-1.4.4'
|
||||
assert (app.outdir / '_static' / 'css/style.css').exists()
|
||||
assert (app.outdir / '_static' / 'css' / 'style.css').exists()
|
||||
assert (app.outdir / '_static' / 'js' / 'custom.js').exists()
|
||||
assert (app.outdir / '_static' / 'rimg.png').exists()
|
||||
assert not (app.outdir / '_static' / '_build/index.html').exists()
|
||||
assert not (app.outdir / '_static' / '_build' / 'index.html').exists()
|
||||
assert (app.outdir / '_static' / 'background.png').exists()
|
||||
assert not (app.outdir / '_static' / 'subdir' / '.htaccess').exists()
|
||||
assert not (app.outdir / '_static' / 'subdir' / '.htpasswd').exists()
|
||||
@ -1107,11 +1108,17 @@ def test_html_assets(app):
|
||||
assert (app.outdir / 'API.html_t').exists()
|
||||
assert (app.outdir / 'css/style.css').exists()
|
||||
assert (app.outdir / 'rimg.png').exists()
|
||||
assert not (app.outdir / '_build/index.html').exists()
|
||||
assert not (app.outdir / '_build' / 'index.html').exists()
|
||||
assert (app.outdir / 'background.png').exists()
|
||||
assert (app.outdir / 'subdir' / '.htaccess').exists()
|
||||
assert not (app.outdir / 'subdir' / '.htpasswd').exists()
|
||||
|
||||
# html_css_files
|
||||
content = (app.outdir / 'index.html').text()
|
||||
assert '<link rel="stylesheet" type="text/css" href="_static/css/style.css" />' in content
|
||||
assert ('<link media="print" rel="stylesheet" title="title" type="text/css" '
|
||||
'href="https://example.com/custom.css" />' in content)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='basic', confoverrides={'html_copy_source': False})
|
||||
def test_html_copy_source(app):
|
||||
|
@ -534,6 +534,50 @@ def test_babel_with_unknown_language(app, status, warning):
|
||||
assert "WARNING: no Babel option known for language 'unknown'" in warning.getvalue()
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'latex', testroot='latex-babel',
|
||||
confoverrides={'language': 'de', 'latex_engine': 'lualatex'})
|
||||
def test_polyglossia_with_language_de(app, status, warning):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'Python.tex').text(encoding='utf8')
|
||||
print(result)
|
||||
print(status.getvalue())
|
||||
print(warning.getvalue())
|
||||
assert '\\documentclass[letterpaper,10pt,german]{sphinxmanual}' in result
|
||||
assert '\\usepackage{polyglossia}' in result
|
||||
assert '\\setmainlanguage[spelling=new]{german}' in result
|
||||
assert '\\usepackage{times}' not in result
|
||||
assert '\\usepackage[Sonny]{fncychap}' in result
|
||||
assert ('\\addto\\captionsgerman{\\renewcommand{\\contentsname}{Table of content}}\n'
|
||||
in result)
|
||||
assert '\\addto\\captionsgerman{\\renewcommand{\\figurename}{Fig.}}\n' in result
|
||||
assert '\\addto\\captionsgerman{\\renewcommand{\\tablename}{Table.}}\n' in result
|
||||
assert '\\def\\pageautorefname{Seite}\n' in result
|
||||
assert '\\shorthandoff' not in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'latex', testroot='latex-babel',
|
||||
confoverrides={'language': 'de-1901', 'latex_engine': 'lualatex'})
|
||||
def test_polyglossia_with_language_de_1901(app, status, warning):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'Python.tex').text(encoding='utf8')
|
||||
print(result)
|
||||
print(status.getvalue())
|
||||
print(warning.getvalue())
|
||||
assert '\\documentclass[letterpaper,10pt,german]{sphinxmanual}' in result
|
||||
assert '\\usepackage{polyglossia}' in result
|
||||
assert '\\setmainlanguage[spelling=old]{german}' in result
|
||||
assert '\\usepackage{times}' not in result
|
||||
assert '\\usepackage[Sonny]{fncychap}' in result
|
||||
assert ('\\addto\\captionsgerman{\\renewcommand{\\contentsname}{Table of content}}\n'
|
||||
in result)
|
||||
assert '\\addto\\captionsgerman{\\renewcommand{\\figurename}{Fig.}}\n' in result
|
||||
assert '\\addto\\captionsgerman{\\renewcommand{\\tablename}{Table.}}\n' in result
|
||||
assert '\\def\\pageautorefname{page}\n' in result
|
||||
assert '\\shorthandoff' not in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex')
|
||||
def test_footnote(app, status, warning):
|
||||
app.builder.build_all()
|
||||
@ -750,6 +794,15 @@ def test_latex_show_urls_is_no(app, status, warning):
|
||||
'{sphinx-dev@googlegroups.com}\n') in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'latex', testroot='footnotes',
|
||||
confoverrides={'latex_show_urls': 'footnote',
|
||||
'rst_prolog': '.. |URL| replace:: `text <http://www.example.com/>`__'})
|
||||
def test_latex_show_urls_footnote_and_substitutions(app, status, warning):
|
||||
# hyperlinks in substitutions should not effect to make footnotes (refs: #4784)
|
||||
test_latex_show_urls_is_footnote(app, status, warning)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='image-in-section')
|
||||
def test_image_in_section(app, status, warning):
|
||||
app.builder.build_all()
|
||||
@ -1098,6 +1151,30 @@ def test_latex_table_complex_tables(app, status, warning):
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='latex-table',
|
||||
confoverrides={'templates_path': ['_mytemplates/latex']})
|
||||
def test_latex_table_custom_template_caseA(app, status, warning):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'test.tex').text(encoding='utf8')
|
||||
assert 'SALUT LES COPAINS' in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='latex-table',
|
||||
confoverrides={'templates_path': ['_mytemplates']})
|
||||
def test_latex_table_custom_template_caseB(app, status, warning):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'test.tex').text(encoding='utf8')
|
||||
assert 'SALUT LES COPAINS' not in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='latex-table')
|
||||
@pytest.mark.test_params(shared_result='latex-table')
|
||||
def test_latex_table_custom_template_caseC(app, status, warning):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'test.tex').text(encoding='utf8')
|
||||
assert 'SALUT LES COPAINS' not in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='directives-raw')
|
||||
def test_latex_raw_directive(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
153
tests/test_directive_other.py
Normal file
153
tests/test_directive_other.py
Normal file
@ -0,0 +1,153 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
test_directive_other
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test the other directives.
|
||||
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from docutils import nodes
|
||||
from docutils.core import publish_doctree
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.io import SphinxStandaloneReader
|
||||
from sphinx.parsers import RSTParser
|
||||
from sphinx.testing.util import assert_node
|
||||
|
||||
|
||||
def parse(app, docname, text):
|
||||
app.env.temp_data['docname'] = docname
|
||||
return publish_doctree(text, app.srcdir / docname + '.rst',
|
||||
reader=SphinxStandaloneReader(app),
|
||||
parser=RSTParser(),
|
||||
settings_overrides={'env': app.env,
|
||||
'gettext_compact': True})
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='toctree-glob')
|
||||
def test_toctree(app):
|
||||
text = (".. toctree::\n"
|
||||
"\n"
|
||||
" foo\n"
|
||||
" bar/index\n"
|
||||
" baz\n")
|
||||
|
||||
app.env.find_files(app.config, app.builder)
|
||||
doctree = parse(app, 'index', text)
|
||||
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
|
||||
assert_node(doctree[0][0],
|
||||
entries=[(None, 'foo'), (None, 'bar/index'), (None, 'baz')],
|
||||
includefiles=['foo', 'bar/index', 'baz'])
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='toctree-glob')
|
||||
def test_relative_toctree(app):
|
||||
text = (".. toctree::\n"
|
||||
"\n"
|
||||
" bar_1\n"
|
||||
" bar_2\n"
|
||||
" bar_3\n"
|
||||
" ../quux\n")
|
||||
|
||||
app.env.find_files(app.config, app.builder)
|
||||
doctree = parse(app, 'bar/index', text)
|
||||
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
|
||||
assert_node(doctree[0][0],
|
||||
entries=[(None, 'bar/bar_1'), (None, 'bar/bar_2'), (None, 'bar/bar_3'),
|
||||
(None, 'quux')],
|
||||
includefiles=['bar/bar_1', 'bar/bar_2', 'bar/bar_3', 'quux'])
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='toctree-glob')
|
||||
def test_toctree_urls_and_titles(app):
|
||||
text = (".. toctree::\n"
|
||||
"\n"
|
||||
" Sphinx <https://www.sphinx-doc.org/>\n"
|
||||
" https://readthedocs.org/\n"
|
||||
" The BAR <bar/index>\n")
|
||||
|
||||
app.env.find_files(app.config, app.builder)
|
||||
doctree = parse(app, 'index', text)
|
||||
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
|
||||
assert_node(doctree[0][0],
|
||||
entries=[('Sphinx', 'https://www.sphinx-doc.org/'),
|
||||
(None, 'https://readthedocs.org/'),
|
||||
('The BAR', 'bar/index')],
|
||||
includefiles=['bar/index'])
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='toctree-glob')
|
||||
def test_toctree_glob(app):
|
||||
text = (".. toctree::\n"
|
||||
" :glob:\n"
|
||||
"\n"
|
||||
" *\n")
|
||||
|
||||
app.env.find_files(app.config, app.builder)
|
||||
doctree = parse(app, 'index', text)
|
||||
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
|
||||
assert_node(doctree[0][0],
|
||||
entries=[(None, 'baz'), (None, 'foo'), (None, 'quux')],
|
||||
includefiles=['baz', 'foo', 'quux'])
|
||||
|
||||
# give both docname and glob (case1)
|
||||
text = (".. toctree::\n"
|
||||
" :glob:\n"
|
||||
"\n"
|
||||
" foo\n"
|
||||
" *\n")
|
||||
|
||||
app.env.find_files(app.config, app.builder)
|
||||
doctree = parse(app, 'index', text)
|
||||
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
|
||||
assert_node(doctree[0][0],
|
||||
entries=[(None, 'foo'), (None, 'baz'), (None, 'quux')],
|
||||
includefiles=['foo', 'baz', 'quux'])
|
||||
|
||||
# give both docname and glob (case2)
|
||||
text = (".. toctree::\n"
|
||||
" :glob:\n"
|
||||
"\n"
|
||||
" *\n"
|
||||
" foo\n")
|
||||
|
||||
app.env.find_files(app.config, app.builder)
|
||||
doctree = parse(app, 'index', text)
|
||||
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
|
||||
assert_node(doctree[0][0],
|
||||
entries=[(None, 'baz'), (None, 'foo'), (None, 'quux'), (None, 'foo')],
|
||||
includefiles=['baz', 'foo', 'quux', 'foo'])
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='toctree-glob')
|
||||
def test_toctree_glob_and_url(app):
|
||||
text = (".. toctree::\n"
|
||||
" :glob:\n"
|
||||
"\n"
|
||||
" https://example.com/?q=sphinx\n")
|
||||
|
||||
app.env.find_files(app.config, app.builder)
|
||||
doctree = parse(app, 'index', text)
|
||||
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
|
||||
assert_node(doctree[0][0],
|
||||
entries=[(None, 'https://example.com/?q=sphinx')],
|
||||
includefiles=[])
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='toctree-glob')
|
||||
def test_toctree_twice(app):
|
||||
text = (".. toctree::\n"
|
||||
"\n"
|
||||
" foo\n"
|
||||
" foo\n")
|
||||
|
||||
app.env.find_files(app.config, app.builder)
|
||||
doctree = parse(app, 'index', text)
|
||||
assert_node(doctree, [nodes.document, nodes.compound, addnodes.toctree])
|
||||
assert_node(doctree[0][0],
|
||||
entries=[(None, 'foo'), (None, 'foo')],
|
||||
includefiles=['foo', 'foo'])
|
@ -188,6 +188,16 @@ def test_autosummary_generate(app, status, warning):
|
||||
' \n' in Foo)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', **default_kw)
|
||||
def test_autosummary_latex_table_colspec(app, status, warning):
|
||||
app.builder.build_all()
|
||||
result = (app.outdir / 'Python.tex').text(encoding='utf8')
|
||||
print(status.getvalue())
|
||||
print(warning.getvalue())
|
||||
assert r'\begin{longtable}{\X{1}{2}\X{1}{2}}' in result
|
||||
assert r'p{0.5\linewidth}' not in result
|
||||
|
||||
|
||||
def test_import_by_name():
|
||||
import sphinx
|
||||
import sphinx.ext.autosummary
|
||||
|
@ -35,19 +35,19 @@ def test_jsmath(app, status, warning):
|
||||
app.builder.build_all()
|
||||
content = (app.outdir / 'math.html').text()
|
||||
|
||||
assert '<div class="math notranslate">\na^2 + b^2 = c^2</div>' in content
|
||||
assert ('<div class="math notranslate">\n\\begin{split}a + 1 < b\\end{split}</div>'
|
||||
in content)
|
||||
assert '<div class="math notranslate nohighlight">\na^2 + b^2 = c^2</div>' in content
|
||||
assert ('<div class="math notranslate nohighlight">\n\\begin{split}a + 1 < '
|
||||
'b\\end{split}</div>' in content)
|
||||
assert (u'<span class="eqno">(1)<a class="headerlink" href="#equation-foo" '
|
||||
u'title="Permalink to this equation">\xb6</a></span>'
|
||||
u'<div class="math notranslate" id="equation-foo">\ne^{i\\pi} = 1</div>'
|
||||
in content)
|
||||
u'<div class="math notranslate nohighlight" id="equation-foo">'
|
||||
'\ne^{i\\pi} = 1</div>' in content)
|
||||
assert (u'<span class="eqno">(2)<a class="headerlink" href="#equation-math-0" '
|
||||
u'title="Permalink to this equation">\xb6</a></span>'
|
||||
u'<div class="math notranslate" id="equation-math-0">\n'
|
||||
u'<div class="math notranslate nohighlight" id="equation-math-0">\n'
|
||||
u'e^{ix} = \\cos x + i\\sin x</div>' in content)
|
||||
assert '<div class="math notranslate">\nn \\in \\mathbb N</div>' in content
|
||||
assert '<div class="math notranslate">\na + 1 < b</div>' in content
|
||||
assert '<div class="math notranslate nohighlight">\nn \\in \\mathbb N</div>' in content
|
||||
assert '<div class="math notranslate nohighlight">\na + 1 < b</div>' in content
|
||||
|
||||
|
||||
@pytest.mark.skipif(not has_binary('dvipng'),
|
||||
@ -91,7 +91,7 @@ def test_mathjax_align(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
content = (app.outdir / 'index.html').text()
|
||||
html = (r'<div class="math notranslate">\s*'
|
||||
html = (r'<div class="math notranslate nohighlight">\s*'
|
||||
r'\\\[ \\begin\{align\}\\begin\{aligned\}S \&= \\pi r\^2\\\\'
|
||||
r'V \&= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]</div>')
|
||||
assert re.search(html, content, re.S)
|
||||
@ -104,7 +104,7 @@ def test_math_number_all_mathjax(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
content = (app.outdir / 'index.html').text()
|
||||
html = (r'<div class="math notranslate" id="equation-index-0">\s*'
|
||||
html = (r'<div class="math notranslate nohighlight" id="equation-index-0">\s*'
|
||||
r'<span class="eqno">\(1\)<a .*>\xb6</a></span>\\\[a\^2\+b\^2=c\^2\\\]</div>')
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
@ -169,7 +169,7 @@ def test_mathjax_numfig_html(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
content = (app.outdir / 'math.html').text()
|
||||
html = ('<div class="math notranslate" id="equation-math-0">\n'
|
||||
html = ('<div class="math notranslate nohighlight" id="equation-math-0">\n'
|
||||
'<span class="eqno">(1.2)')
|
||||
assert html in content
|
||||
html = ('<p>Referencing equation <a class="reference internal" '
|
||||
|
@ -9,6 +9,8 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from six import PY2
|
||||
|
||||
@ -94,6 +96,18 @@ def test_comment_picker_location():
|
||||
('Foo', 'attr3'): 'comment for attr3(3)'}
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason='tests for py36+ syntax')
|
||||
def test_annotated_assignment_py36():
|
||||
source = ('a: str = "Sphinx" #: comment\n'
|
||||
'b: int = 1\n'
|
||||
'"""string on next line"""')
|
||||
parser = Parser(source)
|
||||
parser.parse()
|
||||
assert parser.comments == {('', 'a'): 'comment',
|
||||
('', 'b'): 'string on next line'}
|
||||
assert parser.definitions == {}
|
||||
|
||||
|
||||
def test_complex_assignment():
|
||||
source = ('a = 1 + 1; b = a #: compound statement\n'
|
||||
'c, d = (1, 1) #: unpack assignment\n'
|
||||
|
@ -346,6 +346,24 @@ def test_dictionary_sorting():
|
||||
assert description == "{'a': 1, 'b': 4, 'c': 3, 'd': 2}"
|
||||
|
||||
|
||||
def test_set_sorting():
|
||||
set_ = set("gfedcba")
|
||||
description = inspect.object_description(set_)
|
||||
if PY3:
|
||||
assert description == "{'a', 'b', 'c', 'd', 'e', 'f', 'g'}"
|
||||
else:
|
||||
assert description == "set(['a', 'b', 'c', 'd', 'e', 'f', 'g'])"
|
||||
|
||||
|
||||
def test_set_sorting_fallback():
|
||||
set_ = set((None, 1))
|
||||
description = inspect.object_description(set_)
|
||||
if PY3:
|
||||
assert description in ("{1, None}", "{None, 1}")
|
||||
else:
|
||||
assert description in ("set([1, None])", "set([None, 1])")
|
||||
|
||||
|
||||
def test_dict_customtype():
|
||||
class CustomType(object):
|
||||
def __init__(self, value):
|
||||
|
@ -12,7 +12,7 @@ for stable releases
|
||||
* ``git commit -am 'Bump to X.Y.Z final'``
|
||||
* ``make clean``
|
||||
* ``python setup.py release bdist_wheel sdist upload --identity=[your key]``
|
||||
* open https://pypi.python.org/pypi/Sphinx and check there are no obvious errors
|
||||
* open https://pypi.org/project/Sphinx/ and check there are no obvious errors
|
||||
* ``git tag vX.Y.Z``
|
||||
* ``python utils/bump_version.py --in-develop X.Y.Zb0`` (ex. 1.5.3b0)
|
||||
* Check diff by ``git diff``
|
||||
@ -38,7 +38,7 @@ for first beta releases
|
||||
* ``git commit -am 'Bump to X.Y.0 beta1'``
|
||||
* ``make clean``
|
||||
* ``python setup.py release bdist_wheel sdist upload --identity=[your key]``
|
||||
* open https://pypi.python.org/pypi/Sphinx and check there are no obvious errors
|
||||
* open https://pypi.org/project/Sphinx/ and check there are no obvious errors
|
||||
* ``git tag vX.Y.0b1``
|
||||
* ``python utils/bump_version.py --in-develop X.Y.0b2`` (ex. 1.6.0b2)
|
||||
* Check diff by ``git diff``
|
||||
@ -67,7 +67,7 @@ for other beta releases
|
||||
* ``git commit -am 'Bump to X.Y.0 betaN'``
|
||||
* ``make clean``
|
||||
* ``python setup.py release bdist_wheel sdist upload --identity=[your key]``
|
||||
* open https://pypi.python.org/pypi/Sphinx and check there are no obvious errors
|
||||
* open https://pypi.org/project/Sphinx/ and check there are no obvious errors
|
||||
* ``git tag vX.Y.0bN``
|
||||
* ``python utils/bump_version.py --in-develop X.Y.0bM`` (ex. 1.6.0b3)
|
||||
* Check diff by `git diff``
|
||||
@ -95,7 +95,7 @@ for major releases
|
||||
* ``git commit -am 'Bump to X.Y.0 final'``
|
||||
* ``make clean``
|
||||
* ``python setup.py release bdist_wheel sdist upload --identity=[your key]``
|
||||
* open https://pypi.python.org/pypi/Sphinx and check there are no obvious errors
|
||||
* open https://pypi.org/project/Sphinx/ and check there are no obvious errors
|
||||
* ``git tag vX.Y.0``
|
||||
* ``python utils/bump_version.py --in-develop X.Y.1b0`` (ex. 1.6.1b0)
|
||||
* Check diff by ``git diff``
|
||||
|
Loading…
Reference in New Issue
Block a user