I was working on a visualization of imported data in the style of an embed, and I realized that one of the disadvantages of using a viewof statement to display something different than the returned value is that it hides the foo = section of the output that allows you to see what name the object is assigned to. I’m wondering if it’s possible to add some sort of API that would allow me to integrate that kind of information. I propose a new Notebook global that stores information about the current notebook. As a start, it could have a currentCell property:
const currentCell: {
name: string | null;
viewof: boolean;
value: any; // the `this` value in the cell
id: string; // a unique ID for the current cell
source: string; // This might be useful, not sure.
}
The currentCell object is set to the value of the cell that’s currently executing, so if you define a function in one cell and call it in a second, Notebook.currentCell as defined in the function will return the value for the second cell.
Would this be possible to implement in some way?
(The id value could be useful for things like my React notebook that need to cache data per cell)
There was a previous request along these lines here but in the end something much simpler (a trick to get the name of a function argument by wrapping it in an object) sufficed.
Here are some thoughts on how you might approach getting that data now. I see ways that you can get something like the Notebook global (with data about all the cells in the notebook), but getting a currentCell object working seems harder:
As hinted at in the above-linked thread, you can get a lot of the information you want about a notebook by fetching the notebook JSON object from the Observable API (specifically, from https://api.observablehq.com/document/username/notebook-name); however, this can’t be done directly from a notebook because the origin of the request needs to be observablehq.com and not .observableusercontent.com. I think there used to be some notebooks like this one which got around this using a CORS proxy, but the proxies don’t seem to be working at the moment.
An imperfect way to get something like this notebook JSON data is to use the fromV1 function I’ve written here, which lets you pass a URL to the notebook’s runtime V1 module JS file (which the API lets you access from a notebook). This function can reconstruct a notebook JSON object from the JS file (n.b. this is stuck at the most-recently shared / published version of the notebook), but there are limitations, particularly for notebooks with imports.
Note that the notebook JSON object only contains the id of each cell (currently, a number) and the cell “body” (i.e. the source string you submit for the cell). To get the name and viewof data you want from that, you can pass the cell bodies to the observable parser library; (see e.g. this notebook of mine).
Finally, let’s assume you have accomplished enough of the above so that one of your live cells cell1 has access to a parsed notebook array nbdat whose elements are objects with metadata on each of the cells in that notebook. Then you still have the problem of figuring out from within cell1 which entry of nbdat it corresponds to. This seems tricky to do in general.
OK, I ended up making a rough little demo notebook. The punchline is that cells which output HTML elements can sort of get their own metadata, but you’ll need a “real” notebook JSON object – the one created by fromV1 won’t be good enough: