-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Register custom events? #3806
Description
Use Case Overview
I'm developing a plugin system where one plugin, referred to as a Visitor, needs to interact with other plugins during the build/serve process. These other plugins, referred to as Visitable, should be able to opt into this interaction by declaring a custom event that the Visitor can trigger.
Ideal Implementation
In an ideal scenario, the implementation might look like this:
class Visitor(BasePlugin):
def on_pre_build(self, config, **kwargs):
self.plugins.run_event('visit', data={})
class Visitable(BasePlugin):
def on_visit(self, data: dict):
print("I am currently visited")Here, the Visitor plugin triggers a custom event called visit, and any Visitable plugin that defines an on_visit method would respond to this event.
Current Limitations
However, I've encountered a limitation in MkDocs that prevents this pattern from working as intended:
-
Static Event Registration: MkDocs populates the
config.plugins.eventsdictionary when the configuration is first created. Since plugins are loaded at this stage, no plugin can modify the events dictionary before MkDocs finalizes the plugin setup. This means custom events likevisitcannot be dynamically added later in the process. -
Automatic Event Registration: Methods in a
BasePluginthat start withon_are automatically registered as events by MkDocs. However, since custom events are not pre-defined in theeventsdictionary, any attempt to register them will result in failure. Essentially, allon_methods are reserved for predefined MkDocs events, leaving no room for custom ones.
To work around this, I tried manually registering a custom event:
class Foo(BasePlugin):
def on_config(self, config, **kwargs):
config.plugins.events['visit'] = []
config.plugins._register_event('visit', self._on_visit)
return config
def _on_visit(self, **kwargs):
print("I am currently visited")While this approach technically works, it feels more like a hack than a robust solution. It’s not ideal for long-term maintainability or for broader plugin development.
Proposal
I propose that MkDocs should allow custom events to be automatically registered by any plugin. To avoid potential conflicts with MkDocs' own event system, these custom events could use a unique prefix, such as on_custom_<event>, making it clear that they are user-defined.
Real-World Application
In my specific use case, I'm developing a plugin that generates a PDF book from MkDocs documentation. This plugin creates a LaTeX project that can be compiled into a PDF. I opted not to use existing Markdown-to-PDF converters like Pandoc because I wanted the system to be highly extensible, allowing other plugins to provide custom transformations for LaTeX.
For example, if a latex plugin is loaded, it could automatically trigger events such as on_latex_page, enabling other plugins to perform their tasks as they would for the HTML output. However, without support for custom events, this level of extensibility becomes difficult to achieve.
Conclusion
While my use case is somewhat specialized, I believe that enabling custom events would benefit the MkDocs plugin ecosystem as a whole. It would allow for more flexible and modular plugin designs without requiring workarounds or hacks.
What are your thoughts on this proposal?