From da365ee2d2732fdf078b12cb8452e8ba69addd9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20G=C4=99bal?= Date: Mon, 3 Aug 2026 21:16:11 +0800 Subject: [PATCH] Fix embedded items URL resolution. Correct behavior for files with local references that are included from remote url. Resolves mondeja/mkdocs-include-markdown-plugin#302 --- src/mkdocs_include_markdown_plugin/process.py | 14 +++++- tests/test_unit/test_process.py | 47 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/mkdocs_include_markdown_plugin/process.py b/src/mkdocs_include_markdown_plugin/process.py index 9bbc4fa..67c2bef 100644 --- a/src/mkdocs_include_markdown_plugin/process.py +++ b/src/mkdocs_include_markdown_plugin/process.py @@ -9,6 +9,7 @@ import stat from collections.abc import Callable, Iterator from typing import TYPE_CHECKING +from urllib.parse import urljoin if TYPE_CHECKING: # pragma: no cover @@ -291,8 +292,19 @@ def rewrite_relative_urls( ``source_path`` will still work when inserted into a file at ``destination_path``. """ + source_is_url = is_url(source_path) + def rewrite_url(url: str) -> str: - if is_url(url) or is_absolute_path(url) or is_anchor(url): + if is_anchor(url): + return url + + if source_is_url: + # `source_path` is a remote URL, so relative and + # root-relative references must resolve against it rather + # than against the local `destination_path`. + return url if is_url(url) else urljoin(source_path, url) + + if is_url(url) or is_absolute_path(url): return url new_path = os.path.relpath( diff --git a/tests/test_unit/test_process.py b/tests/test_unit/test_process.py index 3bf5034..ad07434 100644 --- a/tests/test_unit/test_process.py +++ b/tests/test_unit/test_process.py @@ -371,6 +371,53 @@ 'This is a link to an [internal anchor](#internal-anchor).', id='internal-anchor', ), + # Remote source (content included from a URL): relative and + # root-relative references must resolve against that URL, not + # against the local destination file. + # https://github.com/mondeja/mkdocs-include-markdown-plugin/issues/302 + pytest.param( + "Here's a diagram: ![diagram](assets/diagram.png)", + 'https://raw.githubusercontent.com/user/repo/main/README.md', + 'docs/home.md', + ( + "Here's a diagram: ![diagram](" + 'https://raw.githubusercontent.com/user/repo/main' + '/assets/diagram.png)' + ), + id='image-remote-source', + ), + pytest.param( + '[link](../CHANGELOG.md)', + 'https://raw.githubusercontent.com/user/repo/main/docs/nav.md', + 'docs/home.md', + ( + '[link](' + 'https://raw.githubusercontent.com/user/repo/main' + '/CHANGELOG.md)' + ), + id='relative-link-up-remote-source', + ), + pytest.param( + '[abs](/images/diagram.png)', + 'https://raw.githubusercontent.com/user/repo/main/README.md', + 'docs/home.md', + '[abs](https://raw.githubusercontent.com/images/diagram.png)', + id='root-relative-remote-source', + ), + pytest.param( + '[ext](https://example.com/index.html)', + 'https://raw.githubusercontent.com/user/repo/main/README.md', + 'docs/home.md', + '[ext](https://example.com/index.html)', + id='external-link-remote-source-unchanged', + ), + pytest.param( + 'This is a link to an [internal anchor](#internal-anchor).', + 'https://raw.githubusercontent.com/user/repo/main/README.md', + 'docs/home.md', + 'This is a link to an [internal anchor](#internal-anchor).', + id='internal-anchor-remote-source', + ), ), ) def test_rewrite_relative_urls(