Skip to content

mkdocs-gen-files#

Plugin for MkDocs to programmatically generate documentation pages during the build

Installation#

pip install mkdocs-gen-files

Usage#

Activate the plugin in mkdocs.yml (scripts is a required list of Python scripts to execute, always relative to mkdocs.yml):

plugins:
  - search
  - gen-files:
      scripts:
        - gen_pages.py  # or any other name or path

Then create such a script gen_pages.py (this is relative to the root, not to the docs directory).

Basic gen_pages.py
import mkdocs_gen_files

with mkdocs_gen_files.open("foo.md", "w") as f:
    print("Hello, world!", file=f)

Or something a bit more interesting:

Interesting gen_pages.py
import mkdocs_gen_files

for total in range(19, 100, 20):
    filename = f"sample/{total}-bottles.md"

    with mkdocs_gen_files.open(filename, "w") as f:
        for i in reversed(range(1, total + 1)):
            print(f"{i} bottles of beer on the wall, {i} bottles of beer  ", file=f)
            print(f"Take one down and pass it around, **{i-1}** bottles of beer on the wall\n", file=f)

    mkdocs_gen_files.set_edit_path(filename, "gen_pages.py")

This adds programmatically generated pages to our site. This example script has been applied to this very site, you can see sample/99-bottles.md etc.

Use cases#

You might be wondering, what's the point of this?

The original use case was with mkdocstrings - generating pages with just stubs for each item in API documentation, so that they can be populated by the tools.

You can also modify all existing files on the site in some way. Or perhaps copy files from somewhere on the fly.

Description#

For all intents and purposes, please conceptualize the mkdocs_gen_files.open() function as the actual open() function running under the docs_dir (./docs/ by default, picked up from mkdocs.yml). In fact, if a script using mkdocs_gen_files is launched standalone, that is actually the case; you can use that to try out how the results look (though manual cleanup will be required).

But if attached as a MkDocs plugin, it represents that directory only virtually; all file modifications affect only the ongoing site build and aren't persisted. But you can still read (and even virtually append to) the actual files under docs/.

This is implemented by implicitly transferring the files to a temporary directory (which is what you really end up opening) and telling MkDocs to fetch them from there instead. Note that this happens before MkDocs reads any of the doc files, so all of the outputs should look to it exactly as if the files were there all along.

All file modes are supported (even e.g. ab+). You could even open a file to read it, replace something in it, and write it back anew. Though at that point you may be better served by the "macros" plugin.

Note that this function is separate from the top-level built-in open(), which is unaffected and can still be used normally, relative to the current working directory (which is not changed to ./docs/, instead it's just the directory that you ran mkdocs from).