function newNotebookRenderer({
loadData,
loadRuntime,
loadNotebook,
newObserver
} = {}) {
loadData =
loadData ||
async function loadData(d) {
if (typeof d === "string") {
const res = await fetch(d);
d = await res.json();
}
return d;
};
loadRuntime =
loadRuntime ||
(async () =>
await import(
"https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js"
));
loadNotebook = loadNotebook || (async (url) => (await import(url)).default);
newObserver =
newObserver ||
((name, { rootElement, element, runtime, library, Inspector }) => {
const inspector = () =>
(inspector.instance = inspector.instance || new Inspector(element));
element.classList.add("observablehq");
let prev;
return {
pending() {
},
fulfilled(value) {
if (value === prev) return;
if (value instanceof Node) {
element.innerHTML = "";
element.appendChild(value);
} else if (typeof value === "undefined") {
element.innerHTML = "";
} else if (
typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean"
) {
element.innerHTML = String(value);
} else {
inspector().fulfilled(value);
}
prev = value;
},
rejected(error) {
inspector().rejected(error);
}
};
});
return Object.assign(
async function bindNotebook({
notebook,
notebookUrl,
element,
data = {},
invalidation
}) {
const { Runtime, Library, Inspector } = await loadRuntime();
notebook = notebook || (await loadNotebook(notebookUrl));
const dataList = [];
for (const [key, value] of Object.entries(data)) {
dataList.push([key, await loadData(value)]);
}
const cells = [...element.querySelectorAll("[data-cell]")];
const cellsIndex = new Map(cells.map((elm) => [elm.dataset.cell, elm]));
const library = new Library();
const width = (library.width = Math.min(element.clientWidth, 1024));
[...element.querySelectorAll("[data-root]")].forEach((elm) => {
elm.style.width = width + "px";
});
const runtime = new Runtime(library);
invalidation && invalidation.then(() => runtime.dispose());
const parent = runtime.module(notebook);
const module = runtime.module();
for (let [name, elm] of cellsIndex.entries()) {
const observer = newObserver(name, {
element: elm,
rootElement: element,
runtime,
Inspector,
library
});
module.variable(observer).import(name, name, parent);
}
dataList.forEach(([key, value]) => {
parent.redefine(key, value); // ??
});
return Object.assign(element, { module, runtime, library });
},
{ loadData, loadRuntime, loadNotebook }
);
}