1010and fixes them using the previously stored identifier-URL mapping.
1111"""
1212
13+ import functools
1314import logging
1415from typing import Callable , Dict , Optional
1516
1920from mkdocs .structure .toc import AnchorLink
2021from mkdocs .utils import warning_filter
2122
22- from mkdocs_autorefs .references import AutorefsExtension , fix_refs
23+ from mkdocs_autorefs .references import AutorefsExtension , fix_refs , relative_url
2324
2425log = logging .getLogger (f"mkdocs.plugins.{ __name__ } " )
2526log .addFilter (warning_filter )
@@ -45,22 +46,36 @@ def __init__(self) -> None:
4546 """Initialize the object."""
4647 super ().__init__ ()
4748 self ._url_map : Dict [str , str ] = {}
48- self .get_fallback_anchor : Callable [[str ], Optional [str ]] = lambda identifier : None
49+ self ._abs_url_map : Dict [str , str ] = {}
50+ self .get_fallback_anchor : Optional [Callable [[str ], Optional [str ]]] = None
4951
50- def register_anchor (self , page : str , anchor : str ):
52+ def register_anchor (self , page : str , identifier : str ):
5153 """Register that an anchor corresponding to an identifier was encountered when rendering the page.
5254
5355 Arguments:
5456 page: The relative URL of the current page. Examples: `'foo/bar/'`, `'foo/index.html'`
55- anchor : The HTML anchor (without '#') as a string.
57+ identifier : The HTML anchor (without '#') as a string.
5658 """
57- self ._url_map [anchor ] = f"{ page } #{ anchor } "
59+ self ._url_map [identifier ] = f"{ page } #{ identifier } "
5860
59- def get_item_url (self , anchor : str ) -> str :
61+ def register_url (self , identifier : str , url : str ):
62+ """Register that the identifier should be turned into a link to this URL.
63+
64+ Arguments:
65+ identifier: The new identifier.
66+ url: The absolute URL (including anchor, if needed) where this item can be found.
67+ """
68+ self ._abs_url_map [identifier ] = url
69+
70+ def get_item_url (
71+ self , identifier : str , from_url : Optional [str ] = None , fallback : Optional [Callable [[str ], Optional [str ]]] = None
72+ ) -> str :
6073 """Return a site-relative URL with anchor to the identifier, if it's present anywhere.
6174
6275 Arguments:
63- anchor: The anchor (without '#').
76+ identifier: The anchor (without '#').
77+ from_url: The URL of the base page, from which we link towards the targeted pages.
78+ fallback: An optional function to suggest an alternative anchor to try on failure.
6479
6580 Returns:
6681 A site-relative URL.
@@ -69,13 +84,22 @@ def get_item_url(self, anchor: str) -> str:
6984 KeyError: If there isn't an item by this identifier anywhere on the site.
7085 """
7186 try :
72- return self ._url_map [anchor ]
87+ url = self ._url_map [identifier ]
7388 except KeyError :
74- new_anchor = self .get_fallback_anchor (anchor )
75- if new_anchor and new_anchor in self ._url_map :
76- return self ._url_map [new_anchor ]
89+ if identifier in self ._abs_url_map :
90+ return self ._abs_url_map [identifier ]
91+
92+ if fallback :
93+ new_identifier = fallback (identifier )
94+ if new_identifier :
95+ return self .get_item_url (new_identifier , from_url )
96+
7797 raise
7898
99+ if from_url is not None :
100+ return relative_url (from_url , url )
101+ return url
102+
79103 def on_config (self , config : Config , ** kwargs ) -> Config : # noqa: W0613,R0201 (unused arguments, cannot be static)
80104 """Instantiate our Markdown extension.
81105
@@ -166,7 +190,8 @@ def on_post_page(self, output: str, page: Page, **kwargs) -> str: # noqa: W0613
166190 """
167191 log .debug (f"{ __name__ } : Fixing references in page { page .file .src_path } " )
168192
169- fixed_output , unmapped = fix_refs (output , page .url , self .get_item_url )
193+ url_mapper = functools .partial (self .get_item_url , from_url = page .url , fallback = self .get_fallback_anchor )
194+ fixed_output , unmapped = fix_refs (output , url_mapper )
170195
171196 if unmapped and log .isEnabledFor (logging .WARNING ):
172197 for ref in unmapped :
0 commit comments