Skip to content

Commit 31e5618

Browse files
authored
♻️ REFACTOR: sections -> items, add format key (#22)
The `format` key add key-mapping for jupyter-book support.
1 parent f5d8454 commit 31e5618

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+623
-230
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,4 @@ dmypy.json
129129
.pyre/
130130

131131
.vscode/
132+
~$*

MANIFEST.in

+2
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ exclude codecov.yml
1010

1111
include LICENSE
1212
include CHANGELOG.md
13+
include README.md
14+
include toc-graphic.png
1315

1416
include sphinx_external_toc/py.typed

README.md

+91-29
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ In normal Sphinx documentation, the documentation site-map is defined *via* a bo
1111

1212
This extension facilitates a **top-down** approach to defining the site-map structure, within a single YAML file.
1313

14+
![ToC graphic](toc-graphic.png)
15+
16+
It also allows for documents not specified in the ToC to be auto-excluded.
17+
1418
## User Guide
1519

1620
### Sphinx Configuration
@@ -39,7 +43,7 @@ The value of the `root` key will be a path to a file, in Unix format (folders sp
3943
This root file will be set as the [`master_doc`](https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-master_doc).
4044
:::
4145

42-
Document files can then have a `subtrees` key - denoting a list of individual toctrees for that document - and in-turn each subtree should have a `sections` key - denoting a list of children links, that are one of: `file`, `url` or `glob`:
46+
Document files can then have a `subtrees` key - denoting a list of individual toctrees for that document - and in-turn each subtree should have a `items` key - denoting a list of children links, that are one of:
4347

4448
- `file`: path to a single document file in Unix format, with or without the file extension (as for `root`)
4549
- `glob`: path to one or more document files *via* Unix shell-style wildcards (similar to [`fnmatch`](https://docs.python.org/3/library/fnmatch.html), but single stars don't match slashes.)
@@ -54,13 +58,13 @@ This can proceed recursively to any depth.
5458
```yaml
5559
root: intro
5660
subtrees:
57-
- sections:
61+
- items:
5862
- file: doc1
5963
subtrees:
60-
- sections:
64+
- items:
6165
- file: doc2
6266
subtrees:
63-
- sections:
67+
- items:
6468
- file: doc3
6569
- url: https://example.com
6670
- glob: subfolder/other*
@@ -69,16 +73,16 @@ subtrees:
6973
This is equivalent to having a single `toctree` directive in `intro`, containing `doc1`,
7074
and a single `toctree` directive in `doc1`, with the `:glob:` flag and containing `doc2`, `https://example.com` and `subfolder/other*`.
7175

72-
As a shorthand, the `sections` key can be at the same level as the `file`, which denotes a document with a single subtree.
76+
As a shorthand, the `items` key can be at the same level as the `file`, which denotes a document with a single subtree.
7377
For example, this file is exactly equivalent to the one above:
7478

7579
```yaml
7680
root: intro
77-
sections:
81+
items:
7882
- file: doc1
79-
sections:
83+
items:
8084
- file: doc2
81-
sections:
85+
items:
8286
- file: doc3
8387
- url: https://example.com
8488
- glob: subfolder/other*
@@ -92,7 +96,7 @@ With the `title` key you can set an alternative title for a document. and also f
9296
```yaml
9397
root: intro
9498
subtrees:
95-
- sections:
99+
- items:
96100
- file: doc1
97101
title: Document 1 Title
98102
- url: https://example.com
@@ -106,13 +110,13 @@ Each subtree can be configured with a number of options (see also [sphinx `toctr
106110
- `caption` (string): A title for the whole the subtree, e.g. shown above the subtree in ToCs
107111
- `hidden` (boolean): Whether to show the ToC within (inline of) the document (default `False`).
108112
By default it is appended to the end of the document, but see also the `tableofcontents` directive for positioning of the ToC.
109-
- `maxdepth` (integer): A maximum nesting depth to use when showing the ToC within the document.
113+
- `maxdepth` (integer): A maximum nesting depth to use when showing the ToC within the document (default -1, meaning infinite).
110114
- `numbered` (boolean or integer): Automatically add numbers to all documents within a subtree (default `False`).
111115
If set to `True`, all sub-trees will also be numbered based on nesting (e.g. with `1.1` or `1.1.1`),
112116
or if set to an integer then the numbering will only be applied to that depth.
113-
- `reversed` (boolean): If `True` then the entries in the subtree will be listed in reverse order.
114-
This can be useful when using `glob` sections.
115-
- `titlesonly` (boolean): If `True` then only the first heading in the document will be shown in the ToC, not other headings of the same level.
117+
- `reversed` (boolean): If `True` then the entries in the subtree will be listed in reverse order (default `False`).
118+
This can be useful when using `glob` items.
119+
- `titlesonly` (boolean): If `True` then only the first heading in the document will be shown in the ToC, not other headings of the same level (default `False`).
116120

117121
These options can be set at the level of the subtree:
118122

@@ -125,11 +129,11 @@ subtrees:
125129
numbered: True
126130
reversed: False
127131
titlesonly: True
128-
sections:
132+
items:
129133
- file: doc1
130134
subtrees:
131135
- titlesonly: True
132-
sections:
136+
items:
133137
- file: doc2
134138
```
135139

@@ -144,11 +148,11 @@ options:
144148
numbered: True
145149
reversed: False
146150
titlesonly: True
147-
sections:
151+
items:
148152
- file: doc1
149153
options:
150154
titlesonly: True
151-
sections:
155+
items:
152156
- file: doc2
153157
```
154158

@@ -164,9 +168,9 @@ options:
164168
maxdepth: 1
165169
numbered: True
166170
reversed: False
167-
sections:
171+
items:
168172
- file: doc1
169-
sections:
173+
items:
170174
- file: doc2
171175
```
172176

@@ -175,10 +179,55 @@ sections:
175179
:::
176180

177181
:::{note}
178-
By default, section numbering restarts for each subtree.
182+
By default, title numbering restarts for each subtree.
179183
If you want want this numbering to be continuous, check-out the [sphinx-multitoc-numbering extension](https://github.com/executablebooks/sphinx-multitoc-numbering).
180184
:::
181185

186+
### Using different key-mappings
187+
188+
For certain use-cases, it is helpful to map the `subtrees`/`items` keys to mirror e.g. an output [LaTeX structure](https://www.overleaf.com/learn/latex/sections_and_chapters).
189+
190+
The `format` key can be used to provide such mappings (and also initial defaults).
191+
Currently available:
192+
193+
- `jb-article`:
194+
- Maps `items` -> `sections`
195+
- Sets the default of `titlesonly` to `true`
196+
- `jb-book`:
197+
- Maps the top-level `subtrees` to `parts`
198+
- Maps the top-level `items` to `chapters`
199+
- Maps other levels of `items` to `sections`
200+
- Sets the default of `titlesonly` to `true`
201+
202+
For example:
203+
204+
```yaml
205+
defaults:
206+
titlesonly: true
207+
root: index
208+
subtrees:
209+
- items:
210+
- file: doc1
211+
items:
212+
- file: doc2
213+
```
214+
215+
is equivalent to:
216+
217+
```yaml
218+
format: jb-book
219+
root: index
220+
parts:
221+
- chapters:
222+
- file: doc1
223+
sections:
224+
- file: doc2
225+
```
226+
227+
:::{important}
228+
These change in key names do not change the output site-map structure.
229+
:::
230+
182231
## Add a ToC to a page's content
183232

184233
By default, the `toctree` generated per document (one per subtree) are appended to the end of the document and hidden (then, for example, most HTML themes show them in a side-bar).
@@ -225,19 +274,32 @@ To see all options:
225274

226275
```console
227276
$ sphinx-etoc --help
277+
Usage: sphinx-etoc [OPTIONS] COMMAND [ARGS]...
278+
279+
Command-line for ``sphinx-external-toc``.
280+
281+
Options:
282+
--version Show the version and exit.
283+
-h, --help Show this message and exit.
284+
285+
Commands:
286+
from-site Create a ToC file from a site directory.
287+
migrate Migrate a ToC from a previous revision.
288+
parse-toc Parse a ToC file to a site-map YAML.
289+
to-site Create a site directory from a ToC file.
228290
```
229291

230292
To build a template site from only a ToC file:
231293

232294
```console
233-
$ sphinx-etoc create-site -p path/to/site -e rst path/to/_toc.yml
295+
$ sphinx-etoc to-site -p path/to/site -e rst path/to/_toc.yml
234296
```
235297

236298
Note, you can also add additional files in `meta`/`create_files` amd append text to the end of files with `meta`/`create_append`, e.g.
237299

238300
```yaml
239301
root: intro
240-
sections:
302+
items:
241303
- glob: doc*
242304
meta:
243305
create_append:
@@ -253,7 +315,7 @@ meta:
253315
To build a ToC file from an existing site:
254316

255317
```console
256-
$ sphinx-etoc create-toc path/to/folder
318+
$ sphinx-etoc from-site path/to/folder
257319
```
258320

259321
Some rules used:
@@ -290,9 +352,9 @@ index.rst
290352
will create the ToC:
291353

292354
```console
293-
$ sphinx-etoc create-toc path/to/folder -i index -s ".*" -e ".rst" -t
355+
$ sphinx-etoc from-site path/to/folder -i index -s ".*" -e ".rst" -t
294356
root: index
295-
sections:
357+
items:
296358
- file: 1_a_title
297359
title: A title
298360
- file: 11_another_title
@@ -301,20 +363,20 @@ sections:
301363
title: A subfolder
302364
- file: 2_another_subfolder/index
303365
title: Another subfolder
304-
sections:
366+
items:
305367
- file: 2_another_subfolder/other
306368
title: Other
307369
- file: 3_subfolder/1_no_index
308370
title: No index
309-
sections:
371+
items:
310372
- file: 3_subfolder/2_no_index
311373
title: No index
312374
- file: 14_subfolder/index
313375
title: Subfolder
314-
sections:
376+
items:
315377
- file: 14_subfolder/subsubfolder/index
316378
title: Subsubfolder
317-
sections:
379+
items:
318380
- file: 14_subfolder/subsubfolder/other
319381
title: Other
320382
```

docs/_toc.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ defaults:
44
subtrees:
55
- caption: Part 1
66
numbered: true
7-
sections:
7+
items:
88
- file: doc1
99
- file: doc2
10-
sections:
10+
items:
1111
- file: subfolder/doc3
1212
- url: https://example.com
1313
title: Example Link
1414
- caption: Part 2
1515
numbered: true
16-
sections:
16+
items:
1717
- glob: subglobs/glob*

sphinx_external_toc/api.py

+22-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class TocTree:
4646
False, kw_only=True, validator=instance_of((bool, int))
4747
)
4848
reversed: bool = attr.ib(False, kw_only=True, validator=instance_of(bool))
49-
titlesonly: bool = attr.ib(True, kw_only=True, validator=instance_of(bool))
49+
titlesonly: bool = attr.ib(False, kw_only=True, validator=instance_of(bool))
5050

5151
def files(self) -> List[str]:
5252
return [str(item) for item in self.items if isinstance(item, FileItem)]
@@ -78,11 +78,17 @@ def child_globs(self) -> List[str]:
7878
class SiteMap(MutableMapping):
7979
"""A mapping of documents to their toctrees (or None if terminal)."""
8080

81-
def __init__(self, root: Document, meta: Optional[Dict[str, Any]] = None) -> None:
81+
def __init__(
82+
self,
83+
root: Document,
84+
meta: Optional[Dict[str, Any]] = None,
85+
file_format: Optional[str] = None,
86+
) -> None:
8287
self._docs: Dict[str, Document] = {}
8388
self[root.docname] = root
8489
self._root: Document = root
8590
self._meta: Dict[str, Any] = meta or {}
91+
self._file_format = file_format
8692

8793
@property
8894
def root(self) -> Document:
@@ -94,6 +100,16 @@ def meta(self) -> Dict[str, Any]:
94100
"""Return the site-map metadata."""
95101
return self._meta
96102

103+
@property
104+
def file_format(self) -> Optional[str]:
105+
"""Return the format of the file to write to."""
106+
return self._file_format
107+
108+
@file_format.setter
109+
def file_format(self, value: Optional[str]) -> None:
110+
"""Set the format of the file to write to."""
111+
self._file_format = value
112+
97113
def globs(self) -> Set[str]:
98114
"""Return set of all globs present across all toctrees."""
99115
return {glob for item in self._docs.values() for glob in item.child_globs()}
@@ -134,4 +150,7 @@ def as_json(self) -> Dict[str, Any]:
134150
else self._docs[k]
135151
for k in sorted(self._docs)
136152
}
137-
return {"root": self.root.docname, "documents": doc_dict, "meta": self.meta}
153+
data = {"root": self.root.docname, "documents": doc_dict, "meta": self.meta}
154+
if self.file_format:
155+
data["file_format"] = self.file_format
156+
return data

0 commit comments

Comments
 (0)