diff --git a/docs/recipes.md b/docs/recipes.md index c33130f0..c174ca04 100644 --- a/docs/recipes.md +++ b/docs/recipes.md @@ -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 @@ -52,7 +52,7 @@ plugins: - search # (1) - gen-files: scripts: - - docs/gen_ref_pages.py # (2) + - scripts/gen_ref_pages.py # (2) - mkdocstrings ``` @@ -60,70 +60,85 @@ plugins: 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: @@ -180,7 +195,7 @@ plugins: - search - gen-files: scripts: - - docs/gen_ref_pages.py + - scripts/gen_ref_pages.py - literate-nav: nav_file: SUMMARY.md - mkdocstrings @@ -188,7 +203,7 @@ plugins: 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 @@ -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) @@ -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 @@ -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) @@ -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