Published
Edited
Sep 28, 2022
14 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
nodes = {
const comments = [];
try {
const nodes = acorn.parse(input, {
ecmaVersion: 11,
sourceType: "module",
onComment: comments
}).body;
// Interleave top-level comments among AST nodes
for (const comment of comments) {
const {start} = comment;
const priorNodes = nodes.filter((n) => n.start <= start);
// Only splice in comment if it starts after the end of the previous node
if (!priorNodes.length || priorNodes[priorNodes.length - 1].end < start) {
nodes.splice(priorNodes.length, 0, comment);
}
}
return nodes;
} catch (err) {
throw new Error("Cannot parse the vanilla JavaScript you entered above.\n" + err);
}
}
Insert cell
cells = {
const cells = [];
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
switch (node.type) {
case "Line": {
// Combine consecutive single-line comments
if (i && nodes[i - 1].type === node.type) {
cells[cells.length - 1].value += "\n" + node.value.trim();
break;
}
// or else cascade to case "Block"
}
case "Block": {
cells.push({ type: "md", value: node.value.trim() });
break;
}
case "VariableDeclaration": {
// Can have multiple declarations in one statement:
// const x = 0, y = 1;
for (const declaration of node.declarations) {
if (declaration.id.type === "Identifier") {
const name = declaration.id.name;
const value = input.slice(
declaration.init.start,
declaration.init.end
);
if (declaration.init.type === "ObjectExpression") {
// Special case for wrapping object literals in parentheses
cells.push({ type: "js", value: `${name} = (${value})` });
} else {
cells.push({ type: "js", value: `${name} = ${value}` });
}
} else if (declaration.id.type === "ObjectPattern") {
// Destructuring:
// const {a, b} = {a: "toph", b: "tucker"};
// const {first: a, last: b} = {first: "toph", last: "tucker"};
// const {first, last} = user;
for (let i = 0; i < declaration.id.properties.length; i++) {
const key = declaration.id.properties[i].key.name;
const name = declaration.id.properties[i].value.name;
if (declaration.init.type === "Identifier") {
cells.push({
type: "js",
value: `${name} = ${declaration.init.name}.${key}`
});
} else if (declaration.init.type === "ObjectExpression") {
const { start, end } = declaration.init.properties.find(
(d) => d.key.name === key
).value;
const value = input.slice(start, end);
cells.push({ type: "js", value: `${name} = ${value}` });
}
}
}
}
break;
}
case "EmptyStatement": {
break;
}
default: {
cells.push({ type: "js", value: input.slice(node.start, node.end) });
break;
}
}
}

return cells;
}
Insert cell
acorn = require("acorn@8")
Insert cell
import {copyCellButton} from "@tophtucker/generate-copied-cells"
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