Skip to content

Commit 299fe48

Browse files
committed
feat: Add Jinja blocks to module, class, function and attribute templates
1 parent 3d8724e commit 299fe48

File tree

5 files changed

+253
-142
lines changed

5 files changed

+253
-142
lines changed

docs/usage/customization.md

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,33 +69,97 @@ for filepath in sorted(path for path in Path(basedir).rglob("*") if "_base" not
6969
See them [in the repository](https://github.com/mkdocstrings/python/tree/master/src/mkdocstrings_handlers/python/templates/).
7070
See the general *mkdocstrings* documentation to learn how to override them: https://mkdocstrings.github.io/theming/#templates.
7171

72-
In preparation for Jinja2 blocks, which will improve customization,
73-
each one of these templates extends a base version in `theme/_base`. Example:
72+
Each one of these templates extends a base version in `theme/_base`. Example:
7473

75-
```html+jinja title="theme/docstring/admonition.html"
76-
{% extends "_base/docstring/admonition.html" %}
74+
```html+jinja title="theme/class.html"
75+
{% extends "_base/class.html" %}
7776
```
7877

79-
```html+jinja title="theme/_base/docstring/admonition.html"
80-
{{ log.debug() }}
81-
<details class="{{ section.value.kind }}">
82-
<summary>{{ section.title|convert_markdown(heading_level, html_id, strip_paragraph=True) }}</summary>
83-
{{ section.value.contents|convert_markdown(heading_level, html_id) }}
84-
</details>
85-
```
86-
87-
It means you will be able to customize only *parts* of a template
78+
Some of these templates define [Jinja blocks](https://jinja.palletsprojects.com/en/3.0.x/templates/#template-inheritance).
79+
allowing to customize only *parts* of a template
8880
without having to fully copy-paste it into your project:
8981

90-
```jinja title="templates/theme/docstring.html"
91-
{% extends "_base/docstring.html" %}
82+
```jinja title="templates/theme/class.html"
83+
{% extends "_base/class.html" %}
9284
{% block contents %}
9385
{{ block.super }}
9486
Additional contents
9587
{% endblock contents %}
9688
```
9789

98-
WARNING: **Block-level customization is not ready yet. We welcome [suggestions](https://github.com/mkdocstrings/python/issues/new).**
90+
### Available blocks
91+
92+
Only the templates for the **Material for MkDocs** provide Jinja blocks.
93+
The following tables show the block names, description,
94+
and the Jinja context available in their scope.
95+
96+
#### `module.html`
97+
98+
- `heading`: The module heading.
99+
- `labels`: The module labels.
100+
- `contents`: The module contents: docstring and children blocks.
101+
- `docstring`: The module docstring.
102+
- `children`: The module children.
103+
104+
Available context:
105+
106+
- `config`: The handler configuration (dictionary).
107+
- `module`: The [Module][griffe.dataclasses.Module] instance.
108+
109+
#### `class.html`
110+
111+
- `heading`: The class heading.
112+
- `labels`: The class labels.
113+
- `signature`: The class signature.
114+
- `contents`: The class contents: bases, docstring, source and children blocks.
115+
- `bases`: The class bases.
116+
- `docstring`: The class docstring.
117+
- `source`: The class source code.
118+
- `children`: The class children.
119+
120+
Available context:
121+
122+
- `config`: The handler configuration (dictionary).
123+
- `class`: The [Class][griffe.dataclasses.Class] instance.
124+
125+
#### `function.html`
126+
127+
- `heading`: The function heading.
128+
- `labels`: The function labels.
129+
- `signature`: The function signature.
130+
- `contents`: The function contents: docstring and source blocks.
131+
- `docstring`: The function docstring.
132+
- `source`: The function source code.
133+
134+
Available context:
135+
136+
- `config`: The handler configuration (dictionary).
137+
- `function`: The [Function][griffe.dataclasses.Function] instance.
138+
139+
#### `attribute.html`
140+
141+
- `heading`: The attribute heading.
142+
- `labels`: The attribute labels.
143+
- `signature`: The attribute signature.
144+
- `contents`: The attribute contents: docstring block.
145+
- `docstring`: The attribute docstring.
146+
147+
Available context:
148+
149+
- `config`: The handler configuration (dictionary).
150+
- `function`: The [Attribute][griffe.dataclasses.Attribute] instance.
151+
152+
#### Docstring sections
153+
154+
In `docstring/attributes.html`, `docstring/other_parameters.html`, `docstring/parameters.html`, `docstring/raises.html`, `docstring/receives.html`, `docstring/returns.html`, `docstring/warns.html`, and `docstring/yields.html`:
155+
156+
- `table_style`: The section as a table.
157+
- `list_style`: The section as a list.
158+
- `spacy_style`: The section as a Spacy table.
159+
160+
Available context:
161+
162+
- `section`: The [DocstringSection][griffe.docstrings.dataclasses.DocstringSection] instance (see `DocstringSection*` subclasses).
99163

100164
## Style recommendations
101165

src/mkdocstrings_handlers/python/templates/material/_base/attribute.html

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,37 @@
2121
class="doc doc-heading",
2222
toc_label=attribute.name) %}
2323

24-
{% if config.separate_signature %}
25-
<span class="doc doc-object-name doc-attribute-name">{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}</span>
26-
{% else %}
27-
{% filter highlight(language="python", inline=True) %}
28-
{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}
29-
{% if attribute.annotation %}: {{ attribute.annotation }}{% endif %}
30-
{% if attribute.value %} = {{ attribute.value }}{% endif %}
31-
{% endfilter %}
32-
{% endif %}
24+
{% block heading scoped %}
25+
{% if config.separate_signature %}
26+
<span class="doc doc-object-name doc-attribute-name">{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}</span>
27+
{% else %}
28+
{% filter highlight(language="python", inline=True) %}
29+
{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}
30+
{% if attribute.annotation %}: {{ attribute.annotation }}{% endif %}
31+
{% if attribute.value %} = {{ attribute.value }}{% endif %}
32+
{% endfilter %}
33+
{% endif %}
34+
{% endblock heading %}
3335

34-
{% with labels = attribute.labels %}
35-
{% include "labels.html" with context %}
36-
{% endwith %}
36+
{% block labels scoped %}
37+
{% with labels = attribute.labels %}
38+
{% include "labels.html" with context %}
39+
{% endwith %}
40+
{% endblock labels %}
3741

3842
{% endfilter %}
3943

40-
{% if config.separate_signature %}
41-
{% filter highlight(language="python", inline=False) %}
42-
{% filter format_code(config.line_length) %}
43-
{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}
44-
{% if attribute.annotation %}: {{ attribute.annotation|safe }}{% endif %}
45-
{% if attribute.value %} = {{ attribute.value|safe }}{% endif %}
44+
{% block signature scoped %}
45+
{% if config.separate_signature %}
46+
{% filter highlight(language="python", inline=False) %}
47+
{% filter format_code(config.line_length) %}
48+
{% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %}
49+
{% if attribute.annotation %}: {{ attribute.annotation|safe }}{% endif %}
50+
{% if attribute.value %} = {{ attribute.value|safe }}{% endif %}
51+
{% endfilter %}
4652
{% endfilter %}
47-
{% endfilter %}
48-
{% endif %}
53+
{% endif %}
54+
{% endblock signature %}
4955

5056
{% else %}
5157
{% if config.show_root_toc_entry %}
@@ -60,9 +66,13 @@
6066
{% endif %}
6167

6268
<div class="doc doc-contents {% if root %}first{% endif %}">
63-
{% with docstring_sections = attribute.docstring.parsed %}
64-
{% include "docstring.html" with context %}
65-
{% endwith %}
69+
{% block contents scoped %}
70+
{% block docstring scoped %}
71+
{% with docstring_sections = attribute.docstring.parsed %}
72+
{% include "docstring.html" with context %}
73+
{% endwith %}
74+
{% endblock docstring %}
75+
{% endblock contents %}
6676
</div>
6777

6878
{% endwith %}

src/mkdocstrings_handlers/python/templates/material/_base/class.html

Lines changed: 73 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,40 @@
2121
class="doc doc-heading",
2222
toc_label=class.name) %}
2323

24-
{% if config.separate_signature %}
25-
<span class="doc doc-object-name doc-class-name">{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}</span>
26-
{% elif config.merge_init_into_class and "__init__" in class.members -%}
27-
{%- with function = class.members["__init__"] -%}
28-
{%- filter highlight(language="python", inline=True) -%}
29-
{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}
30-
{%- include "signature.html" with context -%}
31-
{%- endfilter -%}
32-
{%- endwith -%}
33-
{% else %}
34-
<code>{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}</code>
35-
{% endif %}
24+
{% block heading scoped %}
25+
{% if config.separate_signature %}
26+
<span class="doc doc-object-name doc-class-name">{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}</span>
27+
{% elif config.merge_init_into_class and "__init__" in class.members -%}
28+
{%- with function = class.members["__init__"] -%}
29+
{%- filter highlight(language="python", inline=True) -%}
30+
{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}
31+
{%- include "signature.html" with context -%}
32+
{%- endfilter -%}
33+
{%- endwith -%}
34+
{% else %}
35+
<code>{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}</code>
36+
{% endif %}
37+
{% endblock heading %}
3638

37-
{% with labels = class.labels %}
38-
{% include "labels.html" with context %}
39-
{% endwith %}
39+
{% block labels scoped %}
40+
{% with labels = class.labels %}
41+
{% include "labels.html" with context %}
42+
{% endwith %}
43+
{% endblock labels %}
4044

4145
{% endfilter %}
4246

43-
{% if config.separate_signature and config.merge_init_into_class %}
44-
{% if "__init__" in class.members %}
45-
{% with function = class.members["__init__"] %}
46-
{% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %}
47-
{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}
48-
{% endfilter %}
49-
{% endwith %}
47+
{% block signature scoped %}
48+
{% if config.separate_signature and config.merge_init_into_class %}
49+
{% if "__init__" in class.members %}
50+
{% with function = class.members["__init__"] %}
51+
{% filter format_signature(function, config.line_length, crossrefs=config.signature_crossrefs) %}
52+
{% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %}
53+
{% endfilter %}
54+
{% endwith %}
55+
{% endif %}
5056
{% endif %}
51-
{% endif %}
57+
{% endblock signature %}
5258

5359
{% else %}
5460
{% if config.show_root_toc_entry %}
@@ -63,47 +69,56 @@
6369
{% endif %}
6470

6571
<div class="doc doc-contents {% if root %}first{% endif %}">
66-
{% if config.show_bases and class.bases %}
67-
<p class="doc doc-class-bases">
68-
Bases: {% for expression in class.bases -%}
69-
<code>{% include "expression.html" with context %}</code>{% if not loop.last %}, {% endif %}
70-
{% endfor -%}
71-
</p>
72-
{% endif %}
73-
74-
{% with docstring_sections = class.docstring.parsed %}
75-
{% include "docstring.html" with context %}
76-
{% endwith %}
72+
{% block contents scoped %}
73+
{% block bases scoped %}
74+
{% if config.show_bases and class.bases %}
75+
<p class="doc doc-class-bases">
76+
Bases: {% for expression in class.bases -%}
77+
<code>{% include "expression.html" with context %}</code>{% if not loop.last %}, {% endif %}
78+
{% endfor -%}
79+
</p>
80+
{% endif %}
81+
{% endblock bases %}
7782

78-
{% if config.merge_init_into_class %}
79-
{% if "__init__" in class.members and class.members["__init__"].has_docstring %}
80-
{% with docstring_sections = class.members["__init__"].docstring.parsed %}
83+
{% block docstring scoped %}
84+
{% with docstring_sections = class.docstring.parsed %}
8185
{% include "docstring.html" with context %}
8286
{% endwith %}
83-
{% endif %}
84-
{% endif %}
87+
{% if config.merge_init_into_class %}
88+
{% if "__init__" in class.members and class.members["__init__"].has_docstring %}
89+
{% with docstring_sections = class.members["__init__"].docstring.parsed %}
90+
{% include "docstring.html" with context %}
91+
{% endwith %}
92+
{% endif %}
93+
{% endif %}
94+
{% endblock docstring %}
8595

86-
{% if config.show_source %}
87-
{% if config.merge_init_into_class %}
88-
{% if "__init__" in class.members and class.members["__init__"].source %}
89-
<details class="quote">
90-
<summary>Source code in <code>{{ class.relative_filepath }}</code></summary>
91-
{{ class.members["__init__"].source|highlight(language="python", linestart=class.members["__init__"].lineno, linenums=True) }}
92-
</details>
96+
{% block source scoped %}
97+
{% if config.show_source %}
98+
{% if config.merge_init_into_class %}
99+
{% if "__init__" in class.members and class.members["__init__"].source %}
100+
<details class="quote">
101+
<summary>Source code in <code>{{ class.relative_filepath }}</code></summary>
102+
{{ class.members["__init__"].source|highlight(language="python", linestart=class.members["__init__"].lineno, linenums=True) }}
103+
</details>
104+
{% endif %}
105+
{% elif class.source %}
106+
<details class="quote">
107+
<summary>Source code in <code>{{ class.relative_filepath }}</code></summary>
108+
{{ class.source|highlight(language="python", linestart=class.lineno, linenums=True) }}
109+
</details>
110+
{% endif %}
93111
{% endif %}
94-
{% elif class.source %}
95-
<details class="quote">
96-
<summary>Source code in <code>{{ class.relative_filepath }}</code></summary>
97-
{{ class.source|highlight(language="python", linestart=class.lineno, linenums=True) }}
98-
</details>
99-
{% endif %}
100-
{% endif %}
112+
{% endblock source %}
101113

102-
{% with obj = class %}
103-
{% set root = False %}
104-
{% set heading_level = heading_level + 1 %}
105-
{% include "children.html" with context %}
106-
{% endwith %}
114+
{% block children scoped %}
115+
{% with obj = class %}
116+
{% set root = False %}
117+
{% set heading_level = heading_level + 1 %}
118+
{% include "children.html" with context %}
119+
{% endwith %}
120+
{% endblock children %}
121+
{% endblock contents %}
107122
</div>
108123

109124
{% endwith %}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy