diff --git a/docs/insiders/changelog.md b/docs/insiders/changelog.md
index ab70887a..a6c7b907 100644
--- a/docs/insiders/changelog.md
+++ b/docs/insiders/changelog.md
@@ -2,6 +2,11 @@
## mkdocstrings-python Insiders
+### 1.9.0 September 03, 2024 { id="1.9.0" }
+
+- [Relative cross-references][relative_crossrefs]
+- [Scoped cross-references][scoped_crossrefs]
+
### 1.8.3 June 19, 2024 { id="1.8.3" }
- Update code for Griffe 0.46+ to avoid deprecation warnings
diff --git a/docs/insiders/goals.yml b/docs/insiders/goals.yml
index 57985eae..16d1d507 100644
--- a/docs/insiders/goals.yml
+++ b/docs/insiders/goals.yml
@@ -37,3 +37,8 @@ goals:
name: FusionDrive Ejection Configuration
features:
- name: Relative cross-references
+ ref: /usage/configuration/docstrings/#relative_crossrefs
+ since: 2024/09/03
+ - name: Scoped cross-references
+ ref: /usage/configuration/docstrings/#scoped_crossrefs
+ since: 2024/09/03
diff --git a/docs/usage/configuration/docstrings.md b/docs/usage/configuration/docstrings.md
index 027ebaed..d88cbbfb 100644
--- a/docs/usage/configuration/docstrings.md
+++ b/docs/usage/configuration/docstrings.md
@@ -317,6 +317,226 @@ class Thing:
////
///
+## `relative_crossrefs`
+
+[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } —
+[:octicons-tag-24: Insiders 1.9.0](../../insiders/changelog.md#1.9.0)
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
+
+
+Whether to enable the relative-crossref syntax.
+
+The relative-crossref syntax lets you reference the current object or its parent by prefixing a crossref identifier with dots. For example, to cross-reference the current object's `name` member, you can write `[link to name attribute][.name]`. The "current object" is the object containing the docstring being rendered.
+
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ relative_crossrefs: false
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.module
+ options:
+ relative_crossrefs: true
+```
+
+/// admonition | Examples
+ type: preview
+
+```python title="pkg/module.py"
+"""Summary.
+
+- Link to [`module`][.].
+- Link to [`module_attribute`][.module_attribute].
+- Link to [`Class`][.Class].
+- Link to [`class_attribute`][.Class.class_attribute].
+- Link to [`instance_attribute`][.Class.instance_attribute].
+- Link to [`method`][.Class.method].
+"""
+
+module_attribute = 0
+"""Summary.
+
+- Link to [`module`][..].
+- Link to [`module_attribute`][.].
+- Link to [`Class`][..Class].
+- Link to [`class_attribute`][..Class.class_attribute].
+- Link to [`instance_attribute`][..Class.instance_attribute].
+- Link to [`method`][..Class.method].
+"""
+
+class Class:
+ """Summary.
+
+ - Link to [`module`][..].
+ - Link to [`module_attribute`][..module_attribute].
+ - Link to [`Class`][.].
+ - Link to [`class_attribute`][.class_attribute].
+ - Link to [`instance_attribute`][.instance_attribute].
+ - Link to [`method`][.method].
+ """
+
+ class_attribute = 0
+ """Summary.
+
+ - Link to [`module`][...].
+ - Link to [`module_attribute`][...module_attribute].
+ - Link to [`Class`][..].
+ - Link to [`class_attribute`][.].
+ - Link to [`instance_attribute`][..instance_attribute].
+ - Link to [`method`][..method].
+ """
+
+ def __init__(self):
+ """Summary.
+
+ - Link to [`module`][...].
+ - Link to [`module_attribute`][...module_attribute].
+ - Link to [`Class`][..].
+ - Link to [`class_attribute`][..class_attribute].
+ - Link to [`instance_attribute`][..instance_attribute].
+ - Link to [`method`][..method].
+ """
+ self.instance_attribute = 0
+ """Summary.
+
+ - Link to [`module`][...].
+ - Link to [`module_attribute`][...module_attribute].
+ - Link to [`Class`][..].
+ - Link to [`class_attribute`][..class_attribute].
+ - Link to [`instance_attribute`][.].
+ - Link to [`method`][..method].
+ """
+
+ def method(self):
+ """Summary.
+
+ - Link to [`module`][...].
+ - Link to [`module_attribute`][...module_attribute].
+ - Link to [`Class`][..].
+ - Link to [`class_attribute`][..class_attribute].
+ - Link to [`instance_attribute`][..instance_attribute].
+ - Link to [`method`][.].
+ """
+```
+
+///
+
+
+## `scoped_crossrefs`
+
+[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } —
+[:octicons-tag-24: Insiders 1.9.0](../../insiders/changelog.md#1.9.0)
+
+- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
+
+
+Whether to enable scoped cross-references.
+
+With scoped cross-references, you can write identifiers as if you wanted to access them from the current object's scope. The scoping rules do not exactly match Python's: you can reference members and siblings too, without prefixing with `self.` or `cls.`.
+
+The following order is applied when resolving a name in a given scope:
+
+1. member of the current object
+2. parent class
+3. repeat 1-2 within parent's scope
+
+In practice, it means that the name is first looked up in members, then it is compared against the parent name (only if it's a class), then it is looked up in siblings. It continues climbing up the object tree until there's no parent, in which case it raises a name resolution error.
+
+Cross-referencing an imported object will directly link to this object if the objects inventory of the project it comes from was [loaded][import]. You won't be able to cross-reference it within your own documentation with scoped references, if you happen to be rendering this external object too. In that case, you can use an absolute reference or a [relative][relative_crossrefs] one instead.
+
+Another limitation is that you won't be able to reference an external package if its name can be resolved in the current object's scope.
+
+```yaml title="in mkdocs.yml (global configuration)"
+plugins:
+- mkdocstrings:
+ handlers:
+ python:
+ options:
+ scoped_crossrefs: false
+```
+
+```md title="or in docs/some_page.md (local configuration)"
+::: path.to.module
+ options:
+ scoped_crossrefs: true
+```
+
+/// admonition | Examples
+ type: preview
+
+```python title="pkg/module.py"
+"""Summary.
+
+- Link to [`module_attribute`][module_attribute].
+- Link to [`Class`][Class].
+- Link to [`class_attribute`][Class.class_attribute].
+- Link to [`instance_attribute`][Class.instance_attribute].
+- Link to [`method`][Class.method].
+"""
+
+module_attribute = 0
+"""Summary.
+
+- Link to [`Class`][Class].
+- Link to [`class_attribute`][Class.class_attribute].
+- Link to [`instance_attribute`][Class.instance_attribute].
+- Link to [`method`][Class.method].
+"""
+
+class Class:
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`class_attribute`][class_attribute].
+ - Link to [`instance_attribute`][instance_attribute].
+ - Link to [`method`][method].
+ """
+
+ class_attribute = 0
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`Class`][Class].
+ - Link to [`instance_attribute`][instance_attribute].
+ - Link to [`method`][method].
+ """
+
+ def __init__(self):
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`Class`][Class].
+ - Link to [`class_attribute`][class_attribute].
+ - Link to [`instance_attribute`][instance_attribute].
+ - Link to [`method`][method].
+ """
+ self.instance_attribute = 0
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`Class`][Class].
+ - Link to [`class_attribute`][class_attribute].
+ - Link to [`method`][method].
+ """
+
+ def method(self):
+ """Summary.
+
+ - Link to [`module_attribute`][module_attribute].
+ - Link to [`Class`][Class].
+ - Link to [`class_attribute`][class_attribute].
+ - Link to [`instance_attribute`][instance_attribute].
+ """
+```
+
+///
+
## `show_if_no_docstring`
- **:octicons-package-24: Type [`bool`][] :material-equal: `False`{ title="default value" }**
diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py
index eb1d73c7..ef93ee3b 100644
--- a/src/mkdocstrings_handlers/python/handler.py
+++ b/src/mkdocstrings_handlers/python/handler.py
@@ -85,6 +85,8 @@ class PythonHandler(BaseHandler):
"separate_signature": False,
"line_length": 60,
"merge_init_into_class": False,
+ "relative_crossrefs": False,
+ "scoped_crossrefs": False,
"show_docstring_attributes": True,
"show_docstring_functions": True,
"show_docstring_classes": True,
@@ -168,6 +170,8 @@ class PythonHandler(BaseHandler):
docstring_options (dict): The options for the docstring parser. See [docstring parsers](https://mkdocstrings.github.io/griffe/reference/docstrings/) and their options in Griffe docs.
docstring_section_style (str): The style used to render docstring sections. Options: `table`, `list`, `spacy`. Default: `"table"`.
merge_init_into_class (bool): Whether to merge the `__init__` method into the class' signature and docstring. Default: `False`.
+ relative_crossrefs (bool): Whether to enable the relative crossref syntax. Default: `False`.
+ scoped_crossrefs (bool): Whether to enable the scoped crossref ability. Default: `False`.
show_if_no_docstring (bool): Show the object heading even if it has no docstring or children with docstrings. Default: `False`.
show_docstring_attributes (bool): Whether to display the "Attributes" section in the object's docstring. Default: `True`.
show_docstring_functions (bool): Whether to display the "Functions" or "Methods" sections in the object's docstring. Default: `True`.
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
index 27a91d13..fd13661b 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja
@@ -133,8 +133,10 @@ Context:
{% endwith %}
{% if config.merge_init_into_class %}
{% if "__init__" in class.all_members and class.all_members["__init__"].has_docstring %}
- {% with docstring_sections = class.all_members["__init__"].docstring.parsed %}
- {% include "docstring"|get_template with context %}
+ {% with function = class.all_members["__init__"] %}
+ {% with obj = function, docstring_sections = function.docstring.parsed %}
+ {% include "docstring"|get_template with context %}
+ {% endwith %}
{% endwith %}
{% endif %}
{% endif %}