posit-dev / posit-dev/positron
Improving on "open" behavior of HTML-ish URLs
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 4.3k
- Forks
- 184
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 195
Description
In particular, this issue is about fixing pkgdown::preview_site(path = "reference/across.html"), which opens in the browser but not with the correct CSS available to render it correctly (see below). But is is also about better / more robust handling of HTML that comes through browseURL() in general
In https://github.com/posit-dev/positron/issues/4297 we saw issues with browseURL() and HTML files, in particular the following HTML files were opening in an editor rather than opening them in the browser / viewer:
pkgdown::preview_site()pkgdown::preview_site(path = "reference/across.html")profvis::profvis(expr)
These all called browseURL("<path>/file.html") in some way.
We determined here https://github.com/posit-dev/positron/issues/4297#issuecomment-2307212078 that this was a regression from https://github.com/posit-dev/positron/pull/4151 and mostly fixed the issues here https://github.com/posit-dev/positron/pull/4468
However, pkgdown::preview_site(path = "reference/across.html") still does not work correctly:
The problem is that we currently send a ShowUrl event from ark, and now as of https://github.com/posit-dev/positron/pull/4468 we detect an HTML file coming through that event and start a proxy server serving from its parent directory. The problem with that is that the parent directory of across.html is just reference/, but that is missing all the CSS to correctly render across.html.
@jmcphers and I think the right approach to fix this is to instead:
-
Go through
ShowHtmlFileon the ark side, who's purpose is to show static HTML content in a proxy server -
Probably add an
externalargument toShowHtmlFileto request that it be opened in a browser rather than the viewer -
Rework the
ShowHtmlFileparams signature to split the absolutepathinto:directory, the base directory to serve frompath, the relative path from the base directory to the HTML file
That allows Positron to know where to serve from, possibly allowing us to remove this code where previously we were guessing and using the parent directory
It would be up to ark to figure out that a URL like
/Users/davis/files/r/packages/dplyr/docs/dev/reference/across.html
should be split into
/Users/davis/files/r/packages/dplyr/docs/dev/ = dir
reference/across.html = path
But for that we could probably look up one directory at a time until we can't find an index.html anymore, and use the last time we saw index.html as the root directory to try and serve from.
Inside the details below is ark code for browser.rs that I was working on to start working towards this:
//
// browser.rs
//
// Copyright (C) 2023-2024 Posit Software, PBC. All rights reserved.
//
//
use amalthea::comm::ui_comm::ShowHtmlFileParams;
use amalthea::comm::ui_comm::ShowUrlParams;
use amalthea::comm::ui_comm::UiFrontendEvent;
use harp::object::RObject;
use libr::Rf_ScalarLogical;
use libr::SEXP;
use crate::help::message::HelpEvent;
use crate::help::message::ShowHelpUrlParams;
use crate::interface::RMain;
#[harp::register]
pub unsafe extern "C" fn ps_browse_url(url: SEXP) -> anyhow::Result<SEXP> {
ps_browse_url_impl(url).or_else(|err| {
log::error!("Failed to browse url due to: {err}");
Ok(Rf_ScalarLogical(0))
})
}
fn is_help_url(url: &str) -> bool {
RMain::with(|main| main.is_help_url(url))
}
fn handle_help_url(url: String) -> anyhow::Result<()> {
log::trace!("Sending `ShowHelpUrl` event");
let event = HelpEvent::ShowHelpUrl(ShowHelpUrlParams { url });
RMain::with(|main| main.send_help_event(event))
}
fn is_html_file(url: &str) -> bool {
url.ends_with(".html")
}
fn handle_html_file(url: String) {
// TODO: Needs separate `path` and `directory` arguments.
// TODO: Possibly needs an `external` argument to request that it opens in a browser.
log::trace!("Sending `ShowHtmlFile` event");
let params = ShowHtmlFileParams {
path: url,
title: "".to_string(),
is_plot: false,
height: 0,
};
let event = UiFrontendEvent::ShowHtmlFile(params);
RMain::with(|main| main.send_frontend_event(event))
}
fn handle_url(url: String) {
log::trace!("Sending `ShowUrl` event");
let params = ShowUrlParams { url };
let event = UiFrontendEvent::ShowUrl(params);
RMain::with(|main| main.send_frontend_event(event))
}
unsafe fn ps_browse_url_impl(url: SEXP) -> anyhow::Result<SEXP> {
// Extract URL.
let url = RObject::view(url).to::<String>()?;
let _span = tracing::trace_span!("browseURL", url = %url).entered();
// Handle help server requests.
if is_help_url(&url) {
handle_help_url(url)?;
return Ok(Rf_ScalarLogical(1));
}
// Handle HTML files.
if is_html_file(&url) {
handle_html_file(url);
return Ok(Rf_ScalarLogical(1));
}
// For all other URLs, create a ShowUrl event and send it to the main
// thread; Positron will handle it.
handle_url(url);
Ok(Rf_ScalarLogical(1))
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in ark's browser.rs, especially handle_html_file() and the ShowHtmlFileParams construction, then inspect extensions/positron-proxy/src/htmlProxy.ts around the linked serving logic. Trace how browseURL() reaches ShowHtmlFile and determine the directory/path and external-browser parameters needed for nested HTML; done means pkgdown::preview_site(path = "reference/across.html") renders with its CSS and other HTML URLs retain correct behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, typescript
- Domain
- desktop, developer-experience
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100