{% endif %}
```
#### base_url
The `base_url` provides a relative path to the root of the MkDocs project. While
this can be used directly by prepending it to a local relative URL, it is best
to use the [url](#url) template filter, which is smarter about how it applies
`base_url`.
#### mkdocs_version
Contains the current MkDocs version.
#### build_date_utc
A Python datetime object that represents the date and time the documentation
was built in UTC. This is useful for showing how recently the documentation
was updated.
#### pages
A flat list of `File` objects for *all* pages in the project. This list can
contain pages not included in the global [navigation](#nav) and may not match
the order of pages within that navigation. The [page](#page) object for each
`File` can be accessed from `file.page`.
#### page
In templates which are not rendered from a Markdown source file, the `page`
variable is `None`. In templates which are rendered from a Markdown source file,
the `page` variable contains a `page` object. The same `page` objects are used
as `page` [navigation objects](#navigation-objects) in the global
[navigation](#nav) and in the [pages](#pages) template variable.
::: mkdocs.structure.pages.Page
options:
show_root_heading: false
show_root_toc_entry: true
members: []
heading_level: 4
All `page` objects contain the following attributes:
::: mkdocs.structure.pages.Page.title
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.content
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.toc
options:
show_root_full_path: false
heading_level: 5
The following example would display the top two levels of the Table of Contents
for a page.
```django
```
::: mkdocs.structure.pages.Page.meta
options:
show_root_full_path: false
heading_level: 5
In this example we define a `source` property above the page title:
```text
source: generics.py
mixins.py
# Page title
Content...
```
A template can access this metadata for the page with the `meta.source`
variable. This could then be used to link to source files related to the
documentation page.
```django
{% for filename in page.meta.source %}
{{ filename }}
{% endfor %}
```
::: mkdocs.structure.pages.Page.url
options:
show_root_full_path: false
heading_level: 5
It is expected that this be used with the [url](#url) filter to ensure the URL is relative to the current
page.
```django
{{ page.title }}
```
::: mkdocs.structure.pages.Page.file
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.abs_url
options:
show_root_full_path: false
heading_level: 5
For example, if `site_url: https://example.com/`, then the value of
`page.abs_url` for the page `foo.md` would be `/foo/`. However, if
`site_url: https://example.com/bar/`, then the value of `page.abs_url` for the
page `foo.md` would be `/bar/foo/`.
::: mkdocs.structure.pages.Page.canonical_url
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.edit_url
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.is_homepage
options:
show_root_full_path: false
heading_level: 5
This can be used in conjunction with other attributes of the `page`
object to alter the behavior. For example, to display a different title
on the homepage:
```django
{% if not page.is_homepage %}{{ page.title }} - {% endif %}{{ site_name }}
```
::: mkdocs.structure.pages.Page.previous_page
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.next_page
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.StructureItem.parent
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.children
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.active
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.is_section
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.is_page
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.pages.Page.is_link
options:
show_root_full_path: false
heading_level: 5
#### AnchorLink
::: mkdocs.structure.toc.AnchorLink
options:
show_root_heading: false
show_root_toc_entry: true
heading_level: 5
### Navigation Objects
Navigation objects contained in the [nav](#nav) template variable may be one of
[section](#section) objects, [page](#page) objects, and [link](#link) objects.
While section objects may contain nested navigation objects, pages and links do
not.
Page objects are the full page object as used for the current [page](#page) with
all of the same attributes available. Section and Link objects contain a subset
of those attributes as defined below:
#### Section
A `section` navigation object defines a named section in the navigation and
contains a list of child navigation objects. Note that sections do not contain
URLs and are not links of any kind. However, by default, MkDocs sorts index
pages to the top and the first child might be used as the URL for a section if a
theme chooses to do so.
::: mkdocs.structure.nav.Section
options:
show_root_heading: false
show_root_toc_entry: true
members: []
heading_level: 4
The following attributes are available on `section` objects:
::: mkdocs.structure.nav.Section.title
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.StructureItem.parent
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Section.children
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Section.active
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Section.is_section
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Section.is_page
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Section.is_link
options:
show_root_full_path: false
heading_level: 5
#### Link
A `link` navigation object contains a link which does not point to an internal
MkDocs page.
::: mkdocs.structure.nav.Link
options:
show_root_heading: false
show_root_toc_entry: true
members: []
heading_level: 4
The following attributes are available on `link` objects:
::: mkdocs.structure.nav.Link.title
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Link.url
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.StructureItem.parent
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Link.children
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Link.active
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Link.is_section
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Link.is_page
options:
show_root_full_path: false
heading_level: 5
::: mkdocs.structure.nav.Link.is_link
options:
show_root_full_path: false
heading_level: 5
### Extra Context
Additional variables can be passed to the template with the
[`extra`](../user-guide/configuration.md#extra) configuration option. This is a
set of key value pairs that can make custom templates far more flexible.
For example, this could be used to include the project version of all pages
and a list of links related to the project. This can be achieved with the
following `extra` configuration:
```yaml
extra:
version: 0.13.0
links:
- https://github.com/mkdocs
- https://docs.readthedocs.org/en/latest/builds.html#mkdocs
- https://www.mkdocs.org/
```
And then displayed with this HTML in the custom theme.
```django
{{ config.extra.version }}
{% if config.extra.links %}
{% for link in config.extra.links %}
{{ link }}
{% endfor %}
{% endif %}
```
## Template Filters
In addition to [Jinja's default filters], the following custom filters are
available to use in MkDocs templates:
### url
Normalizes a URL. Absolute URLs are passed through unaltered. If the URL is
relative and the template context includes a page object, then the URL is
returned relative to the page object. Otherwise, the URL is returned with
[base_url](#base_url) prepended.
```django
{{ page.title }}
```
### tojson
Safely convert a Python object to a value in a JavaScript script.
```django
```
### script_tag
NEW: **New in version 1.5.**
Convert an item from `extra_javascript` to a `
```
With properly configured settings, the following HTML in a template will add a
full search implementation to your theme.
```django
Search Results
Sorry, page not found.
```
The JavaScript in the plugin works by looking for the specific ID's used in the
above HTML. The form input for the user to type the search query must be
identified with `id="mkdocs-search-query"` and the div where the results will be
placed must be identified with `id="mkdocs-search-results"`.
The plugin supports the following options being set in the [theme's
configuration file], `mkdocs_theme.yml`:
### include_search_page
Determines whether the search plugin expects the theme to provide a dedicated
search page via a template located at `search/search.html`.
When `include_search_page` is set to `true`, the search template will be built
and available at `search/search.html`. This method is used by the `readthedocs`
theme.
When `include_search_page` is set to `false` or not defined, it is expected that
the theme provide some other mechanisms for displaying search results. For
example, the `mkdocs` theme displays results on any page via a modal.
### search_index_only
Determines whether the search plugin should only generate a search index or a
complete search solution.
When `search_index_only` is set to `false`, then the search plugin modifies the
Jinja environment by adding its own `templates` directory (with a lower
precedence than the theme) and adds its scripts to the `extra_javascript` config
setting.
When `search_index_only` is set to `true` or not defined, the search plugin
makes no modifications to the Jinja environment. A complete solution using the
provided index file is the responsibility of the theme.
The search index is written to a JSON file at `search/search_index.json` in the
[site_dir]. The JSON object contained within the file may contain up to three
objects.
```json
{
config: {...},
docs: [...],
index: {...}
}
```
If present, the `config` object contains the key/value pairs of config options
defined for the plugin in the user's `mkdocs.yml` config file under
`plugings.search`. The `config` object was new in MkDocs version *1.0*.
The `docs` object contains a list of document objects. Each document object is
made up of a `location` (URL), a `title`, and `text` which can be used to create
a search index and/or display search results.
If present, the `index` object contains a pre-built index which offers
performance improvements for larger sites. Note that the pre-built index is only
created if the user explicitly enables the [prebuild_index] config option.
Themes should expect the index to not be present, but can choose to use the
index when it is available. The `index` object was new in MkDocs version *1.0*.
[Jinja2 template]: https://jinja.palletsprojects.com/
[built-in themes]: https://github.com/mkdocs/mkdocs/tree/master/mkdocs/themes
[theme's configuration file]: #theme-configuration
[lunr.js]: https://lunrjs.com/
[site_dir]: ../user-guide/configuration.md#site_dir
[prebuild_index]: ../user-guide/configuration.md#prebuild_index
[Jinja's default filters]: https://jinja.palletsprojects.com/en/latest/templates/#builtin-filters
## Packaging Themes
MkDocs makes use of [Python packaging] to distribute themes. This comes with a
few requirements.
To see an example of a package containing one theme, see the [MkDocs Bootstrap
theme] and to see a package that contains many themes, see the [MkDocs
Bootswatch theme].
NOTE:
It is not strictly necessary to package a theme, as the entire theme
can be contained in the `custom_dir`. If you have created a "one-off theme,"
that should be sufficient. However, if you intend to distribute your theme
for others to use, packaging the theme has some advantages. By packaging
your theme, your users can more easily install it, they can rely on a default
[configuration] being defined, and they can then take advantage of the
[custom_dir] to make tweaks to your theme to better suit their needs.
[Python packaging]: https://packaging.python.org/en/latest/
[MkDocs Bootstrap theme]: https://mkdocs.github.io/mkdocs-bootstrap/
[MkDocs Bootswatch theme]: https://mkdocs.github.io/mkdocs-bootswatch/
### Package Layout
The following layout is recommended for themes. Two files at the top level
directory called `MANIFEST.in` and `setup.py` beside the theme directory which
contains an empty `__init__.py` file, a theme configuration file
(`mkdocs_theme.yml`), and your template and media files.
```text
.
|-- MANIFEST.in
|-- theme_name
| |-- __init__.py
| |-- mkdocs_theme.yml
| |-- main.html
| |-- styles.css
`-- setup.py
```
The `MANIFEST.in` file should contain the following contents but with
theme_name updated and any extra file extensions added to the include.
```text
recursive-include theme_name *.ico *.js *.css *.png *.html *.eot *.svg *.ttf *.woff
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
```
The `setup.py` should include the following text with the modifications
described below.
```python
from setuptools import setup, find_packages
VERSION = '0.0.1'
setup(
name="mkdocs-themename",
version=VERSION,
url='',
license='',
description='',
author='',
author_email='',
packages=find_packages(),
include_package_data=True,
entry_points={
'mkdocs.themes': [
'themename = theme_name',
]
},
zip_safe=False
)
```
Fill in the URL, license, description, author and author email address.
The name should follow the convention `mkdocs-themename` (like
`mkdocs-bootstrap` and `mkdocs-bootswatch`), starting with MkDocs, using
hyphens to separate words and including the name of your theme.
Most of the rest of the file can be left unedited. The last section we need to
change is the entry_points. This is how MkDocs finds the theme(s) you are
including in the package. The name on the left is the one that users will use
in their mkdocs.yml and the one on the right is the directory containing your
theme files.
The directory you created at the start of this section with the main.html file
should contain all of the other theme files. The minimum requirement is that
it includes a `main.html` for the theme. It **must** also include a
`__init__.py` file which should be empty, this file tells Python that the
directory is a package.
### Theme Configuration
A packaged theme is required to include a configuration file named
`mkdocs_theme.yml` which is placed in the root of your template files. The file
should contain default configuration options for the theme. However, if the
theme offers no configuration options, the file is still required and can be
left blank. A theme which is not packaged does not need a `mkdocs_theme.yml`
file as that file is not loaded from `theme.custom_dir`.
The theme author is free to define any arbitrary options deemed necessary and
those options will be made available in the templates to control behavior.
For example, a theme might want to make a sidebar optional and include the
following in the `mkdocs_theme.yml` file:
```yaml
show_sidebar: true
```
Then in a template, that config option could be referenced:
```django
{% if config.theme.show_sidebar %}
...
{% endif %}
```
And the user could override the default in their project's `mkdocs.yml` config
file:
```yaml
theme:
name: themename
show_sidebar: false
```
In addition to arbitrary options defined by the theme, MkDocs defines a few
special options which alters its behavior:
> BLOCK:
>
> #### locale
>
> This option mirrors the [theme] config option of the same name. If this
> value is not defined in the `mkdocs_theme.yml` file and the user does not
> set it in `mkdocs.yml` then it will default to `en` (English). The value
> is expected to match the language used in the text provided by the theme
> (such a "next" and "previous" links) and should be used as the value of
> the `` tag's `lang` attribute. See [Supporting theme localization/
> translation](#supporting-theme-localizationtranslation) for more
> information.
>
> Note that during configuration validation, the provided string is converted
> to a `Locale` object. The object contains `Locale.language` and
> `Locale.territory` attributes and will resolve as a string from within a
> template. Therefore, the following will work fine:
>
> ```html
>
> ```
>
> If the locale was set to `fr_CA` (Canadian French), then the above template
> would render as:
>
> ```html
>
> ```
>
> If you did not want the territory attribute to be included, then reference
> the `language` attribute directly:
>
> ```html
>
> ```
>
> That would render as:
>
> ```html
>
> ```
>
> #### static_templates
>
> This option mirrors the [theme] config option of the same name and allows
> some defaults to be set by the theme. Note that while the user can add
> templates to this list, the user cannot remove templates included in the
> theme's config.
>
> #### extends
>
> Defines a parent theme that this theme inherits from. The value should be
> the string name of the parent theme. Normal [Jinja inheritance rules]
> apply.
Plugins may also define some options which allow the theme to inform a plugin
about which set of plugin options it expects. See the documentation for any
plugins you may wish to support in your theme.
### Distributing Themes
With the above changes, your theme should now be ready to install. This can be
done with pip, using `pip install .` if you are still in the same directory as
the setup.py.
Most Python packages, including MkDocs, are distributed on PyPI. To do this,
you should run the following command.
```bash
python setup.py register
```
If you don't have an account setup, you should be prompted to create one.
For a much more detailed guide, see the official Python packaging
documentation for [Packaging and Distributing Projects].
[Packaging and Distributing Projects]: https://packaging.python.org/en/latest/distributing/
[Jinja inheritance rules]: https://jinja.palletsprojects.com/en/latest/templates/#template-inheritance
## Supporting theme Localization/Translation
While the built-in themes provide support for [localization/translation] of
templates, custom themes and third-party themes may choose not to. Regardless,
the [`locale`](#locale) setting of the `theme` configuration option is always
present and is relied upon by other parts of the system. Therefore, it is
recommended that all third-party themes use the same setting for designating a
language regardless of the system they use for translation. In that way, users
will experience consistent behavior regardless of the theme they may choose.
The method for managing translations is up to the developers of a theme.
However, if a theme developer chooses to use the same mechanisms used by the
built-in themes, the sections below outline how to enable and make use of the
same commands utilized by MkDocs.
[localization/translation]: ../user-guide/localizing-your-theme.md
### Using the Localization/Translation commands
WARNING:
As **[pybabel] is not installed by default** and most users will not have
pybabel installed, theme developers and/or translators should make sure to
have installed the necessary dependencies
(using `pip install mkdocs[i18n]`) in order for the commands to be
available for use.
The translation commands should be called from the root of your theme's working tree.
For an overview of the workflow used by MkDocs to translate the built-in
themes, see the appropriate [section] of the Contributing Guide and the
[Translation Guide].
[pybabel]: https://babel.pocoo.org/en/latest/setup.html
[section]: ../about/contributing.md#submitting-changes-to-the-builtin-themes
[Translation Guide]: translations.md
### Example custom theme Localization/Translation workflow
> NOTE: If your theme inherits from an existing theme which already provides
> translation catalogs, your theme's translations will be merged with the
> parent theme's translations during a MkDocs build.
>
> This means that you only need to concentrate on the added translations.
> Yet, you will still benefit from the translations of the parent theme. At
> the same time, you may override any of parent theme's translations!
Let's suppose that you're working on your own fork of the
[mkdocs-basic-theme][basic theme] and want to add translations to it.
Edit the templates by wrapping text in your HTML sources with
`{% trans %}` and `{% endtrans %}` as follows:
```diff
--- a/basic_theme/base.html
+++ b/basic_theme/base.html
@@ -88,7 +88,7 @@
-
This is an example theme for MkDocs.
+
{% trans %}This is an example theme for MkDocs.{% endtrans %}
It is designed to be read by looking at the theme HTML which is heavily
```
Then you would follow the [Translation Guide] as usual to get your translations
running.
### Packaging Translations with your theme
While the Portable Object Template (`pot`) file created by the
`extract_messages` command and the Portable Object (`po`) files created by the
`init_catalog` and `update_catalog` commands are useful for creating and
editing translations, they are not used by MkDocs directly and do not need to
be included in a packaged release of a theme. When MkDocs builds a site with
translations, it only makes use of the binary `mo` files(s) for the specified
locale. Therefore, when [packaging a theme], make sure to include it in the
"wheels", using a `MANIFEST.in` file or otherwise.
Then, before building your Python package, you will want to ensure that the
binary `mo` file for each locale is up-to-date by running the `compile_catalog`
command for each locale. MkDocs expects the binary `mo` files to be located at
`locales//LC_MESSAGES/messages.mo`, which the `compile_catalog`
command automatically does for you. See [Testing theme translations] for
details.
NOTE:
As outlined in our [Translation Guide], the MkDocs project has chosen to
include the `pot` and `po` files in our code repository, but not the
`mo` files. This requires us to always run `compile_catalog` before
packaging a new release regardless of whether any changes were made to a
translation or not. However, you may chose an alternate workflow for your
theme. At a minimum, you need to ensure that up-to-date `mo` files are
included at the correct location in each release. However, you may use a
different process for generating those `mo` files if you chose to do so.
[packaging a theme]: #packaging-themes
[Testing theme translations]: translations.md#testing-theme-translations
python-mkdocs-1.5.3/docs/dev-guide/api.md 0000644 0001750 0001750 00000001135 14502137725 020101 0 ustar carsten carsten # API reference
NOTE: The main entry point to the API is through [Events](plugins.md#events) that are received by plugins. These events' descriptions link back to this page.
::: mkdocs.structure.files.Files
options:
show_root_heading: true
::: mkdocs.structure.files.File
options:
show_root_heading: true
::: mkdocs.config.base.Config
options:
show_root_heading: true
::: mkdocs.utils.templates.TemplateContext
options:
show_root_heading: true
show_if_no_docstring: true
::: mkdocs.livereload.LiveReloadServer
options:
show_root_heading: true
python-mkdocs-1.5.3/docs/dev-guide/plugins.md 0000644 0001750 0001750 00000040503 14502137725 021013 0 ustar carsten carsten # MkDocs Plugins
A Guide to installing, using and creating MkDocs Plugins
---
## Installing Plugins
Before a plugin can be used, it must be installed on the system. If you are
using a plugin which comes with MkDocs, then it was installed when you installed
MkDocs. However, to install third party plugins, you need to determine the
appropriate package name and install it using `pip`:
```bash
pip install mkdocs-foo-plugin
```
Once a plugin has been successfully installed, it is ready to use. It just needs
to be [enabled](#using-plugins) in the configuration file. The [Catalog]
repository has a large ranked list of plugins that you can install and use.
## Using Plugins
The [`plugins`][config] configuration option should contain a list of plugins to
use when building the site. Each "plugin" must be a string name assigned to the
plugin (see the documentation for a given plugin to determine its "name"). A
plugin listed here must already be [installed](#installing-plugins).
```yaml
plugins:
- search
```
Some plugins may provide configuration options of their own. If you would like
to set any configuration options, then you can nest a key/value mapping
(`option_name: option value`) of any options that a given plugin supports. Note
that a colon (`:`) must follow the plugin name and then on a new line the option
name and value must be indented and separated by a colon. If you would like to
define multiple options for a single plugin, each option must be defined on a
separate line.
```yaml
plugins:
- search:
lang: en
foo: bar
```
For information regarding the configuration options available for a given plugin,
see that plugin's documentation.
For a list of default plugins and how to override them, see the
[configuration][config] documentation.
## Developing Plugins
Like MkDocs, plugins must be written in Python. It is generally expected that
each plugin would be distributed as a separate Python module, although it is
possible to define multiple plugins in the same module. At a minimum, a MkDocs
Plugin must consist of a [BasePlugin] subclass and an [entry point] which
points to it.
### BasePlugin
A subclass of `mkdocs.plugins.BasePlugin` should define the behavior of the plugin.
The class generally consists of actions to perform on specific events in the build
process as well as a configuration scheme for the plugin.
All `BasePlugin` subclasses contain the following attributes:
#### config_scheme
A tuple of configuration validation instances. Each item must consist of a
two item tuple in which the first item is the string name of the
configuration option and the second item is an instance of
`mkdocs.config.config_options.BaseConfigOption` or any of its subclasses.
For example, the following `config_scheme` defines three configuration options: `foo`, which accepts a string; `bar`, which accepts an integer; and `baz`, which accepts a boolean value.
```python
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))
)
```
> NEW: **New in version 1.4.**
>
> ##### Subclassing `Config` to specify the config schema
>
> To get type safety benefits, if you're targeting only MkDocs 1.4+, define the config schema as a class instead:
>
> ```python
> 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]):
> ...
> ```
##### Examples of config definitions
>! EXAMPLE:
>
> ```python
> 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) # required
> checksum_file = c.Optional(c.File(exists=True)) # can be None but must exist if specified
> validation = c.SubConfig(_ValidationOptions)
> ```
>
> From the user's point of view `SubConfig` is similar to `Type(dict)`, it's just that it also retains full ability for validation: you define all valid keys and what each value should adhere to.
>
> And `ListOfItems` is similar to `Type(list)`, but again, we define the constraint that each value must adhere to.
>
> This accepts a config as follows:
>
> ```yaml
> my_plugin:
> definition_file: configs/test.ini # relative to mkdocs.yml
> validation:
> enabled: !ENV [CI, false]
> verbose: true
> skip_checks:
> - foo
> - baz
> ```
>? EXAMPLE:
>
> ```python
> import numbers
> from mkdocs.config import base, config_options as c
>
> class _Rectangle(base.Config):
> width = c.Type(numbers.Real) # required
> height = c.Type(numbers.Real) # required
>
> class MyPluginConfig(base.Config):
> add_rectangles = c.ListOfItems(c.SubConfig(_Rectangle)) # required
> ```
>
> In this example we define a list of complex items, and that's achieved by passing a concrete `SubConfig` to `ListOfItems`.
>
> This accepts a config as follows:
>
> ```yaml
> my_plugin:
> add_rectangles:
> - width: 5
> height: 7
> - width: 12
> height: 2
> ```
When the user's configuration is loaded, the above scheme will be used to
validate the configuration and fill in any defaults for settings not
provided by the user. The validation classes may be any of the classes
provided in `mkdocs.config.config_options` or a third party subclass defined
in the plugin.
Any settings provided by the user which fail validation or are not defined
in the `config_scheme` will raise a `mkdocs.config.base.ValidationError`.
#### config
A dictionary of configuration options for the plugin, which is populated by
the `load_config` method after configuration validation has completed. Use
this attribute to access options provided by the user.
```python
def on_pre_build(self, config, **kwargs):
if self.config['baz']:
# implement "baz" functionality here...
```
> NEW: **New in version 1.4.**
>
> ##### Safe attribute-based access
>
> To get type safety benefits, if you're targeting only MkDocs 1.4+, access options as attributes instead:
>
> ```python
> def on_pre_build(self, config, **kwargs):
> if self.config.baz:
> print(self.config.bar ** 2) # OK, `int ** 2` is valid.
> ```
All `BasePlugin` subclasses contain the following method(s):
#### load_config(options)
Loads configuration from a dictionary of options. Returns a tuple of
`(errors, warnings)`. This method is called by MkDocs during configuration
validation and should not need to be called by the plugin.
#### on_<event_name>()
Optional methods which define the behavior for specific [events]. The plugin
should define its behavior within these methods. Replace `` with
the actual name of the event. For example, the `pre_build` event would be
defined in the `on_pre_build` method.
Most events accept one positional argument and various keyword arguments. It
is generally expected that the positional argument would be modified (or
replaced) by the plugin and returned. If nothing is returned (the method
returns `None`), then the original, unmodified object is used. The keyword
arguments are simply provided to give context and/or supply data which may
be used to determine how the positional argument should be modified. It is
good practice to accept keyword arguments as `**kwargs`. In the event that
additional keywords are provided to an event in a future version of MkDocs,
there will be no need to alter your plugin.
For example, the following event would add an additional static_template to
the theme config:
```python
class MyPlugin(BasePlugin):
def on_config(self, config, **kwargs):
config['theme'].static_templates.add('my_template.html')
return config
```
> NEW: **New in version 1.4.**
>
> To get type safety benefits, if you're targeting only MkDocs 1.4+, access config options as attributes instead:
>
> ```python
> def on_config(self, config: MkDocsConfig):
> config.theme.static_templates.add('my_template.html')
> return config
> ```
### Events
There are three kinds of events: [Global Events], [Page Events] and
[Template Events].
See a diagram with relations between all the plugin events
The events themselves are shown in yellow, with their parameters.
Arrows show the flow of arguments and outputs of each event.
Sometimes they're omitted.
The events are chronologically ordered from top to bottom.
Dotted lines appear at splits from global events to per-page events.
Click the events' titles to jump to their description.
--8<-- "docs/img/plugin-events.svg"
#### One-time Events
One-time events run once per `mkdocs` invocation. The only case where these tangibly differ from [global events](#global-events) is for `mkdocs serve`: global events, unlike these, will run multiple times -- once per *build*.
##### on_startup
::: mkdocs.plugins.BasePlugin.on_startup
options:
show_root_heading: false
show_root_toc_entry: false
##### on_shutdown
::: mkdocs.plugins.BasePlugin.on_shutdown
options:
show_root_heading: false
show_root_toc_entry: false
##### on_serve
::: mkdocs.plugins.BasePlugin.on_serve
options:
show_root_heading: false
show_root_toc_entry: false
#### Global Events
Global events are called once per build at either the beginning or end of the
build process. Any changes made in these events will have a global effect on the
entire site.
##### on_config
::: mkdocs.plugins.BasePlugin.on_config
options:
show_root_heading: false
show_root_toc_entry: false
##### on_pre_build
::: mkdocs.plugins.BasePlugin.on_pre_build
options:
show_root_heading: false
show_root_toc_entry: false
##### on_files
::: mkdocs.plugins.BasePlugin.on_files
options:
show_root_heading: false
show_root_toc_entry: false
##### on_nav
::: mkdocs.plugins.BasePlugin.on_nav
options:
show_root_heading: false
show_root_toc_entry: false
##### on_env
::: mkdocs.plugins.BasePlugin.on_env
options:
show_root_heading: false
show_root_toc_entry: false
##### on_post_build
::: mkdocs.plugins.BasePlugin.on_post_build
options:
show_root_heading: false
show_root_toc_entry: false
##### on_build_error
::: mkdocs.plugins.BasePlugin.on_build_error
options:
show_root_heading: false
show_root_toc_entry: false
#### Template Events
Template events are called once for each non-page template. Each template event
will be called for each template defined in the [extra_templates] config setting
as well as any [static_templates] defined in the theme. All template events are
called after the [env] event and before any [page events].
##### on_pre_template
::: mkdocs.plugins.BasePlugin.on_pre_template
options:
show_root_heading: false
show_root_toc_entry: false
##### on_template_context
::: mkdocs.plugins.BasePlugin.on_template_context
options:
show_root_heading: false
show_root_toc_entry: false
##### on_post_template
::: mkdocs.plugins.BasePlugin.on_post_template
options:
show_root_heading: false
show_root_toc_entry: false
#### Page Events
Page events are called once for each Markdown page included in the site. All
page events are called after the [post_template] event and before the
[post_build] event.
##### on_pre_page
::: mkdocs.plugins.BasePlugin.on_pre_page
options:
show_root_heading: false
show_root_toc_entry: false
##### on_page_read_source
::: mkdocs.plugins.BasePlugin.on_page_read_source
options:
show_root_heading: false
show_root_toc_entry: false
##### on_page_markdown
::: mkdocs.plugins.BasePlugin.on_page_markdown
options:
show_root_heading: false
show_root_toc_entry: false
##### on_page_content
::: mkdocs.plugins.BasePlugin.on_page_content
options:
show_root_heading: false
show_root_toc_entry: false
##### on_page_context
::: mkdocs.plugins.BasePlugin.on_page_context
options:
show_root_heading: false
show_root_toc_entry: false
##### on_post_page
::: mkdocs.plugins.BasePlugin.on_post_page
options:
show_root_heading: false
show_root_toc_entry: false
### Event Priorities
For each event type, corresponding methods of plugins are called in the order that the plugins appear in the `plugins` [config][].
Since MkDocs 1.4, plugins can choose to set a priority value for their events. Events with higher priority are called first. Events without a chosen priority get a default of 0. Events that have the same priority are ordered as they appear in the config.
#### ::: mkdocs.plugins.event_priority
### Handling Errors
MkDocs defines four error types:
#### ::: mkdocs.exceptions.MkDocsException
#### ::: mkdocs.exceptions.ConfigurationError
#### ::: mkdocs.exceptions.BuildError
#### ::: mkdocs.exceptions.PluginError
Unexpected and uncaught exceptions will interrupt the build process and produce
typical Python tracebacks, which are useful for debugging your code. However,
users generally find tracebacks overwhelming and often miss the helpful error
message. Therefore, MkDocs will catch any of the errors listed above, retrieve
the error message, and exit immediately with only the helpful message displayed
to the user.
Therefore, you might want to catch any exceptions within your plugin and raise a
`PluginError`, passing in your own custom-crafted message, so that the build
process is aborted with a helpful message.
The [on_build_error] event will be triggered for any exception.
For example:
```python
from mkdocs.exceptions import PluginError
from mkdocs.plugins import BasePlugin
class MyPlugin(BasePlugin):
def on_post_page(self, output, page, config, **kwargs):
try:
# some code that could throw a KeyError
...
except KeyError as error:
raise PluginError(str(error))
def on_build_error(self, error, **kwargs):
# some code to clean things up
...
```
### Logging in plugins
MkDocs provides a `get_plugin_logger` function which returns
a logger that can be used to log messages.
#### ::: mkdocs.plugins.get_plugin_logger
### Entry Point
Plugins need to be packaged as Python libraries (distributed on PyPI separate
from MkDocs) and each must register as a Plugin via a setuptools `entry_points`.
Add the following to your `setup.py` script:
```python
entry_points={
'mkdocs.plugins': [
'pluginname = path.to.some_plugin:SomePluginClass',
]
}
```
The `pluginname` would be the name used by users (in the config file) and
`path.to.some_plugin:SomePluginClass` would be the importable plugin itself
(`from path.to.some_plugin import SomePluginClass`) where `SomePluginClass` is a
subclass of [BasePlugin] which defines the plugin behavior. Naturally, multiple
Plugin classes could exist in the same module. Simply define each as a separate
entry point.
```python
entry_points={
'mkdocs.plugins': [
'featureA = path.to.my_plugins:PluginA',
'featureB = path.to.my_plugins:PluginB'
]
}
```
Note that registering a plugin does not activate it. The user still needs to
tell MkDocs to use it via the config.
### Publishing a Plugin
You should publish a package on [PyPI], then add it to the [Catalog] for discoverability. Plugins are strongly recommended to have a unique plugin name (entry point name) according to the catalog.
[BasePlugin]:#baseplugin
[config]: ../user-guide/configuration.md#plugins
[entry point]: #entry-point
[env]: #on_env
[events]: #events
[extra_templates]: ../user-guide/configuration.md#extra_templates
[Global Events]: #global-events
[Page Events]: #page-events
[post_build]: #on_post_build
[post_template]: #on_post_template
[static_templates]: ../user-guide/configuration.md#static_templates
[Template Events]: #template-events
[catalog]: https://github.com/mkdocs/catalog
[on_build_error]: #on_build_error
[PyPI]: https://pypi.org/
python-mkdocs-1.5.3/docs/css/ 0000755 0001750 0001750 00000000000 14502137725 015725 5 ustar carsten carsten python-mkdocs-1.5.3/docs/css/extra.css 0000644 0001750 0001750 00000003044 14502137725 017563 0 ustar carsten carsten div.col-md-9 h1:first-of-type {
text-align: center;
font-size: 60px;
font-weight: 300;
}
div.col-md-9>p:first-of-type {
text-align: center;
}
div.col-md-9 p.admonition-title:first-of-type {
text-align: left;
}
div.col-md-9 h1:first-of-type .headerlink {
display: none;
}
div.admonition.block>.admonition-title {
display: none;
}
.admonition.new, details.new {
color: #15654a;
background-color: #edfff9;
border-color: #bcf1e8;
}
.admonition.example, details.example {
color: #353579;
background-color: #f0f1ff;
border-color: #d8dcf0;
}
/* Definition List styles */
dd {
padding-left: 20px;
}
.card-body svg {
width: 100%;
padding: 0 50px;
height: auto;
}
/* Homepage */
body.homepage div.jumbotron {
margin-top: 1.5rem;
padding-top: 1rem;
padding-bottom: 0;
}
body.homepage div.jumbotron div.card {
margin-bottom: 2rem;
}
body.homepage>div.container>div.row>div.col-md-3 {
display: none;
}
body.homepage>div.container>div.row>div.col-md-9 {
margin-left: 0;
flex: 0 0 100%;
max-width: 100%;
}
/* mkdocstrings */
.doc-object {
padding-left: 10px;
border-left: 4px solid rgba(230, 230, 230);
}
.doc-contents .field-body p:first-of-type {
display: inline;
}
.doc-label-class-attribute,
.doc-label-instance-attribute {
display: none;
}
h2.doc-heading {
font-size: 1.5rem;
}
h3.doc-heading {
font-size: 1.4rem;
}
h4.doc-heading {
font-size: 1.3rem;
}
h5.doc-heading {
font-size: 1.2rem;
}
.doc-contents {
padding-left: 0;
}
python-mkdocs-1.5.3/docs/img/ 0000755 0001750 0001750 00000000000 14502137725 015711 5 ustar carsten carsten python-mkdocs-1.5.3/docs/img/screenshot.png 0000644 0001750 0001750 00000146313 14502137725 020604 0 ustar carsten carsten PNG
IHDR
[@ ̒IDATx}@g_ymc{ZzjkhIkvfwfwY@NYf>;;s=p`04VmP`0`Z;: `0tΜ9o߾۳;{IמtٓY{,5jj6MUӻ@'''ƀ`06Fq駟~y~/s:!^~`0`3(:mm=1::!9N@`0o1*tB)@`0(;u. `0ؔw+o;o91˳Z'|篽O?_|yyy-SN}Y4-`0h?@୷:w=6|ͩ(ӧ6|8[n~/\ްqo~7$b_322v
gsʗ +cWo]̎=>dSF]Q䜯HyvєTU0PUGk,/항w(_vN'r`0ޱ>+}8v؞={U~Q`KƧ~SMY/^x* }x?퓬3 #O=~3oo+VxgC<:`pppÍ7mxxtgΙЗlnۜE^ܺcR_8+GH~nEW_l7G_|5]$h7gVq
I'_ٿ7Z/^<:EVtV
<}b{nyG{$`0l۶m4&}|(u#U__6K Lu[^|xѢE<{MgθΝ;kͺUa
/$X`|zpX';T:e9 ENssC;8~
鈯_4Ο18_
vJ+\C7e0niiyGN6{ `0˒M`PnwJz]]kRڡC[n3\wSWWY
,V'߉εkD>1ܾ}ui#h',^g'h$>u$Wi"}n7_]c0ǫAۉ)p^uy1ׄCo9(Q`mGy-VbvR??Qr1_dnܸA"oNNuݟ}Irƕ-˿pTP+~; WΤ=D'TW攑QiC^Q0qٿK|i~4'f}]Kh;wG&vr*Zj7KKћOWJwܢklHWˎO(`06j7(-}b̓Rٕ+WNu[Ա6}Ŋ7}גHzժUK,L}f1g-"Tظ>?5hpZ[?<}.IىU/D%>EoURIh\
j!5ĐaGoVK(s+紉Nxjjh?s&"}& 5SRzɈEI/b\'gԿ֧^)UlK+ ՍX`0D(*jo4dMSSӟǴfLea̿uue UGt裏RMe˖~괹IF$s]uyGt̳]r峢%$1:7~GWCCщH f8А{4$FGٰw.zxη6P(_^#
7N`0vŋi={4mf(`?z#jLH+Ũfl&yH0p?R~ɞ5{Մ%!@>q.r]cBg'i "eڵT'|=?u!;ڶ@4*$oNH'^:tC&a_~a>z`+qpuH(]X <^̍eKyU y(ۻP50cJn̤:Ke:h% oH4yt4{0zqt ]ݜf6"ihcVBwM67l#q`1`0ߍla78`6KK^0Wc
șN`h*S4>Xm,]Ԩ@?S S4r>KԘ_K3'AֆTEkmzmPCFh:a&a&_.!F`@i:S̋
`0>7Z-W7k2P$`:Arrx|#3KS u
ǘ
+.6mTH)ۼy3N鐔8&2<,g#'e{i~)1ʐzѸ>>PLOsIR^̤4O