mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
std domain handles citations
This commit is contained in:
parent
b03b7e543f
commit
d5a770b592
@ -466,6 +466,7 @@ class StandardDomain(Domain):
|
||||
initial_data = {
|
||||
'progoptions': {}, # (program, name) -> docname, labelid
|
||||
'objects': {}, # (type, name) -> docname, labelid
|
||||
'citations': {}, # name -> docname, labelid
|
||||
'labels': { # labelname -> docname, labelid, sectionname
|
||||
'genindex': ('genindex', '', l_('Index')),
|
||||
'modindex': ('py-modindex', '', l_('Module Index')),
|
||||
@ -485,6 +486,7 @@ class StandardDomain(Domain):
|
||||
'numref': 'undefined label: %(target)s',
|
||||
'keyword': 'unknown keyword: %(target)s',
|
||||
'option': 'unknown option: %(target)s',
|
||||
'citation': 'citation not found: %(target)s',
|
||||
}
|
||||
|
||||
enumerable_nodes = { # node_class -> (figtype, title_getter)
|
||||
@ -500,6 +502,9 @@ class StandardDomain(Domain):
|
||||
for key, (fn, _l) in list(self.data['objects'].items()):
|
||||
if fn == docname:
|
||||
del self.data['objects'][key]
|
||||
for key, (fn, _l) in list(self.data['citations'].items()):
|
||||
if fn == docname:
|
||||
del self.data['citations'][key]
|
||||
for key, (fn, _l, _l) in list(self.data['labels'].items()):
|
||||
if fn == docname:
|
||||
del self.data['labels'][key]
|
||||
@ -515,6 +520,9 @@ class StandardDomain(Domain):
|
||||
for key, data in otherdata['objects'].items():
|
||||
if data[0] in docnames:
|
||||
self.data['objects'][key] = data
|
||||
for key, data in otherdata['citations'].items():
|
||||
if data[0] in docnames:
|
||||
self.data['citations'][key] = data
|
||||
for key, data in otherdata['labels'].items():
|
||||
if data[0] in docnames:
|
||||
self.data['labels'][key] = data
|
||||
@ -523,6 +531,19 @@ class StandardDomain(Domain):
|
||||
self.data['anonlabels'][key] = data
|
||||
|
||||
def process_doc(self, env, docname, document):
|
||||
self.note_citations(env, docname, document)
|
||||
self.note_labels(env, docname, document)
|
||||
|
||||
def note_citations(self, env, docname, document):
|
||||
for node in document.traverse(nodes.citation):
|
||||
label = node[0].astext()
|
||||
if label in self.data['citations']:
|
||||
path = env.doc2path(self.data['citations'][0])
|
||||
env.warn_node('duplicate citation %s, other instance in %s' %
|
||||
(label, path), node)
|
||||
self.data['citations'][label] = (docname, node['ids'][0])
|
||||
|
||||
def note_labels(self, env, docname, document):
|
||||
labels, anonlabels = self.data['labels'], self.data['anonlabels']
|
||||
for name, explicit in iteritems(document.nametypes):
|
||||
if not explicit:
|
||||
@ -593,6 +614,8 @@ class StandardDomain(Domain):
|
||||
resolver = self._resolve_keyword_xref
|
||||
elif typ == 'option':
|
||||
resolver = self._resolve_option_xref
|
||||
elif typ == 'citation':
|
||||
resolver = self._resolve_citation_xref
|
||||
else:
|
||||
resolver = self._resolve_obj_xref
|
||||
|
||||
@ -683,6 +706,28 @@ class StandardDomain(Domain):
|
||||
return make_refnode(builder, fromdocname, docname,
|
||||
labelid, contnode)
|
||||
|
||||
def _resolve_citation_xref(self, env, fromdocname, builder, typ, target, node, contnode):
|
||||
from sphinx.environment import NoUri
|
||||
|
||||
docname, labelid = self.data['citations'].get(target, ('', ''))
|
||||
if not docname:
|
||||
if 'ids' in node:
|
||||
# remove ids attribute that annotated at
|
||||
# transforms.CitationReference.apply.
|
||||
del node['ids'][:]
|
||||
return None
|
||||
|
||||
try:
|
||||
return make_refnode(builder, fromdocname, docname,
|
||||
labelid, contnode)
|
||||
except NoUri:
|
||||
# remove the ids we added in the CitationReferences
|
||||
# transform since they can't be transfered to
|
||||
# the contnode (if it's a Text node)
|
||||
if not isinstance(contnode, nodes.Element):
|
||||
del node['ids'][:]
|
||||
raise
|
||||
|
||||
def _resolve_obj_xref(self, env, fromdocname, builder, typ, target, node, contnode):
|
||||
objtypes = self.objtypes_for_role(typ) or []
|
||||
for objtype in objtypes:
|
||||
|
@ -38,7 +38,7 @@ from sphinx import addnodes
|
||||
from sphinx.io import SphinxStandaloneReader, SphinxDummyWriter, SphinxFileInput
|
||||
from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
|
||||
FilenameUniqDict, split_index_msg
|
||||
from sphinx.util.nodes import clean_astext, make_refnode, WarningStream, is_translatable
|
||||
from sphinx.util.nodes import clean_astext, WarningStream, is_translatable
|
||||
from sphinx.util.osutil import SEP, getcwd, fs_encoding, ensuredir
|
||||
from sphinx.util.images import guess_mimetype
|
||||
from sphinx.util.i18n import find_catalog_files, get_image_filename_for_language, \
|
||||
@ -76,7 +76,7 @@ default_settings = {
|
||||
# or changed to properly invalidate pickle files.
|
||||
#
|
||||
# NOTE: increase base version by 2 to have distinct numbers for Py2 and 3
|
||||
ENV_VERSION = 49 + (sys.version_info[0] - 2)
|
||||
ENV_VERSION = 50 + (sys.version_info[0] - 2)
|
||||
|
||||
|
||||
dummy_reporter = Reporter('', 4, 4)
|
||||
@ -199,7 +199,6 @@ class BuildEnvironment:
|
||||
self.domaindata = {} # domainname -> domain-specific dict
|
||||
|
||||
# Other inventories
|
||||
self.citations = {} # citation name -> docname, labelid
|
||||
self.indexentries = {} # docname -> list of
|
||||
# (type, string, target, aliasname)
|
||||
self.versionchanges = {} # version -> list of (type, docname,
|
||||
@ -276,9 +275,6 @@ class BuildEnvironment:
|
||||
fnset.discard(docname)
|
||||
if not fnset:
|
||||
del self.files_to_rebuild[subfn]
|
||||
for key, (fn, _ignore) in list(self.citations.items()):
|
||||
if fn == docname:
|
||||
del self.citations[key]
|
||||
for version, changes in self.versionchanges.items():
|
||||
new = [change for change in changes if change[1] != docname]
|
||||
changes[:] = new
|
||||
@ -318,10 +314,6 @@ class BuildEnvironment:
|
||||
|
||||
for subfn, fnset in other.files_to_rebuild.items():
|
||||
self.files_to_rebuild.setdefault(subfn, set()).update(fnset & docnames)
|
||||
for key, data in other.citations.items():
|
||||
# XXX duplicates?
|
||||
if data[0] in docnames:
|
||||
self.citations[key] = data
|
||||
for version, changes in other.versionchanges.items():
|
||||
self.versionchanges.setdefault(version, []).extend(
|
||||
change for change in changes if change[1] in docnames)
|
||||
@ -745,7 +737,6 @@ class BuildEnvironment:
|
||||
self.process_refonly_bullet_lists(docname, doctree)
|
||||
self.create_title_from(docname, doctree)
|
||||
self.note_indexentries_from(docname, doctree)
|
||||
self.note_citations_from(docname, doctree)
|
||||
self.build_toc_from(docname, doctree)
|
||||
for domain in itervalues(self.domains):
|
||||
domain.process_doc(self, docname, doctree)
|
||||
@ -1100,15 +1091,6 @@ class BuildEnvironment:
|
||||
else:
|
||||
entries.append(entry + (None,))
|
||||
|
||||
def note_citations_from(self, docname, document):
|
||||
for node in document.traverse(nodes.citation):
|
||||
label = node[0].astext()
|
||||
if label in self.citations:
|
||||
self.warn_node('duplicate citation %s, ' % label +
|
||||
'other instance in %s' % self.doc2path(
|
||||
self.citations[label][0]), node)
|
||||
self.citations[label] = (docname, node['ids'][0])
|
||||
|
||||
def note_toctree(self, docname, toctreenode):
|
||||
"""Note a TOC tree directive in a document and gather information about
|
||||
file relations from it.
|
||||
@ -1527,8 +1509,6 @@ class BuildEnvironment:
|
||||
newnode = self._resolve_any_reference(builder, refdoc, node, contnode)
|
||||
elif typ == 'doc':
|
||||
newnode = self._resolve_doc_reference(builder, refdoc, node, contnode)
|
||||
elif typ == 'citation':
|
||||
newnode = self._resolve_citation(builder, refdoc, node, contnode)
|
||||
# no new node found? try the missing-reference event
|
||||
if newnode is None:
|
||||
newnode = builder.app.emit_firstresult(
|
||||
@ -1565,8 +1545,6 @@ class BuildEnvironment:
|
||||
msg = domain.dangling_warnings[typ]
|
||||
elif typ == 'doc':
|
||||
msg = 'unknown document: %(target)s'
|
||||
elif typ == 'citation':
|
||||
msg = 'citation not found: %(target)s'
|
||||
elif node.get('refdomain', 'std') not in ('', 'std'):
|
||||
msg = '%s:%s reference target not found: %%(target)s' % \
|
||||
(node['refdomain'], typ)
|
||||
@ -1591,25 +1569,6 @@ class BuildEnvironment:
|
||||
newnode.append(innernode)
|
||||
return newnode
|
||||
|
||||
def _resolve_citation(self, builder, fromdocname, node, contnode):
|
||||
docname, labelid = self.citations.get(node['reftarget'], ('', ''))
|
||||
if docname:
|
||||
try:
|
||||
newnode = make_refnode(builder, fromdocname,
|
||||
docname, labelid, contnode)
|
||||
return newnode
|
||||
except NoUri:
|
||||
# remove the ids we added in the CitationReferences
|
||||
# transform since they can't be transfered to
|
||||
# the contnode (if it's a Text node)
|
||||
if not isinstance(contnode, nodes.Element):
|
||||
del node['ids'][:]
|
||||
raise
|
||||
elif 'ids' in node:
|
||||
# remove ids attribute that annotated at
|
||||
# transforms.CitationReference.apply.
|
||||
del node['ids'][:]
|
||||
|
||||
def _resolve_any_reference(self, builder, refdoc, node, contnode):
|
||||
"""Resolve reference generated by the "any" role."""
|
||||
target = node['reftarget']
|
||||
|
@ -140,7 +140,7 @@ class CitationReferences(Transform):
|
||||
def apply(self):
|
||||
for citnode in self.document.traverse(nodes.citation_reference):
|
||||
cittext = citnode.astext()
|
||||
refnode = addnodes.pending_xref(cittext, reftype='citation',
|
||||
refnode = addnodes.pending_xref(cittext, refdomain='std', reftype='citation',
|
||||
reftarget=cittext, refwarn=True,
|
||||
ids=citnode["ids"])
|
||||
refnode.source = citnode.source or citnode.parent.source
|
||||
|
@ -26,6 +26,7 @@ def test_process_doc_handle_figure_caption():
|
||||
nameids={'testname': 'testid'},
|
||||
ids={'testid': figure_node},
|
||||
)
|
||||
document.traverse.return_value = []
|
||||
|
||||
domain = StandardDomain(env)
|
||||
if 'testname' in domain.data['labels']:
|
||||
@ -47,6 +48,7 @@ def test_process_doc_handle_table_title():
|
||||
nameids={'testname': 'testid'},
|
||||
ids={'testid': table_node},
|
||||
)
|
||||
document.traverse.return_value = []
|
||||
|
||||
domain = StandardDomain(env)
|
||||
if 'testname' in domain.data['labels']:
|
||||
|
Loading…
Reference in New Issue
Block a user