@@ -258,7 +258,7 @@ def relative_url(url_a: str, url_b: str) -> str:
258258
259259# YORE: Bump 2: Remove block.
260260def _legacy_fix_ref (
261- url_mapper : Callable [[str ], str ],
261+ url_mapper : Callable [[str ], tuple [ str , str | None ] ],
262262 unmapped : list [tuple [str , AutorefsHookInterface .Context | None ]],
263263) -> Callable :
264264 """Return a `repl` function for [`re.sub`](https://docs.python.org/3/library/re.html#re.sub).
@@ -287,7 +287,7 @@ def inner(match: Match) -> str:
287287 classes = (match ["class" ] or "" ).strip ('"' ).split ()
288288
289289 try :
290- url = url_mapper (unescape (identifier ))
290+ url , _ = url_mapper (unescape (identifier ))
291291 except KeyError :
292292 if kind == "autorefs-optional" :
293293 return title
@@ -364,7 +364,10 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None
364364_html_attrs_parser = _HTMLAttrsParser ()
365365
366366
367- def _find_url (identifiers : Iterable [str ], url_mapper : Callable [[str ], str ]) -> str :
367+ def _find_url (
368+ identifiers : Iterable [str ],
369+ url_mapper : Callable [[str ], tuple [str , str | None ]],
370+ ) -> tuple [str , str | None ]:
368371 for identifier in identifiers :
369372 try :
370373 return url_mapper (identifier )
@@ -374,7 +377,7 @@ def _find_url(identifiers: Iterable[str], url_mapper: Callable[[str], str]) -> s
374377
375378
376379def fix_ref (
377- url_mapper : Callable [[str ], str ],
380+ url_mapper : Callable [[str ], tuple [ str , str | None ] ],
378381 unmapped : list [tuple [str , AutorefsHookInterface .Context | None ]],
379382) -> Callable :
380383 """Return a `repl` function for [`re.sub`](https://docs.python.org/3/library/re.html#re.sub).
@@ -406,7 +409,7 @@ def inner(match: Match) -> str:
406409 identifiers = (identifier , slug ) if slug else (identifier ,)
407410
408411 try :
409- url = _find_url (identifiers , url_mapper )
412+ url , original_title = _find_url (identifiers , url_mapper )
410413 except KeyError :
411414 if optional :
412415 log .debug ("Unresolved optional cross-reference: %s" , identifier )
@@ -436,7 +439,7 @@ def inner(match: Match) -> str:
436439
437440def fix_refs (
438441 html : str ,
439- url_mapper : Callable [[str ], str ],
442+ url_mapper : Callable [[str ], tuple [ str , str | None ] ],
440443 # YORE: Bump 2: Remove line.
441444 _legacy_refs : bool = True , # noqa: FBT001, FBT002
442445) -> tuple [str , list [tuple [str , AutorefsHookInterface .Context | None ]]]:
@@ -481,7 +484,7 @@ def run(self, root: Element) -> None: # noqa: D102
481484 self ._scan_anchors (root , pending_anchors )
482485 pending_anchors .flush ()
483486
484- def _scan_anchors (self , parent : Element , pending_anchors : _PendingAnchors ) -> None :
487+ def _scan_anchors (self , parent : Element , pending_anchors : _PendingAnchors , last_heading : str | None = None ) -> None :
485488 for el in parent :
486489 if el .tag == "a" :
487490 # We found an anchor. Record its id if it has one.
@@ -490,23 +493,24 @@ def _scan_anchors(self, parent: Element, pending_anchors: _PendingAnchors) -> No
490493 # If the element has text or a link, it's not an alias.
491494 # Non-whitespace text after the element interrupts the chain, aliases can't apply.
492495 if el .text or el .get ("href" ) or (el .tail and el .tail .strip ()):
493- pending_anchors .flush ()
496+ pending_anchors .flush (title = last_heading )
494497
495498 elif el .tag == "p" :
496499 # A `p` tag is a no-op for our purposes, just recurse into it in the context
497500 # of the current collection of anchors.
498- self ._scan_anchors (el , pending_anchors )
501+ self ._scan_anchors (el , pending_anchors , last_heading )
499502 # Non-whitespace text after the element interrupts the chain, aliases can't apply.
500503 if el .tail and el .tail .strip ():
501504 pending_anchors .flush ()
502505
503506 elif el .tag in self ._htags :
504507 # If the element is a heading, that turns the pending anchors into aliases.
505- pending_anchors .flush (el .get ("id" ))
508+ last_heading = el .text
509+ pending_anchors .flush (el .get ("id" ), title = last_heading )
506510
507511 else :
508512 # But if it's some other interruption, flush anchors anyway as non-aliases.
509- pending_anchors .flush ()
513+ pending_anchors .flush (title = last_heading )
510514 # Recurse into sub-elements, in a *separate* context.
511515 self .run (el )
512516
@@ -522,9 +526,9 @@ def __init__(self, plugin: AutorefsPlugin, current_page: str):
522526 def append (self , anchor : str ) -> None :
523527 self .anchors .append (anchor )
524528
525- def flush (self , alias_to : str | None = None ) -> None :
529+ def flush (self , alias_to : str | None = None , title : str | None = None ) -> None :
526530 for anchor in self .anchors :
527- self .plugin .register_anchor (self .current_page , anchor , alias_to , primary = True )
531+ self .plugin .register_anchor (self .current_page , anchor , alias_to , title = title , primary = True )
528532 self .anchors .clear ()
529533
530534
0 commit comments