diff --git a/CHANGES b/CHANGES index 5ee2aea14..30ca8a5cc 100644 --- a/CHANGES +++ b/CHANGES @@ -154,6 +154,8 @@ Bugs fixed attributes. Thanks to David Ham. * PR#159: Add coverage targets to quickstart generated Makefile and make.bat. Thanks to Matthias Troffaes. +* #1251: When specifying toctree :numbered: option and :tocdepth: metadata, + sub section number that is larger depth than `:tocdepth:` is shrinked. Documentation ------------- diff --git a/sphinx/environment.py b/sphinx/environment.py index 9916887aa..737369571 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -976,7 +976,6 @@ class BuildEnvironment: def build_toc_from(self, docname, document): """Build a TOC from the doctree and store it in the inventory.""" numentries = [0] # nonlocal again... - maxdepth = self.metadata[docname].get('tocdepth', 0) def traverse_in_section(node, cls): """Like traverse(), but stay within the same section.""" @@ -1030,8 +1029,7 @@ class BuildEnvironment: para = addnodes.compact_paragraph('', '', reference) item = nodes.list_item('', para) sub_item = build_toc(sectionnode, depth + 1) - if maxdepth == 0 or depth < maxdepth: - item += sub_item + item += sub_item entries.append(item) if entries: return nodes.bullet_list('', *entries) @@ -1247,6 +1245,8 @@ class BuildEnvironment: continue refdoc = ref toc = self.tocs[ref].deepcopy() + maxdepth = self.metadata[ref].get('tocdepth', 0) + _toctree_prune(toc, 2, maxdepth) self.process_only_nodes(toc, builder, ref) if title and toc.children and len(toc.children) == 1: child = toc.children[0] diff --git a/tests/roots/test-tocdepth/bar.rst b/tests/roots/test-tocdepth/bar.rst new file mode 100644 index 000000000..402311fdb --- /dev/null +++ b/tests/roots/test-tocdepth/bar.rst @@ -0,0 +1,28 @@ +:tocdepth: 2 + +=== +Bar +=== + +should be 2 + +Bar A +===== + +should be 2.1 + +Bar A1 +------ + +should be 2.1.1 + +Bar B +===== + +should be 2.2 + +Bar B1 +------ + +should be 2.2.1 + diff --git a/tests/roots/test-tocdepth/conf.py b/tests/roots/test-tocdepth/conf.py new file mode 100644 index 000000000..f81c30bc4 --- /dev/null +++ b/tests/roots/test-tocdepth/conf.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' diff --git a/tests/roots/test-tocdepth/foo.rst b/tests/roots/test-tocdepth/foo.rst new file mode 100644 index 000000000..61fd539ff --- /dev/null +++ b/tests/roots/test-tocdepth/foo.rst @@ -0,0 +1,26 @@ +=== +Foo +=== + +should be 1 + +Foo A +===== + +should be 1.1 + +Foo A1 +------ + +should be 1.1.1 + +Foo B +===== + +should be 1.2 + +Foo B1 +------ + +should be 1.2.1 + diff --git a/tests/roots/test-tocdepth/index.rst b/tests/roots/test-tocdepth/index.rst new file mode 100644 index 000000000..0b651d483 --- /dev/null +++ b/tests/roots/test-tocdepth/index.rst @@ -0,0 +1,8 @@ +test-tocdepth +============= + +.. toctree:: + :numbered: + + foo + bar diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 5f0a93ce2..a9ee4524c 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -21,7 +21,7 @@ except ImportError: pygments = None from sphinx import __version__ -from util import test_root, remove_unicode_literals, gen_with_app, with_app +from util import test_root, test_roots, remove_unicode_literals, gen_with_app, with_app from etree13 import ElementTree as ET @@ -296,7 +296,7 @@ class NslessParser(ET.XMLParser): return name -def check_xpath(etree, fname, path, check): +def check_xpath(etree, fname, path, check, be_found=True): nodes = list(etree.findall(path)) assert nodes != [], ('did not find any node matching xpath ' '%r in file %s' % (path, fname)) @@ -308,7 +308,7 @@ def check_xpath(etree, fname, path, check): else: rex = re.compile(check) for node in nodes: - if node.text and rex.search(node.text): + if node.text and (bool(rex.search(node.text)) ^ (not be_found)): break else: assert False, ('%r not found in any node matching ' @@ -371,3 +371,44 @@ def test_html_with_globaltoc_and_hidden_toctree(app): '\n :hidden:' '\n') app.builder.build_all() + + +@gen_with_app(buildername='html', srcdir=(test_roots / 'test-tocdepth')) +def test_tocdepth(app): + # issue #1251 + app.builder.build_all() + + expects = { + 'index.html': [ + (".//li[@class='toctree-l3']/a", '1.1.1. Foo A1', True), + (".//li[@class='toctree-l3']/a", '1.2.1. Foo B1', True), + (".//li[@class='toctree-l3']/a", '2.1.1. Bar A1', False), + (".//li[@class='toctree-l3']/a", '2.2.1. Bar B1', False), + ], + 'foo.html': [ + (".//h1", '1. Foo', True), + (".//h2", '1.1. Foo A', True), + (".//h3", '1.1.1. Foo A1', True), + (".//h2", '1.2. Foo B', True), + (".//h3", '1.2.1. Foo B1', True), + ], + 'bar.html': [ + (".//h1", '2. Bar', True), + (".//h2", '2.1. Bar A', True), + (".//h3", '2.1.1. Bar A1', True), + (".//h2", '2.2. Bar B', True), + (".//h3", '2.2.1. Bar B1', True), + ], + } + + for fname, paths in iteritems(expects): + parser = NslessParser() + parser.entity.update(html_entities.entitydefs) + fp = open(os.path.join(app.outdir, fname), 'rb') + try: + etree = ET.parse(fp, parser) + finally: + fp.close() + + for xpath, check, be_found in paths: + yield check_xpath, etree, fname, xpath, check, be_found