mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '3.x' into merge_3.x_into_master
Resolved Conflicts: sphinx/texinputs/sphinx.sty Some hunks needed to go to sphinx/texinputs/sphinxlatexliterals.py, others already belonged to split files.
This commit is contained in:
commit
b9c53c8ca6
8
CHANGES
8
CHANGES
@ -199,8 +199,13 @@ Bugs fixed
|
||||
* #8683: :confval:`html_last_updated_fmt` generates wrong time zone for %Z
|
||||
* #1112: ``download`` role creates duplicated copies when relative path is
|
||||
specified
|
||||
* #2616 (fifth item): LaTeX: footnotes from captions are not clickable,
|
||||
and for manually numbered footnotes only first one with same number is
|
||||
an hyperlink
|
||||
* #7576: LaTeX with French babel and memoir crash: "Illegal parameter number
|
||||
in definition of ``\FNH@prefntext``"
|
||||
* #8055: LaTeX (docs): A potential display bug with the LaTeX generation step
|
||||
in Sphinx (how to generate one-column index)
|
||||
* #8072: LaTeX: Directive :rst:dir:`hlist` not implemented in LaTeX
|
||||
* #8214: LaTeX: The :rst:role:`index` role and the glossary generate duplicate
|
||||
entries in the LaTeX index (if both used for same term)
|
||||
@ -213,6 +218,9 @@ Bugs fixed
|
||||
* #8780: LaTeX: long words in narrow columns may not be hyphenated
|
||||
* #8788: LaTeX: ``\titleformat`` last argument in sphinx.sty should be
|
||||
bracketed, not braced (and is anyhow not needed)
|
||||
* #8849: LaTex: code-block printed out of margin (see the opt-in LaTeX syntax
|
||||
boolean :ref:`verbatimforcewraps <latexsphinxsetupforcewraps>` for use via
|
||||
the :ref:`'sphinxsetup' <latexsphinxsetup>` key of ``latex_elements``)
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
101
doc/latex.rst
101
doc/latex.rst
@ -469,11 +469,22 @@ Keys that don't need to be overridden unless in special cases are:
|
||||
.. versionchanged:: 1.6
|
||||
Remove unneeded ``{}`` after ``\\hrule``.
|
||||
|
||||
``'makeindex'``
|
||||
"makeindex" call, the last thing before ``\begin{document}``. With
|
||||
``'\\usepackage[columns=1]{idxlayout}\\makeindex'`` the index will use
|
||||
only one column. You may have to install ``idxlayout`` LaTeX package.
|
||||
|
||||
Default: ``'\\makeindex'``
|
||||
|
||||
``'printindex'``
|
||||
"printindex" call, the last thing in the file. Override if you want to
|
||||
generate the index differently or append some content after the index. For
|
||||
example ``'\\footnotesize\\raggedright\\printindex'`` is advisable when the
|
||||
index is full of long entries.
|
||||
generate the index differently, append some content after the index, or
|
||||
change the font. As LaTeX uses two-column mode for the index it is
|
||||
often advisable to set this key to
|
||||
``'\\footnotesize\\raggedright\\printindex'``. Or, to obtain a one-column
|
||||
index, use ``'\\def\\twocolumn[#1]{#1}\\printindex'`` (this trick may fail
|
||||
if using a custom document class; then try the ``idxlayout`` approach
|
||||
described in the documentation of the ``'makeindex'`` key).
|
||||
|
||||
Default: ``'\\printindex'``
|
||||
|
||||
@ -505,7 +516,6 @@ Keys that are set by other options and therefore should not be overridden are:
|
||||
``'title'``
|
||||
``'release'``
|
||||
``'author'``
|
||||
``'makeindex'``
|
||||
|
||||
|
||||
.. _latexsphinxsetup:
|
||||
@ -563,7 +573,9 @@ The below is included at the end of the chapter::
|
||||
|
||||
\endgroup
|
||||
|
||||
LaTeX boolean keys require *lowercase* ``true`` or ``false`` values.
|
||||
LaTeX syntax for boolean keys requires *lowercase* ``true`` or ``false``
|
||||
e.g ``'sphinxsetup': "verbatimwrapslines=false"``. If setting the
|
||||
boolean key to ``true``, ``=true`` is optional.
|
||||
Spaces around the commas and equal signs are ignored, spaces inside LaTeX
|
||||
macros may be significant.
|
||||
|
||||
@ -614,14 +626,68 @@ macros may be significant.
|
||||
Boolean to specify if long lines in :rst:dir:`code-block`\ 's contents are
|
||||
wrapped.
|
||||
|
||||
If ``true``, line breaks may happen at spaces (the last space before the
|
||||
line break will be rendered using a special symbol), and at ascii
|
||||
punctuation characters (i.e. not at letters or digits). Whenever a long
|
||||
string has no break points, it is moved to next line. If its length is
|
||||
longer than the line width it will overflow.
|
||||
|
||||
Default: ``true``
|
||||
|
||||
``literalblockcappos``
|
||||
Decides the caption position: either ``b`` ("bottom") or ``t`` ("top").
|
||||
.. _latexsphinxsetupforcewraps:
|
||||
|
||||
Default: ``t``
|
||||
``verbatimforcewraps``
|
||||
Boolean to specify if long lines in :rst:dir:`code-block`\ 's contents
|
||||
should be forcefully wrapped to never overflow due to long strings.
|
||||
|
||||
.. versionadded:: 1.7
|
||||
.. note::
|
||||
|
||||
It is assumed that the Pygments_ LaTeXFormatter has not been used with
|
||||
its ``texcomments`` or similar options which allow additional
|
||||
(arbitrary) LaTeX mark-up.
|
||||
|
||||
Also, in case of :confval:`latex_engine` set to ``'pdflatex'``, only
|
||||
the default LaTeX handling of Unicode code points, i.e. ``utf8`` not
|
||||
``utf8x`` is allowed.
|
||||
|
||||
.. _Pygments: https://pygments.org/
|
||||
|
||||
Default: ``false``
|
||||
|
||||
.. versionadded:: 3.5.0
|
||||
|
||||
``verbatimmaxoverfull``
|
||||
A number. If an unbreakable long string has length larger than the total
|
||||
linewidth plus this number of characters, and if ``verbatimforcewraps``
|
||||
mode is on, the input line will be reset using the forceful algorithm
|
||||
which applies breakpoints at each character.
|
||||
|
||||
Default: ``3``
|
||||
|
||||
.. versionadded:: 3.5.0
|
||||
|
||||
``verbatimmaxunderfull``
|
||||
A number. If ``verbatimforcewraps`` mode applies, and if after applying
|
||||
the line wrapping at spaces and punctuation, the first part of the split
|
||||
line is lacking at least that number of characters to fill the available
|
||||
width, then the input line will be reset using the forceful algorithm.
|
||||
|
||||
As the default is set to a high value, the forceful algorithm is triggered
|
||||
only in overfull case, i.e. in presence of a string longer than full
|
||||
linewidth. Set this to ``0`` to force all input lines to be hard wrapped
|
||||
at the current avaiable linewidth::
|
||||
|
||||
latex_elements = {
|
||||
'sphinxsetup': "verbatimforcewraps, verbatimmaxunderfull=0",
|
||||
}
|
||||
|
||||
This can be done locally for a given code-block via the use of raw latex
|
||||
directives to insert suitable ``\sphinxsetup`` (before and after) into the
|
||||
latex file.
|
||||
|
||||
Default: ``100``
|
||||
|
||||
.. versionadded:: 3.5.0
|
||||
|
||||
``verbatimhintsturnover``
|
||||
Boolean to specify if code-blocks display "continued on next page" and
|
||||
@ -687,10 +753,10 @@ macros may be significant.
|
||||
|
||||
Default: ``{rgb}{0.126,0.263,0.361}``
|
||||
|
||||
.. warning::
|
||||
.. warning::
|
||||
|
||||
Colours set via ``'sphinxsetup'`` must obey the syntax of the
|
||||
argument of the ``color/xcolor`` packages ``\definecolor`` command.
|
||||
Colours set via ``'sphinxsetup'`` must obey the syntax of the
|
||||
argument of the ``color/xcolor`` packages ``\definecolor`` command.
|
||||
|
||||
``InnerLinkColor``
|
||||
A colour passed to ``hyperref`` as value of ``linkcolor`` and
|
||||
@ -721,10 +787,10 @@ macros may be significant.
|
||||
|
||||
.. versionadded:: 1.6.6
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
Starting with this colour key, and for all others coming next, the actual
|
||||
names declared to "color" or "xcolor" are prefixed with "sphinx".
|
||||
Starting with this colour, and for all others following, the
|
||||
names declared to "color" or "xcolor" are prefixed with "sphinx".
|
||||
|
||||
``verbatimsep``
|
||||
The separation between code lines and the frame.
|
||||
@ -812,9 +878,8 @@ macros may be significant.
|
||||
``attentionBorderColor``, ``dangerBorderColor``,
|
||||
``errorBorderColor``
|
||||
|
||||
.. |wgbdcolorslatex| replace:: ``warningBorderColor``, ``cautionBorderColor``,
|
||||
``attentionB..C..``, ``dangerB..C..``,
|
||||
``errorB..C..``
|
||||
.. |wgbdcolorslatex| replace:: ``warningBorderColor``, and
|
||||
``(caution|attention|danger|error)BorderColor``
|
||||
|
||||
.. else latex goes into right margin, as it does not hyphenate the names
|
||||
|
||||
|
@ -92,6 +92,9 @@
|
||||
% verbatim
|
||||
\DeclareBoolOption[true]{verbatimwithframe}
|
||||
\DeclareBoolOption[true]{verbatimwrapslines}
|
||||
\DeclareBoolOption[false]{verbatimforcewraps}
|
||||
\DeclareStringOption[3]{verbatimmaxoverfull}
|
||||
\DeclareStringOption[100]{verbatimmaxunderfull}
|
||||
\DeclareBoolOption[true]{verbatimhintsturnover}
|
||||
\DeclareBoolOption[true]{inlineliteralwraps}
|
||||
\DeclareStringOption[t]{literalblockcappos}
|
||||
@ -298,6 +301,28 @@
|
||||
|
||||
%% FOOTNOTES
|
||||
%
|
||||
% Support scopes for footnote numbering
|
||||
\newcounter{sphinxscope}
|
||||
\newcommand{\sphinxstepscope}{\stepcounter{sphinxscope}}
|
||||
% Explictly numbered footnotes may be referred to, and for this to be
|
||||
% clickable we need to have only one target. So we will step this at each
|
||||
% explicit footnote and let \thesphinxscope take it into account
|
||||
\newcounter{sphinxexplicit}
|
||||
\newcommand{\sphinxstepexplicit}{\stepcounter{sphinxexplicit}}
|
||||
% Some babel/polyglossia languages fiddle with \@arabic, so let's be extra
|
||||
% cautious and redefine \thesphinxscope with \number not \@arabic.
|
||||
% Memo: we expect some subtle redefinition of \thesphinxscope to be a part of page
|
||||
% scoping for footnotes, when we shall implement it.
|
||||
\renewcommand{\thesphinxscope}{\number\value{sphinxscope}.\number\value{sphinxexplicit}}
|
||||
\newcommand\sphinxthefootnotemark[2]{%
|
||||
% this is used to make reference to an explicitly numbered footnote not on same page
|
||||
% #1=label of footnote text, #2=page number where footnote text was printed
|
||||
\ifdefined\pagename
|
||||
\pagename\space#2, % <- space
|
||||
\else
|
||||
p. #2, % <- space
|
||||
\fi #1% no space
|
||||
}
|
||||
% support large numbered footnotes in minipage; but this is now obsolete
|
||||
% from systematic use of savenotes environment around minipages
|
||||
\def\thempfootnote{\arabic{mpfootnote}}
|
||||
|
@ -268,13 +268,188 @@
|
||||
% no need to restore \fboxsep here, as this ends up in a \hbox from fancyvrb
|
||||
}%
|
||||
% \sphinxVerbatimFormatLine will be set locally to one of those two:
|
||||
\newcommand\sphinxVerbatimFormatLineWrap[1]{%
|
||||
\hsize\linewidth
|
||||
\newcommand\sphinxVerbatimFormatLineWrap{%
|
||||
\hsize\linewidth
|
||||
\ifspx@opt@verbatimforcewraps
|
||||
\expandafter\spx@verb@FormatLineForceWrap
|
||||
\else\expandafter\spx@verb@FormatLineWrap
|
||||
\fi
|
||||
}%
|
||||
\newcommand\sphinxVerbatimFormatLineNoWrap[1]{\hb@xt@\linewidth{\strut #1\hss}}%
|
||||
\long\def\spx@verb@FormatLineWrap#1{%
|
||||
\vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@
|
||||
\doublehyphendemerits\z@\finalhyphendemerits\z@
|
||||
\strut #1\strut}%
|
||||
}%
|
||||
\newcommand\sphinxVerbatimFormatLineNoWrap[1]{\hb@xt@\linewidth{\strut #1\hss}}%
|
||||
%
|
||||
% The normal line wrapping allows breaks at spaces and ascii non
|
||||
% letters, non digits. The \raggedright above means there will be
|
||||
% an overfilled line only if some non-breakable "word" was
|
||||
% encountered, which is longer than a line (it is moved always to
|
||||
% be on its own on a new line).
|
||||
%
|
||||
% The "forced" line wrapping will parse the tokens to add potential
|
||||
% breakpoints at each character. As some strings are highlighted,
|
||||
% we have to apply the highlighting character per character, which
|
||||
% requires to manipulate the output of the Pygments LaTeXFormatter.
|
||||
%
|
||||
% Doing this at latex level is complicated. The contents should
|
||||
% be as expected: i.e. some active characters from
|
||||
% \sphinxbreaksviaactive, some Pygments character escapes such as
|
||||
% \PYGZdl{}, and the highlighting \PYG macro with always 2
|
||||
% arguments. No other macros should be there, except perhaps
|
||||
% zero-parameter macros. In particular:
|
||||
% - the texcomments Pygments option must be set to False
|
||||
%
|
||||
% With pdflatex, Unicode input gives multi-bytes characters
|
||||
% where the first byte is active. We support the "utf8" macros
|
||||
% only. "utf8x" is not supported.
|
||||
%
|
||||
% The highlighting macro \PYG will be applied character per
|
||||
% character. Highlighting via a colored background gives thus a
|
||||
% chain of small colored boxes which may cause some artefact in
|
||||
% some pdf viewers. Can't do anything here if we do want the line
|
||||
% break to be possible.
|
||||
%
|
||||
% First a measurement step is done of what would the standard line
|
||||
% wrapping give (i.e line breaks only at spaces and non-letter,
|
||||
% non-digit ascii characters), cf TeX by Topic for the basic
|
||||
% dissecting technique: TeX unfortunately when building a vertical
|
||||
% box does not store in an accessible way what was the maximal
|
||||
% line-width during paragraph building.
|
||||
%
|
||||
% If the max width exceeds the linewidth by more than verbatimmaxoverfull
|
||||
% character widths, or if the min width plus verbatimmaxunderfull character
|
||||
% widths is inferior to linewidth, then we apply the "force wrapping" with
|
||||
% potential line break at each character, else we don't.
|
||||
\long\def\spx@verb@FormatLineForceWrap#1{%
|
||||
% \spx@image@box is a scratch box register that we can use here
|
||||
\global\let\spx@verb@maxwidth\z@
|
||||
\global\let\spx@verb@minwidth\linewidth
|
||||
\setbox\spx@image@box
|
||||
\vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@
|
||||
\doublehyphendemerits\z@\finalhyphendemerits\z@
|
||||
\strut #1\strut\@@par
|
||||
\spx@verb@getwidths}%
|
||||
\ifdim\spx@verb@maxwidth>
|
||||
\dimexpr\linewidth+\spx@opt@verbatimmaxoverfull\fontcharwd\font`X \relax
|
||||
\spx@verb@FormatLineWrap{\spx@verb@wrapPYG #1\spx@verb@wrapPYG}%
|
||||
\else
|
||||
\ifdim\spx@verb@minwidth<
|
||||
\dimexpr\linewidth-\spx@opt@verbatimmaxunderfull\fontcharwd\font`X \relax
|
||||
\spx@verb@FormatLineWrap{\spx@verb@wrapPYG #1\spx@verb@wrapPYG}%
|
||||
\else
|
||||
\spx@verb@FormatLineWrap{#1}%
|
||||
\fi\fi
|
||||
}%
|
||||
% auxiliary paragraph dissector to get max and min widths
|
||||
\newbox\spx@scratchbox
|
||||
\def\spx@verb@getwidths {%
|
||||
\unskip\unpenalty
|
||||
\setbox\spx@scratchbox\lastbox
|
||||
\ifvoid\spx@scratchbox
|
||||
\else
|
||||
\setbox\spx@scratchbox\hbox{\unhbox\spx@scratchbox}%
|
||||
\ifdim\spx@verb@maxwidth<\wd\spx@scratchbox
|
||||
\xdef\spx@verb@maxwidth{\number\wd\spx@scratchbox sp}%
|
||||
\fi
|
||||
\ifdim\spx@verb@minwidth>\wd\spx@scratchbox
|
||||
\xdef\spx@verb@minwidth{\number\wd\spx@scratchbox sp}%
|
||||
\fi
|
||||
\expandafter\spx@verb@getwidths
|
||||
\fi
|
||||
}%
|
||||
% auxiliary macros to implement "cut long line even in middle of word"
|
||||
\catcode`Z=3 % safe delimiter
|
||||
\def\spx@verb@wrapPYG{%
|
||||
\futurelet\spx@nexttoken\spx@verb@wrapPYG@i
|
||||
}%
|
||||
\def\spx@verb@wrapPYG@i{%
|
||||
\ifx\spx@nexttoken\spx@verb@wrapPYG\let\next=\@gobble\else
|
||||
\ifx\spx@nexttoken\PYG\let\next=\spx@verb@wrapPYG@PYG@onebyone\else
|
||||
\discretionary{}{\sphinxafterbreak}{}%
|
||||
\let\next\spx@verb@wrapPYG@ii
|
||||
\fi\fi
|
||||
\next
|
||||
}%
|
||||
% Let's recognize active characters. We don't support utf8x only utf8.
|
||||
% And here #1 should not have picked up (non empty) braced contents
|
||||
\long\def\spx@verb@wrapPYG@ii#1{%
|
||||
\ifcat\noexpand~\noexpand#1\relax% active character
|
||||
\expandafter\spx@verb@wrapPYG@active
|
||||
\else % non-active character, control sequence such as \PYGZdl, or empty
|
||||
\expandafter\spx@verb@wrapPYG@one
|
||||
\fi {#1}%
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@active#1{%
|
||||
% Let's hope expansion of active character does not really require arguments,
|
||||
% as we certainly don't want to go into expanding upfront token stream anyway.
|
||||
\expandafter\spx@verb@wrapPYG@iii#1{}{}{}{}{}{}{}{}{}Z#1%
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@iii#1#2Z{%
|
||||
\ifx\UTFviii@four@octets#1\let\next=\spx@verb@wrapPYG@four\else
|
||||
\ifx\UTFviii@three@octets#1\let\next=\spx@verb@wrapPYG@three\else
|
||||
\ifx\UTFviii@two@octets#1\let\next=\spx@verb@wrapPYG@two\else
|
||||
\let\next=\spx@verb@wrapPYG@one
|
||||
\fi\fi\fi
|
||||
\next
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@one #1{#1\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}%
|
||||
\long\def\spx@verb@wrapPYG@two #1#2{#1#2\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}%
|
||||
\long\def\spx@verb@wrapPYG@three #1#2#3{#1#2#3\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}%
|
||||
\long\def\spx@verb@wrapPYG@four #1#2#3#4{#1#2#3#4\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}%
|
||||
% Replace \PYG by itself applied one character at a time! This way breakpoints
|
||||
% can be inserted.
|
||||
\def\spx@verb@wrapPYG@PYG@onebyone#1#2#3{% #1 = \PYG, #2 = highlight spec, #3 = tokens
|
||||
\def\spx@verb@wrapPYG@PYG@spec{{#2}}%
|
||||
\futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i#3Z%
|
||||
}%
|
||||
\def\spx@verb@wrapPYG@PYG@i{%
|
||||
\ifx\spx@nexttokenZ\let\next=\spx@verb@wrapPYG@PYG@done\else
|
||||
\discretionary{}{\sphinxafterbreak}{}%
|
||||
\let\next\spx@verb@wrapPYG@PYG@ii
|
||||
\fi
|
||||
\next
|
||||
}%
|
||||
\def\spx@verb@wrapPYG@PYG@doneZ{\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}%
|
||||
\long\def\spx@verb@wrapPYG@PYG@ii#1{%
|
||||
\ifcat\noexpand~\noexpand#1\relax% active character
|
||||
\expandafter\spx@verb@wrapPYG@PYG@active
|
||||
\else % non-active character, control sequence such as \PYGZdl, or empty
|
||||
\expandafter\spx@verb@wrapPYG@PYG@one
|
||||
\fi {#1}%
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@PYG@active#1{%
|
||||
% Let's hope expansion of active character does not really require arguments,
|
||||
% as we certainly don't want to go into expanding upfront token stream anyway.
|
||||
\expandafter\spx@verb@wrapPYG@PYG@iii#1{}{}{}{}{}{}{}{}{}Z#1%
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@PYG@iii#1#2Z{%
|
||||
\ifx\UTFviii@four@octets#1\let\next=\spx@verb@wrapPYG@PYG@four\else
|
||||
\ifx\UTFviii@three@octets#1\let\next=\spx@verb@wrapPYG@PYG@three\else
|
||||
\ifx\UTFviii@two@octets#1\let\next=\spx@verb@wrapPYG@PYG@two\else
|
||||
\let\next=\spx@verb@wrapPYG@PYG@one
|
||||
\fi\fi\fi
|
||||
\next
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@PYG@one#1{%
|
||||
\expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1}%
|
||||
\futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@PYG@two#1#2{%
|
||||
\expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2}%
|
||||
\futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@PYG@three#1#2#3{%
|
||||
\expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2#3}%
|
||||
\futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i
|
||||
}%
|
||||
\long\def\spx@verb@wrapPYG@PYG@four#1#2#3#4{%
|
||||
\expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2#3#4}%
|
||||
\futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i
|
||||
}%
|
||||
\catcode`Z 11%
|
||||
%
|
||||
\g@addto@macro\FV@SetupFont{%
|
||||
\sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}%
|
||||
\sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}%
|
||||
|
@ -331,8 +331,58 @@
|
||||
% some extras for Sphinx :
|
||||
% \sphinxfootnotemark: usable in section titles and silently removed from TOCs.
|
||||
\def\sphinxfootnotemark [#1]%
|
||||
{\ifx\thepage\relax\else\protect\spx@opt@BeforeFootnote
|
||||
\protect\footnotemark[#1]\fi}%
|
||||
{\ifx\thepage\relax\else\sphinxfootref{#1}\fi}%
|
||||
% \sphinxfootref:
|
||||
% - \spx@opt@BeforeFootnote is from BeforeFootnote sphinxsetup option
|
||||
% - \ref:
|
||||
% the latex.py writer inserts a \phantomsection\label{<scope>.<num>}
|
||||
% whenever
|
||||
% - the footnote was explicitly numbered in sources,
|
||||
% - or it was in restrained context and is rendered using footnotetext
|
||||
%
|
||||
% These are the two types of footnotes that \sphinxfootnotemark must
|
||||
% handle. But for explicitly numbered footnotes the same number
|
||||
% can be found in document. So a secondary part in <scope> is updated
|
||||
% at each novel such footnote to know what is the target from then on
|
||||
% for \sphinxfootnotemark and already encountered [1], or [2],...
|
||||
%
|
||||
% LaTeX package varioref is not supported by hyperref (from its doc: "There
|
||||
% are too many problems with varioref. Nobody has time to sort them out.
|
||||
% Therefore this package is now unsupported.") So we will simply use our own
|
||||
% macros to access the page number of footnote text and decide whether to print
|
||||
% it. \pagename is internationalized by latex-babel.
|
||||
\def\spx@thefnmark#1#2{%
|
||||
% #1=label for reference, #2=page where footnote was printed
|
||||
\ifx\spx@tempa\spx@tempb
|
||||
% same page
|
||||
#1%
|
||||
\else
|
||||
\sphinxthefootnotemark{#1}{#2}%
|
||||
\fi
|
||||
}%
|
||||
\def\sphinxfootref@get #1#2#3#4#5\relax{%
|
||||
\def\sphinxfootref@label{#1}%
|
||||
\def\sphinxfootref@page {#2}%
|
||||
\def\sphinxfootref@Href {#4}%
|
||||
}%
|
||||
\protected\def\sphinxfootref#1{% #1 always explicit number in Sphinx usage
|
||||
\spx@opt@BeforeFootnote
|
||||
\ltx@ifundefined{r@\thesphinxscope.#1}%
|
||||
{\gdef\@thefnmark{?}\H@@footnotemark}%
|
||||
{\expandafter\expandafter\expandafter\sphinxfootref@get
|
||||
\csname r@\thesphinxscope.#1\endcsname\relax
|
||||
\edef\spx@tempa{\thepage}\edef\spx@tempb{\sphinxfootref@page}%
|
||||
\protected@xdef\@thefnmark{\spx@thefnmark{\sphinxfootref@label}{\sphinxfootref@page}}%
|
||||
\let\spx@@makefnmark\@makefnmark
|
||||
\def\@makefnmark{%
|
||||
\hyper@linkstart{link}{\sphinxfootref@Href}%
|
||||
\spx@@makefnmark
|
||||
\hyper@linkend
|
||||
}%
|
||||
\H@@footnotemark
|
||||
\let\@makefnmark\spx@@makefnmark
|
||||
}%
|
||||
}%
|
||||
\AtBeginDocument{%
|
||||
% let hyperref less complain
|
||||
\pdfstringdefDisableCommands{\def\sphinxfootnotemark [#1]{}}%
|
||||
|
@ -844,11 +844,16 @@ class LaTeXTranslator(SphinxTranslator):
|
||||
def visit_footnote(self, node: Element) -> None:
|
||||
self.in_footnote += 1
|
||||
label = cast(nodes.label, node[0])
|
||||
if 'auto' not in node:
|
||||
self.body.append('\\sphinxstepexplicit ')
|
||||
if self.in_parsed_literal:
|
||||
self.body.append('\\begin{footnote}[%s]' % label.astext())
|
||||
else:
|
||||
self.body.append('%\n')
|
||||
self.body.append('\\begin{footnote}[%s]' % label.astext())
|
||||
if 'auto' not in node:
|
||||
self.body.append('\\phantomsection'
|
||||
'\\label{\\thesphinxscope.%s}%%\n' % label.astext())
|
||||
self.body.append('\\sphinxAtStartFootnote\n')
|
||||
|
||||
def depart_footnote(self, node: Element) -> None:
|
||||
@ -1746,7 +1751,9 @@ class LaTeXTranslator(SphinxTranslator):
|
||||
label = cast(nodes.label, node[0])
|
||||
self.body.append('%\n')
|
||||
self.body.append('\\begin{footnotetext}[%s]'
|
||||
'\\sphinxAtStartFootnote\n' % label.astext())
|
||||
'\\phantomsection\\label{\\thesphinxscope.%s}%%\n'
|
||||
% (label.astext(), label.astext()))
|
||||
self.body.append('\\sphinxAtStartFootnote\n')
|
||||
|
||||
def depart_footnotetext(self, node: Element) -> None:
|
||||
# the \ignorespaces in particular for after table header use
|
||||
|
@ -723,7 +723,8 @@ def test_footnote(app, status, warning):
|
||||
print(result)
|
||||
print(status.getvalue())
|
||||
print(warning.getvalue())
|
||||
assert ('\\begin{footnote}[1]\\sphinxAtStartFootnote\nnumbered\n%\n'
|
||||
assert ('\\sphinxstepexplicit %\n\\begin{footnote}[1]\\phantomsection'
|
||||
'\\label{\\thesphinxscope.1}%\n\\sphinxAtStartFootnote\nnumbered\n%\n'
|
||||
'\\end{footnote}') in result
|
||||
assert ('\\begin{footnote}[2]\\sphinxAtStartFootnote\nauto numbered\n%\n'
|
||||
'\\end{footnote}') in result
|
||||
@ -731,9 +732,13 @@ def test_footnote(app, status, warning):
|
||||
assert '\\sphinxcite{footnote:bar}' in result
|
||||
assert ('\\bibitem[bar]{footnote:bar}\n\\sphinxAtStartPar\ncite\n') in result
|
||||
assert '\\sphinxcaption{Table caption \\sphinxfootnotemark[4]' in result
|
||||
assert ('\\hline%\n\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n'
|
||||
assert ('\\hline%\n\\begin{footnotetext}[4]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.4}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'footnote in table caption\n%\n\\end{footnotetext}\\ignorespaces %\n'
|
||||
'\\begin{footnotetext}[5]\\sphinxAtStartFootnote\n'
|
||||
'\\begin{footnotetext}[5]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.5}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'footnote in table header\n%\n\\end{footnotetext}\\ignorespaces '
|
||||
'\n\\sphinxAtStartPar\n'
|
||||
'VIDIOC\\_CROPCAP\n&\n\\sphinxAtStartPar\n') in result
|
||||
@ -759,19 +764,27 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning):
|
||||
assert '\\subsubsection*{The rubric title with a reference to {[}AuthorYear{]}}' in result
|
||||
assert ('\\chapter{The section with a reference to \\sphinxfootnotemark[5]}\n'
|
||||
'\\label{\\detokenize{index:the-section-with-a-reference-to}}'
|
||||
'%\n\\begin{footnotetext}[5]\\sphinxAtStartFootnote\n'
|
||||
'%\n\\begin{footnotetext}[5]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.5}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Footnote in section\n%\n\\end{footnotetext}') in result
|
||||
assert ('\\caption{This is the figure caption with a footnote to '
|
||||
'\\sphinxfootnotemark[7].}\\label{\\detokenize{index:id29}}\\end{figure}\n'
|
||||
'%\n\\begin{footnotetext}[7]\\sphinxAtStartFootnote\n'
|
||||
'%\n\\begin{footnotetext}[7]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.7}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Footnote in caption\n%\n\\end{footnotetext}') in result
|
||||
assert ('\\sphinxcaption{footnote \\sphinxfootnotemark[8] in '
|
||||
'caption of normal table}\\label{\\detokenize{index:id30}}') in result
|
||||
assert ('\\caption{footnote \\sphinxfootnotemark[9] '
|
||||
'in caption \\sphinxfootnotemark[10] of longtable\\strut}') in result
|
||||
assert ('\\endlastfoot\n%\n\\begin{footnotetext}[9]\\sphinxAtStartFootnote\n'
|
||||
assert ('\\endlastfoot\n%\n\\begin{footnotetext}[9]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.9}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Foot note in longtable\n%\n\\end{footnotetext}\\ignorespaces %\n'
|
||||
'\\begin{footnotetext}[10]\\sphinxAtStartFootnote\n'
|
||||
'\\begin{footnotetext}[10]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.10}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'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}]'
|
||||
@ -792,7 +805,9 @@ def test_latex_show_urls_is_inline(app, status, warning):
|
||||
print(result)
|
||||
print(status.getvalue())
|
||||
print(warning.getvalue())
|
||||
assert ('Same footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
|
||||
assert ('Same footnote number \\sphinxstepexplicit %\n'
|
||||
'\\begin{footnote}[1]\\phantomsection\\label{\\thesphinxscope.1}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'footnote in bar\n%\n\\end{footnote} in bar.rst') in result
|
||||
assert ('Auto footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
|
||||
'footnote in baz\n%\n\\end{footnote} in baz.rst') in result
|
||||
@ -806,12 +821,16 @@ def test_latex_show_urls_is_inline(app, status, warning):
|
||||
'{\\sphinxcrossref{The section with a reference to }}}' in result)
|
||||
assert ('First footnote: %\n\\begin{footnote}[2]\\sphinxAtStartFootnote\n'
|
||||
'First\n%\n\\end{footnote}') in result
|
||||
assert ('Second footnote: %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
|
||||
assert ('Second footnote: \\sphinxstepexplicit %\n'
|
||||
'\\begin{footnote}[1]\\phantomsection\\label{\\thesphinxscope.1}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Second\n%\n\\end{footnote}') in result
|
||||
assert '\\sphinxhref{http://sphinx-doc.org/}{Sphinx} (http://sphinx\\sphinxhyphen{}doc.org/)' in result
|
||||
assert ('Third footnote: %\n\\begin{footnote}[3]\\sphinxAtStartFootnote\n'
|
||||
'Third \\sphinxfootnotemark[4]\n%\n\\end{footnote}%\n'
|
||||
'\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n'
|
||||
'\\begin{footnotetext}[4]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.4}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Footnote inside footnote\n%\n\\end{footnotetext}\\ignorespaces') in result
|
||||
assert ('\\sphinxhref{http://sphinx-doc.org/~test/}{URL including tilde} '
|
||||
'(http://sphinx\\sphinxhyphen{}doc.org/\\textasciitilde{}test/)') in result
|
||||
@ -819,7 +838,9 @@ def test_latex_show_urls_is_inline(app, status, warning):
|
||||
'(http://sphinx\\sphinxhyphen{}doc.org/)}] '
|
||||
'\\leavevmode\n\\sphinxAtStartPar\nDescription' in result)
|
||||
assert ('\\item[{Footnote in term \\sphinxfootnotemark[6]}] '
|
||||
'\\leavevmode%\n\\begin{footnotetext}[6]\\sphinxAtStartFootnote\n'
|
||||
'\\leavevmode%\n\\begin{footnotetext}[6]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.6}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Footnote in term\n%\n\\end{footnotetext}\\ignorespaces '
|
||||
'\n\\sphinxAtStartPar\nDescription') in result
|
||||
assert ('\\item[{\\sphinxhref{http://sphinx-doc.org/}{Term in deflist} '
|
||||
@ -840,7 +861,9 @@ def test_latex_show_urls_is_footnote(app, status, warning):
|
||||
print(result)
|
||||
print(status.getvalue())
|
||||
print(warning.getvalue())
|
||||
assert ('Same footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
|
||||
assert ('Same footnote number \\sphinxstepexplicit %\n'
|
||||
'\\begin{footnote}[1]\\phantomsection\\label{\\thesphinxscope.1}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'footnote in bar\n%\n\\end{footnote} in bar.rst') in result
|
||||
assert ('Auto footnote number %\n\\begin{footnote}[2]\\sphinxAtStartFootnote\n'
|
||||
'footnote in baz\n%\n\\end{footnote} in baz.rst') in result
|
||||
@ -853,14 +876,18 @@ def test_latex_show_urls_is_footnote(app, status, warning):
|
||||
'{\\sphinxcrossref{The section with a reference to }}}') in result
|
||||
assert ('First footnote: %\n\\begin{footnote}[3]\\sphinxAtStartFootnote\n'
|
||||
'First\n%\n\\end{footnote}') in result
|
||||
assert ('Second footnote: %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
|
||||
assert ('Second footnote: \\sphinxstepexplicit %\n'
|
||||
'\\begin{footnote}[1]\\phantomsection\\label{\\thesphinxscope.1}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Second\n%\n\\end{footnote}') in result
|
||||
assert ('\\sphinxhref{http://sphinx-doc.org/}{Sphinx}'
|
||||
'%\n\\begin{footnote}[4]\\sphinxAtStartFootnote\n'
|
||||
'\\sphinxnolinkurl{http://sphinx-doc.org/}\n%\n\\end{footnote}') in result
|
||||
assert ('Third footnote: %\n\\begin{footnote}[6]\\sphinxAtStartFootnote\n'
|
||||
'Third \\sphinxfootnotemark[7]\n%\n\\end{footnote}%\n'
|
||||
'\\begin{footnotetext}[7]\\sphinxAtStartFootnote\n'
|
||||
'\\begin{footnotetext}[7]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.7}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Footnote inside footnote\n%\n'
|
||||
'\\end{footnotetext}\\ignorespaces') in result
|
||||
assert ('\\sphinxhref{http://sphinx-doc.org/~test/}{URL including tilde}'
|
||||
@ -868,16 +895,22 @@ def test_latex_show_urls_is_footnote(app, status, warning):
|
||||
'\\sphinxnolinkurl{http://sphinx-doc.org/~test/}\n%\n\\end{footnote}') in result
|
||||
assert ('\\item[{\\sphinxhref{http://sphinx-doc.org/}'
|
||||
'{URL in term}\\sphinxfootnotemark[9]}] '
|
||||
'\\leavevmode%\n\\begin{footnotetext}[9]\\sphinxAtStartFootnote\n'
|
||||
'\\leavevmode%\n\\begin{footnotetext}[9]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.9}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'\\sphinxnolinkurl{http://sphinx-doc.org/}\n%\n'
|
||||
'\\end{footnotetext}\\ignorespaces \n\\sphinxAtStartPar\nDescription') in result
|
||||
assert ('\\item[{Footnote in term \\sphinxfootnotemark[11]}] '
|
||||
'\\leavevmode%\n\\begin{footnotetext}[11]\\sphinxAtStartFootnote\n'
|
||||
'\\leavevmode%\n\\begin{footnotetext}[11]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.11}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Footnote in term\n%\n\\end{footnotetext}\\ignorespaces '
|
||||
'\n\\sphinxAtStartPar\nDescription') in result
|
||||
assert ('\\item[{\\sphinxhref{http://sphinx-doc.org/}{Term in deflist}'
|
||||
'\\sphinxfootnotemark[10]}] '
|
||||
'\\leavevmode%\n\\begin{footnotetext}[10]\\sphinxAtStartFootnote\n'
|
||||
'\\leavevmode%\n\\begin{footnotetext}[10]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.10}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'\\sphinxnolinkurl{http://sphinx-doc.org/}\n%\n'
|
||||
'\\end{footnotetext}\\ignorespaces \n\\sphinxAtStartPar\nDescription') in result
|
||||
assert ('\\sphinxurl{https://github.com/sphinx-doc/sphinx}\n' in result)
|
||||
@ -895,7 +928,9 @@ def test_latex_show_urls_is_no(app, status, warning):
|
||||
print(result)
|
||||
print(status.getvalue())
|
||||
print(warning.getvalue())
|
||||
assert ('Same footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
|
||||
assert ('Same footnote number \\sphinxstepexplicit %\n'
|
||||
'\\begin{footnote}[1]\\phantomsection\\label{\\thesphinxscope.1}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'footnote in bar\n%\n\\end{footnote} in bar.rst') in result
|
||||
assert ('Auto footnote number %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
|
||||
'footnote in baz\n%\n\\end{footnote} in baz.rst') in result
|
||||
@ -908,18 +943,24 @@ def test_latex_show_urls_is_no(app, status, warning):
|
||||
'{\\sphinxcrossref{The section with a reference to }}}' in result)
|
||||
assert ('First footnote: %\n\\begin{footnote}[2]\\sphinxAtStartFootnote\n'
|
||||
'First\n%\n\\end{footnote}') in result
|
||||
assert ('Second footnote: %\n\\begin{footnote}[1]\\sphinxAtStartFootnote\n'
|
||||
assert ('Second footnote: \\sphinxstepexplicit %\n'
|
||||
'\\begin{footnote}[1]\\phantomsection\\label{\\thesphinxscope.1}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Second\n%\n\\end{footnote}') in result
|
||||
assert '\\sphinxhref{http://sphinx-doc.org/}{Sphinx}' in result
|
||||
assert ('Third footnote: %\n\\begin{footnote}[3]\\sphinxAtStartFootnote\n'
|
||||
'Third \\sphinxfootnotemark[4]\n%\n\\end{footnote}%\n'
|
||||
'\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n'
|
||||
'\\begin{footnotetext}[4]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.4}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Footnote inside footnote\n%\n\\end{footnotetext}\\ignorespaces') in result
|
||||
assert '\\sphinxhref{http://sphinx-doc.org/~test/}{URL including tilde}' in result
|
||||
assert ('\\item[{\\sphinxhref{http://sphinx-doc.org/}{URL in term}}] '
|
||||
'\\leavevmode\n\\sphinxAtStartPar\nDescription') in result
|
||||
assert ('\\item[{Footnote in term \\sphinxfootnotemark[6]}] '
|
||||
'\\leavevmode%\n\\begin{footnotetext}[6]\\sphinxAtStartFootnote\n'
|
||||
'\\leavevmode%\n\\begin{footnotetext}[6]'
|
||||
'\\phantomsection\\label{\\thesphinxscope.6}%\n'
|
||||
'\\sphinxAtStartFootnote\n'
|
||||
'Footnote in term\n%\n\\end{footnotetext}\\ignorespaces '
|
||||
'\n\\sphinxAtStartPar\nDescription') in result
|
||||
assert ('\\item[{\\sphinxhref{http://sphinx-doc.org/}{Term in deflist}}] '
|
||||
|
Loading…
Reference in New Issue
Block a user