From 474e9eb0f807d1b57e4e9a1c3ac78375d326c93a Mon Sep 17 00:00:00 2001 From: moanos Date: Sun, 19 Oct 2025 09:40:51 +0200 Subject: [PATCH] feat: Add extension to sphinx that includes drawio diagrams --- docs/_ext/drawio.py | 67 +++++++++++++++++++++++++++++++++++++++++++++ docs/conf.py | 12 ++++---- 2 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 docs/_ext/drawio.py diff --git a/docs/_ext/drawio.py b/docs/_ext/drawio.py new file mode 100644 index 0000000..b5ff91d --- /dev/null +++ b/docs/_ext/drawio.py @@ -0,0 +1,67 @@ +from __future__ import annotations + +from pathlib import Path + +from docutils import nodes +from sphinx.application import Sphinx +from sphinx.util.docutils import SphinxDirective +from sphinx.util.typing import ExtensionMetadata + + +class DrawioDirective(SphinxDirective): + """A directive to show a drawio diagram! + + Usage: + .. drawio:: + example-diagram.drawio.html + example-diagram.drawio.png + """ + + has_content = False + required_arguments = 2 # html and png + + def run(self) -> list[nodes.Node]: + html_path = self.arguments[0] + png_path = self.arguments[1] + + env = self.state.document.settings.env + + docdir = Path(env.doc2path(env.docname)).parent + html_rel = Path(self.arguments[0]) + png_rel = Path(self.arguments[1]) + + html_path = (docdir / html_rel).resolve() + png_path = (docdir / png_rel).resolve() + + container = nodes.container() + + # HTML output -> raw HTML node + if self.builder.format == "html": + # Embed the HTML file contents directly + raw_html_node = nodes.raw( + "", + f'
{open(html_path, encoding="utf-8").read()}
', + format="html", + ) + container += raw_html_node + else: + # Other outputs -> PNG image node + image_node = nodes.image(uri=png_path) + container += image_node + + return [container] + + @property + def builder(self): + # Helper to access the builder from the directive context + return self.state.document.settings.env.app.builder + + +def setup(app: Sphinx) -> ExtensionMetadata: + app.add_directive("drawio", DrawioDirective) + + return { + "version": "0.1", + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/docs/conf.py b/docs/conf.py index 9eade3e..8545c41 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,6 +16,10 @@ # import sys # sys.path.insert(0, os.path.abspath('.')) +import sys +from pathlib import Path + +sys.path.append(str(Path('_ext').resolve())) # -- Project information ----------------------------------------------------- @@ -28,7 +32,6 @@ version = '' # The full version, including alpha/beta/rc tags release = '0.2.0' - # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -40,6 +43,7 @@ release = '0.2.0' # ones. extensions = [ 'sphinx.ext.ifconfig', + 'drawio' ] # Add any paths that contain templates here, relative to this directory. @@ -69,7 +73,6 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = None - # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for @@ -104,7 +107,6 @@ html_static_path = ['_static'] # Output file base name for HTML help builder. htmlhelp_basename = 'notfellchen' - # -- Options for LaTeX output ------------------------------------------------ latex_elements = { @@ -133,7 +135,6 @@ latex_documents = [ 'Julian-Samuel Gebühr', 'manual'), ] - # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples @@ -143,7 +144,6 @@ man_pages = [ [author], 1) ] - # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples @@ -155,7 +155,6 @@ texinfo_documents = [ 'Miscellaneous'), ] - # -- Options for Epub output ------------------------------------------------- # Bibliographic Dublin Core info. @@ -173,5 +172,4 @@ epub_title = project # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] - # -- Extension configuration -------------------------------------------------