Additional Samples

Various examples of styling applied to Sphinx constructs. You can view the source of this page to see the specific reStructuredText used to create these examples.

Headings

This is a first level heading (h1).

Sub-Heading

This is a second level heading (h2).

Sub-Sub-Heading

This is a third level heading (h3).

Code

The theme uses pygments for ``inline code text`` and
::

   multiline
   code text

The theme uses pygments for inline code text and

multiline
code text

Here’s an included example with line numbers.

.. literalinclude:: ../sphinx_immaterial/apidoc/python/autodoc_property_type.py
   :caption: source from this theme in *sphinx_immaterial/apidoc/python/autodoc_property_type.py*
   :linenos:
source from this theme in sphinx_immaterial/apidoc/python/autodoc_property_type.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""Adds support for obtaining property types from docstring signatures, and
improves formatting by PyProperty of type annotations."""
import re
from typing import Tuple, Optional, Any

import sphinx
import sphinx.addnodes
import sphinx.domains
import sphinx.domains.python
import sphinx.ext.autodoc
import sphinx.util.inspect
import sphinx.util.typing

if sphinx.version_info >= (6, 1):
    stringify_annotation = sphinx.util.typing.stringify_annotation
else:
    stringify_annotation = sphinx.util.typing.stringify  # type: ignore[attr-defined]

PropertyDocumenter = sphinx.ext.autodoc.PropertyDocumenter


property_sig_re = re.compile("^(\\(.*)\\)\\s*->\\s*(.*)$")


def _get_property_getter(obj: Any) -> Any:
    # property
    func = sphinx.util.inspect.safe_getattr(obj, "fget", None)
    if func is None:
        # cached_property
        func = sphinx.util.inspect.safe_getattr(obj, "func", None)
    return func


def _get_return_type_from_fget_doc(obj: Any) -> Optional[str]:
    fget = _get_property_getter(obj)
    if fget is None:
        return None
    doc = sphinx.util.inspect.safe_getattr(fget, "__doc__", None)
    if doc is None:
        return None
    line = doc.splitlines()[0]
    line = line.rstrip("\\").strip()
    match = property_sig_re.match(line)
    if not match:
        return None
    _, retann = match.groups()
    return retann


def apply_property_documenter_type_annotation_fix():
    # Modify PropertyDocumenter to support obtaining signature from docstring.

    orig_import_object = PropertyDocumenter.import_object

    def import_object(self: PropertyDocumenter, raiseerror: bool = False) -> bool:
        result = orig_import_object(self, raiseerror)
        if not result:
            return False

        func = _get_property_getter(self.object)

        if func is not None:
            try:
                signature = sphinx.util.inspect.signature(
                    func, type_aliases=self.config.autodoc_type_aliases
                )
                if (
                    signature.return_annotation
                    is not sphinx.util.inspect.Parameter.empty
                ):
                    self.retann = stringify_annotation(signature.return_annotation)
                return True
            except:  # pylint: disable=bare-except
                pass

        if not self.retann:
            new_retann = _get_return_type_from_fget_doc(self.object)
            if new_retann is not None:
                self.retann = new_retann
        return True

    PropertyDocumenter.import_object = import_object  # type: ignore[assignment]

    old_add_directive_header = PropertyDocumenter.add_directive_header

    def add_directive_header(self, sig: str) -> None:
        start_line = len(self.directive.result.data)
        old_add_directive_header(self, sig)

        # Check for return annotation
        retann = self.retann or _get_return_type_from_fget_doc(self.object)
        if retann is None:
            return

        # Check if type annotation has already been added.
        type_line_prefix = self.indent + "   :type: "
        for line in self.directive.result.data[start_line:]:
            if line.startswith(type_line_prefix):
                return

        # Type annotation not already added.
        self.add_line("   :type: " + retann, self.get_sourcename())

    PropertyDocumenter.add_directive_header = add_directive_header  # type: ignore[assignment]

    # Modify PyProperty to improve formatting of :type: option
    PyProperty = sphinx.domains.python.PyProperty

    def handle_signature(
        self, sig: str, signode: sphinx.addnodes.desc_signature
    ) -> Tuple[str, str]:
        fullname, prefix = super(PyProperty, self).handle_signature(sig, signode)

        typ = self.options.get("type")
        if typ:
            signode += sphinx.addnodes.desc_sig_punctuation("", " : ")
            signode += sphinx.domains.python._parse_annotation(typ, self.env)

        return fullname, prefix

    PyProperty.handle_signature = handle_signature  # type: ignore[assignment]


apply_property_documenter_type_annotation_fix()

It also works with existing Sphinx highlighting:

.. code-block:: html

   <html>
     <body>Hello World</body>
   </html>

.. code-block:: python

   def hello():
       """Greet."""
       return "Hello World"

.. code-block:: javascript

   /**
   * Greet.
   */
   function hello(): {
       return "Hello World";
   }
<html>
  <body>Hello World</body>
</html>
def hello():
    """Greet."""
    return "Hello World"
/**
* Greet.
*/
function hello(): {
    return "Hello World";
}

Footnotes

I have footnoted a first item [#f1]_ and second item [#f2]_.
This also references the second item [#f2]_.

.. rubric:: Footnotes
.. [#f1] My first footnote.
.. [#f2] My second footnote.

I have footnoted a first item [1] and second item [2]. This also references the second item [2].

Footnotes

Tables

Here are some examples of Sphinx tables. The Sphinx Material all classes and only applies the default style to classless tables. If you want to use a custom table class, you will need to do two thing. First, apply it using .. cssclass:: custom-class and then add it to your configuration’s table_classes variable.

Grid

A grid table:
+------------------------+------------+----------+----------+
| Header1                | Header2    | Header3  | Header4  |
+========================+============+==========+==========+
| row1, cell1            | cell2      | cell3    | cell4    |
+------------------------+------------+----------+----------+
| row2 ...               | ...        | ...      |          |
+------------------------+------------+----------+----------+
| ...                    | ...        | ...      |          |
+------------------------+------------+----------+----------+

Header1

Header2

Header3

Header4

row1, cell1

cell2

cell3

cell4

row2 …

Simple

A simple table:
=====  =====  =======
H1     H2     H3
=====  =====  =======
cell1  cell2  cell3
...    ...    ...
...    ...    ...
=====  =====  =======

H1

H2

H3

cell1

cell2

cell3

User-styled Table

Note

table_classes is set to ["plain"] in the site’s configuration. Only plain remains as the class of the table. Other standard classes applied by Sphinx are removed.

This is feature demonstration. There is no css for the plain class, and so this is completely unstyled.

.. cssclass:: plain

=====  ======  =======
User   Styled  Table
=====  ======  =======
cell1  cell2   cell3
...    ...     ...
...    ...     ...
=====  ======  =======

User

Styled

Table

cell1

cell2

cell3

List Tables

.. list-table:: A List Table
   :header-rows: 1

   * - Column 1
     - Column 2
   * - Item 1
     - Item 2
A List Table

Column 1

Column 2

Item 1

Item 2

Alignment

.. list-table:: Center Aligned
   :header-rows: 1
   :align: center

   * - Column 1
     - Column 2
   * - Item 1
     - Item 2
Center Aligned

Column 1

Column 2

Item 1

Item 2

.. list-table:: Right Aligned
   :widths: 15 10 30
   :header-rows: 1
   :align: right

   * - Treat
     - Quantity
     - Description
   * - Albatross
     - 2.99
     - On a stick!
   * - Crunchy Frog
     - 1.49
     - If we took the bones out
   * - Gannet Ripple
     - 1.99
     - On a stick!
Right Aligned

Treat

Quantity

Description

Albatross

2.99

On a stick!

Crunchy Frog

1.49

If we took the bones out

Gannet Ripple

1.99

On a stick!

Glossaries

.. glossary::

   environment
      A structure where information about all documents under the root is
      saved, and used for cross-referencing.  The environment is pickled
      after the parsing stage, so that successive runs only need to read
      and parse new and changed documents.

   source directory
      The directory which, including its subdirectories, contains all
      source files for one Sphinx project.
environment

A structure where information about all documents under the root is saved, and used for cross-referencing. The environment is pickled after the parsing stage, so that successive runs only need to read and parse new and changed documents.

source directory

The directory which, including its subdirectories, contains all source files for one Sphinx project.

Math

.. math::

   (a + b)^2 = a^2 + 2ab + b^2

   (a - b)^2 = a^2 - 2ab + b^2
\[ \begin{align}\begin{aligned}(a + b)^2 = a^2 + 2ab + b^2\\(a - b)^2 = a^2 - 2ab + b^2\end{aligned}\end{align} \]
.. math::

   (a + b)^2  &=  (a + b)(a + b) \\
              &=  a^2 + 2ab + b^2
\[\begin{split}(a + b)^2 &= (a + b)(a + b) \\ &= a^2 + 2ab + b^2\end{split}\]
.. math::
   :nowrap:

   \begin{eqnarray}
      y    & = & ax^2 + bx + c \\
      f(x) & = & x^2 + 2xy + y^2
   \end{eqnarray}
\begin{eqnarray} y & = & ax^2 + bx + c \\ f(x) & = & x^2 + 2xy + y^2 \end{eqnarray}

Production Lists

The following productionlist is a modified example taken from the Graphviz documentation

Grammar for dot syntax
.. productionlist::
   graph      : [ strict ] (`graph` | digraph) [ ID ] '{' `stmt_list` '}'
   stmt_list  : [ `stmt` [ ';' ] `stmt_list` ]
   stmt       : `node_stmt`
              : `edge_stmt`
              : `attr_stmt`
              : ID '=' ID
              : `subgraph`
   attr_stmt  : (`graph` | node | edge) `attr_list`
   attr_list  : '[' [ `a_list` ] ']' [ `attr_list` ]
   a_list     : ID '=' ID [ (';' | ',') ] [ `a_list` ]
   edge_stmt  : (`node_id` | `subgraph`) `edgeRHS` [ `attr_list` ]
   edgeRHS    : edgeop (`node_id` | `subgraph`) [ `edgeRHS` ]
   node_stmt  : `node_id` [ `attr_list` ]
   node_id    : ID [ `port` ]
   port       : ':' ID [ ':' `compass_pt` ]
              : ':' `compass_pt`
   subgraph   : [ `subgraph` [ ID ] ] '{' `stmt_list` '}'
   compass_pt : (n | ne | e | se | s | sw | w | nw | c | _)

This is a reference to the grammar for a :token:`graph` in dot syntax.
graph      ::=  [ strict ] (graph | digraph) [ ID ] '{' stmt_list '}'
stmt_list  ::=  [ stmt [ ';' ] stmt_list ]
stmt       ::=  node_stmt
                edge_stmt
                attr_stmt
                ID '=' ID
                subgraph
attr_stmt  ::=  (graph | node | edge) attr_list
attr_list  ::=  '[' [ a_list ] ']' [ attr_list ]
a_list     ::=  ID '=' ID [ (';' | ',') ] [ a_list ]
edge_stmt  ::=  (node_id | subgraph) edgeRHS [ attr_list ]
edgeRHS    ::=  edgeop (node_id | subgraph) [ edgeRHS ]
node_stmt  ::=  node_id [ attr_list ]
node_id    ::=  ID [ port ]
port       ::=  ':' ID [ ':' compass_pt ]
                ':' compass_pt
subgraph   ::=  [ subgraph [ ID ] ] '{' stmt_list '}'
compass_pt ::=  (n | ne | e | se | s | sw | w | nw | c | _)

This is a reference to the grammar for a graph in dot syntax.

Sub-pages


Last update: Apr 16, 2024