diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py index 9eec281f3e6..4593f9f3172 100644 --- a/sphinx/domains/rst.py +++ b/sphinx/domains/rst.py @@ -230,8 +230,8 @@ class ReSTDomain(Domain): 'role': ReSTRole, } roles = { - 'dir': XRefRole(), - 'role': XRefRole(), + 'dir': XRefRole(title_fmt=".. {title}::"), + 'role': XRefRole(title_fmt=":{title}:"), } initial_data: dict[str, dict[tuple[str, str], str]] = { 'objects': {}, # fullname -> docname, objtype diff --git a/sphinx/roles.py b/sphinx/roles.py index 27ceed29532..9cf4ab00b72 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -61,6 +61,9 @@ class XRefRole(ReferenceRole): * `lowercase` to lowercase the target * `nodeclass` and `innernodeclass` select the node classes for the reference and the content node + * `title_fmt`: an optional format string using one ``{title}`` variable + that can be used to customize the rendered text, e.g. + ``title_fmt=":{title}:"` * Subclassing and overwriting `process_link()` and/or `result_nodes()`. """ @@ -75,6 +78,7 @@ def __init__( nodeclass: type[Element] | None = None, innernodeclass: type[TextElement] | None = None, warn_dangling: bool = False, + title_fmt: str | None = None ) -> None: self.fix_parens = fix_parens self.lowercase = lowercase @@ -83,6 +87,7 @@ def __init__( self.nodeclass = nodeclass if innernodeclass is not None: self.innernodeclass = innernodeclass + self.title_fmt = title_fmt super().__init__() @@ -145,6 +150,8 @@ def create_xref_node(self) -> tuple[list[Node], list[system_message]]: self.env, refnode, self.has_explicit_title, title, target ) refnode['reftarget'] = target + if self.title_fmt is not None: + title = self.title_fmt.format(title=title) refnode += self.innernodeclass(self.rawtext, title, classes=self.classes) return self.result_nodes(self.inliner.document, self.env, refnode, is_ref=True)