mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge with 'stable'
This commit is contained in:
commit
9ceea10a62
6
CHANGES
6
CHANGES
@ -85,6 +85,12 @@ Bugs fixed
|
||||
the page content.
|
||||
* #1884, #1885: plug-in html themes cannot inherit another plug-in theme. Thanks to
|
||||
Suzumizaki.
|
||||
* #1818: `sphinx.ext.todo` directive generates broken html class attribute as
|
||||
'admonition-' when :confval:`language` is specified with non-ASCII linguistic area like
|
||||
'ru' or 'ja'. To fix this, now ``todo`` directive can use ```:class:`` option.
|
||||
* #2140: Fix footnotes in table has broken in LaTeX
|
||||
* #2127: MecabBinder for html searching feature doesn't work with Python 3.
|
||||
Thanks to Tomoko Uchida.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
@ -16,6 +16,10 @@ There are two additional directives when using this extension:
|
||||
It will only show up in the output if :confval:`todo_include_todos` is
|
||||
``True``.
|
||||
|
||||
.. versionadded:: 1.3.2
|
||||
This directive supports an ``class`` option that determines the class attribute
|
||||
for HTML output. If not given, the class defaults to ``admonition-todo``.
|
||||
|
||||
|
||||
.. rst:directive:: todolist
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
|
||||
import sphinx
|
||||
from sphinx.locale import _
|
||||
@ -38,13 +39,18 @@ class Todo(Directive):
|
||||
required_arguments = 0
|
||||
optional_arguments = 0
|
||||
final_argument_whitespace = False
|
||||
option_spec = {}
|
||||
option_spec = {
|
||||
'class': directives.class_option,
|
||||
}
|
||||
|
||||
def run(self):
|
||||
env = self.state.document.settings.env
|
||||
targetid = 'index-%s' % env.new_serialno('index')
|
||||
targetnode = nodes.target('', '', ids=[targetid])
|
||||
|
||||
if not self.options.get('class'):
|
||||
self.options['class'] = ['admonition-todo']
|
||||
|
||||
ad = make_admonition(todo_node, self.name, [_('Todo')], self.options,
|
||||
self.content, self.lineno, self.content_offset,
|
||||
self.block_text, self.state, self.state_machine)
|
||||
@ -165,6 +171,7 @@ def merge_info(app, env, docnames, other):
|
||||
|
||||
def visit_todo_node(self, node):
|
||||
self.visit_admonition(node)
|
||||
# self.visit_admonition(node, 'todo')
|
||||
|
||||
|
||||
def depart_todo_node(self, node):
|
||||
|
@ -137,6 +137,7 @@ class Table(object):
|
||||
self.has_verbatim = False
|
||||
self.caption = None
|
||||
self.longtable = False
|
||||
self.footnotes = []
|
||||
|
||||
|
||||
class LaTeXTranslator(nodes.NodeVisitor):
|
||||
@ -275,6 +276,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# by .. highlight:: directive in the master file
|
||||
self.hlsettingstack = 2 * [[builder.config.highlight_language,
|
||||
sys.maxsize]]
|
||||
self.bodystack = []
|
||||
self.footnotestack = []
|
||||
self.curfilestack = []
|
||||
self.handled_abbrs = set()
|
||||
@ -303,6 +305,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
self.remember_multirow = {}
|
||||
self.remember_multirowcol = {}
|
||||
|
||||
def pushbody(self, newbody):
|
||||
self.bodystack.append(self.body)
|
||||
self.body = newbody
|
||||
|
||||
def popbody(self):
|
||||
body = self.body
|
||||
self.body = self.bodystack.pop()
|
||||
return body
|
||||
|
||||
def format_docclass(self, docclass):
|
||||
""" prepends prefix to sphinx document classes
|
||||
"""
|
||||
@ -495,7 +506,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):
|
||||
@ -602,8 +614,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
self.body.append('{')
|
||||
self.context.append('}\n')
|
||||
elif isinstance(parent, nodes.table):
|
||||
self.table.caption = self.encode(node.astext())
|
||||
raise nodes.SkipNode
|
||||
# Redirect body output until title is finished.
|
||||
self.pushbody([])
|
||||
else:
|
||||
self.builder.warn(
|
||||
'encountered title node not in section, topic, table, '
|
||||
@ -615,7 +627,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
|
||||
def depart_title(self, node):
|
||||
self.in_title = 0
|
||||
self.body.append(self.context.pop())
|
||||
if isinstance(node.parent, nodes.table):
|
||||
self.table.caption = self.popbody()
|
||||
else:
|
||||
self.body.append(self.context.pop())
|
||||
|
||||
def visit_subtitle(self, node):
|
||||
if isinstance(node.parent, nodes.sidebar):
|
||||
@ -743,7 +758,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('}')
|
||||
@ -770,16 +788,18 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
self.tablebody = []
|
||||
self.tableheaders = []
|
||||
# Redirect body output until table is finished.
|
||||
self._body = self.body
|
||||
self.body = self.tablebody
|
||||
self.pushbody(self.tablebody)
|
||||
|
||||
def depart_table(self, node):
|
||||
if self.table.rowcount > 30:
|
||||
self.table.longtable = True
|
||||
self.body = self._body
|
||||
self.popbody()
|
||||
if not self.table.longtable and self.table.caption is not None:
|
||||
self.body.append(u'\n\n\\begin{threeparttable}\n'
|
||||
u'\\capstart\\caption{%s}\n' % self.table.caption)
|
||||
self.body.append('\n\n\\begin{threeparttable}\n'
|
||||
'\\capstart\\caption{')
|
||||
for caption in self.table.caption:
|
||||
self.body.append(caption)
|
||||
self.body.append('}')
|
||||
for id in self.next_table_ids:
|
||||
self.body.append(self.hypertarget(id, anchor=False))
|
||||
if node['ids']:
|
||||
@ -839,6 +859,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
|
||||
|
||||
@ -1531,7 +1555,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# if a footnote has been inserted once, it shouldn't be repeated
|
||||
# by the next reference
|
||||
if used:
|
||||
self.body.append('\\footnotemark[%s]' % num)
|
||||
if self.table:
|
||||
self.body.append('\\protect\\footnotemark[%s]' % num)
|
||||
else:
|
||||
self.body.append('\\footnotemark[%s]' % num)
|
||||
elif self.table:
|
||||
self.footnotestack[-1][num][1] = True
|
||||
self.body.append('\\protect\\footnotemark[%s]' % num)
|
||||
self.table.footnotes.append(footnode)
|
||||
else:
|
||||
if self.in_caption:
|
||||
raise UnsupportedError('%s:%s: footnotes in float captions '
|
||||
|
@ -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 caption
|
||||
|
||||
.. [#] footnotes in table
|
||||
|
||||
|
||||
missing target
|
||||
--------------------
|
||||
|
@ -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"),
|
||||
|
@ -297,3 +297,24 @@ 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 '\\capstart\\caption{Table caption \\protect\\footnotemark[4]}' in result
|
||||
assert 'name \\protect\\footnotemark[5]' in result
|
||||
assert ('\\end{threeparttable}\n\n'
|
||||
'\\footnotetext[4]{\nfootnotes in table caption\n}'
|
||||
'\\footnotetext[5]{\nfootnotes in table\n}' in result)
|
||||
|
@ -137,8 +137,7 @@ def test_extract_messages_without_rawsource():
|
||||
Check node.rawsource is fall-backed by using node.astext() value.
|
||||
|
||||
`extract_message` which is used from Sphinx i18n feature drop ``not node.rawsource``
|
||||
nodes.
|
||||
So, all nodes which want to translate must have ``rawsource`` value.
|
||||
nodes. So, all nodes which want to translate must have ``rawsource`` value.
|
||||
However, sometimes node.rawsource is not set.
|
||||
|
||||
For example: recommonmark-0.2.0 doesn't set rawsource to `paragraph` node.
|
||||
|
Loading…
Reference in New Issue
Block a user