Skip to content

Instantly share code, notes, and snippets.

@ianb
Created May 4, 2018 22:24
Show Gist options
  • Save ianb/4716840dc98a944a11e6ee402755283a to your computer and use it in GitHub Desktop.
Save ianb/4716840dc98a944a11e6ee402755283a to your computer and use it in GitHub Desktop.
// An extension to evaluate `${Python}` in Markdown cells
define(["base/js/namespace"], function(Jupyter) {
function load_ipython_extension() {
Jupyter.notebook.events.on("rendered.MarkdownCell", (event, data) => {
let cell = data.cell;
renderCell(cell);
});
Jupyter.notebook.events.on("kernel_ready.Kernel", () => {
renderAllCells();
});
Jupyter.notebook.events.on("finished_execute.CodeCell", () => {
console.log("got finish event");
renderAllCells();
});
}
function renderAllCells() {
let cells = Jupyter.notebook.get_cells();
for (let cell of cells) {
if (cell.cell_type !== "markdown" || !cell.rendered) {
continue;
}
renderCell(cell);
}
}
function renderCell(cell) {
let contentEl = cell.element[0].querySelector(".text_cell_render.rendered_html");
for (let codeEl of contentEl.querySelectorAll("code, span.rendered_code")) {
let code;
if (codeEl.tagName === "CODE") {
code = codeEl.textContent;
if (!code.startsWith("${") || !code.endsWith("}")) {
continue;
}
code = code.substr(2, code.length-3);
} else {
code = codeEl.title;
}
let startTime = Date.now();
let outputCalled = false;
let callbacks = {
clear_on_done: false,
shell: {
reply: (msg) => {
if (!outputCalled) {
codeEl.title = "Note: expression had no result";
codeEl.style.color = "#900";
}
}
},
iopub: {
output: (output) => {
outputCalled = true;
let totalTime = Date.now() - startTime;
if (output.content.ename) {
// Got an exception, ignore since this will be common
console.error(`${output.content.ename} in expression ${code}: ${output.content.evalue}`);
let traceback = output.content.traceback.join("\n");
traceback = traceback.replace(/\u001b[^m]+m/g, "");
console.error(traceback);
if (codeEl.tagName === "SPAN") {
let newEl = document.createElement("code");
newEl.textContent = "${" + code + "}";
newEl.title = traceback;
codeEl.replaceWith(newEl);
codeEl = newEl;
}
codeEl.title = traceback;
codeEl.style.color = "#900";
} else {
let newEl = document.createElement("span");
newEl.className = "rendered_code";
newEl.title = code;
if (output.content.data["text/html"]) {
newEl.innerHTML = output.content.data["text/html"];
} else {
newEl.textContent = output.content.data["text/plain"];
}
codeEl.replaceWith(newEl);
codeEl = newEl;
}
if (totalTime > 1000) {
codeEl.style.color = "#900";
codeEl = `Time warning: ${Math.floor(totalTime / 1000)}` + (codeEl.title ? "\n" + codeEl.title : "");
}
}
}
};
if (!cell.notebook.kernel) {
console.warn("No kernel for", code);
return;
}
console.log("Executing code", code);
cell.notebook.kernel.execute(code, callbacks, {
silent: false,
store_history: false,
stop_on_error: true,
});
}
}
return {
load_ipython_extension
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment