Writing pluglets
Note
New, as of version 0.4.20.
Introduction
Definition
A pluglet is a preinstalled module for mkdocs-macros, which is installed thanks to Pythons standard packaging process.
The only
thing needed (as a bare minimum), is to implement a single function,
define_env()
:
def define_env(env):
....
What makes a pluglet different from a plain module?
The only difference between a pluglet and an ordinary
mkdocs-macros module (typically main.py
or main
directory),
is that the pluglet is preinstalled. In this way, you can
benefit from pluglets written by others, and you could share the
pluglets that you wrote.
A pluglet can do two things that any mkdocs-macro module can do:
- Define macros.
- Perform changes on the architecture of the website.
What makes a pluglet different from a plugin?
A pluglet is distinct from an MkDocs plugin. A pluglet is a more lightweight tool that sits over the mkdocs-macros plugin and uses the framework provided by it.
There is no need to implement a subclass of the BasePlugin
class,
only to declare a define_env(env)
function.
Could a pluglet do everything a plugin can do?
The answer is, quite a lot, but not everything. MkDocs plugins are able to rely on a wide range of events, which are hooks for acting on the website at various stages of the config/build process.
A mkdocs-macros pluglet operates mostly on the on_config event of MkDocs thanks to
define_env(env)
hook; but its use can be extended thanks to other hooks.
Using existing pluglets
Declaring a pluglet for an MkDocs project
For your specific documentation project, you may call already
installed pluglets (which would appear with pip list
):
pip list | grep mkdocs-macros
Use the modules
argument.
It is a list, so that you can declare one or more:
e.g. :
plugins:
...
- macros:
modules: [mkdocs_macros_test]
or:
plugins:
...
- macros:
modules: [mkdocs_macros_foo, mkdocs_macros_bar]
Auto-installable pluglets
Every pluglet specified in the modules
list should be available.
However, if the pluglet cannot be found, mkdocs will attempt to install it
(with pip3 install
) from the standard repositories (Pypi and others defined locally). If not, mkdocs will fail and exit.
Make installations easier!
The purpose of this feature is to facilitate the management of environments with several mkdocs websites, typically when a pluglet is designed for a whole company, project, etc.
In this way, the macros and filters declared in the pluglet will work out of the box, as long as the pluglet is properly defined in the config file (and the pluglet is auto-installable).
In some cases, the name of the source package i:
plugins:
...
- macros:
modules: [mkdocs-macros-test:mkdocs_macros_test]
In the example above mkdocs-macros-test
is the package source, and
mkdocs_macros_test
is the package name for the import
statement.
If those names are correct everything should fall into place when you type the mkdocs serve
or mkdocs build
commands.
Implementing a new pluglet
General Principles
You can develop pluglets for mkdocs-macros-plugin and publish them on github and pypi.
How to name a pluglet
The names for pluglets are not constrained. As a naming convention, we strongly recommend:
- a package name starting with
mkdocs-macros-
- an import name starting
mkdocs_macros_
, i.e. replacing the hyphen (-
) symbol by underscore (_
).
Typical structure of a pluglet
Note
You will find a simple example with the mkdocs-test
pluglet, available on gihub.
The setup.py
file will typically have this form:
from setuptools import setup
setup(
name='mkdocs-macros-foo',
version='0.0.1',
description="Foo library for macros plugin",
packages=['mkdocs_macros_foo'],
license='<YOUR CHOICE>',
author='Joe Bloe'
)
The structure will be typically like so:
├── LICENSE.md
├── README.md
├── mkdocs_macros_test.py
└── setup.py
or like so (if it is more complex):
├── LICENSE.md
├── README.md
├── mkdocs_macros_test
│ └── __init__.py
| └── util.py
└── setup.py
Note
The subdirectory containing
the code will have to be called mkdocs_macros_foo
(underscores).
How to write the code
For the code itself, proceed as for a usual module:
"""
Code of the pluglet
"""
def test_fn(x:float):
"Test function"
return x * 4 / 3
def say_hello(s:str):
"Test procedure"
return "<i>Hello %s</i>" % s
def define_env(env):
"Declare environment for jinja2 templates for markdown"
for fn in [test_fn, say_hello]:
env.macro(fn)
# you could, of course, also define a macro here:
@env.macro
def test_fn2(s:str):
return "I am displaying this: %s" % s