Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# Configuration

This page lists the available configuration options and what they achieve.

[](){#setting-options}
## `options`

You can specify a few configuration options under the `options` key:

```yaml title="mkdocs.yml"
plugins:
- mkdocstrings:
handlers:
shell:
options:
# some configuration
```

[](){#option-extra}
### `extra`

- **:octicons-package-24: Type [`dict`][] :material-equal: `{}`{ title="default value" }**

The `extra` option lets you inject additional variables into the Jinja context used when rendering templates. You can then use this extra context in your [overridden templates](https://mkdocstrings.github.io/usage/theming/#templates).

Local `extra` options will be merged into the global `extra` option:

```yaml title="in mkdocs.yml (global configuration)"
plugins:
- mkdocstrings:
handlers:
shell:
options:
extra:
hello: world
```

```md title="in docs/some_page.md (local configuration)"
::: your_package.your_module.your_func
handler: shell
options:
extra:
foo: bar
```

...will inject both `hello` and `foo` into the Jinja context when rendering `your_package.your_module.your_func`.

[](){#option-heading_level}
### `heading_level`

- **:octicons-package-24: Type [`int`][] :material-equal: `2`{ title="default value" }**

The initial heading level to use.

When injecting documentation for an object,
the object itself and its members are rendered.
For each layer of objects, we increase the heading level by 1.

The initial heading level will be used for the first layer.
If you set it to 3, then headings will start with `<h3>`.

If the [heading for the root object][show_root_heading] is not shown,
then the initial heading level is used for its members.

```yaml title="in mkdocs.yml (global configuration)"
plugins:
- mkdocstrings:
handlers:
shell:
options:
heading_level: 2
```

```md title="or in docs/some_page.md (local configuration)"
::: path.to.module
handler: shell
options:
heading_level: 3
```

/// admonition | Preview
type: preview

//// tab | With level 3 and root heading
<h3><code>module</code> (3)</h3>
<p>Docstring of the module.</p>
<h4><code>ClassA</code> (4)</h4>
<p>Docstring of class A.</p>
<h4><code>ClassB</code> (4)</h4>
<p>Docstring of class B.</p>
<h5><code>method_1</code> (5)</h5>
<p>Docstring of the method.</p>
////

//// tab | With level 3, without root heading
<p>Docstring of the module.</p>
<h3><code>ClassA</code> (3)</h3>
<p>Docstring of class A.</p>
<h3><code>ClassB</code> (3)</h3>
<p>Docstring of class B.</p>
<h4><code>method_1</code> (4)</h4>
<p>Docstring of the method.</p>
////
///

[](){#option-show_root_heading}
### `show_root_heading`

- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**

Show the heading of the object at the root of the documentation tree
(i.e. the object referenced by the identifier after `:::`).

While this option defaults to false for backwards compatibility, we recommend setting it to true. Note that the heading of the root object can be a level 1 heading (the first on the page):

```md
# ::: path.to.object
```

```yaml title="in mkdocs.yml (global configuration)"
plugins:
- mkdocstrings:
handlers:
shell:
options:
show_root_heading: false
```

```md title="or in docs/some_page.md (local configuration)"
::: path.to.Class
handler: shell
options:
show_root_heading: true
```

[](){#option-show_root_toc_entry}
### `show_root_toc_entry`

- **:octicons-package-24: Type [`bool`][] :material-equal: `True`{ title="default value" }**
<!-- - **:octicons-project-template-24: Template :material-null:** (N/A) -->

If the root heading is not shown, at least add a ToC entry for it.

If you inject documentation for an object in the middle of a page,
after long paragraphs, and without showing the [root heading][show_root_heading],
then you will not be able to link to this particular object
as it won't have a permalink and will be "lost" in the middle of text.
In that case, it is useful to add a hidden anchor to the document,
which will also appear in the table of contents.

In other cases, you might want to disable the entry to avoid polluting the ToC.
It is not possible to show the root heading *and* hide the ToC entry.

```yaml title="in mkdocs.yml (global configuration)"
plugins:
- mkdocstrings:
handlers:
shell:
options:
show_root_heading: false
show_root_toc_entry: true
```

```md title="or in docs/some_page.md (local configuration)"
## Some heading

Lots of text.

::: path.to.object
handler: shell
options:
show_root_heading: false
show_root_toc_entry: false

## Other heading.

More text.
```

/// admonition | Preview
type: preview

//// tab | With ToC entry
**Table of contents**<br>
[Some heading](#permalink-to-some-heading){ title="#permalink-to-some-heading" }<br>
[`object`](#permalink-to-object){ title="#permalink-to-object" }<br>
[Other heading](#permalink-to-other-heading){ title="#permalink-to-other-heading" }
////

//// tab | Without ToC entry
**Table of contents**<br>
[Some heading](#permalink-to-some-heading){ title="#permalink-to-some-heading" }<br>
[Other heading](#permalink-to-other-heading){ title="#permalink-to-other-heading" }
////
///
22 changes: 22 additions & 0 deletions docs/css/material.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,25 @@
.md-main__inner {
margin-bottom: 1.5rem;
}

/* Custom admonition: preview */
:root {
--md-admonition-icon--preview: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.5 12a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z"/><path d="M12 3.5c3.432 0 6.124 1.534 8.054 3.241 1.926 1.703 3.132 3.61 3.616 4.46a1.6 1.6 0 0 1 0 1.598c-.484.85-1.69 2.757-3.616 4.461-1.929 1.706-4.622 3.24-8.054 3.24-3.432 0-6.124-1.534-8.054-3.24C2.02 15.558.814 13.65.33 12.8a1.6 1.6 0 0 1 0-1.598c.484-.85 1.69-2.757 3.616-4.462C5.875 5.034 8.568 3.5 12 3.5ZM1.633 11.945a.115.115 0 0 0-.017.055c.001.02.006.039.017.056.441.774 1.551 2.527 3.307 4.08C6.691 17.685 9.045 19 12 19c2.955 0 5.31-1.315 7.06-2.864 1.756-1.553 2.866-3.306 3.307-4.08a.111.111 0 0 0 .017-.056.111.111 0 0 0-.017-.056c-.441-.773-1.551-2.527-3.307-4.08C17.309 6.315 14.955 5 12 5 9.045 5 6.69 6.314 4.94 7.865c-1.756 1.552-2.866 3.306-3.307 4.08Z"/></svg>');
}

.md-typeset .admonition.preview,
.md-typeset details.preview {
border-color: rgb(220, 139, 240);
}

.md-typeset .preview>.admonition-title,
.md-typeset .preview>summary {
background-color: rgba(142, 43, 155, 0.1);
}

.md-typeset .preview>.admonition-title::before,
.md-typeset .preview>summary::before {
background-color: rgb(220, 139, 240);
-webkit-mask-image: var(--md-admonition-icon--preview);
mask-image: var(--md-admonition-icon--preview);
}
2 changes: 2 additions & 0 deletions duties.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ def check_types(ctx: Context) -> None:
ctx.run(
tools.mypy(*PY_SRC_LIST, config_file="config/mypy.ini"),
title=pyprefix("Type-checking"),
# TODO: Update when Pydantic supports 3.14.
nofail=sys.version_info >= (3, 14),
)


Expand Down
8 changes: 8 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ validation:
absolute_links: warn
unrecognized_links: warn

hooks:
- scripts/mkdocs_hooks.py

nav:
- Home:
- Overview: index.md
- Configuration: configuration.md
- Changelog: changelog.md
- Credits: credits.md
- License: license.md
Expand Down Expand Up @@ -87,6 +91,9 @@ markdown_extensions:
- admonition
- callouts
- footnotes
- pymdownx.blocks.admonition
- pymdownx.blocks.tab:
alternate_style: true
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
Expand All @@ -107,6 +114,7 @@ markdown_extensions:

plugins:
- search
- autorefs
- markdown-exec
- gen-files:
scripts:
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ classifiers = [
"Typing :: Typed",
]
dependencies = [
"mkdocstrings>=0.18",
"mkdocstrings>=0.28",
"shellman>=1.0.0",
]

Expand Down Expand Up @@ -106,4 +106,5 @@ dev = [
"mkdocstrings[python]>=0.25",
# YORE: EOL 3.10: Remove line.
"tomli>=2.0; python_version < '3.11'",
"pydantic>=2.10",
]
41 changes: 41 additions & 0 deletions scripts/mkdocs_hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Generate a JSON schema of the Python handler configuration."""

import json
from dataclasses import fields
from os.path import join
from typing import Any

from mkdocs.config.defaults import MkDocsConfig
from mkdocs.plugins import get_plugin_logger

from mkdocstrings_handlers.shell.config import ShellInputConfig, ShellInputOptions

# TODO: Update when Pydantic supports Python 3.14 (sources and duties as well).
try:
from pydantic import TypeAdapter
except ImportError:
TypeAdapter = None # type: ignore[assignment,misc]


logger = get_plugin_logger(__name__)


def on_post_build(config: MkDocsConfig, **kwargs: Any) -> None: # noqa: ARG001
"""Write `schema.json` to the site directory."""
if TypeAdapter is None:
logger.info("Pydantic is not installed, skipping JSON schema generation")
return
adapter = TypeAdapter(ShellInputConfig)
schema = adapter.json_schema()
schema["$schema"] = "https://json-schema.org/draft-07/schema"
with open(join(config.site_dir, "schema.json"), "w") as file:
json.dump(schema, file, indent=2)
logger.debug("Generated JSON schema")

autorefs = config["plugins"]["autorefs"]
for field in fields(ShellInputConfig):
if f"setting-{field.name}" not in autorefs._primary_url_map:
logger.warning(f"Handler setting `{field.name}` is not documented")
for field in fields(ShellInputOptions):
if f"option-{field.name}" not in autorefs._primary_url_map:
logger.warning(f"Configuration option `{field.name}` is not documented")
Loading
Loading