From 12396a71d9c1e7a3bd3a4e5d1447f2033db26794 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 29 Nov 2015 16:57:25 +0900 Subject: [PATCH] Fix #2140: footnotes in table has broken in LaTeX --- sphinx/writers/latex.py | 17 +++++++++++++++-- tests/root/footnote.txt | 15 +++++++++++++++ tests/test_build_html.py | 8 ++++++-- tests/test_build_latex.py | 18 ++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index d82e7dd765..bebf4b43d5 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -137,6 +137,7 @@ class Table(object): self.has_verbatim = False self.caption = None self.longtable = False + self.footnotes = [] class LaTeXTranslator(nodes.NodeVisitor): @@ -495,7 +496,8 @@ class LaTeXTranslator(nodes.NodeVisitor): fnotes = {} for fn in footnotes_under(node): num = fn.children[0].astext().strip() - fnotes[num] = [collected_footnote(*fn.children), False] + newnode = collected_footnote(*fn.children, number=num) + fnotes[num] = [newnode, False] return fnotes def depart_start_of_file(self, node): @@ -743,7 +745,10 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_collected_footnote(self, node): self.in_footnote += 1 - self.body.append('\\footnote{') + if 'in_table' in node: + self.body.append('\\footnotetext[%s]{' % node['number']) + else: + self.body.append('\\footnote[%s]{' % node['number']) def depart_collected_footnote(self, node): self.body.append('}') @@ -839,6 +844,10 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append(endmacro) if not self.table.longtable and self.table.caption is not None: self.body.append('\\end{threeparttable}\n\n') + if self.table.footnotes: + for footnode in self.table.footnotes: + footnode['in_table'] = True + footnode.walkabout(self) self.table = None self.tablebody = None @@ -1532,6 +1541,10 @@ class LaTeXTranslator(nodes.NodeVisitor): # by the next reference if used: self.body.append('\\footnotemark[%s]' % num) + elif self.table: + self.footnotestack[-1][num][1] = True + self.body.append('\\footnotemark[%s]' % num) + self.table.footnotes.append(footnode) else: if self.in_caption: raise UnsupportedError('%s:%s: footnotes in float captions ' diff --git a/tests/root/footnote.txt b/tests/root/footnote.txt index b600697fdf..423977a4d0 100644 --- a/tests/root/footnote.txt +++ b/tests/root/footnote.txt @@ -24,6 +24,17 @@ citation [bar]_ +footnotes in table +-------------------- + +.. list-table:: Table caption [#]_ + :header-rows: 1 + + * - name [#]_ + - desription + * - VIDIOC_CROPCAP + - Information about VIDIOC_CROPCAP + footenotes -------------------- @@ -39,6 +50,10 @@ footenotes .. [bar] cite +.. [#] footnotes in table + +.. [#] footnotes in table + missing target -------------------- diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 3ee89b72b2..e0ed4d44f0 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -280,14 +280,18 @@ HTML_XPATH = { (".//dt/a", "double"), ], 'footnote.html': [ - (".//a[@class='footnote-reference'][@href='#id5'][@id='id1']", r"\[1\]"), - (".//a[@class='footnote-reference'][@href='#id6'][@id='id2']", r"\[2\]"), + (".//a[@class='footnote-reference'][@href='#id7'][@id='id1']", r"\[1\]"), + (".//a[@class='footnote-reference'][@href='#id8'][@id='id2']", r"\[2\]"), (".//a[@class='footnote-reference'][@href='#foo'][@id='id3']", r"\[3\]"), (".//a[@class='reference internal'][@href='#bar'][@id='id4']", r"\[bar\]"), + (".//a[@class='footnote-reference'][@href='#id9'][@id='id5']", r"\[4\]"), + (".//a[@class='footnote-reference'][@href='#id10'][@id='id6']", r"\[5\]"), (".//a[@class='fn-backref'][@href='#id1']", r"\[1\]"), (".//a[@class='fn-backref'][@href='#id2']", r"\[2\]"), (".//a[@class='fn-backref'][@href='#id3']", r"\[3\]"), (".//a[@class='fn-backref'][@href='#id4']", r"\[bar\]"), + (".//a[@class='fn-backref'][@href='#id5']", r"\[4\]"), + (".//a[@class='fn-backref'][@href='#id6']", r"\[5\]"), ], 'otherext.html': [ (".//h1", "Generated section"), diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 639204ca12..3d2de232de 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -297,3 +297,21 @@ def test_contentsname_with_language_ja(app, status, warning): print(status.getvalue()) print(warning.getvalue()) assert '\\renewcommand{\\contentsname}{Table of content}' in result + + +@with_app(buildername='latex') +def test_footnote(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\footnote[1]{\nnumbered\n}' in result + assert '\\footnote[2]{\nauto numbered\n}' in result + assert '\\footnote[3]{\nnamed\n}' in result + assert '{\\hyperref[footnote:bar]{\\emph{{[}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 'name \\footnotemark[5]' in result + assert '\\end{threeparttable}\n\n\\footnotetext[5]{\nfootnotes in table\n}' in result