fix(html): drop the blanket link target, and mark only external links - #758
Merged
Conversation
andiwand
force-pushed
the
feat/spreadsheet-cut-reporting
branch
from
August 29, 2026 08:29
a9e5ca9 to
6daf61b
Compare
andiwand
force-pushed
the
feat/link-targets
branch
from
August 29, 2026 08:29
e20b62f to
ee4c724
Compare
andiwand
force-pushed
the
feat/spreadsheet-cut-reporting
branch
2 times, most recently
from
August 29, 2026 08:41
8424d2d to
183ab1f
Compare
andiwand
force-pushed
the
feat/link-targets
branch
from
August 29, 2026 08:41
ee4c724 to
eedff7a
Compare
andiwand
force-pushed
the
feat/spreadsheet-cut-reporting
branch
from
August 29, 2026 08:49
183ab1f to
f552d1e
Compare
andiwand
force-pushed
the
feat/link-targets
branch
from
August 29, 2026 08:53
eedff7a to
7fd2425
Compare
Every view was written with `<base target="_blank">`, so every link was a new tab. A browser has one; an embedded web view does not, and unless the host implements window opening the tap does nothing at all. It showed worst on the archive listing, where the links are the whole point: a zip rendered as a table of its entries and none of them could be opened. The base threw away a distinction the renderer already has. `pdf_file.cpp` was paying to undo it, writing `target="_self"` on every `#pN` anchor so an internal link would scroll instead of opening a copy of the page. `uri_kind` - the scan `is_safe_uri` already did - now says relative, external or refused, and the target follows: a link that leaves the page carries `target="_blank" rel="noopener noreferrer"`, which is what a browser makes a tab of and what an embedded web view raises its window delegate for, and a link back into what serves the page carries nothing and navigates in place. `<base target>` goes, and with it the pdf's `_self` workaround and `HtmlWriter::write_header_target`. Reference output moves in 1525 files, in the base tag and link targets alone - nothing else differs. Fixes #730 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Re7MMYiM7fL58uELzKGy77
andiwand
force-pushed
the
feat/link-targets
branch
from
August 29, 2026 09:04
7fd2425 to
9775f0d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Fixes #730. Rebased onto
mainnow that #756 and #757 are merged.Every view was written with
<base target="_blank">, so every link was a new tab. A browser has one; an embedded web view does not, and unless the host implements window opening the tap does nothing at all. Worst on the archive listing, where the links are the whole point: a zip rendered as a table of its entries and none of them could be opened.Why not a config
The blanket base threw away a distinction the renderer already has and the host doesn't — whether a link points back into the same service or out to the web.
pdf_file.cppwas already paying to undo it:So the fix encodes the distinction instead of asking the embedder to re-answer it.
is_safe_uri's scan becomesuri_kind→relative/external/refused, and the target follows from it:content.xml,#p2,other.html)https:,mailto:, …)target="_blank" rel="noopener noreferrer"createWebViewWith/onCreateWindow— the host's hand-off-to-system-browser hookjavascript:, …)href(#756)<base target>goes, and with it the PDF's_selfworkaround andHtmlWriter::write_header_target, which nothing else used. OpenDocument.ios can drop its currentWKUIDelegateworkaround and just open Safari there — internal links no longer reach the delegate at all.Test
a_link_that_is_navigable_keeps_its_hrefextended: external links carry the target, and#bookmark/other.html/a/b.htmlcarry none.no_view_declares_a_document_wide_link_targetacross the csv, xml, text and markdown writers.PdfFile.link_annotations_render_as_anchorsand the two page-view link tests updated:#pNandpage1.htmlname no target, the/URIaction names_blank.Reference output
1525 files — every view carried the base tag. I verified mechanically that after stripping
<base target="_blank"/>,target="_blank" rel="noopener noreferrer"andtarget="_self"from both sides, zero files differ; the pins are advanced to the regenerated commits.