function loadWithSource(notebook, library, observer) {
if (typeof library == "function") observer = library, library = null;
if (typeof observer !== "function") throw new Error("invalid observer");
if (library == null) library = new observable.Library();
const {modules, id, nodes} = notebook;
const map = new Map;
const runtime = new observable.Runtime(library);
const main = runtime_module(id);
function runtime_module(id) {
let module = map.get(id);
if (!module) map.set(id, module = runtime.module());
return module;
}
for (const m of modules) {
const module = runtime_module(m.id);
for (let i = 0; i < m.variables.length; i++) {
const v = m.variables[i];
if (module === main)
v.node = nodes.find(({id}) => id === v.node_id);
if (v.from) {
module.import(v.remote, v.name, runtime_module(v.from));
if (module === main) {
const importedVars = [v];
const i0 = i;
while (i+1 < m.variables.length && m.variables[i+1].from === v.from) {
const nextImport = m.variables[++i];
importedVars.push(nextImport);
module.import(nextImport.remote, nextImport.name, runtime_module(v.from));
}
const nbURL = 'https://observablehq.com' + (v.from.match(/\//) ? '/' : '/d/') + v.from;
module.variable(observer(v, i0, m.variables))
.define(`import ${v.name}`, ["html"],
(function(html){return(html`
<pre>import {${importedVars.map(
({name, remote}) => {
return `<a href="${nbURL}#${remote}">${remote}</a>` + (name === remote ? '' : ' as ' + name);
}
).join(', ')}} from <a href="${nbURL}">${v.from}
`)}));
}
}
else if (module === main) { // only attach observers to variables in the main module
if (v.node === undefined) console.log(`missing node object at variable ${i}: ${JSON.stringify(v)}`);
// comment-only cell: (observer is actually an observer factory)
if (!v.value) module.variable(observer(v, i, m.variables))
.define(null, ["md"], (function(md){return(md`\`\`\`js
${v.node.value}
\`\`\``)}));
else {
if (v.name && v.name.startsWith('initial ')) { // mutable cell
// (assumes variables come in the order initial Y -> mutable Y -> Y)
module.variable().define(v.name, v.inputs, v.value); // initial Y
const v1 = m.variables[++i]; // mutable Y
module.variable().define(v1.name, v1.inputs, v1.value);
const v2 = m.variables[++i]; // Y
v2.node = v.node;
module.variable(observer(v2, i-2, m.variables)).define(v2.name, v2.inputs, v2.value);
}
else {
module.variable(observer(v, i, m.variables)).define(v.name, v.inputs, v.value);
if (v.name && v.name.startsWith('viewof ')) { // viewof cell
// (assumes variables come in the order viewof X -> X)
const v1 = m.variables[++i]; // X
v1.node = v.node;
module.variable().define(v1.name, v1.inputs, v1.value);
}
}
}
}
else module.define(v.name, v.inputs, v.value); // dependencies in imported modules
}
}
return runtime;
}