Skip to content

Commit

Permalink
docs: Make recipe work with MkDocs -f option
Browse files Browse the repository at this point in the history
  • Loading branch information
pawamoy committed Oct 25, 2023
1 parent f4a94f7 commit 163108a
Showing 1 changed file with 73 additions and 54 deletions.
127 changes: 73 additions & 54 deletions docs/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ Let say you have a project called `project`.
This project has a lot of source files, or modules,
which live in the `src` folder:

```
📁 repo
└─╴📁 src
└─╴📁 project
├─╴📄 lorem
├─╴📄 ipsum
├─╴📄 dolor
├─╴📄 sit
└─╴📄 amet
```tree
repo/
src/
project/
lorem
ipsum
dolor
sit
amet
```

Without an automatic process, you will have to manually
Expand All @@ -52,78 +52,93 @@ plugins:
- search # (1)
- gen-files:
scripts:
- docs/gen_ref_pages.py # (2)
- scripts/gen_ref_pages.py # (2)
- mkdocstrings
```

1. Don't forget to load the `search` plugin when redefining the `plugins` item.
2. The magic happens here, see below how it works.

mkdocs-gen-files is able to run Python scripts at build time.
The Python script that we will execute lives in the docs folder,
The Python script that we will execute lives in a scripts folder,
and is named `gen_ref_pages.py`, like "generate code reference pages".

```python title="docs/gen_ref_pages.py"
```tree
repo/
docs/
index.md
scripts/
gen_ref_pages.py
src/
project/
mkdocs.yml
```

```python title="scripts/gen_ref_pages.py"
"""Generate the code reference pages."""

from pathlib import Path

import mkdocs_gen_files

for path in sorted(Path("src").rglob("*.py")): # (1)
module_path = path.relative_to("src").with_suffix("") # (2)
doc_path = path.relative_to("src").with_suffix(".md") # (3)
full_doc_path = Path("reference", doc_path) # (4)
package_parent_folder = Path(__file__).parent.parent / "src" # (1)

for path in sorted(package_parent_folder.rglob("*.py")): # (2)
module_path = path.relative_to(package_parent_folder).with_suffix("") # (3)
doc_path = path.relative_to(package_parent_folder).with_suffix(".md") # (4)
full_doc_path = Path("reference", doc_path) # (5)

parts = list(module_path.parts)

if parts[-1] == "__init__": # (5)
if parts[-1] == "__init__": # (6)
parts = parts[:-1]
elif parts[-1] == "__main__":
continue

with mkdocs_gen_files.open(full_doc_path, "w") as fd: # (6)
identifier = ".".join(parts) # (7)
print("::: " + identifier, file=fd) # (8)
with mkdocs_gen_files.open(full_doc_path, "w") as fd: # (7)
identifier = ".".join(parts) # (8)
print("::: " + identifier, file=fd) # (9)

mkdocs_gen_files.set_edit_path(full_doc_path, path) # (9)
mkdocs_gen_files.set_edit_path(full_doc_path, path) # (10)
```

1. It's important to build a path relative to the script itself,
to make it possible to build the docs with MkDocs'
[`-f` option](https://www.mkdocs.org/user-guide/cli/#mkdocs-build).
1. Here we recursively list all `.py` files, but you can adapt the code to list
files with other extensions of course, supporting other languages than Python.
2. The module path will look like `project/lorem`.
1. The module path will look like `project/lorem`.
It will be used to build the *mkdocstrings* autodoc identifier.
3. This is the relative path to the Markdown page.
4. This is the absolute path to the Markdown page. Here we put all reference pages
1. This is the relative path to the Markdown page.
1. This is the absolute path to the Markdown page. Here we put all reference pages
into a `reference` folder.
5. This part is only relevant for Python modules. We skip `__main__` modules and
1. This part is only relevant for Python modules. We skip `__main__` modules and
remove `__init__` from the module parts as it's implicit during imports.
6. Magic! Add the file to MkDocs pages, without actually writing it in the docs folder.
7. Build the autodoc identifier. Here we document Python modules, so the identifier
1. Magic! Add the file to MkDocs pages, without actually writing it in the docs folder.
1. Build the autodoc identifier. Here we document Python modules, so the identifier
is a dot-separated path, like `project.lorem`.
8. Actually write to the magic file.
9. We can even set the `edit_uri` on the pages.
1. Actually write to the magic file.
1. We can even set the `edit_uri` on the pages.

> NOTE:
> It is important to look out for correct edit page behaviour when using generated pages.
> For example, if we have `edit_uri` set to `blob/master/docs/` and the following
> file structure:
>
> ```
> 📁 repo
> ├─ 📄 mkdocs.yml
> │
> ├─ 📁 docs
> │ ├─╴📄 index.md
> │ └─╴📄 gen_ref_pages.py
> │
> └─╴📁 src
> └─╴📁 project
> ├─╴📄 lorem.py
> ├─╴📄 ipsum.py
> ├─╴📄 dolor.py
> ├─╴📄 sit.py
> └─╴📄 amet.py
> ```tree
> repo/
> mkdocs.yml
> docs/
> index.md
> scripts/
> gen_ref_pages.py
> src/
> project/
> lorem.py
> ipsum.py
> dolor.py
> sit.py
> amet.py
> ```
>
> Then we will have to change our `set_edit_path` call to:
Expand Down Expand Up @@ -180,15 +195,15 @@ plugins:
- search
- gen-files:
scripts:
- docs/gen_ref_pages.py
- scripts/gen_ref_pages.py
- literate-nav:
nav_file: SUMMARY.md
- mkdocstrings
```

Then, the previous script is updated like so:

```python title="docs/gen_ref_pages.py" hl_lines="7 21 29 30"
```python title="scripts/gen_ref_pages.py" hl_lines="7 21 29 30"
"""Generate the code reference pages and navigation."""

from pathlib import Path
Expand All @@ -197,9 +212,11 @@ import mkdocs_gen_files

nav = mkdocs_gen_files.Nav()

for path in sorted(Path("src").rglob("*.py")):
module_path = path.relative_to("src").with_suffix("")
doc_path = path.relative_to("src").with_suffix(".md")
package_parent_folder = Path(__file__).parent.parent / "src"

for path in sorted(package_parent_folder.rglob("*.py")):
module_path = path.relative_to(package_parent_folder).with_suffix("")
doc_path = path.relative_to(package_parent_folder).with_suffix(".md")
full_doc_path = Path("reference", doc_path)

parts = tuple(module_path.parts)
Expand Down Expand Up @@ -259,7 +276,7 @@ Well, this is possible thanks to a third plugin:

Update the script like this:

```python title="docs/gen_ref_pages.py" hl_lines="18 19"
```python title="scripts/gen_ref_pages.py" hl_lines="18 19"
"""Generate the code reference pages and navigation."""

from pathlib import Path
Expand All @@ -268,9 +285,11 @@ import mkdocs_gen_files

nav = mkdocs_gen_files.Nav()

for path in sorted(Path("src").rglob("*.py")):
module_path = path.relative_to("src").with_suffix("")
doc_path = path.relative_to("src").with_suffix(".md")
package_parent_folder = Path(__file__).parent.parent / "src"

for path in sorted(package_parent_folder.rglob("*.py")):
module_path = path.relative_to(package_parent_folder).with_suffix("")
doc_path = path.relative_to(package_parent_folder).with_suffix(".md")
full_doc_path = Path("reference", doc_path)

parts = tuple(module_path.parts)
Expand Down Expand Up @@ -301,7 +320,7 @@ plugins:
- search
- gen-files:
scripts:
- docs/gen_ref_pages.py
- scripts/gen_ref_pages.py
- literate-nav:
nav_file: SUMMARY.md
- section-index
Expand Down

0 comments on commit 163108a

Please sign in to comment.