1from importlib import import_module
2from typing import TYPE_CHECKING, Dict, Protocol, Union, cast
3
4if TYPE_CHECKING:
5 from ..markdown import Markdown
6
7_plugins = {
8 "speedup": "mistune.plugins.speedup.speedup",
9 "strikethrough": "mistune.plugins.formatting.strikethrough",
10 "mark": "mistune.plugins.formatting.mark",
11 "insert": "mistune.plugins.formatting.insert",
12 "superscript": "mistune.plugins.formatting.superscript",
13 "subscript": "mistune.plugins.formatting.subscript",
14 "footnotes": "mistune.plugins.footnotes.footnotes",
15 "table": "mistune.plugins.table.table",
16 "url": "mistune.plugins.url.url",
17 "abbr": "mistune.plugins.abbr.abbr",
18 "def_list": "mistune.plugins.def_list.def_list",
19 "math": "mistune.plugins.math.math",
20 "ruby": "mistune.plugins.ruby.ruby",
21 "task_lists": "mistune.plugins.task_lists.task_lists",
22 "spoiler": "mistune.plugins.spoiler.spoiler",
23}
24
25
26class Plugin(Protocol):
27 def __call__(self, md: "Markdown") -> None: ...
28
29
30_cached_modules: Dict[str, Plugin] = {}
31
32PluginRef = Union[str, Plugin] # reference to register a plugin
33
34
35def import_plugin(name: PluginRef) -> Plugin:
36 if callable(name):
37 return name
38
39 if name in _cached_modules:
40 return _cached_modules[name]
41
42 if name in _plugins:
43 module_path, func_name = _plugins[name].rsplit(".", 1)
44 else:
45 module_path, func_name = name.rsplit(".", 1)
46
47 module = import_module(module_path)
48 plugin = cast(Plugin, getattr(module, func_name))
49 _cached_modules[name] = plugin
50 return plugin