/ concept-collection / jupyterlite-numbl-kernel
Sign in
concept-collection / jupyterlite-numbl-kernel
jupyterlite-numbl-kernel / README.md
125 lines · 5.8 KBCodeBlameHistory
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 1# jupyterlite-numbl-kernel
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 3Run [**numbl**](https://numbl.org) — numerical computing with **MATLAB
4syntax** — in [JupyterLite](https://jupyterlite.readthedocs.io/) notebooks,
5**entirely in the browser**. No server, no kernel process, nothing for the
6reader to install.
f44f6a3Rebrand numbl-first: this runs numbl (which uses MATLAB syntax)Jeremy Magland 8numbl is an open-source numerical-computing engine, written in TypeScript,
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 9that uses MATLAB syntax, so `.m` code runs unchanged. This kernel runs a numbl
10session in a Web Worker on the page: variables persist across cells, console
11output streams into the running cell, plots render as figures (including
12interactive 3-D), and `.m` files next to the notebook are part of the
13workspace (named functions, called from cells). Everything runs client-side.
15**Demo:** <https://concept-collection.github.io/jupyterlite-numbl-kernel/>
16(deployed from this repo via GitHub Pages)
18## Why
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 20A numbl notebook can be a static web page: hostable on GitHub Pages, shareable
21as a link, and runnable by anyone with a browser. Because numbl uses MATLAB
22syntax and needs no MATLAB/Octave install (or any server), the same `.m` code
23that would otherwise sit behind a licensed product just runs in the tab.
25## How it works
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 27Three small pieces, all in `src/`:
29- **Kernel** ([kernel.ts](src/kernel.ts)) implements JupyterLite's
30 `BaseKernel`. Before each cell runs, `.m` files in the notebook's directory
31 are synced into the numbl session; the cell then runs against the session's
32 persistent workspace (a Web Worker that numbl manages). Console output
33 streams back as `stream` messages, and plots are published as `display_data`
34 with the mime type `application/vnd.numbl.figure+json`.
35- **Figure renderer** ([mime.tsx](src/mime.tsx)) is a mime renderer for that
36 type: it replays the plot instructions and mounts numbl's React `FigureView`.
37 Outputs are plain JSON, so saved notebooks re-render wherever the extension
38 is installed.
39- **Registration** ([index.ts](src/index.ts)) registers the kernelspec.
41## Build a site with it
43```bash
44pip install jupyterlite-core jupyterlite-numbl-kernel
45jupyter lite build --contents my-notebooks --output-dir dist
80cd178Update numbl links and tidy copyJeremy Magland 46# dist/ is a static site; serve it anywhere
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 49`.m` files next to a notebook are synced into the session recursively, so
50MATLAB's folder-based `+namespace/`, `@class/`, and `private/` layouts work as
51expected.
53The `demo/` directory is the source of the demo site above — a numbered
54walkthrough of the language and the MATLAB object model (classes, namespaces,
55packages). [`.github/workflows/deploy.yml`](.github/workflows/deploy.yml)
56builds and deploys it to GitHub Pages.
58### Fresh content on redeploy (demo choice)
60JupyterLite caches notebooks in the browser (IndexedDB) and can keep serving
61stale copies from its service worker even after a redeploy. Because this is a
62demo, [`demo/jupyter-lite.json`](demo/jupyter-lite.json) uses in-memory
63storage and disables the service worker, so every reload re-seeds the latest
64deployed notebooks. The trade-off is that a visitor's edits last only for the
65session. For a real deployment where users keep their work, drop those
66settings and use JupyterLite's default persistent storage.
68### Cross-origin isolation (for interrupt and input)
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 70The Stop button and `input()` both rely on a `SharedArrayBuffer`, which
71browsers expose only on a **cross-origin-isolated** page (`COOP`/`COEP`
72headers). GitHub Pages can't set those headers, so the demo ships a small
73service worker, [`demo/coi-serviceworker.js`](demo/coi-serviceworker.js)
74(based on [coi-serviceworker](https://github.com/niccokunzmann/coi-serviceworker)),
75that synthesizes them client-side; [`demo/inject-coi.mjs`](demo/inject-coi.mjs)
76wires it into every generated page during the build. Without isolation,
77interrupt and `input()` degrade gracefully (see Limitations).
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 79## Limitations (proof of concept)
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 81- **Interrupt** is cooperative: the Stop button aborts the running cell at the
82 next loop iteration or function call, reports a `KeyboardInterrupt`, and
83 leaves earlier variables intact. It needs cross-origin isolation (above); on
84 a non-isolated page it's a no-op, and a tight loop with no calls (e.g.
85 `while true; x = x + 1; end`) has no checkpoint to abort at — both cases need
86 a kernel restart.
87- **`input()`** prompts in the notebook and blocks until you answer. It also
88 needs cross-origin isolation; without it, `input()` raises rather than
89 prompting.
90- **Figures are per-cell** (like inline matplotlib): `hold on` does not span
91 cells.
92- **Named functions go in `.m` files**, not cells (a numbl REPL limitation);
93 anonymous functions work in cells. See [`demo/content/fib.m`](demo/content/fib.m).
94- **`.m` sync is one-way**: deleting a file leaves its function defined until
95 the kernel restarts, and files written by cell code don't appear back in the
96 file browser.
97- **numbl is not MATLAB** — it covers a large, tested subset of the language
98 and toolboxes. See [numbl](https://numbl.org) for scope.
100## Development
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 102Requires Python ≥ 3.9, Node ≥ 20, and `numbl >= 0.4.16`.
104```bash
105python -m venv .venv && source .venv/bin/activate
106pip install "jupyterlab~=4.6.0" "jupyterlite-core==0.8.1"
108jlpm install
109jlpm build # tsc + labextension (dev)
110pip install -e . # editable install, registers the labextension
112# Build and serve the demo site locally
113pip install -r demo/requirements.txt
114jupyter lite build --lite-dir demo --contents content --output-dir demo/_output
cf2d698Add cooperative cell interrupt (Stop button)Jeremy Magland 115node demo/inject-coi.mjs demo/_output # cross-origin isolation, for interrupt
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 116python -m http.server -d demo/_output 8000 # then open http://localhost:8000
119`jlpm watch` rebuilds on change during development.
121## License
80cd178Update numbl links and tidy copyJeremy Magland 123Apache-2.0. Built on [numbl](https://numbl.org) and
9391828Simplify and tidy README; de-emphasize mipJeremy Magland 124[JupyterLite](https://github.com/jupyterlite/jupyterlite); scaffolded from the
125[jupyterlite/echo-kernel](https://github.com/jupyterlite/echo-kernel) template.
moveopenescclose