Skip to content

Let the HTML output follow links like a browser - #87

Merged
dayglojesus merged 1 commit into
mainfrom
fix/html-output-file-links
Sep 22, 2026
Merged

dayglojesus merged 1 commit into
mainfrom
fix/html-output-file-links

Conversation

@dayglojesus

Copy link
Copy Markdown
Collaborator

Fixes #86.

The HTML output view allowed every tm-file: and file: navigation to load in the web view. A Markdown preview links to other files relative to the document, WebKit shows a .md target as plain text, so following a link replaced the preview with the raw file. A fragment link ([terms](#terms)) resolves against the document's <base href>, which is not the preview page's own URL, so it replaced the preview with the raw document itself. Both reproduce on main by clicking the links in the preview of a file like the one in the issue.

The preview now behaves like a browser:

  • OakLocalLinkActionForURL (new, Frameworks/HTMLOutput/src/helpers/OakLocalLinkPolicy.mm) decides what to do with a tm-file:/file: navigation: only link clicks are affected; a fragment of the document itself scrolls in place; an existing file whose type conforms to HTML, image or PDF loads in the web view as before; directories and missing paths are left to the scheme handler.
  • Any other file is offered to the view's owner through a new localFileHandler hook on OakHTMLOutputView. OakCommandRefresher, which already keeps an auto-refreshing preview up to date, takes the link when its command accepts the target (command_accepts_document: whole-document input and a matching scope selector, new in command/parser), re-runs the command with the target as the document and streams the result into the same view as a new page. Back and forward work through WebKit's history, and refreshes follow the document being shown. When the owner declines, or there is none, the file opens in TextMate through the existing txmt://open handler.
  • Running the command again from another document in the same project window steers the existing view to that document instead of opening a second output window (browsingRefresherForCommand: in OakTextView).
  • Back and forward: command output is streamed once and its pipe is then spent, so WebKit could only show such a page again from its own page cache; on a miss the scheme handler answered 404 and the pane went blank. OakHTMLOutputPageCache (new) keeps the last 32 pages served and the handler replays them. The view also remembers the environment each page was produced with and restores it when history lands on that page, so fragment and relative links keep working there, and it tells the owner which document is now showing so refreshes follow it.
  • Refresh in place: an auto-refresh used loadHTMLString:, which replaces the history entry with a document WebKit cannot revisit, so going back to it after following a link failed with "frame load interrupted", which HOBrowserView swallowed while leaving the progress bar running. A refreshed page is now served again under its own URL through the page cache and reloaded, so its history entry stays revisitable, and an interrupted load resets the status bar.
  • OakTxMtOpenURLForPath percent-encodes the path so & and = survive the query parser in handleTxMtURL:.
  • Tests: HTMLOutput/tests/t_link_policy.mm covers the decision table with temporary files, the URL encoding and the scroll script; t_page_cache.mm the page cache; command/tests/t_accepts_document.cc covers the acceptance predicate.

Verification on macOS 27.0, Debug build, with the issue's sample file previewed via Show Preview:

  • Clicking [glossary](GLOSSARY.md#terms) renders GLOSSARY.md in the same preview window as a new page (the view's URL moves from …/Show Preview/1 to …/Show Preview/2), with no editor window opened and no second preview window. History back returns to the README page. Show Preview from README again re-renders README in the same window. Clicking [guide](./docs/guide.md "Guide") renders docs/guide.md. Clicking [terms](#terms) changes the preview's URL fragment without leaving the page. On main the file links replace the preview with raw Markdown.
  • Back and forward through README, GLOSSARY.md and docs/guide.md land on the right page every time over a dozen hops, including after an edit refreshed the README page in place before and after following a link, with the status bar back button and a real mouse click on the link; a fragment link clicked after going back scrolls in place; an edit to README after going back to it refreshes the preview.
  • HTMLOutput_tests: 13 tests pass; command_tests (run serially, as CI excludes this suite from ctest): 6 tests pass. With the policy forced to "load" the link policy tests fail.

A Markdown preview links to other files relative to the document, and
the HTML output view let every tm-file: and file: navigation load in the
web view. WebKit shows a .md target as plain text, so following a link
from the preview replaced it with the raw file, and a fragment link
resolved against the document's <base href> did the same with the
document itself.

A clicked link to a local file now goes through OakLocalLinkActionForURL.
Files the web view can render (HTML, images, PDF) load as before and a
fragment of the document scrolls in place. Any other file is offered to
the view's owner first: the command refresher that keeps a preview up to
date re-runs its command with the target as the document when the
command's scope and input allow it, streaming the result into the same
view as a new page, so back and forward work and refreshes now follow
the target. Otherwise the file opens in TextMate through txmt://open.

Pages served are kept so back and forward can replay them once the
stream is spent, and each page brings back the environment it was made
with, so links and refreshes follow the page being shown. An auto-refresh
re-serves the page under its own URL instead of loading an HTML string,
which left a history entry WebKit could not return to.

Running the command again from another document in the same window
steers that view to it instead of opening a second output window.

Fixes #86
@dayglojesus
dayglojesus merged commit 0fe5049 into main Sep 22, 2026
2 checks passed
@dayglojesus
dayglojesus deleted the fix/html-output-file-links branch September 22, 2026 02:56
@dayglojesus dayglojesus mentioned this pull request Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTML output shows local non-HTML link targets as raw text instead of opening them

1 participant