How to Write "Enriched" Markdown Pages
Definitions
1. Variable
A variable is a predefined value.
- The primary source of variables is the
extra
namespace in the config file (by default:mkdocs.yml
). - You can add variables in the Python module.
- Also local variables can be added directly to each
markdown page, thanks to jinja2 directives, called
set
(those local variables are accessible by jinja2 directives, but not the Python code).
2. Macro
We call macros, Python functions (or callables) that will be used in jinja2 snippets within the markdown pages. A macro should return a string that can be plain, markdown or HTML. Each call to the macro in markdown page will be replaced by that result.
Note
For more information on the full concept of a macro, see the detailed explanation.
3. Filter
A custom filter is a Jinja2 concept. It is essentially a Python
function used with a different syntax,
e.g. {{ 'my text ' | uppercase}}
(supposing there was a custom
function called uppercase
and declared as a filter). Just as a
macro, a filter should return a string that can be plain, markdown
or HTML.
"Batteries included": defaut objects
The following objects are, in particular, available by default, with their set of attributes:
Object | Description |
---|---|
config |
The standard config information on MkDocs' environment. |
page |
Info on the current page (source) |
navigation |
List of all pages/sections of the website; sections are themselves list of pages; (source) |
environment |
Data on the system on which MkDocs is currently running. |
plugin |
Arguments of the macro plugin, in the config file |
git |
Information on the git version of the website (if part of a git repository) |
files |
The file structure (for advanced users who know how to manipulate the mkdocs.structure.files.Files object, as well as mkdocs.structure.files.File objects) |
For example,
{{ config.site_name }}
returns the main title of the website{{ environment.system }}
returns the name of the OS.{{ navigation.pages }}
returns a flattened list of all pages{{ plugin.module }}
name of the Python module
To discover what each of these objects contain, you can use the pretty
filter provided with the plugin, e.g.:
{{ context(page) | pretty }}
Configuration variables
To easily and quickly define custom variables, declare them in you
mkdocs.yml
file:
extra:
price: 12.50
company:
name: Acme
address: ....
website: www.acme.com
In your markdown file:
The price of the product is {{ price }}.
See [more information on the website]({{ company.website }}).
See <a href="{{ company.website }}">more information on the website</a>.
Local (page-level) variables and macros
If you really need a variable or macro that needs to remain local to the markdown page, you can use a standard Jinja2 declaration.
Warning
Note that the context()
macro (for listing variables)
will not display variables defined at page level.
In the YAML header of the page
Variables defined in the YAML header of the page are accessible as themselves
and via the page.meta
object.
For example, if the the header is as follows:
---
title: My special title
bottles:
whine: 500
beer: 123
---
Then you can access the content of the YAML header in two ways:
- By name e.g.
{{ title }}
and{{ bottles.whine }}
- Explicitly, i.e. using the dot notation, e.g.
{{ page.meta.title }}
and{{ page.meta.bottles.whine }}
.
Tip
{{ page.meta }}
gives the content of the header.
If you wish to have it typed in a nice tabular form, you can use:
{{ context(page.meta) | pretty }}
Caution
If variables in the metadata have the same name as variables
already defined (suche as extra
, config
, etc.) those will
be overwritten, but for this page only.
Using the set
keyword
Variables can be defined in the template with the set
keyword, e.g.:
{% set acme = 'Acme Company Ltd' %}
Please buy the great products from {{ acme }}!
Contrary to variables defined in the extra
section of the mkdocs.yml
file, they are accessible only within the specific page. They are not
accessible from the python code.
Tip
If you need reference information on the page, there is a page
object
e.g.: {{ page.title }}
,
{{ page.url }}
, {{ page.is_homepage }}
, etc.
Page-level macros
It is possible to write Jinja2 macros written with the Jinja2 syntax (instead of a Python module). This allows you benefit from the power of that language for the manipulation of strings.
Here is an example of Jinja2 macro, from the official documentation:
{% macro input(name, value='', type='text', size=20) -%}
<input type="{{ type }}" name="{{ name }}" value="{{
value|e }}" size="{{ size }}">
{%- endmacro %}
Which can be called (within the page) as:
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
Note
All definitions will remain local to the page.
It is possible to define Jinja2 macros in a separate file,
and to import them from there in any page, using the
{% import ..}
directive.
See explanations under Advanced Usage.
Conditionals, loops, etc.
With the macros plugin, you may use the conditional statement of Jinja2, e.g.
### My title
{% if == 'bar' %}
We will write this **first version**
{% else %}
_Second version_
{% endif %}
You may produce Markdown or any mix of Markdown, HTML, css and even javascript that you wish.
Similarly, you could use for loops:
### List of users
{% set users = ['joe', 'jill', 'david', 'sam'] %}
{% for user in users %}
1. {{ user }}
{% endfor %}
In fact, you can do all the fancy footwork you want with Jinja2!