Day 19 — I madeth a Sphinx extension

Today I thought that adding a gallery to display what everyone is building with present would be great! I guess this was a distraction from the talk research I previously mentioned (which I need to finish ASAP!) :(

But I learned how to write a simple Sphinx extension, which is cool! I had to run a lot of "how to do this in html and css" searches though.

Sphinx is a tool that you can use to write beautiful docs using reStructuredText. To define your own reStructuredText directive, you can extend the Directive class from docutils:


  from docutils.parsers.rst import Directive, directives

  class GalleryImage(Directive):
      has_content = False
      required_arguments = 0
      optional_arguments = 0
      final_argument_whitespace = True
      option_spec = {
          "src": directives.unchanged,
          "stub": directives.unchanged,
          "description": directives.unchanged,
      }

      def run(self):
          ...

After this, you need to register this new directive with Sphinx using app.add_directive("gallery_image", GalleryImage) in a setup(app) function. The option_spec declares the options that you can use with the directive in your docs:


  .. gallery_image::
      :src: _static/gallery/the-hitchhikers-guide-to-clis-in-python.png
      :stub: the-hitchhikers-guide-to-clis-in-python
      :description: The Hitchhiker's Guide to CLIs in Python by Vinayak Mehta

You also need to define how the directive and its options should be converted into HTML, and then add that HTML to the page body.


  def gallery_image_html(self, node):
      src = node["src"]
      stub = node["stub"]
      description = node["description"]

      template = f"""
      <div class="gallery">
        <a href="{stub}/index.html">
          <img src="/en/latest/{src}" width="600" height="400">
          <div class="desc">{description}</div>
        </a>
      </div>
      """
      self.body.append(template)

      raise SkipNode

Finally, you need to add the extension to your Sphinx conf.py. You can check out full extension here.