mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #2206: Sphinx latex doc build failed if footnotes in caption of figure
At same time, refactored around pending footnotes (tables, terms and figures). They are all controled as ``pending_footnotes``.
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -22,6 +22,7 @@ Bugs fixed
|
|||||||
* #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters
|
* #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters
|
||||||
* #2193: Fix shutil.SameFileError if source directory and destination directory are same
|
* #2193: Fix shutil.SameFileError if source directory and destination directory are same
|
||||||
* #2178: Fix unparseable C++ cross-reference when referencing a function with :cpp:any:
|
* #2178: Fix unparseable C++ cross-reference when referencing a function with :cpp:any:
|
||||||
|
* #2206: Fix Sphinx latex doc build failed due to a footnotes
|
||||||
|
|
||||||
|
|
||||||
Release 1.3.3 (released Dec 2, 2015)
|
Release 1.3.3 (released Dec 2, 2015)
|
||||||
|
|||||||
@@ -234,7 +234,6 @@ class Table(object):
|
|||||||
self.has_verbatim = False
|
self.has_verbatim = False
|
||||||
self.caption = None
|
self.caption = None
|
||||||
self.longtable = False
|
self.longtable = False
|
||||||
self.footnotes = []
|
|
||||||
|
|
||||||
|
|
||||||
class LaTeXTranslator(nodes.NodeVisitor):
|
class LaTeXTranslator(nodes.NodeVisitor):
|
||||||
@@ -375,7 +374,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
sys.maxsize]]
|
sys.maxsize]]
|
||||||
self.bodystack = []
|
self.bodystack = []
|
||||||
self.footnotestack = []
|
self.footnotestack = []
|
||||||
self.termfootnotestack = []
|
self.footnote_restricted = False
|
||||||
|
self.pending_footnotes = []
|
||||||
self.curfilestack = []
|
self.curfilestack = []
|
||||||
self.handled_abbrs = set()
|
self.handled_abbrs = set()
|
||||||
if document.settings.docclass == 'howto':
|
if document.settings.docclass == 'howto':
|
||||||
@@ -414,6 +414,20 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.body = self.bodystack.pop()
|
self.body = self.bodystack.pop()
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
def restrict_footnote(self, node):
|
||||||
|
if self.footnote_restricted is False:
|
||||||
|
self.footnote_restricted = node
|
||||||
|
self.pending_footnotes = []
|
||||||
|
|
||||||
|
def unrestrict_footnote(self, node):
|
||||||
|
print self.footnote_restricted, self.pending_footnotes
|
||||||
|
if self.footnote_restricted == node:
|
||||||
|
self.footnote_restricted = False
|
||||||
|
for footnode in self.pending_footnotes:
|
||||||
|
footnode['footnotetext'] = True
|
||||||
|
footnode.walkabout(self)
|
||||||
|
self.pending_footnotes = []
|
||||||
|
|
||||||
def format_docclass(self, docclass):
|
def format_docclass(self, docclass):
|
||||||
""" prepends prefix to sphinx document classes
|
""" prepends prefix to sphinx document classes
|
||||||
"""
|
"""
|
||||||
@@ -891,6 +905,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.tableheaders = []
|
self.tableheaders = []
|
||||||
# Redirect body output until table is finished.
|
# Redirect body output until table is finished.
|
||||||
self.pushbody(self.tablebody)
|
self.pushbody(self.tablebody)
|
||||||
|
self.restrict_footnote(node)
|
||||||
|
|
||||||
def depart_table(self, node):
|
def depart_table(self, node):
|
||||||
if self.table.rowcount > 30:
|
if self.table.rowcount > 30:
|
||||||
@@ -961,10 +976,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.body.append(endmacro)
|
self.body.append(endmacro)
|
||||||
if not self.table.longtable and self.table.caption is not None:
|
if not self.table.longtable and self.table.caption is not None:
|
||||||
self.body.append('\\end{threeparttable}\n\n')
|
self.body.append('\\end{threeparttable}\n\n')
|
||||||
if self.table.footnotes:
|
self.unrestrict_footnote(node)
|
||||||
for footnode in self.table.footnotes:
|
|
||||||
footnode['footnotetext'] = True
|
|
||||||
footnode.walkabout(self)
|
|
||||||
self.table = None
|
self.table = None
|
||||||
self.tablebody = None
|
self.tablebody = None
|
||||||
|
|
||||||
@@ -1138,16 +1150,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
if node.get('ids'):
|
if node.get('ids'):
|
||||||
ctx += self.hypertarget(node['ids'][0])
|
ctx += self.hypertarget(node['ids'][0])
|
||||||
self.body.append('\\item[{')
|
self.body.append('\\item[{')
|
||||||
self.termfootnotestack.append([])
|
self.restrict_footnote(node)
|
||||||
self.context.append(ctx)
|
self.context.append(ctx)
|
||||||
|
|
||||||
def depart_term(self, node):
|
def depart_term(self, node):
|
||||||
self.body.append(self.context.pop())
|
self.body.append(self.context.pop())
|
||||||
footnotes = self.termfootnotestack.pop()
|
self.unrestrict_footnote(node)
|
||||||
for footnode in footnotes:
|
|
||||||
footnode['footnotetext'] = True
|
|
||||||
footnode.walkabout(self)
|
|
||||||
|
|
||||||
self.in_term -= 1
|
self.in_term -= 1
|
||||||
|
|
||||||
def visit_termsep(self, node):
|
def visit_termsep(self, node):
|
||||||
@@ -1304,6 +1312,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
for id in self.next_figure_ids:
|
for id in self.next_figure_ids:
|
||||||
ids += self.hypertarget(id, anchor=False)
|
ids += self.hypertarget(id, anchor=False)
|
||||||
self.next_figure_ids.clear()
|
self.next_figure_ids.clear()
|
||||||
|
self.restrict_footnote(node)
|
||||||
if (len(node.children) and
|
if (len(node.children) and
|
||||||
isinstance(node.children[0], nodes.image) and
|
isinstance(node.children[0], nodes.image) and
|
||||||
node.children[0]['ids']):
|
node.children[0]['ids']):
|
||||||
@@ -1331,6 +1340,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
|
|
||||||
def depart_figure(self, node):
|
def depart_figure(self, node):
|
||||||
self.body.append(self.context.pop())
|
self.body.append(self.context.pop())
|
||||||
|
self.unrestrict_footnote(node)
|
||||||
|
|
||||||
def visit_caption(self, node):
|
def visit_caption(self, node):
|
||||||
self.in_caption += 1
|
self.in_caption += 1
|
||||||
@@ -1666,18 +1676,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.body.append('\\protect\\footnotemark[%s]' % num)
|
self.body.append('\\protect\\footnotemark[%s]' % num)
|
||||||
else:
|
else:
|
||||||
self.body.append('\\footnotemark[%s]' % num)
|
self.body.append('\\footnotemark[%s]' % num)
|
||||||
elif self.table:
|
elif self.footnote_restricted:
|
||||||
self.footnotestack[-1][num][1] = True
|
self.footnotestack[-1][num][1] = True
|
||||||
self.body.append('\\protect\\footnotemark[%s]' % num)
|
self.body.append('\\protect\\footnotemark[%s]' % num)
|
||||||
self.table.footnotes.append(footnode)
|
self.pending_footnotes.append(footnode)
|
||||||
elif self.in_term:
|
|
||||||
self.body.append('\\footnotemark[%s]' % num)
|
|
||||||
self.termfootnotestack[-1].append(footnode)
|
|
||||||
else:
|
else:
|
||||||
if self.in_caption:
|
|
||||||
raise UnsupportedError('%s:%s: footnotes in float captions '
|
|
||||||
'are not supported by LaTeX' %
|
|
||||||
(self.curfilestack[-1], node.line))
|
|
||||||
self.footnotestack[-1][num][1] = True
|
self.footnotestack[-1][num][1] = True
|
||||||
footnode.walkabout(self)
|
footnode.walkabout(self)
|
||||||
raise nodes.SkipChildren
|
raise nodes.SkipChildren
|
||||||
|
|||||||
@@ -46,3 +46,9 @@ Footnote in term [#]_
|
|||||||
Description2
|
Description2
|
||||||
|
|
||||||
.. [#] Footnote in term
|
.. [#] Footnote in term
|
||||||
|
|
||||||
|
.. figure:: rimg.png
|
||||||
|
|
||||||
|
This is the figure caption with a footnote to [#]_.
|
||||||
|
|
||||||
|
.. [#] Footnote in caption
|
||||||
|
|||||||
@@ -332,6 +332,9 @@ def test_reference_in_caption(app, status, warning):
|
|||||||
assert '\\caption{The table title 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 '\\paragraph{The rubric title with a reference to {[}AuthorYear{]}}' in result
|
||||||
assert '\\chapter{The section with a reference to \\protect\\footnotemark[1]}' in result
|
assert '\\chapter{The section with a reference to \\protect\\footnotemark[1]}' in result
|
||||||
|
assert ('\\caption{This is the figure caption with a footnote to '
|
||||||
|
'\\protect\\footnotemark[5].}\end{figure}\n'
|
||||||
|
'\\footnotetext[5]{\nFootnote in caption\n}')in result
|
||||||
|
|
||||||
|
|
||||||
@with_app(buildername='latex', testroot='footnotes',
|
@with_app(buildername='latex', testroot='footnotes',
|
||||||
@@ -350,7 +353,7 @@ def test_latex_show_urls_is_inline(app, status, warning):
|
|||||||
'(http://sphinx-doc.org/\\textasciitilde{}test/)' in result)
|
'(http://sphinx-doc.org/\\textasciitilde{}test/)' in result)
|
||||||
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term} (http://sphinx-doc.org/)}] '
|
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term} (http://sphinx-doc.org/)}] '
|
||||||
'\\leavevmode\nDescription' in result)
|
'\\leavevmode\nDescription' in result)
|
||||||
assert ('\\item[{Footnote in term \\footnotemark[4]}] '
|
assert ('\\item[{Footnote in term \\protect\\footnotemark[4]}] '
|
||||||
'\\leavevmode\\footnotetext[4]{\nFootnote in term\n}\nDescription' in result)
|
'\\leavevmode\\footnotetext[4]{\nFootnote in term\n}\nDescription' in result)
|
||||||
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist} '
|
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist} '
|
||||||
'(http://sphinx-doc.org/)}] \\leavevmode\nDescription' in result)
|
'(http://sphinx-doc.org/)}] \\leavevmode\nDescription' in result)
|
||||||
@@ -375,11 +378,11 @@ def test_latex_show_urls_is_footnote(app, status, warning):
|
|||||||
assert 'Third footnote: \\footnote[5]{\nThird\n}' in result
|
assert 'Third footnote: \\footnote[5]{\nThird\n}' in result
|
||||||
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
|
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
|
||||||
'\\footnote[4]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result)
|
'\\footnote[4]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result)
|
||||||
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\footnotemark[6]}] '
|
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[6]}] '
|
||||||
'\\leavevmode\\footnotetext[6]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
|
'\\leavevmode\\footnotetext[6]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
|
||||||
assert ('\\item[{Footnote in term \\footnotemark[8]}] '
|
assert ('\\item[{Footnote in term \\protect\\footnotemark[8]}] '
|
||||||
'\\leavevmode\\footnotetext[8]{\nFootnote in term\n}\nDescription' in result)
|
'\\leavevmode\\footnotetext[8]{\nFootnote in term\n}\nDescription' in result)
|
||||||
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\footnotemark[7]}] '
|
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\protect\\footnotemark[7]}] '
|
||||||
'\\leavevmode\\footnotetext[7]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
|
'\\leavevmode\\footnotetext[7]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
|
||||||
assert ('\\href{https://github.com/sphinx-doc/sphinx}'
|
assert ('\\href{https://github.com/sphinx-doc/sphinx}'
|
||||||
'{https://github.com/sphinx-doc/sphinx}\n' in result)
|
'{https://github.com/sphinx-doc/sphinx}\n' in result)
|
||||||
@@ -402,7 +405,7 @@ def test_latex_show_urls_is_no(app, status, warning):
|
|||||||
assert '\\href{http://sphinx-doc.org/~test/}{URL including tilde}' in result
|
assert '\\href{http://sphinx-doc.org/~test/}{URL including tilde}' in result
|
||||||
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}}] '
|
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}}] '
|
||||||
'\\leavevmode\nDescription' in result)
|
'\\leavevmode\nDescription' in result)
|
||||||
assert ('\\item[{Footnote in term \\footnotemark[4]}] '
|
assert ('\\item[{Footnote in term \\protect\\footnotemark[4]}] '
|
||||||
'\\leavevmode\\footnotetext[4]{\nFootnote in term\n}\nDescription' in result)
|
'\\leavevmode\\footnotetext[4]{\nFootnote in term\n}\nDescription' in result)
|
||||||
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}}] '
|
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}}] '
|
||||||
'\\leavevmode\nDescription' in result)
|
'\\leavevmode\nDescription' in result)
|
||||||
|
|||||||
Reference in New Issue
Block a user