Generating labels for nodes of a custom directive

允我心安 提交于 2021-01-04 03:12:35

问题


Using the Sphinx "TODO" Directive example I would like to reference the todo instances embedded within a .rst file. For example, if the .rst file content contains:

.. todo:: foo

.. todo:: bar

I can see that the following code (taken from the Sphinx TODO example page)

class TodoDirective(SphinxDirective):

    # this enables content in the directive
    has_content = True

    def run(self):
        targetid = 'todo-%d' % self.env.new_serialno('todo')
        targetnode = nodes.target('', '', ids=[targetid])

        todo_node = todo('\n'.join(self.content))
        todo_node += nodes.title(_('Todo'), _('Todo'))
        self.state.nested_parse(self.content, self.content_offset, todo_node)

        if not hasattr(self.env, 'todo_all_todos'):
            self.env.todo_all_todos = []

        self.env.todo_all_todos.append({
            'docname': self.env.docname,
            'lineno': self.lineno,
            'todo': todo_node.deepcopy(),
            'target': targetnode,
        })

        return [targetnode, todo_node]

Creates target nodes with ids: todo-0 and todo-1. That are successfully referenced by embedding the directive in a .rst file as:

.. todolist::

What I would like to do is reference the todo items within a .rst file like this:

:ref:`todo-0`
:ref:`todo-1`

This would require getting the TodoDirective to generate a label for each target node. I have not been able to figure out how to do so.

This simple project is posted here: https://github.com/natersoz/sphinx_sandbox


回答1:


I had the same problem as you and was able to resolve the issue by looking at the autosectionlabel extension.

What they do there is to add the reference to the labels domain data. I got it working inside a custom directive like so:

nodeId = nodes.make_id("some-id")
self.env.app.env.domaindata["std"]["labels"][nodeId] = self.env.docname, nodeId, "Title"
section = nodes.section(ids=[nodeId])
section.append(nodes.title(text="Title"))

Key is the second line of the code above.

Also you want to add the label to the anonlabels to be able to reference it via

:ref:`foo <nodeId>`

like so:

self.env.app.env.domaindata["std"]["anonlabels"][nodeId] = self.env.docname, nodeId



回答2:


I found one way to perform this operation. It likely only works for HTML output:

`Text related to todo-0 <introduction.html#todo-0>`_

This reference link will successfully link to the TODO. All other reference attempts fail. i.e. These all fail:

Note: these syntaxes do not work::

    `introduction.html#todo-1`_

    :ref:`introduction.html#todo-1`

    :ref:`todo-1`


来源:https://stackoverflow.com/questions/64146870/generating-labels-for-nodes-of-a-custom-directive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!