manzt / anywidget

jupyter widgets made easy
https://anywidget.dev
MIT License
451 stars 35 forks source link

feat: Add `%%vfile` cell magic #594

Closed manzt closed 3 months ago

manzt commented 3 months ago

This PR a new experimental cell magic %%vfile, designed for prototyping widget ideas within Jupyter notebooks. This is not intended for production use. The goal is to enable nicer syntax highlighting of code and to allow using anywidget's Hot Module Replacement (HMR) entirely from within a notebook.

Previously, anywidget ESM and CSS had to be provided as inline strings or file paths. Notebook development required editing JS/CSS as inline strings, which resulted in losing widget state to see front-end code changes. Anywidget's HMR enables live reloading of front-end code without losing state, but only by monitoring the file system (requring making separate files for the best DX).

With the new %%vfile cell magic, you can prototype entirely from within a a single notebook and enjoy "live" reloads whenever the vfile cell is re-executed.

In[1]:

%load_ext anywidget

In[2]:

%%vfile index.js
export default {
  render({ model, el }) {
    el.innerHTML = `<h1>Hello, ${model.get("name")}!</h1>`;
  }
}

In[3]:

import anywidget
import traitlets

class Widget(anywidget.AnyWidget):
    _esm = "vfile:index.js"
    name = traitlets.Unicode("world")

Widget()

Example:

https://github.com/manzt/anywidget/assets/24403730/a6bd172d-6fac-4bf5-bd93-c9a07c328ba7

Open questions:

I'm not entirely sure what the magic API should look like. We could have %%esm and %%css, but under the hood they do the same thing. I'd also like to avoid populating variables in the notebook namespace with objects like FileContents which aren't meant for end users.

Right now, the %%vfile requires a virtual file name, that we can then match to whatever is passed to _esm. I guess would could be more pedantic about his with something like requiring a prefix in _esm = "vfile:index.js".

EDIT: Ok I've decided to be pedantic and require vfile: prefix.

changeset-bot[bot] commented 3 months ago

🦋 Changeset detected

Latest commit: de6dea8652be4f1f82841716ce85c9dff235caa4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package | Name | Type | | --------- | ----- | | anywidget | Patch |

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR