mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Added the any
role that can be used to find a cross-reference of
*any* type in *any* domain. Custom domains should implement the new `~Domain.resolve_any_xref` method to make this work properly.
This commit is contained in:
parent
430be0496a
commit
c3eb669f8a
5
CHANGES
5
CHANGES
@ -18,6 +18,8 @@ Incompatible changes
|
|||||||
* #1543: :confval:`templates_path` is automatically added to
|
* #1543: :confval:`templates_path` is automatically added to
|
||||||
:confval:`exclude_patterns` to avoid reading autosummary rst templates in the
|
:confval:`exclude_patterns` to avoid reading autosummary rst templates in the
|
||||||
templates directory.
|
templates directory.
|
||||||
|
* Custom domains should implement the new :meth:`~Domain.resolve_any_xref`
|
||||||
|
method to make the :rst:role:`any` role work properly.
|
||||||
|
|
||||||
Features added
|
Features added
|
||||||
--------------
|
--------------
|
||||||
@ -26,6 +28,9 @@ Features added
|
|||||||
* Add support for docutils 0.12
|
* Add support for docutils 0.12
|
||||||
* Added ``sphinx.ext.napoleon`` extension for NumPy and Google style docstring
|
* Added ``sphinx.ext.napoleon`` extension for NumPy and Google style docstring
|
||||||
support.
|
support.
|
||||||
|
* Added the :rst:role:`any` role that can be used to find a cross-reference of
|
||||||
|
*any* type in *any* domain. Custom domains should implement the new
|
||||||
|
:meth:`~Domain.resolve_any_xref` method to make this work properly.
|
||||||
* Exception logs now contain the last 10 messages emitted by Sphinx.
|
* Exception logs now contain the last 10 messages emitted by Sphinx.
|
||||||
* Added support for extension versions (a string returned by ``setup()``, these
|
* Added support for extension versions (a string returned by ``setup()``, these
|
||||||
can be shown in the traceback log files). Version requirements for extensions
|
can be shown in the traceback log files). Version requirements for extensions
|
||||||
|
@ -12,7 +12,9 @@ They are written as ``:rolename:`content```.
|
|||||||
|
|
||||||
The default role (```content```) has no special meaning by default. You are
|
The default role (```content```) has no special meaning by default. You are
|
||||||
free to use it for anything you like, e.g. variable names; use the
|
free to use it for anything you like, e.g. variable names; use the
|
||||||
:confval:`default_role` config value to set it to a known role.
|
:confval:`default_role` config value to set it to a known role -- the
|
||||||
|
:rst:role:`any` role to find anything or the :rst:role:`py:obj` role to find
|
||||||
|
Python objects are very useful for this.
|
||||||
|
|
||||||
See :ref:`domains` for roles added by domains.
|
See :ref:`domains` for roles added by domains.
|
||||||
|
|
||||||
@ -38,12 +40,53 @@ more versatile:
|
|||||||
|
|
||||||
* If you prefix the content with ``~``, the link text will only be the last
|
* If you prefix the content with ``~``, the link text will only be the last
|
||||||
component of the target. For example, ``:py:meth:`~Queue.Queue.get``` will
|
component of the target. For example, ``:py:meth:`~Queue.Queue.get``` will
|
||||||
refer to ``Queue.Queue.get`` but only display ``get`` as the link text.
|
refer to ``Queue.Queue.get`` but only display ``get`` as the link text. This
|
||||||
|
does not work with all cross-reference roles, but is domain specific.
|
||||||
|
|
||||||
In HTML output, the link's ``title`` attribute (that is e.g. shown as a
|
In HTML output, the link's ``title`` attribute (that is e.g. shown as a
|
||||||
tool-tip on mouse-hover) will always be the full target name.
|
tool-tip on mouse-hover) will always be the full target name.
|
||||||
|
|
||||||
|
|
||||||
|
.. _any-role:
|
||||||
|
|
||||||
|
Cross-referencing anything
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. rst:role:: any
|
||||||
|
|
||||||
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
|
This convenience role tries to do its best to find a valid target for its
|
||||||
|
reference text.
|
||||||
|
|
||||||
|
* First, it tries standard cross-reference targets that would be referenced
|
||||||
|
by :rst:role:`doc`, :rst:role:`ref` or :rst:role:`option`.
|
||||||
|
|
||||||
|
Custom objects added to the standard domain by extensions (see
|
||||||
|
:meth:`.add_object_type`) are also searched.
|
||||||
|
|
||||||
|
* Then, it looks for objects (targets) in all loaded domains. It is up to
|
||||||
|
the domains how specific a match must be. For example, in the Python
|
||||||
|
domain a reference of ``:any:`Builder``` would match the
|
||||||
|
``sphinx.builders.Builder`` class.
|
||||||
|
|
||||||
|
If none or multiple targets are found, a warning will be emitted. In the
|
||||||
|
case of multiple targets, you can change "any" to a specific role.
|
||||||
|
|
||||||
|
This role is a good candidate for setting :confval:`default_role`. If you
|
||||||
|
do, you can write cross-references without a lot of markup overhead. For
|
||||||
|
example, in this Python function documentation ::
|
||||||
|
|
||||||
|
.. function:: install()
|
||||||
|
|
||||||
|
This function installs a `handler` for every signal known by the
|
||||||
|
`signal` module. See the section `about-signals` for more information.
|
||||||
|
|
||||||
|
there could be references to a glossary term (usually ``:term:`handler```), a
|
||||||
|
Python module (usually ``:py:mod:`signal``` or ``:mod:`signal```) and a
|
||||||
|
section (usually ``:ref:`about-signals```).
|
||||||
|
|
||||||
|
|
||||||
Cross-referencing objects
|
Cross-referencing objects
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@ -155,10 +155,13 @@ class Domain(object):
|
|||||||
self._role_cache = {}
|
self._role_cache = {}
|
||||||
self._directive_cache = {}
|
self._directive_cache = {}
|
||||||
self._role2type = {}
|
self._role2type = {}
|
||||||
|
self._type2role = {}
|
||||||
for name, obj in iteritems(self.object_types):
|
for name, obj in iteritems(self.object_types):
|
||||||
for rolename in obj.roles:
|
for rolename in obj.roles:
|
||||||
self._role2type.setdefault(rolename, []).append(name)
|
self._role2type.setdefault(rolename, []).append(name)
|
||||||
|
self._type2role[name] = obj.roles[0] if obj.roles else ''
|
||||||
self.objtypes_for_role = self._role2type.get
|
self.objtypes_for_role = self._role2type.get
|
||||||
|
self.role_for_objtype = self._type2role.get
|
||||||
|
|
||||||
def role(self, name):
|
def role(self, name):
|
||||||
"""Return a role adapter function that always gives the registered
|
"""Return a role adapter function that always gives the registered
|
||||||
@ -220,6 +223,22 @@ class Domain(object):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
|
||||||
|
"""Resolve the pending_xref *node* with the given *target*.
|
||||||
|
|
||||||
|
The reference comes from an "any" or similar role, which means that we
|
||||||
|
don't know the type. Otherwise, the arguments are the same as for
|
||||||
|
:meth:`resolve_xref`.
|
||||||
|
|
||||||
|
The method must return a list (potentially empty) of tuples
|
||||||
|
``('domain:role', newnode)``, where ``'domain:role'`` is the name of a
|
||||||
|
role that could have created the same reference, e.g. ``'py:func'``.
|
||||||
|
``newnode`` is what :meth:`resolve_xref` would return.
|
||||||
|
|
||||||
|
.. versionadded:: 1.3
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
"""Return an iterable of "object descriptions", which are tuples with
|
"""Return an iterable of "object descriptions", which are tuples with
|
||||||
five items:
|
five items:
|
||||||
|
@ -279,6 +279,17 @@ class CDomain(Domain):
|
|||||||
return make_refnode(builder, fromdocname, obj[0], 'c.' + target,
|
return make_refnode(builder, fromdocname, obj[0], 'c.' + target,
|
||||||
contnode, target)
|
contnode, target)
|
||||||
|
|
||||||
|
def resolve_any_xref(self, env, fromdocname, builder, target,
|
||||||
|
node, contnode):
|
||||||
|
# strip pointer asterisk
|
||||||
|
target = target.rstrip(' *')
|
||||||
|
if target not in self.data['objects']:
|
||||||
|
return []
|
||||||
|
obj = self.data['objects'][target]
|
||||||
|
return [('c:' + self.role_for_objtype(obj[1]),
|
||||||
|
make_refnode(builder, fromdocname, obj[0], 'c.' + target,
|
||||||
|
contnode, target))]
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
for refname, (docname, type) in list(self.data['objects'].items()):
|
for refname, (docname, type) in list(self.data['objects'].items()):
|
||||||
yield (refname, refname, type, docname, 'c.' + refname, 1)
|
yield (refname, refname, type, docname, 'c.' + refname, 1)
|
||||||
|
@ -1838,18 +1838,18 @@ class CPPDomain(Domain):
|
|||||||
if data[0] == docname:
|
if data[0] == docname:
|
||||||
del self.data['objects'][fullname]
|
del self.data['objects'][fullname]
|
||||||
|
|
||||||
def resolve_xref(self, env, fromdocname, builder,
|
def _resolve_xref_inner(self, env, fromdocname, builder,
|
||||||
typ, target, node, contnode):
|
target, node, contnode, warn=True):
|
||||||
def _create_refnode(nameAst):
|
def _create_refnode(nameAst):
|
||||||
name = text_type(nameAst)
|
name = text_type(nameAst)
|
||||||
if name not in self.data['objects']:
|
if name not in self.data['objects']:
|
||||||
# try dropping the last template
|
# try dropping the last template
|
||||||
name = nameAst.get_name_no_last_template()
|
name = nameAst.get_name_no_last_template()
|
||||||
if name not in self.data['objects']:
|
if name not in self.data['objects']:
|
||||||
return None
|
return None, None
|
||||||
docname, objectType, id = self.data['objects'][name]
|
docname, objectType, id = self.data['objects'][name]
|
||||||
return make_refnode(builder, fromdocname, docname, id, contnode,
|
return make_refnode(builder, fromdocname, docname, id, contnode,
|
||||||
name)
|
name), objectType
|
||||||
|
|
||||||
parser = DefinitionParser(target)
|
parser = DefinitionParser(target)
|
||||||
try:
|
try:
|
||||||
@ -1858,20 +1858,34 @@ class CPPDomain(Domain):
|
|||||||
if not parser.eof:
|
if not parser.eof:
|
||||||
raise DefinitionError('')
|
raise DefinitionError('')
|
||||||
except DefinitionError:
|
except DefinitionError:
|
||||||
env.warn_node('unparseable C++ definition: %r' % target, node)
|
if warn:
|
||||||
return None
|
env.warn_node('unparseable C++ definition: %r' % target, node)
|
||||||
|
return None, None
|
||||||
|
|
||||||
# try as is the name is fully qualified
|
# try as is the name is fully qualified
|
||||||
refNode = _create_refnode(nameAst)
|
res = _create_refnode(nameAst)
|
||||||
if refNode:
|
if res[0]:
|
||||||
return refNode
|
return res
|
||||||
|
|
||||||
# try qualifying it with the parent
|
# try qualifying it with the parent
|
||||||
parent = node.get('cpp:parent', None)
|
parent = node.get('cpp:parent', None)
|
||||||
if parent and len(parent) > 0:
|
if parent and len(parent) > 0:
|
||||||
return _create_refnode(nameAst.prefix_nested_name(parent[-1]))
|
return _create_refnode(nameAst.prefix_nested_name(parent[-1]))
|
||||||
else:
|
else:
|
||||||
return None
|
return None, None
|
||||||
|
|
||||||
|
def resolve_xref(self, env, fromdocname, builder,
|
||||||
|
typ, target, node, contnode):
|
||||||
|
return self._resolve_xref_inner(env, fromdocname, builder, target, node,
|
||||||
|
contnode)[0]
|
||||||
|
|
||||||
|
def resolve_any_xref(self, env, fromdocname, builder, target,
|
||||||
|
node, contnode):
|
||||||
|
node, objtype = self._resolve_xref_inner(env, fromdocname, builder,
|
||||||
|
target, node, contnode, warn=False)
|
||||||
|
if node:
|
||||||
|
return [('cpp:' + self.role_for_objtype(objtype), node)]
|
||||||
|
return []
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
for refname, (docname, type, theid) in iteritems(self.data['objects']):
|
for refname, (docname, type, theid) in iteritems(self.data['objects']):
|
||||||
|
@ -179,7 +179,7 @@ class JavaScriptDomain(Domain):
|
|||||||
'attr': JSXRefRole(),
|
'attr': JSXRefRole(),
|
||||||
}
|
}
|
||||||
initial_data = {
|
initial_data = {
|
||||||
'objects': {}, # fullname -> docname, objtype
|
'objects': {}, # fullname -> docname, objtype
|
||||||
}
|
}
|
||||||
|
|
||||||
def clear_doc(self, docname):
|
def clear_doc(self, docname):
|
||||||
@ -214,6 +214,16 @@ class JavaScriptDomain(Domain):
|
|||||||
return make_refnode(builder, fromdocname, obj[0],
|
return make_refnode(builder, fromdocname, obj[0],
|
||||||
name.replace('$', '_S_'), contnode, name)
|
name.replace('$', '_S_'), contnode, name)
|
||||||
|
|
||||||
|
def resolve_any_xref(self, env, fromdocname, builder, target, node,
|
||||||
|
contnode):
|
||||||
|
objectname = node.get('js:object') # not likely
|
||||||
|
name, obj = self.find_obj(env, objectname, target, None, 1)
|
||||||
|
if not obj:
|
||||||
|
return []
|
||||||
|
return [('js:' + self.role_for_objtype(obj[1]),
|
||||||
|
make_refnode(builder, fromdocname, obj[0],
|
||||||
|
name.replace('$', '_S_'), contnode, name))]
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
for refname, (docname, type) in list(self.data['objects'].items()):
|
for refname, (docname, type) in list(self.data['objects'].items()):
|
||||||
yield refname, refname, type, docname, \
|
yield refname, refname, type, docname, \
|
||||||
|
@ -643,7 +643,10 @@ class PythonDomain(Domain):
|
|||||||
|
|
||||||
newname = None
|
newname = None
|
||||||
if searchmode == 1:
|
if searchmode == 1:
|
||||||
objtypes = self.objtypes_for_role(type)
|
if type is None:
|
||||||
|
objtypes = list(self.object_types)
|
||||||
|
else:
|
||||||
|
objtypes = self.objtypes_for_role(type)
|
||||||
if objtypes is not None:
|
if objtypes is not None:
|
||||||
if modname and classname:
|
if modname and classname:
|
||||||
fullname = modname + '.' + classname + '.' + name
|
fullname = modname + '.' + classname + '.' + name
|
||||||
@ -704,22 +707,44 @@ class PythonDomain(Domain):
|
|||||||
name, obj = matches[0]
|
name, obj = matches[0]
|
||||||
|
|
||||||
if obj[1] == 'module':
|
if obj[1] == 'module':
|
||||||
# get additional info for modules
|
return self._make_module_refnode(builder, fromdocname, name,
|
||||||
docname, synopsis, platform, deprecated = self.data['modules'][name]
|
contnode)
|
||||||
assert docname == obj[0]
|
|
||||||
title = name
|
|
||||||
if synopsis:
|
|
||||||
title += ': ' + synopsis
|
|
||||||
if deprecated:
|
|
||||||
title += _(' (deprecated)')
|
|
||||||
if platform:
|
|
||||||
title += ' (' + platform + ')'
|
|
||||||
return make_refnode(builder, fromdocname, docname,
|
|
||||||
'module-' + name, contnode, title)
|
|
||||||
else:
|
else:
|
||||||
return make_refnode(builder, fromdocname, obj[0], name,
|
return make_refnode(builder, fromdocname, obj[0], name,
|
||||||
contnode, name)
|
contnode, name)
|
||||||
|
|
||||||
|
def resolve_any_xref(self, env, fromdocname, builder, target,
|
||||||
|
node, contnode):
|
||||||
|
modname = node.get('py:module') # it is not likely we have these
|
||||||
|
clsname = node.get('py:class')
|
||||||
|
results = []
|
||||||
|
|
||||||
|
# always search in "refspecific" mode with the :any: role
|
||||||
|
matches = self.find_obj(env, modname, clsname, target, None, 1)
|
||||||
|
for name, obj in matches:
|
||||||
|
if obj[1] == 'module':
|
||||||
|
results.append(('py:mod',
|
||||||
|
self._make_module_refnode(builder, fromdocname,
|
||||||
|
name, contnode)))
|
||||||
|
else:
|
||||||
|
results.append(('py:' + self.role_for_objtype(obj[1]),
|
||||||
|
make_refnode(builder, fromdocname, obj[0], name,
|
||||||
|
contnode, name)))
|
||||||
|
return results
|
||||||
|
|
||||||
|
def _make_module_refnode(self, builder, fromdocname, name, contnode):
|
||||||
|
# get additional info for modules
|
||||||
|
docname, synopsis, platform, deprecated = self.data['modules'][name]
|
||||||
|
title = name
|
||||||
|
if synopsis:
|
||||||
|
title += ': ' + synopsis
|
||||||
|
if deprecated:
|
||||||
|
title += _(' (deprecated)')
|
||||||
|
if platform:
|
||||||
|
title += ' (' + platform + ')'
|
||||||
|
return make_refnode(builder, fromdocname, docname,
|
||||||
|
'module-' + name, contnode, title)
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
for modname, info in iteritems(self.data['modules']):
|
for modname, info in iteritems(self.data['modules']):
|
||||||
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
|
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
|
||||||
|
@ -134,6 +134,19 @@ class ReSTDomain(Domain):
|
|||||||
objtype + '-' + target,
|
objtype + '-' + target,
|
||||||
contnode, target + ' ' + objtype)
|
contnode, target + ' ' + objtype)
|
||||||
|
|
||||||
|
def resolve_any_xref(self, env, fromdocname, builder, target,
|
||||||
|
node, contnode):
|
||||||
|
objects = self.data['objects']
|
||||||
|
results = []
|
||||||
|
for objtype in self.object_types:
|
||||||
|
if (objtype, target) in self.data['objects']:
|
||||||
|
results.append(('rst:' + self.role_for_objtype(objtype),
|
||||||
|
make_refnode(builder, fromdocname,
|
||||||
|
objects[objtype, target],
|
||||||
|
objtype + '-' + target,
|
||||||
|
contnode, target + ' ' + objtype)))
|
||||||
|
return results
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
for (typ, name), docname in iteritems(self.data['objects']):
|
for (typ, name), docname in iteritems(self.data['objects']):
|
||||||
yield name, name, typ, docname, typ + '-' + name, 1
|
yield name, name, typ, docname, typ + '-' + name, 1
|
||||||
|
@ -628,6 +628,23 @@ class StandardDomain(Domain):
|
|||||||
return make_refnode(builder, fromdocname, docname,
|
return make_refnode(builder, fromdocname, docname,
|
||||||
labelid, contnode)
|
labelid, contnode)
|
||||||
|
|
||||||
|
def resolve_any_xref(self, env, fromdocname, builder, target,
|
||||||
|
node, contnode):
|
||||||
|
results = []
|
||||||
|
for role in ('ref', 'option'): # do not try "keyword"
|
||||||
|
res = self.resolve_xref(env, fromdocname, builder, target,
|
||||||
|
role, node, contnode)
|
||||||
|
if res:
|
||||||
|
results.append(('std:ref', res))
|
||||||
|
# all others
|
||||||
|
for objtype in self.object_types:
|
||||||
|
if (objtype, target) in self.data['objects']:
|
||||||
|
docname, labelid = self.data['objects'][objtype, target]
|
||||||
|
results.append(('std:' + self.role_for_objtype(objtype),
|
||||||
|
make_refnode(builder, fromdocname, docname,
|
||||||
|
labelid, contnode)))
|
||||||
|
return results
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
for (prog, option), info in iteritems(self.data['progoptions']):
|
for (prog, option), info in iteritems(self.data['progoptions']):
|
||||||
yield (option, option, 'option', info[0], info[1], 1)
|
yield (option, option, 'option', info[0], info[1], 1)
|
||||||
|
@ -1352,6 +1352,8 @@ class BuildEnvironment:
|
|||||||
newnode = domain.resolve_xref(self, refdoc, builder,
|
newnode = domain.resolve_xref(self, refdoc, builder,
|
||||||
typ, target, node, contnode)
|
typ, target, node, contnode)
|
||||||
# really hardwired reference types
|
# really hardwired reference types
|
||||||
|
elif typ == 'any':
|
||||||
|
newnode = self._resolve_any_reference(builder, node, contnode)
|
||||||
elif typ == 'doc':
|
elif typ == 'doc':
|
||||||
newnode = self._resolve_doc_reference(builder, node, contnode)
|
newnode = self._resolve_doc_reference(builder, node, contnode)
|
||||||
elif typ == 'citation':
|
elif typ == 'citation':
|
||||||
@ -1435,6 +1437,49 @@ class BuildEnvironment:
|
|||||||
# transforms.CitationReference.apply.
|
# transforms.CitationReference.apply.
|
||||||
del node['ids'][:]
|
del node['ids'][:]
|
||||||
|
|
||||||
|
def _resolve_any_reference(self, builder, node, contnode):
|
||||||
|
"""Resolve reference generated by the "any" role."""
|
||||||
|
refdoc = node['refdoc']
|
||||||
|
target = node['reftarget']
|
||||||
|
results = []
|
||||||
|
# first, try resolving as :doc:
|
||||||
|
doc_ref = self._resolve_doc_reference(builder, node, contnode)
|
||||||
|
if doc_ref:
|
||||||
|
results.append(('doc', doc_ref))
|
||||||
|
# next, do the standard domain (makes this a priority)
|
||||||
|
results.extend(self.domains['std'].resolve_any_xref(
|
||||||
|
self, refdoc, builder, target, node, contnode))
|
||||||
|
for domain in self.domains.values():
|
||||||
|
if domain.name == 'std':
|
||||||
|
continue # we did this one already
|
||||||
|
try:
|
||||||
|
results.extend(domain.resolve_any_xref(self, refdoc, builder,
|
||||||
|
target, node, contnode))
|
||||||
|
except NotImplementedError:
|
||||||
|
# the domain doesn't yet support the new interface
|
||||||
|
# we have to manually collect possible references (SLOW)
|
||||||
|
for role in domain.roles:
|
||||||
|
res = domain.resolve_xref(self, refdoc, builder, role, target,
|
||||||
|
node, contnode)
|
||||||
|
if res:
|
||||||
|
results.append(('%s:%s' % (domain.name, role), res))
|
||||||
|
# now, see how many matches we got...
|
||||||
|
if not results:
|
||||||
|
return None
|
||||||
|
if len(results) > 1:
|
||||||
|
nice_results = ' or '.join(':%s:' % r[0] for r in results)
|
||||||
|
self.warn_node('more than one target found for \'any\' cross-'
|
||||||
|
'reference %r: could be %s' % (target, nice_results),
|
||||||
|
node)
|
||||||
|
res_role, newnode = results[0]
|
||||||
|
# Override "any" class with the actual role type to get the styling
|
||||||
|
# approximately correct.
|
||||||
|
res_domain = res_role.split(':')[0]
|
||||||
|
if newnode and newnode[0].get('classes'):
|
||||||
|
newnode[0]['classes'].append(res_domain)
|
||||||
|
newnode[0]['classes'].append(res_role.replace(':', '-'))
|
||||||
|
return newnode
|
||||||
|
|
||||||
def process_only_nodes(self, doctree, builder, fromdocname=None):
|
def process_only_nodes(self, doctree, builder, fromdocname=None):
|
||||||
# A comment on the comment() nodes being inserted: replacing by [] would
|
# A comment on the comment() nodes being inserted: replacing by [] would
|
||||||
# result in a "Losing ids" exception if there is a target node before
|
# result in a "Losing ids" exception if there is a target node before
|
||||||
|
@ -316,6 +316,8 @@ specific_docroles = {
|
|||||||
'download': XRefRole(nodeclass=addnodes.download_reference),
|
'download': XRefRole(nodeclass=addnodes.download_reference),
|
||||||
# links to documents
|
# links to documents
|
||||||
'doc': XRefRole(warn_dangling=True),
|
'doc': XRefRole(warn_dangling=True),
|
||||||
|
# links to anything
|
||||||
|
'any': XRefRole(warn_dangling=True),
|
||||||
|
|
||||||
'pep': indexmarkup_role,
|
'pep': indexmarkup_role,
|
||||||
'rfc': indexmarkup_role,
|
'rfc': indexmarkup_role,
|
||||||
|
Loading…
Reference in New Issue
Block a user