Can a role create a target?

39 views
Skip to first unread message

Peter Burdine

unread,
Jun 21, 2016, 9:35:55 AM6/21/16
to sphinx-dev
I am working on an extension that would be able to identify all of the TBDs in a document.  I have it working with directives, but It would be much nicer to have it working with roles since they could be inline and flow more naturally then having them be in their own paragraph.  However, I don't seem to be able to get the target nodes working with the role.  In the directive, I do the following which works well.

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

However, when I do the same thing for the role, it doesn't work:
def tbd_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
    env
= inliner.document.settings.env
    app
= env.app
   
...
   
# Add this to our TBD list
    targetid
= "tbd-%d" % env.new_serialno('tbd')
    targetnode
= nodes.target('', '', ids=[targetid]])
    inliner
.document.note_explicit_target(targetnode)
   
...
    node
= nodes.Text('TBD')
   
return [targetnode, node], []

 
It looks like when it goes through the build phases the the "id" attribute of the target gets resolved to a "refid" for all of the targets created by directive, but one target created by the role doesn't get resolved.  Is there something I am missing?

Thanks,
Peter

Peter Burdine

unread,
Jun 21, 2016, 1:53:26 PM6/21/16
to sphinx-dev
This is probably the really wrong way to do this, but if I go up the doc tree until I find a parent with the source attribute, and then manually set the refuri and refid it seems to work:


   
# Find the file that we are in
    docname
= ''
    parent
= inliner.parent
   
while parent:
       
if hasattr(parent, 'attributes'):
           
if parent.attributes.get('source', ''):
                docname
= parent.attributes['source'].replace(''.join([app.confdir, '/']), '', 1)
                docname
= docname.replace('.rst', '')
               
break
        parent
= parent.parent
               
   
# Add this to our TBD list

    targetid
= "tbd-%d" % env.new_serialno('tbd')

    targetnode
= nodes.target(ids=[targetid],
                              names
=[docname],
                              refuri
="/" + docname,
                              refid
=targetid,)

Is there a better way of making this work?

Peter Burdine

unread,
Jun 21, 2016, 4:25:44 PM6/21/16
to sphinx-dev
This above works for HTML, but the labels are not generated for the PDF output so I end up with a bunch of undefined references.  When I look at the .tex output, I can see the text from the TBD roles, but there is no label for it.  So the latex writer may be looking at nodes differently than the htmlwriter.

Ideas anyone?

Thanks,
Peter

Komiya Takeshi

unread,
Jun 24, 2016, 11:41:00 PM6/24/16
to sphinx-dev
Hi,

Really? It looks the first tbd_role works fine on latex writer.
I got following .tex code from :role:`hello`.
\phantomsection\label{index:tbd-0}TBD

And it can refer by \hyperref macro at latex level.
I confirmed that using raw directive:
.. raw:: latex

   \hyperref[index:tbd-0]{reference}

How do you resolve the reference? I want to see it.


BTW, you can get current docname from the environment object using env.docname.

Thanks,
Takeshi KOMIYA

2016年6月22日水曜日 5時25分44秒 UTC+9 Peter Burdine:

Peter Burdine

unread,
Jul 2, 2016, 9:28:10 AM7/2/16
to sphinx-dev
 Hmm, I wonder how yours is working differently.  My rst file looks like:
=====
Scope
=====

This is a role :tbd:`link here`.



And the tex output looks like:

\chapter{Scope}
\label{scope:project}\label{scope:scope}\label{scope::doc}
This is a role TBD.


This was build with Sphinx 1.4.4.

Komiya Takeshi

unread,
Jul 2, 2016, 10:21:24 PM7/2/16
to sphinx-dev
Hi,

I retry this and push my project into https://github.com/tk0miya/test-tbdrole


Could you check this please?

2016年7月2日土曜日 22時28分10秒 UTC+9 Peter Burdine:

Peter Burdine

unread,
Jul 20, 2016, 10:44:52 AM7/20/16
to sphinx-dev
Thanks, for getting back to me, I had to go work on other projects hence the very late response.

How to a create a reference back to that link?  From what I saw in other examples, it should be something like:

newnode['refuri'] += '#' + tbd_info['target']['refid']

Where tbd_info is defined as:
{
           
'docname': env.docname,
           
'lineno': self.lineno,
           
'target': targetnode,
           
'content': self.content,
           
'node': self.state_machine.node,
           
'sectionname': self.state_machine.node.attributes['names'],
           
'sectionid': self.state_machine.node.attributes['ids'],
           
'sectiontitle': get_section_title(self.state_machine.node),
       
}

Peter Burdine

unread,
Jul 20, 2016, 11:01:43 AM7/20/16
to sphinx-dev
Sorry, I somehow posted when I was trying updating the code blocks.

tbd_info is defined as follows:

    targetid = "tbd-%d" % env.new_serialno('tbd')
    targetnode
= nodes.target('', '', ids=[targetid])
    inliner
.document.note_explicit_target(targetnode)

   
    tbd_info
= {
       
'docname': env.docname,
       
'target': targetnode,
       
'content': text,
       
'sectionid': sectionid,
       
'sectiontitle': get_section_title(inliner.parent),
       
'parent': inliner.parent,

       
}
    node
= nodes.Text('TBD')
   
return [targetnode, node], []  

However, when the build runs, it can't find the correct link.  Maybe I am defining the link incorrectly, but from what I saw in other examples, it something like:

            newnode = nodes.reference('', '')

            newnode
['refuri'] += '#' + tbd_info['target']['refid']

However, tbd_info['target']['id'] isn't being changed to tbd_info['target']['refid'] like I see for the rest of the links.  So it appears to not be resolving.  I think my code is pretty similar to: http://www.sphinx-doc.org/en/stable/extdev/tutorial.html  I'll reread through that example a few more times, hopefully I can find what I am missing, but I can't get the link to resolve at the moment.

I can get it working with the HTML builder by making it more complicated, eg define the target like so:
    docname = ''
    parent
= inliner.parent
   
while parent:
       
if hasattr(parent, 'attributes'):
           
if parent.attributes.get('source', ''):
                docname
= parent.attributes['source'].replace(''.join([app.confdir, '/']), '', 1)
                docname
= docname.replace('.rst', '')
               
break
        parent
= parent.
parent
    targetid
= "tbd%d" % env.new_serialno('tbd')

    targetnode
= nodes.target(ids=[targetid],
                              names
=[docname],
                              refuri
="/" + docname,
                              refid
=targetid,)  

Then I can create the reference node as such:
            newnode = nodes.reference('', '')
            newnode
['refdocname'] = tbd_info['docname']
            newnode
['refuri'] = app.builder.get_relative_uri(
                fromdocname
, tbd_info['docname'])

However all of that seems overly complicated compared to the example.

Thanks!
Reply all
Reply to author
Forward
0 new messages