@@ -258,7 +258,7 @@ def relative_url(url_a: str, url_b: str) -> str:
258
258
259
259
# YORE: Bump 2: Remove block.
260
260
def _legacy_fix_ref (
261
- url_mapper : Callable [[str ], str ],
261
+ url_mapper : Callable [[str ], tuple [ str , str | None ] ],
262
262
unmapped : list [tuple [str , AutorefsHookInterface .Context | None ]],
263
263
) -> Callable :
264
264
"""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:
287
287
classes = (match ["class" ] or "" ).strip ('"' ).split ()
288
288
289
289
try :
290
- url = url_mapper (unescape (identifier ))
290
+ url , _ = url_mapper (unescape (identifier ))
291
291
except KeyError :
292
292
if kind == "autorefs-optional" :
293
293
return title
@@ -364,7 +364,10 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None
364
364
_html_attrs_parser = _HTMLAttrsParser ()
365
365
366
366
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 ]:
368
371
for identifier in identifiers :
369
372
try :
370
373
return url_mapper (identifier )
@@ -374,7 +377,7 @@ def _find_url(identifiers: Iterable[str], url_mapper: Callable[[str], str]) -> s
374
377
375
378
376
379
def fix_ref (
377
- url_mapper : Callable [[str ], str ],
380
+ url_mapper : Callable [[str ], tuple [ str , str | None ] ],
378
381
unmapped : list [tuple [str , AutorefsHookInterface .Context | None ]],
379
382
) -> Callable :
380
383
"""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:
406
409
identifiers = (identifier , slug ) if slug else (identifier ,)
407
410
408
411
try :
409
- url = _find_url (identifiers , url_mapper )
412
+ url , original_title = _find_url (identifiers , url_mapper )
410
413
except KeyError :
411
414
if optional :
412
415
log .debug ("Unresolved optional cross-reference: %s" , identifier )
@@ -436,7 +439,7 @@ def inner(match: Match) -> str:
436
439
437
440
def fix_refs (
438
441
html : str ,
439
- url_mapper : Callable [[str ], str ],
442
+ url_mapper : Callable [[str ], tuple [ str , str | None ] ],
440
443
# YORE: Bump 2: Remove line.
441
444
_legacy_refs : bool = True , # noqa: FBT001, FBT002
442
445
) -> tuple [str , list [tuple [str , AutorefsHookInterface .Context | None ]]]:
@@ -481,7 +484,7 @@ def run(self, root: Element) -> None: # noqa: D102
481
484
self ._scan_anchors (root , pending_anchors )
482
485
pending_anchors .flush ()
483
486
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 :
485
488
for el in parent :
486
489
if el .tag == "a" :
487
490
# 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
490
493
# If the element has text or a link, it's not an alias.
491
494
# Non-whitespace text after the element interrupts the chain, aliases can't apply.
492
495
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 )
494
497
495
498
elif el .tag == "p" :
496
499
# A `p` tag is a no-op for our purposes, just recurse into it in the context
497
500
# of the current collection of anchors.
498
- self ._scan_anchors (el , pending_anchors )
501
+ self ._scan_anchors (el , pending_anchors , last_heading )
499
502
# Non-whitespace text after the element interrupts the chain, aliases can't apply.
500
503
if el .tail and el .tail .strip ():
501
504
pending_anchors .flush ()
502
505
503
506
elif el .tag in self ._htags :
504
507
# 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 )
506
510
507
511
else :
508
512
# But if it's some other interruption, flush anchors anyway as non-aliases.
509
- pending_anchors .flush ()
513
+ pending_anchors .flush (title = last_heading )
510
514
# Recurse into sub-elements, in a *separate* context.
511
515
self .run (el )
512
516
@@ -522,9 +526,9 @@ def __init__(self, plugin: AutorefsPlugin, current_page: str):
522
526
def append (self , anchor : str ) -> None :
523
527
self .anchors .append (anchor )
524
528
525
- def flush (self , alias_to : str | None = None ) -> None :
529
+ def flush (self , alias_to : str | None = None , title : str | None = None ) -> None :
526
530
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 )
528
532
self .anchors .clear ()
529
533
530
534
0 commit comments