mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Move :ref: labels over to std domain.
This commit is contained in:
parent
981f134e15
commit
77b3c15049
@ -199,6 +199,12 @@ class Domain(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_doc(self, env, docname, document):
|
||||
"""
|
||||
Process a document after it is read by the environment.
|
||||
"""
|
||||
pass
|
||||
|
||||
def resolve_xref(self, env, fromdocname, builder,
|
||||
typ, target, node, contnode):
|
||||
"""
|
||||
|
@ -20,7 +20,7 @@ from sphinx.locale import l_, _
|
||||
from sphinx.domains import Domain, ObjType
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.util import ws_re
|
||||
from sphinx.util.nodes import make_refnode
|
||||
from sphinx.util.nodes import clean_astext, make_refnode
|
||||
from sphinx.util.compat import Directive
|
||||
|
||||
|
||||
@ -327,6 +327,7 @@ class StandardDomain(Domain):
|
||||
object_types = {
|
||||
'term': ObjType(l_('glossary term'), 'term', searchprio=-1),
|
||||
'token': ObjType(l_('grammar token'), 'token', searchprio=-1),
|
||||
'label': ObjType(l_('reference label'), 'ref', searchprio=-1),
|
||||
'envvar': ObjType(l_('environment variable'), 'envvar'),
|
||||
'cmdoption': ObjType(l_('program option'), 'option'),
|
||||
}
|
||||
@ -340,15 +341,31 @@ class StandardDomain(Domain):
|
||||
'productionlist': ProductionList,
|
||||
}
|
||||
roles = {
|
||||
'option': OptionXRefRole(innernodeclass=addnodes.literal_emphasis),
|
||||
'envvar': EnvVarXRefRole(),
|
||||
'token': XRefRole(),
|
||||
'term': XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
|
||||
'option': OptionXRefRole(innernodeclass=addnodes.literal_emphasis),
|
||||
'envvar': EnvVarXRefRole(),
|
||||
# links to tokens in grammar productions
|
||||
'token': XRefRole(),
|
||||
# links to terms in glossary
|
||||
'term': XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
|
||||
# links to headings or arbitrary labels
|
||||
'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
|
||||
# links to labels, without a different title
|
||||
'keyword': XRefRole(),
|
||||
}
|
||||
|
||||
initial_data = {
|
||||
'progoptions': {}, # (program, name) -> docname, labelid
|
||||
'objects': {}, # (type, name) -> docname, labelid
|
||||
'labels': { # labelname -> docname, labelid, sectionname
|
||||
'genindex': ('genindex', '', l_('Index')),
|
||||
'modindex': ('py-modindex', '', l_('Module Index')),
|
||||
'search': ('search', '', l_('Search Page')),
|
||||
},
|
||||
'anonlabels': { # labelname -> docname, labelid
|
||||
'genindex': ('genindex', ''),
|
||||
'modindex': ('py-modindex', ''),
|
||||
'search': ('search', ''),
|
||||
},
|
||||
}
|
||||
|
||||
def clear_doc(self, docname):
|
||||
@ -358,10 +375,97 @@ class StandardDomain(Domain):
|
||||
for key, (fn, _) in self.data['objects'].items():
|
||||
if fn == docname:
|
||||
del self.data['objects'][key]
|
||||
for key, (fn, _, _) in self.data['labels'].items():
|
||||
if fn == docname:
|
||||
del self.data['labels'][key]
|
||||
for key, (fn, _) in self.data['anonlabels'].items():
|
||||
if fn == docname:
|
||||
del self.data['anonlabels'][key]
|
||||
|
||||
def process_doc(self, env, docname, document):
|
||||
labels, anonlabels = self.data['labels'], self.data['anonlabels']
|
||||
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
|
||||
if name in labels:
|
||||
env.warn(docname, 'duplicate label %s, ' % name +
|
||||
'other instance in ' + env.doc2path(labels[name][0]),
|
||||
node.line)
|
||||
anonlabels[name] = docname, labelid
|
||||
if node.tagname == 'section':
|
||||
sectname = clean_astext(node[0]) # node[0] == title node
|
||||
elif node.tagname == 'figure':
|
||||
for n in node:
|
||||
if n.tagname == 'caption':
|
||||
sectname = clean_astext(n)
|
||||
break
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
# anonymous-only labels
|
||||
continue
|
||||
labels[name] = docname, labelid, sectname
|
||||
|
||||
def resolve_xref(self, env, fromdocname, builder,
|
||||
typ, target, node, contnode):
|
||||
if typ == 'option':
|
||||
if typ == 'ref':
|
||||
refdoc = node.get('refdoc', fromdocname)
|
||||
if node['refexplicit']:
|
||||
# reference to anonymous label; the reference uses
|
||||
# the supplied link caption
|
||||
docname, labelid = self.data['anonlabels'].get(target, ('',''))
|
||||
sectname = node.astext()
|
||||
if not docname:
|
||||
env.warn(refdoc, 'undefined label: %s' %
|
||||
target, node.line)
|
||||
else:
|
||||
# reference to named label; the final node will
|
||||
# contain the section name after the label
|
||||
docname, labelid, sectname = self.data['labels'].get(target,
|
||||
('','',''))
|
||||
if not docname:
|
||||
env.warn(refdoc,
|
||||
'undefined label: %s' % target + ' -- if you '
|
||||
'don\'t give a link caption the label must '
|
||||
'precede a section header.', node.line)
|
||||
if not docname:
|
||||
return None
|
||||
newnode = nodes.reference('', '')
|
||||
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
|
||||
elif typ == 'keyword':
|
||||
# keywords are oddballs: they are referenced by named labels
|
||||
docname, labelid, _ = self.data['labels'].get(target, ('','',''))
|
||||
if not docname:
|
||||
#env.warn(refdoc, 'unknown keyword: %s' % target)
|
||||
return None
|
||||
else:
|
||||
return make_refnode(builder, fromdocname, docname,
|
||||
labelid, contnode)
|
||||
elif typ == 'option':
|
||||
progname = node['refprogram']
|
||||
docname, labelid = self.data['progoptions'].get((progname, target),
|
||||
('', ''))
|
||||
@ -387,3 +491,5 @@ class StandardDomain(Domain):
|
||||
for (type, name), info in self.data['objects'].iteritems():
|
||||
yield (name, type, info[0], info[1],
|
||||
self.object_types[type].attrs['searchprio'])
|
||||
for name, info in self.data['labels'].iteritems():
|
||||
yield (name, 'label', info[0], info[1], -1)
|
||||
|
@ -304,12 +304,8 @@ class BuildEnvironment:
|
||||
# domain-specific inventories, here to be pickled
|
||||
self.domaindata = {} # domainname -> domain-specific dict
|
||||
|
||||
# X-ref target inventory
|
||||
self.labels = {} # labelname -> docname, labelid, sectionname
|
||||
self.anonlabels = {} # labelname -> docname, labelid
|
||||
self.citations = {} # citation name -> docname, labelid
|
||||
|
||||
# Other inventories
|
||||
self.citations = {} # citation name -> docname, labelid
|
||||
self.indexentries = {} # docname -> list of
|
||||
# (type, string, target, aliasname)
|
||||
self.versionchanges = {} # version -> list of (type, docname,
|
||||
@ -322,16 +318,6 @@ class BuildEnvironment:
|
||||
# temporary data storage while reading a document
|
||||
self.temp_data = {}
|
||||
|
||||
# Some magically present labels
|
||||
def add_magic_label(name, description, target=None):
|
||||
self.labels[name] = (target or name, '', description)
|
||||
self.anonlabels[name] = (target or name, '')
|
||||
add_magic_label('genindex', _('Index'))
|
||||
# XXX add per domain?
|
||||
# compatibility alias
|
||||
add_magic_label('modindex', _('Module Index'), 'py-modindex')
|
||||
add_magic_label('search', _('Search Page'))
|
||||
|
||||
def set_warnfunc(self, func):
|
||||
self._warnfunc = func
|
||||
self.settings['warning_stream'] = WarningStream(func)
|
||||
@ -366,9 +352,6 @@ class BuildEnvironment:
|
||||
fnset.discard(docname)
|
||||
if not fnset:
|
||||
del self.files_to_rebuild[subfn]
|
||||
for labelname, (fn, _, _) in self.labels.items():
|
||||
if fn == docname:
|
||||
del self.labels[labelname]
|
||||
for key, (fn, _) in self.citations.items():
|
||||
if fn == docname:
|
||||
del self.citations[key]
|
||||
@ -669,10 +652,11 @@ class BuildEnvironment:
|
||||
self.process_metadata(docname, doctree)
|
||||
self.process_refonly_bullet_lists(docname, doctree)
|
||||
self.create_title_from(docname, doctree)
|
||||
self.note_labels_from(docname, doctree)
|
||||
self.note_indexentries_from(docname, doctree)
|
||||
self.note_citations_from(docname, doctree)
|
||||
self.build_toc_from(docname, doctree)
|
||||
for domain in self.domains.itervalues():
|
||||
domain.process_doc(self, docname, doctree)
|
||||
|
||||
# allow extension-specific post-processing
|
||||
if app:
|
||||
@ -949,39 +933,6 @@ class BuildEnvironment:
|
||||
self.titles[docname] = titlenode
|
||||
self.longtitles[docname] = longtitlenode
|
||||
|
||||
def note_labels_from(self, docname, document):
|
||||
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
|
||||
if name in self.labels:
|
||||
self.warn(docname, 'duplicate label %s, ' % name +
|
||||
'other instance in ' +
|
||||
self.doc2path(self.labels[name][0]),
|
||||
node.line)
|
||||
self.anonlabels[name] = docname, labelid
|
||||
if node.tagname == 'section':
|
||||
sectname = clean_astext(node[0]) # node[0] == title node
|
||||
elif node.tagname == 'figure':
|
||||
for n in node:
|
||||
if n.tagname == 'caption':
|
||||
sectname = clean_astext(n)
|
||||
break
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
# anonymous-only labels
|
||||
continue
|
||||
self.labels[name] = docname, labelid, sectname
|
||||
|
||||
def note_indexentries_from(self, docname, document):
|
||||
entries = self.indexentries[docname] = []
|
||||
for node in document.traverse(addnodes.index):
|
||||
@ -1309,44 +1260,6 @@ class BuildEnvironment:
|
||||
newnode = domain.resolve_xref(self, fromdocname, builder,
|
||||
typ, target, node, contnode)
|
||||
# really hardwired reference types
|
||||
elif typ == 'ref':
|
||||
if node['refexplicit']:
|
||||
# reference to anonymous label; the reference uses
|
||||
# the supplied link caption
|
||||
docname, labelid = self.anonlabels.get(target, ('',''))
|
||||
sectname = node.astext()
|
||||
if not docname:
|
||||
self.warn(refdoc, 'undefined label: %s' %
|
||||
target, node.line)
|
||||
warned = True
|
||||
else:
|
||||
# reference to named label; the final node will
|
||||
# contain the section name after the label
|
||||
docname, labelid, sectname = self.labels.get(target,
|
||||
('','',''))
|
||||
if not docname:
|
||||
self.warn(refdoc,
|
||||
'undefined label: %s' % target + ' -- if you '
|
||||
'don\'t give a link caption the label must '
|
||||
'precede a section header.', node.line)
|
||||
warned = True
|
||||
if docname:
|
||||
newnode = nodes.reference('', '')
|
||||
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)
|
||||
elif typ == 'doc':
|
||||
# directly reference to document by source name;
|
||||
# can be absolute or relative
|
||||
@ -1375,16 +1288,6 @@ class BuildEnvironment:
|
||||
else:
|
||||
newnode = make_refnode(builder, fromdocname, docname,
|
||||
labelid, contnode)
|
||||
elif typ == 'keyword':
|
||||
# keywords are oddballs: they are referenced by named labels
|
||||
docname, labelid, _ = self.labels.get(target, ('','',''))
|
||||
if not docname:
|
||||
#self.warn(refdoc, 'unknown keyword: %s' % target)
|
||||
pass
|
||||
else:
|
||||
newnode = make_refnode(builder, fromdocname, docname,
|
||||
labelid, contnode)
|
||||
|
||||
# no new node found? try the missing-reference event
|
||||
if newnode is None:
|
||||
newnode = builder.app.emit_firstresult(
|
||||
|
@ -244,12 +244,8 @@ def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||
specific_docroles = {
|
||||
# links to download references
|
||||
'download': XRefRole(nodeclass=addnodes.download_reference),
|
||||
# links to headings or arbitrary labels
|
||||
'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
|
||||
# links to documents
|
||||
'doc': XRefRole(),
|
||||
# links to labels, without a different title
|
||||
'keyword': XRefRole(),
|
||||
|
||||
'pep': indexmarkup_role,
|
||||
'rfc': indexmarkup_role,
|
||||
|
Loading…
Reference in New Issue
Block a user