From b8e0e935e47560859dcfb9c236746d4bda19122a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20B?= Date: Sat, 15 Oct 2016 12:09:58 +0200 Subject: [PATCH] Improve LaTeX footnotes (#3022) Allow code-blocks in footnotes for LaTeX PDF output. This is done via using a ``footnote environment``, provided by LaTeX package footnotehyper which replaces old problematic package footnote. No need to ship a custom tabulary anymore. The footnote markers are silently removed from the table of contents and do not end in the PDF bookmarks (the old code in ``sphinx.sty`` copying ``footmisc.sty`` was not satisfactory and has been deleted and replaced by use of better ``\sphinxfootnotemark``.) Footnotes can be used also in captions of literal blocks. --- sphinx/texinputs/footnotehyper-sphinx.sty | 158 ++++++++ sphinx/texinputs/sphinx.sty | 52 +-- sphinx/texinputs/tabulary.sty | 454 ---------------------- sphinx/writers/latex.py | 40 +- tests/roots/test-footnotes/index.rst | 28 +- tests/test_build_latex.py | 168 ++++---- 6 files changed, 319 insertions(+), 581 deletions(-) create mode 100644 sphinx/texinputs/footnotehyper-sphinx.sty delete mode 100644 sphinx/texinputs/tabulary.sty diff --git a/sphinx/texinputs/footnotehyper-sphinx.sty b/sphinx/texinputs/footnotehyper-sphinx.sty new file mode 100644 index 000000000..d0c592710 --- /dev/null +++ b/sphinx/texinputs/footnotehyper-sphinx.sty @@ -0,0 +1,158 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{footnotehyper-sphinx}% + [2016/10/08 v0.9f hyperref aware footnote.sty for sphinx (JFB)] +%% +%% Package: footnotehyper-sphinx +%% Version: based on footnotehyper.sty v0.9f (2016/10/03) +%% as available at http://www.ctan.org/pkg/footnotehyper +%% License: the one applying to Sphinx +%% +%% Differences from footnotehyper v0.9f (2016/10/03): +%% 1. hyperref is assumed in use (with default hyperfootnotes=true), +%% 2. no need to check if footnote.sty was loaded, +%% 3. a special tabulary compatibility layer added, (partial but enough for +%% Sphinx), +%% 4. the \sphinxfootnotemark command is added. Its rôle is to silently remove +%% footnote marks from locations like the tables of contents, or page headers, +%% and to be compatible with hyperref constructions of bookmarks, and survive +%% to \MakeUppercase command or such which may be used to typeset chapter +%% titles for example. +%% +%% Note: with \footnotemark[N]/\footnotetext[N] syntax, hyperref +%% does not insert an hyperlink. This is _not_ improved here. +%% +\DeclareOption*{\PackageWarning{footnotehyper}{Option `\CurrentOption' is unknown}}% +\ProcessOptions\relax +\let\FNH@@makefntext\@makefntext\let\@makefntext\@firstofone +\RequirePackage{footnote} +\let\fnparbox\parbox\let\parbox\fn@parbox\let\@makefntext\FNH@@makefntext +\let\FNH@fn@footnote \footnote % buggy footnote.sty's \footnote +\let\FNH@fn@footnotetext\footnotetext % will be redefined later +\let\footnote \fn@latex@@footnote % meaning of \footnote before footnote.sty +\let\footnotetext\fn@latex@@footnotetext +\def\fn@endnote {\color@endgroup}% +\AtBeginDocument {% + \let\fn@latex@@footnote \footnote % meaning of \footnote at end of preamble + \let\fn@latex@@footnotetext\footnotetext + \let\fn@fntext \FNH@hyper@fntext + \let\spewnotes \FNH@hyper@spewnotes + \let\endsavenotes\spewnotes + \let\fn@endfntext\FNH@fixed@endfntext + \let\footnote \FNH@fixed@footnote + \let\footnotetext\FNH@fixed@footnotetext + \let\endfootnote\fn@endfntext + \let\endfootnotetext\endfootnote +}% +\def\FNH@hyper@fntext {% +%% amsmath compatibility + \ifx\ifmeasuring@\undefined\expandafter\@secondoftwo + \else\expandafter\@firstofone\fi + {\ifmeasuring@\expandafter\@gobbletwo\else\expandafter\@firstofone\fi}% +%% partial tabulary compatibility, [N] must be used, but Sphinx does it + {\ifx\equation$\expandafter\@gobbletwo\fi\FNH@hyper@fntext@i }%$ +}% +\long\def\FNH@hyper@fntext@i #1{\global\setbox\fn@notes\vbox + {\unvbox\fn@notes + \fn@startnote + \@makefntext + {\rule\z@\footnotesep\ignorespaces + \ifHy@nesting\expandafter\ltx@firstoftwo + \else\expandafter\ltx@secondoftwo + \fi + {\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}{#1}}% + {\Hy@raisedlink + {\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}% + {\relax}}% + \let\@currentHref\Hy@footnote@currentHref + \let\@currentlabelname\@empty + #1}% + \@finalstrut\strutbox }% + \fn@endnote }% +}% +\def\FNH@hyper@spewnotes {\endgroup + \if@savingnotes\else\ifvoid\fn@notes\else + \begingroup\let\@makefntext\@empty + \let\@finalstrut\@gobble + \let\rule\@gobbletwo + \H@@footnotetext{\unvbox\fn@notes}% + \endgroup\fi\fi +}% +\def\FNH@fixed@endfntext {% + \@finalstrut\strutbox + \fn@postfntext + \fn@endnote + \egroup\FNH@endfntext@next % will decide if link or no link +}% +\def\FNH@endfntext@link {\begingroup + \let\@makefntext\@empty\let\@finalstrut\@gobble\let\rule\@gobbletwo + \@footnotetext {\unvbox\z@}% + \endgroup +}% +\def\FNH@endfntext@nolink {\begingroup + \let\@makefntext\@empty\let\@finalstrut\@gobble + \let\rule\@gobbletwo + \if@savingnotes\expandafter\fn@fntext\else\expandafter\H@@footnotetext\fi + {\unvbox\z@}\endgroup +}% +\def\FNH@fixed@footnote {\ifx\@currenvir\fn@footnote + \expandafter\FNH@footnoteenv\else\expandafter\fn@latex@@footnote\fi }% +\def\FNH@footnoteenv {\@ifnextchar[\FNH@xfootnoteenv%] + {\stepcounter\@mpfn + \protected@xdef\@thefnmark{\thempfn}\@footnotemark + \def\FNH@endfntext@next{\FNH@endfntext@link}\fn@startfntext}}% +\def\FNH@xfootnoteenv [#1]{% + \begingroup + \csname c@\@mpfn\endcsname #1\relax + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup\@footnotemark\def\FNH@endfntext@next{\FNH@endfntext@link}% + \fn@startfntext}% +\def\FNH@fixed@footnotetext {\ifx\@currenvir\fn@footnotetext + \expandafter\FNH@footnotetextenv\else\expandafter\fn@latex@@footnotetext\fi}% +\def\FNH@footnotetextenv {\@ifnextchar[\FNH@xfootnotetextenv%] + {\protected@xdef\@thefnmark{\thempfn}% + \def\FNH@endfntext@next{\FNH@endfntext@link}\fn@startfntext}}% +\def\FNH@xfootnotetextenv [#1]{% + \begingroup + \csname c@\@mpfn\endcsname #1\relax + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup\def\FNH@endfntext@next{\FNH@endfntext@nolink}% + \fn@startfntext }% +% Now some checks in case some package has modified \@makefntext. +\AtBeginDocument +{% compatibility with French module of LaTeX babel + \ifx\@makefntextFB\undefined + \expandafter\@gobble\else\expandafter\@firstofone\fi + {\ifFBFrenchFootnotes \let\FNH@@makefntext\@makefntextFB \else + \let\FNH@@makefntext\@makefntextORI\fi}% + \expandafter\FNH@check@a\FNH@@makefntext{1.2!3?4,}\FNH@@@1.2!3?4,\FNH@@@\relax +}% +\long\def\FNH@check@a #11.2!3?4,#2\FNH@@@#3% +{% + \ifx\relax#3\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi + \FNH@bad@footnote@env + {\def\fn@prefntext{#1}\def\fn@postfntext{#2}\FNH@check@b}% +}% +\def\FNH@check@b #1\relax +{% + \expandafter\expandafter\expandafter\FNH@check@c + \expandafter\meaning\expandafter\fn@prefntext + \meaning\fn@postfntext1.2!3?4,\FNH@check@c\relax +}% +\def\FNH@check@c #11.2!3?4,#2#3\relax + {\ifx\FNH@check@c#2\expandafter\@gobble\fi\FNH@bad@footnote@env}% +\def\FNH@bad@footnote@env +{\PackageWarningNoLine{footnotehyper}% + {The footnote environment from package footnote^^J + will be dysfunctional, sorry (not my fault...). You may try to make a bug^^J + report at https://github.com/sphinx-doc/sphinx including the next lines:}% + \typeout{\meaning\@makefntext}% + \let\fn@prefntext\@empty\let\fn@postfntext\@empty +}% +%% \sphinxfootnotemark: usable in section titles and silently removed from TOCs +\def\sphinxfootnotemark [#1]% + {\ifx\thepage\relax\else \protect\footnotemark[#1]\fi}% +\AtBeginDocument + {\pdfstringdefDisableCommands{\def\sphinxfootnotemark [#1]{}}}% +\endinput +%% +%% End of file `footnotehyper-sphinx.sty'. diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index bb2da9f1f..d6e19d53d 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -49,9 +49,13 @@ \fvset{fontsize=\small} % For table captions. \RequirePackage{threeparttable} -% Handle footnotes in tables. -\RequirePackage{footnote} +% For hyperlinked footnotes in tables; also for gathering footnotes from +% topic and warning blocks. Also to allow code-blocks in footnotes. +\RequirePackage{footnotehyper-sphinx} \makesavenoteenv{tabulary} +\makesavenoteenv{tabular} +\makesavenoteenv{threeparttable} +% (longtable is hyperref compatible and needs no special treatment here.) % For the H specifier. Do not \restylefloat{figure}, it breaks Sphinx code % for allowing figures in tables. \RequirePackage{float} @@ -215,6 +219,12 @@ {\py@NormalColor \captionof{literalblock}{\sphinxLiteralBlockLabel #1}\smallskip }% } +\newcommand*\sphinxSetupCodeBlockInFootnote {% + \fvset{fontsize=\footnotesize}\let\caption\sphinxfigcaption + \sphinxverbatimwithminipagetrue % reduces vertical spaces + % we counteract float.sty's \caption which does \@normalsize + \let\normalsize\footnotesize\let\@parboxrestore\relax + \abovecaptionskip \smallskipamount \belowcaptionskip \z@skip} % Inspired and adapted from framed.sty's \CustomFBox with extra handling % of a non separable by pagebreak caption. @@ -474,6 +484,8 @@ % imitate closely the layout from Sphinx <= 1.4.1; the \FrameHeightAdjust % will put top part of frame on this baseline. \def\FrameHeightAdjust {\baselineskip}% + % use package footnote to handle footnotes + \savenotes \trivlist\item\noindent % use a minipage if we are already inside a framed environment \ifspx@inframed\begin{minipage}{\linewidth}\fi @@ -487,9 +499,6 @@ % itemize/enumerate are therein typeset more tightly, we want to keep % that). We copy-paste from LaTeX source code but don't do a real minipage. \@pboxswfalse - % for footnotes, but Sphinx inactivates footnotes in topics - \def\@mpfn{mpfootnote}\def\thempfn{\thempfootnote}\c@mpfootnote\z@ - \let\@footnotetext\@mpfootnotetext \let\@listdepth\@mplistdepth \@mplistdepth\z@ \@minipagerestore \@setminipage @@ -497,14 +506,12 @@ }% {% insert the "endminipage" code \par\unskip - % handle (currently non existing) minipage style footnotes - \ifvoid\@mpfootins\else - \vskip\skip\@mpfootins\normalcolor\footnoterule\unvbox\@mpfootins - \fi \@minipagefalse \endMakeFramed \ifspx@inframed\end{minipage}\fi \endtrivlist + % output the stored footnotes + \spewnotes } @@ -634,6 +641,7 @@ \fboxsep\FrameSep \fboxrule\FrameRule \fcolorbox{spx@notice@bordercolor}{spx@notice@bgcolor}{##1}% \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% + \savenotes % use a minipage if we are already inside a framed environment \ifspx@inframed \noindent\begin{minipage}{\linewidth} @@ -649,22 +657,17 @@ \advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize % minipage initialization copied from LaTeX source code. \@pboxswfalse - % for footnotes - \def\@mpfn{mpfootnote}\def\thempfn{\thempfootnote}\c@mpfootnote\z@ - \let\@footnotetext\@mpfootnotetext \let\@listdepth\@mplistdepth \@mplistdepth\z@ \@minipagerestore \@setminipage }% } {% \par\unskip - % handles footnotes - \ifvoid\@mpfootins\else - \vskip\skip\@mpfootins\normalcolor\footnoterule\unvbox\@mpfootins - \fi \@minipagefalse \endMakeFramed \ifspx@inframed\end{minipage}\fi + % set footnotes at bottom of page + \spewnotes % arrange for similar spacing below frame as for "light" boxes. \vskip .4\baselineskip }% end of sphinxheavybox environment definition @@ -886,23 +889,6 @@ {\endlist} \fi -% From footmisc.sty: allows footnotes in titles -\let\FN@sf@@footnote\footnote -\def\footnote{\ifx\protect\@typeset@protect - \expandafter\FN@sf@@footnote - \else - \expandafter\FN@sf@gobble@opt - \fi -} -\edef\FN@sf@gobble@opt{\noexpand\protect - \expandafter\noexpand\csname FN@sf@gobble@opt \endcsname} -\expandafter\def\csname FN@sf@gobble@opt \endcsname{% - \@ifnextchar[%] - \FN@sf@gobble@twobracket - \@gobble -} -\def\FN@sf@gobble@twobracket[#1]#2{} - % adjust the margins for footer, % this works with the jsclasses only (Japanese standard document classes) \ifx\@jsc@uplatextrue\undefined\else diff --git a/sphinx/texinputs/tabulary.sty b/sphinx/texinputs/tabulary.sty deleted file mode 100644 index 03e07ec2a..000000000 --- a/sphinx/texinputs/tabulary.sty +++ /dev/null @@ -1,454 +0,0 @@ -%% -%% This is file `tabulary.sty', -%% generated with the docstrip utility. -%% -%% The original source files were: -%% -%% tabulary.dtx (with options: `package') -%% DRAFT VERSION -%% -%% File `tabulary.dtx'. -%% Copyright (C) 1995 1996 2003 2008 David Carlisle -%% This file may be distributed under the terms of the LPPL. -%% See 00readme.txt for details. -%% -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{tabulary} - [2014/06/11 v0.10 tabulary package (DPC) + footnote patch (sphinx)] -\RequirePackage{array} -\catcode`\Z=14 -\DeclareOption{debugshow}{\catcode`\Z=9\relax} -\ProcessOptions -\def\arraybackslash{\let\\=\@arraycr} -\def\@finalstrut#1{% - \unskip\ifhmode\nobreak\fi\vrule\@width\z@\@height\z@\@depth\dp#1} -\newcount\TY@count -\def\tabulary{% - \let\TY@final\tabular - \let\endTY@final\endtabular - \TY@tabular} -\def\TY@tabular#1{% - \edef\TY@{\@currenvir}% - {\ifnum0=`}\fi - \@ovxx\TY@linewidth - \@ovyy\TY@tablewidth - \count@\z@ - \@tempswatrue - \@whilesw\if@tempswa\fi{% - \advance\count@\@ne - \expandafter\ifx\csname TY@F\the\count@\endcsname\relax - \@tempswafalse - \else - \expandafter\let\csname TY@SF\the\count@\expandafter\endcsname - \csname TY@F\the\count@\endcsname - \global\expandafter\let\csname TY@F\the\count@\endcsname\relax - \expandafter\let\csname TY@S\the\count@\expandafter\endcsname - \csname TY@\the\count@\endcsname - \fi}% - \global\TY@count\@ne - \TY@width\xdef{0pt}% - \global\TY@tablewidth\z@ - \global\TY@linewidth#1\relax -Z\message{^^J^^JTable^^J% -Z Target Width: \the\TY@linewidth^^J% -Z \string\tabcolsep: \the\tabcolsep\space -Z \string\arrayrulewidth: \the\arrayrulewidth\space -Z \string\doublerulesep: \the\doublerulesep^^J% -Z \string\tymin: \the\tymin\space -Z \string\tymax: \the\tymax^^J}% - \let\@classz\TY@classz - \let\verb\TX@verb - \toks@{}\TY@get@body} -\let\TY@@mkpream\@mkpream -\def\TY@mkpream{% - \def\@addamp{% - \if@firstamp \@firstampfalse \else - \global\advance\TY@count\@ne - \edef\@preamble{\@preamble &}\fi - \TY@width\xdef{0pt}}% - \def\@acol{% - \TY@subwidth\col@sep - \@addtopreamble{\hskip\col@sep}}% - \let\@arrayrule\TY@arrayrule - \let\@classvi\TY@classvi - \def\@classv{\save@decl - \expandafter\NC@ecs\@nextchar\extracolsep{}\extracolsep\@@@ - \sbox\z@{\d@llarbegin\@nextchar\d@llarend}% - \TY@subwidth{\wd\z@}% - \@addtopreamble{\d@llarbegin\the@toks\the\count@\relax\d@llarend}% - \prepnext@tok}% - \global\let\@mkpream\TY@@mkpream - \TY@@mkpream} -\def\TY@arrayrule{% - \TY@subwidth\arrayrulewidth - \@addtopreamble \vline} -\def\TY@classvi{\ifcase \@lastchclass - \@acol \or - \TY@subwidth\doublerulesep - \@addtopreamble{\hskip \doublerulesep}\or - \@acol \or - \@classvii - \fi} -\def\TY@tab{% - \setbox\z@\hbox\bgroup - \let\[$\let\]$% - \let\equation$\let\endequation$% - \col@sep\tabcolsep - \let\d@llarbegin\begingroup\let\d@llarend\endgroup - \let\@mkpream\TY@mkpream - \def\multicolumn##1##2##3{\multispan##1\relax}% - \CT@start\TY@tabarray} -\def\TY@tabarray{\@ifnextchar[{\TY@array}{\@array[t]}} -\def\TY@array[#1]{\@array[t]} -\def\TY@width#1{% - \expandafter#1\csname TY@\the\TY@count\endcsname} -\def\TY@subwidth#1{% - \TY@width\dimen@ - \advance\dimen@-#1\relax - \TY@width\xdef{\the\dimen@}% - \global\advance\TY@linewidth-#1\relax} -\def\endtabulary{% - \gdef\@halignto{}% - \let\TY@footnote\footnote% - \def\footnote{}% prevent footnotes from doing anything - \expandafter\TY@tab\the\toks@ - \crcr\omit - {\xdef\TY@save@row{}% - \loop - \advance\TY@count\m@ne - \ifnum\TY@count>\z@ - \xdef\TY@save@row{\TY@save@row&\omit}% - \repeat}\TY@save@row - \endarray\global\setbox1=\lastbox\setbox0=\vbox{\unvbox1 - \unskip\global\setbox1=\lastbox}\egroup - \dimen@\TY@linewidth - \divide\dimen@\TY@count - \ifdim\dimen@<\tymin - \TY@warn{tymin too large (\the\tymin), resetting to \the\dimen@}% - \tymin\dimen@ - \fi - \setbox\tw@=\hbox{\unhbox\@ne - \loop -\@tempdima=\lastskip -\ifdim\@tempdima>\z@ -Z \message{ecs=\the\@tempdima^^J}% - \global\advance\TY@linewidth-\@tempdima -\fi - \unskip - \setbox\tw@=\lastbox - \ifhbox\tw@ -Z \message{Col \the\TY@count: Initial=\the\wd\tw@\space}% - \ifdim\wd\tw@>\tymax - \wd\tw@\tymax -Z \message{> max\space}% -Z \else -Z \message{ \@spaces\space}% - \fi - \TY@width\dimen@ -Z \message{\the\dimen@\space}% - \advance\dimen@\wd\tw@ -Z \message{Final=\the\dimen@\space}% - \TY@width\xdef{\the\dimen@}% - \ifdim\dimen@<\tymin -Z \message{< tymin}% - \global\advance\TY@linewidth-\dimen@ - \expandafter\xdef\csname TY@F\the\TY@count\endcsname - {\the\dimen@}% - \else - \expandafter\ifx\csname TY@F\the\TY@count\endcsname\z@ -Z \message{***}% - \global\advance\TY@linewidth-\dimen@ - \expandafter\xdef\csname TY@F\the\TY@count\endcsname - {\the\dimen@}% - \else -Z \message{> tymin}% - \global\advance\TY@tablewidth\dimen@ - \global\expandafter\let\csname TY@F\the\TY@count\endcsname - \maxdimen - \fi\fi - \advance\TY@count\m@ne - \repeat}% - \TY@checkmin - \TY@checkmin - \TY@checkmin - \TY@checkmin - \TY@count\z@ - \let\TY@box\TY@box@v - \let\footnote\TY@footnote % restore footnotes - {\expandafter\TY@final\the\toks@\endTY@final}% - \count@\z@ - \@tempswatrue - \@whilesw\if@tempswa\fi{% - \advance\count@\@ne - \expandafter\ifx\csname TY@SF\the\count@\endcsname\relax - \@tempswafalse - \else - \global\expandafter\let\csname TY@F\the\count@\expandafter\endcsname - \csname TY@SF\the\count@\endcsname - \global\expandafter\let\csname TY@\the\count@\expandafter\endcsname - \csname TY@S\the\count@\endcsname - \fi}% - \TY@linewidth\@ovxx - \TY@tablewidth\@ovyy - \ifnum0=`{\fi}} -\def\TY@checkmin{% - \let\TY@checkmin\relax -\ifdim\TY@tablewidth>\z@ - \Gscale@div\TY@ratio\TY@linewidth\TY@tablewidth - \ifdim\TY@tablewidth <\TY@linewidth - \def\TY@ratio{1}% - \fi -\else - \TY@warn{No suitable columns!}% - \def\TY@ratio{1}% -\fi -\count@\z@ -Z \message{^^JLine Width: \the\TY@linewidth, -Z Natural Width: \the\TY@tablewidth, -Z Ratio: \TY@ratio^^J}% -\@tempdima\z@ -\loop -\ifnum\count@<\TY@count -\advance\count@\@ne - \ifdim\csname TY@F\the\count@\endcsname>\tymin - \dimen@\csname TY@\the\count@\endcsname - \dimen@\TY@ratio\dimen@ - \ifdim\dimen@<\tymin -Z \message{Column \the\count@\space ->}% - \global\expandafter\let\csname TY@F\the\count@\endcsname\tymin - \global\advance\TY@linewidth-\tymin - \global\advance\TY@tablewidth-\csname TY@\the\count@\endcsname - \let\TY@checkmin\TY@@checkmin - \else - \expandafter\xdef\csname TY@F\the\count@\endcsname{\the\dimen@}% - \advance\@tempdima\csname TY@F\the\count@\endcsname - \fi - \fi -Z \dimen@\csname TY@F\the\count@\endcsname\message{\the\dimen@, }% -\repeat -Z \message{^^JTotal:\the\@tempdima^^J}% -} -\let\TY@@checkmin\TY@checkmin -\newdimen\TY@linewidth -\def\tyformat{\everypar{{\nobreak\hskip\z@skip}}} -\newdimen\tymin -\tymin=10pt -\newdimen\tymax -\tymax=2\textwidth -\def\@testpach{\@chclass - \ifnum \@lastchclass=6 \@ne \@chnum \@ne \else - \ifnum \@lastchclass=7 5 \else - \ifnum \@lastchclass=8 \tw@ \else - \ifnum \@lastchclass=9 \thr@@ - \else \z@ - \ifnum \@lastchclass = 10 \else - \edef\@nextchar{\expandafter\string\@nextchar}% - \@chnum - \if \@nextchar c\z@ \else - \if \@nextchar l\@ne \else - \if \@nextchar r\tw@ \else - \if \@nextchar C7 \else - \if \@nextchar L8 \else - \if \@nextchar R9 \else - \if \@nextchar J10 \else - \z@ \@chclass - \if\@nextchar |\@ne \else - \if \@nextchar !6 \else - \if \@nextchar @7 \else - \if \@nextchar <8 \else - \if \@nextchar >9 \else - 10 - \@chnum - \if \@nextchar m\thr@@\else - \if \@nextchar p4 \else - \if \@nextchar b5 \else - \z@ \@chclass \z@ \@preamerr \z@ \fi \fi \fi \fi\fi \fi \fi\fi \fi - \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi} -\def\TY@classz{% - \@classx - \@tempcnta\count@ - \ifx\TY@box\TY@box@v - \global\advance\TY@count\@ne - \fi - \let\centering c% - \let\raggedright\noindent - \let\raggedleft\indent - \let\arraybackslash\relax - \prepnext@tok - \ifnum\@chnum<4 - \global\expandafter\let\csname TY@F\the\TY@count\endcsname\z@ - \fi - \ifnum\@chnum=6 - \global\expandafter\let\csname TY@F\the\TY@count\endcsname\z@ - \fi - \@addtopreamble{% - \ifcase\@chnum - \hfil \d@llarbegin\insert@column\d@llarend \hfil \or - \kern\z@ - \d@llarbegin \insert@column \d@llarend \hfil \or - \hfil\kern\z@ \d@llarbegin \insert@column \d@llarend \or - $\vcenter\@startpbox{\@nextchar}\insert@column \@endpbox $\or - \vtop \@startpbox{\@nextchar}\insert@column \@endpbox \or - \vbox \@startpbox{\@nextchar}\insert@column \@endpbox \or - \d@llarbegin \insert@column \d@llarend \or% dubious "s" case - \TY@box\centering\or - \TY@box\raggedright\or - \TY@box\raggedleft\or - \TY@box\relax - \fi}\prepnext@tok} -\def\TY@box#1{% - \ifx\centering#1% - \hfil \d@llarbegin\insert@column\d@llarend \hfil \else - \ifx\raggedright#1% - \kern\z@%<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - \d@llarbegin \insert@column \d@llarend \hfil \else - \ifx\raggedleft#1% - \hfil\kern\z@ \d@llarbegin \insert@column \d@llarend \else - \ifx\relax#1% - \d@llarbegin \insert@column \d@llarend - \fi \fi \fi \fi} -\def\TY@box@v#1{% - \vtop \@startpbox{\csname TY@F\the\TY@count\endcsname}% - #1\arraybackslash\tyformat - \insert@column\@endpbox} -\newdimen\TY@tablewidth -\def\Gscale@div#1#2#3{% - \setlength\dimen@{#3}% - \ifdim\dimen@=\z@ - \PackageError{graphics}{Division by 0}\@eha - \dimen@#2% - \fi - \edef\@tempd{\the\dimen@}% - \setlength\dimen@{#2}% - \count@65536\relax - \ifdim\dimen@<\z@ - \dimen@-\dimen@ - \count@-\count@ - \fi - \loop - \ifdim\dimen@<8192\p@ - \dimen@\tw@\dimen@ - \divide\count@\tw@ - \repeat - \dimen@ii=\@tempd\relax - \divide\dimen@ii\count@ - \divide\dimen@\dimen@ii - \edef#1{\strip@pt\dimen@}} -\long\def\TY@get@body#1\end - {\toks@\expandafter{\the\toks@#1}\TY@find@end} -\def\TY@find@end#1{% - \def\@tempa{#1}% - \ifx\@tempa\TY@\def\@tempa{\end{#1}}\expandafter\@tempa - \else\toks@\expandafter - {\the\toks@\end{#1}}\expandafter\TY@get@body\fi} -\def\TY@warn{% - \PackageWarning{tabulary}} -\catcode`\Z=11 -\AtBeginDocument{ -\@ifpackageloaded{colortbl}{% -\expandafter\def\expandafter\@mkpream\expandafter#\expandafter1% - \expandafter{% - \expandafter\let\expandafter\CT@setup\expandafter\relax - \expandafter\let\expandafter\CT@color\expandafter\relax - \expandafter\let\expandafter\CT@do@color\expandafter\relax - \expandafter\let\expandafter\color\expandafter\relax - \expandafter\let\expandafter\CT@column@color\expandafter\relax - \expandafter\let\expandafter\CT@row@color\expandafter\relax - \expandafter\let\expandafter\CT@cell@color\expandafter\relax - \@mkpream{#1}} -\let\TY@@mkpream\@mkpream -\def\TY@classz{% - \@classx - \@tempcnta\count@ - \ifx\TY@box\TY@box@v - \global\advance\TY@count\@ne - \fi - \let\centering c% - \let\raggedright\noindent - \let\raggedleft\indent - \let\arraybackslash\relax - \prepnext@tok -\expandafter\CT@extract\the\toks\@tempcnta\columncolor!\@nil - \ifnum\@chnum<4 - \global\expandafter\let\csname TY@F\the\TY@count\endcsname\z@ - \fi - \ifnum\@chnum=6 - \global\expandafter\let\csname TY@F\the\TY@count\endcsname\z@ - \fi - \@addtopreamble{% - \setbox\z@\hbox\bgroup\bgroup - \ifcase\@chnum - \hskip\stretch{.5}\kern\z@ - \d@llarbegin\insert@column\d@llarend\hskip\stretch{.5}\or - \kern\z@%<<<<<<<<<<<<<<<<<<<<<<<<<<< - \d@llarbegin \insert@column \d@llarend \hfill \or - \hfill\kern\z@ \d@llarbegin \insert@column \d@llarend \or - $\vcenter\@startpbox{\@nextchar}\insert@column \@endpbox $\or - \vtop \@startpbox{\@nextchar}\insert@column \@endpbox \or - \vbox \@startpbox{\@nextchar}\insert@column \@endpbox \or - \d@llarbegin \insert@column \d@llarend \or% dubious s case - \TY@box\centering\or - \TY@box\raggedright\or - \TY@box\raggedleft\or - \TY@box\relax - \fi - \egroup\egroup -\begingroup - \CT@setup - \CT@column@color - \CT@row@color - \CT@cell@color - \CT@do@color -\endgroup - \@tempdima\ht\z@ - \advance\@tempdima\minrowclearance - \vrule\@height\@tempdima\@width\z@ -\unhbox\z@ -}\prepnext@tok}% - \def\TY@arrayrule{% - \TY@subwidth\arrayrulewidth - \@addtopreamble{{\CT@arc@\vline}}}% - \def\TY@classvi{\ifcase \@lastchclass - \@acol \or - \TY@subwidth\doublerulesep - \ifx\CT@drsc@\relax - \@addtopreamble{\hskip\doublerulesep}% - \else - \@addtopreamble{{\CT@drsc@\vrule\@width\doublerulesep}}% - \fi\or - \@acol \or - \@classvii - \fi}% -}{% -\let\CT@start\relax -} -} -{\uccode`\*=`\ % -\uppercase{\gdef\TX@verb{% - \leavevmode\null\TX@vwarn - {\ifnum0=`}\fi\ttfamily\let\\\ignorespaces - \@ifstar{\let~*\TX@vb}{\TX@vb}}}} -\def\TX@vb#1{\def\@tempa##1#1{\toks@{##1}\edef\@tempa{\the\toks@}% - \expandafter\TX@v\meaning\@tempa\\ \\\ifnum0=`{\fi}}\@tempa!} -\def\TX@v#1!{\afterassignment\TX@vfirst\let\@tempa= } -\begingroup -\catcode`\*=\catcode`\# -\catcode`\#=12 -\gdef\TX@vfirst{% - \if\@tempa#% - \def\@tempb{\TX@v@#}% - \else - \let\@tempb\TX@v@ - \if\@tempa\space~\else\@tempa\fi - \fi - \@tempb} -\gdef\TX@v@*1 *2{% - \TX@v@hash*1##\relax\if*2\\\else~\expandafter\TX@v@\fi*2} -\gdef\TX@v@hash*1##*2{*1\ifx*2\relax\else#\expandafter\TX@v@hash\fi*2} -\endgroup -\def\TX@vwarn{% - \@warning{\noexpand\verb may be unreliable inside tabularx/y}% - \global\let\TX@vwarn\@empty} -\endinput -%% -%% End of file `tabulary.sty'. diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index a47864443..27eabb230 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -961,12 +961,17 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_collected_footnote(self, node): self.in_footnote += 1 if 'footnotetext' in node: - self.body.append('\\footnotetext[%s]{\sphinxAtStartFootnote\n' % node['number']) + self.body.append('%%\n\\begin{footnotetext}[%s]' + '\\sphinxAtStartFootnote\n' % node['number']) else: - self.body.append('\\footnote[%s]{\sphinxAtStartFootnote\n' % node['number']) + self.body.append('%%\n\\begin{footnote}[%s]' + '\\sphinxAtStartFootnote\n' % node['number']) def depart_collected_footnote(self, node): - self.body.append('}') + if 'footnotetext' in node: + self.body.append('%\n\\end{footnotetext}') + else: + self.body.append('%\n\\end{footnote}') self.in_footnote -= 1 def visit_label(self, node): @@ -1488,6 +1493,7 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_caption(self, node): self.in_caption += 1 + self.restrict_footnote(node) if self.in_container_literal_block: self.body.append('\\sphinxSetupCaptionForVerbatim{') elif self.in_minipage and isinstance(node.parent, nodes.figure): @@ -1500,6 +1506,7 @@ class LaTeXTranslator(nodes.NodeVisitor): def depart_caption(self, node): self.body.append('}') self.in_caption -= 1 + self.unrestrict_footnote(node) def visit_legend(self, node): self.body.append('{\\small ') @@ -1831,13 +1838,10 @@ class LaTeXTranslator(nodes.NodeVisitor): # if a footnote has been inserted once, it shouldn't be repeated # by the next reference if used: - if self.table or self.in_term or self.in_title: - self.body.append('\\protect\\footnotemark[%s]' % num) - else: - self.body.append('\\footnotemark[%s]' % num) + self.body.append('\\sphinxfootnotemark[%s]' % num) elif self.footnote_restricted: self.footnotestack[-1][num][1] = True - self.body.append('\\protect\\footnotemark[%s]' % num) + self.body.append('\\sphinxfootnotemark[%s]' % num) self.pending_footnotes.append(footnode) else: self.footnotestack[-1][num][1] = True @@ -1848,10 +1852,6 @@ class LaTeXTranslator(nodes.NodeVisitor): pass def visit_literal_block(self, node): - if self.in_footnote: - raise UnsupportedError('%s:%s: literal blocks in footnotes are ' - 'not supported by LaTeX' % - (self.curfilestack[-1], node.line)) if node.rawsource != node.astext(): # most probably a parsed-literal block -- don't highlight self.body.append('\\begin{alltt}\n') @@ -1863,7 +1863,7 @@ class LaTeXTranslator(nodes.NodeVisitor): # suppress with anchor=False \phantomsection insertion ids += self.hypertarget(node['ids'][0], anchor=False) # LaTeX code will insert \phantomsection prior to \label - if ids: + if ids and not self.in_footnote: self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + ids + '}') code = node.astext() lang = self.hlsettingstack[-1][0] @@ -1888,9 +1888,13 @@ class LaTeXTranslator(nodes.NodeVisitor): **highlight_args) # workaround for Unicode issue hlcode = hlcode.replace(u'€', u'@texteuro[]') + if self.in_footnote: + self.body.append('\n\\sphinxSetupCodeBlockInFootnote') + hlcode = hlcode.replace('\\begin{Verbatim}', + '\\begin{sphinxVerbatim}') # if in table raise verbatim flag to avoid "tabulary" environment # and opt for sphinxVerbatimintable to handle caption & long lines - if self.table: + elif self.table: self.table.has_problematic = True self.table.has_verbatim = True hlcode = hlcode.replace('\\begin{Verbatim}', @@ -1900,10 +1904,12 @@ class LaTeXTranslator(nodes.NodeVisitor): '\\begin{sphinxVerbatim}') # get consistent trailer hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim} - self.body.append('\n' + hlcode + '\\end{sphinxVerbatim%s}\n' % - (self.table and 'intable' or '')) + self.body.append('\n' + hlcode + '\\end{sphinxVerbatim') + if self.table and not self.in_footnote: + self.body.append('intable') + self.body.append('}\n') if ids: - self.body.append('\\let\\sphinxLiteralBlockLabel\empty\n') + self.body.append('\\let\\sphinxLiteralBlockLabel\\empty\n') raise nodes.SkipNode def depart_literal_block(self, node): diff --git a/tests/roots/test-footnotes/index.rst b/tests/roots/test-footnotes/index.rst index 3a8bc25c5..a714f9e22 100644 --- a/tests/roots/test-footnotes/index.rst +++ b/tests/roots/test-footnotes/index.rst @@ -76,15 +76,17 @@ Footnote in term [#]_ .. [#] Foot note in table -.. list-table:: footnote [#]_ in caption of longtable +.. list-table:: footnote [#]_ in caption [#]_ of longtable :widths: 1 1 :header-rows: 1 * - name - desc - * - a - - b - * - a + * - This is a reference to the code-block in the footnote: + :ref:`codeblockinfootnote` + - This is one more footnote with some code in it [#]_. + * - This is a reference to the other code block: + :ref:`codeblockinanotherfootnote` - b * - a - b @@ -148,3 +150,21 @@ Footnote in term [#]_ - b .. [#] Foot note in longtable + +.. [#] Second footnote in caption of longtable + + .. code-block:: python + :caption: I am in a footnote + :name: codeblockinfootnote + + def foo(x,y): + return x+y + +.. [#] Third footnote in longtable + + .. code-block:: python + :caption: I am also in a footnote + :name: codeblockinanotherfootnote + + def bar(x,y): + return x+y diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 89a888ab3..a0366f1f1 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -380,22 +380,26 @@ def test_footnote(app, status, warning): print(result) print(status.getvalue()) print(warning.getvalue()) - assert '\\footnote[1]{\sphinxAtStartFootnote\nnumbered\n}' in result - assert '\\footnote[2]{\sphinxAtStartFootnote\nauto numbered\n}' in result - assert '\\footnote[3]{\sphinxAtStartFootnote\nnamed\n}' in result + assert ('\\begin{footnote}[1]\\sphinxAtStartFootnote\nnumbered\n%\n' + '\\end{footnote}') in result + assert ('\\begin{footnote}[2]\\sphinxAtStartFootnote\nauto numbered\n%\n' + '\\end{footnote}') in result + assert '\\begin{footnote}[3]\\sphinxAtStartFootnote\nnamed\n%\n\\end{footnote}' in result assert '{\\hyperref[footnote:bar]{\\sphinxcrossref{{[}bar{]}}}}' in result assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} ' in result assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} \ncite' in result assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} \ncite\n}' in result - assert '\\capstart\\caption{Table caption \\protect\\footnotemark[4]}' in result - assert 'name \\protect\\footnotemark[5]' in result - assert ('\\end{threeparttable}\n\n' - '\\footnotetext[4]{\sphinxAtStartFootnote\nfootnotes in table caption\n}' - '\\footnotetext[5]{\sphinxAtStartFootnote\nfootnotes in table\n}' in result) + assert '\\caption{Table caption \\sphinxfootnotemark[4]' in result + assert 'name \\sphinxfootnotemark[5]' in result + assert ('\\end{threeparttable}\n\n%\n' + '\\begin{footnotetext}[4]\sphinxAtStartFootnote\n' + 'footnotes in table caption\n%\n\\end{footnotetext}%\n' + '\\begin{footnotetext}[5]\sphinxAtStartFootnote\n' + 'footnotes in table\n%\n\\end{footnotetext}') in result @with_app(buildername='latex', testroot='footnotes') -def test_reference_in_caption(app, status, warning): +def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning): app.builder.build_all() result = (app.outdir / 'Python.tex').text(encoding='utf8') print(result) @@ -406,20 +410,27 @@ def test_reference_in_caption(app, status, warning): assert '\\chapter{The section with a reference to {[}AuthorYear{]}}' in result assert '\\caption{The table title with a reference to {[}AuthorYear{]}}' in result assert '\\paragraph{The rubric title with a reference to {[}AuthorYear{]}}' in result - assert ('\\chapter{The section with a reference to \\protect\\footnotemark[4]}\n' + assert ('\\chapter{The section with a reference to \\sphinxfootnotemark[4]}\n' '\\label{index:the-section-with-a-reference-to}' - '\\footnotetext[4]{\sphinxAtStartFootnote\nFootnote in section\n}' in result) + '%\n\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n' + 'Footnote in section\n%\n\\end{footnotetext}') in result assert ('\\caption{This is the figure caption with a footnote to ' - '\\protect\\footnotemark[6].}\label{index:id23}\end{figure}\n' - '\\footnotetext[6]{\sphinxAtStartFootnote\nFootnote in caption\n}')in result - assert ('\\caption{footnote \\protect\\footnotemark[7] ' - 'in caption of normal table}') in result - assert ('\\end{threeparttable}\n\n\\footnotetext[7]{\sphinxAtStartFootnote\n' - 'Foot note in table\n}' in result) - assert ('\\caption{footnote \\protect\\footnotemark[8] in caption of longtable}' - in result) - assert ('\end{longtable}\n\n\\footnotetext[8]{\sphinxAtStartFootnote\n' - 'Foot note in longtable\n}' in result) + '\\sphinxfootnotemark[6].}\label{index:id27}\end{figure}\n' + '%\n\\begin{footnotetext}[6]\\sphinxAtStartFootnote\n' + 'Footnote in caption\n%\n\\end{footnotetext}')in result + assert ('\\caption{footnote \\sphinxfootnotemark[7] ' + 'in caption of normal table}\\label{index:id28}') in result + assert ('\\caption{footnote \\sphinxfootnotemark[8] ' + 'in caption \sphinxfootnotemark[9] of longtable}') in result + assert ('\end{longtable}\n\n%\n\\begin{footnotetext}[8]' + '\sphinxAtStartFootnote\n' + 'Foot note in longtable\n%\n\\end{footnotetext}' in result) + assert ('This is a reference to the code-block in the footnote:\n' + '{\hyperref[index:codeblockinfootnote]{\\sphinxcrossref{\\DUrole' + '{std,std-ref}{I am in a footnote}}}}') in result + assert ('&\nThis is one more footnote with some code in it ' + '\\sphinxfootnotemark[10].\n\\\\') in result + assert '\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]' in result @with_app(buildername='latex', testroot='footnotes', @@ -430,29 +441,32 @@ def test_latex_show_urls_is_inline(app, status, warning): print(result) print(status.getvalue()) print(warning.getvalue()) - assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote\n' - 'footnote in bar\n} in bar.rst' in result) - assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote\n' - 'footnote in baz\n} in baz.rst' in result) - assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section' + assert ('Same footnote number %\n\\begin{footnote}[1]\\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) + assert ('\\phantomsection\\label{index:id30}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]' '{\\sphinxcrossref{The section with a reference to ' '\\phantomsection\\label{index:id1}' '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result) - assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section' + assert ('\\phantomsection\\label{index:id31}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to]' '{\\sphinxcrossref{The section with a reference to }}}' in result) - assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote\nFirst\n}' in result - assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote\nSecond\n}' 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' + 'Second\n%\n\\end{footnote}') in result assert '\\href{http://sphinx-doc.org/}{Sphinx} (http://sphinx-doc.org/)' in result - assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote\nThird\n}' in result + assert ('Third footnote: %\n\\begin{footnote}[3]\\sphinxAtStartFootnote\n' + 'Third\n%\n\\end{footnote}') in result assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde} ' '(http://sphinx-doc.org/\\textasciitilde{}test/)' in result) assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term} (http://sphinx-doc.org/)}] ' '\\leavevmode\nDescription' in result) - assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] ' - '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote\n' - 'Footnote in term\n}\nDescription' in result) + assert ('\\item[{Footnote in term \\sphinxfootnotemark[5]}] ' + '\\leavevmode%\n\\begin{footnotetext}[5]\\sphinxAtStartFootnote\n' + 'Footnote in term\n%\n\\end{footnotetext}\nDescription' in result) assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist} ' '(http://sphinx-doc.org/)}] \\leavevmode\nDescription' in result) assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result) @@ -468,40 +482,45 @@ def test_latex_show_urls_is_footnote(app, status, warning): print(result) print(status.getvalue()) print(warning.getvalue()) - assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote\n' - 'footnote in bar\n} in bar.rst' in result) - assert ('Auto footnote number \\footnote[2]{\sphinxAtStartFootnote\n' - 'footnote in baz\n} in baz.rst' in result) - assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section' + assert ('Same footnote number %\n\\begin{footnote}[1]\\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) + assert ('\\phantomsection\\label{index:id30}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]' '{\\sphinxcrossref{The section with a reference ' 'to \\phantomsection\\label{index:id1}' '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result) - assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section' + assert ('\\phantomsection\\label{index:id31}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to]' '{\\sphinxcrossref{The section with a reference to }}}' in result) - assert 'First footnote: \\footnote[3]{\sphinxAtStartFootnote\nFirst\n}' in result - assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote\nSecond\n}' 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' + 'Second\n%\n\\end{footnote}') in result assert ('\\href{http://sphinx-doc.org/}{Sphinx}' - '\\footnote[4]{\sphinxAtStartFootnote\n' - '\\nolinkurl{http://sphinx-doc.org/}\n}' in result) - assert 'Third footnote: \\footnote[6]{\sphinxAtStartFootnote\nThird\n}' in result + '%\n\\begin{footnote}[4]\\sphinxAtStartFootnote\n' + '\\nolinkurl{http://sphinx-doc.org/}\n%\n\\end{footnote}') in result + assert ('Third footnote: %\n\\begin{footnote}[6]\\sphinxAtStartFootnote\n' + 'Third\n%\n\\end{footnote}') in result assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}' - '\\footnote[5]{\sphinxAtStartFootnote\n' - '\\nolinkurl{http://sphinx-doc.org/~test/}\n}' in result) - assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[8]}] ' - '\\leavevmode\\footnotetext[8]{\sphinxAtStartFootnote\n' - '\\nolinkurl{http://sphinx-doc.org/}\n}\nDescription' in result) - assert ('\\item[{Footnote in term \\protect\\footnotemark[10]}] ' - '\\leavevmode\\footnotetext[10]{\sphinxAtStartFootnote\n' - 'Footnote in term\n}\nDescription' in result) - assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\protect' - '\\footnotemark[9]}] ' - '\\leavevmode\\footnotetext[9]{\sphinxAtStartFootnote\n' - '\\nolinkurl{http://sphinx-doc.org/}\n}\nDescription' in result) + '%\n\\begin{footnote}[5]\\sphinxAtStartFootnote\n' + '\\nolinkurl{http://sphinx-doc.org/~test/}\n%\n\\end{footnote}') in result + assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\sphinxfootnotemark[8]}] ' + '\\leavevmode%\n\\begin{footnotetext}[8]\\sphinxAtStartFootnote\n' + '\\nolinkurl{http://sphinx-doc.org/}\n%\n' + '\\end{footnotetext}\nDescription') in result + assert ('\\item[{Footnote in term \\sphinxfootnotemark[10]}] ' + '\\leavevmode%\n\\begin{footnotetext}[10]\\sphinxAtStartFootnote\n' + 'Footnote in term\n%\n\\end{footnotetext}\nDescription') in result + assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}' + '\\sphinxfootnotemark[9]}] ' + '\\leavevmode%\n\\begin{footnotetext}[9]\\sphinxAtStartFootnote\n' + '\\nolinkurl{http://sphinx-doc.org/}\n%\n' + '\\end{footnotetext}\nDescription') in result assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result) assert ('\\href{mailto:sphinx-dev@googlegroups.com}' - '{sphinx-dev@googlegroups.com}\n' in result) + '{sphinx-dev@googlegroups.com}\n') in result @with_app(buildername='latex', testroot='footnotes', @@ -512,33 +531,36 @@ def test_latex_show_urls_is_no(app, status, warning): print(result) print(status.getvalue()) print(warning.getvalue()) - assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote\n' - 'footnote in bar\n} in bar.rst' in result) - assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote\n' - 'footnote in baz\n} in baz.rst' in result) - assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section' + assert ('Same footnote number %\n\\begin{footnote}[1]\\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 + assert ('\\phantomsection\\label{index:id30}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]' '{\\sphinxcrossref{The section with a reference ' 'to \\phantomsection\\label{index:id1}' - '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result) - assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section' + '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}') in result + assert ('\\phantomsection\\label{index:id31}{\\hyperref[index:the\\string-section' '\\string-with\\string-a\\string-reference\\string-to]' '{\\sphinxcrossref{The section with a reference to }}}' in result) - assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote\nFirst\n}' in result - assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote\nSecond\n}' 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' + 'Second\n%\n\\end{footnote}') in result assert '\\href{http://sphinx-doc.org/}{Sphinx}' in result - assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote\nThird\n}' in result + assert ('Third footnote: %\n\\begin{footnote}[3]\\sphinxAtStartFootnote\n' + 'Third\n%\n\\end{footnote}') in result assert '\\href{http://sphinx-doc.org/~test/}{URL including tilde}' in result assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}}] ' - '\\leavevmode\nDescription' in result) - assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] ' - '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote\n' - 'Footnote in term\n}\nDescription' in result) + '\\leavevmode\nDescription') in result + assert ('\\item[{Footnote in term \\sphinxfootnotemark[5]}] ' + '\\leavevmode%\n\\begin{footnotetext}[5]\\sphinxAtStartFootnote\n' + 'Footnote in term\n%\n\\end{footnotetext}\nDescription') in result assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}}] ' - '\\leavevmode\nDescription' in result) + '\\leavevmode\nDescription') in result assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result) assert ('\\href{mailto:sphinx-dev@googlegroups.com}' - '{sphinx-dev@googlegroups.com}\n' in result) + '{sphinx-dev@googlegroups.com}\n') in result @with_app(buildername='latex', testroot='image-in-section')