diff --git a/downloaded_files/pipfinding.lock b/downloaded_files/pipfinding.lock new file mode 100644 index 0000000..e69de29 diff --git a/sphinxext/rediraffe.py b/sphinxext/rediraffe.py index 28d423d..732d264 100644 --- a/sphinxext/rediraffe.py +++ b/sphinxext/rediraffe.py @@ -17,6 +17,8 @@ TYPE_CHECKING = False if TYPE_CHECKING: + from os import PathLike + from sphinx.application import Sphinx from sphinx.util.typing import ExtensionMetadata @@ -137,9 +139,58 @@ def remove_suffix(docname: str, suffixes: list[str]) -> str: return docname +def is_external(dest: str) -> bool: + """Return True if the redirect destination is a URL.""" + return dest.startswith(('http://', 'https://')) + + +def build_external_redirect( + app: Sphinx, + rediraffe_template: Template, + redirect_record: dict[str, str], + src_redirect_from: PathLike[str], + src_redirect_to: str, +): + """Redirect to an external link.""" + + src_redirect_from = Path(PureWindowsPath(src_redirect_from)) + + redirect_from_name = remove_suffix(src_redirect_from.name, app.config.source_suffix) + + redirect_from = src_redirect_from.parent / f'{redirect_from_name}.html' + + if type(app.builder) is DirectoryHTMLBuilder and redirect_from_name != 'index': + redirect_from = src_redirect_from.parent / redirect_from_name / 'index.html' + + build_redirect_from = Path(app.outdir) / redirect_from + + build_redirect_from.parent.mkdir(parents=True, exist_ok=True) + + with build_redirect_from.open('w', encoding='utf-8') as f: + f.write( + rediraffe_template.render( + rel_url=src_redirect_to, + from_file=src_redirect_from, + to_file=src_redirect_to, + from_url=redirect_from, + to_url=src_redirect_to, + ) + ) + + logger.info( + '%s %s %s %s', + green('(good)'), + redirect_from, + green('-->'), + src_redirect_to, + ) + + redirect_record[src_redirect_from.as_posix()] = src_redirect_to + + def build_redirects(app: Sphinx, exception: Exception | None) -> None: """ - Build amd write redirects + Build and write redirects """ redirect_json_file = Path(app.outdir) / REDIRECT_JSON_NAME if redirect_json_file.exists(): @@ -218,6 +269,17 @@ def build_redirects(app: Sphinx, exception: Exception | None) -> None: # write redirects for src_redirect_from, src_redirect_to in redirects.items(): + # Offload to helper function if the destination path is external + if is_external(src_redirect_to): + build_external_redirect( + app, + rediraffe_template, + redirect_record, + src_redirect_from, + src_redirect_to, + ) + continue + # Normalize path - src_redirect_.* is relative so drive letters aren't an issue. src_redirect_from = Path(PureWindowsPath(src_redirect_from)) src_redirect_to = Path(PureWindowsPath(src_redirect_to)) diff --git a/tests/roots/ext/test-external/conf.py b/tests/roots/ext/test-external/conf.py new file mode 100644 index 0000000..165a581 --- /dev/null +++ b/tests/roots/ext/test-external/conf.py @@ -0,0 +1,10 @@ +from __future__ import annotations + +extensions = ['sphinxext.rediraffe'] + +master_doc = 'index' +exclude_patterns = ['_build'] + +html_theme = 'basic' + +rediraffe_redirects = 'redirects.txt' diff --git a/tests/roots/ext/test-external/index.rst b/tests/roots/ext/test-external/index.rst new file mode 100644 index 0000000..e5616f3 --- /dev/null +++ b/tests/roots/ext/test-external/index.rst @@ -0,0 +1 @@ +Index File \ No newline at end of file diff --git a/tests/roots/ext/test-external/redirects.txt b/tests/roots/ext/test-external/redirects.txt new file mode 100644 index 0000000..a2264e7 --- /dev/null +++ b/tests/roots/ext/test-external/redirects.txt @@ -0,0 +1,3 @@ +another.rst https://github.com/sphinx-doc/sphinxext-rediraffe +yet-another.rst http://github.com/sphinx-doc/sphinxext-rediraffe +internal-src.rst index.rst \ No newline at end of file diff --git a/tests/test_ext.py b/tests/test_ext.py index 3fd379e..35a98c4 100644 --- a/tests/test_ext.py +++ b/tests/test_ext.py @@ -113,6 +113,18 @@ def test_bad_rediraffe_file(self, app: Sphinx): app.build() assert app.statuscode == 1 + @pytest.mark.sphinx('html', testroot='external') + def test_external(self, app: Sphinx, ensure_redirect): + app.build() + assert app.statuscode == 0 + assert 'https://github.com/sphinx-doc/sphinxext-rediraffe' in ( + Path(app.outdir) / 'another.html' + ).read_text(encoding='utf-8') + assert 'http://github.com/sphinx-doc/sphinxext-rediraffe' in ( + Path(app.outdir) / 'yet-another.html' + ).read_text(encoding='utf-8') + ensure_redirect('internal-src.html', 'index.html') + @pytest.mark.sphinx('html', testroot='no_rediraffe_file') def test_no_rediraffe_file(self, app: Sphinx): app.build()