MkDocs 插件
安装、使用和创建 MkDocs 插件的指南
安装插件
在使用插件之前,必须将其安装在系统上。如果你使用的是 MkDocs 自带的插件,那么在你安装 MkDocs 时就已经安装了这些插件。然而,要安装第三方插件,你需要确定相应的包名,并使用 pip
进行安装:
pip install mkdocs-foo-plugin
警告:安装 MkDocs 插件意味着安装一个 Python 包并执行作者放置在那里的任何代码。因此,请保持通常的谨慎;这里没有尝试进行沙箱化。
一旦插件成功安装,它就可以使用了。只需在配置文件中启用即可。Catalog 仓库有一个大型排序列表,你可以从中安装和使用插件。
使用插件
plugins
配置选项应包含一个在构建站点时要使用的插件列表。每个“插件”必须是一个分配给插件的字符串名称(参见特定插件的文档以确定其“名称”)。此处列出的插件必须已经安装。
plugins:
- search
一些插件可能提供了自己的配置选项。如果你想设置任何配置选项,那么你可以嵌套一个键/值映射(option_name: option value
),其中包含给定插件支持的任何选项。请注意,冒号(:
)必须跟随插件名称,然后在下一行中,选项名称和值必须缩进并用冒号分隔。如果你想为一个插件定义多个选项,每个选项必须在单独的行上定义。
plugins:
- search:
lang: en
foo: bar
有关特定插件可用的配置选项的信息,请参阅该插件的文档。
有关默认插件列表以及如何覆盖它们的信息,请参阅配置文档。
开发插件
与 MkDocs 一样,插件必须用 Python 编写。通常期望每个插件作为一个单独的 Python 模块分发,尽管可以在同一个模块中定义多个插件。至少,一个 MkDocs 插件必须包含一个 BasePlugin 子类和一个指向它的[入口点]。
BasePlugin
mkdocs.plugins.BasePlugin
的子类应定义插件的行为。该类通常包含在构建过程中特定事件上执行的操作以及插件的配置方案。
所有 BasePlugin
子类包含以下属性:
config_scheme
一个配置验证实例的元组。每个项目必须由一个两项元组组成,其中第一项是配置选项的字符串名称,第二项是 mkdocs.config.config_options.BaseConfigOption
或其任何子类的实例。
例如,以下 config_scheme
定义了三个配置选项:foo
,接受一个字符串;bar
,接受一个整数;和 baz
,接受一个布尔值。
class MyPlugin(mkdocs.plugins.BasePlugin):
config_scheme = (
('foo', mkdocs.config.config_options.Type(str, default='a default value')),
('bar', mkdocs.config.config_options.Type(int, default=0)),
('baz', mkdocs.config.config_options.Type(bool, default=True))
)
新功能:在版本 1.4 中新增。
通过子类化
Config
来指定配置模式为了获得类型安全的好处,如果你只针对 MkDocs 1.4+,请将配置模式定义为一个类:
class MyPluginConfig(mkdocs.config.base.Config): foo = mkdocs.config.config_options.Type(str, default='a default value') bar = mkdocs.config.config_options.Type(int, default=0) baz = mkdocs.config.config_options.Type(bool, default=True) class MyPlugin(mkdocs.plugins.BasePlugin[MyPluginConfig]): ...
配置定义示例
! 示例:
from mkdocs.config import base, config_options as c class _ValidationOptions(base.Config): enabled = c.Type(bool, default=True) verbose = c.Type(bool, default=False) skip_checks = c.ListOfItems(c.Choice(('foo', 'bar', 'baz')), default=[]) class MyPluginConfig(base.Config): definition_file = c.File(exists=True) # 必需 checksum_file = c.Optional(c.File(exists=True)) # 可以是 None,但如果指定则必须存在 validation = c.SubConfig(_ValidationOptions)
从用户的角度来看,
SubConfig
类似于Type(dict)
,只是它还保留了完全的验证能力:你定义所有有效的键以及每个值应遵循的内容。而
ListOfItems
类似于Type(list)
,但我们再次定义了每个值必须遵循的约束。这接受如下配置:
my_plugin: definition_file: configs/test.ini # 相对于 mkdocs.yml validation: enabled: !ENV [CI, false] verbose: true skip_checks: - foo - baz
? 示例:
import numbers from mkdocs.config import base, config_options as c class _Rectangle(base.Config): width = c.Type(numbers.Real) # 必需 height = c.Type(numbers.Real) # 必需 class MyPluginConfig(base.Config): add_rectangles = c.ListOfItems(c.SubConfig(_Rectangle)) # 必需
在这个示例中,我们定义了一个复杂项的列表,这是通过将具体的
SubConfig
传递给ListOfItems
实现的。这接受如下配置:
my_plugin: add_rectangles: - width: 5 height: 7 - width: 12 height: 2
当用户的配置被加载时,上述方案将用于验证配置并为未由用户提供的设置填充默认值。验证类可以是 mkdocs.config.config_options
中提供的任何类,或者是插件中定义的第三方子类。
用户提供的任何未通过验证或在 config_scheme
中未定义的设置将引发 mkdocs.config.base.ValidationError
。
config
一个包含插件配置选项的字典,在配置验证完成后由 load_config
方法填充。使用此属性访问用户提供的选项。
def on_pre_build(self, config, **kwargs):
if self.config['baz']:
# 在此处实现 "baz" 功能...
新增:在版本 1.4 中新增。
安全的基于属性的访问
为了获得类型安全的好处,如果你只针对 MkDocs 1.4+,请将选项作为属性访问:
def on_pre_build(self, config, **kwargs): if self.config.baz: print(self.config.bar ** 2) # 可以,`int ** 2` 是有效的。
所有 BasePlugin
子类包含以下方法:
load_config(options)
从选项字典加载配置。返回一个 (errors, warnings)
的元组。此方法在配置验证期间由 MkDocs 调用,插件不需要调用它。
on_<event_name>()
可选方法,定义特定[事件]的行为。插件应在这些方法中定义其行为。将 <event_name>
替换为事件的实际名称。例如,pre_build
事件将在 on_pre_build
方法中定义。
大多数事件接受一个位置参数和各种关键字参数。通常期望位置参数会被插件修改(或替换)并返回。如果没有返回任何内容(方法返回 None
),则使用原始的、未修改的对象。关键字参数仅提供上下文和/或提供可能用于确定如何修改位置参数的数据。接受关键字参数作为 **kwargs
是一个好习惯。在 MkDocs 的未来版本中,如果为事件提供了额外的关键字,则无需修改你的插件。
例如,以下事件将向主题配置添加一个额外的 static_template:
class MyPlugin(BasePlugin):
def on_config(self, config, **kwargs):
config['theme'].static_templates.add('my_template.html')
return config
新增:在版本 1.4 中新增。
为了获得类型安全的好处,如果你只针对 MkDocs 1.4+,请将配置选项作为属性访问:
def on_config(self, config: MkDocsConfig): config.theme.static_templates.add('my_template.html') return config
事件
有三种类型的事件:[全局事件]、[页面事件]和[模板事件]。
查看所有插件事件之间关系的图表
- 事件本身以黄色显示,带有它们的参数。
- 箭头显示每个事件的参数和输出的流向。有时它们被省略。
- 事件按时间顺序从上到下排列。
- 虚线出现在从全局事件到每页事件的分裂处。
- 点击事件标题跳转到它们的描述。
一次性事件
一次性事件在每次 mkdocs
调用时运行一次。这些与全局事件的唯一区别在于 mkdocs serve
的情况:全局事件与这些不同,它们会运行多次——每次构建一次。
on_startup
The startup
event runs once at the very beginning of an mkdocs
invocation.
New in MkDocs 1.4.
The presence of an on_startup
method (even if empty) migrates the plugin to the new
system where the plugin object is kept across builds within one mkdocs serve
.
Note that for initializing variables, the __init__
method is still preferred.
For initializing per-build variables (and whenever in doubt), use the on_config
event.
Parameters:
-
command
(Literal['build', 'gh-deploy', 'serve']
) –the command that MkDocs was invoked with, e.g. "serve" for
mkdocs serve
. -
dirty
(bool
) –whether
--dirty
flag was passed.
on_shutdown
The shutdown
event runs once at the very end of an mkdocs
invocation, before exiting.
This event is relevant only for support of mkdocs serve
, otherwise within a
single build it's undistinguishable from on_post_build
.
New in MkDocs 1.4.
The presence of an on_shutdown
method (even if empty) migrates the plugin to the new
system where the plugin object is kept across builds within one mkdocs serve
.
Note the on_post_build
method is still preferred for cleanups, when possible, as it has
a much higher chance of actually triggering. on_shutdown
is "best effort" because it
relies on detecting a graceful shutdown of MkDocs.
on_serve
The serve
event is only called when the serve
command is used during
development. It runs only once, after the first build finishes.
It is passed the Server
instance which can be modified before
it is activated. For example, additional files or directories could be added
to the list of "watched" files for auto-reloading.
Parameters:
-
server
(LiveReloadServer
) –livereload.Server
instance -
config
(MkDocsConfig
) –global configuration object
-
builder
(Callable
) –a callable which gets passed to each call to
server.watch
Returns:
-
LiveReloadServer | None
–livereload.Server
instance
全局事件
全局事件在每次构建过程中只调用一次,无论是在构建过程的开始还是结束。在这些事件中所做的任何更改都将对整个站点产生全局影响。
on_config
The config
event is the first event called on build and is run immediately
after the user configuration is loaded and validated. Any alterations to the
config should be made here.
Parameters:
-
config
(MkDocsConfig
) –global configuration object
Returns:
-
MkDocsConfig | None
–global configuration object
on_pre_build
The pre_build
event does not alter any variables. Use this event to call
pre-build scripts.
Parameters:
-
config
(MkDocsConfig
) –global configuration object
on_files
The files
event is called after the files collection is populated from the
docs_dir
. Use this event to add, remove, or alter files in the
collection. Note that Page objects have not yet been associated with the
file objects in the collection. Use Page Events to manipulate page
specific data.
Parameters:
-
files
(Files
) –global files collection
-
config
(MkDocsConfig
) –global configuration object
Returns:
-
Files | None
–global files collection
on_nav
The nav
event is called after the site navigation is created and can
be used to alter the site navigation.
Parameters:
-
nav
(Navigation
) –global navigation object
-
config
(MkDocsConfig
) –global configuration object
-
files
(Files
) –global files collection
Returns:
-
Navigation | None
–global navigation object
on_env
The env
event is called after the Jinja template environment is created
and can be used to alter the
Jinja environment.
Parameters:
-
env
(Environment
) –global Jinja environment
-
config
(MkDocsConfig
) –global configuration object
-
files
(Files
) –global files collection
Returns:
-
Environment | None
–global Jinja Environment
on_post_build
The post_build
event does not alter any variables. Use this event to call
post-build scripts.
Parameters:
-
config
(MkDocsConfig
) –global configuration object
on_build_error
The build_error
event is called after an exception of any kind
is caught by MkDocs during the build process.
Use this event to clean things up before MkDocs terminates. Note that any other
events which were scheduled to run after the error will have been skipped. See
Handling Errors for more details.
Parameters:
-
error
(Exception
) –exception raised
模板事件
模板事件针对每个非页面模板调用一次。每个模板事件将对extra_templates配置设置中定义的每个模板以及主题中定义的任何static_templates调用。所有模板事件都在env事件之后和任何[页面事件]之前调用。
on_pre_template
The pre_template
event is called immediately after the subject template is
loaded and can be used to alter the template.
Parameters:
-
template
(Template
) –a Jinja2 Template object
-
template_name
(str
) –string filename of template
-
config
(MkDocsConfig
) –global configuration object
Returns:
-
Template | None
–a Jinja2 Template object
on_template_context
The template_context
event is called immediately after the context is created
for the subject template and can be used to alter the context for that specific
template only.
Parameters:
-
context
(TemplateContext
) –dict of template context variables
-
template_name
(str
) –string filename of template
-
config
(MkDocsConfig
) –global configuration object
Returns:
-
TemplateContext | None
–dict of template context variables
on_post_template
The post_template
event is called after the template is rendered, but before
it is written to disc and can be used to alter the output of the template.
If an empty string is returned, the template is skipped and nothing is is
written to disc.
Parameters:
-
output_content
(str
) –output of rendered template as string
-
template_name
(str
) –string filename of template
-
config
(MkDocsConfig
) –global configuration object
Returns:
-
str | None
–output of rendered template as string
页面事件
页面事件针对站点中包含的每个Markdown页面调用一次。所有页面事件都在post_template事件之后和post_build事件之前调用。
on_pre_page
The pre_page
event is called before any actions are taken on the subject
page and can be used to alter the Page
instance.
Parameters:
-
page
(Page
) –mkdocs.structure.pages.Page
instance -
config
(MkDocsConfig
) –global configuration object
-
files
(Files
) –global files collection
Returns:
-
Page | None
–mkdocs.structure.pages.Page
instance
on_page_read_source
Deprecated
Instead of this event, prefer one of these alternatives:
- Since MkDocs 1.6, instead set
content_bytes
/content_string
of aFile
insideon_files
. - Usually (although it's not an exact alternative),
on_page_markdown
can serve the same purpose.
The on_page_read_source
event can replace the default mechanism to read
the contents of a page's source from the filesystem.
Parameters:
-
page
(Page
) –mkdocs.structure.pages.Page
instance -
config
(MkDocsConfig
) –global configuration object
Returns:
-
str | None
–The raw source for a page as unicode string. If
None
is returned, the default loading from a file will be performed.
on_page_markdown
The page_markdown
event is called after the page's markdown is loaded
from file and can be used to alter the Markdown source text. The meta-
data has been stripped off and is available as page.meta
at this point.
Parameters:
-
markdown
(str
) –Markdown source text of page as string
-
page
(Page
) –mkdocs.structure.pages.Page
instance -
config
(MkDocsConfig
) –global configuration object
-
files
(Files
) –global files collection
Returns:
-
str | None
–Markdown source text of page as string
on_page_content
The page_content
event is called after the Markdown text is rendered to
HTML (but before being passed to a template) and can be used to alter the
HTML body of the page.
Parameters:
-
html
(str
) –HTML rendered from Markdown source as string
-
page
(Page
) –mkdocs.structure.pages.Page
instance -
config
(MkDocsConfig
) –global configuration object
-
files
(Files
) –global files collection
Returns:
-
str | None
–HTML rendered from Markdown source as string
on_page_context
The page_context
event is called after the context for a page is created
and can be used to alter the context for that specific page only.
Parameters:
-
context
(TemplateContext
) –dict of template context variables
-
page
(Page
) –mkdocs.structure.pages.Page
instance -
config
(MkDocsConfig
) –global configuration object
-
nav
(Navigation
) –global navigation object
Returns:
-
TemplateContext | None
–dict of template context variables
on_post_page
The post_page
event is called after the template is rendered, but
before it is written to disc and can be used to alter the output of the
page. If an empty string is returned, the page is skipped and nothing is
written to disc.
Parameters:
-
output
(str
) –output of rendered template as string
-
page
(Page
) –mkdocs.structure.pages.Page
instance -
config
(MkDocsConfig
) –global configuration object
Returns:
-
str | None
–output of rendered template as string
事件优先级
对于每种事件类型,插件的相应方法按照插件在plugins
[配置][]中出现的顺序调用。
自MkDocs 1.4起,插件可以选择为其事件设置优先级值。优先级较高的事件首先被调用。未选择优先级的事件默认值为0。具有相同优先级的事件按照它们在配置中出现的顺序排列。
mkdocs.plugins.event_priority(priority: float) -> Callable[[T], T]
A decorator to set an event priority for an event handler method.
Recommended priority values:
100
"first", 50
"early", 0
"default", -50
"late", -100
"last".
As different plugins discover more precise relations to each other, the values should be further tweaked.
Usage example:
@plugins.event_priority(-100) # Wishing to run this after all other plugins' `on_files` events.
def on_files(self, files, config, **kwargs):
...
New in MkDocs 1.4. Recommended shim for backwards compatibility:
try:
from mkdocs.plugins import event_priority
except ImportError:
event_priority = lambda priority: lambda f: f # No-op fallback
新增: 自版本1.6起新增
有时可能需要在多个不同的优先级上为同一事件注册处理程序。
CombinedEvent
使得这成为可能。
mkdocs.plugins.CombinedEvent
Bases:
Generic[P, T]
A descriptor that allows defining multiple event handlers and declaring them under one event's name.
Usage example:
@plugins.event_priority(100) def _on_page_markdown_1(self, markdown: str, **kwargs): ... @plugins.event_priority(-50) def _on_page_markdown_2(self, markdown: str, **kwargs): ... on_page_markdown = plugins.CombinedEvent(_on_page_markdown_1, _on_page_markdown_2)
Note
The names of the sub-methods can't start with
on_
; instead they can start with_on_
like in the the above example, or anything else.
错误处理
MkDocs定义了四种错误类型:
mkdocs.exceptions.MkDocsException
Bases: ClickException
The base class which all MkDocs exceptions inherit from. This should not be raised directly. One of the subclasses should be raised instead.
mkdocs.exceptions.ConfigurationError
Bases: MkDocsException
This error is raised by configuration validation when a validation error is encountered. This error should be raised by any configuration options defined in a plugin's config_scheme.
mkdocs.exceptions.BuildError
Bases: MkDocsException
This error may be raised by MkDocs during the build process. Plugins should not raise this error.
mkdocs.exceptions.PluginError
Bases: BuildError
A subclass of mkdocs.exceptions.BuildError
which can be raised by plugin
events.
意外且未捕获的异常将中断构建过程并产生典型的Python回溯,这对于调试代码非常有用。然而,用户通常会发现回溯信息过于庞大,并且常常忽略有用的错误消息。因此,MkDocs将捕获上述任何错误,检索错误消息,并立即退出,仅向用户显示有用的消息。
因此,您可能希望在插件中捕获任何异常并引发PluginError
,传入您自己精心设计的自定义消息,以便构建过程以有用的消息中止。
on_build_error事件将针对任何异常触发。
例如:
from mkdocs.exceptions import PluginError
from mkdocs.plugins import BasePlugin
class MyPlugin(BasePlugin):
def on_post_page(self, output, page, config, **kwargs):
try:
# 可能会抛出 KeyError 的代码
...
except KeyError as error:
raise PluginError(f"无法通过键 '{error}' 找到项目")
def on_build_error(self, error, **kwargs):
# 清理代码
...
插件中的日志记录
为了确保您的插件日志消息符合 MkDocs 的格式和 --verbose
/--debug
标志,请将日志写入 mkdocs.plugins.
命名空间下的记录器。
示例:
import logging log = logging.getLogger(f"mkdocs.plugins.{__name__}") log.warning("文件 '%s' 未找到。如果传递了 --strict,则会导致构建中断", my_file_name) log.info("通常显示") log.debug("仅在 `--verbose` 时显示") if log.getEffectiveLevel() <= logging.DEBUG: log.debug("仅用于调试的非常昂贵的计算: %s", get_my_diagnostics())
log.error()
是另一个日志级别,其外观有所不同,但在其他方面与 warning
功能相同,因此使用它显得奇怪。如果您的插件遇到实际错误,最好的做法是通过引发 mkdocs.exceptions.PluginError
来中断构建(这也会记录一条 ERROR 消息)。
新增:自版本 1.5 起新增
MkDocs 现在提供了一个
get_plugin_logger()
便捷函数,该函数返回一个类似于上述的记录器,并且还带有插件名称的前缀。
mkdocs.plugins.get_plugin_logger(name: str) -> PrefixedLogger
Return a logger for plugins.
Parameters:
name
(str
) –The name to use with
logging.getLogger
.Returns:
PrefixedLogger
–A logger configured to work well in MkDocs, prefixing each message with the plugin package name.
Example
from mkdocs.plugins import get_plugin_logger log = get_plugin_logger(__name__) log.info("My plugin message")
入口点
插件需要打包为 Python 库(在 PyPI 上单独分发,不与 MkDocs 一起),并且每个插件都必须通过 setuptools 的 entry_points
注册为插件。将以下内容添加到您的 setup.py
脚本中:
entry_points={
'mkdocs.plugins': [
'pluginname = path.to.some_plugin:SomePluginClass',
]
}
pluginname
是用户在配置文件中使用的名称,而 path.to.some_plugin:SomePluginClass
是可导入的插件本身(from path.to.some_plugin import SomePluginClass
),其中 SomePluginClass
是 BasePlugin 的子类,定义了插件的行为。自然地,多个插件类可以存在于同一个模块中。只需为每个插件定义一个单独的入口点。
entry_points={
'mkdocs.plugins': [
'featureA = path.to.my_plugins:PluginA',
'featureB = path.to.my_plugins:PluginB'
]
}
请注意,注册插件并不会激活它。用户仍然需要通过配置告诉 MkDocs 使用它。
发布插件
您应该在 PyPI 上发布一个包,然后将其添加到 Catalog 中以提高可发现性。强烈建议插件根据目录拥有一个唯一的插件名称(入口点名称)。