Skip to content

Instantly share code, notes, and snippets.

@shimizukawa
Created December 1, 2012 07:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shimizukawa/4181015 to your computer and use it in GitHub Desktop.
Save shimizukawa/4181015 to your computer and use it in GitHub Desktop.
Sphinx extension "Anonimous Domain" extend objects.inv entries.

Anonymous Domain

Anonymous domain hook anonymous link target and store targets into objects.inv.

Problem

objects.inv not have anonymous link targets.

For example index.rst:

.. _named-label:

Welcome to spam's documentation!
================================

.. _anon-label:

ham! egg! spam!

and 'make html' generate objects.inv like below:

u'std:label': {u'genindex': (u'spam', u'1.0', u'genindex.html#', u'Index'),
               u'modindex': (u'spam',
                             u'1.0',
                             u'py-modindex.html#',
                             u'Module Index'),
               u'named-label': (u'spam',
                                u'1.0',
                                u'index.html#named-label',
                                u"Welcome to spam's documentation!"),
               u'search': (u'spam', u'1.0', u'search.html#', u'Search Page')}

This objects.inv not have 'anon-label' then another sphinx can not link to 'anon-label' by using sphinx.ext.intersphinx.

Solution

AnonimousDomain (ext_anon_domain.py) support generating all label targets in objects.inv.

For example:

u'anon:label': {u'anon-label': (u'spam',
                                u'1.0',
                                u'index.html#anon-label',
                                u'-'),
                u'named-label': (u'spam',
                                 u'1.0',
                                 u'index.html#named-label',
                                 u'-')},
u'std:label': {u'genindex': (u'spam', u'1.0', u'genindex.html#', u'Index'),
               u'modindex': (u'spam',
                             u'1.0',
                             u'py-modindex.html#',
                             u'Module Index'),
               u'named-label': (u'spam',
                                u'1.0',
                                u'index.html#named-label',
                                u"Welcome to spam's documentation!"),
               u'search': (u'spam', u'1.0', u'search.html#', u'Search Page')}

and you can reference by:

this is :anon:ref:`anon-label`.
# add this line at last
extensions.append('ext_anon_domain')
# -*- coding: utf-8 -*-
from docutils import nodes
from sphinx.roles import XRefRole
from sphinx.locale import l_, _
from sphinx.domains import Domain, ObjType
class AnonymousDomain(Domain):
name = 'anon'
label = 'Anonymous'
object_types = {
'label': ObjType(l_('reference label'), 'ref', 'keyword',
searchprio=-1),
}
roles = {
# links to headings or arbitrary labels
'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
warn_dangling=True),
}
initial_data = {
'labels': {}
}
dangling_warnings = {
'ref': 'undefined label: %(target)s',
}
def clear_doc(self, docname):
for key, (fn, _) in self.data['labels'].items():
if fn == docname:
del self.data['labels'][key]
def process_doc(self, env, docname, document):
labels = self.data['labels']
for name, explicit in document.nametypes.iteritems():
if not explicit:
continue
labelid = document.nameids[name]
if labelid is None:
continue
node = document.ids[labelid]
if name.isdigit() or node.has_key('refuri') or \
node.tagname.startswith('desc_'):
# ignore footnote labels, labels automatically generated from a
# link and object descriptions
continue
labels[name] = docname, labelid
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
if typ == 'ref':
docname, labelid = self.data['labels'].get(target, ('',''))
sectname = labelid
if not docname:
return None
newnode = nodes.reference('', '', internal=True)
innernode = nodes.emphasis(sectname, sectname)
if docname == fromdocname:
newnode['refid'] = labelid
else:
# set more info in contnode; in case the
# get_relative_uri call raises NoUri,
# the builder will then have to resolve these
contnode = addnodes.pending_xref('')
contnode['refdocname'] = docname
contnode['refsectname'] = sectname
newnode['refuri'] = builder.get_relative_uri(
fromdocname, docname)
if labelid:
newnode['refuri'] += '#' + labelid
newnode.append(innernode)
return newnode
def get_objects(self):
for name, info in self.data['labels'].iteritems():
yield (name, name, 'label', info[0], info[1], -1)
def setup(app):
app.add_domain(AnonymousDomain)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment