This repository was archived by the owner on Apr 9, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathdomains.py
140 lines (111 loc) · 4.94 KB
/
domains.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
from sphinx.util import logging
logger = logging.getLogger(__name__)
class HoverXRefBaseDomain:
hoverxref_types = (
'hoverxref',
'hoverxreftooltip',
'hoverxrefmodal',
)
def _inject_hoverxref_data(self, env, refnode, typ):
classes = ['hoverxref']
type_class = None
if typ == 'hoverxreftooltip':
type_class = 'tooltip'
classes.append(type_class)
elif typ == 'hoverxrefmodal':
type_class = 'modal'
classes.append(type_class)
if not type_class:
type_class = env.config.hoverxref_role_types.get(typ)
if not type_class:
default = env.config.hoverxref_default_type
type_class = default
logger.info(
'Using default style (%s) for unknown typ (%s). '
'Define it in hoverxref_role_types.',
default,
typ,
)
classes.append(type_class)
refnode.replace_attr('classes', classes)
# TODO: log something else here, so we can unique identify this node
logger.debug(
':%s: _hoverxref injected. classes=%s',
typ,
classes,
)
def _is_ignored_ref(self, env, target):
# HACK: skip all references if the builder is non-html. We shouldn't
# have overridden the Domain in first instance at ``setup_domains``
# function, but at that time ``app.builder`` is not yet initialized. If
# we suscribe ourselves to ``builder-initied`` it's too late and our
# override does not take effect. Other builders (e.g. LatexBuilder) may
# fail with internal functions we use (e.g. builder.get_outfilename).
# So, we are skipping it here :(
if env.app.builder.format != 'html':
return True
if target in env.config.hoverxref_ignore_refs:
logger.info(
'Ignoring reference in hoverxref_ignore_refs. target=%s',
target,
)
return True
return False
class HoverXRefPythonDomainMixin(HoverXRefBaseDomain):
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
refnode = super().resolve_xref(env, fromdocname, builder, typ, target, node, contnode)
if refnode is None:
return refnode
if self._is_ignored_ref(env, target):
return refnode
self._inject_hoverxref_data(env, refnode, typ)
return refnode
class HoverXRefStandardDomainMixin(HoverXRefBaseDomain):
"""
Mixin for ``StandardDomain`` to save the values after the xref resolution.
``:ref:`` are treating as a different node in Sphinx
(``sphinx.addnodes.pending_xref``). These nodes are translated to regular
``docsutils.nodes.reference`` for this domain class.
This class add the required ``hoverxref`` and ``modal``/``tooltip`` to tell
the frontend to show a modal/tooltip on this element.
"""
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
if typ in self.hoverxref_types:
resolver = self._resolve_ref_xref
return resolver(env, fromdocname, builder, typ, target, node, contnode)
return super().resolve_xref(env, fromdocname, builder, typ, target, node, contnode)
# NOTE: We could override more ``_resolve_xref`` method apply hover in more places
def _resolve_ref_xref(self, env, fromdocname, builder, typ, target, node, contnode):
refnode = super()._resolve_ref_xref(env, fromdocname, builder, typ, target, node, contnode)
if refnode is None:
return refnode
if any([
self._is_ignored_ref(env, target),
not (env.config.hoverxref_auto_ref or typ in self.hoverxref_types)
]):
return refnode
self._inject_hoverxref_data(env, refnode, typ)
return refnode
def _resolve_obj_xref(self, env, fromdocname, builder, typ, target, node, contnode):
refnode = super()._resolve_obj_xref(env, fromdocname, builder, typ, target, node, contnode)
if refnode is None:
return refnode
if any([
self._is_ignored_ref(env, target),
typ not in env.config.hoverxref_roles,
]):
return refnode
self._inject_hoverxref_data(env, refnode, typ)
return refnode
# TODO: combine this method with ``_resolve_obj_xref``
def _resolve_numref_xref(self, env, fromdocname, builder, typ, target, node, contnode):
refnode = super()._resolve_numref_xref(env, fromdocname, builder, typ, target, node, contnode)
if refnode is None:
return refnode
if any([
self._is_ignored_ref(env, target),
typ not in env.config.hoverxref_roles,
]):
return refnode
self._inject_hoverxref_data(env, refnode, typ)
return refnode