Stars identify *important* text.
Basic Templates
'That's the idea,' replied Norton. 'This may be an indexed catalogue for 3-D images—templates—solid blueprints, if you like to call them that.'
So far, Mau provides features similar to Markdown, Asciidoc, and other markup languages. The real power of Mau, however, relies in its use of templates to render the output of the syntax.
Everything you saw in the previous chapters is rendered as described thanks to the default Jinja templates provided by the visitor, but such templates can be easily customised to provide the output you prefer.
The Abstract Syntax Tree
To start off on our journey with templates let's have a look at how Mau parses text. Let's assume the input is
This piece of text is processed by Mau and an internal representation called Abstract Syntax Tree (AST) is created. A compact version of the AST for this input is
data:
type: document
content:
- data:
type: paragraph
content:
- data:
type: text
value: 'Stars identify '
- data:
type: style
value: star
content:
- data:
type: text
value: important
- data:
type: text
value: ' text.'
You can see the AST at any time using the output format yaml
on the command line
mau -f yaml -i input.mau -o -
Templates
Once the AST has been created, the chosen visitor is used to render each node. In this case the nodes are of type text
, sentence
, style
, paragraph
, and document
.
The style
node in the previous AST is
- data:
type: style
value: star
content:
- data:
type: text
value: important
And the visitor called JinjaVisitor
will identify certain templates based on the properties of the node.
For the text node the template will be text
, while for the style node the template will be style.star
.
However, as we want to generate a specific type of output, for example HTML, we will select a more specialised visitor that selects the templates using a custom extension. In this case the visitor is HtmlVisitor
and the templates are text.html
and style.star.html
text.html
{{ value }}
style.star.html
<strong>{{ content }}</strong>
The output of the text node will then be
important
and the output of the style node will then be
<strong>important</strong>.
as {{ content }}
is the rendering of all nodes contained in the style node.
If we changed the style template to
style.star.html
<span class="italic">{{ content }}</span>
the result would be
<span class="italic">important</span>
Jinja
Currently, the hierarchy of visitors is the following
BaseVisitor
^
|
|
JinjaVisitor
^
|
|
+----------+--------+
| |
| |
HtmlVisitor TexVisitor
BaseVisitor
is used to produce the YAML representation of the AST, while JinjaVisitor
augments it with a list of plugin names for each node, loads them, and calls the Jinja templating engine to transform them into text.
HtmlVisitor
and TexVisitor
are provided as plugins and build on top of what JinjaVisitor
does, adding some specific features connected with the output format. For example, HtmlVisitor
processes source code blocks using Pygments.
Loading visitors from plugins means that it's pretty easy to add a new templating engine or to add other formats on top of JinjaVisitor
BaseVisitor
^
|
+-------------------------+
| |
JinjaVisitor TemplatingEngineVisitor
^
|
|
+----------+--------+-------------------+
| | |
| | |
HtmlVisitor TexVisitor OtherFormatVisitor
How to define templates
Mau templates can be provided in the YAML configuration or as individual files.
YAML Configuration file
Mau templates can be defined in the YAML configuration file using the key custom_templates
. For example
---
target_format: html
custom_templates:
style.underscore.html: '<span class="bold">{{ content }}</span>'
style.star.html: '<span class="italic">{{ content }}</span>'
This is a good solution for simple templates, but it might quickly become unmanageable if your templates include a lot of Jinja operators.
Individual files
You can store templates in individual files inside a directory and pass the latter to Mau through the configuration file with the key mau.visitor.templates_directory
.
---
mau:
visitor:
templates_directory: templates
The file has to be named after the template and have an extension matching the output format. This is a good solution for complex templates, as it doesn't require to quote the text. You can also benefit from syntax highlighting in your editor while writing the template.
Template files can be created with a flat or nested structure. Each file can be created with its full name, so you can have
templates/
header.html
source.html
source.python.html
source.javascript.html
style.star.html
style.underscore.html
or you can use each part of the dotted name as a subdirectory
templates/
header.html
source.html
source/
python.html
javascript.html
style/
star.html
underscore.html
This is true at individual level, so you can mix the two styles
templates/
header.html
source.html
source.python.html
source/
javascript.html
style/
star.html
underscore.html
Install visitor plugins
The two classes HtmlVisitor
and TexVisitor
are provided by plugins. They can be installed in any virtual environment using pip
pip install mau-html-visitor
pip install mau-tex-visitor
The two plugins provide default templates for their output format. You can see them in the relative repositories
- Mau HTML visitor: https://github.com/Project-Mau/mau-html-visitor
- Mau TeX visitor: https://github.com/Project-Mau/mau-tex-visitor
Template plugins
Mau supports plugins that only add templates, such as mau-docs-templates
(link). Such plugins provide only template files, without a specific visitor.
The templates provided by the plugin can be used directly as they are loaded by visitors, or can be included in your own templates using Jinja extend
or include
.