diff --git a/pyproject.toml b/pyproject.toml
index 04f1b273..c25588d5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,7 +30,7 @@ classifiers = [
]
dependencies = [
"mkdocstrings>=0.20",
- "griffe>=0.30,<0.33",
+ "griffe>=0.33",
]
[project.urls]
diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py
index 7a7d0da3..bd25424d 100644
--- a/src/mkdocstrings_handlers/python/handler.py
+++ b/src/mkdocstrings_handlers/python/handler.py
@@ -340,6 +340,7 @@ def update_env(self, md: Markdown, config: dict) -> None: # noqa: D102 (ignore
self.env.trim_blocks = True
self.env.lstrip_blocks = True
self.env.keep_trailing_newline = False
+ self.env.filters["split_path"] = rendering.do_split_path
self.env.filters["crossref"] = rendering.do_crossref
self.env.filters["multi_crossref"] = rendering.do_multi_crossref
self.env.filters["order_members"] = rendering.do_order_members
diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py
index ce6cf9cb..7a875a5c 100644
--- a/src/mkdocstrings_handlers/python/rendering.py
+++ b/src/mkdocstrings_handlers/python/rendering.py
@@ -174,6 +174,28 @@ def repl(match: Match) -> str:
return Markup(text).format(**variables)
+def do_split_path(path: str, full_path: str) -> list[tuple[str, str]]:
+ """Split object paths for building cross-references.
+
+ Parameters:
+ path: The path to split.
+
+ Returns:
+ A list of pairs (title, full path).
+ """
+ if "." not in path:
+ return [(path, full_path)]
+ pairs = []
+ full_path = ""
+ for part in path.split("."):
+ if full_path:
+ full_path += f".{part}"
+ else:
+ full_path = part
+ pairs.append((part, full_path))
+ return pairs
+
+
def _keep_object(name: str, filters: Sequence[tuple[Pattern, bool]]) -> bool:
keep = None
rules = set()
diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
index 9bcfc867..52d3a624 100644
--- a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
+++ b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html
@@ -1,14 +1,46 @@
-{%- set original_expression = expression -%}
-{%- if original_expression is iterable and original_expression is not string -%}
- {%- for expression in original_expression -%}
- {%- include "expression.html" with context -%}
- {%- endfor -%}
-{%- elif original_expression is string -%}
- {{ original_expression }}
-{%- else -%}
- {%- with annotation = original_expression|attr(config.annotations_path) -%}
- {%- filter stash_crossref(length=annotation|length) -%}
- {{ annotation }}
- {%- endfilter -%}
+{%- macro crossref(name, annotation_path) -%}
+ {%- with full = name.canonical_path -%}
+ {%- if annotation_path == "brief" -%}
+ {%- set annotation = name.canonical_name -%}
+ {%- elif annotation_path == "source" -%}
+ {%- set annotation = name.name -%}
+ {%- elif annotation_path == "full" -%}
+ {%- set annotation = full -%}
+ {%- endif -%}
+ {%- for title, path in annotation|split_path(full) -%}
+ {%- filter stash_crossref(length=title|length) -%}
+ {{ title }}
+ {%- endfilter -%}
+ {%- if not loop.last -%}.{%- endif -%}
+ {%- endfor -%}
{%- endwith -%}
-{%- endif -%}
+{%- endmacro -%}
+
+{%- macro render(expression, annotations_path) -%}
+ {%- if expression is string -%}
+ {%- if signature -%}{{ expression|safe }}{%- else -%}{{ expression }}{%- endif -%}
+ {%- elif expression.classname == "ExprName" -%}
+ {{ crossref(expression, annotations_path) }}
+ {%- elif expression.classname == "ExprAttribute" -%}
+ {%- if annotations_path == "brief" -%}
+ {{ render(expression.last, "brief") }}
+ {%- elif annotations_path == "full" -%}
+ {{ render(expression.first, "full") }}
+ {%- for element in expression -%}
+ {%- if not loop.first -%}
+ {{ render(element, "brief") }}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- else -%}
+ {%- for element in expression -%}
+ {{ render(element, annotations_path) }}
+ {%- endfor -%}
+ {%- endif -%}
+ {%- else -%}
+ {%- for element in expression -%}
+ {{ render(element, annotations_path) }}
+ {%- endfor -%}
+ {%- endif -%}
+{%- endmacro -%}
+
+{{ render(expression, config.annotations_path) }}