diff --git a/DOCKER.md b/DOCKER.md deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/README.md b/README.md index b34cd3bc346269f5290e21a0acf5480ee6765b28..0c2fcb7c8b91f30633f583e126e4d17bcea1d533 100644 --- a/README.md +++ b/README.md @@ -176,3 +176,7 @@ Mostly I copied files, but also: ### Running `.sh` files on Windows To run a `.sh` in Windows, make sure you have Git installed. If Windows still doesn't recognize the file as executable, right click it and select `Open With`, then click `Git for Windows`, and set it as the default too. + +### Thebe Lite + +Thebe Lite is used to allow interactive code within the notebook. For more information on its use, read the `Live Code` page in the `Cookbook` section. For technical information, read the [Thebe Lite readme](thebe_lite/THEBE_LITE.md). diff --git a/book/_toc.yml b/book/_toc.yml index 5f81724ff7242877aed1441e8771ff06d75d238d..3ffeda32f4fe00f4913bd42a78e02b994102f096 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -64,6 +64,7 @@ parts: sections: - file: cookbook/benchmarks/benchmark_aux_dont_execute.ipynb - file: cookbook/benchmarks/benchmark_tags_dont_execute.ipynb + - file: cookbook/benchmarks/benchmark_load_dont_execute.ipynb - file: cookbook/widgets_dont_execute.ipynb - caption: Old Material chapters: diff --git a/book/cookbook/benchmarks/benchmark_load_dont_execute.ipynb b/book/cookbook/benchmarks/benchmark_load_dont_execute.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..85375d87b582dbf11348c7007e9da66b095b3760 --- /dev/null +++ b/book/cookbook/benchmarks/benchmark_load_dont_execute.ipynb @@ -0,0 +1,57 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Benchmarks: loading messages\n", + "\n", + "This page includes benchmarks for the loading messages given during intialization." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-init" + ] + }, + "outputs": [], + "source": [ + "# Long init cell\n", + "sisyphus = 0\n", + "for i in range(100000000):\n", + " sisyphus += 1\n", + "print(sisyphus)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.6" + }, + "vscode": { + "interpreter": { + "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/book/cookbook/benchmarks/benchmark_tags_dont_execute.ipynb b/book/cookbook/benchmarks/benchmark_tags_dont_execute.ipynb index 24e2d2c147f0b48a5af137121ea698a640dcf63b..011a55dfccb6d3a01ac0ff51229ceebd8240796c 100644 --- a/book/cookbook/benchmarks/benchmark_tags_dont_execute.ipynb +++ b/book/cookbook/benchmarks/benchmark_tags_dont_execute.ipynb @@ -43,7 +43,7 @@ "execution_count": null, "metadata": { "tags": [ - "thebe-remove-input" + "thebe-remove-input-init" ] }, "outputs": [], @@ -57,7 +57,7 @@ "execution_count": 1, "metadata": { "tags": [ - "thebe-remove-input" + "thebe-remove-input-init" ] }, "outputs": [ diff --git a/book/cookbook/widgets_dont_execute.ipynb b/book/cookbook/widgets_dont_execute.ipynb index f55ae6b41edf91317cfedcddfdbb312d378d6854..90b734122181a85f5d8616f0d0eb92c8617c960e 100644 --- a/book/cookbook/widgets_dont_execute.ipynb +++ b/book/cookbook/widgets_dont_execute.ipynb @@ -45,7 +45,7 @@ "execution_count": null, "metadata": { "tags": [ - "thebe-remove-input" + "thebe-remove-input-init" ] }, "outputs": [], @@ -169,7 +169,7 @@ "execution_count": null, "metadata": { "tags": [ - "thebe-remove-input" + "thebe-remove-input-init" ] }, "outputs": [], diff --git a/build-book.sh b/build-book.sh index 6e701a06d7950ec68623afed10d297159b98ccef..dc02204259afce1ae776a46f6badd21498b7931d 100755 --- a/build-book.sh +++ b/build-book.sh @@ -8,7 +8,8 @@ set -euo pipefail jupyter-book build book # Note: the structure of thebe_lite mimicks where thing are needed in the html folder -cp book/thebe_lite/* book/_build/html/ -r +cp thebe_lite/* book/_build/html/ -r +rm book/_build/html/THEBE_LITE.md # Copy all non notebook, markdown or build files into the build for local access in pyodide etc. # The commands do as follows: @@ -19,7 +20,7 @@ cp book/thebe_lite/* book/_build/html/ -r # 5. grep: finds a file's parent's path by matching against the section of the string ending in a '/' # 6. mkdir: makes all the parent directories, -p will do so recrusively # 7. cp: finally copies all files from the /book folder to /book/_build/html -find book/ -type f | grep -v "^book/_.*\|.*\.\(md\|ipynb\)\|thebe_lite" | cut -c 6- | xargs -i sh -c 'echo "book/_build/html/{}" | grep -o "^.*/" | xargs -d "\n" mkdir -p; cp book/"{}" book/_build/html/"{}"' +find book/ -type f | grep -v "^book/_.*\|.*\.\(md\|ipynb\)" | cut -c 6- | xargs -i sh -c 'echo "book/_build/html/{}" | grep -o "^.*/" | xargs -d "\n" mkdir -p; cp book/"{}" book/_build/html/"{}"' # Check whether python has the alias 'python' or 'python3' if command -v python3 > /dev/null 2>&1 diff --git a/book/thebe_lite/106.index.js b/thebe_lite/106.index.js similarity index 100% rename from book/thebe_lite/106.index.js rename to thebe_lite/106.index.js diff --git a/book/thebe_lite/106.index.js.map b/thebe_lite/106.index.js.map similarity index 100% rename from book/thebe_lite/106.index.js.map rename to thebe_lite/106.index.js.map diff --git a/book/thebe_lite/328.thebe-lite.min.js b/thebe_lite/328.thebe-lite.min.js similarity index 100% rename from book/thebe_lite/328.thebe-lite.min.js rename to thebe_lite/328.thebe-lite.min.js diff --git a/book/thebe_lite/328.thebe-lite.min.js.map b/thebe_lite/328.thebe-lite.min.js.map similarity index 100% rename from book/thebe_lite/328.thebe-lite.min.js.map rename to thebe_lite/328.thebe-lite.min.js.map diff --git a/book/thebe_lite/330.index.js b/thebe_lite/330.index.js similarity index 100% rename from book/thebe_lite/330.index.js rename to thebe_lite/330.index.js diff --git a/book/thebe_lite/330.index.js.map b/thebe_lite/330.index.js.map similarity index 100% rename from book/thebe_lite/330.index.js.map rename to thebe_lite/330.index.js.map diff --git a/book/thebe_lite/562.thebe-lite.min.js b/thebe_lite/562.thebe-lite.min.js similarity index 100% rename from book/thebe_lite/562.thebe-lite.min.js rename to thebe_lite/562.thebe-lite.min.js diff --git a/book/thebe_lite/562.thebe-lite.min.js.map b/thebe_lite/562.thebe-lite.min.js.map similarity index 100% rename from book/thebe_lite/562.thebe-lite.min.js.map rename to thebe_lite/562.thebe-lite.min.js.map diff --git a/book/thebe_lite/609.thebe-lite.min.js b/thebe_lite/609.thebe-lite.min.js similarity index 100% rename from book/thebe_lite/609.thebe-lite.min.js rename to thebe_lite/609.thebe-lite.min.js diff --git a/book/thebe_lite/609.thebe-lite.min.js.map b/thebe_lite/609.thebe-lite.min.js.map similarity index 100% rename from book/thebe_lite/609.thebe-lite.min.js.map rename to thebe_lite/609.thebe-lite.min.js.map diff --git a/book/thebe_lite/686.thebe-lite.min.js b/thebe_lite/686.thebe-lite.min.js similarity index 100% rename from book/thebe_lite/686.thebe-lite.min.js rename to thebe_lite/686.thebe-lite.min.js diff --git a/book/thebe_lite/686.thebe-lite.min.js.map b/thebe_lite/686.thebe-lite.min.js.map similarity index 100% rename from book/thebe_lite/686.thebe-lite.min.js.map rename to thebe_lite/686.thebe-lite.min.js.map diff --git a/THEBE_LITE.md b/thebe_lite/THEBE_LITE.md similarity index 82% rename from THEBE_LITE.md rename to thebe_lite/THEBE_LITE.md index 23df24566aa24b0365743f7502e500a39e9533f4..33d976719d4bc2562a3a4eb86f6a76723a7c94da 100644 --- a/THEBE_LITE.md +++ b/thebe_lite/THEBE_LITE.md @@ -16,6 +16,7 @@ The extra features provided by this implementation of Thebe Lite: 2. Ability to load "local" files transparently 3. Ability to add/delete scratch cells 4. Clear button for cell outputs +5. Custom cell tags for removing input, and proper handling of existing cell tags. ## Updating Thebe Lite @@ -41,18 +42,26 @@ await thebelab.session.kernel.requestExecute({ }')")`, ``` -Adds support for local file access. This line in specific also shouldn't need to be touched. Look at the `override_pyodide_lookup` function instead to change this behaviour. +Adds support for local file access. This line in specific also shouldn't need to be touched. Look at the `override_pyodide_lookup` function instead to change this behaviour. Currently files are lazily loaded from the server, expect python files (to support imports). Loading in python files also requires that directory listings are available (and compatible with the expected format used by NGINX). -The `configureThebe` function has been modified to support more useful status messages, but further work could be done. It would be nice to only display a ready message when Pyodide is done initializing, but I couldn't figure out a nice way to find this information. One could potentially try to execute something in the kernel to guage the status. +```js +await thebelab.session.kernel.requestExecute({ + code: `import ipykernel; ipykernel.version_info = (0,0)`, +}); +``` + +Fixes some issues with Pyodide and ipywidgets. Hopefully it can be removed in the future. `finalizeCodeCells` adds the "add cell", "delete cell" and "clear" buttons to the Thebe controls. Adding a cell is the most interesting part. Thebe does not actually keep track of cells in the book, but instead keeps a "notebook" which has [ThebeCell](https://github.com/executablebooks/thebe/blob/main/packages/core/src/cell.ts)s in it. These cells have an `area` associated with them that keeps track of events in the cell and updates the appropriate HTML. Due to this organization, if you mess with cells in Thebe, it's important to synchronize the notebook properly too. +Some special tags have also been defined, the logic for which is spread between `consumeSpecialTags` (on load) and `setupSpecialTaggedElements` (once Thebe is initialized). + ## code.css Contains CSS for dark mode and personal styling preferences, feel free to play with it. ## Contact -In case of questions, feel free to contact me! +In case of questions, please contact me! - Email: M.Guichard@student.tudelft.nl diff --git a/book/thebe_lite/_static/code.css b/thebe_lite/_static/code.css similarity index 87% rename from book/thebe_lite/_static/code.css rename to thebe_lite/_static/code.css index 5a2ec200259bad2ace2d5f28290d0f6a3978a678..ef17b2b3255e9f6c30034b7fe66dccb20b1b4de0 100644 --- a/book/thebe_lite/_static/code.css +++ b/thebe_lite/_static/code.css @@ -18,8 +18,8 @@ color: var(--pst-color-text-base); } -.jp-OutputArea { - padding: 5px 0px 5px 0px; +.cell_output .jp-OutputArea-output pre { + border: var(--mystnb-source-border-width) var(--mystnb-source-border-color) solid; } .thebe-controls { @@ -53,6 +53,24 @@ height: 20px; } +html[data-theme=dark] .tag_hide-input summary { + background: var(--pst-color-surface) !important; +} + +.cell_output { + margin-top: 0.2em !important; +} + +.cell_output .output.stream { + margin-top: 0.2em !important; + border: var(--mystnb-source-border-width) var(--mystnb-source-border-color) solid !important; +} + +div.container.cell_output { + padding-left: 0; + margin-bottom: 1em; +} + /* These rules are used for the dark mode code styling */ /* Values taken from: https://codemirror.net/5/demo/theme.html#abcdef, with some minor tweaks to comments and gutter */ html[data-theme=dark] div.CodeMirror-selected { background: #515151; } diff --git a/book/thebe_lite/_static/sphinx-thebe.js b/thebe_lite/_static/sphinx-thebe.js similarity index 76% rename from book/thebe_lite/_static/sphinx-thebe.js rename to thebe_lite/_static/sphinx-thebe.js index e14bc3d99c93eaf7e3f3cd948956734e14a7a2ac..4b9ff23b3a9511ebc4fbf669b84fddb7ebb3de9b 100644 --- a/book/thebe_lite/_static/sphinx-thebe.js +++ b/thebe_lite/_static/sphinx-thebe.js @@ -65,6 +65,13 @@ function addToThebeControls(cell, element) { controls.insertBefore(element, controls.lastChild); } +function getNotebookCellOfCodeCell(codeCell) { + const cellId = codeCell + .querySelector("[data-thebe-id]") // Once rendered a cell has a data-thebe-id attached to it + .getAttribute("data-thebe-id"); // This corresponds to the id in the notebook + return thebe.notebook.cells.find((cell) => cell.id === cellId); +} + function finalizeCodeCells(cells) { const createButton = (classList, title, text) => { const button = document.createElement("button"); @@ -90,12 +97,7 @@ function finalizeCodeCells(cells) { addToThebeControls(codeCell, clear); clear.onclick = () => { - const cellId = codeCell - .querySelector("[data-thebe-id]") // Once rendered a cell has a data-thebe-id attached to it - .getAttribute("data-thebe-id"); // This corresponds to the id in the notebook - const notebookCell = thebe.notebook.cells.find( - (cell) => cell.id === cellId - ); + const notebookCell = getNotebookCellOfCodeCell(codeCell); notebookCell.clear(); }; @@ -141,6 +143,14 @@ function finalizeCodeCells(cells) { }); } +function updateThebeButtonStatus(msg, loading = true) { + const spinner = + '<div class="spinner"><div class="rect1"></div><div class="rect2"></div><div class="rect3"></div><div class="rect4"></div></div>'; + $(".thebe-launch-button ").html( + (loading ? spinner : "") + `<span class='status'>${msg}</span>` + ); +} + /** * Add attributes to Thebe blocks to initialize thebe properly */ @@ -153,59 +163,26 @@ var configureThebe = () => { thebe_config = thebeLiteConfig; // Update thebe buttons with loading message - $(".thebe-launch-button").each((ii, button) => { - button.innerHTML = ` - <div class="spinner"> - <div class="rect1"></div> - <div class="rect2"></div> - <div class="rect3"></div> - <div class="rect4"></div> - </div> - <span class="loading-text"></span>`; - }); + updateThebeButtonStatus("Initializing Thebe"); // Set thebe event hooks - var thebeStatus; thebelab.on("status", function (evt, data) { console.log("Status changed:", data.status, data.message); - $(".thebe-launch-button ") - .removeClass("thebe-status-" + thebeStatus) - .addClass("thebe-status-" + data.status) - .find(".loading-text") - .html( - "<span class='launch_msg'>Launching Pyodide kernel: </span><span class='status'>" + - data.status + - "</span>" - ); - - // Now update our thebe status - thebeStatus = data.status; - - // Find any cells with an initialization tag and ask thebe to run them when ready - if (data.status === "ready") { - $(".thebe-launch-button").each((ii, button) => { - button.innerHTML = `Python interaction ready!`; - }); + updateThebeButtonStatus( + `<span class='launch_msg'>Launching Pyodide kernel: </span><span class='status'>` + + data.status + + "</span>" + ); - const codeCells = document.querySelectorAll(thebe_selector); - finalizeCodeCells(codeCells); + if (data.status === "attached") { + updateThebeButtonStatus(`Waiting for packages to load...`); - thebelab.on("status", () => {}); + thebelab.events.listeners.status.clear(); // Remove further status message handling } }); }; -var runInitCells = () => { - var thebeInitCells = document.querySelectorAll( - ".thebe-init, .tag_thebe-init" - ); - thebeInitCells.forEach((cell) => { - console.log("Initializing Thebe with cell: " + cell.id); - cell.querySelector(".thebe-run-button").click(); - }); -}; - /** * Update the page DOM to use Thebe elements */ @@ -393,17 +370,46 @@ function override_pyodide_lookup(fs, server_path) { fs.lookupPath = new_lookup; } +async function runInitCells() { + var thebeInitCells = document.querySelectorAll( + ".thebe-init, .tag_thebe-init" + ); + for (const cell of thebeInitCells) { + console.log("Initializing Thebe with cell: " + cell.id); + const notebookCell = getNotebookCellOfCodeCell(cell); + + // Emulate clicking the run button, with more information about execution + thebe.setButtonsBusy(notebookCell.id); + await notebookCell.execute(); + thebe.clearButtonsBusy(notebookCell.id); + } +} + +function wrapNakedOutput(element) { + const wrapper = document.createElement("div"); + wrapper.classList.add("cell_output", "container"); + wrapper.appendChild(element); + return wrapper; +} + function setupSpecialTaggedElements() { for (const taggedElement of window.specialTaggedElements) { switch (taggedElement.tag) { - case "thebe-remove-input": { + case "thebe-remove-input-init": { const { newCellInfo, newNotebookCell } = setupNewCell( undefined, undefined, taggedElement.code ); - newNotebookCell.execute(); - taggedElement.placeholder.before(newNotebookCell.area.node); + + const wrappedOutput = wrapNakedOutput(newNotebookCell.area.node); + // The 4 following lines are an ugly hack to make sure we preserve init order + // Maybe improving runInitCells could circumvent this + wrappedOutput.classList.add("tag_thebe-init"); + const idDiv = document.createElement("div"); + idDiv.setAttribute("data-thebe-id", newNotebookCell.id); + wrappedOutput.appendChild(idDiv); + taggedElement.placeholder.before(wrappedOutput); break; } default: { @@ -419,58 +425,54 @@ function moveHideInputOutput() { const taggedCells = document.querySelectorAll(".tag_hide-input"); for (const cell of taggedCells) { const outputArea = cell.querySelector(".jp-OutputArea"); - cell.after(outputArea); + cell.appendChild(wrapNakedOutput(outputArea)); } } var initThebe = async () => { - // Load thebe dynamically if it's not already loaded - if (typeof thebelab === "undefined") { - console.log("[sphinx-thebe]: Loading thebe..."); - $(".thebe-launch-button ").css("display", "none"); - - // Provides nice things like a running animation and some padding - { - await loadStyleAsync("/thebe.css"); - await loadStyleAsync("/_static/code.css"); - } - - $(".thebe-launch-button ").css("display", "block"); - $(".thebe-launch-button ").text("Loading thebe..."); - - await loadScriptAsync("/thebe-lite.min.js"); - await loadScriptAsync("/index.js"); - - // Runs once the script has finished loading - console.log("[sphinx-thebe]: Finished loading thebe..."); - configureThebe(); - modifyDOMForThebe(); - await thebelab.bootstrap(thebeLiteConfig); - - // Runs override_pyodide_lookup on the web worker - // We can't access the web worker directly, but we can execute code on the current kernel - // Since Pyodide has access to its javascript enviroment through the js package, we do the following steps: - // 1. Load the js and pyodide_js package - // 2. Set the fs variable in JS to our pyodide_js, this gives access to pyodide in JS - // 3. Eval the string og the override_pyodide_lookup function in JS, this brings it into scope - // 4. Execute the override_pyodide_lookup function in JS, and bake in the relative path from root in the book (the home) - // NOTE: All functions used in override_pyodide_lookup should be nested inside it, since the web worker cannot access functions in this script - await thebelab.session.kernel.requestExecute({ - code: `import js; import pyodide_js; js.fs = pyodide_js.FS; js.eval("""${override_pyodide_lookup.toString()}"""); js.eval(f"override_pyodide_lookup(fs, '${ - location.pathname.split("/").slice(0, -1).join("/") + "/" - }')")`, - }); - - // Fix for issues with ipywidgets in Thebe - await thebelab.session.kernel.requestExecute({ - code: `import ipykernel; ipykernel.version_info = (0,0)`, - }); - moveHideInputOutput(); - runInitCells(); - setupSpecialTaggedElements(); - } else { - console.log("[sphinx-thebe]: thebe already loaded..."); - } + // Remove Rocket now that we're initializing + document.querySelector(".dropdown-launch-buttons").remove(); + + console.log("[sphinx-thebe]: Loading thebe..."); + $(".thebe-launch-button ").text("Loading thebe..."); + + await loadScriptAsync("/thebe-lite.min.js"); + await loadScriptAsync("/index.js"); + + // Runs once the script has finished loading + console.log("[sphinx-thebe]: Finished loading thebe..."); + configureThebe(); + modifyDOMForThebe(); + await thebelab.bootstrap(thebeLiteConfig); + + finalizeCodeCells(document.querySelectorAll(thebe_selector)); + + // Runs override_pyodide_lookup on the web worker + // We can't access the web worker directly, but we can execute code on the current kernel + // Since Pyodide has access to its javascript enviroment through the js package, we do the following steps: + // 1. Load the js and pyodide_js package + // 2. Set the fs variable in JS to our pyodide_js, this gives access to pyodide in JS + // 3. Eval the string og the override_pyodide_lookup function in JS, this brings it into scope + // 4. Execute the override_pyodide_lookup function in JS, and bake in the relative path from root in the book (the home) + // NOTE: All functions used in override_pyodide_lookup should be nested inside it, since the web worker cannot access functions in this script + await thebelab.session.kernel.requestExecute({ + code: `import js; import pyodide_js; js.fs = pyodide_js.FS; js.eval("""${override_pyodide_lookup.toString()}"""); js.eval(f"override_pyodide_lookup(fs, '${ + location.pathname.split("/").slice(0, -1).join("/") + "/" + }')")`, + }).done; + + // Fix for issues with ipywidgets in Thebe + await thebelab.session.kernel.requestExecute({ + code: `import ipykernel; ipykernel.version_info = (0,0)`, + }).done; + updateThebeButtonStatus("Running pre-intialized cells..."); + setupSpecialTaggedElements(); + + await runInitCells(); + + updateThebeButtonStatus("Python interaction ready!", false); + + moveHideInputOutput(); }; // Helper function to munge the language name @@ -488,7 +490,7 @@ function handleThebeRemoveInputTag(element) { placeholder.style.display = "none"; window.specialTaggedElements.push({ - tag: "thebe-remove-input", + tag: "thebe-remove-input-init", placeholder: placeholder, code: element.querySelector("pre").textContent?.trim() ?? "", }); @@ -502,10 +504,10 @@ function handleThebeRemoveInputTag(element) { } // Deal with custom-defined tags to properly prepare Thebe and DOM -// Current special tags: thebe-remove-input +// Current special tags: thebe-remove-input-init function consumeSpecialTags() { const specialTagsInfo = [ - { tag: "thebe-remove-input", handler: handleThebeRemoveInputTag }, + { tag: "thebe-remove-input-init", handler: handleThebeRemoveInputTag }, ]; window.specialTaggedElements = []; @@ -526,3 +528,6 @@ if (document.readyState !== "loading") { consumeSpecialTags(); }); } + +loadStyleAsync("/thebe.css"); +loadStyleAsync("/_static/code.css"); diff --git a/book/thebe_lite/api/contents/all.json b/thebe_lite/api/contents/all.json similarity index 100% rename from book/thebe_lite/api/contents/all.json rename to thebe_lite/api/contents/all.json diff --git a/book/thebe_lite/index.js b/thebe_lite/index.js similarity index 100% rename from book/thebe_lite/index.js rename to thebe_lite/index.js diff --git a/book/thebe_lite/index.js.map b/thebe_lite/index.js.map similarity index 100% rename from book/thebe_lite/index.js.map rename to thebe_lite/index.js.map diff --git a/book/thebe_lite/pypi/all.json b/thebe_lite/pypi/all.json similarity index 100% rename from book/thebe_lite/pypi/all.json rename to thebe_lite/pypi/all.json diff --git a/book/thebe_lite/pypi/ipykernel-6.9.2-py3-none-any.whl b/thebe_lite/pypi/ipykernel-6.9.2-py3-none-any.whl similarity index 100% rename from book/thebe_lite/pypi/ipykernel-6.9.2-py3-none-any.whl rename to thebe_lite/pypi/ipykernel-6.9.2-py3-none-any.whl diff --git a/book/thebe_lite/pypi/piplite-0.0.8-py3-none-any.whl b/thebe_lite/pypi/piplite-0.0.8-py3-none-any.whl similarity index 100% rename from book/thebe_lite/pypi/piplite-0.0.8-py3-none-any.whl rename to thebe_lite/pypi/piplite-0.0.8-py3-none-any.whl diff --git a/book/thebe_lite/pypi/pyodide_kernel-0.0.8-py3-none-any.whl b/thebe_lite/pypi/pyodide_kernel-0.0.8-py3-none-any.whl similarity index 100% rename from book/thebe_lite/pypi/pyodide_kernel-0.0.8-py3-none-any.whl rename to thebe_lite/pypi/pyodide_kernel-0.0.8-py3-none-any.whl diff --git a/book/thebe_lite/pypi/widgetsnbextension-3.6.4-py3-none-any.whl b/thebe_lite/pypi/widgetsnbextension-3.6.4-py3-none-any.whl similarity index 100% rename from book/thebe_lite/pypi/widgetsnbextension-3.6.4-py3-none-any.whl rename to thebe_lite/pypi/widgetsnbextension-3.6.4-py3-none-any.whl diff --git a/book/thebe_lite/pypi/widgetsnbextension-4.0.7-py3-none-any.whl b/thebe_lite/pypi/widgetsnbextension-4.0.7-py3-none-any.whl similarity index 100% rename from book/thebe_lite/pypi/widgetsnbextension-4.0.7-py3-none-any.whl rename to thebe_lite/pypi/widgetsnbextension-4.0.7-py3-none-any.whl diff --git a/book/thebe_lite/service-worker-dddfe83.js b/thebe_lite/service-worker-dddfe83.js similarity index 100% rename from book/thebe_lite/service-worker-dddfe83.js rename to thebe_lite/service-worker-dddfe83.js diff --git a/book/thebe_lite/thebe-lite.min.js b/thebe_lite/thebe-lite.min.js similarity index 100% rename from book/thebe_lite/thebe-lite.min.js rename to thebe_lite/thebe-lite.min.js diff --git a/book/thebe_lite/thebe-lite.min.js.map b/thebe_lite/thebe-lite.min.js.map similarity index 100% rename from book/thebe_lite/thebe-lite.min.js.map rename to thebe_lite/thebe-lite.min.js.map diff --git a/book/thebe_lite/thebe.css b/thebe_lite/thebe.css similarity index 100% rename from book/thebe_lite/thebe.css rename to thebe_lite/thebe.css diff --git a/book/thebe_lite/types/activate.d.ts b/thebe_lite/types/activate.d.ts similarity index 100% rename from book/thebe_lite/types/activate.d.ts rename to thebe_lite/types/activate.d.ts diff --git a/book/thebe_lite/types/codemirror.d.ts b/thebe_lite/types/codemirror.d.ts similarity index 100% rename from book/thebe_lite/types/codemirror.d.ts rename to thebe_lite/types/codemirror.d.ts diff --git a/book/thebe_lite/types/index.d.ts b/thebe_lite/types/index.d.ts similarity index 100% rename from book/thebe_lite/types/index.d.ts rename to thebe_lite/types/index.d.ts diff --git a/book/thebe_lite/types/options.d.ts b/thebe_lite/types/options.d.ts similarity index 100% rename from book/thebe_lite/types/options.d.ts rename to thebe_lite/types/options.d.ts diff --git a/book/thebe_lite/types/render.d.ts b/thebe_lite/types/render.d.ts similarity index 100% rename from book/thebe_lite/types/render.d.ts rename to thebe_lite/types/render.d.ts diff --git a/book/thebe_lite/types/status.d.ts b/thebe_lite/types/status.d.ts similarity index 100% rename from book/thebe_lite/types/status.d.ts rename to thebe_lite/types/status.d.ts diff --git a/book/thebe_lite/types/thebe.d.ts b/thebe_lite/types/thebe.d.ts similarity index 100% rename from book/thebe_lite/types/thebe.d.ts rename to thebe_lite/types/thebe.d.ts diff --git a/book/thebe_lite/types/types.d.ts b/thebe_lite/types/types.d.ts similarity index 100% rename from book/thebe_lite/types/types.d.ts rename to thebe_lite/types/types.d.ts diff --git a/book/thebe_lite/types/utils.d.ts b/thebe_lite/types/utils.d.ts similarity index 100% rename from book/thebe_lite/types/utils.d.ts rename to thebe_lite/types/utils.d.ts