Package: mkdocs-plugin-daon-macros
mkdocs-macros-plugin: Unleash the power of MkDocs with variables and macrosOverviewContext and purposeSources of inspirationmkdocs-markdownextradata (rosscdh)jinja2: variables can also be Python callablesMacros in Wiki enginesUse Case: Overcoming the Intrinsic Limitations of Markdown SyntaxSolution 1: Markdown extensionsSolution 2: Custom HTML CodeSolution 3: Enter MacrosInstallationPrerequisitesProcedureHow to use itDefining variables in the configuration fileDefining variables and macros in Python codeLocation of the moduleContent of the moduleDefining local variables and macros within the markdown pageVariablesMacros and other templating toolsOverviewmkdocs-macros-pluginis a plugin to make it easier for the contributors
to aMkDocswebsite to make richer and more beautiful
pages, by usingvariablesand calls tomacrosin the markdown code.Regularvariablescan be defined in three ways:global (for contributors): in themkdocs.ymlfile,
under the 'extra' headingglobal (for programmers): in amain.pyfile (Python),
by adding them to a dictionarylocal (for contributors): in the markdown file, with a{%set variable = value %}statementSimilarly programmers can definemacros, as Python functions in themain.pyfile, which the users will then be able to
use without much difficulty inside of the Python code.With these two tools, you could write e.g.:The unit price of product A is {{ unit_price }} EUR.
Taking the standard discount into account,
the sale price of 50 units is {{ price(unit_price, 50) }} EUR.Which could translate into:The unit price of product A is 10.00 EUR.
Taking the standard discount into account,
the sale price of 50 units is 450.00 EUR.The result of a macro can beHTML code:
this makes macros especially useful
to make custom extensions to the syntax of markdown.In reality, it is possible to use the full range of facilities ofJinja2 templates.Context and purposeSources of inspirationmkdocs-markdownextradata (rosscdh)The idea for that extension came to me after I saw the excellent pluginmkdocs-markdownextradatacreated by rosscdh, which takes metadata data
from themkdocs.ymlfile,  and allows you to insert them
with double curly brackets:The price of the item is {{price}}.His concept of using thejinja2templating engine for that purpose was  simple and beautiful:
all it took for this plugin was a few lines of code.jinja2: variables can also be Python callablesAnd then I discovered that the creators of jinja2,
in their great wisdom (thanks also to them!),
had decided to supportanykind of Python variables,including the callables, typically functions, e.g.:The price of the item is {{calculate(2, 7.4)}}.They did not think it was worth more a few words,
but it was a diamond in plain sight.Oh yeah?So let's support them also in the markdown pages of MkDocs!Macros in Wiki enginesThe idea of using 'macros' to speed up the process of writing web pages
is in fact rather old.Most wiki engines,
which also rely on somemarkuplanguage, had the same problems of enriching the presentation of the pages,
at the turn of the year 2000.
In response, they often implemented macros in one form or another
(in mediawiki, they were confusingly calledtemplates).
And in many cases, these wiki engines relied on the double-curly-braces syntax.After all, astatic website generatorcan be defined as a wiki whose
online editing features have been removed, to make it "wiki-wikier"!Use Case: Overcoming the Intrinsic Limitations of Markdown SyntaxMkDocsis a powerful and simple
tool for generating websites. Pages are based on markdown, which is simple by design. The downside is that the expressiveness of markdown is
necessarily limited.What do you do if you want to enrich your web with new features like buttons,
fancy images, etc. without messing up with templates?Solution 1: Markdown extensionsIn order to express more things with it, the standard recourse is to extend
markdown through standardmarkdown extensions.
Adding extensions is straightforward, as they
can be directly activated through themkdocs.ymlconfiguration file
of the website e.g.:markdown_extensions:-footnotes(If they are non-standard, you just have to install them first on your
machine.)The problem is, however, that there willalwaysbesomethingspecific
you will want to do, for which there is no markdown extension available.
Or the extension will be too complicated, or not quite what you wanted.Furthermore, the are limitations to the number of possible extensions,
because extending the grammar of markdown is always a little tricky and
can create incompabilities with the standard syntax or other extensions.Solution 2: Custom HTML CodeIf don't have an extension, the standard recourse
is to write some pure HTML within your markdown,
which may also contain some
css code (especially if you are using css that
is specific to your theme or website), e.g.:Here is my code:<aclass='button'href="http:your.website.com/page">Try this</a>The combination of HTML and css works well and can solve a wide range of issues.But it will soon become tedious, if you have to type
the same code again and again with some variations;
and if you want to change something to the
call (typically the css class), you will then have to manually changeallinstances of that code, with all the related risks.
This solution doesn't scale.Solution 3: Enter MacrosWhat if you had amacroinstead, that would allow you to write
the above HTML as:{{button('Try this', 'http:your.website.com/page')}}... that call was translated into the proper HTML?That would be something you could teach to a person who can
already write markdown, without the need for them to get involved
inanycss or HTML!And, what's more,
you couldeasily(as a programmer) write your own new macro in Python,
whenever you needed one?Amacrois, simply stated, aPython functionthat takes a few arguments
and returns a string. It could contain all the logic you want; it could
be as simple as the example above, or as sophisticated as making a query from
a database and formatting the results as markdown.All of this becomes possible, thanks tomkdocs-macros-plugin!InstallationPrerequisitesPython version > 3.5MkDocs version > 0.17 (compatible with post 1.0 versions)Standard installationpip install mkdocs-macros-plugin"Manual installation"To install the package, download it and run:pythonsetup.pyinstallDeclaration of pluginDeclare the plugin in the the filemkdocs.yml:plugins:-search-macrosNote:If you have nopluginsentry in your config file yet,
you should also add thesearchplugin.
If nopluginsentry is set, MkDocs enablessearchby default; but
if you use it, then you have to declare it explicitly.How to use itDefining variables in the configuration fileTo easily and quickly define custom variables, declare them in youmkdocs.ymlfile:extra:price:12.50company:name:Acmeaddress:....website:www.acme.comIn 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>.Defining variables and macros in Python codeLocation of the modulePython code must go into amain.pyfile in the main website's directory
(beside themkdocs.ymlfile).In can also be a package (i.e. amaindirectory),
as long as thedeclare_variablesfunction is accessible.If you wish, you can change the name of that module by adding apython_moduleparameter to themkdocs.ymlfile
(no need to add the.pysuffix):python_module:source_codeContent of the moduleAs a first step, you need declare a hook function
calleddeclare_variables, with two arguments:variables: the dictionary that will contain your variables.macro: a decorator function that you can use to declare a Python
function as a Jinja2 callable ('macro' for MkDocs).The example should be self-explanatory:defdeclare_variables(variables,macro):"""This is the hook for the functions- variables: the dictionary that contains the variables- macro: a decorator function, to declare a macro."""variables['baz']="John Doe"@macrodefbar(x):return(2.3*x)+7# If you wish, you can  declare a macro with a different name:deff(x):returnx*xmacro(f,'barbaz')# or to export some predefined functionimportmathmacro(math.floor)# will be exported as 'floor'Here is the code for thebuttonfunction:@macro
def button(label, url):
    "Add a button"
    url = fix_url(url)
    HTML = """<a class='button' href="%s">%s</a>"""
    return HTML % (url, label)Yourregistrationof variables or macros for MkDocs
should be done inside that
hook function. On the other hand, nothing prevents you from making imports or
declarationsoutsideof this function.Note:You can export a wide range of objects, and their attributes
remain accessible (seemore information)Defining local variables and macros within the markdown pageIf you really need a variable or macro that needs to remainlocalto the markdown page,
you can use a standard Jinja2 declaration.VariablesVariables can be defined with thesetkeyword, e.g.:{% set acme = 'Acme Company Ltd' %}

Please buy the great products from {{ acme }}!Macros and other templating toolsIn fact, you can doall the fancy footwork you want with Jinja2,
including defining pure Jina2 macros, conditionals and for loops!Here is an example of macro, from the official Jinja2 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>Only remember that you don't need to define any header, footer or navigation,
as this is already taken care of by MkDocs.
Also, all definitions will remainlocalto the page.