Substitution in a file name with reStructuredText (Sphinx)?

后端 未结 2 1314
梦毁少年i
梦毁少年i 2021-01-17 10:59

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

(file1.rst):

.. |variable| replace:: 1
..          


        
相关标签:
2条回答
  • 2021-01-17 10:59

    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.

    0 讨论(0)
  • 2021-01-17 11:13

    You have to create a custom directive in this case as Sphinx doesn't allow you to substitute image paths. You can change Sphinx figure directive as follows and use it instead of the image directive.

    from typing import Any, Dict, List, Tuple
    from typing import cast
    
    from docutils import nodes
    from docutils.nodes import Node, make_id, system_message
    from docutils.parsers.rst import directives
    from docutils.parsers.rst.directives import images, html, tables
    
    from sphinx import addnodes
    from sphinx.directives import optional_int
    from sphinx.domains.math import MathDomain
    from sphinx.util.docutils import SphinxDirective
    from sphinx.util.nodes import set_source_info
    
    if False:
        # For type annotation
        from sphinx.application import Sphinx
    
    
    class CustomFigure(images.Figure):
        """The figure directive which applies `:name:` option to the figure node
        instead of the image node.
        """
    
        def run(self) -> List[Node]:
            name = self.options.pop('name', None)
            path = self.arguments[0]  #path = ./images/variable-image.png
            #replace 'variable' from th.e given value 
            self.argument[0] = path.replace("variable", "string substitution")
            result = super().run()
            if len(result) == 2 or isinstance(result[0], nodes.system_message):
                return result
    
            assert len(result) == 1
            figure_node = cast(nodes.figure, result[0])
            if name:
                # set ``name`` to figure_node if given
                self.options['name'] = name
                self.add_name(figure_node)
    
            # copy lineno from image node
            if figure_node.line is None and len(figure_node) == 2:
                caption = cast(nodes.caption, figure_node[1])
                figure_node.line = caption.line
    
            return [figure_node]
    
    
    def setup(app: "Sphinx") -> Dict[str, Any]:
        directives.register_directive('figure', Figure)
    
        return {
            'version': 'builtin',
            'parallel_read_safe': True,
            'parallel_write_safe': True,
        }
    

    You can add this CustomFigure.py directive in the conf.py of the project and use the customfigure directive across Sphinx project instead of the Image directive. Refer http://www.sphinx-doc.org/en/master/usage/extensions/index.html to add a custom directive to your Sphinx project.

    0 讨论(0)
提交回复
热议问题