mkdocs-section-index#
Plugin for MkDocs to allow clickable sections that lead to an index page
pip install mkdocs-section-index
Example#
With this nav
in mkdocs.yml (or without nav
but with an equivalent directory structure):
nav:
- Frob: index.md
- Baz: baz.md
- Borgs:
- borgs/index.md
- Bar: borgs/bar.md
- Foo: borgs/foo.md
plugins:
- search
- section-index
The borgs/index.md page is merged as the index of the "Borgs" section. Normally sections in MkDocs cannot be clickable as pages themselves, but this plugin makes that possible.
See also: a realistic demo site.
Theme support#
This plugin requires per-theme overrides (implemented within the plugin), or support from themes themselves.
Currently supported themes are:
Usage notes#
The kind of nav as shown above also happens to be what MkDocs produces when nav
is omitted; it detects index.md
and README.md
pages and automatically puts them as the first item.
To make writing this kind of nav
more natural (in YAML there's no better option), consider using the literate-nav plugin along with this; then the above nav might be written like this:
* [Frob](index.md)
* [Baz](baz.md)
* [Borgs](borgs/index.md)
* [Bar](borgs/bar.md)
* [Foo](borgs/foo.md)
Implementation#
"Protocol"#
Normally in MkDocs nav
, the items can be one of:
- a
Section
, which has atitle
andchildren
.- (
url
is alwaysNone
)
- (
- a
Page
, which has atitle
andurl
.- (
title
can be omitted, and later deduced from the page content) - (
children
is alwaysNone
)
- (
- a
Link
(inconsequential for our purposes).
This plugin introduces a hybrid kind of Page
, which has all of these properties:
title
:str
url
:str
children
:list
is_page
=True
is_section
=True
Such a special item gets put into a nav in the place of a Section
which has a Page
with an intentionally omitted title as its first child. Those two are naturally combined into a special section-page that's a hybrid of the two.
Implementation within themes#
Then all that a theme's template needs to do is to meaningfully support such nav items -- ones that have both a url
and children
. The item should be directly clickable to go to the corresponding page, and also be able to house sub-items.
Of course, currently templates don't expect such a case; or if they did, it would be purely by chance. So currently this plugin "hacks into" templates of supported themes, patching their source on the fly to fit its needs. The hope is that, once this plugin gains enough traction, theme authors will be happy to directly support this scenario (which is totally non-intrusive and backwards-compatible), and then the patches could be dropped.
"Alternatives considered"#
Even if all the template patches are gone, this plugin will still remain as the implementation of this special nav "protocol", and as the opt-in mechanism. In the author's view, such an approach is advantageous, because:
-
This is too controversial to be enabled by default, or even be part of MkDocs at all. This has been discussed in the past and dropped. The main reason is that in MkDocs there's no requirement for a nav's structure to follow the actual directory structure of the doc files. Consequently, there's no natural way to deduce that a document should become the index page of a section just from its location, even if it's named index.md. Although if the nav is omitted & generated, then yes, such an assumption works. It also works in the vast majority of actual usages with a nav, but that doesn't help.
-
Themes themselves also probably shouldn't directly try to detect logic such as "first child of a section if it has no title" and manually collapse the child within Jinja template code, as that's too messy. This also shouldn't be enabled by default. And even though templates could also make this opt-in, a centralized approach like this one ensures that accessing this feature is done uniformly. Not to mention that templates might never implement this themselves.