Skip to content

Commit a738925

Browse files
authored
Styling version directives (#246)
resolves #243 This does not override the original sphinx directives `versionadded`, `versionchanged`, and `deprecated`. Rather, the CSS styles have been adjusted to render these directives as admonitions. The default styles can be customized using the custom admonitions feature, but only `color` and `icon` will apply (as long as the `name` matches the directive name). Also adds the italicized style inherent in Sphinx' basic theme CSS.
1 parent 3625a8f commit a738925

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

docs/admonitions.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,40 @@ usage in other sphinx-based themes.
5353
.. error::
5454
You have made a grave :dutree:`error`.
5555

56+
Version Directives
57+
******************
58+
59+
The `versionadded`, `versionchanged`, and `deprecated` directives defined by Sphinx are also
60+
rendered by the sphinx-immaterial theme as admonitions.
61+
62+
These admonition styles can be customized using the `Custom Admonitions`_ feature provided the
63+
:py:attr:`~sphinx_immaterial.custom_admonitions.CustomAdmonitionConfig.name` matches the directive
64+
name, but only the
65+
:py:attr:`~sphinx_immaterial.custom_admonitions.CustomAdmonitionConfig.icon` and
66+
:py:attr:`~sphinx_immaterial.custom_admonitions.CustomAdmonitionConfig.color` options will apply;
67+
all other options are ignored.
68+
69+
.. code-block:: py
70+
:caption: Adjusting the `versionchanged` style
71+
72+
sphinx_immaterial_custom_admonitions = [
73+
{
74+
"name": "versionchanged",
75+
"color": (27, 138, 236),
76+
"icon": "material/alert-rhombus",
77+
}
78+
]
79+
80+
.. rst-example::
81+
82+
.. versionadded:: 1.0
83+
Description in title.
84+
85+
Some additional context.
86+
.. versionchanged:: 2.0
87+
Description in title.
88+
.. deprecated:: 3.0
89+
5690
.. _inherited_admonitions:
5791

5892
Admonitions from mkdocs-material

sphinx_immaterial/custom_admonitions.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from sphinx.writers.html5 import HTML5Translator
1919
from .css_and_javascript_bundles import add_global_css
2020
from .inline_icons import load_svg_into_builder_env, get_custom_icons
21+
from . import html_translator_mixin
2122

2223
logger = getLogger(__name__)
2324

@@ -26,6 +27,13 @@
2627

2728
_CUSTOM_ADMONITIONS_KEY = "sphinx_immaterial_custom_admonitions"
2829

30+
# defaults used for version directives re-styling
31+
VERSION_DIR_STYLE = {
32+
"versionadded": {"icon": "material/alert-circle", "color": (72, 138, 87)},
33+
"versionchanged": {"icon": "material/alert-circle", "color": (238, 144, 64)},
34+
"deprecated": {"icon": "material/delete", "color": (203, 70, 83)},
35+
}
36+
2937

3038
class CustomAdmonitionConfig(pydantic.BaseModel):
3139
"""This data class validates the user's configuration value(s) in
@@ -146,6 +154,22 @@ def depart_admonition(self: HTML5Translator, node: Optional[nodes.Element] = Non
146154
HTML5Translator.depart_admonition = depart_admonition # type: ignore[assignment]
147155

148156

157+
@html_translator_mixin.override
158+
def visit_versionmodified(
159+
self: html_translator_mixin.HTMLTranslatorMixin,
160+
node: sphinx.addnodes.versionmodified,
161+
super_func: html_translator_mixin.BaseVisitCallback[
162+
sphinx.addnodes.versionmodified
163+
],
164+
) -> None:
165+
# similar to what the OG visitor does but with an added admonition class
166+
self.body.append(self.starttag(node, "div", CLASSES=[node["type"], "admonition"]))
167+
# do compatibility check for changes in Sphinx
168+
assert len(node) >= 1 and isinstance(node[0], nodes.paragraph)
169+
# add admonition-title class to first paragraph
170+
node[0]["classes"].append("admonition-title")
171+
172+
149173
patch_visit_admonition()
150174
patch_depart_admonition()
151175

@@ -257,7 +281,20 @@ def on_builder_inited(app: Sphinx):
257281
custom_admonitions: List[CustomAdmonitionConfig] = getattr(
258282
config, "sphinx_immaterial_custom_admonitions"
259283
)
284+
custom_admonition_names = []
260285
for admonition in custom_admonitions:
286+
custom_admonition_names.append(admonition.name)
287+
if admonition.name in VERSION_DIR_STYLE: # if specific to version directives
288+
admonition.icon = load_svg_into_builder_env(
289+
app.builder,
290+
admonition.icon
291+
or cast(str, VERSION_DIR_STYLE[admonition.name]["icon"]),
292+
)
293+
if admonition.color is None:
294+
admonition.color = cast(
295+
Tuple[int, int, int], VERSION_DIR_STYLE[admonition.name]["color"]
296+
)
297+
continue # don't override the version directives
261298
app.add_directive(
262299
name=admonition.name,
263300
cls=get_directive_class(
@@ -270,6 +307,18 @@ def on_builder_inited(app: Sphinx):
270307
admonition.name = nodes.make_id(admonition.name)
271308
if admonition.icon is not None:
272309
admonition.icon = load_svg_into_builder_env(app.builder, admonition.icon)
310+
311+
# add styles for sphinx directives versionadded, versionchanged, and deprecated
312+
for name, style in VERSION_DIR_STYLE.items():
313+
if name in custom_admonition_names:
314+
continue # already handled above
315+
# add entries for default style of version directives
316+
version_dir_style = CustomAdmonitionConfig(
317+
name=name,
318+
icon=load_svg_into_builder_env(app.builder, cast(str, style["icon"])),
319+
color=style["color"],
320+
)
321+
custom_admonitions.append(version_dir_style)
273322
setattr(app.builder.env, "sphinx_immaterial_custom_admonitions", custom_admonitions)
274323

275324

src/assets/stylesheets/main/_sphinx.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,8 @@
8383
.viewcode-block .viewcode-back {
8484
float: right;
8585
}
86+
87+
.versionmodified {
88+
font-style: italic;
89+
}
8690
}

0 commit comments

Comments
 (0)