diff --git a/sphinx/texinputs/footnotehyper-sphinx.sty b/sphinx/texinputs/footnotehyper-sphinx.sty new file mode 100644 index 00000000000..b03ec06fc1e --- /dev/null +++ b/sphinx/texinputs/footnotehyper-sphinx.sty @@ -0,0 +1,67 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{footnotehyper-sphinx}% + [2016/04/22 v0.9d-sphinx hyperref aware footnote.sty (JFB)] +\DeclareOption*{}% +\ProcessOptions\relax +%% +%% Package: footnotehyper-sphinx +%% Version: 0.9d-sphinx (2016/04/22) +%% License: LPPL 1.3c (http://www.latex-project.org/lppl/lppl-1-3c.txt) +%% Copyright (C) 2016 Jean-Francois Burnol . +%% +%% Trimmed variant of footnotehyper v0.9d (2016/04/21) +%% Sphinx does not use the `footnote` environment defined by footnote.sty. The +%% loading of footnote.sty may crash if the user has other footnote related +%% packages loaded first. Thus to make sure no such crash can happen, we +%% deactivate this construction of footnote environment and take care only +%% of \footnote command. +\let\FNHS@@makefntext\@makefntext\let\@makefntext\@firstofone +\let\FNHS@endfootnote\endfootnote % probably \undefined +\let\FNHS@endfootnotetext\endfootnotetext + \RequirePackage{footnote}\relax +\let\@makefntext\FNHS@@makefntext +\let\footnote \fn@latex@@footnote +\let\footnotetext\fn@latex@@footnotetext +\let\endfootnote \FNHS@endfootnote +\let\endfootnotetext\FNHS@endfootnotetext +\def\fn@fntext {\ifx\ifmeasuring@\undefined\expandafter\@secondoftwo + \else\expandafter\@firstofone\fi + {\ifmeasuring@\expandafter\@gobbletwo\fi}% + \FNHS@fn@fntext }% +\long\def\FNHS@fn@fntext #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\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 +}% +\let\endsavenotes\spewnotes +\def\fn@endnote {\color@endgroup}% +\AtBeginDocument {% + \let\fn@latex@@footnote \footnote + \let\fn@latex@@footnotetext\footnotetext + \let\footnote \FNHS@fn@footnote + \let\footnotetext\FNHS@fn@footnotetext +}% +\endinput +%% +%% End of file `footnotehyper-sphinx.sty'. diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 9c289a57862..d85fc0dea96 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -36,9 +36,12 @@ \RequirePackage{fancyvrb} % For table captions. \RequirePackage{threeparttable} -% Handle footnotes in tables. -\RequirePackage{footnote} +% Handle footnotes in tables; also for topic and warning blocks. +\RequirePackage{footnotehyper-sphinx} +% longtable is already able to handle footnotes in a hyperref compatible way \makesavenoteenv{tabulary} +\makesavenoteenv{tabular} +\makesavenoteenv{threeparttable} % For floating figures in the text. \RequirePackage{wrapfig} % Separate paragraphs by space by default. @@ -313,9 +316,12 @@ % 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 - \ifSphinx@inframed\begin{minipage}{\linewidth}\fi + % use minipage* for global footnotes + \ifSphinx@inframed\begin{minipage*}{\linewidth}\fi \MakeFramed {\Sphinx@inframedtrue % framed.sty puts into "\width" the added width (=2shadowsep+2shadowrule) % adjust \hsize to what the contents must use @@ -326,9 +332,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 @@ -336,14 +339,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 - \ifSphinx@inframed\end{minipage}\fi + \ifSphinx@inframed\end{minipage*}\fi \endtrivlist + % output the stored footnotes + \spewnotes } % \moduleauthor{name}{email} @@ -423,9 +424,10 @@ \def\FrameCommand##1{\hskip\@totalleftmargin \fboxsep\FrameSep \fboxrule\FrameRule\fbox{##1}% \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% + \savenotes % use a minipage if we are already inside a framed environment \ifSphinx@inframed - \noindent\begin{minipage}{\linewidth} + \noindent\begin{minipage*}{\linewidth} \else \vspace{\parskip} \fi @@ -433,21 +435,16 @@ \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 }% } \newcommand{\py@endheavybox}{% \par\unskip - % handles footnotes - \ifvoid\@mpfootins\else - \vskip\skip\@mpfootins\normalcolor\footnoterule\unvbox\@mpfootins - \fi \@minipagefalse\endMakeFramed - \ifSphinx@inframed\end{minipage}\fi + \ifSphinx@inframed\end{minipage*}\fi + % set footnotes at bottom of page + \spewnotes % arrange for similar spacing below frame as for "light" boxes. \vskip .4\baselineskip } diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 7ce35b80fbb..5fbdace77dd 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -179,15 +179,11 @@ def expand_show_urls(self): if node.astext() != uri: index = node.parent.index(node) if show_urls == 'footnote': - if list(traverse_parent(node, nodes.topic)): - # should not expand references in topics - pass - else: - footnote_nodes = self.create_footnote(uri) - for i, fn in enumerate(footnote_nodes): - node.parent.insert(index + i + 1, fn) - - self.expanded = True + footnote_nodes = self.create_footnote(uri) + for i, fn in enumerate(footnote_nodes): + node.parent.insert(index + i + 1, fn) + + self.expanded = True else: # all other true values (b/w compat) textnode = nodes.Text(" (%s)" % uri) node.parent.insert(index + 1, textnode) @@ -964,7 +960,6 @@ def visit_table(self, node): self.tableheaders = [] # Redirect body output until table is finished. self.pushbody(self.tablebody) - self.restrict_footnote(node) def depart_table(self, node): if self.table.rowcount > 30: @@ -1036,7 +1031,6 @@ def depart_table(self, node): self.body.append(endmacro) if not self.table.longtable and self.table.caption is not None: self.body.append('\\end{threeparttable}\n\n') - self.unrestrict_footnote(node) self.table = None self.tablebody = None