Skip to content

Commit

Permalink
Merge branch '5.2.x' into 5.x
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGES
#	sphinx/__init__.py
  • Loading branch information
AA-Turner committed Sep 30, 2022
2 parents 7514e5c + cbb19d6 commit 2906071
Show file tree
Hide file tree
Showing 13 changed files with 76 additions and 16 deletions.
7 changes: 7 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ Bugs fixed
Testing
--------

Release 5.2.3 (released Sep 30, 2022)
=====================================

* #10878: Fix base64 image embedding in ``sphinx.ext.imgmath``
* #10886: Add ``:nocontentsentry:`` flag and global domain table of contents
entry control option. Patch by Adam Turner

Release 5.2.2 (released Sep 27, 2022)
=====================================

Expand Down
5 changes: 5 additions & 0 deletions doc/usage/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,11 @@ General configuration
:term:`object` names (for object types where a "module" of some kind is
defined), e.g. for :rst:dir:`py:function` directives. Default is ``True``.

.. confval:: toc_object_entries

Create table of contents entries for domain objects (e.g. functions, classes,
attributes, etc.). Default is ``True``.

.. confval:: toc_object_entries_show_parents

A string that determines how domain objects (e.g. functions, classes,
Expand Down
42 changes: 34 additions & 8 deletions doc/usage/restructuredtext/domains.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,15 @@ Basic Markup
Most domains provide a number of :dfn:`object description directives`, used to
describe specific objects provided by modules. Each directive requires one or
more signatures to provide basic information about what is being described, and
the content should be the description. A domain will typically keep an
internal index of all entities to aid cross-referencing. Typically it will
also add entries in the shown general index.
the content should be the description.

A domain will typically keep an internal index of all entities to aid
cross-referencing.
Typically it will also add entries in the shown general index.
If you want to suppress the addition of an entry in the shown index, you can
give the directive option flag ``:noindexentry:``.
If you want to exclude the object description from the table of contents, you
can give the directive option flag ``:nocontentsentry:``.
If you want to typeset an object description, without even making it available
for cross-referencing, you can give the directive option flag ``:noindex:``
(which implies ``:noindexentry:``).
Expand All @@ -57,6 +61,10 @@ options.
The directive option ``noindexentry`` in the Python, C, C++, and Javascript
domains.

.. versionadded:: 5.2.3
The directive option ``:nocontentsentry:`` in the Python, C, C++, Javascript,
and reStructuredText domains.

An example using a Python domain directive::

.. py:function:: spam(eggs)
Expand Down Expand Up @@ -862,15 +870,19 @@ Example::
This will be rendered as:
.. c:struct:: Data
:nocontentsentry:
:noindexentry:
.. c:union:: @data
:nocontentsentry:
:noindexentry:
.. c:var:: int a
:nocontentsentry:
:noindexentry:
.. c:var:: double b
:nocontentsentry:
:noindexentry:
Explicit ref: :c:var:`Data.@data.a`. Short-hand ref: :c:var:`Data.a`.
Expand Down Expand Up @@ -953,9 +965,11 @@ Inline Expressions and Types
will be rendered as follows:
.. c:var:: int a = 42
:nocontentsentry:
:noindexentry:
.. c:function:: int f(int i)
:nocontentsentry:
:noindexentry:
An expression: :c:expr:`a * f(a)` (or as text: :c:texpr:`a * f(a)`).
Expand Down Expand Up @@ -1166,23 +1180,27 @@ visibility statement (``public``, ``private`` or ``protected``).
The example are rendered as follows.
.. cpp:type:: std::vector<int> MyList
:noindex:
:nocontentsentry:
:noindexentry:
A typedef-like declaration of a type.
.. cpp:type:: MyContainer::const_iterator
:noindex:
:nocontentsentry:
:noindexentry:
Declaration of a type alias with unspecified type.
.. cpp:type:: MyType = std::unordered_map<int, std::string>
:noindex:
:nocontentsentry:
:noindexentry:
Declaration of a type alias.
.. cpp:type:: template<typename T> \
MyContainer = std::vector<T>
:noindex:
:nocontentsentry:
:noindexentry:
.. rst:directive:: .. cpp:enum:: unscoped enum declaration
.. cpp:enum-struct:: scoped enum declaration
Expand Down Expand Up @@ -1277,7 +1295,7 @@ Options
Some directives support options:
- ``:noindexentry:``, see :ref:`basic-domain-markup`.
- ``:noindexentry:`` and ``:nocontentsentry:``, see :ref:`basic-domain-markup`.
- ``:tparam-line-spec:``, for templated declarations.
If specified, each template parameter will be rendered on a separate line.
Expand Down Expand Up @@ -1309,15 +1327,19 @@ Example::
This will be rendered as:
.. cpp:class:: Data
:nocontentsentry:
:noindexentry:
.. cpp:union:: @data
:nocontentsentry:
:noindexentry:
.. cpp:var:: int a
:nocontentsentry:
:noindexentry:
.. cpp:var:: double b
:nocontentsentry:
:noindexentry:
Explicit ref: :cpp:var:`Data::@data::a`. Short-hand ref: :cpp:var:`Data::a`.
Expand Down Expand Up @@ -1424,11 +1446,13 @@ introduction` instead of a template parameter list::
They are rendered as follows.

.. cpp:function:: std::Iterator{It} void advance(It &it)
:nocontentsentry:
:noindexentry:

A function template with a template parameter constrained to be an Iterator.

.. cpp:class:: std::LessThanComparable{T} MySortedContainer
:nocontentsentry:
:noindexentry:

A class template with a template parameter constrained to be
Expand Down Expand Up @@ -1459,9 +1483,11 @@ Inline Expressions and Types
will be rendered as follows:

.. cpp:var:: int a = 42
:nocontentsentry:
:noindexentry:

.. cpp:function:: int f(int i)
:nocontentsentry:
:noindexentry:

An expression: :cpp:expr:`a * f(a)` (or as text: :cpp:texpr:`a * f(a)`).
Expand Down
1 change: 1 addition & 0 deletions sphinx/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class Config:
'default_role': (None, 'env', [str]),
'add_function_parentheses': (True, 'env', []),
'add_module_names': (True, 'env', []),
'toc_object_entries': (True, 'env', [bool]),
'toc_object_entries_show_parents': ('domain', 'env',
ENUM('domain', 'all', 'hide')),
'trim_footnote_reference_space': (False, 'env', []),
Expand Down
11 changes: 9 additions & 2 deletions sphinx/directives/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class ObjectDescription(SphinxDirective, Generic[T]):
final_argument_whitespace = True
option_spec: OptionSpec = {
'noindex': directives.flag,
'noindexentry': directives.flag,
'nocontentsentry': directives.flag,
}

# types of doc fields that this directive handles, see sphinx.util.docfields
Expand Down Expand Up @@ -211,6 +213,7 @@ def run(self) -> List[Node]:
node['objtype'] = node['desctype'] = self.objtype
node['noindex'] = noindex = ('noindex' in self.options)
node['noindexentry'] = ('noindexentry' in self.options)
node['nocontentsentry'] = ('nocontentsentry' in self.options)
if self.domain:
node['classes'].append(self.domain)
node['classes'].append(node['objtype'])
Expand All @@ -236,8 +239,12 @@ def run(self) -> List[Node]:
finally:
# Private attributes for ToC generation. Will be modified or removed
# without notice.
signode['_toc_parts'] = self._object_hierarchy_parts(signode)
signode['_toc_name'] = self._toc_entry_name(signode)
if self.env.app.config.toc_object_entries:
signode['_toc_parts'] = self._object_hierarchy_parts(signode)
signode['_toc_name'] = self._toc_entry_name(signode)
else:
signode['_toc_parts'] = ()
signode['_toc_name'] = ''
if name not in self.names:
self.names.append(name)
if not noindex:
Expand Down
2 changes: 1 addition & 1 deletion sphinx/domains/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -3142,8 +3142,8 @@ class CObject(ObjectDescription[ASTDeclaration]):
"""

option_spec: OptionSpec = {
'noindex': directives.flag,
'noindexentry': directives.flag,
'nocontentsentry': directives.flag,
}

def _add_enumerator_to_parent(self, ast: ASTDeclaration) -> None:
Expand Down
2 changes: 1 addition & 1 deletion sphinx/domains/cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -7186,8 +7186,8 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
]

option_spec: OptionSpec = {
'noindex': directives.flag,
'noindexentry': directives.flag,
'nocontentsentry': directives.flag,
'tparam-line-spec': directives.flag,
}

Expand Down
4 changes: 3 additions & 1 deletion sphinx/domains/javascript.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class JSObject(ObjectDescription[Tuple[str, str]]):
option_spec: OptionSpec = {
'noindex': directives.flag,
'noindexentry': directives.flag,
'nocontentsentry': directives.flag,
}

def get_display_prefix(self) -> List[Node]:
Expand Down Expand Up @@ -284,7 +285,8 @@ class JSModule(SphinxDirective):
optional_arguments = 0
final_argument_whitespace = False
option_spec: OptionSpec = {
'noindex': directives.flag
'noindex': directives.flag,
'nocontentsentry': directives.flag,
}

def run(self) -> List[Node]:
Expand Down
2 changes: 2 additions & 0 deletions sphinx/domains/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ class PyObject(ObjectDescription[Tuple[str, str]]):
option_spec: OptionSpec = {
'noindex': directives.flag,
'noindexentry': directives.flag,
'nocontentsentry': directives.flag,
'module': directives.unchanged,
'canonical': directives.unchanged,
'annotation': directives.unchanged,
Expand Down Expand Up @@ -1008,6 +1009,7 @@ class PyModule(SphinxDirective):
'platform': lambda x: x,
'synopsis': lambda x: x,
'noindex': directives.flag,
'nocontentsentry': directives.flag,
'deprecated': directives.flag,
}

Expand Down
1 change: 1 addition & 0 deletions sphinx/domains/rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ReSTMarkup(ObjectDescription[str]):
option_spec: OptionSpec = {
'noindex': directives.flag,
'noindexentry': directives.flag,
'nocontentsentry': directives.flag,
}

def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None:
Expand Down
5 changes: 4 additions & 1 deletion sphinx/environment/collectors/toctree.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,12 @@ def build_toc(
# Skip if no name set
if not sig_node.get('_toc_name', ''):
continue
# Skip if explicitly disabled
if sig_node.parent.get('nocontentsentry'):
continue
# Skip entries with no ID (e.g. with :noindex: set)
ids = sig_node['ids']
if not ids or sig_node.parent.get('noindexentry'):
if not ids:
continue

anchorname = _make_anchor_name(ids, numentries)
Expand Down
4 changes: 2 additions & 2 deletions sphinx/ext/imgmath.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ def html_visit_math(self: HTMLTranslator, node: nodes.math) -> None:
raise nodes.SkipNode from exc
if self.builder.config.imgmath_embed:
image_format = self.builder.config.imgmath_image_format.lower()
img_src = render_maths_to_base64(image_format, outfn)
img_src = render_maths_to_base64(image_format, imgpath)
else:
# Move generated image on tempdir to build dir
if imgpath is not None:
Expand Down Expand Up @@ -350,7 +350,7 @@ def html_visit_displaymath(self: HTMLTranslator, node: nodes.math_block) -> None
self.body.append('</span>')
if self.builder.config.imgmath_embed:
image_format = self.builder.config.imgmath_image_format.lower()
img_src = render_maths_to_base64(image_format, outfn)
img_src = render_maths_to_base64(image_format, imgpath)
else:
# Move generated image on tempdir to build dir
if imgpath is not None:
Expand Down
6 changes: 6 additions & 0 deletions tests/test_ext_math.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Test math extensions."""

import re
import shutil
import subprocess
import warnings

Expand Down Expand Up @@ -33,6 +34,7 @@ def test_imgmath_png(app, status, warning):
raise pytest.skip.Exception('dvipng command "dvipng" is not available')

content = (app.outdir / 'index.html').read_text(encoding='utf8')
shutil.rmtree(app.outdir)
html = (r'<div class="math">\s*<p>\s*<img src="_images/math/\w+.png"'
r'\s*alt="a\^2\+b\^2=c\^2"/>\s*</p>\s*</div>')
assert re.search(html, content, re.S)
Expand All @@ -51,6 +53,7 @@ def test_imgmath_svg(app, status, warning):
raise pytest.skip.Exception('dvisvgm command "dvisvgm" is not available')

content = (app.outdir / 'index.html').read_text(encoding='utf8')
shutil.rmtree(app.outdir)
html = (r'<div class="math">\s*<p>\s*<img src="_images/math/\w+.svg"'
r'\s*alt="a\^2\+b\^2=c\^2"/>\s*</p>\s*</div>')
assert re.search(html, content, re.S)
Expand All @@ -70,6 +73,7 @@ def test_imgmath_svg_embed(app, status, warning):
pytest.skip('dvisvgm command "dvisvgm" is not available')

content = (app.outdir / 'index.html').read_text(encoding='utf8')
shutil.rmtree(app.outdir)
html = r'<img src="data:image/svg\+xml;base64,[\w\+/=]+"'
assert re.search(html, content, re.DOTALL)

Expand All @@ -81,6 +85,7 @@ def test_mathjax_options(app, status, warning):
app.builder.build_all()

content = (app.outdir / 'index.html').read_text(encoding='utf8')
shutil.rmtree(app.outdir)
assert ('<script async="async" integrity="sha384-0123456789" '
'src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">'
'</script>' in content)
Expand All @@ -92,6 +97,7 @@ def test_mathjax_align(app, status, warning):
app.builder.build_all()

content = (app.outdir / 'index.html').read_text(encoding='utf8')
shutil.rmtree(app.outdir)
html = (r'<div class="math notranslate nohighlight">\s*'
r'\\\[ \\begin\{align\}\\begin\{aligned\}S \&amp;= \\pi r\^2\\\\'
r'V \&amp;= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]</div>')
Expand Down

0 comments on commit 2906071

Please sign in to comment.