@@ -17,15 +17,15 @@ Let say you have a project called `project`.
17
17
This project has a lot of source files, or modules,
18
18
which live in the ` src ` folder:
19
19
20
- ```
21
- 📁 repo
22
- └─╴📁 src
23
- └─╴📁 project
24
- ├─╴📄 lorem
25
- ├─╴📄 ipsum
26
- ├─╴📄 dolor
27
- ├─╴📄 sit
28
- └─╴📄 amet
20
+ ``` tree
21
+ repo/
22
+ src/
23
+ project/
24
+ lorem
25
+ ipsum
26
+ dolor
27
+ sit
28
+ amet
29
29
```
30
30
31
31
Without an automatic process, you will have to manually
@@ -49,87 +49,102 @@ and configure it like so:
49
49
50
50
``` yaml title="mkdocs.yml"
51
51
plugins :
52
- - search # (1)
52
+ - search # (1)!
53
53
- gen-files :
54
54
scripts :
55
- - docs /gen_ref_pages.py # (2)
55
+ - scripts /gen_ref_pages.py # (2)!
56
56
- mkdocstrings
57
57
` ` `
58
58
59
59
1. Don't forget to load the ` search` plugin when redefining the `plugins` item.
60
60
2. The magic happens here, see below how it works.
61
61
62
62
mkdocs-gen-files is able to run Python scripts at build time.
63
- The Python script that we will execute lives in the docs folder,
63
+ The Python script that we will execute lives in a scripts folder,
64
64
and is named `gen_ref_pages.py`, like "generate code reference pages".
65
65
66
- ` ` ` python title="docs/gen_ref_pages.py"
66
+ ` ` ` tree
67
+ repo/
68
+ docs/
69
+ index.md
70
+ scripts/
71
+ gen_ref_pages.py
72
+ src/
73
+ project/
74
+ mkdocs.yml
75
+ ` ` `
76
+
77
+ ` ` ` python title="scripts/gen_ref_pages.py"
67
78
"""Generate the code reference pages."""
68
79
69
80
from pathlib import Path
70
81
71
82
import mkdocs_gen_files
72
83
73
- for path in sorted(Path("src").rglob("*.py")): # (1)
74
- module_path = path.relative_to("src").with_suffix("") # (2)
75
- doc_path = path.relative_to("src").with_suffix(".md") # (3)
76
- full_doc_path = Path("reference", doc_path) # (4)
84
+ src = Path(__file__).parent.parent / "src" # (1)!
85
+
86
+ for path in sorted(src.rglob("*.py")): # (2)!
87
+ module_path = path.relative_to(src).with_suffix("") # (3)!
88
+ doc_path = path.relative_to(src).with_suffix(".md") # (4)!
89
+ full_doc_path = Path("reference", doc_path) # (5)!
77
90
78
91
parts = list(module_path.parts)
79
92
80
- if parts[-1] == "__init__": # (5)
93
+ if parts[-1] == "__init__": # (6)!
81
94
parts = parts[:-1]
82
95
elif parts[-1] == "__main__":
83
96
continue
84
97
85
- with mkdocs_gen_files.open(full_doc_path, "w") as fd: # (6)
86
- identifier = ".".join(parts) # (7)
87
- print("::: " + identifier, file=fd) # (8)
98
+ with mkdocs_gen_files.open(full_doc_path, "w") as fd: # (7)!
99
+ identifier = ".".join(parts) # (8)!
100
+ print("::: " + identifier, file=fd) # (9)!
88
101
89
- mkdocs_gen_files.set_edit_path(full_doc_path, path) # (9)
102
+ mkdocs_gen_files.set_edit_path(full_doc_path, path) # (10)!
90
103
` ` `
91
104
92
- 1. Here we recursively list all `.py` files, but you can adapt the code to list
105
+ 1. It's important to build a path relative to the script itself,
106
+ to make it possible to build the docs with MkDocs'
107
+ [`-f` option](https://www.mkdocs.org/user-guide/cli/#mkdocs-build).
108
+ 2. Here we recursively list all `.py` files, but you can adapt the code to list
93
109
files with other extensions of course, supporting other languages than Python.
94
- 2 . The module path will look like `project/lorem`.
110
+ 3 . The module path will look like `project/lorem`.
95
111
It will be used to build the *mkdocstrings* autodoc identifier.
96
- 3 . This is the relative path to the Markdown page.
97
- 4 . This is the absolute path to the Markdown page. Here we put all reference pages
98
- into a `reference` folder.
99
- 5 . This part is only relevant for Python modules. We skip `__main__` modules and
112
+ 4 . This is the partial path of the Markdown page for the module .
113
+ 5 . This is the full path of the Markdown page within the docs.
114
+ Here we put all reference pages into a `reference` folder.
115
+ 6 . This part is only relevant for Python modules. We skip `__main__` modules and
100
116
remove `__init__` from the module parts as it's implicit during imports.
101
- 6 . Magic! Add the file to MkDocs pages, without actually writing it in the docs folder.
102
- 7 . Build the autodoc identifier. Here we document Python modules, so the identifier
117
+ 7 . Magic! Add the file to MkDocs pages, without actually writing it in the docs folder.
118
+ 8 . Build the autodoc identifier. Here we document Python modules, so the identifier
103
119
is a dot-separated path, like `project.lorem`.
104
- 8 . Actually write to the magic file.
105
- 9 . We can even set the `edit_uri` on the pages.
120
+ 9 . Actually write to the magic file.
121
+ 10 . We can even set the `edit_uri` on the pages.
106
122
107
123
> NOTE:
108
124
> It is important to look out for correct edit page behaviour when using generated pages.
109
125
> For example, if we have `edit_uri` set to `blob/master/docs/` and the following
110
126
> file structure:
111
127
>
112
- > ```
113
- > 📁 repo
114
- > ├─ 📄 mkdocs.yml
115
- > │
116
- > ├─ 📁 docs
117
- > │ ├─╴📄 index.md
118
- > │ └─╴📄 gen_ref_pages.py
119
- > │
120
- > └─╴📁 src
121
- > └─╴📁 project
122
- > ├─╴📄 lorem.py
123
- > ├─╴📄 ipsum.py
124
- > ├─╴📄 dolor.py
125
- > ├─╴📄 sit.py
126
- > └─╴📄 amet.py
128
+ > ```tree
129
+ > repo/
130
+ > mkdocs.yml
131
+ > docs/
132
+ > index.md
133
+ > scripts/
134
+ > gen_ref_pages.py
135
+ > src/
136
+ > project/
137
+ > lorem.py
138
+ > ipsum.py
139
+ > dolor.py
140
+ > sit.py
141
+ > amet.py
127
142
> ```
128
143
>
129
144
> Then we will have to change our `set_edit_path` call to:
130
145
>
131
146
> ```python
132
- > mkdocs_gen_files.set_edit_path(full_doc_path, Path("../") / path) # (1)
147
+ > mkdocs_gen_files.set_edit_path(full_doc_path, Path("../") / path) # (1)!
133
148
> ```
134
149
>
135
150
> 1. Path can be used to traverse the structure in any way you may need, but
@@ -180,15 +195,15 @@ plugins:
180
195
- search
181
196
- gen-files:
182
197
scripts:
183
- - docs /gen_ref_pages.py
198
+ - scripts /gen_ref_pages.py
184
199
- literate-nav:
185
200
nav_file: SUMMARY.md
186
201
- mkdocstrings
187
202
` ` `
188
203
189
204
Then, the previous script is updated like so :
190
205
191
- ` ` ` python title="docs /gen_ref_pages.py" hl_lines="7 21 29 30 "
206
+ ` ` ` python title="scripts /gen_ref_pages.py" hl_lines="7 23 31 32 "
192
207
"""Generate the code reference pages and navigation."""
193
208
194
209
from pathlib import Path
@@ -197,9 +212,11 @@ import mkdocs_gen_files
197
212
198
213
nav = mkdocs_gen_files.Nav()
199
214
200
- for path in sorted(Path("src").rglob("*.py")):
201
- module_path = path.relative_to("src").with_suffix("")
202
- doc_path = path.relative_to("src").with_suffix(".md")
215
+ src = Path(__file__).parent.parent / "src"
216
+
217
+ for path in sorted(src.rglob("*.py")):
218
+ module_path = path.relative_to(src).with_suffix("")
219
+ doc_path = path.relative_to(src).with_suffix(".md")
203
220
full_doc_path = Path("reference", doc_path)
204
221
205
222
parts = tuple(module_path.parts)
@@ -209,16 +226,16 @@ for path in sorted(Path("src").rglob("*.py")):
209
226
elif parts[-1] == "__main__":
210
227
continue
211
228
212
- nav[parts] = doc_path.as_posix() # (1)
229
+ nav[parts] = doc_path.as_posix() # (1)!
213
230
214
231
with mkdocs_gen_files.open(full_doc_path, "w") as fd:
215
232
ident = ".".join(parts)
216
233
fd.write(f"::: {ident}")
217
234
218
235
mkdocs_gen_files.set_edit_path(full_doc_path, path)
219
236
220
- with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file: # (2)
221
- nav_file.writelines(nav.build_literate_nav()) # (3)
237
+ with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file: # (2)!
238
+ nav_file.writelines(nav.build_literate_nav()) # (3)!
222
239
` ` `
223
240
224
241
1. Progressively build the navigation object.
@@ -232,7 +249,7 @@ and replace it with a single line!
232
249
nav:
233
250
# rest of the navigation...
234
251
# defer to gen-files + literate-nav
235
- - Code Reference: reference/ # (1)
252
+ - Code Reference: reference/ # (1)!
236
253
# rest of the navigation...
237
254
` ` `
238
255
@@ -259,7 +276,7 @@ Well, this is possible thanks to a third plugin:
259
276
260
277
Update the script like this :
261
278
262
- ` ` ` python title="docs /gen_ref_pages.py" hl_lines="18 19 "
279
+ ` ` ` python title="scripts /gen_ref_pages.py" hl_lines="20 21 "
263
280
"""Generate the code reference pages and navigation."""
264
281
265
282
from pathlib import Path
@@ -268,9 +285,11 @@ import mkdocs_gen_files
268
285
269
286
nav = mkdocs_gen_files.Nav()
270
287
271
- for path in sorted(Path("src").rglob("*.py")):
272
- module_path = path.relative_to("src").with_suffix("")
273
- doc_path = path.relative_to("src").with_suffix(".md")
288
+ src = Path(__file__).parent.parent / "src"
289
+
290
+ for path in sorted(src.rglob("*.py")):
291
+ module_path = path.relative_to(src).with_suffix("")
292
+ doc_path = path.relative_to(src).with_suffix(".md")
274
293
full_doc_path = Path("reference", doc_path)
275
294
276
295
parts = tuple(module_path.parts)
@@ -301,7 +320,7 @@ plugins:
301
320
- search
302
321
- gen-files:
303
322
scripts:
304
- - docs /gen_ref_pages.py
323
+ - scripts /gen_ref_pages.py
305
324
- literate-nav:
306
325
nav_file: SUMMARY.md
307
326
- section-index
0 commit comments