mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Allow extensions to define the keys returned by linkcode (#11824)
Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
parent
20c1c7fc1c
commit
0fbf88a59f
@ -21,6 +21,9 @@ Features added
|
|||||||
* Add a new ``duplicate_declaration`` warning type,
|
* Add a new ``duplicate_declaration`` warning type,
|
||||||
with ``duplicate_declaration.c`` and ``duplicate_declaration.cpp`` subtypes.
|
with ``duplicate_declaration.c`` and ``duplicate_declaration.cpp`` subtypes.
|
||||||
Patch by Julien Lecomte and Adam Turner.
|
Patch by Julien Lecomte and Adam Turner.
|
||||||
|
* #11824: linkcode: Allow extensions to add support for a domain by defining
|
||||||
|
the keys that should be present.
|
||||||
|
Patch by Nicolas Peugnet.
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
@ -49,3 +49,21 @@ Configuration
|
|||||||
return None
|
return None
|
||||||
filename = info['module'].replace('.', '/')
|
filename = info['module'].replace('.', '/')
|
||||||
return "https://somesite/sourcerepo/%s.py" % filename
|
return "https://somesite/sourcerepo/%s.py" % filename
|
||||||
|
|
||||||
|
|
||||||
|
Third-party domains
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Support for other domains can be added by extensions with
|
||||||
|
:py:func:`.add_linkcode_domain()`.
|
||||||
|
For example, a Sphinx extension that provides a ``php`` domain
|
||||||
|
could use the following code to support :mod:`~sphinx.ext.linkcode`:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from sphinx.ext.linkcode import add_linkcode_domain
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
add_linkcode_domain('php', ['namespace', 'class', 'fullname'])
|
||||||
|
|
||||||
|
.. autofunction:: add_linkcode_domain
|
||||||
|
@ -18,6 +18,23 @@ if TYPE_CHECKING:
|
|||||||
from sphinx.util.typing import ExtensionMetadata
|
from sphinx.util.typing import ExtensionMetadata
|
||||||
|
|
||||||
|
|
||||||
|
_DOMAIN_KEYS = {
|
||||||
|
'py': ['module', 'fullname'],
|
||||||
|
'c': ['names'],
|
||||||
|
'cpp': ['names'],
|
||||||
|
'js': ['object', 'fullname'],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def add_linkcode_domain(domain: str, keys: list[str], override: bool = False) -> None:
|
||||||
|
"""Register a new list of keys to use for a domain.
|
||||||
|
|
||||||
|
.. versionadded:: 8.2
|
||||||
|
"""
|
||||||
|
if override or domain not in _DOMAIN_KEYS:
|
||||||
|
_DOMAIN_KEYS[domain] = list(keys)
|
||||||
|
|
||||||
|
|
||||||
class LinkcodeError(SphinxError):
|
class LinkcodeError(SphinxError):
|
||||||
category = 'linkcode error'
|
category = 'linkcode error'
|
||||||
|
|
||||||
@ -37,13 +54,6 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|||||||
# ``supported_linkcode`` attribute.
|
# ``supported_linkcode`` attribute.
|
||||||
node_only_expr = getattr(app.builder, 'supported_linkcode', 'html')
|
node_only_expr = getattr(app.builder, 'supported_linkcode', 'html')
|
||||||
|
|
||||||
domain_keys = {
|
|
||||||
'py': ['module', 'fullname'],
|
|
||||||
'c': ['names'],
|
|
||||||
'cpp': ['names'],
|
|
||||||
'js': ['object', 'fullname'],
|
|
||||||
}
|
|
||||||
|
|
||||||
for objnode in list(doctree.findall(addnodes.desc)):
|
for objnode in list(doctree.findall(addnodes.desc)):
|
||||||
domain = objnode.get('domain')
|
domain = objnode.get('domain')
|
||||||
uris: set[str] = set()
|
uris: set[str] = set()
|
||||||
@ -53,7 +63,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None:
|
|||||||
|
|
||||||
# Convert signode to a specified format
|
# Convert signode to a specified format
|
||||||
info = {}
|
info = {}
|
||||||
for key in domain_keys.get(domain, []):
|
for key in _DOMAIN_KEYS.get(domain, []):
|
||||||
value = signode.get(key)
|
value = signode.get(key)
|
||||||
if not value:
|
if not value:
|
||||||
value = ''
|
value = ''
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from sphinx.ext.linkcode import add_linkcode_domain
|
||||||
|
|
||||||
sys.path.insert(0, str(Path.cwd().resolve()))
|
sys.path.insert(0, str(Path.cwd().resolve()))
|
||||||
|
|
||||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||||
@ -19,5 +21,10 @@ if 'test_linkcode' in tags: # NoQA: F821 (tags is injected into conf.py)
|
|||||||
return 'https://foobar/js/' + info['fullname']
|
return 'https://foobar/js/' + info['fullname']
|
||||||
elif domain in {'c', 'cpp'}:
|
elif domain in {'c', 'cpp'}:
|
||||||
return f'https://foobar/{domain}/{"".join(info["names"])}'
|
return f'https://foobar/{domain}/{"".join(info["names"])}'
|
||||||
|
elif domain == 'rst':
|
||||||
|
return 'http://foobar/rst/{fullname}'.format(**info)
|
||||||
else:
|
else:
|
||||||
raise AssertionError
|
raise AssertionError
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
add_linkcode_domain('rst', ['fullname'])
|
||||||
|
@ -167,3 +167,10 @@ CPP domain
|
|||||||
|
|
||||||
.. cpp:function:: T& operator[]( unsigned j )
|
.. cpp:function:: T& operator[]( unsigned j )
|
||||||
const T& operator[]( unsigned j ) const
|
const T& operator[]( unsigned j ) const
|
||||||
|
|
||||||
|
rST domain
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. rst:role:: foo
|
||||||
|
|
||||||
|
Foo description.
|
||||||
|
@ -116,6 +116,7 @@ def test_linkcode(app):
|
|||||||
assert 'https://foobar/js/' in stuff
|
assert 'https://foobar/js/' in stuff
|
||||||
assert 'https://foobar/c/' in stuff
|
assert 'https://foobar/c/' in stuff
|
||||||
assert 'https://foobar/cpp/' in stuff
|
assert 'https://foobar/cpp/' in stuff
|
||||||
|
assert 'http://foobar/rst/' in stuff
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-viewcode-find', freshenv=True)
|
@pytest.mark.sphinx('html', testroot='ext-viewcode-find', freshenv=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user