Replace :index: role by class based implementation

This commit is contained in:
Takeshi KOMIYA 2019-02-14 22:36:34 +09:00
parent 424c438c52
commit a6d345f95d
4 changed files with 67 additions and 2 deletions

View File

@ -116,6 +116,7 @@ Deprecated
* ``sphinx.io.SphinxRSTFileInput`` * ``sphinx.io.SphinxRSTFileInput``
* ``sphinx.registry.SphinxComponentRegistry.add_source_input()`` * ``sphinx.registry.SphinxComponentRegistry.add_source_input()``
* ``sphinx.roles.abbr_role()`` * ``sphinx.roles.abbr_role()``
* ``sphinx.roles.index_role()``
* ``sphinx.testing.util.remove_unicode_literal()`` * ``sphinx.testing.util.remove_unicode_literal()``
* ``sphinx.util.attrdict`` * ``sphinx.util.attrdict``
* ``sphinx.util.force_decode()`` * ``sphinx.util.force_decode()``

View File

@ -380,6 +380,11 @@ The following is a list of deprecated interfaces.
- 4.0 - 4.0
- ``sphinx.roles.Abbreviation`` - ``sphinx.roles.Abbreviation``
* - ``sphinx.roles.index_role()``
- 2.0
- 4.0
- ``sphinx.roles.Index``
* - ``sphinx.testing.util.remove_unicode_literal()`` * - ``sphinx.testing.util.remove_unicode_literal()``
- 2.0 - 2.0
- 4.0 - 4.0

View File

@ -18,7 +18,7 @@ from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.errors import SphinxError from sphinx.errors import SphinxError
from sphinx.locale import _ from sphinx.locale import _
from sphinx.util import ws_re from sphinx.util import ws_re
from sphinx.util.docutils import SphinxRole from sphinx.util.docutils import ReferenceRole, SphinxRole
from sphinx.util.nodes import split_explicit_title, process_index_entry, \ from sphinx.util.nodes import split_explicit_title, process_index_entry, \
set_role_source_info set_role_source_info
@ -371,6 +371,8 @@ class Abbreviation(SphinxRole):
def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA # type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
warnings.warn('index_role() is deprecated. Please use Index class instead.',
RemovedInSphinx40Warning, stacklevel=2)
# create new reference target # create new reference target
env = inliner.document.settings.env env = inliner.document.settings.env
targetid = 'index-%s' % env.new_serialno('index') targetid = 'index-%s' % env.new_serialno('index')
@ -398,6 +400,30 @@ def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
return [indexnode, targetnode, textnode], [] return [indexnode, targetnode, textnode], []
class Index(ReferenceRole):
def run(self):
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
target_id = 'index-%s' % self.env.new_serialno('index')
if self.has_explicit_title:
# if an explicit target is given, process it as a full entry
title = self.title
entries = process_index_entry(self.target, target_id)
else:
# otherwise we just create a single entry
if self.target.startswith('!'):
title = self.title[1:]
entries = [('single', self.target[1:], target_id, 'main', None)]
else:
title = self.title
entries = [('single', self.target, target_id, '', None)]
index = addnodes.index(entries=entries)
target = nodes.target('', '', ids=[target_id])
text = nodes.Text(title, title)
self.set_source_info(index)
return [index, target, text], []
specific_docroles = { specific_docroles = {
# links to download references # links to download references
'download': XRefRole(nodeclass=addnodes.download_reference), 'download': XRefRole(nodeclass=addnodes.download_reference),
@ -411,7 +437,7 @@ specific_docroles = {
'file': emph_literal_role, 'file': emph_literal_role,
'samp': emph_literal_role, 'samp': emph_literal_role,
'abbr': Abbreviation(), 'abbr': Abbreviation(),
'index': index_role, 'index': Index(),
} # type: Dict[str, RoleFunction] } # type: Dict[str, RoleFunction]

View File

@ -421,6 +421,39 @@ class SphinxRole:
"""Reference to the :class:`.Config` object.""" """Reference to the :class:`.Config` object."""
return self.env.config return self.env.config
def set_source_info(self, node, lineno=None):
# type: (nodes.Node, int) -> None
if lineno is None:
lineno = self.lineno
source_info = self.inliner.reporter.get_source_and_line(lineno) # type: ignore
node.source, node.line = source_info
class ReferenceRole(SphinxRole):
"""A base class for reference roles.
The reference roles can accpet ``link title <target>`` style as a text for
the role. The parsed result: link title and target will be stored to
``self.title`` and ``self.target``.
"""
# \x00 means the "<" was backslash-escaped
explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
def __call__(self, typ, rawtext, text, lineno, inliner, options={}, content=[]):
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
matched = self.explicit_title_re.match(text)
if matched:
self.has_explicit_title = True
self.title = unescape(matched.group(1))
self.target = unescape(matched.group(2))
else:
self.has_explicit_title = False
self.title = unescape(text)
self.target = unescape(text)
return super().__call__(typ, rawtext, text, lineno, inliner, options, content)
class SphinxTranslator(nodes.NodeVisitor): class SphinxTranslator(nodes.NodeVisitor):
"""A base class for Sphinx translators. """A base class for Sphinx translators.