Open juba opened 4 years ago
@juba Do you mean that if a user has a local stored copy of an observablehq notebook that they could use the local copy instead of an online download? Observablehq allows for download that produces a zip file that we could potentially plug in instead either with bare text/<script>
tag or through a file attachment. Also, this notebook offers a ui to help a user get exactly what they want.
Or, we could set up an htmlDependency
on the R side to handle local or offline with src
.
It seems like we would need a mechanism here to choose local instead of online.
I'm not sure yet if this might be helpful, but htmlwidget simplification https://github.com/ramnathv/htmlwidgets/issues/305 might aid in this feature.
After a little experimentation, offline will be possible unless we can get http server in R to serve .js
as text/javascript
. Here is the code for reference.
library(robservable)
library(htmltools)
# get temp directory
tmpd <- tempdir()
# create directory for notebook
nb <- file.path(tmpd, "notebook")
dir.create(nb)
# download notebook locally in our newly created directory
path_file <- file.path(nb,"notebook.js")
download.file(
"https://api.observablehq.com/@jashkenas/inputs.js?v=3",
path_file
)
# see contents of our new notebook directory
list.files(nb)
# does not work because server not configured to serve module
# Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.
browsable(tagList(
htmlDependency(
name = "notebook",
version = "0.0.0",
src = list(file = nb),
all_files = TRUE
),
tags$script(
"
(async () => {
let nb = await import('./lib/notebook-0.0.0/notebook.js');
let notebook = nb.default;
})()
"
)
))
# also does not work because of mime type
browsable(tagList(
htmlDependency(
name = "notebook",
version = "0.0.0",
src = list(file = nb),
all_files = TRUE
),
tags$script(
type = "module",
"import {define} from './lib/notebook-0.0.0/notebook.js'"
)
))
# also does not work because of mime type
browsable(tagList(
htmlDependency(
name = "notebook",
version = "0.0.0",
src = list(file = nb),
script = "notebook.js"
),
tags$script(
type = "module",
"import {define} from './lib/notebook-0.0.0/notebook.js'"
)
))
# works in that no error but no way to import that I know of with script type="module"
browsable(
tagList(
tags$script(
type="module",
HTML(paste(readLines(path_file), collapse="\n"))
)
)
)
This is a less than ideal way to make this work, but if we only expect one notebook then perhaps we could replace export default
and then define
becomes available on window/global
.
library(robservable)
library(htmltools)
# get temp directory
tmpd <- tempdir()
# create directory for notebook
nb <- file.path(tmpd, "notebook")
dir.create(nb)
# download notebook locally in our newly created directory
path_file <- file.path(nb,"notebook.js")
download.file(
"https://api.observablehq.com/@jashkenas/inputs.js?v=3",
path_file
)
# since mime type seems to be blocking with module
# try to replace export default
# but this means we will likely face namespace issues
path_file2 <- file.path(nb,"notebook_no_export.js")
cat(
paste(
# replace export default
gsub(
x = readLines(path_file),
pattern = "export default ",
replacement = ""
), collapse="\n"
),
file = path_file2
)
browsable(tagList(
htmlDependency(
name = "notebook",
version = "0.0.0",
src = list(file = nb),
script = "notebook_no_export.js",
all_files = TRUE
),
tags$script(
"console.log(define);"
)
))
Thanks for taking the time to experiment on this. You're right, the MIME type issue is a real problem here as modules are not expected to be loaded from local files. In my browser even downloading a notebook via Observable "Download code" features doesn't work outside of a local HTTP server.
Your workaround is quite clever if not ideal !
The only use case of an offline support I can think of is an rmarkdown document which would be completely self_contained
, ie would work without an active Internet connection. But maybe it is a case not frequent enough to justify investing time in it or using workarounds right now ?
Other workarounds could be :
In other words, none of these workarounds are ideal either...
See if there could be a way to provide offline support (ie functional widget in rmarkdown or shiny without an active Internet connection).