Documenting with Sphinx#

This page is dedicated to help editors to write RST files in XLiFE++ documentation.

Short introduction to Sphinx#

Sphinx is a python documentation generator, originally dedicated to python codes, but now accepting C/C++/Fortran codes. In comparison with Doxygen, Sphinx provides modern themes and the ability to write static pages very easily. Documentation can be generated in different formats: HTML, PDF (through LaTeX), EPUB, … The input files are written in RST format (or in Markdown format, with the dedicated extension).

Here is the Sphinx reference documentation

Configuration file and extensions#

When generating a documentation project, the most important file is the configuration file conf.py in the source directory. In this file, you will:

  • Include Sphinx extensions to enable additional RST directives and roles (aka commands);

  • Define configuration parameters of your website: global parameters, extensions parameters, …

  • Define the HTML theme (here we chose PyData)

  • Implement a setup() method to run python code before generating your documentation

When ready, you just have to call make with the appropriate target to generate your documentation

Let’s talk now about the RST syntax.

The RST syntax#

RST files are ASCII formatted files with markups. Block markups are called directives and inline markups are called roles. Here is the general syntax of a directive and a role:

.. directive-name:: [directive-parameter]

  directive-content

:role-name:`role-content`

Some directives need a parameter and others not. As in python syntax, the content is indented. Directive can also have options:

.. directive-name:: [directive-parameter]
  :direction-option1: val1
  :direction-option2: val2

  directive-content

About paths#

For some directives or roles, you will have to give a filename with its path (images, code files, …). You may preferentially set absolute paths, but you just have to know one thing: in absolute paths, the first / means the root directory of the project, namely the directory that contains conf.py, i.e. source directory in your Sphinx project.

Headings and tables of contents#

There is no special markup to define headings. Rather than imposing a fixed number and order of section title adornment styles, the order enforced will be the order as encountered. The first style encountered will be an outermost title (like HTML H1), the second style will be a subtitle, the third will be a subsubtitle, and so on. Here are the recommended characters: = - ` : . ‘ “ ~ ^ _ * + # and the adopted convention:

parts
#####

chapters
********

sections
++++++++

subsections
===========

subsubsections
--------------

paragraphs
..........

The toctree directive is used to define tables of contents. Here is the one defined in index.rst:

.. toctree::
  :maxdepth: 2
  :hidden:
  :caption: Contents:

  intro
  examples
  doc
  language
  api
  events/index

The caption option defines the title of the table of contents. The maxdepth option defines the number of levels used in the table of contents. The hidden option prevents the table of contents from being displayed in the left sidebar.

Then you give the file names you want to appear in the table of contents. You may have noticed there is no level information about the included files. So, how to define sublevels ? By using toctree directive in child files.

With PyData theme, the toctree defined in the root RST file (generally called index.rst) defines the header menu.

Text styles#

The standard RST inline markup is quite simple: use

  • Use one asterisk for emphasis (italics). For instance: *text*.

  • Use two asterisks for strong emphasis (boldface): For instance: **text**.

  • Use double backquotes for code samples. For instance, ``text``.

Lists#

Unnumbered lists items start with a single markup such as - and the content of an item has to be indented properly if on several lines.

* This is a bulleted list with asterisk.
* It has two items, the second
  item uses two lines.

- This is a bulleted list with dash.
- It has two items, the second
  item uses two lines.
  • This is a bulleted list with asterisk.

  • It has two items, the second item uses two lines.

  • This is a bulleted list with dash.

  • It has two items, the second item uses two lines.

Numbered lists items start with a single markup such as a number followed by ., or #. and the content of an item has to be indented properly if on several lines. With #. markup, numbering is automatical.

1. This is a numbered list.
2. It has two items too.

#. This is a numbered list.
#. It has two items too.
  1. This is a numbered list.

  2. It has two items too.

  3. This is a numbered list.

  4. It has two items too.

Description lists are very light syntax.

item 1
  item 1 description

item 2
  item 2 description

Images and figures#

The image directive is used to display an image.

.. image:: /_static/events/roscoff18/affiche.png
  :width: 80%
  :align: center

The figure directive is used to display an image with a caption (and a legend).

.. figure:: /_static/pictures/doc/bin_win_conf_1.png
  :width: 80%

  optional caption on a single line

  optional legend
  as a paragraph

Both have several options: width, height, align, alt, target, …

target is to set a link.

XLiFE++ loads the sphinx_subfigure (sphinx-subfigure documentation) extension that provides subfigure directive to create figures with several images.

.. subfigure:: AB

  .. image:: /_static/pictures/examples/U_OmegaFig1.png

  .. image:: /_static/pictures/examples/U_OmegaFig2.png
../_images/U_OmegaFig1.png
../_images/U_OmegaFig2.png

The subfigure parameter is the definition the structure of the subfigure. A represents the first image, B the second one … AB means that there will be two figures side by side taking half the width, whereas A|B means that the first image will be above the other one.

Tables#

Grid tables are described with a visual grid made up of the characters “-”, “=”, “|”, and “+”. The hyphen (“-”) is used for horizontal lines (row separators). The equals sign (“=”) may be used to separate optional header rows from the table body. The vertical bar (“|”) is used for vertical lines (column separators). The plus sign (“+”) is used for intersections of horizontal and vertical lines.

Caution

How tables are displayed in HTML documentation depends on the HTML theme. With PyData, column separators are not displayed.

+------------------------+------------+----------+----------+
| Header row, column 1   | Header 2   | Header 3 | Header 4 |
| (header rows optional) |            |          |          |
+========================+============+==========+==========+
| body row 1, column 1   | column 2   | column 3 | column 4 |
+------------------------+------------+----------+----------+
| body row 2             | Cells may span columns.          |
+------------------------+------------+---------------------+
| body row 3             | Cells may  | - Table cells       |
+------------------------+ span rows. | - contain           |
| body row 4             |            | - body elements.    |
+------------------------+------------+---------------------+

Header row, column 1 (header rows optional)

Header 2

Header 3

Header 4

body row 1, column 1

column 2

column 3

column 4

body row 2

Cells may span columns.

body row 3

Cells may span rows.

  • Table cells

  • contain

  • body elements.

body row 4

There is another useful way to define a table, by using list-table directive. The main differences with grid tables are:

  • a list table can have a caption

  • a list table can’t have row/columns spanned cells

  • in a list table, you do not have to “draw” borders

  • in a list table, you can define several header rows or “header columns” (called stub columns)

  • in a list table, you define the width of each column (by a percentage)

Table 13 the optional caption#

row 1, column 1

row 1, column 2

row 1, column 3

row 1, column 4

row 2, column 1

row 2, column 2

row 2, column 3

row 2, column 4

row 3, column 1

row 3, column 2

row 3, column 3

row 3, column 4

row 4, column 1

row 4, column 3

.. list-table:: the optional caption
  :widths: 35 30 25 10
  :header-rows: 1
  :stub-columns: 1

  * - row 1, column 1
    - row 1, column 2
    - row 1, column 3
    - row 1, column 4
  * - row 2, column 1
    - row 2, column 2
    - row 2, column 3
    - row 2, column 4
  * - row 3, column 1
    - row 3, column 2
    - row 3, column 3
    - row 3, column 4
  * - row 4, column 1
    -
    - row 4, column 3
    -

Code blocks#

The code directive is to be used to construct literal block. If the code language is specified (as a directive parameter), the content is parsed by the Pygments syntax highlighter and tokens are stored in nested inline elements with class arguments according to their syntactic category. The actual highlighting requires a style-sheet (e.g. one generated by Pygments, see the sandbox/stylesheets for examples). XLiFE++ provides its own style-sheet called XLiFE++. This is the default style-sheet of code directive.

If you want to include a code file, you will use literalinclude directive instead and the language by its language option.

The sphinx_copybutton extension provides a small button in the top right corner of code directive to copy content properly.

Now, if you want to display code listing in inline mode, you should use the xlifepp specific role to display code with color highlighting, or the var to display variable for instance to explain what they are.

When you want to refer to a XLiFE++ sub-library (for instance utils), you should use the lib specific role.

Substitutions#

Substitutions are pieces of text and/or markup referred to in the text by |name|.

.. |xlifepp| replace:: **XLiFE++**

Every substitution is defined in /include/macros.txt in order to be automatically included in every RST file, as it is configured in conf.py.

Footnotes#

To define a footnote, you have to define a label between brackets and starting with #, followed by an underscore. Here is a sample taken from Installation:

As mentioned in the banner, a |cpp| compiler, `Cmake`_ and `Gmsh`_ have to be installed on your computer and defined in the |win| PATH [#winpath]_ system environnement variable. An EDI such as `CodeBlocks`_ and `Paraview`_ are not mandatory but highly recommended. Click on the *Configure* button.

Then, you have to write the footnote content. Here is the corresponding content of the previous footnote label:

.. [#winpath] A simple tool to edit the window path is `Windows Path Editor`_ if you have a version of |win| less or equal to 8, as PATH environment variable is shown in |win| preference pane as a single string. For recent |win| OS, this was improved and now there is one line for each directory in the PATH.

Admonitions#

Sphinx (and PyData theme) provides admonition directives: attention, caution, danger, error, hint, important, note, seealso, tip, todo, warning, versionadded, versionchanged and deprecated.

.. caution::
  How tables are displayed in HTML documentation depends on the HTML theme. With `PyData`_, column separators are not displayed.

Those directives are special cases of the generic one: admonition. In XLiFE++ projects, 3 custom admonitions are defined, one for each OS:

.. admonition:: |unix|
 :class: unix

 admonition-content

.. admonition:: |macOS|
 :class: macos

 admonition-content

.. admonition:: |win|
 :class: win

 admonition-content

To define the appearance of a custom admonition, you have to set some CSS, in the dedicated CSS file /_static/css/admonitions.css. Here is CSS code concerning the Windows admonition:

:root {
  --icon--win: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 34" width="28" height="24"><path fill="none" d="M0 0H24V24H0z"/><path d="M3 5.479l7.377-1.016v7.127H3V5.48zm0 13.042l7.377 1.017v-7.04H3v6.023zm8.188 1.125L21 21v-8.502h-9.812v7.148zm0-15.292v7.236H21V3l-9.812 1.354z"/></svg>');
}
.admonition.win {
  border-color: rgb(155, 155, 155);
}
.admonition.win > .admonition-title {
  background-color: rgba(155, 155, 155, 0.1);
  border-color: rgb(155, 155, 155);
}
.admonition.win > .admonition-title::after {
  background-color: rgb(155, 155, 155);
  content:"";
  -webkit-mask-image: var(--icon--win);
  mask-image: var(--icon--win);
}

Advanced elements with sphinx_design extension#

Here is the Sphinx Design reference documentation. Here comes a little summary.

Grids#

Grids are based on a 12 columns system, which can be adapted to the size of the viewing screen.

The grid directive can take one or four integers as parameter to set the number of columns according to the size of the viewing screen. The first integer is for extra-small viewing screens (<576px), the second one for small viewing screens (768px), the third one for medium viewing screens (992px) and the last one for large viewing screens (>1200px). If only a single integer is done, it is for all screens whatever their size.

The child grid-item directive is sued to define each item of the grid. You can override the number of columns a single item takes up by using the columns option of the grid-item directive. As the total columns are 12, this means 12 would indicate a single item takes up the entire grid row, or 6 half. Alternatively, use auto to automatically decide how many columns to use based on the item content. Like for grid columns, you can either provide a single number or four according to the size of the viewing screens.

.. grid:: 2

  .. grid-item-card::
    :columns: auto

    A

  .. grid-item-card::
    :columns: 12 6 6 6

    B

  .. grid-item-card::
    :columns: 12

    C

A

B

C

Cards#

Cards contain content and actions about a single subject. A card is a flexible and extensible content container, it can be formatted with components including headers and footers, titles and images.

The card directive needs to give a title and a content:

.. card:: Card Title

  Card content
Card Title

Card content

You can set images in a card through img-background, img-top, and img-bottom options to card.

Attention

If you want to add cards in grid items, you may use grid-item-card directive, which combines grid-item and card

Tabs#

The tab-set directive defines a set of tabs. Each tab will be defined with the tab-item directive:

.. tab-set::

  .. tab-item:: Label1

    Content 1

  .. tab-item:: Label2

    Content 2

Content 1

Content 2

Managing API with breathe extension#

This extension provides management of API documentation from XML files generated by Doxygen. It also provides breathe-apidoc application to generate RST files according to XML files from Doxygen.

Nevertheless, files /api/classlist.rst and /api/structlist.rst are automatically generated at the beginning of compilation to get a better result (class lists per displayed on 3 responsive columns letter by letter).

Managing events pages#

Page /events.rst is automatically generated at the beginning of compilation to obtain abstracts sorted from the most recent to the older event.

Events files are in /events/ directory. Their names begin by the date written with the format YYYY-MM-DD. These files always by the definition of a target for cross-referencing, and the title on the third line. The abstract is identified by 2 comments : “.. abstract” and “.. end abstract”.

.. _PoX.14:

Presentation of XLiFE++
#######################

Objectives
**********

.. abstract

This event intends to present the newly released library |xlifepp|

.. end abstract

TikZ figures with sphinxcontrib.tikz extension#

The tikz directive from sphinxcontrib.tikz extension (Sphinx TikZ documentation)allows you to write TikZ code or to include files containing TikZ code, through the include option. sphinxcontrib.tikz, as configured in XLiFE++ website, will call pdf2svg to generate SVG pictures from TikZ code.

The libs options allows you to set the TikZ libraries necessary to generate the picture.

The drawback of sphinxcontrib.tikz extension is that currently it does not manage class option that is for instance used to manage dark and light modes. So, there is a way to emulate this properly, by using the container directive:

  • You put TikZ files in the /_static/pictures/tikz directory. Here is a sample /_static/pictures/tikz/geo-loop3d.tikz:

    \coordinate (p1) at (0,0,0);
    \coordinate (p2) at (4,0.0);
    \coordinate (p3) at (4,0,-4);
    \coordinate (p4) at (0,0,-4);
    \coordinate (p5) at (0,4,0);
    \coordinate (p6) at (4,4,0);
    \coordinate (p7) at (4,4,-4);
    \coordinate (p8) at (0,4,-4);
    \coordinate (p9) at (8,2,-2);
    \draw[thick] (p9) -- (p6) -- (p2) -- (p1) -- (p5) -- (p8) -- (p7) -- (p6) -- (p5) (p7) -- (p9) -- (p2);
    \draw[thick, dashed] (p1) -- (p4) -- (p3) -- (p2) (p4) -- (p8) (p9) -- (p3) -- (p7);
    \fill[maincolor] (p1) circle (5pt) node[maincolor, below=1ex] {a};
    \fill[maincolor] (p2) circle (5pt) node[maincolor, below=1ex] {b};
    \fill[maincolor] (p3) circle (5pt) node[maincolor, above left] {c};
    \fill[maincolor] (p4) circle (5pt) node[maincolor, above left] {d};
    \fill[maincolor] (p5) circle (5pt) node[maincolor, below right] {e};
    \fill[maincolor] (p6) circle (5pt) node[maincolor, below right] {f};
    \fill[maincolor] (p7) circle (5pt) node[maincolor, above=1ex] {g};
    \fill[maincolor] (p8) circle (5pt) node[maincolor, above=1ex] {h};
    \fill[maincolor] (p9) circle (5pt) node[maincolor, right=1ex] {i};
    

    You can see that there is no tikzpicture environment. But you can start the file by the bracket that will be options given to the tikzpicture environment, as you can see for instance in the following generated file /_static/pictures/tikz/defineMap.tikz:

    [scale=4]
    \draw[->, thick](0,1) -- (0,2);
    \draw[->, thick](1,0) -- (2,0);
    \draw[thick, dashed](0,0) -- (0,1);
    \draw[thick, dashed](0,0) -- (1,0);
    \draw[very thick, dashed](0,1) -- (1,0);
    \node[fill=maincolor, inner sep=4pt, ellipse] (a1) at (0.5,0.5) {};
    \node[fill=maincolor, inner sep=4pt, ellipse] (a2) at (1.1,1.1) {};
    \coordinate (b1) at (1.9,0.6);
    \coordinate (b2) at (0.8,1.81);
    \coordinate (b3) at (1.4,1.41);
    \coordinate (c1) at (2,0.);
    \coordinate (c2) at (0.,2.);
    \node[fill=maincolor, inner sep=4pt, ellipse] (d1) at (1.45,1.3) {};
    \draw[ultra thick] (1,0) arc (0:90:1);
    \draw[ultra thick] (2,0) arc (0:90:2);
    \draw[thick, dashed] (0,0) -- (a1);
    \draw[->, very thick] (a1) -- (a2);
    \draw[thick, dashed] (c1) -- (b1);
    \draw[thick, dashed] (b1) -- (b3);
    \draw[thick, dashed] (b3) -- (b2);
    \draw[thick, dashed] (b2) -- (c2);
    \draw[->, very thick] (a2) -- (d1);
    \draw (d1) node[above right=0.5ex and 0.5ex] {projection};
    \draw (0.7,0.75) node[right=1ex] {circle scaling};
    

    Caution

    In XLiFE++ website, options allowed are simple key-values delimited by commas. The forbidden case is for instance the every path option that can have several key-values parameters delimited by commas inside the braces.

  • You have guidelines concerning colors. It is highly recommended using the following color names, available in light and dark modes:

    color name

    light mode

    dark mode

    usage

    lightdarkcolor

    white

    black

    to design holes

    lightdarknegcolor

    black

    white

    to force border colors when default value is not taken into account (when clipping for instance)

    filtercolor

    white

    gray

    to light or to darken other colors

    maincolor

    XLiFE++

    light XLiFE++

    secondcolor

    dark red

    light yellow

    thirdcolor

    dark blue

    light magenta

    fourthcolor

    dark green

    light green

    fifthcolor

    orange

    light orange

  • When generating website, two TikZ files will be generated with the same name but respectively in /_static/pictures/tikz/light and /_static/pictures/tikz/dark directories. Please take a look at the setup() method in conf.py to see how it works. The aim is to add global options to the tikzpicture environment to display code properly (in dark mode, for instance, the default behavior is that paths and texts are colored in white, and that paths are thicked). Here are what have been added to original TikZ code to generate light and dark TikZ files from /_static/pictures/tikz/defineMap.tikz:

    [scale=4,font=\Large\itshape,every path/.style={thick}]
    \definecolor{lightdarkcolor}{RGB}{255,255,255}%
    \definecolor{filtercolor}{RGB}{255,255,255}%
    \definecolor{lightdarknegcolor}{RGB}{0,0,0}%
    \definecolor{maincolor}{RGB}{0,127,127}%
    \definecolor{secondcolor}{RGB}{127,0,0}%
    \definecolor{thirdcolor}{RGB}{0,0,127}%
    \definecolor{fourthcolor}{RGB}{0,127,0}%
    \definecolor{fifthcolor}{RGB}{255,127,0}%
    
    [scale=4,font=\Large\itshape,every path/.style={draw=white,thick},every node/.style={text=white}]
    \definecolor{lightdarkcolor}{RGB}{0,0,0}%
    \definecolor{filtercolor}{RGB}{127,127,127}%
    \definecolor{lightdarknegcolor}{RGB}{255,255,255}%
    \definecolor{maincolor}{RGB}{127,255,255}%
    \definecolor{secondcolor}{RGB}{255,255,127}%
    \definecolor{thirdcolor}{RGB}{255,127,255}%
    \definecolor{fourthcolor}{RGB}{127,255,127}%
    \definecolor{fifthcolor}{RGB}{255,190,63}%
    
  • You write the following in your RST file:

    .. container:: only-light center
    
      .. tikz::
        :include: /_static/pictures/tikz/light/geo-loop3d.tikz
        :libs: positioning
    
    .. only:: html
    
      .. container:: only-dark center
    
        .. tikz::
          :include: /_static/pictures/tikz/dark/geo-loop3d.tikz
          :libs: positioning
    
  • Here is the result. You can play with the dark/light button to see the difference:

    Figure made with TikZ

    Figure made with TikZ

Management of bibliography with sphinx-bibtex extension#

2 bibliography files /articles.bib and /theses.bib contain all bibliography references with the bibtex format.

Example files and tags#

sphinx-tags extension defines directive tags, that is used just after the main title to define tags on example files. Automatically, pages per tag are generated at the beginning of the compilation. Several tags families are defined, one color is defined for each of them : PDE:*, Method:*, FE:*, Condition:*, Solver:*