gwchq-textjam 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -101,14 +101,12 @@ The consumer's webpack config should include the following
101
101
  `TextJamEditor` accepts the following props (previously exposed as web-component attributes):
102
102
 
103
103
  - `assetsIdentifier`: Load assets (not code) from this project identifier
104
- - `authKey`: Authenticate the user to allow them to make API requests such as saving their work
105
104
  - `code`: A preset blob of code to show in the editor pane (overrides content of `main.py`/`index.html`)
106
105
  - `editableInstructions`: Boolean; show edit panel for instructions when `true`
107
106
  - `embedded`: Enable embedded mode which hides some functionality (defaults to `false`)
108
107
  - `identifier`: Load the project with this identifier from the database
109
108
  - `instructions`: JSON object containing steps to be displayed in the instructions panel in the sidebar
110
109
  - `loadCache`: Load latest version of project code from local storage (defaults to `true`)
111
- - `loadRemixDisabled`: Do not load a logged-in user's remixed version of the project specified by `identifier` even if one exists (defaults to `false`)
112
110
  - `locale`: Locale for UI elements and to determine the language of projects loaded from the API (defaults to `en`)
113
111
  - `outputOnly`: Only display the output panel (defaults to `false`)
114
112
  - `outputPanels`: Array of output panel names to display (defaults to `['text', 'visual']`)
@@ -116,7 +114,6 @@ The consumer's webpack config should include the following
116
114
  - `projectNameEditable`: Allow the user to edit the project name in the project bar (defaults to `false`)
117
115
  - `reactAppApiEndpoint`: API endpoint to send project-related requests to
118
116
  - `readOnly`: Display the editor in read-only mode (defaults to `false`)
119
- - `senseHatAlwaysEnabled`: Show the Astro Pi Sense HAT emulator on page load (defaults to `false`)
120
117
  - `showSavePrompt`: Prompt the user to save their work (defaults to `false`)
121
118
  - `sidebarOptions`: Array of strings specifying the panels to be displayed in the sidebar. Options include `"projects"`, `"instructions"`, `"file"`, `"images"`, `"download"`, `"settings"`, and `"info"`.
122
119
  - `sidebarPlugins`: Array of plugin definitions to render inside the sidebar (defaults to `[]`)
package/dist/360.index.js CHANGED
@@ -1 +1 @@
1
- export const id=360;export const ids=[360];export const modules={22796:e=>{e.exports=JSON.parse('{"modal":{"close":"Close","error":{"error":"Error","heading":"An error has occurred","externalLink":{"message":"Unfortunately links to external sites are not available in the Editor."}}},"editorPanel":{"ariaLabel":"editor text input","characterLimitError":"Error: Character limit reached","characterLimitExplanation_one":"Files in the editor are limited to {{count}} character","characterLimitExplanation_other":"Files in the editor are limited to {{count}} characters","viewOnly":"View only","close":"close"},"filePanel":{"errors":{"reservedFileName":"{{fileName}} is a reserved file name. Please choose a different name.","containsSpaces":"File names must not contain spaces.","generalError":"Error","notUnique":"File names must be unique.","or":"or","unsupportedExtension":"File names must end in {{allowedExtensions}}."},"files":"Project files","images":"Image gallery","newFileButton":"Add file","newFileModal":{"cancel":"Cancel","heading":"Add a new file to your project","helpText":"Remember to add the file extension at the end of your file name, for example, {{examples}}","helpTextExample":{"html":"\'file.html\', \'file.css\' or \'file.js\'","python":"\'file.py\'"},"inputLabel":"Name your file","addFile":"Add file"},"renameFileModal":{"cancel":"Cancel","heading":"Rename file","inputLabel":"Name your file","save":"Save"},"fileMenu":{"label":"Open file menu","renameItem":"Rename file"}},"downloadPanel":{"heading":"Save & download","logInTitle":"Log in to save your progress","logInHint":"With a Raspberry Pi Account you can save your code and project steps progress.","logInButton":"Log in to save","signUpButton":"Sign up","downloadHint":"Download your project files so you can use them offline and in a different code editor.","downloadButton":"Download project"},"footer":{"accessibility":"Accessibility","charityNameAndNumber":"Raspberry Pi Foundation UK registered charity 1129409","cookies":"Cookies","privacy":"Privacy","safeguarding":"Safeguarding"},"projectName":{"label":"Project name","newProject":"New Project"},"header":{"download":"Download","downloadFileNameDefault":"my {{project_type}} project","editorLogoAltText":"Editor logo","projects":"Your projects","renameProject":"Edit project name","renameSave":"Save project name","save":"Save","loginToSave":"Log in to save","settings":"Settings"},"imagePanel":{"gallery":"Image Gallery"},"infoPanel":{"info":"Information"},"instructionsPanel":{"demoInstructions":{"title":"How instructions work","enablingInstructions":"Enabling instructions","visible":"Any text written here will be visible to students in the sidebar.","writingInstructions":"Writing instructions","markdown":"Write your instructions using [Markdown](https://www.markdownguide.org/).","whatYouCanDo":"What you can do","lists":"Lists","bulletPoints":"Bullet points","numberedSteps":"Numbered steps"},"emptyState":{"addInstructions":"Add instructions","edits":"Like project code, students will not see any edits you make to the instructions after they have saved their version of the project.","location":"These instructions will be shown to students in their project sidebar and will be view-only.","markdown":"Instructions are written in <0>markdown</0>.","purpose":"Instructions can be added to your project to guide students."},"removeInstructions":"Remove instructions","nextStep":"Next step","previousStep":"Previous step","projectSteps":"Project instructions","edit":"Edit","view":"View","removeInstructionsModal":{"removeInstructions":"Remove instructions","close":"Close","heading":"Remove project instructions?","removeInstuctionsWarning":"You are about to remove the instructions from the project.","resultRemovingInstructions":"As a result of removing these instructions:","instructionsWillBeDeleted":"Instructions content will be deleted.","studentsWorkingProjectNotRecievedInstructions":"Students who start working on this project will not receive instructions.","studentsStartedWillSeeInstructions":"Students who have already started working on this project will still be able to see the instructions as they were when they started."}},"projectsPanel":{"projects":"Projects","yourProjectsButton":"Go to your projects","projectTypeLabel":"Project type"},"settingsPanel":{"info":"Settings"},"input":{"comment":{"py5":"Py5: imported mode"}},"mobile":{"code":"Code","menu":"Menu","output":"Output","preview":"Preview","steps":"Steps"},"modals":{"close":"Close"},"notifications":{"close":"close","loginPrompt":"To save this project and access it later, don\'t forget to log in or sign up!","projectRemixed":"Your remixed project has been saved","projectRenamed":"You have renamed your project.","projectSaved":"Your project has been saved","savePrompt":"Save this project to access it later under \\"Your projects\\"."},"output":{"errors":{"interrupted":"Execution interrupted"},"newTab":"Preview in new tab","preview":"preview","senseHat":{"controls":{"colour":"colour","humidity":"humidity","motion":"motion","motionSensorOptions":{"no":"No","yes":"Yes"},"name":"Space Station Control Panel","pressure":"pressure","temperature":"temperature","timer":"timer"},"model":{"pitch":"pitch","roll":"roll","yaw":"yaw"}},"textOutput":"Text output","visualOutput":"Visual output"},"outputViewToggle":{"buttonTabLabel":"Tabbed view","buttonTabTitle":"Tabbed view","buttonSplitLabel":"Split view","buttonSplitTitle":"Split view"},"project":{"accessDeniedWithAuthModal":{"embedded":{"text":"Visit the Projects site for cool project ideas"},"heading":"You can\'t access this project","newProject":"Create a new code project","projectsSiteLinkText":"Explore Projects site","text":"Visit the Projects site for cool project ideas or start coding in a new project."},"loading":"Loading","notFoundModal":{"embedded":{"text":"Visit the Projects site for cool project ideas"},"heading":"This project does not exist","newProject":"Start new code project","projectsSiteLinkText":"Explore Projects site","text":"You can start coding in a new project, or visit the Projects site for cool project ideas."},"untitled":"Untitled project"},"projectHeader":{"subTitle":"Code Editor","title":"Your projects","text":"Select a project to continue coding, view, or edit it."},"projectList":{"delete":"Delete","deleteLabel":"Delete project","empty":"No projects created yet","label":"Open project menu","loading":"Loading","loadingFailed":"Failed to load projects","newProject":"Create a new project","pagination":{"first":"First page","last":"Last page","next":"Next page","previous":"Previous page","more":"Load more projects"},"rename":"Rename","renameLabel":"Rename project","renameProjectModal":{"cancel":"Do not save","heading":"Rename project","inputLabel":"Change the name of your project","save":"Save"},"updated":"Edited","python_type":"Python","html_type":"HTML"},"projectTypes":{"html":"HTML/CSS","python":"Python"},"runButton":{"run":"Run","stop":"Stop","stopping":"Stopping..."},"saveStatus":{"saving":"Saving","saved":"Saved"},"runners":{"HtmlOutput":"HTML Output Preview"},"sidebar":{"collapse":"Collapse sidebar","download":"Download project","expand":"Expand sidebar","file":"Project files","images":"Image gallery","settings":"Settings","projects":"Projects","information":"Information","information_text":"Our Code Editor is a tool to help young people learn to code. We have only included functions that are simple and safe to use. That\'s why, for example, links to other websites are not allowed.","instructions":"Project instructions","feedback":"Feedback","help":"Help","privacy":"Privacy","cookies":"Cookies","accessibility":"Accessibility","safeguarding":"Safeguarding","charity":"Raspberry Pi Foundation - UK registered charity 1129409","settingsMenu":{"heading":"Settings","textSize":"Text size","theme":"Theme","textSizeOptions":{"large":"Large","medium":"Medium","small":"Small"},"themeOptions":{"dark":"Dark","light":"Light"}}},"webComponent":{"loading":"Loading","failed":"Load failed"},"imageUploadButton":{"uploadImage":"Upload image","uploadAnImage":"Upload an image","info":"Drag and drop images here, or click to select images from file","cancel":"Cancel","save":"Save","or":"or","errors":{"error":"Error","imageNameNotUnique":"Image names must be unique.","invalidImageExtension":"Image names must end in {{extensions}}."}},"newInputPanelButton":{"buttonText":"Add another panel"},"button":{"yes":"Yes","no":"No"},"common":{"or":"or"}}')}};
1
+ export const id=360;export const ids=[360];export const modules={22796:e=>{e.exports=JSON.parse('{"modal":{"close":"Close","error":{"error":"Error","heading":"An error has occurred","externalLink":{"message":"Unfortunately links to external sites are not available in the Editor."}}},"editorPanel":{"ariaLabel":"editor text input","characterLimitError":"Error: Character limit reached","characterLimitExplanation_one":"Files in the editor are limited to {{count}} character","characterLimitExplanation_other":"Files in the editor are limited to {{count}} characters","viewOnly":"View only","close":"close"},"filePanel":{"errors":{"reservedFileName":"{{fileName}} is a reserved file name. Please choose a different name.","containsSpaces":"File names must not contain spaces.","generalError":"Error","notUnique":"File names must be unique.","or":"or","unsupportedExtension":"File names must end in {{allowedExtensions}}."},"files":"Project files","images":"Image gallery","newFileButton":"Add file","newFileModal":{"cancel":"Cancel","heading":"Add a new file to your project","helpText":"Remember to add the file extension at the end of your file name, for example, {{examples}}","helpTextExample":{"html":"\'file.html\', \'file.css\' or \'file.js\'","python":"\'file.py\'"},"inputLabel":"Name your file","addFile":"Add file"},"renameFileModal":{"cancel":"Cancel","heading":"Rename file","inputLabel":"Name your file","save":"Save"},"fileMenu":{"label":"Open file menu","renameItem":"Rename file"}},"downloadPanel":{"heading":"Save & download","logInTitle":"Log in to save your progress","logInHint":"With a Raspberry Pi Account you can save your code and project steps progress.","logInButton":"Log in to save","signUpButton":"Sign up","downloadHint":"Download your project files so you can use them offline and in a different code editor.","downloadButton":"Download project"},"footer":{"accessibility":"Accessibility","charityNameAndNumber":"Raspberry Pi Foundation UK registered charity 1129409","cookies":"Cookies","privacy":"Privacy","safeguarding":"Safeguarding"},"projectName":{"label":"Project name","newProject":"New Project"},"header":{"download":"Download","downloadFileNameDefault":"my {{project_type}} project","editorLogoAltText":"Editor logo","projects":"Your projects","renameProject":"Edit project name","renameSave":"Save project name","save":"Save","loginToSave":"Log in to save","settings":"Settings"},"imagePanel":{"gallery":"Image Gallery"},"infoPanel":{"info":"Information"},"instructionsPanel":{"demoInstructions":{"title":"How instructions work","enablingInstructions":"Enabling instructions","visible":"Any text written here will be visible to students in the sidebar.","writingInstructions":"Writing instructions","markdown":"Write your instructions using [Markdown](https://www.markdownguide.org/).","whatYouCanDo":"What you can do","lists":"Lists","bulletPoints":"Bullet points","numberedSteps":"Numbered steps"},"emptyState":{"addInstructions":"Add instructions","edits":"Like project code, students will not see any edits you make to the instructions after they have saved their version of the project.","location":"These instructions will be shown to students in their project sidebar and will be view-only.","markdown":"Instructions are written in <0>markdown</0>.","purpose":"Instructions can be added to your project to guide students."},"removeInstructions":"Remove instructions","nextStep":"Next step","previousStep":"Previous step","projectSteps":"Project instructions","edit":"Edit","view":"View","removeInstructionsModal":{"removeInstructions":"Remove instructions","close":"Close","heading":"Remove project instructions?","removeInstuctionsWarning":"You are about to remove the instructions from the project.","resultRemovingInstructions":"As a result of removing these instructions:","instructionsWillBeDeleted":"Instructions content will be deleted.","studentsWorkingProjectNotRecievedInstructions":"Students who start working on this project will not receive instructions.","studentsStartedWillSeeInstructions":"Students who have already started working on this project will still be able to see the instructions as they were when they started."}},"projectsPanel":{"projects":"Projects","yourProjectsButton":"Go to your projects","projectTypeLabel":"Project type"},"settingsPanel":{"info":"Settings"},"input":{"comment":{"py5":"Py5: imported mode"}},"mobile":{"code":"Code","menu":"Menu","output":"Output","preview":"Preview","steps":"Steps"},"modals":{"close":"Close"},"notifications":{"close":"close","loginPrompt":"To save this project and access it later, don\'t forget to log in or sign up!","projectRenamed":"You have renamed your project.","projectSaved":"Your project has been saved","savePrompt":"Save this project to access it later under \\"Your projects\\"."},"output":{"errors":{"interrupted":"Execution interrupted"},"newTab":"Preview in new tab","preview":"preview","textOutput":"Text output","visualOutput":"Visual output"},"outputViewToggle":{"buttonTabLabel":"Tabbed view","buttonTabTitle":"Tabbed view","buttonSplitLabel":"Split view","buttonSplitTitle":"Split view"},"project":{"accessDeniedWithAuthModal":{"embedded":{"text":"Visit the Projects site for cool project ideas"},"heading":"You can\'t access this project","newProject":"Create a new code project","projectsSiteLinkText":"Explore Projects site","text":"Visit the Projects site for cool project ideas or start coding in a new project."},"loading":"Loading","notFoundModal":{"embedded":{"text":"Visit the Projects site for cool project ideas"},"heading":"This project does not exist","newProject":"Start new code project","projectsSiteLinkText":"Explore Projects site","text":"You can start coding in a new project, or visit the Projects site for cool project ideas."},"untitled":"Untitled project"},"projectHeader":{"subTitle":"Code Editor","title":"Your projects","text":"Select a project to continue coding, view, or edit it."},"projectList":{"delete":"Delete","deleteLabel":"Delete project","empty":"No projects created yet","label":"Open project menu","loading":"Loading","loadingFailed":"Failed to load projects","newProject":"Create a new project","pagination":{"first":"First page","last":"Last page","next":"Next page","previous":"Previous page","more":"Load more projects"},"rename":"Rename","renameLabel":"Rename project","renameProjectModal":{"cancel":"Do not save","heading":"Rename project","inputLabel":"Change the name of your project","save":"Save"},"updated":"Edited","python_type":"Python","html_type":"HTML"},"projectTypes":{"html":"HTML/CSS","python":"Python"},"runButton":{"run":"Run","stop":"Stop","stopping":"Stopping..."},"saveStatus":{"saving":"Saving","saved":"Saved"},"runners":{"HtmlOutput":"HTML Output Preview"},"sidebar":{"collapse":"Collapse sidebar","download":"Download project","expand":"Expand sidebar","file":"Project files","images":"Image gallery","settings":"Settings","projects":"Projects","information":"Information","information_text":"Our Code Editor is a tool to help young people learn to code. We have only included functions that are simple and safe to use. That\'s why, for example, links to other websites are not allowed.","instructions":"Project instructions","feedback":"Feedback","help":"Help","privacy":"Privacy","cookies":"Cookies","accessibility":"Accessibility","safeguarding":"Safeguarding","charity":"Raspberry Pi Foundation - UK registered charity 1129409","settingsMenu":{"heading":"Settings","textSize":"Text size","theme":"Theme","textSizeOptions":{"large":"Large","medium":"Medium","small":"Small"},"themeOptions":{"dark":"Dark","light":"Light"}}},"webComponent":{"loading":"Loading","failed":"Load failed"},"newInputPanelButton":{"buttonText":"Add another panel"},"button":{"yes":"Yes","no":"No"},"common":{"or":"or"}}')}};
@@ -0,0 +1 @@
1
+ function toAbsoluteFromOrigin(e){return e.startsWith("http")||e.startsWith("/")?e:new URL(e,self.location.origin).href}const PyodideWorker=()=>{let e;const t="undefined"!=typeof SharedArrayBuffer;let n,o,i,a,r;t||"incremental-features"===name||console.warn(["The code editor will not be able to capture standard input or stop execution because these HTTP headers are not set:"," - Cross-Origin-Opener-Policy: same-origin"," - Cross-Origin-Embedder-Policy: require-corp","","If your app can cope with or without these features, please initialize the web worker with { name: 'incremental-features' } to silence this warning.","You can then check for the presence of { stdinBuffer, interruptBuffer } in the handleLoaded message to check whether these features are supported.","","If you definitely need these features, either configure your server to respond with the HTTP headers above, or register a service worker.","Once the HTTP headers are set, the browser will block cross-domain resources so you will need to add 'crossorigin' to <script> and other tags.","You may wish to scope the HTTP headers to only those pages that host the code editor to make the browser restriction easier to deal with.","","Please refer to these code snippets for registering a service worker:"," - https://github.com/RaspberryPiFoundation/python-execution-prototypes/blob/fd2c50e032cba3bb0e92e19a88eb62e5b120fe7a/pyodide/index.html#L92-L98"," - https://github.com/RaspberryPiFoundation/python-execution-prototypes/blob/fd2c50e032cba3bb0e92e19a88eb62e5b120fe7a/pyodide/serviceworker.js"].join("\n"));addEventListener("message",(async t=>{(async({data:t})=>{n=await o;let i=new TextEncoder;switch(t.method){case"init":(t=>{e=t.assets,console.log("PyodideWorker","importing scripts"),importScripts(toAbsoluteFromOrigin(e.pygalUrl)),e.pyodideBaseUrl="https://cdn.jsdelivr.net/pyodide/v0.26.2/full/pyodide.js",importScripts(toAbsoluteFromOrigin(e.pyodideBaseUrl)),f()})(t);break;case"writeFile":n.FS.writeFile(t.filename,i.encode(t.content));break;case"runPython":s(t.python);break;case"stopPython":r=!0;break;default:throw new Error(`Unsupported method: ${t.method}`)}})(t)}));const s=async e=>{r=!1;try{await p(e,(async()=>{await n.runPython(e)}))}catch(e){if(!(e instanceof n.ffi.PythonError))throw e;postMessage({method:"handleError",...u(e)})}await h()},l=()=>{if(r)throw new n.ffi.PythonError("KeyboardInterrupt")},p=async(e,t=async()=>{})=>{const o=await n._api.pyodide_code.find_imports(e).toJs();await Promise.all(o.map((e=>c(e)))),l(),await n.loadPackagesFromImports(e),l(),await n.runPythonAsync('\n import basthon\n import builtins\n import os\n\n MAX_FILES = 100\n MAX_FILE_SIZE = 8500000\n\n def _custom_open(filename, mode="r", *args, **kwargs):\n if "x" in mode and os.path.exists(filename):\n raise FileExistsError(f"File \'{filename}\' already exists")\n if ("w" in mode or "a" in mode or "x" in mode) and "b" not in mode:\n if len(os.listdir()) > MAX_FILES and not os.path.exists(filename):\n raise OSError(f"File system limit reached, no more than {MAX_FILES} files allowed")\n class CustomFile:\n def __init__(self, filename):\n self.filename = filename\n self.content = ""\n\n def write(self, content):\n self.content += content\n if len(self.content) > MAX_FILE_SIZE:\n raise OSError(f"File \'{self.filename}\' exceeds maximum file size of {MAX_FILE_SIZE} bytes")\n with _original_open(self.filename, mode) as f:\n f.write(self.content)\n basthon.kernel.write_file({ "filename": self.filename, "content": self.content, "mode": mode })\n\n def close(self):\n pass\n\n def __enter__(self):\n return self\n\n def __exit__(self, exc_type, exc_val, exc_tb):\n self.close()\n\n return CustomFile(filename)\n else:\n return _original_open(filename, mode, *args, **kwargs)\n\n # Override the built-in open function\n builtins.open = _custom_open\n ',{filename:"__custom_open__.py"}),await t();for(let e of o)l(),await(d[e]?.after())},c=async e=>{if(l(),n.FS.readdir("/home/pyodide").includes(`${e}.py`)){const t=n.FS.readFile(`/home/pyodide/${e}.py`,{encoding:"utf8"});return void await p(t)}const t=d[e];if(await(t?.before()),t)return;let o,i;try{o=n.pyimport(e)}catch(e){}if(!o){await(n.loadPackage(e)?.catch((()=>{})));try{i=n.pyimport(e)}catch(e){}i||(n.micropip||(await n.loadPackage("micropip"),n.micropip=n.pyimport("micropip")),await n.micropip.install(e).catch((()=>{})))}},d={enigma:{before:async()=>{await n.loadPackage(toAbsoluteFromOrigin(e.enigmaWhlUrl))},after:()=>{}},turtle:{before:async()=>{n.registerJsModule("basthon",m),await n.loadPackage(toAbsoluteFromOrigin(e.turtleWhlUrl))},after:()=>n.runPython('\n import turtle\n import basthon\n\n svg_dict = turtle.Screen().show_scene()\n basthon.kernel.display_event({ "display_type": "turtle", "content": svg_dict })\n turtle.restart()\n ')},p5:{before:async()=>{n.registerJsModule("basthon",m),await n.loadPackage(["setuptools",toAbsoluteFromOrigin(e.p5WhlUrl)])},after:()=>{}},pygal:{before:()=>{n.registerJsModule("pygal",{...pygal}),pygal.config.renderChart=e=>{postMessage({method:"handleVisual",origin:"pygal",content:e})}},after:()=>{}},matplotlib:{before:async()=>{let e;n.registerJsModule("basthon",m),n.runPython("\n import js\n\n class __DummyDocument__:\n def __init__(self, *args, **kwargs) -> None:\n return\n def __getattr__(self, __name: str):\n return __DummyDocument__\n js.document = __DummyDocument__()\n "),await(n.loadPackage("matplotlib")?.catch((()=>{})));try{e=n.pyimport("matplotlib")}catch(e){}e&&n.runPython('\n import matplotlib.pyplot as plt\n import io\n import basthon\n\n def show_chart():\n bytes_io = io.BytesIO()\n plt.savefig(bytes_io, format=\'jpg\')\n bytes_io.seek(0)\n basthon.kernel.display_event({ "display_type": "matplotlib", "content": bytes_io.read() })\n plt.show = show_chart\n ')},after:()=>{n.runPython("\n import matplotlib.pyplot as plt\n plt.clf()\n ")}},seaborn:{before:async()=>{n.registerJsModule("basthon",m),n.runPython("\n import js\n\n class __DummyDocument__:\n def __init__(self, *args, **kwargs) -> None:\n return\n def __getattr__(self, __name: str):\n return __DummyDocument__\n js.document = __DummyDocument__()\n "),n.micropip||(await n.loadPackage("micropip"),n.micropip=n.pyimport("micropip")),await n.micropip.install("seaborn").catch((()=>{}))},after:()=>{n.runPython('\n import matplotlib.pyplot as plt\n import io\n import basthon\n\n def is_plot_empty():\n fig = plt.gcf()\n for ax in fig.get_axes():\n # Check if the axes contain any lines, patches, collections, etc.\n if ax.lines or ax.patches or ax.collections or ax.images or ax.texts:\n return False\n return True\n\n if not is_plot_empty():\n bytes_io = io.BytesIO()\n plt.savefig(bytes_io, format=\'jpg\')\n bytes_io.seek(0)\n basthon.kernel.display_event({ "display_type": "matplotlib", "content": bytes_io.read() })\n\n plt.clf()\n ')}},plotly:{before:async()=>{n.micropip||(await n.loadPackage("micropip"),n.micropip=n.pyimport("micropip")),await n.micropip.install("plotly").catch((()=>{})),await n.micropip.install("pandas").catch((()=>{})),n.registerJsModule("basthon",m),n.runPython('\n import plotly.graph_objs as go\n\n def _hacked_show(self, *args, **kwargs):\n basthon.kernel.display_event({\n "display_type": "plotly",\n "content": self.to_json()\n })\n\n go.Figure.show = _hacked_show\n ')},after:()=>{}}},m={kernel:{display_event:e=>{const t=e.toJs().get("display_type"),n=e.toJs().get("content");postMessage({method:"handleVisual",origin:t,content:n})},write_file:e=>{const t=e.toJs().get("filename"),n=e.toJs().get("content"),o=e.toJs().get("mode");postMessage({method:"handleFileWrite",filename:t,content:n,mode:o})},locals:()=>n.runPython("globals()")}},h=async()=>{postMessage({method:"handleLoading"}),console.log("clearPyodideData"),await n.runPythonAsync("\n # Clear all user-defined variables and modules\n for name in dir():\n if not name.startswith('_') and not name=='basthon':\n del globals()[name]\n "),console.log("clearPyodideData done"),postMessage({method:"handleLoaded",stdinBuffer:i,interruptBuffer:a})},f=async()=>{postMessage({method:"handleLoading"}),o=loadPyodide({stdout:e=>postMessage({method:"handleOutput",stream:"stdout",content:e}),stderr:e=>postMessage({method:"handleOutput",stream:"stderr",content:e})}),n=await o,n.registerJsModule("basthon",m),await n.runPythonAsync("\n __old_input__ = input\n def __patched_input__(prompt=False):\n if (prompt):\n print(prompt)\n return __old_input__()\n __builtins__.input = __patched_input__\n "),await n.runPythonAsync("\n import builtins\n # Save the original open function\n _original_open = builtins.open\n "),await n.loadPackage("pyodide-http"),await n.runPythonAsync("\n import pyodide_http\n pyodide_http.patch_all()\n "),t&&(i=i||new Int32Array(new SharedArrayBuffer(1048576)),i[0]=1,n.setStdin({isatty:!0,read:_}),a=a||new Uint8Array(new SharedArrayBuffer(1)),n.setInterruptBuffer(a)),postMessage({method:"handleLoaded",stdinBuffer:i,interruptBuffer:a})},_=e=>{const t=i[0];for(postMessage({method:"handleInput"});n.checkInterrupt(),"not-equal"!==Atomics.wait(i,0,t,100););const o=i[0];if(-1===o)return 0;const a=i.slice(t,o);return e.set(a),a.length},u=e=>{const t=e.type,[n,o]=e.message.split(`${t}:`).map((e=>e?.trim())),i=n.split("\n");i.length>3&&/File "__custom_open__\.py", line (\d+)/g.test(i[i.length-3])&&i.splice(-3,3);const a=i[i.length-2],r=i[i.length-1],s=r.includes("^")?[a.slice(4),r.slice(4)].join("\n"):"",l=[...n.matchAll(/File "(?!__custom_open__\.py)(.*)", line (\d+)/g)],p=l[l.length-1],c=(p?p[1]:"").split("/").reverse()[0];return{file:"<exec>"===c?"main.py":c,line:p?parseInt(p[2],10):"",mistake:s,type:t,info:o}}};globalThis.PyodideWorker=PyodideWorker,PyodideWorker();