diff --git a/_extensions/classref_admonitions.py b/_extensions/classref_admonitions.py new file mode 100644 index 000000000..c9bc0dbae --- /dev/null +++ b/_extensions/classref_admonitions.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +""" + class_ref_admonitions + ~~~~~~~~~~~~~~~~~~~~~ + + Sphinx extension to format Godot's classref admonitions. + + :copyright: Copyright 2026 by The Godot Engine Community + :license: MIT. +""" + +import re +from docutils import nodes +from docutils.parsers.rst import Directive +from sphinx.writers.html5 import HTML5Translator + + +class classref_admonition(nodes.General, nodes.Element): + pass + + +class classref_important(classref_admonition): + pass + + +class classref_note(classref_admonition): + pass + + +class classref_tip(classref_admonition): + pass + + +class classref_warning(classref_admonition): + pass + + +class BaseClassrefDirective(Directive): + has_content = True + + title = "" + css_class = "" + node_class = classref_admonition + + def run(self): + self.assert_has_content() + + node = self.node_class() + node["title"] = self.title + node["classes"].append(self.css_class) + + self.state.nested_parse( + self.content, + self.content_offset, + node, + ) + + return [node] + + +class ClassrefNoteDirective(BaseClassrefDirective): + node_class = classref_note + title = "Note" + css_class = "note classref-admonition" + + +class ClassrefWarningDirective(BaseClassrefDirective): + node_class = classref_warning + title = "Warning" + css_class = "warning classref-admonition" + + +class ClassrefTipDirective(BaseClassrefDirective): + node_class = classref_tip + title = "Tip" + css_class = "tip classref-admonition" + + +class ClassrefImportantDirective(BaseClassrefDirective): + node_class = classref_important + title = "Important" + css_class = "important classref-admonition" + + +def visit_inline_html(self, node): + classes = " ".join(node["classes"]) + self.body.append(f'

') + self.body.append(f'{node["title"]}: ') + + +def depart_inline_html(self, node): + self.body.append("

") + + +def setup(app): + app.set_translator("html", ClassrefAdmonitionHTMLTranslator, override=True) + for node in ( + classref_important, + classref_note, + classref_tip, + classref_warning, + ): + app.add_node(node, html=(visit_inline_html, depart_inline_html)) + app.add_directive("classref_important", ClassrefImportantDirective) + app.add_directive("classref_note", ClassrefNoteDirective) + app.add_directive("classref_tip", ClassrefTipDirective) + app.add_directive("classref_warning", ClassrefWarningDirective) + + return { + "parallel_read_safe": True, + "parallel_write_safe": True, + } + + +class ClassrefAdmonitionHTMLTranslator(HTML5Translator): + def visit_paragraph(self, node): + if isinstance(node.parent, classref_admonition): + return + super().visit_paragraph(node) + + def depart_paragraph(self, node): + if isinstance(node.parent, classref_admonition): + return + super().depart_paragraph(node) diff --git a/_static/css/custom.css b/_static/css/custom.css index 9e12f4386..d055c0005 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -164,18 +164,28 @@ --admonition-note-color: #404040; --admonition-note-title-background-color: #6ab0de; --admonition-note-title-color: #fff; + --admonition-note-icon: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTggMWE3IDcgMCAwIDAgMCAxNEE3IDcgMCAwIDAgOCAxek03IDRoMnYySDd6bTAgM2gydjVIN3oiLz48L3N2Zz4="); --admonition-attention-background-color: #ffedcc; --admonition-attention-color: #404040; --admonition-attention-title-background-color: #f0b37e; --admonition-attention-title-color: #fff; + --admonition-attention-icon: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTggMWE3IDcgMCAwIDAgMCAxNEE3IDcgMCAwIDAgOCAxek03IDNoMnY3SDd6bTAgOGgydjJIN3oiLz48L3N2Zz4="); --admonition-danger-background-color: #fcf3f2; --admonition-danger-color: #404040; --admonition-danger-title-background-color: #e9a499; --admonition-danger-title-color: #fff; + --admonition-danger-icon: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTggMmExIDEgMCAwIDAtLjg1LjQ4NGwtNiAxMEExIDEgMCAwIDAgMiAxNGgxMmExIDEgMCAwIDAgLjg1Ny0xLjUxNGwtNi0xMGExIDEgMCAwIDAtLjg1LS40ODR6TTcgNWgydjVIN3ptMCA2aDJ2Mkg3eiIvPjwvc3ZnPg=="); --admonition-tip-background-color: #dbfaf4; --admonition-tip-color: #404040; --admonition-tip-title-background-color: #1abc9c; --admonition-tip-title-color: #fff; + --admonition-tip-icon: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTggMWE3IDcgMCAxIDAgMCAxNEE3IDcgMCAwIDAgOCAxem0zLjI5MyAzLjg3NyAxLjQxNCAxLjQxNEw3IDEyLjAwMSAzLjI5MyA4LjI5bDEuNDE0LTEuNDE0TDcgOS4xN3oiLz48L3N2Zz4="); + + --classref-admonition-note-color: color-mix(in oklch, var(--admonition-note-color) 50%, var(--admonition-note-title-background-color)); + --classref-admonition-warning-color: color-mix(in oklch, var(--admonition-attention-color) 50%, var(--admonition-attention-title-background-color)); + --classref-admonition-tip-color: color-mix(in oklch, var(--admonition-tip-color) 50%, var(--admonition-tip-title-background-color)); + --classref-admonition-important-color: color-mix(in oklch, var(--admonition-danger-color) 50%, var(--admonition-danger-title-background-color)); + --classref-admonition-saturation: 300%; --kbd-background-color: #fafbfc; --kbd-outline-color: #d1d5da; @@ -319,6 +329,8 @@ --admonition-tip-title-background-color: #336648; --admonition-tip-title-color: #dfd; + --classref-admonition-saturation: 200%; + --kbd-background-color: #595b5d; --kbd-outline-color: #3d4144; --kbd-shadow-color: #1e2023; @@ -1244,6 +1256,75 @@ code, color: var(--admonition-tip-title-color); } +.rst-content .classref-admonition .admonition-title { + background-color: transparent; + display: inline; +} +.rst-content .classref-admonition .admonition-title::before { + content: ""; + height: 1rem; + top: 0.1rem; + position: relative; + width: 1rem; +} + +.rst-content .classref-admonition.note .admonition-title { + color: var(--classref-admonition-note-color); +} +.rst-content .classref-admonition.note .admonition-title::before { + mask-image: var(--admonition-note-icon); + background-color: var(--classref-admonition-note-color); +} + +.rst-content .classref-admonition.warning .admonition-title { + color: var(--classref-admonition-warning-color); +} +.rst-content .classref-admonition.warning .admonition-title::before { + mask-image: var(--admonition-danger-icon); + background-color: var(--classref-admonition-warning-color); +} + +.rst-content .classref-admonition.tip .admonition-title { + color: var(--classref-admonition-tip-color); +} +.rst-content .classref-admonition.tip .admonition-title::before { + mask-image: var(--admonition-tip-icon); + background-color: var(--classref-admonition-tip-color); +} + +.rst-content .classref-admonition.important .admonition-title { + color: var(--classref-admonition-important-color); +} +.rst-content .classref-admonition.important .admonition-title::before { + mask-image: var(--admonition-attention-icon); + background-color: var(--classref-admonition-important-color); +} + +.rst-content .classref-admonition { + padding: 0px; + padding-left: 12px; + margin-bottom: 12px; + background-color: transparent; + border-left: 0.2rem solid; + filter: saturate(var(--classref-admonition-saturation)); +} + +.rst-content .classref-admonition.note { + border-left-color: var(--classref-admonition-note-color); +} + +.rst-content .classref-admonition.warning { + border-left-color: var(--classref-admonition-warning-color); +} + +.rst-content .classref-admonition.tip { + border-left-color: var(--classref-admonition-tip-color); +} + +.rst-content .classref-admonition.important { + border-left-color: var(--classref-admonition-important-color); +} + .article-status strong { color: var(--body-color); } diff --git a/conf.py b/conf.py index f64d4cb70..fef107e12 100644 --- a/conf.py +++ b/conf.py @@ -20,6 +20,7 @@ extensions = [ "sphinx_copybutton", "sphinxcontrib.video", "gdscript", + "classref_admonitions", ] # Warning when the Sphinx Tabs extension is used with unknown