Skip to content

Commit 0fbf88a

Browse files
n-peugnetAA-Turner
andauthored
Allow extensions to define the keys returned by linkcode (sphinx-doc#11824)
Co-authored-by: Adam Turner <[email protected]>
1 parent 20c1c7f commit 0fbf88a

File tree

6 files changed

+54
-8
lines changed

6 files changed

+54
-8
lines changed

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ Features added
2121
* Add a new ``duplicate_declaration`` warning type,
2222
with ``duplicate_declaration.c`` and ``duplicate_declaration.cpp`` subtypes.
2323
Patch by Julien Lecomte and Adam Turner.
24+
* #11824: linkcode: Allow extensions to add support for a domain by defining
25+
the keys that should be present.
26+
Patch by Nicolas Peugnet.
2427

2528
Bugs fixed
2629
----------

doc/usage/extensions/linkcode.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,21 @@ Configuration
4949
return None
5050
filename = info['module'].replace('.', '/')
5151
return "https://somesite/sourcerepo/%s.py" % filename
52+
53+
54+
Third-party domains
55+
-------------------
56+
57+
Support for other domains can be added by extensions with
58+
:py:func:`.add_linkcode_domain()`.
59+
For example, a Sphinx extension that provides a ``php`` domain
60+
could use the following code to support :mod:`~sphinx.ext.linkcode`:
61+
62+
.. code-block:: python
63+
64+
from sphinx.ext.linkcode import add_linkcode_domain
65+
66+
def setup(app):
67+
add_linkcode_domain('php', ['namespace', 'class', 'fullname'])
68+
69+
.. autofunction:: add_linkcode_domain

sphinx/ext/linkcode.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,23 @@
1818
from sphinx.util.typing import ExtensionMetadata
1919

2020

21+
_DOMAIN_KEYS = {
22+
'py': ['module', 'fullname'],
23+
'c': ['names'],
24+
'cpp': ['names'],
25+
'js': ['object', 'fullname'],
26+
}
27+
28+
29+
def add_linkcode_domain(domain: str, keys: list[str], override: bool = False) -> None:
30+
"""Register a new list of keys to use for a domain.
31+
32+
.. versionadded:: 8.2
33+
"""
34+
if override or domain not in _DOMAIN_KEYS:
35+
_DOMAIN_KEYS[domain] = list(keys)
36+
37+
2138
class LinkcodeError(SphinxError):
2239
category = 'linkcode error'
2340

@@ -37,13 +54,6 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
3754
# ``supported_linkcode`` attribute.
3855
node_only_expr = getattr(app.builder, 'supported_linkcode', 'html')
3956

40-
domain_keys = {
41-
'py': ['module', 'fullname'],
42-
'c': ['names'],
43-
'cpp': ['names'],
44-
'js': ['object', 'fullname'],
45-
}
46-
4757
for objnode in list(doctree.findall(addnodes.desc)):
4858
domain = objnode.get('domain')
4959
uris: set[str] = set()
@@ -53,7 +63,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
5363

5464
# Convert signode to a specified format
5565
info = {}
56-
for key in domain_keys.get(domain, []):
66+
for key in _DOMAIN_KEYS.get(domain, []):
5767
value = signode.get(key)
5868
if not value:
5969
value = ''

tests/roots/test-ext-viewcode/conf.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import sys
22
from pathlib import Path
33

4+
from sphinx.ext.linkcode import add_linkcode_domain
5+
46
sys.path.insert(0, str(Path.cwd().resolve()))
57

68
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
@@ -19,5 +21,10 @@ def linkcode_resolve(domain, info):
1921
return 'https://foobar/js/' + info['fullname']
2022
elif domain in {'c', 'cpp'}:
2123
return f'https://foobar/{domain}/{"".join(info["names"])}'
24+
elif domain == 'rst':
25+
return 'http://foobar/rst/{fullname}'.format(**info)
2226
else:
2327
raise AssertionError
28+
29+
def setup(app):
30+
add_linkcode_domain('rst', ['fullname'])

tests/roots/test-ext-viewcode/objects.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,10 @@ CPP domain
167167

168168
.. cpp:function:: T& operator[]( unsigned j )
169169
const T& operator[]( unsigned j ) const
170+
171+
rST domain
172+
==========
173+
174+
.. rst:role:: foo
175+
176+
Foo description.

tests/test_extensions/test_ext_viewcode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ def test_linkcode(app):
116116
assert 'https://foobar/js/' in stuff
117117
assert 'https://foobar/c/' in stuff
118118
assert 'https://foobar/cpp/' in stuff
119+
assert 'http://foobar/rst/' in stuff
119120

120121

121122
@pytest.mark.sphinx('html', testroot='ext-viewcode-find', freshenv=True)

0 commit comments

Comments
 (0)