Published
Edited
May 2, 2020
2 forks
Importers
26 stars
Insert cell
Insert cell
embed1 = embedWithSource({
id: "test",
nodes: [
{
id: 0,
pinned: false,
value:
"md`I'm an unpinned cell! Click in the pink area below to expand and see my source.`"
},
{
id: 1,
pinned: true,
value: "md`I'm a pinned cell! My source is always visible.`"
}
]
})
Insert cell
Insert cell
Insert cell
Insert cell
radio0 === 'div' ?
embedWithSource(nbLatt, 600) : // embed in div
embedWithSourceIframe(nbLatt, 600) // embed in iframe
Insert cell
Insert cell
Insert cell
Insert cell
moduleDiv = importModule('https://api.observablehq.com/@bryangingechen/divisibility-lattice@732.js')
Insert cell
Insert cell
nbDiv = fromV1(moduleDiv)
Insert cell
Insert cell
embedWithSource({id:'@bryangingechen/divisibility-lattice', version:'731', nodes:nbDiv}, 800)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// old documentation for Runtime.load is at:
// https://github.com/observablehq/runtime/blob/98905d3ad7d6850152e4604faf96f8c8218e93ce/README.md
// This function is modified from:
// https://github.com/observablehq/runtime/blob/9019bfef749255b5ae14d8dad8dfc2d91f88bad9/src/load.js#L4
// See LICENSE cell
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) // attach node object to variable
v.node = nodes.find(({id}) => id === v.node_id);
if (v.from) { // import cell
module.import(v.remote, v.name, runtime_module(v.from));
if (module === main) { // imitate Observable's output for an import with a fake cell
const importedVars = [v];
const i0 = i;
// only show this fake cell once for each import
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;
}
Insert cell
// This function is modified from Inspector.into:
// https://github.com/observablehq/inspector/blob/115a96dd78d41f7fbebc0260155aa9ec90cccca3/src/index.js#L51
// See LICENSE cell
function intoWithSource(container, prefix="myInspect", md, reverse=false) {
if (typeof container === "string") {
container = document.querySelector(container);
if (container == null) throw new Error("container not found");
}
return function(v) { // supplied inputs are variable, array index, array of all variables
const newContainer = container.appendChild(document.createElement("div"));
const div = document.createElement("div");
// makes links to cells work
if (v.name) {
const name = v.name.split(' ');
if (name[0] === "viewof" || name[0] === "initial") name.shift();
if (name.length === 1 && !document.querySelector(name[0])) div.setAttribute("id", name[0]);
}
const newdiv = newContainer.appendChild(div);
if (v.node !== undefined) { // if node not attached, this'll just act like the default inspector
newContainer.setAttribute("id", `${prefix}-node-${v.node.id}`)
newdiv.setAttribute("class", v.node.pinned ?
`${prefix}-pinned${reverse ? ` ${prefix}-reverse` : ''}` :
`${prefix}-unpinned${reverse ? ` ${prefix}-reverse` : ''}`);
if (v.from || v.value) { // show source if not comment-only cell
const sourcediv = reverse ? newContainer.insertBefore(document.createElement("div"), newdiv) :
newContainer.appendChild(document.createElement("div"));
sourcediv.setAttribute(
"class",
`${prefix}-source ${v.node.pinned ?
`${prefix}-source-pinned` :
`${prefix}-source-unpinned`}`);
if (v.node.pinned) sourcediv.appendChild(md`\`\`\`js
${v.node.value}
\`\`\``);
else sourcediv.addEventListener('click', event => {
if (sourcediv.firstChild) sourcediv.firstChild.remove();
else sourcediv.appendChild(md`\`\`\`js
${v.node.value}
\`\`\``);
});
}
}
return new observable.Inspector(newdiv);
};
}
Insert cell
Insert cell
async function embedWithSource(nb, h=null, prefix='myInspect', reverse=false) {
const v1script = await toV1(nb, true);
const module = await importModule(`data:text/javascript;base64,${utoa(v1script)}`);
const hello = html`<div style="${h !== null ?
`height:${h}px; overflow:scroll; ` :
''}border: thin solid #555; padding:25px; resize:vertical">`;
loadWithSource(module.default, lib, intoWithSource(hello, prefix, md_, reverse));
return hello;
}
Insert cell
async function embedWithSourceIframe(nb, h=null, prefix='myInspect', reverse=false) {
const v1script = await toV1(nb, true);
const iFrame = html`<iframe title="${nb.title}" id="${nb.id}"
style="height:100%; width:100%; border: none; border-width:0px; padding:0px;">`;
iFrame.srcdoc = indexhtml(`data:text/javascript;base64,${utoa(v1script)}`, nb.title, prefix, reverse);
return html`<div style="height:${h}px; resize:vertical; overflow:hidden;
border: thin solid #555; padding:10px;">${iFrame}`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
zipBlob = {
const zip = new JSZip();
zip.file("notebook.js", script);
zip.file("index.html", ihtml);
return zip.generateAsync({type:"blob"});
}
Insert cell
Insert cell
// see the Warning in this notebook for why we need to use require_ and md_ here
import {toV1, utoa, observable, importModule, lib, require_, md_} from '@bryangingechen/from-raw-notebook-source-to-observable-runtime-v1-modules'
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more