Styling cells through metadata?

Hey folks

my ultimate goal is to be able to “paint” parts of my notebooks in colors - mainly to indicate a level, like basic/intermediate/expert

I found a couple extensions in jupyter-contrib-nbextensions that kind of touch on that, but not quite to my needs; it’s really the whole (range of) cells that I want to outline, not only parts of their contents

So I figured I’d write my own extension; I get it how to do it mostly, except for the crucial part which is to actually render cells in color :wink:

I have looked in the code and so far am out of luck;
at first I reasoned that the cell toolbar thing was behaving a bit like what I need to do, but it seems like this is part of the core and not an extension, unless I’m mistaken
so, is there an elegant way to do that ?

if not as a rough proposal I would suggest to add a very general mechanism at the cell level, that would for exemple allow to set a metadata like this on a cell
“extra_classes”: “basic flashy”
so the generic cell code would just need to inject those classes in the cell <div> elt

with that in place, it’d become a trivial matter of tweaking custom.css

so my questions:

  • is there something in the current code already that would let me achieve that without messing with each and every cell content, just metadata of some kind
  • if not, has there been discussions about similar ideas in the past, and/or is there a chance to get something to the effect of the above ideas be adopted mainstream someday ?

PS. my current focus is the classic notebook

I don’t know if this helps, but this extension adds colour highlights to indicate the execution status of a cell:

It was mentioned in this thread

I have started a couple of extensions that I’m using to explore different ways of colouring cells, one using metadata as metadata:

One that uses tags (which underneath is a specific flavour of metadata):

At some point I’d love to have similar functionality for MyST Markdown inside of Jupyter interfaces (which right now will render things like directives as code blocks). Would love to see attempts in that direction for cell metadata as well (though we’ll probably prioritize Jupyter Lab extensions as a more long-term solution)

@choldgraf From the notebook perspective, I think there is a lot of potential for overloading tags as a tool for triggering extension and styling based customisation; my first attempt at a tagstyler co-opted the alert convention of classnames that are recognised by certain default styling options in notebooks (not sure about JupyterLab; JupyterLab is too complex an envt for amateur have-a-go hackers imho…).

Trying to identify some tag conventions that might be used to trigger various flavours of display output (whether interactive, or simple CSS) would be a Good Thing I think, offering simplicity in use and the potential for building cookie cutter based tools / sphinx plugins etc. So on tag convention might just be class-X if you want to apply a css class X to a cell; but then you have to think: which bit of the cell… which may require: a) a top level default behaviour; b) something more structured to tunnel down, eg class-output-X, class-input-sidebar-X etc; these extension may map to notebook element class names, or may be defined according to naming conventions based on what bit of the cell as perceived by the user you want to style.

definitely +1 on trying to build community standards around tags - I think there are patterns that are common enough across workflows that it’d be worth agreeing on “one way” to do these things in order to avoid re-invention of various wheels.

I’m not sure whether the right kind of standard would be ‘operational’ (e.g. “putting class- before a tag means it will become an HTML tag”) vs. ‘semantic’ (e.g., “error”, “warning”, “note”)…but it’s a conversation I’d be in favor of having!

Jupyter Book’s approach so far has been to start implementing functionality without calling it anything like a “standard”, and over time if particular patterns seem worth formalizing, we’ll try to start a community process to make an official decision / adoption

Re: semantic versus operational tags, I could see a benefit of both; eg the operational approach might be used to support rapid development (it feels “closer to the code”) whereas for a user environment, the semantic approach would be more meaningful (why should users have to worry about operational concerns).

Re: standards evolultion: I’m a firm believer in trying to identify and develop good conventions that can then inform standards adoption if formal standards are ultimately required. But in many cases, particularly where a community development is encouraged, the conventions approach is more compelling of behaviour, I think.

Re: tag conventions, I can also imagine “namespaced” tags; eg packagename-TAG.

FYI, there is a PR for JupyterLab open right now that is about adding a data-tag-FOO attribute to a cell DOM node if the cell is labeled with the tag FOO:

So that would mean every tag is essentially exposed as an attribute in the DOM?

I also note that that PR is a JupyterLab specific one (I tend to just work in vanilla notebooks…).

For styling purposes in notebooks, automatically passing a tags as class attributes, perhaps prefixed (eg tag-FOO) could be interesting, because it then starts to make the UI display programmable/customisable by the user via CSS and extensions that detect particular (class) tags.

It could presumably also make cell tags act like block cell magic invocations?

I’m confused by your explanation of that PR; the code says

  if (this.model.metadata.has('parameters')) {
      this.node.setAttribute('data-parameter-cell', 'true');
    } else {

which unless I’m missing s/t huge, seems to rely on the presence of a parameters metadata key and not tags, am I right ?
even so I’m having a hard time seeing how this applies to a random name like FOO

For the sake of clarity, I would personally argue that we pick some sort of consistent naming; if the side effect on the DOM are additional attributes, why not use the attributes metadata key, or maybe data-tag-attributes if indeed the added attribute is data-tag-FOO ?

Because as much as I can appreciate the simplicity of re-cycling something already used like tags, it feels confusing to use parameters here that seems a little to come out of nowhere, no ? unless it’s already used indeed, I’m just a user and probably not a very representative one :slight_smile:

Please read the review of the PR, where we discuss proposed changes to bring it in line with my explanation above. The code in that PR right now does something different and hasn’t been updated.

@psychemedia thanks for referring to your 2 extensions, particularly the empinken one that very much looks like what I’m after !

being like you more of a classic notebook user, I guess as a way forward I’ll need to either

  • go the quick and dirty way and use you code as a starting point for my own ad hoc use case
  • or post a pr in the classic notebook to somehow mimick what’s being done in jlab; which at this point is not super clear to me yet

in any case, I have just a quick question though about the need for dealing with codecells and textcells differently
I mean here

the purpose being only styling here, could the prompt case not be handled using only css ?

Yes, essentially.

Right. I was just posting here as a solution explored by one of the Jupyter frontends.

Yes, that’s the idea.

I’m not sure what you mean here. Block cell magics are about running code in the kernel, this is about annotating DOM elements in the frontend. Those concepts aren’t implicitly connected.

thanks for clarifying, and sorry to have botched it; will re-read it thoroughly :slight_smile:

@jasongrout it sounds like there’s some discussion in that PR that could help guide the broader conversation about tag standards and how they relate to things like the DOM, “kinds of cells”, etc. Thanks for sharing it!

Do you see any value in trying to have a “standards conversation” around tags, or do you think it’s still at a point where each project can make their own decisions? I think it’s not a big deal now, though I worry about 1-2 years from now if there are lots of notebooks with “jupyterlab-only metadata” or “vscode-only metadata” etc.

I’d like to relate this with the splitcell extension - the one that allows to get cells to take only half of the width

this extension has always had a rather annoying bug; copy and paste a split cell, the resulting copy will show on a 100% width; toggle the cell twice to see it come to 50%; the reason for twice is, the data model has been copied alright but the repercussion of the metadata tag (spit_cell uses cell_style) does not happen during copy/paste

with something like what’s being proposed here, the code for splitcell would become more trivial; and it would work better

provided of course that the specification has it that changing the metadata tags (if that’s what we go for) gets the core to trigger repercussions in the DOM; that’s my expectation, is that a reasonable one ?

@parmetelat My code is likely far from optimal and is definitely not intended as “production code” (not my skill set…):wink: It’s typically evolved rather than designed; some bits may be split out explicitly in “scaffolding” / spaghetti code as I try to simplify a problem, articulate to myself what I think I want to achieve, or consider alternatives to s/thing I’ve already achieved, before getting round (or more likely, not) to refactoring. I’m generally playing with end user ideas of the application achieved howsoever, rather than worry about the code, and generating really quick and crude sketches, not finished work. The code itself is just essentially doodles, and repos are pages in my sketchpad. Rather than use things like wireframe design tools to mockup possible extensions, I tend to hack code to creating half working prototypes that I can point to and say: it’d be good to have something like that, but done properly…:wink: The code is there essentially as a thinking tool to help me explore a user interaction idea.


I was only asking because I wanted to make sure that the ideas considered elsewhere in the thread, to add attributes in the cells depending on its metadata, were not doing a distinction b/w code and text cells, and I wanted to make sure there was no fundamental reason to do so in your case either, is all :slight_smile:

Yeah, there was no good reason other than perhaps I was originally exploring, or reserving the right to explore, different approaches for each cell type.

The tagstyler extension makes no distinction. On my to do list is to combine the two extensions and probably follow the tag approach…