10
10
from functools import lru_cache
11
11
from html import escape , unescape
12
12
from html .parser import HTMLParser
13
+ from io import StringIO
13
14
from typing import TYPE_CHECKING , Any , Callable , ClassVar , Literal
14
15
from urllib .parse import urlsplit
15
16
from xml .etree .ElementTree import Element
@@ -376,22 +377,48 @@ def _find_url(
376
377
raise KeyError (f"None of the identifiers { identifiers } were found" )
377
378
378
379
379
- def _tooltip (identifier : str , title : str | None ) -> str :
380
+ def _tooltip (identifier : str , title : str | None , * , strip_tags : bool = False ) -> str :
380
381
if title :
381
382
# Don't append identifier if it's already in the title.
382
383
if identifier in title :
383
384
return title
384
385
# Append identifier (useful for API objects).
386
+ if strip_tags :
387
+ return f"{ title } ({ identifier } )"
385
388
return f"{ title } (<code>{ identifier } </code>)"
386
389
# No title, just return the identifier.
390
+ if strip_tags :
391
+ return identifier
387
392
return f"<code>{ identifier } </code>"
388
393
389
394
395
+ class _TagStripper (HTMLParser ):
396
+ def __init__ (self ) -> None :
397
+ super ().__init__ ()
398
+ self .reset ()
399
+ self .strict = False
400
+ self .convert_charrefs = True
401
+ self .text = StringIO ()
402
+
403
+ def handle_data (self , data : str ) -> None :
404
+ self .text .write (data )
405
+
406
+ def get_data (self ) -> str :
407
+ return self .text .getvalue ()
408
+
409
+
410
+ def _strip_tags (html : str ) -> str :
411
+ stripper = _TagStripper ()
412
+ stripper .feed (html )
413
+ return stripper .get_data ()
414
+
415
+
390
416
def fix_ref (
391
417
url_mapper : Callable [[str ], tuple [str , str | None ]],
392
418
unmapped : list [tuple [str , AutorefsHookInterface .Context | None ]],
393
419
* ,
394
420
link_titles : bool | Literal ["external" ] = True ,
421
+ strip_title_tags : bool = False ,
395
422
) -> Callable :
396
423
"""Return a `repl` function for [`re.sub`](https://docs.python.org/3/library/re.html#re.sub).
397
424
@@ -406,6 +433,7 @@ def fix_ref(
406
433
such as [mkdocs_autorefs.plugin.AutorefsPlugin.get_item_url][].
407
434
unmapped: A list to store unmapped identifiers.
408
435
link_titles: How to set HTML titles on links. Always (`True`), never (`False`), or external-only (`"external"`).
436
+ strip_title_tags: Whether to strip HTML tags from link titles.
409
437
410
438
Returns:
411
439
The actual function accepting a [`Match` object](https://docs.python.org/3/library/re.html#match-objects)
@@ -449,14 +477,14 @@ def inner(match: Match) -> str:
449
477
if optional :
450
478
# The `optional` attribute is generally only added by mkdocstrings handlers,
451
479
# for API objects, meaning we can and should append the full identifier.
452
- tooltip = _tooltip (identifier , original_title )
480
+ tooltip = _tooltip (identifier , original_title , strip_tags = strip_title_tags )
453
481
else :
454
482
# Autorefs without `optional` are generally user-written ones,
455
483
# so we should only use the original title.
456
484
tooltip = original_title or ""
457
485
458
486
if tooltip and tooltip not in f"<code>{ title } </code>" :
459
- title_attr = f' title="{ escape (tooltip )} "'
487
+ title_attr = f' title="{ _strip_tags ( tooltip ) if strip_title_tags else escape (tooltip )} "'
460
488
461
489
return f'<a class="{ class_attr } "{ title_attr } href="{ escape (url )} "{ remaining } >{ title } </a>'
462
490
@@ -468,6 +496,7 @@ def fix_refs(
468
496
url_mapper : Callable [[str ], tuple [str , str | None ]],
469
497
* ,
470
498
link_titles : bool | Literal ["external" ] = True ,
499
+ strip_title_tags : bool = False ,
471
500
# YORE: Bump 2: Remove line.
472
501
_legacy_refs : bool = True ,
473
502
) -> tuple [str , list [tuple [str , AutorefsHookInterface .Context | None ]]]:
@@ -478,13 +507,14 @@ def fix_refs(
478
507
url_mapper: A callable that gets an object's site URL by its identifier,
479
508
such as [mkdocs_autorefs.plugin.AutorefsPlugin.get_item_url][].
480
509
link_titles: How to set HTML titles on links. Always (`True`), never (`False`), or external-only (`"external"`).
510
+ strip_title_tags: Whether to strip HTML tags from link titles.
481
511
482
512
Returns:
483
513
The fixed HTML, and a list of unmapped identifiers (string and optional context).
484
514
"""
485
515
unmapped : list [tuple [str , AutorefsHookInterface .Context | None ]] = []
486
516
html = AUTOREF_RE .sub (
487
- fix_ref (url_mapper , unmapped , link_titles = link_titles ),
517
+ fix_ref (url_mapper , unmapped , link_titles = link_titles , strip_title_tags = strip_title_tags ),
488
518
html ,
489
519
)
490
520
0 commit comments