Skip to content

Commit

Permalink
fixup! feat: Provide hook interface, use it to expand identifiers and…
Browse files Browse the repository at this point in the history
… attach additional context to references
  • Loading branch information
pawamoy committed Sep 1, 2024
1 parent 0bf5e46 commit 2498f0e
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 18 deletions.
5 changes: 3 additions & 2 deletions src/mkdocs_autorefs/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ def on_post_page(self, output: str, page: Page, **kwargs: Any) -> str: # noqa:
fixed_output, unmapped = fix_refs(output, url_mapper, _legacy_refs=self.legacy_refs)

if unmapped and log.isEnabledFor(logging.WARNING):
for ref in unmapped:
log.warning(f"{page.file.src_path}: Could not find cross-reference target '[{ref}]'")
for ref, context in unmapped:
message = f"from {context.filepath}:{context.lineno}: ({context.origin}) " if context else ""
log.warning(f"{page.file.src_path}: {message}Could not find cross-reference target '{ref}'")

return fixed_output
50 changes: 42 additions & 8 deletions src/mkdocs_autorefs/references.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,10 @@ def relative_url(url_a: str, url_b: str) -> str:


# YORE: Bump 2: Remove block.
def _legacy_fix_ref(url_mapper: Callable[[str], str], unmapped: list[str]) -> Callable:
def _legacy_fix_ref(
url_mapper: Callable[[str], str],
unmapped: list[tuple[str, AutorefsHookInterface.Context | None]],
) -> Callable:
"""Return a `repl` function for [`re.sub`](https://docs.python.org/3/library/re.html#re.sub).
In our context, we match Markdown references and replace them with HTML links.
Expand Down Expand Up @@ -263,7 +266,7 @@ def inner(match: Match) -> str:
return title
if kind == "autorefs-optional-hover":
return f'<span title="{identifier}">{title}</span>'
unmapped.append(identifier)
unmapped.append((identifier, None))
if title == identifier:
return f"[{identifier}][]"
return f"[{title}][{identifier}]"
Expand All @@ -286,7 +289,30 @@ def inner(match: Match) -> str:


class _AutorefsAttrs(dict):
_handled_attrs: ClassVar[set[str]] = {"identifier", "optional", "hover", "class"}
_handled_attrs: ClassVar[set[str]] = {
"identifier",
"optional",
"hover",
"class",
"domain",
"role",
"origin",
"filepath",
"lineno",
}

@property
def context(self) -> AutorefsHookInterface.Context | None:
try:
return AutorefsHookInterface.Context(
domain=self["domain"],
role=self["role"],
origin=self["origin"],
filepath=self["filepath"],
lineno=int(self["lineno"]),
)
except KeyError:
return None

@property
def remaining(self) -> str:
Expand All @@ -310,7 +336,10 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None
_html_attrs_parser = _HTMLAttrsParser()


def fix_ref(url_mapper: Callable[[str], str], unmapped: list[str]) -> Callable:
def fix_ref(
url_mapper: Callable[[str], str],
unmapped: list[tuple[str, AutorefsHookInterface.Context | None]],
) -> Callable:
"""Return a `repl` function for [`re.sub`](https://docs.python.org/3/library/re.html#re.sub).
In our context, we match Markdown references and replace them with HTML links.
Expand Down Expand Up @@ -343,7 +372,7 @@ def inner(match: Match) -> str:
if hover:
return f'<span title="{identifier}">{title}</span>'
return title
unmapped.append(identifier)
unmapped.append((identifier, attrs.context))
if title == identifier:
return f"[{identifier}][]"
return f"[{title}][{identifier}]"
Expand All @@ -363,7 +392,12 @@ def inner(match: Match) -> str:


# YORE: Bump 2: Replace `, *, _legacy_refs: bool = True` with `` within line.
def fix_refs(html: str, url_mapper: Callable[[str], str], *, _legacy_refs: bool = True) -> tuple[str, list[str]]:
def fix_refs(
html: str,
url_mapper: Callable[[str], str],
*,
_legacy_refs: bool = True,
) -> tuple[str, list[tuple[str, AutorefsHookInterface.Context | None]]]:
"""Fix all references in the given HTML text.
Arguments:
Expand All @@ -372,9 +406,9 @@ def fix_refs(html: str, url_mapper: Callable[[str], str], *, _legacy_refs: bool
such as [mkdocs_autorefs.plugin.AutorefsPlugin.get_item_url][].
Returns:
The fixed HTML.
The fixed HTML, and a list of unmapped identifiers (string and optional context).
"""
unmapped: list[str] = []
unmapped: list[tuple[str, AutorefsHookInterface.Context | None]] = []
html = AUTOREF_RE.sub(fix_ref(url_mapper, unmapped), html)

# YORE: Bump 2: Remove block.
Expand Down
16 changes: 8 additions & 8 deletions tests/test_references.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pytest

from mkdocs_autorefs.plugin import AutorefsPlugin
from mkdocs_autorefs.references import AutorefsExtension, fix_refs, relative_url
from mkdocs_autorefs.references import AutorefsExtension, AutorefsHookInterface, fix_refs, relative_url


@pytest.mark.parametrize(
Expand Down Expand Up @@ -46,7 +46,7 @@ def run_references_test(
url_map: dict[str, str],
source: str,
output: str,
unmapped: list[str] | None = None,
unmapped: list[tuple[str, AutorefsHookInterface.Context | None]] | None = None,
from_url: str = "page.html",
extensions: Mapping = {},
) -> None:
Expand Down Expand Up @@ -169,7 +169,7 @@ def test_missing_reference() -> None:
url_map={"NotFoo": "foo.html#NotFoo"},
source="[Foo][]",
output="<p>[Foo][]</p>",
unmapped=["Foo"],
unmapped=[("Foo", None)],
)


Expand All @@ -179,7 +179,7 @@ def test_missing_reference_with_markdown_text() -> None:
url_map={"NotFoo": "foo.html#NotFoo"},
source="[`Foo`][Foo]",
output="<p>[<code>Foo</code>][Foo]</p>",
unmapped=["Foo"],
unmapped=[("Foo", None)],
)


Expand All @@ -189,7 +189,7 @@ def test_missing_reference_with_markdown_id() -> None:
url_map={"Foo": "foo.html#Foo", "NotFoo": "foo.html#NotFoo"},
source="[Foo][*NotFoo*]",
output="<p>[Foo][*NotFoo*]</p>",
unmapped=["*NotFoo*"],
unmapped=[("*NotFoo*", None)],
)


Expand All @@ -199,7 +199,7 @@ def test_missing_reference_with_markdown_implicit() -> None:
url_map={"Foo-bar": "foo.html#Foo-bar"},
source="[*Foo-bar*][] and [`Foo`-bar][]",
output="<p>[<em>Foo-bar</em>][*Foo-bar*] and [<code>Foo</code>-bar][]</p>",
unmapped=["*Foo-bar*"],
unmapped=[("*Foo-bar*", None)],
)


Expand All @@ -224,7 +224,7 @@ def test_legacy_custom_required_reference() -> None:
with pytest.warns(DeprecationWarning, match="`span` elements are deprecated"):
output, unmapped = fix_refs(source, url_map.__getitem__)
assert output == '[foo][bar] <a class="autorefs autorefs-internal" href="ok.html#ok">ok</a>'
assert unmapped == ["bar"]
assert unmapped == [("bar", None)]


def test_custom_required_reference() -> None:
Expand All @@ -233,7 +233,7 @@ def test_custom_required_reference() -> None:
source = "<autoref identifier=bar>foo</autoref> <autoref identifier=ok>ok</autoref>"
output, unmapped = fix_refs(source, url_map.__getitem__)
assert output == '[foo][bar] <a class="autorefs autorefs-internal" href="ok.html#ok">ok</a>'
assert unmapped == ["bar"]
assert unmapped == [("bar", None)]


def test_legacy_custom_optional_reference() -> None:
Expand Down

0 comments on commit 2498f0e

Please sign in to comment.