为狮身人面像创建代码引用角色

时间:2018-12-31 13:39:09

标签: python python-sphinx docutils

问题

我想创建一个rolecoderef,它将引用由sphinx.ext.viewcode生成的插入模块代码。为此,我得到的印象是我需要适当地填充env._viewcode_modules,但我不确定该怎么做。

背景

看着viewcode,看来viewcode.doctree_read扫描文档树中的addnode.desc_signature节点(嵌套在addnode.desc节点下)时,填充了env._viewcode_modules,这样就可以插入模块了。插入字典中的值最初是None,如果无法插入模块,则将其替换为False,或者是 document node (在此处不确定) ,何时可以掉毛。似乎sphinx.ext.viewcode.collect_pages对这些内容进行了相应的迭代。

当前实施

我的希望是加入这种机制,当遇到coderef事件时,只需在env._viewcode_modules中添加一些其他条目。但是,我不确定我是否正确执行了此操作。我拥有的代码如下:

from docutils          import nodes, utils
from sphinx            import addnodes
from sphinx.util.nodes import split_explicit_title

def coderef(role, rawtext, text, line, inliner, options={}, content=[]):
    try : 
     env = inliner.document.settings.env
     if not hasattr(env, '_viewcode_modules'): env._viewcode_modules = {} # View Code retains a list of modules, we sneak the cross linked modules into the list.
     test, name, link = split_explicit_title(text)
     refid   = link.replace('.','-')
     refuri  = env.app.builder.get_relative_uri("/", "/".join(["_modules", *link.split('.')])) # Originally : "_modules/" + link.replace('.','/')
     refname = utils.unescape(name) # Future : inliner.nested_parse() ?
     reflink = utils.unescape("_modules/" + link.replace(".","/")) # str(Path("_modules").join(target.split('.')))
     refnode = nodes.inline('', refname, classes=['viewcode-link']) # viewcode-link is a CSS class
     coderef = addnodes.only(expr='html')
     coderef+= addnodes.pending_xref('', refname, 
         refid       = refid,
         reftype     = 'viewcode' or role, # The reference type, see viewcode extention
         refdomain   = 'std',              # 
         refexplicit = False,              # 
         refdoc      = env.docname,        # Originally : env.docname; This represents the name of the document with all extentions stripped, I think this doubles as a back reference.
         reftarget   = reflink)
     return [coderef], [] 
    except Exception as error : # This is bad form, specify explicit errors you know how to deal with
     msg = inliner.reporter.error(
               'An error occured while determining the code reference for'
               ' "%s" ' % text,
               line = line)
     prb = inliner.problematic(rawtext, text, msg)
     return [prb], [msg]

执行失败

以前,我设法使用nodes.reference来部分解决这个问题,但是由于总是没有生成带斜线的模块,因为它们没有被添加到env._viewcode_modules且未被sphinx.ext.viewcode.collect_pages处理。

观察

我尚不了解的一些奇怪之处是如何解决addnodes.pending_xref。似乎必须同时具有反向引用和正向引用,并且我认为目前我还没有创建适当的反向引用。 addnodes.pending_xref似乎也接受nodes.inline节点,大概是最终链接中文本的节点;目前也无法正确管理。

0 个答案:

没有答案