From ef854e75023acd9a18c5c16818f749c1576b9e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20B?= <2589111+jfbu@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:50:41 +0200 Subject: [PATCH] LaTeX: fix mark-up when \DUrole is used with multiple classes Fix #12744 --- CHANGES.rst | 4 ++++ doc/latex.rst | 13 +++++++++++++ sphinx/writers/latex.py | 4 ++-- .../expects/longtable_having_widths.tex | 2 +- .../expects/table_having_widths.tex | 2 +- tests/test_builders/test_build_latex.py | 3 ++- tests/test_directives/test_directive_code.py | 8 ++++---- 7 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 4b920ca3911..e9338ba2fff 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -26,5 +26,9 @@ Bugs fixed so that it now runs after the docutils ``Footnotes`` resolution transform. Patch by Chris Sewell. +* #12744: Classes injected by a custom interpreted text role now give rise to + nested ``\DUrole``'s, rather than a single one with comma separated classes. + Patch by Jean-François B. + Testing ------- diff --git a/doc/latex.rst b/doc/latex.rst index 821c8329764..137e2d4cf43 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -1865,6 +1865,19 @@ Miscellany Formerly, use of *fncychap* with other styles than ``Bjarne`` was dysfunctional. +- The :dudir:`role` directive allows to mark inline text with class arguments. + This is handled in LaTeX output via the ``\DUrole`` dispatcher command `as + in Docutils `_. Object signatures also use ``\DUrole`` for + some components, with one or two-letters class names as in HTML output. + + .. versionchanged:: 8.1.0 When multiple classes are injected via a a custom + role, the LaTeX output uses nested ``\DUrole``'s as in the `Docutils + documentation `_. Formerly it used a single ``\DUrole`` + with comma separated classes, making the LaTeX customization more + arduous. + +.. _classarguments: https://docutils.sourceforge.io/docs/user/latex.html#custom-interpreted-text-roles + .. _latexcontainer: - Docutils :dudir:`container` directives are supported in LaTeX output: to diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 4badfa87f85..4fb271d8537 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -2173,8 +2173,8 @@ def visit_inline(self, node: Element) -> None: self.body.append(r'\sphinxaccelerator{') self.context.append('}') elif classes and not self.in_title: - self.body.append(r'\DUrole{%s}{' % ','.join(classes)) - self.context.append('}') + self.body.append(r'\DUrole{' + r'}{\DUrole{'.join(classes) + '}{') + self.context.append('}' * len(classes)) else: self.context.append('') diff --git a/tests/roots/test-latex-table/expects/longtable_having_widths.tex b/tests/roots/test-latex-table/expects/longtable_having_widths.tex index 24dad79fd6a..bcad23be4f0 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_widths.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_widths.tex @@ -70,4 +70,4 @@ \end{savenotes} \sphinxAtStartPar -See {\hyperref[\detokenize{longtable:mylongtable}]{\sphinxcrossref{mylongtable}}}, same as {\hyperref[\detokenize{longtable:namedlongtable}]{\sphinxcrossref{\DUrole{std,std-ref}{this one}}}}. +See {\hyperref[\detokenize{longtable:mylongtable}]{\sphinxcrossref{mylongtable}}}, same as {\hyperref[\detokenize{longtable:namedlongtable}]{\sphinxcrossref{\DUrole{std}{\DUrole{std-ref}{this one}}}}}. diff --git a/tests/roots/test-latex-table/expects/table_having_widths.tex b/tests/roots/test-latex-table/expects/table_having_widths.tex index fe5f4c44d72..e9863d277f6 100644 --- a/tests/roots/test-latex-table/expects/table_having_widths.tex +++ b/tests/roots/test-latex-table/expects/table_having_widths.tex @@ -43,4 +43,4 @@ \sphinxattableend\end{savenotes} \sphinxAtStartPar -See {\hyperref[\detokenize{tabular:mytabular}]{\sphinxcrossref{\DUrole{std,std-ref}{this}}}}, same as {\hyperref[\detokenize{tabular:namedtabular}]{\sphinxcrossref{namedtabular}}}. +See {\hyperref[\detokenize{tabular:mytabular}]{\sphinxcrossref{\DUrole{std}{\DUrole{std-ref}{this}}}}}, same as {\hyperref[\detokenize{tabular:namedtabular}]{\sphinxcrossref{namedtabular}}}. diff --git a/tests/test_builders/test_build_latex.py b/tests/test_builders/test_build_latex.py index c2bd2d970d1..52ae9d0dfb2 100644 --- a/tests/test_builders/test_build_latex.py +++ b/tests/test_builders/test_build_latex.py @@ -815,7 +815,8 @@ def test_reference_in_caption_and_codeblock_in_footnote(app): 'Second footnote in caption of longtable\n') in result assert ('This is a reference to the code\\sphinxhyphen{}block in the footnote:\n' '{\\hyperref[\\detokenize{index:codeblockinfootnote}]' - '{\\sphinxcrossref{\\DUrole{std,std-ref}{I am in a footnote}}}}') in result + '{\\sphinxcrossref{\\DUrole{std}{\\DUrole{std-ref}' + '{I am in a footnote}}}}}') in result assert ('&\n\\sphinxAtStartPar\nThis is one more footnote with some code in it %\n' '\\begin{footnote}[12]\\sphinxAtStartFootnote\n' 'Third footnote in longtable\n') in result diff --git a/tests/test_directives/test_directive_code.py b/tests/test_directives/test_directive_code.py index 3f65bf58646..bc2e61a060b 100644 --- a/tests/test_directives/test_directive_code.py +++ b/tests/test_directives/test_directive_code.py @@ -346,11 +346,11 @@ def test_code_block_namedlink_latex(app): latex = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') label1 = '\\def\\sphinxLiteralBlockLabel{\\label{\\detokenize{caption:name-test-rb}}}' link1 = '\\hyperref[\\detokenize{caption:name-test-rb}]'\ - '{\\sphinxcrossref{\\DUrole{std,std-ref}{Ruby}}' + '{\\sphinxcrossref{\\DUrole{std}{\\DUrole{std-ref}{Ruby}}}}' label2 = ('\\def\\sphinxLiteralBlockLabel' '{\\label{\\detokenize{namedblocks:some-ruby-code}}}') link2 = '\\hyperref[\\detokenize{namedblocks:some-ruby-code}]'\ - '{\\sphinxcrossref{\\DUrole{std,std-ref}{the ruby code}}}' + '{\\sphinxcrossref{\\DUrole{std}{\\DUrole{std-ref}{the ruby code}}}}' assert label1 in latex assert link1 in latex assert label2 in latex @@ -466,11 +466,11 @@ def test_literalinclude_namedlink_latex(app): latex = (app.outdir / 'projectnamenotset.tex').read_text(encoding='utf8') label1 = '\\def\\sphinxLiteralBlockLabel{\\label{\\detokenize{caption:name-test-py}}}' link1 = '\\hyperref[\\detokenize{caption:name-test-py}]'\ - '{\\sphinxcrossref{\\DUrole{std,std-ref}{Python}}' + '{\\sphinxcrossref{\\DUrole{std}{\\DUrole{std-ref}{Python}}}}' label2 = ('\\def\\sphinxLiteralBlockLabel' '{\\label{\\detokenize{namedblocks:some-python-code}}}') link2 = '\\hyperref[\\detokenize{namedblocks:some-python-code}]'\ - '{\\sphinxcrossref{\\DUrole{std,std-ref}{the python code}}}' + '{\\sphinxcrossref{\\DUrole{std}{\\DUrole{std-ref}{the python code}}}}' assert label1 in latex assert link1 in latex assert label2 in latex