From c6303542018ca835f6941c070accb582f851f6b1 Mon Sep 17 00:00:00 2001 From: Markus B Date: Fri, 5 Jul 2024 18:09:25 +0200 Subject: [PATCH] feat: Warn when multiple URLs are found for the same identifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue-35: https://github.com/mkdocstrings/autorefs/issues/35 PR-50: https://github.com/mkdocstrings/autorefs/pull/50 Co-authored-by: Timothée Mazzucotelli --- src/mkdocs_autorefs/plugin.py | 20 +++++++++++++++---- tests/test_references.py | 36 ++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/mkdocs_autorefs/plugin.py b/src/mkdocs_autorefs/plugin.py index 52e60fa..a52f878 100644 --- a/src/mkdocs_autorefs/plugin.py +++ b/src/mkdocs_autorefs/plugin.py @@ -57,7 +57,7 @@ class AutorefsPlugin(BasePlugin): def __init__(self) -> None: """Initialize the object.""" super().__init__() - self._url_map: dict[str, str] = {} + self._url_map: dict[str, list[str]] = {} self._abs_url_map: dict[str, str] = {} self.get_fallback_anchor: Callable[[str], tuple[str, ...]] | None = None @@ -68,7 +68,12 @@ def register_anchor(self, page: str, identifier: str, anchor: str | None = None) page: The relative URL of the current page. Examples: `'foo/bar/'`, `'foo/index.html'` identifier: The HTML anchor (without '#') as a string. """ - self._url_map[identifier] = f"{page}#{anchor or identifier}" + page_anchor = f"{page}#{anchor or identifier}" + if identifier in self._url_map: + if page_anchor not in self._url_map[identifier]: + self._url_map[identifier].append(page_anchor) + else: + self._url_map[identifier] = [page_anchor] def register_url(self, identifier: str, url: str) -> None: """Register that the identifier should be turned into a link to this URL. @@ -85,7 +90,7 @@ def _get_item_url( fallback: Callable[[str], Sequence[str]] | None = None, ) -> str: try: - return self._url_map[identifier] + urls = self._url_map[identifier] except KeyError: if identifier in self._abs_url_map: return self._abs_url_map[identifier] @@ -94,9 +99,16 @@ def _get_item_url( for new_identifier in new_identifiers: with contextlib.suppress(KeyError): url = self._get_item_url(new_identifier) - self._url_map[identifier] = url + self._url_map[identifier] = [url] return url raise + else: + if len(urls) > 1: + log.warning( + f"Multiple URLs found for '{identifier}': {urls}. " + "Make sure to use unique headings, identifiers, or Markdown anchors (see our docs).", + ) + return urls[0] def get_item_url( self, diff --git a/tests/test_references.py b/tests/test_references.py index 748eacf..82da870 100644 --- a/tests/test_references.py +++ b/tests/test_references.py @@ -325,23 +325,29 @@ def test_register_markdown_anchors() -> None: [](){#alias9} ## Heading more2 {#heading-custom2} + [](){#aliasSame} + ## Same heading 1 + [](){#aliasSame} + ## Same heading 2 + [](){#alias10} """, ), ) assert plugin._url_map == { - "foo": "page#heading-foo", - "bar": "page#bar", - "alias1": "page#heading-bar", - "alias2": "page#heading-bar", - "alias3": "page#alias3", - "alias4": "page#heading-baz", - "alias5": "page#alias5", - "alias6": "page#alias6", - "alias7": "page#alias7", - "alias8": "page#alias8", - "alias9": "page#heading-custom2", - "alias10": "page#alias10", + "foo": ["page#heading-foo"], + "bar": ["page#bar"], + "alias1": ["page#heading-bar"], + "alias2": ["page#heading-bar"], + "alias3": ["page#alias3"], + "alias4": ["page#heading-baz"], + "alias5": ["page#alias5"], + "alias6": ["page#alias6"], + "alias7": ["page#alias7"], + "alias8": ["page#alias8"], + "alias9": ["page#heading-custom2"], + "alias10": ["page#alias10"], + "aliasSame": ["page#same-heading-1", "page#same-heading-2"], } @@ -366,9 +372,9 @@ def test_register_markdown_anchors_with_admonition() -> None: ), ) assert plugin._url_map == { - "alias1": "page#alias1", - "alias2": "page#heading-bar", - "alias3": "page#alias3", + "alias1": ["page#alias1"], + "alias2": ["page#heading-bar"], + "alias3": ["page#alias3"], }