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 cluster_on_startup on_startup cluster_build build cluster_on_config on_config cluster_on_pre_build on_pre_build cluster_on_files on_files cluster_on_nav on_nav cluster_populate_page populate_page cluster_on_pre_page on_pre_page cluster_on_page_read_source on_page_read_source cluster_on_page_markdown on_page_markdown cluster_on_page_content on_page_content cluster_on_env on_env cluster_populate_page_2 populate_page cluster_populate_page_3 populate_page cluster_build_page build_page cluster_on_page_context on_page_context cluster_on_post_page on_post_page cluster_build_page_2 build_page cluster_build_page_3 build_page cluster_on_post_build on_post_build cluster_on_serve on_serve cluster_on_shutdown on_shutdown on_startup command dirty load_config load_config on_config config on_pre_build config on_config:s->on_pre_build:n get_files get_files on_config:s->get_files on_files files config on_nav nav config files on_files:s->on_nav:n get_nav get_nav on_files:s->get_nav render_p render pages_point_a on_nav:s->pages_point_a get_context get_context on_nav:s->get_context load_config->on_config:n get_files->on_files:n get_nav->on_nav:n on_pre_page page config files on_page_read_source page config on_pre_page:s->on_page_read_source:n on_page_markdown markdown page config files on_page_read_source:s->on_page_markdown:n on_page_markdown:s->render_p on_page_content html page config files pages_point_b on_page_content:s->pages_point_b on_env env config files render_p->on_page_content:n pages_point_a->on_pre_page:n pages_point_a->render_p placeholder_cluster_populate_page_2 ... pages_point_a->placeholder_cluster_populate_page_2:n placeholder_cluster_populate_page_3 ... pages_point_a->placeholder_cluster_populate_page_3:n placeholder_cluster_populate_page_2:s->pages_point_b pages_point_b->on_env:n pages_point_c pages_point_b->pages_point_c placeholder_cluster_populate_page_3:s->pages_point_b on_env:s->get_context on_page_context context page config nav pages_point_c->on_page_context:n placeholder_cluster_build_page_2 ... pages_point_c->placeholder_cluster_build_page_2:n placeholder_cluster_build_page_3 ... pages_point_c->placeholder_cluster_build_page_3:n render render on_page_context:s->render on_post_page output page config write_file write_file on_post_page:s->write_file get_context->on_page_context:n render->on_post_page:n get_template get_template get_template->render on_post_build config on_serve server config on_shutdown


一次性事件

一次性事件在每次 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:

全局事件

全局事件在每次构建过程中只调用一次,无论是在构建过程的开始还是结束。在这些事件中所做的任何更改都将对整个站点产生全局影响。

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:

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:

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 a File inside on_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:

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),其中 SomePluginClassBasePlugin 的子类,定义了插件的行为。自然地,多个插件类可以存在于同一个模块中。只需为每个插件定义一个单独的入口点。

entry_points={
    'mkdocs.plugins': [
        'featureA = path.to.my_plugins:PluginA',
        'featureB = path.to.my_plugins:PluginB'
    ]
}

请注意,注册插件并不会激活它。用户仍然需要通过配置告诉 MkDocs 使用它。

发布插件

您应该在 PyPI 上发布一个包,然后将其添加到 Catalog 中以提高可发现性。强烈建议插件根据目录拥有一个唯一的插件名称(入口点名称)。