-
-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compatibility with mkdocs-macros
#615
Comments
This has been discussed several times already, let me try to find the relevant discussions. In short, while you wait: it's not possible without hacks. mkdocs-macros and mkdocstrings work at different levels: mkdocs-macros at the plugin level (in something like the |
OK, I did search for |
OK I was thinking about this one: #441.
To expand a bit, the idea here is to:
|
Ah, sorry, I missed searching the discussions. So, it is hard to do but possible if I understand correctly? |
I think it's possible yes. Based on https://mkdocs-macros-plugin.readthedocs.io/en/latest/macros/#manipulating-the-mkdocs-configuration-information, it looks like one could do the following: def define_env(env):
# get the Jinja environment of mkdocstrings' Python handler
python_env = env.config["plugins"]["mkdocstrings"].get_handler("python").env
# get the `convert_markdown` filter of the Python handler
convert_markdown = python_env.filters["convert_markdown"]
# get the `render` method of the macros plugin
macros_render = env.config["plugins"]["macros"].render
# build a chimera made of both
def render_convert(markdown: str, *args, **kwargs):
return convert_markdown(macros_render(markdown), *args, **kwargs)
# override the original `convert_markdown` filter
python_env.filters["convert_markdown"] = render_convert Not tested! Tagging @fralau because it's exciting 😂 |
Yes it is exciting. 😄 I asked DallE to draw a chimera between an mkdocs extension and an mkdocs plugin. Kinda cool: We had conversation on MkDocs/Community on 22 August, on the order of events, and we refered to this diagram. The key is that mkdocstrings is an extension, and MkdocsMacros is a plugin. Here us a table giving the relationship of MkDocs-Macros with MkDocs events. @pawamoy It would be a good idea to include the import statements, for the guys like me who are a little less familiar with mkdocstrings? |
So cool haha! 😀 What do you mean by including the import statements 🤔? |
Here is the indication that @squidfunk had given me:
So that's after MkDocMacros has executed. 🤔 So yes, the solution would be to capture the output of MkdocsString before it MkDocs-Macros goes through. A solution would be to make a macro, of course, or rather a filter. But since At that point the Jinja2 should already be operational (minus the page variables, but we don't need them anyway). You would have to go through all your files produced by MkdocsString and produce a rendered copy of them. I am not sure what will happen if trying to execute |
Amazing, good to hear! I guess the chimera wasn't ready for public consumption, but I was too eager so I tried out, and sadly it didn't work. I had to change Chimera failing...
|
@llucax thanks for testing! Try putting |
|
@llucax hmmm yes, I should have expected that. This filter is only created once the Markdown conversion process has started, because it needs access to the current def define_env(env):
# get mkdocstrings' Python handler
python_handler = env.config["plugins"]["mkdocstrings"].get_handler("python")
# get the `render` method of the macros plugin
macros_render = env.config["plugins"]["macros"].render
# get the `update_env` method of the Python handler
update_env = python_handler.update_env
# patch the `update_env` method of the Python handler
def patched_update_env(self, md, config):
update_env(md, config)
# get the `convert_markdown` filter of the env
convert_markdown = self.env.filters["convert_markdown"]
# build a chimera made of macros+mkdocstrings
def render_convert(markdown: str, *args, **kwargs):
return convert_markdown(macros_render(markdown), *args, **kwargs)
# patch the filter
self.env.filters["convert_markdown"] = render_convert
# patch the method
python_handler.update_env = patched_update_env Something like this 🥵 |
I had to fix again
(I need to leave now, will be able to do some more testing tomorrow) |
OK I've ran some tests and this is working now 😄 def define_env(env):
@env.macro
def is_it_working():
return '!!! success "WORKING"'
# get mkdocstrings' Python handler
python_handler = env.conf["plugins"]["mkdocstrings"].get_handler("python")
# get the `update_env` method of the Python handler
update_env = python_handler.update_env
# override the `update_env` method of the Python handler
def patched_update_env(md, config):
update_env(md, config)
# get the `convert_markdown` filter of the env
convert_markdown = python_handler.env.filters["convert_markdown"]
# build a chimera made of macros+mkdocstrings
def render_convert(markdown: str, *args, **kwargs):
return convert_markdown(env.render(markdown), *args, **kwargs)
# patch the filter
python_handler.env.filters["convert_markdown"] = render_convert
# patch the method
python_handler.update_env = patched_update_env Example module docstring: """Debugging utilities.
{{ is_it_working() }}
""" ...getting properly rendered to: |
Ah, I think I am finally catching up. So you are modifying the mkdocstrings' Python handler, and basically decorating it with That's bold wizardry. 🫡 When you are happy with it, maybe you want to package that into a pluglet for mkdocs-macros, so that anybody could use it? I would gladly put a reference to it in Mkdocs-Macros doc. |
Sorry @fralau I wanted to try and write a better explanation of what we were trying to achieve. If you got it by looking at my final code snippet, that works too! |
@pawamoy Amazing that you got it working. I tried it, and now Update: Oh, no it does! I guess I had some copy&paste error! Amazing! 🎉 |
According to @pawamoy: > `mkdocs-macros` and `mkdocstrings` work at different levels: > `mkdocs-macros` at the plugin level (in something like the > `on_page_markdown` hook) while `mkdocstrings` renders docstrings at > the Markdown conversion level, so in-between `on_page_markdown` and > `on_page_content`. That means `mkdocs-macros` never sees the > docstrings. To fix this, we can implement a hack to plug both together in the `define_env()` function for `mkdocs-macros`. Eventually a `mkdocs-macros` *pluglet* might be implemented so that this hack is not necessary anymore. For more context see: * mkdocstrings/mkdocstrings#615 Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
@fralau I'd like to refactor mkdocstrings a bit to make the patching easier (ideally refactor so that no patching is necessary), and then I'd be happy to provide a pluglet, yes! |
According to @pawamoy: > `mkdocs-macros` and `mkdocstrings` work at different levels: > `mkdocs-macros` at the plugin level (in something like the > `on_page_markdown` hook) while `mkdocstrings` renders docstrings at > the Markdown conversion level, so in-between `on_page_markdown` and > `on_page_content`. That means `mkdocs-macros` never sees the > docstrings. To fix this, we can implement a hack to plug both together in the `define_env()` function for `mkdocs-macros`. Eventually a `mkdocs-macros` *pluglet* might be implemented so that this hack is not necessary anymore. For more context see: * mkdocstrings/mkdocstrings#615 Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
According to @pawamoy: > `mkdocs-macros` and `mkdocstrings` work at different levels: `mkdocs-macros` at the plugin level (in something like the `on_page_markdown` hook) while `mkdocstrings` renders docstrings at the Markdown conversion level, so in-between `on_page_markdown` and `on_page_content`. That means `mkdocs-macros` never sees the docstrings. To fix this, we can implement a hack to plug both together in the `define_env()` function for `mkdocs-macros`. Eventually a `mkdocs-macros` *pluglet* might be implemented so that this hack is not necessary anymore. For more context see: * mkdocstrings/mkdocstrings#615
@pawamoy just chiming in that it would be great to have some way to hook into the Code
At least for the suggestion:
Would it make sense to add a mkdocstrings option for some hook to call? Or maybe better, could mkdocstrings look in the standard
|
Hey @larsoner, sorry for the late answer.
It's actually exposed: def on_pre_build(config: MkDocsConfig) -> None:
"""Monkey patch mkdocstrings-python jinja template to have global vars."""
python_handler = config["plugins"]["mkdocstrings"].get_handler("python")
python_handler.env.globals["pipeline_steps"] = _ParseConfigSteps() The point of patching |
Is your feature request related to a problem? Please describe.
To be able to write more powerful documentation and avoid repetition, it is very useful to use the
mkdocs-macros
plugin, but it seems the documentation written inside docstrings is not being processed by the macros plugin.Describe the solution you'd like
It would be nice if there is a way to make mkdocstrings extract the docstrings before the macros plugin runs, so macros can be expanded also inside the documentation hosted in docstrings.
Describe alternatives you've considered
None really, just avoid using the macros plugin.
Additional context
I could show a way I'm using the macros plugin, but I guess it is irrelevant, as there are many many uses for it, like showing the current git tag, etc.
The text was updated successfully, but these errors were encountered: