Fix again. Sections which depth are lower than :tocdepth: should not be shown on localtoc sidebar. Closes #1251

This commit is contained in:
Takayuki Shimizukawa 2014-12-05 16:42:30 +09:00
parent 32e4fab86b
commit edf63e1406
3 changed files with 44 additions and 29 deletions

View File

@ -24,6 +24,8 @@ Bugs fixed
in class docstrings.
* Rebuilding cause crash unexpectedly when source files were added.
* #1607: Fix a crash when building latexpdf with "howto" class
* #1251: Fix again. Sections which depth are lower than :tocdepth: should not
be shown on localtoc sidebar.
Release 1.3b1 (released Oct 10, 2014)

View File

@ -1182,8 +1182,10 @@ class BuildEnvironment:
def get_toc_for(self, docname, builder):
"""Return a TOC nodetree -- for use on the same page only!"""
tocdepth = self.metadata[docname].get('tocdepth', 0)
try:
toc = self.tocs[docname].deepcopy()
self._toctree_prune(toc, 2, tocdepth)
except KeyError:
# the document does not exist anymore: return a dummy node that
# renders to nothing
@ -1262,6 +1264,27 @@ class BuildEnvironment:
return doctree
def _toctree_prune(self, node, depth, maxdepth, collapse=False):
"""Utility: Cut a TOC at a specified depth."""
for subnode in node.children[:]:
if isinstance(subnode, (addnodes.compact_paragraph,
nodes.list_item)):
# for <p> and <li>, just recurse
self._toctree_prune(subnode, depth, maxdepth, collapse)
elif isinstance(subnode, nodes.bullet_list):
# for <ul>, determine if the depth is too large or if the
# entry is to be collapsed
if maxdepth > 0 and depth > maxdepth:
subnode.parent.replace(subnode, [])
else:
# cull sub-entries whose parents aren't 'current'
if (collapse and depth > 1 and
'iscurrent' not in subnode.parent):
subnode.parent.remove(subnode)
else:
# recurse on visible children
self._toctree_prune(subnode, depth+1, maxdepth, collapse)
def resolve_toctree(self, docname, builder, toctree, prune=True, maxdepth=0,
titles_only=False, collapse=False, includehidden=False):
"""Resolve a *toctree* node into individual bullet lists with titles
@ -1296,27 +1319,6 @@ class BuildEnvironment:
# The transformation is made in two passes in order to avoid
# interactions between marking and pruning the tree (see bug #1046).
def _toctree_prune(node, depth, maxdepth):
"""Utility: Cut a TOC at a specified depth."""
for subnode in node.children[:]:
if isinstance(subnode, (addnodes.compact_paragraph,
nodes.list_item)):
# for <p> and <li>, just recurse
_toctree_prune(subnode, depth, maxdepth)
elif isinstance(subnode, nodes.bullet_list):
# for <ul>, determine if the depth is too large or if the
# entry is to be collapsed
if maxdepth > 0 and depth > maxdepth:
subnode.parent.replace(subnode, [])
else:
# cull sub-entries whose parents aren't 'current'
if (collapse and depth > 1 and
'iscurrent' not in subnode.parent):
subnode.parent.remove(subnode)
else:
# recurse on visible children
_toctree_prune(subnode, depth+1, maxdepth)
def _toctree_add_classes(node, depth):
"""Add 'toctree-l%d' and 'current' classes to the toctree."""
for subnode in node.children:
@ -1387,7 +1389,7 @@ class BuildEnvironment:
refdoc = ref
toc = self.tocs[ref].deepcopy()
maxdepth = self.metadata[ref].get('tocdepth', 0)
_toctree_prune(toc, 2, maxdepth)
self._toctree_prune(toc, 2, maxdepth, collapse)
self.process_only_nodes(toc, builder, ref)
if title and toc.children and len(toc.children) == 1:
child = toc.children[0]
@ -1456,7 +1458,7 @@ class BuildEnvironment:
# prune the tree to maxdepth, also set toc depth and current classes
_toctree_add_classes(newnode, 1)
_toctree_prune(newnode, 1, prune and maxdepth or 0)
self._toctree_prune(newnode, 1, prune and maxdepth or 0, collapse)
# set the target paths in the toctrees (they are not known at TOC
# generation time)

View File

@ -323,13 +323,16 @@ def check_xpath(etree, fname, path, check, be_found=True):
pass
else:
rex = re.compile(check)
for node in nodes:
if node.text and (bool(rex.search(node.text)) ^ (not be_found)):
break
if be_found:
if any(node.text and rex.search(node.text) for node in nodes):
return
else:
assert False, ('%r not found in any node matching '
'path %s in %s: %r' % (check, path, fname,
[node.text for node in nodes]))
if all(node.text and not rex.search(node.text) for node in nodes):
return
assert False, ('%r not found in any node matching '
'path %s in %s: %r' % (check, path, fname,
[node.text for node in nodes]))
def check_static_entries(outdir):
@ -396,12 +399,20 @@ def test_tocdepth(app, status, warning):
(".//h3", '1.1.1. Foo A1', True),
(".//h2", '1.2. Foo B', True),
(".//h3", '1.2.1. Foo B1', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '1.1. Foo A', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '1.1.1. Foo A1', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '1.2. Foo B', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '1.2.1. Foo B1', True),
],
'bar.html': [
(".//h1", '2. Bar', True),
(".//h2", '2.1. Bar A', True),
(".//h2", '2.2. Bar B', True),
(".//h3", '2.2.1. Bar B1', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '2. Bar', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '2.1. Bar A', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '2.2. Bar B', True),
(".//div[@class='sphinxsidebarwrapper']//li/a", '2.2.1. Bar B1', False),
],
'baz.html': [
(".//h1", '2.1.1. Baz A', True),