diff --git a/CHANGES b/CHANGES index 1bf3f113c..ada67e572 100644 --- a/CHANGES +++ b/CHANGES @@ -34,9 +34,10 @@ Incompatible changes * #1857: latex: :confval:`latex_show_pagerefs` does not add pagerefs for citations * #4648: latex: Now "rubric" elements are rendered as unnumbered section title -* #4983: html: The URL for the productionlist has been changed +* #4983: html: The anchor for productionlist tokens has been changed * Modifying a template variable ``script_files`` in templates is allowed now. Please use ``app.add_js_file()`` instead. +* #5072: Save environment object also with only new documents * #5035: qthelp builder allows dashes in :confval:`qthelp_namespace` Deprecated @@ -138,6 +139,9 @@ Features added * html: Output ``canonical_url`` metadata if :confval:`html_baseurl` set (refs: #4193) * #5029: autosummary: expose ``inherited_members`` to template +* #3784: mathjax: Add :confval:`mathjax_options` to give options to script tag + for mathjax +* #4362: latex: Don't overwrite .tex file if document not changed Bugs fixed ---------- @@ -156,6 +160,11 @@ Features removed * ``sphinx.ext.pngmath`` extension +Documentation +------------- + +* #5083: Fix wrong make.bat option for internationalization. + Release 1.7.6 (in development) ============================== @@ -187,6 +196,8 @@ Bugs fixed * #5019: autodoc: crashed by Form Feed Character * #5032: autodoc: loses the first staticmethod parameter for old styled classes * #5036: quickstart: Typing Ctrl-U clears the whole of line +* #5066: html: "relations" sidebar is not shown by default +* #5091: latex: curly braces in index entries are not handled correctly Testing -------- diff --git a/EXAMPLES b/EXAMPLES index ee9d4a128..94aade9bc 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -195,6 +195,7 @@ Documentation using sphinx_rtd_theme * Julia: https://julia.readthedocs.io/ * Jupyter Notebook: https://jupyter-notebook.readthedocs.io/ * Lasagne: https://lasagne.readthedocs.io/ +* latexindent.pl: https://latexindentpl.readthedocs.io/ * Linguistica: https://linguistica-uchicago.github.io/lxa5/ * Linux kernel: https://www.kernel.org/doc/html/latest/index.html * MathJax: https://docs.mathjax.org/ diff --git a/doc/Makefile b/doc/Makefile index 293ccca2e..4d2067071 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,9 +1,10 @@ # Makefile for Sphinx documentation # +PYTHON ?= python # You can set these variables from the command line. SPHINXOPTS = -SPHINXBUILD = python3 ../sphinx/cmd/build.py +SPHINXBUILD = $(PYTHON) ../sphinx/cmd/build.py SPHINXPROJ = sphinx SOURCEDIR = . BUILDDIR = _build diff --git a/doc/_templates/indexsidebar.html b/doc/_templates/indexsidebar.html index e1747c762..94174ce90 100644 --- a/doc/_templates/indexsidebar.html +++ b/doc/_templates/indexsidebar.html @@ -3,19 +3,9 @@ {%trans%}project{%endtrans%}

Download

-{% if version.endswith('+') %} -

{%trans%}This documentation is for version {{ version }}, which is - not released yet.{%endtrans%}

-

{%trans%}You can use it from the - Git repo or look for - released versions in the Python - Package Index.{%endtrans%}

-{% else %} -

{%trans%}Current version: {{ version }}{%endtrans%}

-

{%trans%}Get Sphinx from the Python Package -Index, or install it with:{%endtrans%}

+

{%trans%}Current version: {%endtrans%}

+

{%trans%}Install Sphinx with:{%endtrans%}

pip install -U Sphinx
-{% endif %}

{%trans%}Questions? Suggestions?{%endtrans%}

diff --git a/doc/_themes/sphinx13/static/sphinx13.css b/doc/_themes/sphinx13/static/sphinx13.css index eff18df3c..c2afc2a7c 100644 --- a/doc/_themes/sphinx13/static/sphinx13.css +++ b/doc/_themes/sphinx13/static/sphinx13.css @@ -140,6 +140,10 @@ div.sphinxsidebar .logo img { vertical-align: middle; } +div.sphinxsidebar .download a img { + vertical-align: middle; +} + div.subscribeformwrapper { display: block; overflow: auto; diff --git a/doc/ext/math.rst b/doc/ext/math.rst index c00713a3d..c299b7bee 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -260,6 +260,16 @@ Sphinx. You can also give a full ``https://`` URL different from the CDN URL. +.. confval:: mathjax_options + + The options to script tag for mathjax. For example, you can set integrity + option with following setting:: + + mathjax_options = { + 'integrity': 'sha384-......', + } + + The default is empty (``{}``). :mod:`sphinx.ext.jsmath` -- Render math via JavaScript ------------------------------------------------------ diff --git a/doc/intl.rst b/doc/intl.rst index 43f620bd0..129665dde 100644 --- a/doc/intl.rst +++ b/doc/intl.rst @@ -123,14 +123,14 @@ This section describe an easy way to translate with sphinx-intl. .. code-block:: console - > set SPHINXOPTS=-D language='de' + > set SPHINXOPTS=-D language=de > .\make.bat html command line (for PowerShell): .. code-block:: console - > Set-Item env:SPHINXOPTS "-D language='de'" + > Set-Item env:SPHINXOPTS "-D language=de" > .\make.bat html diff --git a/doc/make.bat b/doc/make.bat index 0a4bd77b9..1e6dc991e 100644 --- a/doc/make.bat +++ b/doc/make.bat @@ -3,7 +3,7 @@ REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=python ../sphinx-build.py + set SPHINXBUILD=python ../sphinx/cmd/build.py ) set SOURCEDIR=. set BUILDDIR=_build diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 7cfacbd3c..e446ca94a 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -372,14 +372,14 @@ class Builder(object): else: logger.info(__('none found')) - if updated_docnames: - # save the environment - from sphinx.application import ENV_PICKLE_FILENAME - logger.info(bold(__('pickling environment... ')), nonl=True) - with open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f: - pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL) - logger.info(__('done')) + # save the environment + from sphinx.application import ENV_PICKLE_FILENAME + logger.info(bold(__('pickling environment... ')), nonl=True) + with open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f: + pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL) + logger.info(__('done')) + if updated_docnames: # global actions self.app.phase = BuildPhase.CONSISTENCY_CHECK logger.info(bold(__('checking consistency... ')), nonl=True) diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index b98d4104a..62e0a28d7 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -1014,19 +1014,27 @@ class StandaloneHTMLBuilder(Builder): def has_wildcard(pattern): # type: (unicode) -> bool return any(char in pattern for char in '*?[') - sidebars = self.theme.get_config('theme', 'sidebars', None) + sidebars = None matched = None customsidebar = None # default sidebars settings for selected theme - theme_default_sidebars = self.theme.get_config('theme', 'sidebars', None) - if theme_default_sidebars: - sidebars = [name.strip() for name in theme_default_sidebars.split(',')] - elif self.theme.name == 'alabaster': + if self.theme.name == 'alabaster': # provide default settings for alabaster (for compatibility) # Note: this will be removed before Sphinx-2.0 - sidebars = ['about.html', 'navigation.html', 'relation.html', - 'searchbox.html', 'donate.html'] + try: + # get default sidebars settings from alabaster (if defined) + theme_default_sidebars = self.theme.config.get('theme', 'sidebars') + if theme_default_sidebars: + sidebars = [name.strip() for name in theme_default_sidebars.split(',')] + except Exception: + # fallback to better default settings + sidebars = ['about.html', 'navigation.html', 'relations.html', + 'searchbox.html', 'donate.html'] + else: + theme_default_sidebars = self.theme.get_config('theme', 'sidebars', None) + if theme_default_sidebars: + sidebars = [name.strip() for name in theme_default_sidebars.split(',')] # user sidebar settings for pattern, patsidebars in iteritems(self.config.html_sidebars): diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index 32e813241..382914731 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -13,7 +13,6 @@ import os from os import path from docutils.frontend import OptionParser -from docutils.io import FileOutput from six import text_type from sphinx import package_dir, addnodes, highlighting @@ -31,7 +30,7 @@ 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 +from sphinx.util.docutils import SphinxFileOutput, new_document from sphinx.util.fileutil import copy_asset_file from sphinx.util.nodes import inline_all_toctrees from sphinx.util.osutil import SEP, make_filename @@ -134,9 +133,8 @@ class LaTeXBuilder(Builder): toctree_only = False if len(entry) > 5: toctree_only = entry[5] - destination = FileOutput( - destination_path=path.join(self.outdir, targetname), - encoding='utf-8') + destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname), + encoding='utf-8', overwrite_if_changed=True) logger.info(__("processing %s..."), targetname, nonl=1) toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree) if toctrees: diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index 8aeafefc7..0d73f3d3d 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -74,6 +74,8 @@ def builder_inited(app): 'mathjax extension to work') if app.builder.format == 'html': options = {'async': 'async'} + if app.config.mathjax_options: + options.update(app.config.mathjax_options) app.builder.add_js_file(app.config.mathjax_path, **options) # type: ignore @@ -88,7 +90,8 @@ def setup(app): # https://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn app.add_config_value('mathjax_path', 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?' - 'config=TeX-AMS-MML_HTMLorMML', False) + 'config=TeX-AMS-MML_HTMLorMML', 'html') + app.add_config_value('mathjax_options', {}, 'html') app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html') app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html') app.connect('builder-inited', builder_inited) diff --git a/sphinx/themes/basic/search.html b/sphinx/themes/basic/search.html index 6264d0414..57030d83a 100644 --- a/sphinx/themes/basic/search.html +++ b/sphinx/themes/basic/search.html @@ -9,10 +9,10 @@ #} {%- extends "layout.html" %} {% set title = _('Search') %} -{%- macro script() %} +{%- block scripts %} {{ super() }} -{%- endmacro %} +{%- endblock %} {% block extrahead %} -{%- endmacro %} +{%- endblock %} {# put the sidebar before the body #} {% block sidebar1 %}{{ sidebar() }}{% endblock %} diff --git a/sphinx/themes/classic/layout.html b/sphinx/themes/classic/layout.html index 3ba9ad57f..8042e3f7e 100644 --- a/sphinx/themes/classic/layout.html +++ b/sphinx/themes/classic/layout.html @@ -10,8 +10,8 @@ {%- extends "basic/layout.html" %} {% if theme_collapsiblesidebar|tobool %} -{%- macro script() %} +{%- block scripts %} {{ super() }} -{%- endmacro %} +{%- endblock %} {% endif %} diff --git a/sphinx/themes/scrolls/layout.html b/sphinx/themes/scrolls/layout.html index 1b58a6d46..7bb7b19e3 100644 --- a/sphinx/themes/scrolls/layout.html +++ b/sphinx/themes/scrolls/layout.html @@ -13,10 +13,10 @@ {{ super() }} {%- endblock %} -{%- macro script() %} +{%- block scripts %} {{ super() }} -{%- endmacro %} +{%- endblock %} {# do not display relbars #} {% block relbar1 %}{% endblock %} {% block relbar2 %}{% endblock %} diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index d96ab843c..547d74c17 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -10,6 +10,7 @@ """ from __future__ import absolute_import +import codecs import os import re import types @@ -21,6 +22,7 @@ from os import path import docutils from docutils import nodes +from docutils.io import FileOutput from docutils.parsers.rst import Directive, directives, roles, convert_directive_function from docutils.statemachine import StateMachine from docutils.utils import Reporter @@ -300,6 +302,26 @@ def switch_source_input(state, content): state.memo.reporter.get_source_and_line = get_source_and_line +class SphinxFileOutput(FileOutput): + """Better FileOutput class for Sphinx.""" + + def __init__(self, **kwargs): + # type: (Any) -> None + self.overwrite_if_changed = kwargs.pop('overwrite_if_changed', False) + FileOutput.__init__(self, **kwargs) + + def write(self, data): + # type: (unicode) -> unicode + if (self.destination_path and self.autoclose and 'b' not in self.mode and + self.overwrite_if_changed and os.path.exists(self.destination_path)): + with codecs.open(self.destination_path, encoding=self.encoding) as f: + # skip writing: content not changed + if f.read() == data: + return data + + return FileOutput.write(self, data) + + class SphinxDirective(Directive): """A base class for Sphinx directives. diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index db58780f1..e4fdf3ca1 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1894,8 +1894,8 @@ class LaTeXTranslator(nodes.NodeVisitor): # type: (nodes.Node, Pattern) -> None def escape(value): value = self.encode(value) - value = value.replace(r'\{', r'\sphinxleftcurlybrace') - value = value.replace(r'\}', r'\sphinxrightcurlybrace') + value = value.replace(r'\{', r'{\sphinxleftcurlybrace}') + value = value.replace(r'\}', r'{\sphinxrightcurlybrace}') return value if not node.get('inline', True): diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 50e323a23..68017a80d 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1245,21 +1245,50 @@ def test_html_remote_images(app, status, warning): @pytest.mark.sphinx('html', testroot='basic') def test_html_sidebar(app, status, warning): + ctx = {} + + # default for alabaster app.builder.build_all() result = (app.outdir / 'index.html').text(encoding='utf8') - assert '

Table Of Contents

' in result + assert ('