Skip to content

Black-box JS/TS widgets for MyST based on the AnyWidget standard #2603

@stevejpurves

Description

@stevejpurves

Objective

The objective of this ticket is to track the implementation of a black-box javascript "widget" system for MyST Markdown that follows the interfaces and approach taken by https://anywidget.dev/.

The purpose of the system is to allow users to incorporate arbitrary JS code into MyST website builds, without needing to adjust the theme/website-renderer, instead a single NodeRenderer following the AnyWidget
interface is built into the theme/website-renderer, tht can handle loading and passing of data to any Javascript ESM module.

AnyWidgets are used in Juptyerlab as an alternative to ipywidgets. In MyST, we intend to reproduce the best of the interfaces that AnyWidget has standardized and usee them in an approraite way in the MyST MArkdown stack.

This type of JS plugin opens many possibilities for custom rendering, and has been used in extensions to MyST Markdown like those developed by Curvenote. Examples are here and here

The approach taken here will build on what we already have working in Curvenote. We propose upstreaming that functionality and then extending it. The starting point is this package

Proposed Approach

First base

  • initial upstream & Release
    • in mystmd implement the widget directive, based on the starting point here
    • Add the widget renderer to myst-theme, based on this code
      • Add this in an isolated package in the myst-theme monorepo, this will allow the more flexibility for consumers
      • IN PROGRESS

Just completing this first step will allow people to start plugging in their own JS modules provided that they remotely host the JS module (and css is needed), and if only 1 way custom rendering is needed (as full anywidget model / view is not yet implemented). This is how the plugin works at the moment, and is more aimed at a group of users with separate (trusted) package management in place for the JS ESM modules.

We propose getting this out there as-is, early so we can also start gathering more use cases as people try to use it

Testing

An example site for use in development and testing is here: https://github.com/jupyter-book/example-widgets.

The idea is to extend this repo to cover many core use cases, similar to this repo which works well for outputs.

Extensions

The following are extensions to the above that are obvious, or needed based on experience so far.

  1. Allow a widget to point to a local JS ESM module (and css file) in the project folder and have this hosted as part of the site on build. (related?)
    1. Possibly implemented by a transform that can do the file copying and url rewriting
  2. When a widget uses a remote ESM module (and CSS file), pull the module in to the lcoal build and use from there - this allows us to break the ongoing depndency and "bake in" the current version of teh remote module.
  3. Enable a widget to define additional static assets that should be shipped with the site at build time, e.g. PNG, SVGs, etc...
  4. Fully enable the AnyWidget Front End Model in the website, including named model instantiation - the goal is to enable multiple widgets to communicate. An acceptance test would be equivalent to the AnyWidget "Counter" example https://anywidget.dev/en/notebooks/counter/.

TODO: Looking for more extension ideas to suport additional use cases

Open Questions

  • The AnyWidget interface in python/jupyter allows for _esm and _css to be written inline in the directive, although here this seems less useful and it is better to promote using local files instead, e.g. my-widget.mjs
  • How to handle the "hardcopy" alternatives for a widget?

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions