Skip to content

Commit 4fcd265

Browse files
author
Laurent Franceschetti
committed
Add on_post_build() function to macros' code
- Added documentation, under "Advanced usage"
1 parent 974b87e commit 4fcd265

File tree

3 files changed

+159
-28
lines changed

3 files changed

+159
-28
lines changed

mkdocs_macros/plugin.py

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
import yaml
1515
from jinja2 import Environment, FileSystemLoader
1616
from mkdocs.plugins import BasePlugin
17+
from mkdocs.config import config_options
1718
from mkdocs.config.config_options import Type as PluginType
1819

20+
1921
from .util import trace, debug, update, SuperDict, import_local_module, format_chatter, LOG
2022
from .context import define_env
2123

@@ -64,6 +66,35 @@ class MacrosPlugin(BasePlugin):
6466
)
6567

6668

69+
def start_chatting(self, prefix:str, color:str='yellow'):
70+
"Generate a chatter function (trace for macros)"
71+
def chatter(*args):
72+
"""
73+
Defines a tracer for the Verbose mode, to be used in macros.
74+
If `verbose: true` in the YAML config file (under macros plugin),
75+
it will start "chattering"
76+
(talking a lot and in a friendly way,
77+
about mostly unimportant things).
78+
Otherwise, it will remain silent.
79+
80+
If you change the `verbose` while the local server is activated,
81+
(`mkdocs server`) this should be instantly reflected.
82+
83+
Usage:
84+
-----
85+
chatter = env.make_chatter('MY_MODULE_NAME')
86+
chatter("This is a dull debug message.")
87+
88+
Will result in:
89+
90+
INFO - [macros - Simple module] - This is a dull info message.
91+
"""
92+
if self.config['verbose']:
93+
LOG.info(format_chatter(*args, prefix=prefix, color=color))
94+
95+
return chatter
96+
97+
6798
# ------------------------------------------------
6899
# These properties are available in the env object
69100
# ------------------------------------------------
@@ -168,6 +199,19 @@ def reverse(x):
168199
return v
169200

170201

202+
@property
203+
def post_build_functions(self):
204+
"""
205+
List of post build functions contained in modules.
206+
These are deferred to the on_post_build() event.
207+
"""
208+
try:
209+
return self._post_build_functions
210+
except AttributeError:
211+
raise AttributeError("You have called post_build_functions property "
212+
"too early. Does not exist yet !")
213+
214+
171215
# ----------------------------------
172216
# load elements
173217
# ----------------------------------
@@ -216,6 +260,8 @@ def foobar(x):
216260
...
217261
218262
"""
263+
self._post_build_functions = []
264+
219265
# installed modules (as in pip list)
220266
modules = self.config['modules']
221267
if modules:
@@ -252,6 +298,12 @@ def foobar(x):
252298
"module '%s'. Prefer the define_env() function "
253299
"(see documentation)!" % local_module_name)
254300
function_found = True
301+
if hasattr(module, 'on_post_build'):
302+
# append the module to the list of functions
303+
# `on_post_build_functions`
304+
# NOTE: each of these functions requires
305+
# self (the environment).
306+
self._post_build_functions.append(module.on_post_build)
255307
if not function_found:
256308
raise NameError("No valid function found in module '%s'" %
257309
local_module_name)
@@ -457,30 +509,10 @@ def on_page_markdown(self, markdown, page, config,
457509
self.variables["page"] = page
458510
return self.render(markdown)
459511

460-
def start_chatting(self, prefix:str, color:str='yellow'):
461-
"Generate a chatter function"
462-
def chatter(*args):
463-
"""
464-
Defines a tracer for the Verbose mode, to be used in macros.
465-
If `verbose: true` in the YAML config file (under macros plugin),
466-
it will start "chattering"
467-
(talking a lot and in a friendly way, about mostly unimportant things).
468-
Otherwise, it will remain silent.
469-
470-
If you change the `verbose` while the local server is activated,
471-
(`mkdocs server`) this should be instantly reflected.
472-
473-
Usage:
474-
-----
475-
chatter = env.make_chatter('MY_MODULE_NAME')
476-
chatter("This is a dull debug message.")
477-
478-
Will result in:
479-
480-
INFO - [macros - Simple module] - This is a dull info message.
481-
"""
482-
if self.config['verbose']:
483-
LOG.info(format_chatter(*args, prefix=prefix, color=color))
484-
485-
return chatter
486-
512+
def on_post_build(self, config: config_options.Config):
513+
"""
514+
Hook for post build actions, typically adding
515+
raw files to the setup.
516+
"""
517+
for func in self.post_build_functions:
518+
func(self)

test/module/main.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,12 @@ def button(label, url):
4949
return HTML % (url, label)
5050

5151

52-
env.variables.special_docs_dir = env.variables.config['docs_dir']
52+
env.variables.special_docs_dir = env.variables.config['docs_dir']
53+
54+
55+
56+
def on_post_build(env):
57+
"Post build action"
58+
# activate trace
59+
chatter = env.start_chatting("Simple module (post-build)")
60+
chatter("This means `on_post_build(env)` works")

webdoc/docs/advanced.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,94 @@ You may, of course, chose the combination that best suits your needs.
305305
of trouble, please do not expect help from the maintainers of this
306306
plugin.
307307

308+
## Adding post-build files to the HTML website
309+
310+
_From version 0.5_
311+
312+
### Use case
313+
314+
Sometimes, you want your Python code to add some files to the HTML website that
315+
MkDocs is producing.
316+
317+
These could be:
318+
319+
- an extra HTML page
320+
- an additional or updated image
321+
- a RSS feed
322+
- a form processor (written for example in the php language)
323+
- ....
324+
325+
!!! Tip
326+
The logical idea is to add files to the site (HTML) directory,
327+
which is given by `env.conf['site_dir']`.
328+
329+
!!! Note "Beware the of the 'disappeared file' trap"
330+
331+
One problem will occur if you attempt to add files to the site directory
332+
from within the `define_env()` function in your macro module.
333+
334+
**The file will be created, but nevertheless it is going to "disappear".**
335+
336+
The reason is that the code of `define_env()` is executed during the
337+
`on_config` event of MkDocs; **and you can expect the site directory
338+
to be wiped out later, during the build phase (which produces
339+
the HTML files)**. So, of course, the files you
340+
just created will be deleted.
341+
342+
343+
### Solution: Post-Build Actions
344+
345+
346+
347+
The solution to do that, is to perform those additions
348+
as **post-build** actions (i.e. executed with `on_post_build` event).
349+
350+
Here is an example. Suppose you want to add a special file (e.g. HTML).
351+
352+
```Python
353+
import os
354+
MY_FILENAME = 'foo.html'
355+
my_HTML = None
356+
357+
def define_env(env):
358+
"Definition of the module"
359+
360+
# put here your HTML content
361+
my_HTML = ......
362+
363+
364+
def on_post_build(env):
365+
"Post-build actions"
366+
367+
site_dir = env.conf['site_dir']
368+
file_path = os.path.join(site_dir, MY_FILENAME)
369+
with open(file_path, 'w') as f:
370+
f.write(my_HTML)
371+
```
372+
373+
The mkdocs-macros plugin will pick up that function and execute it during
374+
as on `on_post_build()` action.
375+
376+
!!! Warning "Argument of `on_post_build()`"
377+
In this case, the argument is `env` (as for `define_env()`);
378+
it is **not**
379+
`config` as in the `on_post_build()` method in an MkDocs plugin.
380+
381+
If you want to get the plugin's arguments, you can find them in the
382+
`env.conf` dictionary.
383+
384+
!!! Note "Global variables"
385+
To facilitate the communication between `define_env()` and
386+
`on_post_build` you may want to define **global variables** within
387+
your module (in this example: `MY_FILENAME` and `my_HTML`).
388+
389+
!!! Warning
390+
Do not forget that any variable assigned for the first time
391+
within a function is _by default_
392+
a **local** variable: its content will be lost once the function
393+
is fully executed.
394+
395+
In the example above, `my_HTML` **must** appear in the global definitions;
396+
which is why it was assigned an empty value.
397+
398+

0 commit comments

Comments
 (0)