From 711335b6ee8285d42963bc764fa6b549dd56e07d Mon Sep 17 00:00:00 2001 From: Jared Dillard Date: Tue, 30 Sep 2025 13:28:39 -0700 Subject: [PATCH 1/4] Prepend doc name to references --- sphinx/builders/singlehtml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/builders/singlehtml.py b/sphinx/builders/singlehtml.py index 1888f6679d1..9528763ec0a 100644 --- a/sphinx/builders/singlehtml.py +++ b/sphinx/builders/singlehtml.py @@ -42,7 +42,7 @@ def get_outdated_docs(self) -> str | list[str]: # type: ignore[override] def get_target_uri(self, docname: str, typ: str | None = None) -> str: if docname in self.env.all_docs: # all references are on the same page... - return '#document-' + docname + return self.config.root_doc + self.out_suffix + '#document-' + docname else: # chances are this is a html_additional_page return docname + self.out_suffix From bf7fbb1351b5648d0eac6f2db803edde621c9145 Mon Sep 17 00:00:00 2001 From: Jared Dillard Date: Tue, 30 Sep 2025 13:31:13 -0700 Subject: [PATCH 2/4] Don't add files that aren't created in singlehtml builder --- sphinx/builders/singlehtml.py | 4 ++++ sphinx/util/inventory.py | 3 +++ 2 files changed, 7 insertions(+) diff --git a/sphinx/builders/singlehtml.py b/sphinx/builders/singlehtml.py index 9528763ec0a..bc85efddc64 100644 --- a/sphinx/builders/singlehtml.py +++ b/sphinx/builders/singlehtml.py @@ -43,6 +43,10 @@ def get_target_uri(self, docname: str, typ: str | None = None) -> str: if docname in self.env.all_docs: # all references are on the same page... return self.config.root_doc + self.out_suffix + '#document-' + docname + elif docname in ('genindex', 'search', 'modindex', 'py-modindex'): + # These pages are not generated in singlehtml builds + # Return empty string to signal they should be skipped + return '' else: # chances are this is a html_additional_page return docname + self.out_suffix diff --git a/sphinx/util/inventory.py b/sphinx/util/inventory.py index 6e4c648bd3f..ad8e538fc09 100644 --- a/sphinx/util/inventory.py +++ b/sphinx/util/inventory.py @@ -198,6 +198,9 @@ def escape(string: str) -> str: # this can shorten the inventory by as much as 25% anchor = anchor.removesuffix(fullname) + '$' uri = builder.get_target_uri(docname) + if not uri: + # Skip entries with empty URIs (e.g., pages not generated by builder) + continue if anchor: uri += '#' + anchor if dispname == fullname: From 650a9ff2770e862075cb22a6069e1b6de7b33698 Mon Sep 17 00:00:00 2001 From: Jared Dillard Date: Tue, 30 Sep 2025 14:01:35 -0700 Subject: [PATCH 3/4] Try better approach --- sphinx/builders/singlehtml.py | 6 +----- sphinx/util/inventory.py | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/sphinx/builders/singlehtml.py b/sphinx/builders/singlehtml.py index bc85efddc64..1888f6679d1 100644 --- a/sphinx/builders/singlehtml.py +++ b/sphinx/builders/singlehtml.py @@ -42,11 +42,7 @@ def get_outdated_docs(self) -> str | list[str]: # type: ignore[override] def get_target_uri(self, docname: str, typ: str | None = None) -> str: if docname in self.env.all_docs: # all references are on the same page... - return self.config.root_doc + self.out_suffix + '#document-' + docname - elif docname in ('genindex', 'search', 'modindex', 'py-modindex'): - # These pages are not generated in singlehtml builds - # Return empty string to signal they should be skipped - return '' + return '#document-' + docname else: # chances are this is a html_additional_page return docname + self.out_suffix diff --git a/sphinx/util/inventory.py b/sphinx/util/inventory.py index ad8e538fc09..5c48c9fa146 100644 --- a/sphinx/util/inventory.py +++ b/sphinx/util/inventory.py @@ -191,16 +191,25 @@ def escape(string: str) -> str: # body compressor = zlib.compressobj(9) + # Special pages not generated by singlehtml builder + singlehtml_excluded_pages = {'genindex', 'search', 'modindex', 'py-modindex'} for domain in env.domains.sorted(): sorted_objects = sorted(domain.get_objects()) for fullname, dispname, type, docname, anchor, prio in sorted_objects: + # Skip pages that singlehtml builder doesn't generate + if builder.name == 'singlehtml' and docname in singlehtml_excluded_pages: + continue + if anchor.endswith(fullname): # this can shorten the inventory by as much as 25% anchor = anchor.removesuffix(fullname) + '$' uri = builder.get_target_uri(docname) - if not uri: - # Skip entries with empty URIs (e.g., pages not generated by builder) - continue + + # For singlehtml builder, prepend the output filename to anchor-only URIs + # so intersphinx knows which file to reference + if builder.name == 'singlehtml' and uri.startswith('#'): + uri = builder.config.root_doc + builder.out_suffix + uri + if anchor: uri += '#' + anchor if dispname == fullname: From 04799dc27988605b82abf93170fbcbe3ac7e5205 Mon Sep 17 00:00:00 2001 From: Jared Dillard Date: Tue, 30 Sep 2025 14:16:24 -0700 Subject: [PATCH 4/4] fix document-id issue --- sphinx/util/inventory.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sphinx/util/inventory.py b/sphinx/util/inventory.py index 5c48c9fa146..99fd8780903 100644 --- a/sphinx/util/inventory.py +++ b/sphinx/util/inventory.py @@ -208,7 +208,13 @@ def escape(string: str) -> str: # For singlehtml builder, prepend the output filename to anchor-only URIs # so intersphinx knows which file to reference if builder.name == 'singlehtml' and uri.startswith('#'): - uri = builder.config.root_doc + builder.out_suffix + uri + if anchor: + # When there's a specific anchor, use just the filename + # (not #document-xxx) to avoid double anchors + uri = builder.config.root_doc + builder.out_suffix + else: + # No specific anchor, keep the #document-xxx part + uri = builder.config.root_doc + builder.out_suffix + uri if anchor: uri += '#' + anchor