Jlab extension newbie naive questions


I’m trying to make progress on porting the RISE slideshow extension to jlab; I started from the jupyterlab-apod tuto

I have a couple upfront questions, on which any hint or feedback would be most appreciated

Note: sorry for shoving all my issues into a single thread, I can split that later on if some of these topics deserve a larger horizon

  • A. toolbar button: I figured how to insert a toolbar button at either the beginning or end, but that does not seem right; leftmost entries should IMHO remain the standard ones, and OTOH - or on the other end;) - pushing it rightmost sucks too; I would wish to insert it as the rightmost button in the left area, right after the Markdown dropdown in the screenshot below; how should I go about doing that ?

  • B. devel tools: I struggled quite a bit at first to get a watch mode to behave as expected; one thing that I believe is missing from the tutorial is that I essentially ended up running two watching processes,
    one doing jupyter lab --watch and one doing jlpm watch; if I’m right that it’s the way to go, then the tutorial could probably be improved to reflect that

  • C. devel tools - bis: I was playing with the idea of using relative dependencies in my package.json; use case here is that we would like to isolate the dirty patches that we do on top of the mainstream reveal.js into a npm package of its own, but would like to avoid the need to formally publish it at each devel cycle; I have not been able to get that to work so far, does anybody know if that’s a known limitation to this jlpm thing, or on the contrary is that supposed to just work fine ? I need to add that I’m more of a Python guy and am totally new to this tsc/yarn thingy, so I very well may have screwed up somewhere…

  • D. extension design: on a much more general level, the classic notebook extension is by definition not able to create extra tabs; so when triggering on slideshow mode, the notebook content is replaced with a reveal-empowered slideshow; now in the context of jlab, we could envision this feature as a dual-tab gadget; I mean, quite similar to, for example, a markdown preview in vscode.

    At this point I have no idea on how to even start tackling this, so the first iteration’s goal is to reproduce the behaviour of classic RISE; but in anticipation: a) does that seem to even make sense from a usage point of view ? and b) if so is that sort of interaction supported ? are there abstractions in jlab to address the apparently challenging aspect of having 2 tabs sharing the same memory object with an mvc-like behaviour ?

sorry again for mixing all this into a single thread; thanks very much in anticipation for any clue about these questions

Hi @parmentelat, some answers:

A. panel.toolbar.insertItem(0, ‘myButtonName’, button);
B. There is a sentence in the APOD guide that says “If you wish to avoid running jlpm run build after each change, you can open a third terminal, and run the jlpm run watch command from your extension directory, which will automatically compile the TypeScript files as they change.”
C. You can use jupyter labextension link on non-extension packages
D. You can add a sibling widget if you have the parent widget’s context object.


1 Like

thanks again Steven

about A. my understanding was that your sentence would create a button in the leftmost position in the toolbar, is that right ?

thanks for the useful tips in any case, I’m sure this will turn out invaluable when we push again on this matter

@parmentelat, sorry for resurrecting this old thread, but for the icon stuff, next to the cell type button/dropdown I came up with this snippet:

// Getting the index iteratively is less resource consuming, but this is far more readable
// and we only need to get the index at the loading of the extension...
let cellTypeButton = panel.toolbar.node.getElementsByClassName("jp-Notebook-toolbarCellType")[0]
let index = Array.from(cellTypeButton.parentNode.children).indexOf(cellTypeButton)

panel.toolbar.insertItem(index + 1,'rise', button);
return new DisposableDelegate(() => {

Surely @blink1073 has better ideas, but this seems to be working OK.