diff --git a/docs/customize/toc.md b/docs/customize/toc.md
index b8f6aba62..2eec5d2da 100644
--- a/docs/customize/toc.md
+++ b/docs/customize/toc.md
@@ -110,37 +110,39 @@ We recommend nesting your sections no more than 3 layers deep (as shown above).
## Number your book's sections
You can automatically add numbers to each section of your book. To add numbers
-to any section or subsection of the book, add the `numbered: true` flag to its
-entry in your `_toc.yml` file. For example:
+to **all sections of your book**, add the `numbered: true` flag to
+your introduction page entry (the first entry in `_toc.yml`). For example:
-````{list-table}
-:header-rows: 1
-
-* - Files
- - Chapters
-* - ```yaml
- - file: myfolder/mypage
- numbered: true
- sections:
- - file: myfolder/mysubpage
- ```
- - ```yaml
- - chapter: My chapter
- numbered: true
- sections:
- - file: myfolder/mypage
- numbered: true
- sections:
- - file: myfolder/mysubpage
- ```
-````
+```yaml
+- file: home
+ numbered: true
+- file: page2
+- file: page3
+- file: page4
+```
-This will cause both `myfolder/mypage` as well as `myfolder/asubpage` to be
+This will cause all sections of the book to be
numbered. They will follow a hierarchy according to the sub-sections structure
defined in your `_toc.yml` file.
-To number *all* of the sections of your book, add the `numbered: true` flag to
-the first entry of your `_toc.yml` file.
+If you'd like to number **subsets of sections**, group them into chapters and
+apply the `numbered: true` flag to the chapters that you wish to be numbered.
+For example:
+
+```yaml
+- file: home
+ numbered: true
+# This chapter will not be numbered
+- chapter: Introduction
+ sections:
+ - file: page2
+# This chapter will be numbered
+- chapter: Chapter 1
+ numbered: true
+ sections:
+ - file: page3
+ - file: page4
+```
### Numbering caveats and notes
diff --git a/jupyter_book/toc.py b/jupyter_book/toc.py
index 77a4e8831..d0ffa2171 100644
--- a/jupyter_book/toc.py
+++ b/jupyter_book/toc.py
@@ -71,10 +71,7 @@ def add_toctree(app, docname, source):
# Check if subsections are all individual files. If so, embed them in a section
are_files = [("file" in ii) or ("url" in ii) for ii in sections]
if all(are_files):
- sections = {"chapter": "", "sections": sections}
- if "numbered" in parent_page:
- sections["numbered"] = True
- sections = [sections]
+ sections = [{"chapter": "", "sections": sections}]
elif any(are_files) and not all(are_files):
raise ValueError(
f"Mixed chapters and individual files in `_toc.yml` entry {parent_name}"
@@ -85,7 +82,7 @@ def add_toctree(app, docname, source):
for isection in sections:
# Check for TOC options (that generally only change behavior on top-level page)
toc_options = {}
- if "numbered" in isection and isection.get("numbered") is not False:
+ if isection.get("numbered") or parent_page.get("numbered"):
toc_options["numbered"] = "" # Empty string will == a flag in the toctree
if isection.get("chapter"):
toc_options["caption"] = isection.get("chapter")
diff --git a/tests/books/toc/_toc_numbered_chapters.yml b/tests/books/toc/_toc_numbered_chapters.yml
new file mode 100644
index 000000000..b90d2ce86
--- /dev/null
+++ b/tests/books/toc/_toc_numbered_chapters.yml
@@ -0,0 +1,18 @@
+- file: index
+ title: Toc
+ numbered: true
+- chapter: Chapter 1
+ sections:
+ - file: content1
+ title: Content1
+ - file: subfolder/index
+ title: Subfolder
+ sections:
+ - file: subfolder/asubpage
+ title: Asubpage
+- chapter: Chapter 2
+ sections:
+ - file: content2
+ title: Content2
+ - file: content3
+ title: Content3
diff --git a/tests/books/toc/_toc_numbered_chapters_subset.yml b/tests/books/toc/_toc_numbered_chapters_subset.yml
new file mode 100644
index 000000000..76aba839c
--- /dev/null
+++ b/tests/books/toc/_toc_numbered_chapters_subset.yml
@@ -0,0 +1,21 @@
+- file: index
+ title: Toc
+- chapter: Chapter 1
+ numbered: true
+ sections:
+ - file: content1
+ title: Content1
+- chapter: Chapter 2
+ sections:
+ - file: content2
+ title: Content2
+ - file: content3
+ title: Content3
+- chapter: Chapter 3
+ numbered: true
+ sections:
+ - file: subfolder/index
+ title: Subfolder
+ sections:
+ - file: subfolder/asubpage
+ title: Asubpage
diff --git a/tests/test_toc.py b/tests/test_toc.py
index 360382499..1b658415f 100644
--- a/tests/test_toc.py
+++ b/tests/test_toc.py
@@ -2,6 +2,10 @@
from subprocess import run, PIPE
import pytest
import yaml
+from bs4 import BeautifulSoup
+
+
+path_books = Path(__file__).parent.joinpath("books")
def test_toc():
@@ -21,7 +25,7 @@ def test_toc():
def test_toc_add_titles():
- path_book = Path(__file__).parent.joinpath("books", "toc")
+ path_book = path_books.joinpath("toc")
run(f"jb toc {path_book}".split(), check=True)
toc_yaml = path_book.joinpath("_toc.yml")
res = yaml.safe_load(toc_yaml.read_text(encoding="utf8"))
@@ -35,3 +39,30 @@ def test_toc_add_titles():
assert "title" in res
for section in res["sections"]:
assert "title" in section
+
+
+def test_toc_numbered(tmpdir, file_regression):
+ """Testing that numbers make it into the sidebar"""
+ path_output = Path(tmpdir).joinpath("mybook").absolute()
+ toc_list = [
+ "_toc_numbered.yml", # Numbered in top-level title
+ "_toc_numbered_chapters.yml", # Numbered in top-level title w/ chapters
+ "_toc_numbered_chapters_subset.yml", # Only some sections numbered
+ ]
+ for itoc in toc_list:
+ # Numbering with files
+ p_toc = path_books.joinpath("toc")
+ path_toc = p_toc.joinpath(itoc)
+ run(
+ f"jb build {p_toc} --path-output {path_output} --toc {path_toc} -W".split(),
+ check=True,
+ )
+
+ path_toc_directive = path_output.joinpath("_build", "html", "index.html")
+
+ # get the tableofcontents markup
+ soup = BeautifulSoup(
+ path_toc_directive.read_text(encoding="utf8"), "html.parser"
+ )
+ toc = soup.select("nav.bd-links")[0]
+ file_regression.check(str(toc), basename=itoc.split(".")[0], extension=".html")
diff --git a/tests/test_tocdirective/test_toc_numbered.html b/tests/test_toc/_toc_numbered.html
similarity index 98%
rename from tests/test_tocdirective/test_toc_numbered.html
rename to tests/test_toc/_toc_numbered.html
index de8eb6188..ba7864a07 100644
--- a/tests/test_tocdirective/test_toc_numbered.html
+++ b/tests/test_toc/_toc_numbered.html
@@ -28,4 +28,4 @@
-
\ No newline at end of file
+
diff --git a/tests/test_toc/_toc_numbered_chapters.html b/tests/test_toc/_toc_numbered_chapters.html
new file mode 100644
index 000000000..353d9b284
--- /dev/null
+++ b/tests/test_toc/_toc_numbered_chapters.html
@@ -0,0 +1,43 @@
+
diff --git a/tests/test_toc/_toc_numbered_chapters_subset.html b/tests/test_toc/_toc_numbered_chapters_subset.html
new file mode 100644
index 000000000..df3986239
--- /dev/null
+++ b/tests/test_toc/_toc_numbered_chapters_subset.html
@@ -0,0 +1,50 @@
+
diff --git a/tests/test_tocdirective.py b/tests/test_tocdirective.py
index c30c10a43..9fbe1bbcf 100644
--- a/tests/test_tocdirective.py
+++ b/tests/test_tocdirective.py
@@ -64,22 +64,3 @@ def test_toc_urllink(tmpdir, file_regression):
soup = BeautifulSoup(path_toc_directive.read_text(encoding="utf8"), "html.parser")
toc = soup.find_all("div", class_="tableofcontents-wrapper")[0]
file_regression.check(str(toc), extension=".html")
-
-
-def test_toc_numbered(tmpdir, file_regression):
- """Testing that numbers make it into the sidebar"""
- path_output = Path(tmpdir).joinpath("mybook").absolute()
- # Regular TOC should work
- p_toc = path_books.joinpath("toc")
- path_toc = p_toc.joinpath("_toc_numbered.yml")
- run(
- f"jb build {p_toc} --path-output {path_output} --toc {path_toc} -W".split(),
- check=True,
- )
-
- path_toc_directive = path_output.joinpath("_build", "html", "index.html")
-
- # get the tableofcontents markup
- soup = BeautifulSoup(path_toc_directive.read_text(encoding="utf8"), "html.parser")
- toc = soup.select("nav.bd-links")[0]
- file_regression.check(str(toc), extension=".html")