44
55import re
66from html import escape , unescape
7- from typing import TYPE_CHECKING , Any , Callable , Match , Tuple
7+ from typing import TYPE_CHECKING , Any , Callable , Match
88from urllib .parse import urlsplit
99from xml .etree .ElementTree import Element
1010
11+ import markupsafe
1112from markdown .extensions import Extension
1213from markdown .inlinepatterns import REFERENCE_RE , ReferenceInlineProcessor
13- from markdown .util import INLINE_PLACEHOLDER_RE
14+ from markdown .util import HTML_PLACEHOLDER_RE , INLINE_PLACEHOLDER_RE
1415
1516if TYPE_CHECKING :
1617 from markdown import Markdown
2425in the [`on_post_page` hook][mkdocs_autorefs.plugin.AutorefsPlugin.on_post_page].
2526"""
2627
27- EvalIDType = Tuple [Any , Any , Any ]
28-
2928
3029class AutoRefInlineProcessor (ReferenceInlineProcessor ):
3130 """A Markdown extension."""
@@ -36,7 +35,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: # noqa: D107
3635 # Code based on
3736 # https://github.com/Python-Markdown/markdown/blob/8e7528fa5c98bf4652deb13206d6e6241d61630b/markdown/inlinepatterns.py#L780
3837
39- def handleMatch (self , m : Match [str ], data : Any ) -> Element | EvalIDType : # type: ignore[override] # noqa: N802
38+ def handleMatch (self , m : Match [str ], data : str ) -> tuple [ Element | None , int | None , int | None ] : # type: ignore[override] # noqa: N802
4039 """Handle an element that matched.
4140
4241 Arguments:
@@ -51,7 +50,7 @@ def handleMatch(self, m: Match[str], data: Any) -> Element | EvalIDType: # type
5150 return None , None , None
5251
5352 identifier , end , handled = self .evalId (data , index , text )
54- if not handled :
53+ if not handled or identifier is None :
5554 return None , None , None
5655
5756 if re .search (r"[/ \x00-\x1f]" , identifier ):
@@ -61,9 +60,9 @@ def handleMatch(self, m: Match[str], data: Any) -> Element | EvalIDType: # type
6160 # but references with Markdown formatting are not possible anyway.
6261 return None , m .start (0 ), end
6362
64- return self .makeTag (identifier , text ), m .start (0 ), end
63+ return self ._make_tag (identifier , text ), m .start (0 ), end
6564
66- def evalId (self , data : str , index : int , text : str ) -> EvalIDType : # noqa: N802 (parent's casing)
65+ def evalId (self , data : str , index : int , text : str ) -> tuple [ str | None , int , bool ] : # noqa: N802 (parent's casing)
6766 """Evaluate the id portion of `[ref][id]`.
6867
6968 If `[ref][]` use `[ref]`.
@@ -86,13 +85,22 @@ def evalId(self, data: str, index: int, text: str) -> EvalIDType: # noqa: N802
8685 # Allow the entire content to be one placeholder, with the intent of catching things like [`Foo`][].
8786 # It doesn't catch [*Foo*][] though, just due to the priority order.
8887 # https://github.com/Python-Markdown/markdown/blob/1858c1b601ead62ed49646ae0d99298f41b1a271/markdown/inlinepatterns.py#L78
89- if INLINE_PLACEHOLDER_RE .fullmatch (identifier ):
90- identifier = self .unescape (identifier )
88+ if match := INLINE_PLACEHOLDER_RE .fullmatch (identifier ):
89+ stashed_nodes : dict [str , Element | str ] = self .md .treeprocessors ["inline" ].stashed_nodes # type: ignore[attr-defined]
90+ el = stashed_nodes .get (match [1 ])
91+ if isinstance (el , Element ) and el .tag == "code" :
92+ identifier = "" .join (el .itertext ())
93+ # Special case: allow pymdownx.inlinehilite raw <code> snippets but strip them back to unhighlighted.
94+ if match := HTML_PLACEHOLDER_RE .fullmatch (identifier ):
95+ stash_index = int (match .group (1 ))
96+ html = self .md .htmlStash .rawHtmlBlocks [stash_index ]
97+ identifier = markupsafe .Markup (html ).striptags ()
98+ self .md .htmlStash .rawHtmlBlocks [stash_index ] = escape (identifier )
9199
92100 end = m .end (0 )
93101 return identifier , end , True
94102
95- def makeTag (self , identifier : str , text : str ) -> Element : # type: ignore[override] # noqa: N802
103+ def _make_tag (self , identifier : str , text : str ) -> Element :
96104 """Create a tag that can be matched by `AUTO_REF_RE`.
97105
98106 Arguments:
0 commit comments