diff --git a/CHANGES b/CHANGES index ffc8b8b3284..0b2c97c7ba1 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,8 @@ Bugs fixed * #6046: LaTeX: ``TypeError`` is raised when invalid latex_elements given * #6067: LaTeX: images having a target are concatenated to next line * #6067: LaTeX: images having a target are not aligned even if specified +* #6149: LaTeX: ``:index:`` role in titles causes ``Use of \@icentercr doesn't + match its definition`` error on latexpdf build * #6019: imgconverter: Including multipage PDF fails * #6047: autodoc: ``autofunction`` emits a warning for method objects * #6028: graphviz: Ensure the graphviz filenames are reproducible diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index 4ab4080643c..0734f9e5319 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -20,7 +20,7 @@ from sphinx.builders.latex.transforms import ( BibliographyTransform, CitationReferenceTransform, MathReferenceTransform, FootnoteDocnameUpdater, LaTeXFootnoteTransform, LiteralBlockTransform, - ShowUrlsTransform, DocumentTargetTransform, + ShowUrlsTransform, DocumentTargetTransform, IndexInSectionTitleTransform, ) from sphinx.config import string_classes, ENUM from sphinx.environment import NoUri @@ -284,7 +284,8 @@ def apply_transforms(self, doctree): ShowUrlsTransform, LaTeXFootnoteTransform, LiteralBlockTransform, - DocumentTargetTransform]) + DocumentTargetTransform, + IndexInSectionTitleTransform]) transformer.apply_transforms() def finish(self): diff --git a/sphinx/builders/latex/transforms.py b/sphinx/builders/latex/transforms.py index ca3e64b70b7..dcd07a3affa 100644 --- a/sphinx/builders/latex/transforms.py +++ b/sphinx/builders/latex/transforms.py @@ -596,3 +596,40 @@ def apply(self): section = node.next_node(nodes.section) if section: section['ids'].append(':doc') # special label for :doc: + + +class IndexInSectionTitleTransform(SphinxTransform): + """Move index nodes in section title to outside of the title. + + LaTeX index macro is not compatible with some handling of section titles + such as uppercasing done on LaTeX side (cf. fncychap handling of ``\\chapter``). + Moving the index node to after the title node fixes that. + + Before:: + +
+ + blah blah <index entries=[...]/>blah + <paragraph> + blah blah blah + ... + + After:: + + <section> + <title> + blah blah blah + <index entries=[...]/> + <paragraph> + blah blah blah + ... + """ + default_priority = 400 + + def apply(self): + for node in self.document.traverse(nodes.title): + if isinstance(node.parent, nodes.section): + for i, index in enumerate(node.traverse(addnodes.index)): + # move the index node next to the section title + node.remove(index) + node.parent.insert(i + 1, index) diff --git a/tests/roots/test-index_on_title/conf.py b/tests/roots/test-index_on_title/conf.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/roots/test-index_on_title/contents.rst b/tests/roots/test-index_on_title/contents.rst new file mode 100644 index 00000000000..8256c42d757 --- /dev/null +++ b/tests/roots/test-index_on_title/contents.rst @@ -0,0 +1,5 @@ +index_on_title +============== + +Test for :index:`index` in top level title +------------------------------------------ diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 03558cd924c..b549404db1e 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -1349,6 +1349,15 @@ def test_latex_labels(app, status, warning): r'\label{\detokenize{otherdoc:otherdoc}}' r'\label{\detokenize{otherdoc::doc}}' in result) - # Embeded standalone hyperlink reference (refs: #5948) assert result.count(r'\label{\detokenize{index:section1}}') == 1 + + +@pytest.mark.sphinx('latex', testroot='index_on_title') +def test_index_on_title(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + assert ('\\chapter{Test for index in top level title}\n' + '\\label{\\detokenize{contents:test-for-index-in-top-level-title}}' + '\\index{index@\\spxentry{index}}\n' + in result)