Instantly share code, notes, and snippets.
Last active
April 8, 2022 09:31
-
Save psychemedia/da20c8b4a1ce111498f20176c1a1ce6d to your computer and use it in GitHub Desktop.
Jupyterlab-empinken early sketches
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Most of the code cribbed from @krassowski | |
// https://stackoverflow.com/questions/71736749/accessing-notebook-cell-metadata-and-html-class-attributes-in-jupyterlab-extensi/71744107?noredirect=1#comment126807644_71744107 | |
// Testing this in: | |
// https://github.com/jupyterlab/jupyterlab-plugin-playground | |
import { IDisposable, DisposableDelegate } from '@lumino/disposable'; | |
import { | |
JupyterFrontEnd, | |
JupyterFrontEndPlugin, | |
} from '@jupyterlab/application'; | |
import { DocumentRegistry } from '@jupyterlab/docregistry'; | |
import { | |
NotebookActions, | |
NotebookPanel, | |
INotebookModel, | |
} from '@jupyterlab/notebook'; | |
/** | |
* The plugin registration information. | |
*/ | |
const plugin: JupyterFrontEndPlugin<void> = { | |
activate, | |
id: 'ouseful-tag-class-demo', | |
autoStart: true, | |
}; | |
/* | |
The most relevant docs appear to be: | |
https://jupyterlab.readthedocs.io/en/stable/api/modules/notebook.notebookactions.html | |
*/ | |
export class ClassDemoExtension | |
implements DocumentRegistry.IWidgetExtension<NotebookPanel, INotebookModel> | |
{ | |
/** | |
* Create a new extension for the notebook panel widget. | |
* | |
* @param panel Notebook panel | |
* @param context Notebook context | |
* @returns Disposable | |
*/ | |
createNew( | |
panel: NotebookPanel, | |
context: DocumentRegistry.IContext<INotebookModel> | |
): IDisposable { | |
const notebook = panel.content; | |
function check_tags(notebook){ | |
/* | |
Iterate through all the cells | |
If we see a cell with a tag that starts with class- | |
then add a corresponding tag to differnt elements in the | |
notebook HTML DOM | |
*/ | |
for (const cell of notebook.widgets) { | |
let tagList = cell.model.metadata.get('tags') as string[]; | |
if (tagList) { | |
for (let i = 0; i < tagList.length; i++) { | |
var tag = tagList[i]; | |
if tag.startsWith("class-") { | |
/* | |
The plugin playground extension is rather hostile | |
to have-a-go end-user devs (it's rather strict in | |
its Javascript epxectations) so if you don't | |
declare things with let, const or var then an | |
error of the following form is likely to be thrown | |
that stops further execution: | |
ReferenceError: class_name is not definred | |
*/ | |
//This will replace just the first instance of class- | |
const class_name = tag.replace("class-", "tag-") | |
// Add class tags to various parts of the DOM | |
// What sort of cell are we? | |
console.log("Cell type: " + cell.model.type) | |
// Try to see what's going on... | |
console.log("Try node...") | |
cell.node.classList.add(class_name + "-" + cell.model.type + "-node"); | |
console.log("Try inputArea.node...") | |
cell.inputArea.node.classList.add(class_name + "-" + cell.model.type + "-inputArea_node"); | |
console.log("Try editor.node...") | |
cell.editor.host.classList.add(class_name + "-" + cell.model.type + "-editor_host"); | |
console.log("Try .inputArea.promptNode...") | |
cell.inputArea.promptNode.classList.add(class_name + "-" + cell.model.type + "-inputArea_promptNode"); | |
if (cell.model.type=="markdown") { | |
//console.log("Try RenderedHTMLCommon.node...") | |
//cell.RenderedHTMLCommon.node.classList.add(class_name + "-" + cell.model.type + "-RenderedHTMLCommon.node") | |
//TO DO - access lm-Widget p-Widget jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput | |
// DOESN'T WORK: cell.MarkdownOutput.node, MarkdownOutput.host, RenderedMarkdown.node, RenderedHTMLCommon.node | |
} | |
else { | |
console.log("Try outputArea.node...") | |
cell.outputArea.node.classList.add(class_name + "-" + cell.model.type + "-outputArea_node") | |
} | |
} // end: if class starts with tag... | |
} // end: tags iterator | |
} //end: if there are tags | |
} // end: iterate cells | |
} // end: check_tags function definition | |
notebook.modelChanged.connect((notebook) => { | |
console.log("I think we're changed"); | |
// This doesn't seem to do anything on notebook load | |
// iterate cells and toggle DOM classes as needed, e.g. | |
//check_tags(notebook); | |
}); | |
notebook.fullyRendered.connect((notebook) => { | |
/* | |
I don't think this means fully rendered on a cells becuase it seems | |
like we try to add the tags mutliple times on notebook load | |
which is really inefficient. | |
This may be unstable anyway, eg the following comment: | |
https://stackoverflow.com/questions/71736749/accessing-notebook-cell-metadata-and-html-class-attributes-in-jupyterlab-extensi/71744107?noredirect=1#comment126807644_71744107 | |
I'll with go with in now in the expectation it will be break | |
and I will hopefully be able to find another even to fire from. | |
I get the impression the UI is some some of signal hell and | |
the solution is just to keep redoing things on everything | |
if anything changes. Who needs efficiency or elegance anyway...! | |
After all, this is just an end-user hack-from-a-position-of-ignorance | |
and works sort of enough to do something that I couldn't do before... | |
*/ | |
console.log("I think we're fullyRendered...(?!)"); | |
// iterate cells and toggle DOM classes as needed, e.g. | |
check_tags(notebook); | |
}); | |
return new DisposableDelegate(() => { | |
}); | |
} | |
} | |
/** | |
* Activate the extension. | |
* | |
* @param app Main application object | |
*/ | |
function activate(app: JupyterFrontEnd): void { | |
app.docRegistry.addWidgetExtension('Notebook', new ClassDemoExtension()); | |
} | |
/** | |
* Export the plugin as default. | |
*/ | |
export default plugin; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment