observablehq / stdlib

The Observable standard library.
https://observablehq.com/@observablehq/standard-library
ISC License
957 stars 83 forks source link

Method to resolve all dependencies via a relative URL #394

Closed mjskay closed 1 month ago

mjskay commented 1 month ago

Hi, I was wondering if there is a way to set up Observable to resolve all dependencies via a relative URL, or if this is not currently possible, if it is on the horizon.

I see that the source seems to specifically load some dependencies via this hardcoded CDN:

https://github.com/observablehq/stdlib/blob/746ca2e69135df6178e4f3a17244def35d8d6b20/src/require.js#L3-L4

My specific use case is that we are running an experimental submission track at the Journal of Visualization and Interaction where people can submit interactive articles, which may include using Observable in the submission (you can see an example of one such paper currently under review here; e.g. Figure 3).

We would like to be able to package up all external resources so we can serve them from the paper repository as part of long-term archiving of papers. Basically, we don't want the longevity of papers to be dependent on external servers continuing to exist. See also discussion here: https://github.com/journalovi/2023-park-gatherplots/issues/22

Thanks for any help / pointers!

mbostock commented 1 month ago

If you use Observable Framework for this (instead of Quarto + the Observable runtime), it will self-host all external dependencies by default; you don’t have to do anything in order to package up external resources. If you use npm: imports (which the Observable standard library does by default), they are downloaded and self-hosted from jsDelivr during build; if you use node imports, you can use your preferred package manager to install libraries to node_modules, and likewise they are self-hosted.

If you’re using the Observable runtime directly (or via Quarto), you’ll need to configure the runtime’s library to use a different resolver rather than using the default one. That’s the first argument to the Library constructor. But there are a couple places that don’t respect a custom resolver, such as SQLiteDatabaseClient and FileAttachment. 😞

cscheid commented 1 month ago

SQLiteDatabaseClient and FileAttachment.

I didn't know about SQLiteDatabaseClient (I'll have to file a Quarto bug!), but Quarto does patch FileAttachment to do the right thing.

If you’re using the Observable runtime directly (or via Quarto), you’ll need to configure the runtime’s library to use a different resolver rather than using the default one. That’s the first argument to the Library constructor. But there are a couple places that don’t respect a custom resolver, such as SQLiteDatabaseClient and FileAttachment. 😞

This sounds promising. @mjskay, I don't think Quarto supports overwriting the resolver from a document, but it feels like the kind of thing we should support.

EDIT: It will be a good bit of work for Quarto to figure out how to support custom resolvers, since the Library constructor is pretty hidden in our code, but it looks like that's what we need to do.

mjskay commented 1 month ago

Thanks for the quick reply @mbostock! Sounds like this is something we can resolve at the Quarto / JoVI level, so I'll close this issue.

If you use Observable Framework for this (instead of Quarto + the Observable runtime), it will self-host all external dependencies by default; you don’t have to do anything in order to package up external resources

Reminds me I should add Observable Framework to the JoVI list of suggested article formats (we allow anything that compiles to a static webpage).