Public
Edited
Mar 19
Importers
1 star
Insert cell
Insert cell
withImportmap = function withImportMap(importmap, hook) {
let resolve, reject;
const ready = new Promise(function set(resolve_, reject_) {
resolve = resolve_;
reject = reject_;
});

const source = [
`<script type=importmap onerror="frameElement.reject">`,
JSON.stringify(importmap).replace(
/<(?:!--|\/?script)/g,
(match) => "\\x3C" + match.substring(1)
),
`</script>`,
"<script type=module>(",
async function importer() {
const { hook, importmap, resolve, reject } = window.frameElement;
try {
hook?.(window, (name) => import(name));
const toEntry = async (name) => [name, await import(name)];
const entries = await Promise.all(
Object.keys(importmap.imports || {}).map(toEntry)
);
const imports = Object.fromEntries(entries);
resolve({ imports, window });
} catch (e) {
reject(e);
}
}.toString(),
")()</script>"
].join("");
//const blob = new Blob(source, { type: "text/html" });
//const url = URL.createObjectURL(blob);

const iframe = document.createElement("iframe");
//iframe.setAttribute("src", url);
iframe.setAttribute("srcdoc", source);
Object.assign(iframe, {
hook,
ready,
resolve,
reject,
importmap,
appendTo: (invalidation, parent = document.body) => {
invalidation.then(() => {
iframe.remove();
});
parent.append(iframe);
return iframe.ready;
}
});
return iframe;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
replaceWindow = function replaceWindow(newWindow) {
replace(newWindow, window);
}
Insert cell
Insert cell
demoImports = withImportmap(importmap, function hook(newWindow) {
root.replaceChildren();
const log = root.value.with("hook", { level: levels.trace });
replace(newWindow.document, window.document, log.with("document"));
log("done");
})
.appendTo(invalidation)
.then(({ imports }) => imports)
Insert cell
basicEditor({ imports: demoImports, document, invalidation })
Insert cell
root = newLog()
Insert cell
{
const iframe = withImportmap(importmap);
yield iframe;
const {
imports,
window: { document }
} = await iframe.ready;
const editor = basicEditor({ imports, document, invalidation });
document.body.append("iframe", editor);
}
Insert cell
basicEditor = function basicEditor({
imports,
invalidation,
document = window.document
}) {
const { EditorView, minimalSetup, basicSetup } = imports.codemirror;
const { javascript } = imports["@codemirror/lang-javascript"];
const parent = document.createElement("div");
parent.style.minHeight = "10ex";
parent.style.marginBottom = "10ex";
const editor = new EditorView({
extensions: [basicSetup, javascript()],
parent
});
invalidation.then(() => {
editor.destroy();
parent.remove();
});
return parent;
}
Insert cell
importmap = generate(["codemirror", "@codemirror/lang-javascript"])
Insert cell
generate = async function generate(dependencies, env = "production") {
const response = await fetch("https://api.jspm.io/generate", {
method: "POST",
body: JSON.stringify({
install: dependencies,
env: [env, "browser", "module"]
})
});
if (!response.ok) {
throw new Error("not ok");
}
const json = await response.json();
return json.map;
}
Insert cell
viewof dependencies = Inputs.textarea({
label: "Dependencies",
value: "codemirror@6",
placeholder: "codemirror@6"
})
Insert cell
generated = generate(
dependencies
.split("\n")
.map((dep) => dep.trim())
.filter((dep) => dep)
)
Insert cell
JSON.stringify(generated, null, 2)
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