diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..be3ac71 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "printWidth": 120 +} \ No newline at end of file diff --git a/README.md b/README.md index 8d1a19a..e4adc67 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,27 @@ npm run build http-server --port 8080 --cors ``` +To connect to a local Jupyter Kernel Gateway, run: + +```shell +KG_ALLOW_METHODS="*" \ +jupyter kernelgateway \ + --KernelGatewayApp.allow_origin="https://unpkg.com" \ + --KernelGatewayApp.allow_headers="authorization,content-type,x-xsrftoken" \ + --JupyterWebsocketPersonality.list_kernels=True +``` + + +## Development + +``` +npm run start +``` + +And in a different tab you can serve the demo: + +``` +http-server --cors +``` + +Note that the demo runs in a properly sandboxes iframe, which means that you need to do a full reload to see changes. \ No newline at end of file diff --git a/demo/demo.js b/demo/demo.js index c63952d..02f803c 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -1,6 +1,6 @@ -import {convertJupyterStringToStarboardString, convertStarboardStringToJupyterString} from "https://cdn.skypack.dev/jupystar"; -import {StarboardNotebookIFrame} from "https://cdn.skypack.dev/starboard-wrap@0.2.5"; -import {upgradeNBGraderCells, preprocessGraderCellsForJupystar, prependPluginLoaderCell} from "../dist/converter.js"; +import { convertJupyterStringToStarboardString, convertStarboardStringToJupyterString } from "https://cdn.skypack.dev/jupystar"; +import { StarboardEmbed } from "https://cdn.skypack.dev/starboard-wrap@0.3.1"; +import { upgradeNBGraderCells, preprocessGraderCellsForJupystar, prependPluginLoaderCell } from "../dist/converter.js"; let currentStarboardNotebookContent = ` # %%--- [javascript] @@ -161,19 +161,19 @@ function readFileAsText(file) { resolve(event.target.result); }) reader.readAsText(file); - }) + }) } function downloadIpynbAsFile() { var element = document.createElement('a'); element.setAttribute("href", 'data:text/plain;charset=utf-8,' + encodeURIComponent(currentJupyterNotebookContent)); element.setAttribute('download', "starboard-grader-output.ipynb"); - + element.style.display = 'none'; document.body.appendChild(element); - + element.click(); - + document.body.removeChild(element); } @@ -188,11 +188,11 @@ function createNotebook(content) { const href = window.location.href; const baseUrl = href.substring(0, href.lastIndexOf('/')) + "/"; - const el = new StarboardNotebookIFrame({ + const el = new StarboardEmbed({ // TODO: we should not need to prepend this loader cell like this, starboard-notebook doesn't // have a clean way to load plugins at runtime level yet, coming soon! notebookContent: prependPluginLoaderCell(content), - src: "https://unpkg.com/starboard-notebook@0.8.10/dist/index.html", + src: "https://unpkg.com/starboard-notebook@0.9.3/dist/index.html", // src: "http://localhost:9001/index.html", baseUrl: baseUrl, @@ -204,7 +204,6 @@ function createNotebook(content) { updateContent(payload.content); } }); - el.style.width = "100%"; mount.appendChild(el); } diff --git a/package-lock.json b/package-lock.json index ab7881c..8a7d0ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@illumidesk/starboard-nbgrader", - "version": "0.1.3", + "version": "0.1.6", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -36,25 +36,32 @@ } }, "@babel/parser": { - "version": "7.13.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.16.tgz", - "integrity": "sha512-6bAg36mCwuqLO0hbR+z7PHuqWiCeP7Dzg73OpQwsAB1Eb8HnGEz5xYBzCfbu+YjoaJsJs+qheDxVAuqbt3ILEw==" + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.2.tgz", + "integrity": "sha512-IoVDIHpsgE/fu7eXBeRWt8zLbDrSvD7H1gpomOkPpBoEN8KCruCqSDdqo8dddwQQrui30KSvQBaMUOJiuFu6QQ==" }, "@babel/runtime": { - "version": "7.13.17", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.17.tgz", - "integrity": "sha512-NCdgJEelPTSh+FEFylhnP1ylq848l1z9t9N0j1Lfbcw0+KXGjsTvUmkxy+voLLXB5SOKMbLLx4jxYliGrYQseA==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", + "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/types": { - "version": "7.13.17", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.17.tgz", - "integrity": "sha512-RawydLgxbOPDlTLJNtoIypwdmAy//uQIzlKt2+iBiJaRlVuI6QLUxVAyWGNfOzp8Yu4L4lLIacoCyTNtpb4wiA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz", + "integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==", "requires": { - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-validator-identifier": "^7.14.0", "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==" + } } }, "@benrbray/prosemirror-math": { @@ -62,6 +69,64 @@ "resolved": "https://registry.npmjs.org/@benrbray/prosemirror-math/-/prosemirror-math-0.1.4.tgz", "integrity": "sha512-Mlr9rChTD7wWmd5rSjjAL+OPWsHK6RlO+bprf0vrVCQhmmBTA1S8ZzRKPx5TymmtmvViVytKOk8vBXjg7EwbFg==" }, + "@blueprintjs/core": { + "version": "3.44.2", + "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.44.2.tgz", + "integrity": "sha512-rxw0KU0Trdnf5HoILyWrEYpfubC1+VyfpbqcD4pG3iA79oGfo1q5x4S16YTeZpVXRm8VK3TBob4RDRXDd+/4PQ==", + "requires": { + "@blueprintjs/icons": "^3.26.0", + "@types/dom4": "^2.0.1", + "classnames": "^2.2", + "dom4": "^2.1.5", + "normalize.css": "^8.0.1", + "popper.js": "^1.16.1", + "react-lifecycles-compat": "^3.0.4", + "react-popper": "^1.3.7", + "react-transition-group": "^2.9.0", + "resize-observer-polyfill": "^1.5.1", + "tslib": "~1.13.0" + }, + "dependencies": { + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + } + } + }, + "@blueprintjs/icons": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.26.0.tgz", + "integrity": "sha512-1+yhYH1Fjj5qGx8drZUL2L1R42MiN0WVHTTKYqGEV9TAzhvFHCSZgALD7WNQa+FEibw/8B4U+79IRgUPJNEjow==", + "requires": { + "classnames": "^2.2", + "tslib": "~1.13.0" + }, + "dependencies": { + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + } + } + }, + "@blueprintjs/select": { + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@blueprintjs/select/-/select-3.16.2.tgz", + "integrity": "sha512-/wcQTVwQNqesmi7ag/BFjBMla64HkwyvPRfYK0INwaIW08itjoATflAvw5QYRqqk6FeZ/OwGUOwoKS8oe5goDg==", + "requires": { + "@blueprintjs/core": "^3.44.2", + "classnames": "^2.2", + "tslib": "~1.13.0" + }, + "dependencies": { + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + } + } + }, "@codemirror/next": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/@codemirror/next/-/next-0.16.0.tgz", @@ -193,17 +258,488 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, + "@fortawesome/fontawesome-free": { + "version": "5.15.3", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.3.tgz", + "integrity": "sha512-rFnSUN/QOtnOAgqFRooTA3H57JLDm0QEG/jPdk+tLQNL/eWd+Aok8g3qCI+Q1xuDPWpGW/i9JySpJVsq8Q0s9w==" + }, "@github/mini-throttle": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@github/mini-throttle/-/mini-throttle-2.1.0.tgz", "integrity": "sha512-iEeR2OdVCPkdIPUszL8gJnKNu4MR8ANh7y0u/LPyaatYezgaWxUZEzhFntloqQq+HE6MZkFy+cl+xzCNuljOdw==" }, + "@hypnosphi/create-react-context": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz", + "integrity": "sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A==", + "requires": { + "gud": "^1.0.0", + "warning": "^4.0.3" + } + }, "@iktakahiro/markdown-it-katex": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@iktakahiro/markdown-it-katex/-/markdown-it-katex-4.0.1.tgz", "integrity": "sha512-kGFooO7fIOgY34PSG8ZNVsUlKhhNoqhzW2kq94TNGa8COzh73PO4KsEoPOsQVG1mEAe8tg7GqG0FoVao0aMHaw==", "requires": { "katex": "^0.12.0" + }, + "dependencies": { + "katex": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.12.0.tgz", + "integrity": "sha512-y+8btoc/CK70XqcHqjxiGWBOeIL8upbS0peTPXTvgrh21n1RiWWcIpSWM+4uXq+IAgNh9YYQWdc7LVDPDAEEAg==", + "requires": { + "commander": "^2.19.0" + } + } + } + }, + "@jupyterlab/application": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@jupyterlab/application/-/application-3.0.10.tgz", + "integrity": "sha512-ub4g8mu76gR/3uCa8jNVD4fqztLaDxypbIjl/xXDk1RRcb0Z1xyOW5U0MQzvYrPLYTjlPKo8BAkaO/ps+Mj1ng==", + "requires": { + "@fortawesome/fontawesome-free": "^5.12.0", + "@jupyterlab/apputils": "^3.0.8", + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/docregistry": "^3.0.10", + "@jupyterlab/rendermime": "^3.0.9", + "@jupyterlab/rendermime-interfaces": "^3.0.8", + "@jupyterlab/services": "^6.0.8", + "@jupyterlab/statedb": "^3.0.5", + "@jupyterlab/translation": "^3.0.8", + "@jupyterlab/ui-components": "^3.0.7", + "@lumino/algorithm": "^1.3.3", + "@lumino/application": "^1.13.1", + "@lumino/commands": "^1.12.0", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/messaging": "^1.4.3", + "@lumino/polling": "^1.3.3", + "@lumino/properties": "^1.2.3", + "@lumino/signaling": "^1.4.3", + "@lumino/widgets": "^1.16.1" + } + }, + "@jupyterlab/apputils": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jupyterlab/apputils/-/apputils-3.0.8.tgz", + "integrity": "sha512-s5B9+JlFZ6fylttx1YVD6+/ADbv2cIP9e82xNeqpak8/FRcZfnZ+JBCGjx7TA0pRUxTF4VjYrKJMobXxlGIC1A==", + "requires": { + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/services": "^6.0.8", + "@jupyterlab/settingregistry": "^3.0.5", + "@jupyterlab/statedb": "^3.0.5", + "@jupyterlab/translation": "^3.0.8", + "@jupyterlab/ui-components": "^3.0.7", + "@lumino/algorithm": "^1.3.3", + "@lumino/commands": "^1.12.0", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/domutils": "^1.2.3", + "@lumino/messaging": "^1.4.3", + "@lumino/properties": "^1.2.3", + "@lumino/signaling": "^1.4.3", + "@lumino/virtualdom": "^1.8.0", + "@lumino/widgets": "^1.16.1", + "@types/react": "^17.0.0", + "buffer": "^5.6.0", + "react": "^17.0.1", + "react-dom": "^17.0.1", + "sanitize-html": "~2.3.3", + "url": "^0.11.0" + } + }, + "@jupyterlab/codeeditor": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jupyterlab/codeeditor/-/codeeditor-3.0.8.tgz", + "integrity": "sha512-ipQUu7a4GPyzN7mmYCi1rm85FVSIDbTPJp/OJXMPQdaQxOZ/wnzBj3iVxpYQMlPe2LCVXsRwmlHCRV0gNSWRLA==", + "requires": { + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/nbformat": "^3.0.5", + "@jupyterlab/observables": "^4.0.5", + "@jupyterlab/translation": "^3.0.8", + "@jupyterlab/ui-components": "^3.0.7", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/dragdrop": "^1.7.1", + "@lumino/messaging": "^1.4.3", + "@lumino/signaling": "^1.4.3", + "@lumino/widgets": "^1.16.1" + } + }, + "@jupyterlab/codemirror": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jupyterlab/codemirror/-/codemirror-3.0.8.tgz", + "integrity": "sha512-yF8Azb/U4nvOK73lH9MsBXlEOKzgxw7yp6RjI0AjBAY/3X0EjW5ViIQTfih4Kif1oxRyF4F1d/Ny9DUtTsgA0Q==", + "requires": { + "@jupyterlab/apputils": "^3.0.8", + "@jupyterlab/codeeditor": "^3.0.8", + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/nbformat": "^3.0.5", + "@jupyterlab/observables": "^4.0.5", + "@jupyterlab/statusbar": "^3.0.8", + "@jupyterlab/translation": "^3.0.8", + "@lumino/algorithm": "^1.3.3", + "@lumino/commands": "^1.12.0", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/polling": "^1.3.3", + "@lumino/signaling": "^1.4.3", + "@lumino/widgets": "^1.16.1", + "codemirror": "~5.57.0", + "react": "^17.0.1" + } + }, + "@jupyterlab/coreutils": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@jupyterlab/coreutils/-/coreutils-5.0.6.tgz", + "integrity": "sha512-nXGpI1IJw+4pNq6Afy+oI3LrTsaQ14xG7Kxbhg9UPfoDgsNt2rdG4pwYe4NZyj2GJHAkUj00lcUD9eBTrxMWvw==", + "requires": { + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/signaling": "^1.4.3", + "minimist": "~1.2.0", + "moment": "^2.24.0", + "path-browserify": "^1.0.0", + "url-parse": "~1.5.1" + } + }, + "@jupyterlab/docregistry": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@jupyterlab/docregistry/-/docregistry-3.0.10.tgz", + "integrity": "sha512-0TV+FWpfwBKpn1w28EHoHoEsOutq/rqEfQlnwTUH/Ml9JdQI7YG5IZGFFVbZpqPF8z9X5MSb5DMA2T+NKFk3Fw==", + "requires": { + "@jupyterlab/apputils": "^3.0.8", + "@jupyterlab/codeeditor": "^3.0.8", + "@jupyterlab/codemirror": "^3.0.8", + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/observables": "^4.0.5", + "@jupyterlab/rendermime": "^3.0.9", + "@jupyterlab/rendermime-interfaces": "^3.0.8", + "@jupyterlab/services": "^6.0.8", + "@jupyterlab/translation": "^3.0.8", + "@jupyterlab/ui-components": "^3.0.7", + "@lumino/algorithm": "^1.3.3", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/messaging": "^1.4.3", + "@lumino/signaling": "^1.4.3", + "@lumino/widgets": "^1.16.1" + } + }, + "@jupyterlab/nbformat": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jupyterlab/nbformat/-/nbformat-3.0.5.tgz", + "integrity": "sha512-OnkeTuBLBc/2hOqO5N43DJjNhAabzEAVQvVmyteBUCRInAlCRgRbCyv0leCO+pYWBIBQAUTwddkf5lyOV/rv9Q==", + "requires": { + "@lumino/coreutils": "^1.5.3" + } + }, + "@jupyterlab/observables": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@jupyterlab/observables/-/observables-4.0.5.tgz", + "integrity": "sha512-fvz9aN3S3ypPLdz69Jy0JckiUsNkU3WXeY48DB2nX3gBIPjnJLHuETAik6JrD0nkes17e9dWsafkox2643TIqQ==", + "requires": { + "@lumino/algorithm": "^1.3.3", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/messaging": "^1.4.3", + "@lumino/signaling": "^1.4.3" + } + }, + "@jupyterlab/outputarea": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/outputarea/-/outputarea-3.0.9.tgz", + "integrity": "sha512-JP+wzfC/tPxhbKV/Q9yGbwOuoF8EzZeQtIz77afKcukUlkcxPLJ71RPTzfihMDkp7j5i29ZWFEcyk9DKdqnzWA==", + "requires": { + "@jupyterlab/apputils": "^3.0.8", + "@jupyterlab/nbformat": "^3.0.5", + "@jupyterlab/observables": "^4.0.5", + "@jupyterlab/rendermime": "^3.0.9", + "@jupyterlab/rendermime-interfaces": "^3.0.8", + "@jupyterlab/services": "^6.0.8", + "@lumino/algorithm": "^1.3.3", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/messaging": "^1.4.3", + "@lumino/properties": "^1.2.3", + "@lumino/signaling": "^1.4.3", + "@lumino/widgets": "^1.16.1", + "resize-observer-polyfill": "^1.5.1" + } + }, + "@jupyterlab/rendermime": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@jupyterlab/rendermime/-/rendermime-3.0.9.tgz", + "integrity": "sha512-xQhoOUH3lkdVBX4zSNnlhr/vuYTlOBzbtEOkclFVc7jif9S4HhwSK9BxNH96zfNxnQcOijWTlbwotEjgR2gfbw==", + "requires": { + "@jupyterlab/apputils": "^3.0.8", + "@jupyterlab/codemirror": "^3.0.8", + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/nbformat": "^3.0.5", + "@jupyterlab/observables": "^4.0.5", + "@jupyterlab/rendermime-interfaces": "^3.0.8", + "@jupyterlab/services": "^6.0.8", + "@jupyterlab/translation": "^3.0.8", + "@lumino/algorithm": "^1.3.3", + "@lumino/coreutils": "^1.5.3", + "@lumino/messaging": "^1.4.3", + "@lumino/signaling": "^1.4.3", + "@lumino/widgets": "^1.16.1", + "lodash.escape": "^4.0.1", + "marked": "^2.0.0" + } + }, + "@jupyterlab/rendermime-interfaces": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jupyterlab/rendermime-interfaces/-/rendermime-interfaces-3.0.8.tgz", + "integrity": "sha512-jGTovsFwgMEk4j4JPrRYIPpu48K4cHJ8Lwbwjg7a3y09VdVJBOjxENfzcp9wLnEC07gJCluu+Cb07fN3MtQ/Ng==", + "requires": { + "@jupyterlab/translation": "^3.0.8", + "@lumino/coreutils": "^1.5.3", + "@lumino/widgets": "^1.16.1" + } + }, + "@jupyterlab/services": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@jupyterlab/services/-/services-6.0.8.tgz", + "integrity": "sha512-UW9bJuFHibnfPNLCUZaSM3zAbRHOizb7SsG/36UIj6yy+saOCRgyWqx+IbwakZBUZCLK4UmtS9smH88BajpSkg==", + "requires": { + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/nbformat": "^3.0.5", + "@jupyterlab/observables": "^4.0.5", + "@jupyterlab/settingregistry": "^3.0.5", + "@jupyterlab/statedb": "^3.0.5", + "@lumino/algorithm": "^1.3.3", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/polling": "^1.3.3", + "@lumino/signaling": "^1.4.3", + "node-fetch": "^2.6.0", + "ws": "^7.2.0" + } + }, + "@jupyterlab/settingregistry": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jupyterlab/settingregistry/-/settingregistry-3.0.5.tgz", + "integrity": "sha512-H86y+CKUxObPA/g8kafmoK23rRsKaXnYCkp4qDx5Vl932/rN6wJUezQ1POe4iFW8MHiniUJpKB8WCknVGc/AUg==", + "requires": { + "@jupyterlab/statedb": "^3.0.5", + "@lumino/commands": "^1.12.0", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/signaling": "^1.4.3", + "ajv": "^6.12.3", + "json5": "^2.1.1" + } + }, + "@jupyterlab/statedb": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jupyterlab/statedb/-/statedb-3.0.5.tgz", + "integrity": "sha512-lzFDEaGtn3movHoL2Z7umsUXjTcSJZaWxBfSbm0OBhtoZ9OG+KmQfkln00ThOAboMZT2zmTxfRBGwkDwi6wDSw==", + "requires": { + "@lumino/commands": "^1.12.0", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/properties": "^1.2.3", + "@lumino/signaling": "^1.4.3" + } + }, + "@jupyterlab/statusbar": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jupyterlab/statusbar/-/statusbar-3.0.8.tgz", + "integrity": "sha512-3Vs4BlsyUHBqQAm+OfN4s+2bB7PCeGyku6KGnrMfOupRU+dJJ6i+kIN6hMtQHdPzftGgIbmRtQSQ4aIbFOsTXw==", + "requires": { + "@jupyterlab/apputils": "^3.0.8", + "@jupyterlab/codeeditor": "^3.0.8", + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/services": "^6.0.8", + "@jupyterlab/translation": "^3.0.8", + "@jupyterlab/ui-components": "^3.0.7", + "@lumino/algorithm": "^1.3.3", + "@lumino/coreutils": "^1.5.3", + "@lumino/disposable": "^1.4.3", + "@lumino/messaging": "^1.4.3", + "@lumino/signaling": "^1.4.3", + "@lumino/widgets": "^1.16.1", + "csstype": "~3.0.3", + "react": "^17.0.1", + "typestyle": "^2.0.4" + }, + "dependencies": { + "csstype": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", + "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + } + } + }, + "@jupyterlab/theme-light-extension": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@jupyterlab/theme-light-extension/-/theme-light-extension-3.0.10.tgz", + "integrity": "sha512-fclv0f5diw/eY2yXk6RH9NfpOXIDuzyMVNtvzgqMgQJoIlL6vNwNoEWb6TvKB3MYcz6tkk0MOQRXVvAOotGeaw==", + "requires": { + "@jupyterlab/application": "^3.0.10", + "@jupyterlab/apputils": "^3.0.8", + "@jupyterlab/translation": "^3.0.8" + } + }, + "@jupyterlab/translation": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jupyterlab/translation/-/translation-3.0.8.tgz", + "integrity": "sha512-veaOzv4xo6Lmjxw5YMMSqPEN1fG3z0laXhK42X/aiuNaXAhXetq6/ioVEk0KXExe58jzb1Z/DGovJmSQU8II0g==", + "requires": { + "@jupyterlab/coreutils": "^5.0.6", + "@jupyterlab/services": "^6.0.8", + "@jupyterlab/statedb": "^3.0.5", + "@lumino/coreutils": "^1.5.3" + } + }, + "@jupyterlab/ui-components": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jupyterlab/ui-components/-/ui-components-3.0.7.tgz", + "integrity": "sha512-kuq2aZ3DcCQNqf5ucsXWREHxbYq23+S12zMertOs+74KQr8jm8chX9HmqpmefNKnSIqqi/RKVSS2PWuSTpkEEw==", + "requires": { + "@blueprintjs/core": "^3.36.0", + "@blueprintjs/select": "^3.15.0", + "@jupyterlab/coreutils": "^5.0.6", + "@lumino/coreutils": "^1.5.3", + "@lumino/signaling": "^1.4.3", + "@lumino/virtualdom": "^1.8.0", + "@lumino/widgets": "^1.16.1", + "react": "^17.0.1", + "react-dom": "^17.0.1", + "typestyle": "^2.0.4" + } + }, + "@lumino/algorithm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lumino/algorithm/-/algorithm-1.6.0.tgz", + "integrity": "sha512-NMOcm5Yr9nXz5gokS/K4jHBbUMQYBkvDXl1n51XWdcz0LY+oGuIKPhjazhUgmbNRehzdZBj5hMMd1+htYWeVKQ==" + }, + "@lumino/application": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@lumino/application/-/application-1.20.0.tgz", + "integrity": "sha512-FAoQcq4L3ZswTK0lWfLKnG1ecG26cwqjzg2fyoBeuWGBi1TG9BYjFBdV7ErTFMxW8jE1CLOLuxsZaKFLNErcKA==", + "requires": { + "@lumino/commands": "^1.15.0", + "@lumino/coreutils": "^1.8.0", + "@lumino/widgets": "^1.23.0" + } + }, + "@lumino/collections": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lumino/collections/-/collections-1.6.0.tgz", + "integrity": "sha512-ZETm0/xF0oUHV03sOXNOfFI1EEpS317HvN5n+fZBJvCNZIrJkWmKD8QuxcfwHb7AChKUhXlVHhDbWlb1LKnd7g==", + "requires": { + "@lumino/algorithm": "^1.6.0" + } + }, + "@lumino/commands": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@lumino/commands/-/commands-1.15.0.tgz", + "integrity": "sha512-JOE68KfbR9xw5YTfcwo+9E0PSWidifEMAcOC/aXd7iSzfsCRknMTcMQIUGL277IU7J7CJvoe10DUE5QKwTmX+g==", + "requires": { + "@lumino/algorithm": "^1.6.0", + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0", + "@lumino/domutils": "^1.5.0", + "@lumino/keyboard": "^1.5.0", + "@lumino/signaling": "^1.7.0", + "@lumino/virtualdom": "^1.11.0" + } + }, + "@lumino/coreutils": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@lumino/coreutils/-/coreutils-1.8.0.tgz", + "integrity": "sha512-OvCsaASUqOE7R6Dxngyk4/b5QMOjyRUNxuZuuL+fx+JvGKZFZ/B2c9LYtAJ9mDmQ1BQiGNV/qSpL4o7x8PCfjw==" + }, + "@lumino/disposable": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/disposable/-/disposable-1.7.0.tgz", + "integrity": "sha512-3mWi11ko3XVY63BPwvys7MXrbFddA2i+gp72d0wAKM2NDDUopVPikMHhJpjGJcw+otjahzXYiTewxPDEau9dYg==", + "requires": { + "@lumino/algorithm": "^1.6.0", + "@lumino/signaling": "^1.7.0" + } + }, + "@lumino/domutils": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lumino/domutils/-/domutils-1.5.0.tgz", + "integrity": "sha512-dZ0Aa+/qhvfPc1aa5kX4LLGE3B6BW1XmJa0R1XVCEpAFY3cZiujuQWmhYHJtZPrOiqn0UtioT2OpqnWdtCWc0A==" + }, + "@lumino/dragdrop": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@lumino/dragdrop/-/dragdrop-1.10.0.tgz", + "integrity": "sha512-A3cNLcp09zygOprWmLTkLZCQYNq3dJfN+mhni4IZizqCTkKbTCEzo2/IwoCWvy+ABKft8d/A9Y40wFW6yJ9OyA==", + "requires": { + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0" + } + }, + "@lumino/keyboard": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lumino/keyboard/-/keyboard-1.5.0.tgz", + "integrity": "sha512-/uF9xqHYVbIkser2Q6UIv7VWrzThr1fxAmSOShjSoKGocL0XHeaBaCOMezSaVxnJ1wm1ciNdhMsjscVM8Inp7g==" + }, + "@lumino/messaging": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/messaging/-/messaging-1.7.0.tgz", + "integrity": "sha512-QYWf9QGIGD0Oes104zw7mVln4S8yRije2mZhNNRBjkYcDuQlPW+eRSuC5LwAMsFnGymBlUPwPbKOUEO2RbhAtg==", + "requires": { + "@lumino/algorithm": "^1.6.0", + "@lumino/collections": "^1.6.0" + } + }, + "@lumino/polling": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lumino/polling/-/polling-1.6.0.tgz", + "integrity": "sha512-jG1nqw6UO5XEN7QamOr6iDW8WvYeZQcBVRjM38fszz62dwJ/VGPvO2hlNl6QWWIfCynbJudms0LQm+z0BT1EdA==", + "requires": { + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0", + "@lumino/signaling": "^1.7.0" + } + }, + "@lumino/properties": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lumino/properties/-/properties-1.5.0.tgz", + "integrity": "sha512-YqpJE6/1Wkjrie0E+ypu+yzd55B5RlvKYMnQs3Ox+SrJsnNBhA6Oj44EhVf8SUTuHgn1t/mm+LvbswKN5RM4+g==" + }, + "@lumino/signaling": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@lumino/signaling/-/signaling-1.7.0.tgz", + "integrity": "sha512-a5kd11Sf04jTfpzxCr7TOBD2o5YvItA4IGwiOoG+QR6sPR0Rwmcf47fPItqXo5st58iNIblC3F+c264N+Me+gg==", + "requires": { + "@lumino/algorithm": "^1.6.0" + } + }, + "@lumino/virtualdom": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@lumino/virtualdom/-/virtualdom-1.11.0.tgz", + "integrity": "sha512-G0sIx4pLYbgJ4w+SIgsCYQgKP/GBrWgjh8wcumD6XpaYZNivJv4c01xITYYlh7FU61jZmMWMrxtZztArNRDSqg==", + "requires": { + "@lumino/algorithm": "^1.6.0" + } + }, + "@lumino/widgets": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@lumino/widgets/-/widgets-1.23.0.tgz", + "integrity": "sha512-0Akt9ESgc06SJ3EJG3VK1Liw+AAjRWkKMfm8VUTwT/1QJYYGZ8kfHNO97mkBLv+0EkLEkZIeaQb8fIoU6vh7bw==", + "requires": { + "@lumino/algorithm": "^1.6.0", + "@lumino/commands": "^1.15.0", + "@lumino/coreutils": "^1.8.0", + "@lumino/disposable": "^1.7.0", + "@lumino/domutils": "^1.5.0", + "@lumino/dragdrop": "^1.10.0", + "@lumino/keyboard": "^1.5.0", + "@lumino/messaging": "^1.7.0", + "@lumino/properties": "^1.5.0", + "@lumino/signaling": "^1.7.0", + "@lumino/virtualdom": "^1.11.0" } }, "@popperjs/core": { @@ -317,6 +853,11 @@ "tslib": "^2.0.0" } }, + "@types/dom4": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/dom4/-/dom4-2.0.1.tgz", + "integrity": "sha512-kSkVAvWmMZiCYtvqjqQEwOmvKwcH+V4uiv3qPQ8pAh1Xl39xggGEo8gHUqV4waYGHezdFw0rKBR8Jt0CrQSDZA==" + }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -333,20 +874,33 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.33.tgz", "integrity": "sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g==" }, - "@types/node-fetch": { - "version": "2.5.10", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz", - "integrity": "sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==", - "requires": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" + }, + "@types/react": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.5.tgz", + "integrity": "sha512-bj4biDB9ZJmGAYTWSKJly6bMr4BLUiBrx9ujiJEoP9XIDY9CTaPGxE5QWN/1WjpPLzYF7/jRNnV2nNxNe970sw==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", + "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" + } + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -356,6 +910,22 @@ "@types/node": "*" } }, + "@types/scheduler": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", + "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -365,17 +935,9 @@ } }, "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "babel-plugin-emotion": { "version": "10.2.2", @@ -392,6 +954,13 @@ "escape-string-regexp": "^1.0.5", "find-root": "^1.1.0", "source-map": "^0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } } }, "babel-plugin-macros": { @@ -423,10 +992,15 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "bootstrap": { - "version": "5.0.0-beta3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.0-beta3.tgz", - "integrity": "sha512-0urccjfIOzhrb9qJysN8XW/DRw6rg3zH7qLeKIp4Zyl8+Ens4JWB0NC0cB5AhnSFPd2tftRggjwCMxablo6Tpg==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.1.tgz", + "integrity": "sha512-Fl79+wsLOZKoiU345KeEaWD0ik8WKRI5zm0YSPj2oF1Qr+BO7z0fco6GbUtqjoG1h4VI89PeKJnMsMMVQdKKTw==" }, "brace-expansion": { "version": "1.1.11", @@ -438,6 +1012,15 @@ "concat-map": "0.0.1" } }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -449,6 +1032,15 @@ "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", "dev": true }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -464,6 +1056,11 @@ "supports-color": "^5.3.0" } }, + "classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, "clean-css": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.1.tgz", @@ -492,6 +1089,11 @@ "tiny-emitter": "^2.0.0" } }, + "codemirror": { + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.57.0.tgz", + "integrity": "sha512-WGc6UL7Hqt+8a6ZAsj/f1ApQl3NPvHY/UQSzG6fB6l4BjExgVdhFaxd7mRTw1UCiYe/6q86zHP+kfvBQcZGvUg==" + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -505,13 +1107,10 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" }, "commander": { "version": "2.20.3", @@ -574,20 +1173,35 @@ "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" }, "csstype": { - "version": "2.6.17", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz", - "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==" + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz", + "integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==" + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } }, "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } }, "delegate": { "version": "3.2.0", @@ -595,6 +1209,52 @@ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", "optional": true }, + "dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, + "dom-serializer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.1.tgz", + "integrity": "sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "entities": "^2.0.0" + } + }, + "dom4": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/dom4/-/dom4-2.1.6.tgz", + "integrity": "sha512-JkCVGnN4ofKGbjf5Uvc8mmxaATIErKQKSgACdBXpsQ3fY6DlIpAyWfiBSrGkttATssbDCp3psiAKWXk5gmjycA==" + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + }, + "domhandler": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", + "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz", + "integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, "emotion-theming": { "version": "10.0.27", "resolved": "https://registry.npmjs.org/emotion-theming/-/emotion-theming-10.0.27.tgz", @@ -606,9 +1266,9 @@ } }, "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, "error-ex": { "version": "1.3.2", @@ -618,6 +1278,12 @@ "is-arrayish": "^0.2.1" } }, + "esbuild": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.11.16.tgz", + "integrity": "sha512-34ZWjo4ouvM5cDe7uRoM9GFuMyEmpH9fnVYmomvS1cq9ED9d/0ZG1r+p4P2VbX7ihjv36zA2SWTmP8Zmt/EANA==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -629,6 +1295,16 @@ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", "dev": true }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, "find-cache-dir": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", @@ -653,15 +1329,10 @@ "path-exists": "^4.0.0" } }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } + "free-style": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/free-style/-/free-style-3.1.0.tgz", + "integrity": "sha512-vJujYSIyT30iDoaoeigNAxX4yB1RUrh+N2ZMhIElMr3BvCuGXOw7XNJMEEJkDUeamK2Rnb/IKFGKRKlTWIGRWA==" }, "fs-extra": { "version": "8.1.0", @@ -690,6 +1361,16 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -718,6 +1399,11 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -731,6 +1417,11 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, "hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -739,10 +1430,26 @@ "react-is": "^16.7.0" } }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "iframe-resizer": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/iframe-resizer/-/iframe-resizer-4.3.1.tgz", - "integrity": "sha512-PkoTPNF6EYhTbDjogdKu7JVgKqRwwNBXMeywZaQyzEYM3BNltA8O9fIIrtUkmj+8VZGckXpwtXsWsaQ5lrhd0w==" + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/iframe-resizer/-/iframe-resizer-4.3.2.tgz", + "integrity": "sha512-gOWo2hmdPjMQsQ+zTKbses08mDfDEMh4NneGQNP4qwePYujY1lguqP6gnbeJkf154gojWlBhIltlgnMfYjGHWA==" }, "import-fresh": { "version": "3.3.0", @@ -769,6 +1476,14 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "requires": { + "call-bind": "^1.0.0" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -782,6 +1497,11 @@ "has": "^1.0.3" } }, + "is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==" + }, "is-dom": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz", @@ -802,6 +1522,11 @@ "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==" }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, "is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -811,6 +1536,15 @@ "@types/estree": "*" } }, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + } + }, "is-window": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-window/-/is-window-1.0.2.tgz", @@ -841,6 +1575,12 @@ } } }, + "joycon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.0.1.tgz", + "integrity": "sha512-SJcJNBg32dGgxhPtM0wQqxqV0ax9k/9TaUskGDSJkSFSQOEWWvQ3zzWdGQRIUry2j1zA5+ReH13t0Mf3StuVZA==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -851,6 +1591,25 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -860,13 +1619,25 @@ } }, "katex": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.12.0.tgz", - "integrity": "sha512-y+8btoc/CK70XqcHqjxiGWBOeIL8upbS0peTPXTvgrh21n1RiWWcIpSWM+4uXq+IAgNh9YYQWdc7LVDPDAEEAg==", + "version": "0.13.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.13.10.tgz", + "integrity": "sha512-NUUY4U7I2NUAzNY7DwK5afH7zZS5k9OiCgmh1T13svIv+Toemrmzj1WtUlFOrLM4bXGrb/LWWrdrNCBLSdNTKA==", "requires": { - "commander": "^2.19.0" + "commander": "^6.0.0" + }, + "dependencies": { + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==" + } } }, + "klona": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", + "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==" + }, "lezer": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/lezer/-/lezer-0.13.4.tgz", @@ -892,9 +1663,9 @@ } }, "lezer-html": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/lezer-html/-/lezer-html-0.13.4.tgz", - "integrity": "sha512-qBBEJO+pQ8jVFin/1C7lj7QFrr+pTzRmJDgKxaZqIHr7IKzq2jN+NXQVprru4g6l+2b0h4350wKeVGP9kLkq0A==", + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/lezer-html/-/lezer-html-0.13.5.tgz", + "integrity": "sha512-xjWhwttVp2NdCzV8BE4Duj/u4iSMf39YRQ+ur93DoiSxfpANA3oc/hduKJr5MB/isph1kQdFy8rIqkl8FtBkCQ==", "requires": { "lezer": "^0.13.3" } @@ -908,9 +1679,9 @@ } }, "lezer-javascript": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/lezer-javascript/-/lezer-javascript-0.13.3.tgz", - "integrity": "sha512-YvTUZUZUk69nt6flmUaPuc/9yynsPqhbpqY6GXZK/8EH9/4X7B2AmMc86hk2yBGbTMrorou8ouV7neoDRk9khA==", + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/lezer-javascript/-/lezer-javascript-0.13.4.tgz", + "integrity": "sha512-nhRbeSwPZo2xVYq6TWyUhi/r9j0CFSUpkuA5J992Az2AYZFw2HnGVjixfP43DKufL+npJwSy0qcCcAHFQ2bFOQ==", "requires": { "lezer": "^0.13.0" } @@ -967,9 +1738,9 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", "requires": { "uc.micro": "^1.0.1" } @@ -1000,6 +1771,11 @@ "p-locate": "^4.1.0" } }, + "lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -1026,15 +1802,22 @@ } }, "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "version": "12.0.6", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.6.tgz", + "integrity": "sha512-qv3sVLl4lMT96LLtR7xeRJX11OUFjsaD5oVat2/SNBIb21bJXwal2+SklcRbTwGwqWpWH/HRtYavOoJE+seL8w==", "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" + } } }, "markdown-it-emoji": { @@ -1050,6 +1833,11 @@ "prismjs": "1.23.0" } }, + "marked": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.3.tgz", + "integrity": "sha512-5otztIIcJfPc2qGTN8cVtOJEjNJZ0jwa46INMagrYfk0EvqtRuEHLsEe0LrFS0/q+ZRKT0+kXK7P2T1AN5lWRA==" + }, "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -1060,19 +1848,6 @@ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, - "mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" - }, - "mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", - "requires": { - "mime-db": "1.47.0" - } - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1082,16 +1857,55 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, "monaco-editor": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.21.3.tgz", - "integrity": "sha512-9N7wATLpi+googstvtm6IKg97vPQ77FDYEpkow5tLriM/VJ0DaTRyUP4UVzcoH7KlPDX+e/rE7/imcOUeGkT6g==" + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.23.0.tgz", + "integrity": "sha512-q+CP5zMR/aFiMTE9QlIavGyGicKnG2v/H8qVvybLzeFsARM8f6G9fL0sMST2tyVYCwDKkGamZUI6647A0jR/Lg==" + }, + "nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==" + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "normalize.css": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz", + "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==" }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1146,6 +1960,16 @@ "lines-and-columns": "^1.1.6" } }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=" + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -1180,11 +2004,32 @@ "find-up": "^4.0.0" } }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" + }, + "postcss": { + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", + "requires": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map": "^0.6.1" + } + }, "preact": { "version": "10.5.13", "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.13.tgz", "integrity": "sha512-q/vlKIGNwzTLu+jCcvywgGrt+H/1P/oIRSD6mV4ln3hmlC+Aa34C7yfPI4+5bzW8pONyVXYS7SvXosy2dKKtWQ==" }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + }, "prismjs": { "version": "1.23.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", @@ -1274,9 +2119,9 @@ } }, "prosemirror-model": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.14.0.tgz", - "integrity": "sha512-+9J7YE2qD2lsRgaI5aF7u6LynBoHxb/8sW1gaMKRAhK+yeQ+motBIaxb2GxRWSadDWMOq5haAImSTBo6jDkv2A==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.14.1.tgz", + "integrity": "sha512-vZcbI+24VloFefKZkDnMaEpipL/vSKKPdFiik4KOnTzq3e6AO7+CAOixZ2G/SsfRaYC965XvnOIEbhIQdgki7w==", "requires": { "orderedmap": "^1.1.0" } @@ -1308,15 +2153,30 @@ } }, "prosemirror-view": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.18.3.tgz", - "integrity": "sha512-B0zlzjBI0cHadpghyvAA+JgqLGbkNU9Vxywqkfaa+AdmOZUZImBKH6ufhpK+AEZn97WWgSIkr/MT9RmGpaboAA==", + "version": "1.18.4", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.18.4.tgz", + "integrity": "sha512-6oi62XRK5WxhMX1Amjk5uMsWILUEcFbFF75i09BzpAdI+5glhs7heCaRvKOj4v3YRJ7LJVkOXS9xvjetlE3+pA==", "requires": { "prosemirror-model": "^1.1.0", "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0" } }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -1325,6 +2185,25 @@ "safe-buffer": "^5.1.0" } }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + } + }, "react-inspector": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz", @@ -1340,11 +2219,65 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-popper": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", + "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==", + "requires": { + "@babel/runtime": "^7.1.2", + "@hypnosphi/create-react-context": "^0.3.1", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", + "warning": "^4.0.2" + } + }, + "react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "requires": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + } + }, "regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, + "regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "requirejs": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -1376,6 +2309,35 @@ "fsevents": "~2.3.1" } }, + "rollup-plugin-esbuild": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-4.2.3.tgz", + "integrity": "sha512-GWyDUPv79Iw4uQdizD7ch7yA+wiB9W4Ye01RmO/kuF3yjybluJT5rbmLAnyv3kWmOF8suOjf+TvvBCXEj6qSAw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^4.1.0", + "joycon": "^3.0.1", + "jsonc-parser": "^3.0.0" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz", + "integrity": "sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==", + "dev": true, + "requires": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + } + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + } + } + }, "rollup-plugin-terser": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", @@ -1425,6 +2387,36 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "sanitize-html": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.3.3.tgz", + "integrity": "sha512-DCFXPt7Di0c6JUnlT90eIgrjs6TsJl/8HYU3KLdmrVclFN4O0heTcVbJiMa23OKVr6aR051XYtsgd8EWwEBwUA==", + "requires": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^6.0.0", + "is-plain-object": "^5.0.0", + "klona": "^2.0.3", + "parse-srcset": "^1.0.2", + "postcss": "^8.0.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + } + } + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, "select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", @@ -1445,9 +2437,9 @@ } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { "version": "0.5.19", @@ -1471,15 +2463,23 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "dev": true }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "starboard-jupyter": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/starboard-jupyter/-/starboard-jupyter-0.2.8.tgz", + "integrity": "sha512-Gz3Lv6GZ4LLYVWAKw0F95N4zNUPp3J1Mmv0ggKQyo/QujJxKtnrY40qaHv2RAECMierJMvlz1Zu7JN4eC9CVfg==", + "requires": { + "@jupyterlab/outputarea": "^3.0.7", + "@jupyterlab/rendermime": "^3.0.7", + "@jupyterlab/services": "^6.0.6", + "@jupyterlab/theme-light-extension": "^3.0.8", + "@types/katex": "^0.11.0", + "requirejs": "^2.3.6" + } }, "starboard-notebook": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/starboard-notebook/-/starboard-notebook-0.8.10.tgz", - "integrity": "sha512-CRCAVErZ9HtCZSXiJRJ441pUCShNMYZenZEZvhnxKu/hZTBLOSaRJN+M6/Q8ETOKF7rcWYBX/nrXyBXXwuZFMQ==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/starboard-notebook/-/starboard-notebook-0.9.3.tgz", + "integrity": "sha512-GAQjzSM/VEQvrgdPOahxCRpWf5JQq+1WOt2bF4S6C6Kb951bKDok5/cvrx+KI+BLcYY9rNjhgKawr97rZTvA7g==", "requires": { "@babel/parser": "^7.10.5", "@benrbray/prosemirror-math": "^0.1.4", @@ -1489,18 +2489,17 @@ "@popperjs/core": "^2.5.3", "@spectrum-web-components/icons-ui": "^0.1.0", "@spectrum-web-components/icons-workflow": "^0.2.0", - "@types/node-fetch": "^2.5.7", "babel-walk": "^3.0.0", - "bootstrap": "^5.0.0-beta2", + "bootstrap": "^5.0.0", "console-feed-modern": "^3.0.5", "iframe-resizer": "^4.2.10", - "katex": "^0.12.0", + "katex": "^0.13.10", "lit-element": "^2.3.1", "lit-html": "^1.2.1", - "markdown-it": "^10.0.0", + "markdown-it": "^12.0.6", "markdown-it-emoji": "^2.0.0", "markdown-it-prism": "^2.1.6", - "monaco-editor": "^0.21.0", + "monaco-editor": "^0.23.0", "preact": "^10.5.3", "prismjs": "^1.23.0", "prosemirror-commands": "^1.1.7", @@ -1515,7 +2514,7 @@ "prosemirror-state": "^1.3.4", "prosemirror-transform": "^1.2.12", "prosemirror-view": "^1.18.1", - "starboard-python": "^0.5.1", + "starboard-python": "^0.6.4", "yaml": "^2.0.0-1" }, "dependencies": { @@ -1531,9 +2530,9 @@ } }, "starboard-python": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/starboard-python/-/starboard-python-0.5.1.tgz", - "integrity": "sha512-ETd/Yepv3UwSf0ZPdff7/YqdbePkU9Sv/NOSrp255ZozCL52lxKwe2S2vas3gN85blMRNsXly80P0S2dZ2xqzg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/starboard-python/-/starboard-python-0.6.5.tgz", + "integrity": "sha512-tke7okgahfkZsZkUMKxSWXQrEF3fkXfx1/zFKR5uzfclN0mcYn41ytQ7pLf7OAvhbRmN0gE18jWEIK8DW7eHLA==", "requires": { "@types/katex": "^0.11.0" } @@ -1584,12 +2583,26 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" }, + "typed-styles": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", + "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==" + }, "typescript": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", "dev": true }, + "typestyle": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typestyle/-/typestyle-2.1.0.tgz", + "integrity": "sha512-6uCYPdG4xWLeEcl9O0GtNFnNGhami+irKiLsXSuvWHC/aTS7wdj49WeikWAKN+xHN3b1hm+9v0svwwgSBhCsNA==", + "requires": { + "csstype": "2.6.9", + "free-style": "3.1.0" + } + }, "uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -1600,17 +2613,63 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-parse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", + "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "w3c-keyname": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "ws": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==" + }, "yaml": { "version": "2.0.0-5", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-5.tgz", diff --git a/package.json b/package.json index 6a38288..a9f45a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@illumidesk/starboard-nbgrader", - "version": "0.1.3", + "version": "0.1.6", "description": "Starboard and nbgrader proof of concept", "main": "dist/index.js", "dependencies": { @@ -9,19 +9,24 @@ "rollup": "^2.41.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-typescript2": "^0.30.0", - "starboard-notebook": "^0.8.10" + "starboard-jupyter": "^0.2.8", + "starboard-notebook": "^0.9.3" }, "devDependencies": { "@rollup/plugin-commonjs": "^17.1.0", "@rollup/plugin-node-resolve": "^11.2.0", "clean-css": "^5.1.1", + "esbuild": "^0.11.16", + "prettier": "^2.2.1", "rimraf": "^3.0.2", + "rollup-plugin-esbuild": "^4.2.3", "typescript": "^4.2.3" }, "scripts": { "build": "rollup -c && tsc", - "dev": "rollup -c --watch", + "start": "rollup -c --watch", "test": "echo \"Error: no test specified\" && exit 1", + "format": "prettier -w src", "prepublishOnly": "rimraf dist && npm i && npm run build" }, "repository": { diff --git a/rollup.config.js b/rollup.config.js index 042d195..85302ef 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,7 @@ import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import typescript from 'rollup-plugin-typescript2'; +import esbuild from 'rollup-plugin-esbuild' import { terser } from 'rollup-plugin-terser'; const CleanCSS = require('clean-css'); @@ -21,18 +22,21 @@ export default [ input: `src/plugin.ts`, output: [ { file: 'dist/plugin.js', format: 'es' }, - { file: 'dist/plugin.min.js', format: 'es', plugins: [terser()] }, - { file: 'dist/plugin.cjs', format: 'cjs' } + // { file: 'dist/plugin.min.js', format: 'es', plugins: [terser()] }, + // { file: 'dist/plugin.cjs', format: 'cjs' } ], plugins: [ css(), - typescript({ - include: [ - './src/**/*.ts', - ], + esbuild({ + target: "es2018" }), + // typescript({ + // include: [ + // './src/**/*.ts', + // ], + // }), resolve(), - commonjs(), + // commonjs(), ] }, { @@ -41,10 +45,13 @@ export default [ { file: 'dist/converter.js', format: 'es' }, ], plugins: [ - typescript({ - include: [ - './src/**/*.ts', - ], + // typescript({ + // include: [ + // './src/**/*.ts', + // ], + // }), + esbuild({ + target: "es2018" }), resolve(), commonjs(), diff --git a/src/cellType.ts b/src/cellType.ts index 2e5138f..19fe067 100644 --- a/src/cellType.ts +++ b/src/cellType.ts @@ -1,7 +1,18 @@ -import {Cell} from "starboard-notebook/dist/src/types" -import {CellElements, CellHandler, CellHandlerAttachParameters, ControlButton, Runtime} from "starboard-notebook/dist/src/types" - -import { convertNBGraderType, getDefaultCellNBGraderMetadata, GraderCellType, GraderCellTypeDefinitions as DEFINITIONS} from "./definitions"; +import { Cell } from "starboard-notebook/dist/src/types"; +import { + CellElements, + CellHandler, + CellHandlerAttachParameters, + ControlButton, + Runtime, +} from "starboard-notebook/dist/src/types"; + +import { + convertNBGraderType, + getDefaultCellNBGraderMetadata, + GraderCellType, + GraderCellTypeDefinitions as DEFINITIONS, +} from "./definitions"; import { LitHtml as lithtml } from "starboard-notebook/dist/src/runtime/esm/exports/libraries"; import { StarboardContentEditor, StarboardTextEditor } from "starboard-notebook/dist/src/runtime/esm/exports/elements"; @@ -11,294 +22,347 @@ import { NBGraderMetadata, StarboardGraderMetadata } from "./types"; import { graderMetadataToNBGraderCellType } from "./graderUtils"; import { TemplateResult } from "lit-html"; import { CodeRunnerFeedbackElement, CodeRunnerResult } from "./elements/codeRunnerFeedback"; +import { getJupyterPlugin } from "./jupyter"; +import { getPythonExecutionMode } from "./state"; -declare const runtime: Runtime +declare const runtime: Runtime; declare const html: typeof lithtml.html; +type OutputArea = ReturnType["exports"]["createJupyterOutputArea"]>; + const GRADER_CELL_TYPE_DEFINITION = { - name: "Assignment (grader)", - cellType: ["grader"], - createHandler: (cell: Cell, runtime: Runtime) => new GraderCellHandler(cell, runtime), -} + name: "Assignment (grader)", + cellType: ["grader"], + createHandler: (cell: Cell, runtime: Runtime) => new GraderCellHandler(cell, runtime), +}; export class GraderCellHandler implements CellHandler { - cell: Cell; - runtime: Runtime; - - elements!: CellElements; - editor?: InstanceType | InstanceType; - - private topbarExpanded = false; - /** - * Quality of life: If switching away from a cell type that doesn't have points and back again, we remember - * the last point count. - */ - private cachedPointCount = 1; - - - private graderType: GraderCellType; - private underlyingCellType: "python" | "markdown"; - - /** - * The editor is shown for Markdown content currently (instead of the content itself) - */ - private isCurrentlyRunning: boolean = false; - private isCurrentlyLoadingPyodide: boolean = false; - - /** - * The last ID of a Python run. This is used for showing the right state of the "run" button if there are - * more than 1 overlapping runs of Python in this cell. - */ - private lastRunId = -1; - private codeRunnerFeedbackElement: CodeRunnerFeedbackElement - - constructor(cell: Cell, runtime: Runtime) { - this.cell = cell; - this.runtime = runtime; - - if (this.getNBGraderMetadata() === undefined) { - this.cell.metadata.nbgrader = getDefaultCellNBGraderMetadata(this.cell.id); - } - this.graderType = graderMetadataToNBGraderCellType(this.getNBGraderMetadata()); - - this.codeRunnerFeedbackElement = new CodeRunnerFeedbackElement(); - - const starboardGraderMetadata = (this.cell.metadata.starboard_grader as StarboardGraderMetadata | undefined); - if (!starboardGraderMetadata) { - this.underlyingCellType = "python"; - } else { - this.underlyingCellType = starboardGraderMetadata.original_cell_type; - } + cell: Cell; + runtime: Runtime; + + elements!: CellElements; + editor?: InstanceType | InstanceType; + + private topbarExpanded = false; + /** + * Quality of life feature: When switching away from a cell type that doesn't have points and back again, we remember + * the last point count. + */ + private cachedPointCount = 1; + + private get useJupyterBackend() { + return getPythonExecutionMode() === "jupyter"; + } + + private jupyterOutputArea?: OutputArea; + + private graderType: GraderCellType; + private underlyingCellType: "python" | "markdown"; + + /** + * The editor is shown for Markdown content currently (instead of the content itself) + */ + private isCurrentlyRunning: boolean = false; + private isCurrentlyLoadingPyodide: boolean = false; + + /** + * The last ID of a Python run. This is used for showing the right state of the "run" button if there are + * more than 1 overlapping runs of Python in this cell. + */ + private lastRunId = -1; + private codeRunnerFeedbackElement: CodeRunnerFeedbackElement; + + constructor(cell: Cell, runtime: Runtime) { + this.cell = cell; + this.runtime = runtime; + + if (this.getNBGraderMetadata() === undefined) { + this.cell.metadata.nbgrader = getDefaultCellNBGraderMetadata(this.cell.id); + } + this.graderType = graderMetadataToNBGraderCellType(this.getNBGraderMetadata()); + this.codeRunnerFeedbackElement = new CodeRunnerFeedbackElement(); + + const starboardGraderMetadata = this.cell.metadata.starboard_grader as StarboardGraderMetadata | undefined; + if (!starboardGraderMetadata) { + this.underlyingCellType = "python"; + } else { + this.underlyingCellType = starboardGraderMetadata.original_cell_type; + } + } + + private getNBGraderMetadata() { + return this.cell.metadata.nbgrader as NBGraderMetadata; + } + + private getControls(): TemplateResult | string | undefined { + if (this.underlyingCellType === "python") { + const icon = this.isCurrentlyRunning ? icons.ClockIcon : icons.PlayCircleIcon; + const tooltip = this.isCurrentlyRunning ? "Run Cell" : "Cell is running"; + const runButton: ControlButton = { + icon, + tooltip, + callback: () => this.runtime.controls.emit({ id: this.cell.id, type: "RUN_CELL" }), + }; + let buttons = [runButton]; + + if (this.isCurrentlyLoadingPyodide) { + buttons = [ + { + icon: icons.GearsIcon, + tooltip: "Downloading and initializing Pyodide", + callback: () => { + alert( + "Loading Python runtime. It's fairly large so it may take some time. It will be cached for next time." + ); + }, + }, + ...buttons, + ]; + } + + return cellControlsTemplate({ buttons }); + } + } + + private updateRender() { + const topElement = this.elements.topElement; + lithtml.render(this.topTemplate(), topElement); + lithtml.render(this.getControls(), this.elements.topControlsElement); + lithtml.render(html`${this.codeRunnerFeedbackElement}`, this.elements.bottomElement); + } + + private setupEditor() { + if (this.editor !== undefined) { + this.editor.dispose(); } - private getNBGraderMetadata() { - return this.cell.metadata.nbgrader as NBGraderMetadata; + if (this.underlyingCellType === "python") { + this.editor = new StarboardTextEditor(this.cell, this.runtime, { language: this.underlyingCellType }); + } else { + this.editor = new StarboardContentEditor(this.cell, this.runtime); } + } - private getControls(): TemplateResult | string { - if (this.underlyingCellType === "python") { - const icon = this.isCurrentlyRunning ? icons.ClockIcon : icons.PlayCircleIcon; - const tooltip = this.isCurrentlyRunning ? "Run Cell": "Cell is running"; - const runButton: ControlButton = { - icon, - tooltip, - callback: () => this.runtime.controls.emit({id: this.cell.id, type: "RUN_CELL"}), - }; - let buttons = [runButton]; - - if (this.isCurrentlyLoadingPyodide) { - buttons = [{ - icon: icons.GearsIcon, - tooltip: "Downloading and initializing Pyodide", - callback: () => {alert("Loading Python runtime. It's fairly large so it may take some time. It will be cached for next time.")} - }, ...buttons] - } - - return cellControlsTemplate({ buttons }); - } else { - return '' - } + private changeNBType(newType: GraderCellType) { + this.graderType = newType; + const md = this.getNBGraderMetadata(); + + if (md.points !== undefined) { + this.cachedPointCount = md.points; } - private updateRender() { - const topElement = this.elements.topElement; - lithtml.render(this.topTemplate(), topElement); - lithtml.render(this.getControls(), this.elements.topControlsElement); - lithtml.render(html`${this.codeRunnerFeedbackElement}`, this.elements.bottomElement); + convertNBGraderType(md, newType, this.cachedPointCount); + // These types can't be markdown-based. + if (newType === "autograder-answer" || newType === "autograder-tests") { + this.changeLanguage("python"); + } + this.updateRender(); + } + + private changeLanguage(newLanguage: "python" | "markdown") { + if (newLanguage !== this.underlyingCellType) { + this.codeRunnerFeedbackElement = new CodeRunnerFeedbackElement(); + this.underlyingCellType = newLanguage; + this.setupEditor(); + this.cell.metadata.starboard_grader = { original_cell_type: this.underlyingCellType }; + this.updateRender(); + } + } + + private changePointValue(evt: Event) { + const nbgraderMeta = this.cell.metadata.nbgrader as NBGraderMetadata; + const newValue = (evt.target as HTMLInputElement).value; + try { + nbgraderMeta.points = parseInt(newValue, 10); + } catch (e) { + nbgraderMeta.points = 0; + } + if (isNaN(nbgraderMeta.points) || nbgraderMeta.points < 0) { + nbgraderMeta.points = 0; } - private setupEditor() { - if (this.editor !== undefined) { - this.editor.dispose(); - } + this.updateRender(); + } - if (this.underlyingCellType === "python") { - this.editor = new StarboardTextEditor(this.cell, this.runtime, {language: this.underlyingCellType}); - } else { - this.editor = new StarboardContentEditor(this.cell); - } - } + private toggleExpansion() { + this.topbarExpanded = !this.topbarExpanded; + this.updateRender(); + } - private changeNBType(newType: GraderCellType) { - this.graderType = newType; - const md = this.getNBGraderMetadata(); + topTemplate() { + const md = this.getNBGraderMetadata(); - if (md.points !== undefined) { - this.cachedPointCount = md.points - } + const graderDefinition = DEFINITIONS[this.graderType]; - convertNBGraderType(md, newType, this.cachedPointCount) - // These types can't be markdown-based. - if (newType === "autograder-answer" || newType === "autograder-tests") { - this.changeLanguage("python"); - } - this.updateRender(); - } + let topbarControls: TemplateResult | undefined; - private changeLanguage(newLanguage: "python" | "markdown") { - if (newLanguage !== this.underlyingCellType) { - this.codeRunnerFeedbackElement = new CodeRunnerFeedbackElement(); - this.underlyingCellType = newLanguage; - this.setupEditor(); - this.cell.metadata.starboard_grader = {original_cell_type: this.underlyingCellType}; - this.updateRender(); - } + if (this.topbarExpanded) { + topbarControls = html`
+
+
+ ${Object.entries(DEFINITIONS).map( + ([type, def]) => + html` + + ` + )} +
+ + ${graderDefinition.hasPoints + ? html` + ${graderDefinition.hasPoints + ? html`
+ Points + +
` + : undefined} + ` + : undefined} + +
+ ${graderDefinition.supportedCellTypes.map( + (ct) => html` ` + )} +
+
+ +

${graderDefinition.description}

+
`; } - private changeCellId(evt: Event) { - const newValue = (evt.target as HTMLInputElement).value; - if (typeof newValue === "string") { - (this.cell.metadata.nbgrader as NBGraderMetadata).grade_id = newValue || this.cell.id; + return html` + + ${topbarControls} +
${this.editor}
+ `; + } + + attach(params: CellHandlerAttachParameters) { + this.elements = params.elements; + this.setupEditor(); + this.updateRender(); + } + + async run() { + // TODO refactor this.. bigtime + if (this.underlyingCellType === "markdown") { + this.updateRender(); + } else if (this.underlyingCellType === "python") { + const outputMount = this.codeRunnerFeedbackElement.getOutputElement(); + this.codeRunnerFeedbackElement.reset(); + + // Pyodide-based plugin + let pythonPlugin; + // Jupyter-based plugin + let jupyterPlugin = getJupyterPlugin(); + + if (!this.useJupyterBackend) { + pythonPlugin = await this.runtime.exports.libraries.async.StarboardPython(); + if (pythonPlugin.getPyodideLoadingStatus() !== "ready") { + this.isCurrentlyLoadingPyodide = true; + this.codeRunnerFeedbackElement.setRunResult("running-setup"); + lithtml.render(this.getControls(), this.elements.topControlsElement); + } else { + this.codeRunnerFeedbackElement.setRunResult("running"); } - } + } else { + if (!this.jupyterOutputArea) { + this.jupyterOutputArea = jupyterPlugin.exports.createJupyterOutputArea(); + } + this.codeRunnerFeedbackElement.setRunResult("running"); - private changePointValue(evt: Event) { - const nbgraderMeta = this.cell.metadata.nbgrader as NBGraderMetadata; - const newValue = (evt.target as HTMLInputElement).value; - try { - nbgraderMeta.points = parseInt(newValue, 10) - } catch(e) { - nbgraderMeta.points = 0; + if (outputMount.children[0] !== this.jupyterOutputArea!.node) { + outputMount.innerHTML = ""; + outputMount.append(this.jupyterOutputArea!.node); } - if (isNaN(nbgraderMeta.points) || nbgraderMeta.points < 0) { - nbgraderMeta.points = 0; + } + const codeToRun = this.cell.textContent; + + this.lastRunId++; + const currentRunId = this.lastRunId; + this.isCurrentlyRunning = true; + let status: "ok" | "abort" | "error" = "ok"; + + // Cell output value + let val = undefined; + let err = undefined; + + if (this.useJupyterBackend) { + await jupyterPlugin.exports.getGlobalKernelManager().runCode({ code: codeToRun }, this.jupyterOutputArea!); + const x = await this.jupyterOutputArea!.future.done; + status = x.content.status; + val = x.content; + } else { + try { + val = await pythonPlugin.runStarboardPython(this.runtime, codeToRun, outputMount); + } catch (e) { + status = "error"; + err = e; } - - this.updateRender(); - } + } - private toggleExpansion() { - this.topbarExpanded = !this.topbarExpanded; - this.updateRender(); - } + this.isCurrentlyLoadingPyodide = false; + if (this.lastRunId === currentRunId) { + this.isCurrentlyRunning = false; + lithtml.render(this.getControls(), this.elements.topControlsElement); - topTemplate() { - const md = this.getNBGraderMetadata(); - - const graderDefinition = DEFINITIONS[this.graderType]; - - let topbarControls: TemplateResult | undefined; - - if (this.topbarExpanded) { - topbarControls = html` -
-
-
- ${Object.entries(DEFINITIONS) - .map(([type, def]) => - html` - - ` - )} -
- - ${graderDefinition.hasPoints ? - html` - ${graderDefinition.hasPoints ? - html` -
- Points - -
` - : undefined - } - ` : undefined } - -
- ${graderDefinition.supportedCellTypes.map(ct => html` - `)} -
-
- -

${graderDefinition.description}

- -
` + let runnerStatusCode: CodeRunnerResult = status !== "ok" ? "fail" : "success"; + if (this.graderType === "autograder-tests") { + runnerStatusCode = status !== "ok" ? "test-fail" : "test-success"; } + if (status === "abort") { + runnerStatusCode = "abort"; + } + this.codeRunnerFeedbackElement.setRunResult(runnerStatusCode); + } - return html` - - ${topbarControls} -
${this.editor}
- ` - } + if (err !== undefined) throw err; - attach(params: CellHandlerAttachParameters) { - this.elements = params.elements; - this.setupEditor(); - this.updateRender(); + return val; } + } - async run() { - // TODO: evaluate Python if it's a Python cell. - if (this.underlyingCellType === "markdown") { - this.updateRender(); - } else if (this.underlyingCellType === "python"){ - const pythonPlugin = await this.runtime.exports.libraries.async.StarboardPython(); - this.codeRunnerFeedbackElement.reset(); - - const codeToRun = this.cell.textContent; - - this.lastRunId++; - const currentRunId = this.lastRunId; - this.isCurrentlyRunning = true; - this.codeRunnerFeedbackElement.setRunResult("running"); - - if (pythonPlugin.getPyodideLoadingStatus() !== "ready") { - this.isCurrentlyLoadingPyodide = true; - this.codeRunnerFeedbackElement.setRunResult("running-setup"); - lithtml.render(this.getControls(), this.elements.topControlsElement); - } - - let val = undefined; - let didError = false; - try { - val = await pythonPlugin.runStarboardPython(this.runtime, codeToRun, this.codeRunnerFeedbackElement.getOutputElement()); - } catch(e) { - didError = true; - } - - this.isCurrentlyLoadingPyodide = false; - if (this.lastRunId === currentRunId) { - this.isCurrentlyRunning = false; - lithtml.render(this.getControls(), this.elements.topControlsElement); - - let runnerStatusCode: CodeRunnerResult = didError ? "fail" : "success"; - if (this.graderType === "autograder-tests") { - runnerStatusCode = didError ? "test-fail" : "test-success"; - } - this.codeRunnerFeedbackElement.setRunResult(runnerStatusCode); - } - - return val; - } - } + focusEditor() { + this.editor?.focus(); + } - focusEditor() { - this.editor?.focus(); - } + async dispose() { + this.editor?.remove(); + } - async dispose() { - this.editor?.remove(); - } + clear() { + const outputMount = this.codeRunnerFeedbackElement.getOutputElement(); + this.codeRunnerFeedbackElement.reset(); + lithtml.render(lithtml.html``, outputMount); + } } export function registerGraderCellType() { - runtime.definitions.cellTypes.register(GRADER_CELL_TYPE_DEFINITION.cellType, GRADER_CELL_TYPE_DEFINITION); + runtime.definitions.cellTypes.register(GRADER_CELL_TYPE_DEFINITION.cellType, GRADER_CELL_TYPE_DEFINITION); } - - diff --git a/src/converter.ts b/src/converter.ts index 57b57b7..a650a14 100644 --- a/src/converter.ts +++ b/src/converter.ts @@ -1,57 +1,60 @@ import { NotebookContent } from "starboard-notebook/dist/src/types"; -import { textToNotebookContent } from "starboard-notebook/dist/src/content/parsing" -import { notebookContentToText } from "starboard-notebook/dist/src/content/serialization" +import { textToNotebookContent } from "starboard-notebook/dist/src/content/parsing"; +import { notebookContentToText } from "starboard-notebook/dist/src/content/serialization"; import { NBGraderMetadata, StarboardGraderMetadata } from "./types"; /** * Transforms given notebook content, replacing python and markdown cells that have nbgrader metadata with a special grader cell type. */ export function upgradeNBGraderCells(nb: NotebookContent | string) { - if (typeof nb === "string") { - nb = textToNotebookContent(nb); - } else { - // Poor man's copy - nb = JSON.parse(JSON.stringify(nb)); - } + if (typeof nb === "string") { + nb = textToNotebookContent(nb); + } else { + // Poor man's copy + nb = JSON.parse(JSON.stringify(nb)); + } - // Make TS happy - if (typeof nb === "string") { - return; - } + // Make TS happy + if (typeof nb === "string") { + return; + } - nb.cells.forEach(c => { - const md = c.metadata.nbgrader as NBGraderMetadata; - if (md) { - if (!md.grade && md.locked && !md.task && !md.solution) { - // This cell is only "locked", it is not a "task" per say. - c.metadata.properties.nbgrader_locked = true; - } - else { - (c.metadata.starboard_grader as StarboardGraderMetadata) = {original_cell_type: c.cellType as "markdown" | "python"}; - c.cellType = "grader"; - } - } - }); + nb.cells.forEach((c) => { + const md = c.metadata.nbgrader as NBGraderMetadata; + if (md) { + if (!md.grade && md.locked && !md.task && !md.solution) { + // This cell is only "locked", it is not a "task" per say. + c.metadata.properties.nbgrader_locked = true; + } else { + (c.metadata.starboard_grader as StarboardGraderMetadata) = { + original_cell_type: c.cellType as "markdown" | "python", + }; + c.cellType = "grader"; + } + } + }); - return notebookContentToText(nb); + return notebookContentToText(nb); } export function prependPluginLoaderCell(nb: string) { - const content = textToNotebookContent(nb); + const content = textToNotebookContent(nb); - content.cells = [ - { - cellType: "javascript", - metadata: {id: "nbgrader-init-cell", properties:{run_on_load: true}}, - id: "nbgrader-init-cell", - textContent: `const baseImport = (path) => import(document.querySelector("base").href + path); -const {initPlugin} = await baseImport("../dist/plugin.js"); -initPlugin(); + content.cells = [ + { + cellType: "javascript", + metadata: { id: "nbgrader-init-cell", properties: { run_on_load: true } }, + id: "nbgrader-init-cell", + textContent: `const baseImport = (path) => import(document.querySelector("base").href + path); +const {plugin} = await baseImport("../dist/plugin.js"); +runtime.controls.registerPlugin(plugin, {jupyter: {serverSettings: {baseUrl: "http://localhost:8888"}}}); runtime.controls.removeCell("nbgrader-init-cell"); -` - }, ...content.cells] +`, + }, + ...content.cells, + ]; - return notebookContentToText(content); + return notebookContentToText(content); } /** @@ -59,37 +62,36 @@ runtime.controls.removeCell("nbgrader-init-cell"); * @param nb */ export function preprocessGraderCellsForJupystar(nb: NotebookContent | string) { + if (typeof nb === "string") { + nb = textToNotebookContent(nb); + } else { + // Poor man's copy + nb = JSON.parse(JSON.stringify(nb)); + } - if (typeof nb === "string") { - nb = textToNotebookContent(nb); - } else { - // Poor man's copy - nb = JSON.parse(JSON.stringify(nb)); - } + // Make TS happy + if (typeof nb === "string") { + return; + } - // Make TS happy - if (typeof nb === "string") { - return; - } - - nb.cells.forEach(c => { - if (c.cellType === "grader") { - const md = c.metadata.starboard_grader as StarboardGraderMetadata | undefined; + nb.cells.forEach((c) => { + if (c.cellType === "grader") { + const md = c.metadata.starboard_grader as StarboardGraderMetadata | undefined; - c.cellType = md === undefined ? "python" : md.original_cell_type; - delete (c.metadata as any).starboard_grader; - } else if (c.metadata.properties.nbgrader_locked) { - const md: NBGraderMetadata = { - locked: true, - grade_id: c.id, - grade: false, - solution: false, - schema_version: 3, - task: false, - } - c.metadata.nbgrader = md; - } - }); + c.cellType = md === undefined ? "python" : md.original_cell_type; + delete (c.metadata as any).starboard_grader; + } else if (c.metadata.properties.nbgrader_locked) { + const md: NBGraderMetadata = { + locked: true, + grade_id: c.id, + grade: false, + solution: false, + schema_version: 3, + task: false, + }; + c.metadata.nbgrader = md; + } + }); - return notebookContentToText(nb); + return notebookContentToText(nb); } diff --git a/src/definitions.ts b/src/definitions.ts index a092870..ba0a400 100644 --- a/src/definitions.ts +++ b/src/definitions.ts @@ -1,104 +1,100 @@ - import { TemplateResult } from "lit-html"; import { Runtime } from "starboard-notebook/dist/src/types"; import { LitHtml } from "starboard-notebook/dist/src/runtime/esm/exports/libraries"; import { NBGraderMetadata } from "./types"; - -declare const runtime: Runtime +declare const runtime: Runtime; declare const html: typeof LitHtml.html; export type GraderCellType = "manual-answer" | "manual-task" | "autograder-answer" | "autograder-tests"; export interface GraderCellTypeDefinition { - /** - * One paragraph description, used as inline help text. - */ - description: TemplateResult, + /** + * One paragraph description, used as inline help text. + */ + description: TemplateResult; - id: GraderCellType; + id: GraderCellType; - /** - * Name for human consumption, short, example usage is as button text. - */ - name: string, + /** + * Name for human consumption, short, example usage is as button text. + */ + name: string; - emoji: string, + emoji: string; - supportedCellTypes: ("python" | "markdown")[], + supportedCellTypes: ("python" | "markdown")[]; - /** - * Does this type of cell have points associated with it when grading? - */ - hasPoints: boolean, + /** + * Does this type of cell have points associated with it when grading? + */ + hasPoints: boolean; } export const GraderCellTypeDefinitions: Record = { - "manual-answer": { - id: "manual-answer", - name: "Graded answer cell", - supportedCellTypes: ["markdown", "python"], - hasPoints: true, - emoji: "โœ๏ธ", - description: html` -

- In a graded answer cell the student enters their answer in a specific location in this cell. -
This makes it a good choice for free-form answers. After submission these cells are graded manually. -

` - }, - "manual-task": { - id: "manual-task", - name: "Graded task", - supportedCellTypes: ["markdown", "python"], - hasPoints: true, - emoji: "๐Ÿ“", - description: html` -

- In a graded task the student adds their answer across the notebook. -
Use this for free-form answers that span multiple cells, or for tasks that are global (e.g. "Make sure all Python code follows the PEP8 style guidelines"). After submission these cells graded manually. -

`}, - "autograder-answer": { - id: "autograder-answer", - name: "Auto-graded task", - supportedCellTypes: ["python"], - hasPoints: false, - emoji: "๐Ÿงช", - description: html` -

- An Auto-graded task is a code assignment that is graded automatically. - Points are earned in separate Auto-grader test cells. -

-
+ "manual-answer": { + id: "manual-answer", + name: "Graded answer cell", + supportedCellTypes: ["markdown", "python"], + hasPoints: true, + emoji: "โœ๏ธ", + description: html`

+ In a graded answer cell the student enters their answer in a specific location in this cell.
This + makes it a good choice for free-form answers. After submission these cells are graded manually. +

`, + }, + "manual-task": { + id: "manual-task", + name: "Graded task", + supportedCellTypes: ["markdown", "python"], + hasPoints: true, + emoji: "๐Ÿ“", + description: html`

+ In a graded task the student adds their answer across the notebook.
Use this for free-form answers + that span multiple cells, or for tasks that are global (e.g. "Make sure all Python code follows the PEP8 style + guidelines"). After submission these cells graded manually. +

`, + }, + "autograder-answer": { + id: "autograder-answer", + name: "Auto-graded task", + supportedCellTypes: ["python"], + hasPoints: false, + emoji: "๐Ÿงช", + description: html`

+ An Auto-graded task is a code assignment that is graded automatically. Points are earned in separate + Auto-grader test cells. +

+
View Example

- The student's answer is delimited by special BEGIN SOLUTION and END SOLUTION comments, anything in this section will not be visible to the student. + The student's answer is delimited by special BEGIN SOLUTION and + END SOLUTION comments, anything in this section will not be visible to the student.

-
def squares(n):
+        
def squares(n):
     """Compute the squares of numbers from 1 to n"""
     ### BEGIN SOLUTION
     if n < 1:
         raise ValueError("n must be greater than or equal to 1")
     return [i**2 for i in range(1, n+1)]
     ### END SOLUTION
- -
` - }, - "autograder-tests": { - id: "autograder-tests", - name: "Auto-grader test", - supportedCellTypes: ["python"], - hasPoints: true, - emoji: "๐Ÿค–", - description: html` -

- An Auto-grader test cell is used to score code assignments automatically. Points are only scored if all tests in the cell pass. -

-
+
`, + }, + "autograder-tests": { + id: "autograder-tests", + name: "Auto-grader test", + supportedCellTypes: ["python"], + hasPoints: true, + emoji: "๐Ÿค–", + description: html` +

+ An Auto-grader test cell is used to score code assignments automatically. Points are only scored if all + tests in the cell pass. +

+
View Example -

- Test conditions can be hidden from the student using special BEGIN HIDDEN TESTS comments. -

-
import nose
+        

Test conditions can be hidden from the student using special BEGIN HIDDEN TESTS comments.

+
import nose
 from nose.tools import assert_equal
 
 assert_equal(squares(1), [1])
@@ -108,45 +104,43 @@ assert_equal(squares(2), [1, 4])
 assert_equal(squares(3), [1, 4, 9])
 ### END HIDDEN TESTS
 
-
-` - - } -} +
+ `, + }, +}; export function getDefaultCellNBGraderMetadata(cellId: string): NBGraderMetadata { - const md: NBGraderMetadata = { - solution: true, - grade: true, - points: 1, - task: false, - grade_id: cellId, - locked: false, - schema_version: 3, - } - return md; + const md: NBGraderMetadata = { + solution: true, + grade: true, + points: 1, + task: false, + grade_id: cellId, + locked: false, + schema_version: 3, + }; + return md; } /** * Mutates the given NBGraderMetadata such that it is valid for the new grader cell type. */ export function convertNBGraderType(md: NBGraderMetadata, newType: GraderCellType, pointCount: number) { - if (newType === "manual-answer") { - md.grade = md.solution = true; - md.task = md.locked = false; - md.points = md.points || pointCount; - } else if (newType === "manual-task") { - md.grade = md.solution = false; - md.task = md.locked = true; - md.points = md.points || pointCount; - } else if (newType === "autograder-answer") { - md.grade = md.task = md.locked = false; - md.solution = true; - delete md.points; - } else if (newType === "autograder-tests") { - md.grade = md.locked = true; - md.solution = md.task = false; - md.points = md.points || pointCount; - } - -} \ No newline at end of file + if (newType === "manual-answer") { + md.grade = md.solution = true; + md.task = md.locked = false; + md.points = md.points || pointCount; + } else if (newType === "manual-task") { + md.grade = md.solution = false; + md.task = md.locked = true; + md.points = md.points || pointCount; + } else if (newType === "autograder-answer") { + md.grade = md.task = md.locked = false; + md.solution = true; + delete md.points; + } else if (newType === "autograder-tests") { + md.grade = md.locked = true; + md.solution = md.task = false; + md.points = md.points || pointCount; + } +} diff --git a/src/elements/codeRunnerFeedback.ts b/src/elements/codeRunnerFeedback.ts index fc6fece..6d5065e 100644 --- a/src/elements/codeRunnerFeedback.ts +++ b/src/elements/codeRunnerFeedback.ts @@ -1,84 +1,81 @@ -import {LitElement, LitHtml} from "starboard-notebook/dist/src/runtime/esm/exports/libraries"; +import { LitElement, LitHtml } from "starboard-notebook/dist/src/runtime/esm/exports/libraries"; -export type CodeRunnerResult = "empty" | "success" | "test-success" | "test-fail" | "fail" | "running" | "running-setup"; +export type CodeRunnerResult = + | "empty" + | "success" + | "test-success" + | "test-fail" + | "fail" + | "running" + | "running-setup" + | "abort"; const html = LitHtml.html; @LitElement.customElement("grader-code-feedback") export class CodeRunnerFeedbackElement extends LitElement.LitElement { - showOutput: boolean = true; + showOutput: boolean = true; + result: CodeRunnerResult = "empty"; - result: CodeRunnerResult = "empty"; + @LitElement.query(".grader-code-cell-output") + outputElement!: HTMLElement; - @LitElement.query(".grader-code-cell-output") - outputElement!: HTMLElement; + constructor() { + super(); + } - constructor() { - super(); - } + createRenderRoot() { + return this; + } - createRenderRoot() { - return this; - } + reset() { + this.result = "empty"; + this.performUpdate(); + } - reset() { - this.result = "empty"; - this.performUpdate(); - } + setRunResult(c: CodeRunnerResult) { + this.result = c; + this.performUpdate(); + } - setRunResult(c: CodeRunnerResult) { - this.result = c; - this.performUpdate(); - } + /** + * A HTML element where the output of the cell should be shown (such as a console output element). + * @returns + */ + getOutputElement() { + return this.outputElement; + } - getOutputElement() { - return this.outputElement; - } - - render() { - return html` - ${this.result === "empty" ? undefined : - html` -
- ${ - (() => { - switch(this.result) { - case("success"): { - return html`
- โœ… Code ran succesfully -
` - } - case("fail"): { - return html`
- โŒ An error was thrown -
` - } - case("test-success"): { - return html`
- โœ… Tests passed -
` - } - case("test-fail"): { - return html`
- โŒ Tests failed. -
` - } - case("running"): { - return html`
- โš™๏ธ Cell is running.. -
` - } - case("running-setup"): { - return html`
- โš™๏ธ Cell is running.. (First time Python setup.. please wait) -
` - } - } - - })() - } -
` - } -
` - } + render() { + return html` ${this.result === "empty" + ? undefined + : html`
+ ${(() => { + switch (this.result) { + case "success": { + return html`
โœ… Code ran succesfully
`; + } + case "fail": { + return html`
โŒ An error was thrown
`; + } + case "test-success": { + return html`
โœ… Tests passed
`; + } + case "test-fail": { + return html`
โŒ Tests failed.
`; + } + case "running": { + return html`
โš™๏ธ Cell is running..
`; + } + case "running-setup": { + return html`
โš™๏ธ Cell is running.. (First time Python setup.. please wait)
`; + } + case "abort": { + return html`
โŒ Cell aborted
`; + } + } + })()} +
`} +
`; + } } diff --git a/src/elements/graderBar.ts b/src/elements/graderBar.ts new file mode 100644 index 0000000..b285caf --- /dev/null +++ b/src/elements/graderBar.ts @@ -0,0 +1,195 @@ +import { TemplateResult } from "lit-element"; +import { Runtime } from "starboard-notebook/dist/src/types"; +import { registerJupyterPlugin } from "../jupyter"; +import { GraderPluginOpts } from "../plugin"; +import { getPythonExecutionMode, PythonGraderCellExecutionMode, setPythonExecutionMode } from "../state"; + +const LitElement = (window.runtime as Runtime).exports.libraries.LitElement; +const html = LitElement.html; + +const runtimeDescriptions = { + jupyter: "Jupyter", + pyodide: "Pyodide", +}; + +type JupyterPluginLoadStatus = "unstarted" | "loading" | "error-during-loading" | "loaded"; +type RunningAllCellsStatus = "unstarted" | "running" | "success" | "fail"; + +@LitElement.customElement("starboard-grader-bar") +export class StarboardGraderBar extends LitElement.LitElement { + set executionMode(val: PythonGraderCellExecutionMode) { + setPythonExecutionMode(val); + } + get executionMode() { + return getPythonExecutionMode(); + } + + private opts: GraderPluginOpts; + private jupyterPluginStatus: JupyterPluginLoadStatus = "unstarted"; + private runningAllCellsStatus: RunningAllCellsStatus = "unstarted"; + private runtime: Runtime; + + constructor(opts: GraderPluginOpts, runtime: Runtime) { + super(); + this.opts = opts; + this.runtime = runtime; + + if (this.opts.jupyter.serverSettings === undefined) { + this.opts.jupyter.serverSettings = { + baseUrl: "http://localhost:8888", + token: "", + }; + } + } + + createRenderRoot() { + return this; + } + + disconnectedCallback() { + super.disconnectedCallback(); + } + + private setRunningAllCellsStatus(status: RunningAllCellsStatus) { + this.runningAllCellsStatus = status; + this.performUpdate(); + } + + async enableJupyter(event: Event) { + event.preventDefault(); + this.opts.jupyter.serverSettings!.baseUrl = (this.querySelector( + 'input[name="jupyter-server-url"]' + ) as HTMLInputElement).value; + this.opts.jupyter.mount = (this.querySelector(".jupyter-plugin-mount") as HTMLElement) || undefined; + this.jupyterPluginStatus = "loading"; + this.performUpdate(); + try { + await registerJupyterPlugin(this.opts.jupyter, this.opts.jupyterPluginUrl); + } catch (e) { + this.jupyterPluginStatus = "error-during-loading"; + this.performUpdate(); + throw e; + } + this.jupyterPluginStatus = "loaded"; + this.performUpdate(); + } + + switchExecutionMode() { + this.executionMode = this.executionMode === "jupyter" ? "pyodide" : "jupyter"; + this.clearAllCells(); + } + + private async runAllCells() { + this.clearAllCells(); + + this.setRunningAllCellsStatus("running"); + try { + await this.runtime.controls.runAllCells({}); + this.setRunningAllCellsStatus("success"); + } catch (e) { + this.setRunningAllCellsStatus("fail"); + throw e; + } + } + + private clearAllCells() { + try { + this.setRunningAllCellsStatus("unstarted"); + this.runtime.controls.clearAllCells(); + } catch (e) { + console.error("Failed to clear all cells:", e); + } + } + + render() { + let content: TemplateResult; + if (this.jupyterPluginStatus === "unstarted") { + content = html`
this.enableJupyter(e)}> +
+ You can connect to a running Jupyter kernel to run Python assignment cells on a remote machine. +
+
+ + +
+
`; + } else if (this.jupyterPluginStatus === "loading") { + content = html`
+ โŒ› Jupyter Plugin loading.. +
`; + } else if (this.jupyterPluginStatus === "error-during-loading") { + content = html`
+ โŒ Something went wrong loading the plugin, please check your browser's console for details.
+ Refresh the page to try again. +
`; + } else { + content = html`
`; + } + + let runAllIndicator = undefined; + + if (this.runningAllCellsStatus === "fail") { + runAllIndicator = html`โŒ Cell error`; + } else if (this.runningAllCellsStatus === "success") { + runAllIndicator = html`Ran all cells without errors`; + } else if (this.runningAllCellsStatus === "running") { + runAllIndicator = html`โš™๏ธ Running all cells..`; + } + + return html` +
+
+ +
+

Notebook Assignment Creator

+ Click to expand +
+
+
+ ${this.jupyterPluginStatus !== "loaded" + ? undefined + : this.executionMode === "pyodide" + ? html`` + : html``} +
+
+ + ${runtimeDescriptions[this.executionMode]} + +
+
+
+ +
+
+ + +
${runAllIndicator}
+
+
${content}
+
+
+
+
+ `; + } +} diff --git a/src/graderUtils.ts b/src/graderUtils.ts index f330e3a..a75b80b 100644 --- a/src/graderUtils.ts +++ b/src/graderUtils.ts @@ -2,23 +2,23 @@ import { GraderCellType } from "./definitions"; import { NBGraderMetadata } from "./types"; export function graderMetadataToNBGraderCellType(m: NBGraderMetadata | undefined): GraderCellType { - if (m === undefined) { // Default - return "manual-answer"; - } - if (m.points === undefined) { - return "autograder-answer"; - } + if (m === undefined) { + // Default + return "manual-answer"; + } + if (m.points === undefined) { + return "autograder-answer"; + } - if (m.grade && m.solution && !m.task && !m.locked) { - return "manual-answer"; - } else if (!m.grade && !m.solution && m.task && m.locked) { - return "manual-task"; - } else if (!m.grade && m.solution && !m.task && !m.locked) { - return "autograder-answer" - } else if (m.grade && !m.solution && !m.task && m.locked) { - return "autograder-tests"; - } - console.error("Possibly invalid nbgrader cell metadata:", m); + if (m.grade && m.solution && !m.task && !m.locked) { return "manual-answer"; + } else if (!m.grade && !m.solution && m.task && m.locked) { + return "manual-task"; + } else if (!m.grade && m.solution && !m.task && !m.locked) { + return "autograder-answer"; + } else if (m.grade && !m.solution && !m.task && m.locked) { + return "autograder-tests"; + } + console.error("Possibly invalid nbgrader cell metadata:", m); + return "manual-answer"; } - diff --git a/src/jupyter.ts b/src/jupyter.ts new file mode 100644 index 0000000..98c1345 --- /dev/null +++ b/src/jupyter.ts @@ -0,0 +1,22 @@ +import type { plugin as JPlugin } from "starboard-jupyter/dist/index"; +import type { JupyterPluginSettings } from "starboard-jupyter/dist/types"; +import { Runtime } from "starboard-notebook/dist/src/types"; + +export type { JupyterPluginSettings } from "starboard-jupyter/dist/types"; + +declare const runtime: Runtime; + +let singletonPlugin: undefined | typeof JPlugin = undefined; + +export async function registerJupyterPlugin( + opts: JupyterPluginSettings, + pluginUrl: string = "https://unpkg.com/starboard-jupyter@0.2.8/dist/index.js" +) { + const { plugin } = await import(pluginUrl); + singletonPlugin = plugin; + return runtime.controls.registerPlugin(plugin, opts); +} + +export function getJupyterPlugin(): typeof JPlugin { + return singletonPlugin as typeof JPlugin; +} diff --git a/src/lockedProperty.ts b/src/lockedProperty.ts index b325c13..c64eddc 100644 --- a/src/lockedProperty.ts +++ b/src/lockedProperty.ts @@ -3,11 +3,11 @@ import { Runtime } from "starboard-notebook/dist/src/types"; declare const runtime: Runtime; export function registerStudentLockedCellProperty() { - runtime.definitions.cellProperties.register("nbgrader_locked", { - name: "Locked for students", - textEnabled: "Locked for students: they won't be able to edit this cell.", - textDisabled: "Lock cell for students (stop them from editing)", - cellProperty: "nbgrader_locked", - icon: () => "STUDENT LOCK", - }); + runtime.definitions.cellProperties.register("nbgrader_locked", { + name: "Locked for students", + textEnabled: "Locked for students: they won't be able to edit this cell.", + textDisabled: "Lock cell for students (stop them from editing)", + cellProperty: "nbgrader_locked", + icon: () => "STUDENT LOCK", + }); } diff --git a/src/plugin.ts b/src/plugin.ts index 5121f45..7eb35e5 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,17 +1,36 @@ +import { Runtime, StarboardPlugin } from "starboard-notebook/dist/src/types"; import { registerGraderCellType } from "./cellType"; +import { StarboardGraderBar } from "./elements/graderBar"; +import { JupyterPluginSettings } from "./jupyter"; import { registerStudentLockedCellProperty } from "./lockedProperty"; -export {GraderCellHandler, registerGraderCellType} from "./cellType"; +export { GraderCellHandler, registerGraderCellType } from "./cellType"; // @ts-ignore import css from "./styles.css"; -export function initPlugin() { +export type GraderPluginOpts = { + jupyter: JupyterPluginSettings; + jupyterPluginUrl?: string; +}; + +export const plugin: StarboardPlugin = { + id: "starboard-nbgrader", + metadata: { + name: "Starboard NBGrader", + }, + exports: {}, + async register(runtime: Runtime, opts: GraderPluginOpts = { jupyter: {} }) { + const topbar = new StarboardGraderBar(opts, runtime); + const nb = document.querySelector("starboard-notebook"); + if (nb) nb.prepend(topbar); + registerGraderCellType(); registerStudentLockedCellProperty(); - const styleSheet = document.createElement("style") + const styleSheet = document.createElement("style"); styleSheet.id = "nbgrader-styles"; - styleSheet.innerHTML = css - document.head.appendChild(styleSheet) -} + styleSheet.innerHTML = css; + document.head.appendChild(styleSheet); + }, +}; diff --git a/src/state.ts b/src/state.ts new file mode 100644 index 0000000..91a91e3 --- /dev/null +++ b/src/state.ts @@ -0,0 +1,13 @@ +// Some global state for the plugin.. + +export type PythonGraderCellExecutionMode = "pyodide" | "jupyter" + +let executionMode: PythonGraderCellExecutionMode = "pyodide"; + +export function getPythonExecutionMode() { + return executionMode; +} + +export function setPythonExecutionMode(m: PythonGraderCellExecutionMode) { + executionMode = m; +} \ No newline at end of file diff --git a/src/styles.css b/src/styles.css index 53c1612..18cbfd9 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,113 +1,138 @@ .grader-cell { - border: 3px solid #fff; - background-color: #fafafa; - padding: 0.8em; - border-radius: 6px; - border-top-left-radius: 0; + border: 3px solid #fff; + background-color: #fafafa; + padding: 0.8em; + border-radius: 6px; + border-top-left-radius: 0; } .grader-cell-top-bar { - margin-bottom: 1em; + margin-bottom: 1em; } .grader-cell pre { - padding: 0 1em; - background-color: #f2f2f2; - border-left: 4px solid #d0d0d0; + padding: 0 1em; + background-color: #f2f2f2; + border-left: 4px solid #d0d0d0; } .grader-code-feedback-bar { - border: 1px solid #999; - background-color: #fafafa; - padding: 0.2em 0.4em; - font-size: 0.8em; + border: 1px solid #999; + background-color: #fafafa; + padding: 0.2em 0.4em; + font-size: 0.8em; } -.grader-code-feedback-bar.success, .grader-code-feedback-bar.test-success{ - border: 1px solid #00ce6e; - background-color: #baedc0; +.grader-code-feedback-bar.success, +.grader-code-feedback-bar.test-success { + border: 1px solid #00ce6e; + background-color: #baedc0; } -.grader-code-feedback-bar.fail, .grader-code-feedback-bar.test-fail { - border: 1px solid #d20d0d; - background-color: #eba0ac; +.grader-code-feedback-bar.fail, +.grader-code-feedback-bar.test-fail { + border: 1px solid #d20d0d; + background-color: #eba0ac; } -.grader-code-feedback-bar.running, .grader-code-feedback-bar.running-setup { - border: 1px solid #ceff93; - background-color: #e4f6ff; +.grader-code-feedback-bar.running, +.grader-code-feedback-bar.running-setup { + border: 1px solid #ceff93; + background-color: #e4f6ff; } .grader-pill { - padding: 0.16em 0.6em; - border-radius: 9px; - background-color: var(--brand-color); - width: max-content; - margin: 0.4em 0.4em 0.4em 0; - color: #fff; - transition: filter ease-in-out 0.15s; - border: 0; + padding: 0.16em 0.6em; + border-radius: 9px; + background-color: var(--brand-color); + width: max-content; + margin: 0.4em 0.4em 0.4em 0; + color: #fff; + transition: filter ease-in-out 0.15s; + border: 0; } .grader-pill.expanded { - margin-bottom: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; + margin-bottom: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } .grader-controls { - display: flex; - align-items: baseline; + display: flex; + align-items: baseline; } .grader-controls * .btn { - background-color: #fefefe; - border-color: #6c757d; + background-color: #fefefe; + border-color: #6c757d; } .grader-controls * .btn:hover { - filter: brightness(0.95); + filter: brightness(0.95); } .grader-controls * .btn.active { - font-weight: bold; + font-weight: bold; } .grader-pill:hover { - filter: brightness(1.03); + filter: brightness(1.03); } -.grader-pill.manual-task, .btn.manual-task.active { - background-color: #ceff93; - color: #313131; +.grader-pill.manual-task, +.btn.manual-task.active { + background-color: #ceff93; + color: #313131; } .grader-cell.manual-task { - border-color: #ceff93; + border-color: #ceff93; } -.grader-pill.manual-answer, .btn.manual-answer.active { - background-color: #ffe6ab; - color: #313131; +.grader-pill.manual-answer, +.btn.manual-answer.active { + background-color: #ffe6ab; + color: #313131; } .grader-cell.manual-answer { - border-color: #ffe6ab; + border-color: #ffe6ab; } -.grader-pill.autograder-answer, .btn.autograder-answer.active { - background-color: #00307b; - color: #fff; +.grader-pill.autograder-answer, +.btn.autograder-answer.active { + background-color: #4c86e1; + color: #fff; } .grader-cell.autograder-answer { - border-color: #00307b; + border-color: #4c86e1; } -.grader-pill.autograder-tests, .btn.autograder-tests.active { - background-color: #851cb6; - color: #fff; +.grader-pill.autograder-tests, +.btn.autograder-tests.active { + background-color: #995fdf; + color: #fff; } .grader-cell.autograder-tests { - border-color: #851cb6; + border-color: #995fdf; +} + +starboard-grader-bar { + display: grid; + grid-template-columns: [full-width-start] auto [margin-left-start] var(--cell-margin-left) [margin-left-end content-start] minmax( + auto, + calc(min(var(--cell-base-width), 100% - var(--cell-margin-left) - var(--cell-margin-right))) + ) [content-end margin-right-start] var(--cell-margin-right) [margin-right-end] auto [full-width-end]; +} + +.starboard-grader-interface { + grid-column: content-start / content-end; + border-radius: var(--border-radius); + border: 1px solid var(--border-color); +} + +.x-small { + font-size: 0.625em; } diff --git a/src/types.ts b/src/types.ts index cbb90c5..f0a0402 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,13 +1,13 @@ export interface NBGraderMetadata { - grade: boolean, - grade_id: string, - locked: boolean, - schema_version: 3, - solution: boolean, - task: boolean - points?: number; + grade: boolean; + grade_id: string; + locked: boolean; + schema_version: 3; + solution: boolean; + task: boolean; + points?: number; } export interface StarboardGraderMetadata { - original_cell_type: "python" | "markdown"; -} \ No newline at end of file + original_cell_type: "python" | "markdown"; +} diff --git a/tsconfig.json b/tsconfig.json index 6fbc1f2..42acd3a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,11 +3,10 @@ "moduleResolution": "node", "downlevelIteration": true, "target": "ES2018", - "module": "es2015", + "module": "es2020", "lib": [ - "es2015", - "es2016", "es2017", + "es2018", "dom" ], "strict": true,