diff --git a/src/mkdocs_autorefs/plugin.py b/src/mkdocs_autorefs/plugin.py index 24d2a23..5ebc618 100644 --- a/src/mkdocs_autorefs/plugin.py +++ b/src/mkdocs_autorefs/plugin.py @@ -59,7 +59,7 @@ def __init__(self) -> None: super().__init__() self._url_map: dict[str, str] = {} self._abs_url_map: dict[str, str] = {} - self.get_fallback_anchor: Callable[[str], str | None] | None = None + self.get_fallback_anchor: Callable[[str], tuple[str, ...]] | None = None def register_anchor(self, page: str, identifier: str, anchor: str | None = None) -> None: """Register that an anchor corresponding to an identifier was encountered when rendering the page. diff --git a/src/mkdocs_autorefs/references.py b/src/mkdocs_autorefs/references.py index 1d058ed..59999c0 100644 --- a/src/mkdocs_autorefs/references.py +++ b/src/mkdocs_autorefs/references.py @@ -29,9 +29,10 @@ # TODO: remove once support for MkDocs <1.5 is dropped log = logging.getLogger(f"mkdocs.plugins.{__name__}") # type: ignore[assignment] +_ATTR_VALUE = r'"[^"<>]+"|[^"<> ]+' # Possibly with double quotes around AUTO_REF_RE = re.compile( - r"autorefs-identifier|autorefs-optional|autorefs-optional-hover)=" - r'("?)(?P[^"<>]*)\2>(?P.*?)</span>', + rf"<span data-(?P<kind>autorefs-(?:identifier|optional|optional-hover))=(?P<identifier>{_ATTR_VALUE})" + rf"(?: class=(?P<class>{_ATTR_VALUE}))?(?P<attrs> [^<>]+)?>(?P<title>.*?)</span>", flags=re.DOTALL, ) """A regular expression to match mkdocs-autorefs' special reference markers @@ -175,9 +176,11 @@ def fix_ref(url_mapper: Callable[[str], str], unmapped: list[str]) -> Callable: """ def inner(match: Match) -> str: - identifier = match["identifier"] + identifier = match["identifier"].strip('"') title = match["title"] kind = match["kind"] + attrs = match["attrs"] or "" + classes = (match["class"] or "").strip('"').split() try: url = url_mapper(unescape(identifier)) @@ -193,11 +196,11 @@ def inner(match: Match) -> str: parsed = urlsplit(url) external = parsed.scheme or parsed.netloc - classes = ["autorefs", "autorefs-external" if external else "autorefs-internal"] + classes = ["autorefs", "autorefs-external" if external else "autorefs-internal", *classes] class_attr = " ".join(classes) if kind == "autorefs-optional-hover": - return f'<a class="{class_attr}" title="{identifier}" href="{escape(url)}">{title}</a>' - return f'<a class="{class_attr}" href="{escape(url)}">{title}</a>' + return f'<a class="{class_attr}" title="{identifier}" href="{escape(url)}"{attrs}>{title}</a>' + return f'<a class="{class_attr}" href="{escape(url)}"{attrs}>{title}</a>' return inner diff --git a/tests/test_references.py b/tests/test_references.py index 5cc67c1..f687afb 100644 --- a/tests/test_references.py +++ b/tests/test_references.py @@ -331,3 +331,11 @@ def test_register_markdown_anchors_with_admonition() -> None: "alias2": "page#heading-bar", "alias3": "page#alias3", } + + +def test_keep_data_attributes() -> None: + """Keep HTML data attributes from autorefs spans.""" + url_map = {"example": "https://e.com"} + source = '<span data-autorefs-optional="example" class="hi ho" data-foo data-bar="0">e</span>' + output, _ = fix_refs(source, url_map.__getitem__) + assert output == '<a class="autorefs autorefs-external hi ho" href="https://e.com" data-foo data-bar="0">e</a>'