Search code examples
python-sphinxsubstitutionrestructuredtext

Substitution in a file name with reStructuredText (Sphinx)?


I want to create several files from a single template, which differ only by a variable name. For example :

(file1.rst):

.. |variable| replace:: 1
.. include template.rst

(template.rst) :

Variable |variable|
=====================

Image
-------

.. image:: ./images/|variable|-image.png

where of course I have an image called "./images/1-image.png". The substitution of "|variable|" by "1" works well in the title, but not in the image file name, and at compilation I get :

WARNING: image file not readable: ./images/|variable|-image.png

How can I get reST to make the substitution in the variable name too? (if this changes anything, am using Sphinx).


Solution

  • There are two problems here: a substitution problem, and a parsing order problem.

    For the first problem, the substitution reference |variable| cannot have adjacent characters (besides whitespace or maybe _ for hyperlinking) or else it won't parse as a substitution reference, so you need to escape it:

    ./images/\ |variable|\ -image.png
    

    However, the second problem is waiting around the corner. While I'm not certain of the details, it seems reST is unable to parse substitutions inside other directives. I think it first parses the image directive, which puts it in the document tree and thus out of reach of the substitution mechanism. Similarly, I don't think it's possible to use a substitution to insert content intended to be parsed (e.g. .. |img1| replace::`.. image:: images/1-image.png`). This is all speculative based on some tests and my incomplete comprehension of the official documentation, so someone more knowledgeable can correct what I've said here.

    I think you're aware of the actual image substitution directive (as opposed to text substitution), but I don't think it attains the generality you're aiming for (you'll still need a separate directive for the image as from the |variable|), but in any case it looks like this:

    .. |img1| image:: images/1-image.png
    

    Since you're using Sphinx, you can try creating your own directive extension (see this answer for information), but it won't solve the substitutions-inside-markup problem.