code-playpad 0.10.1 → 0.11.0

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.
Files changed (57) hide show
  1. package/README.md +165 -8
  2. package/dist/THIRD-PARTY-NOTICES.txt +223 -0
  3. package/dist/cdn.js +2 -2
  4. package/dist/compiler-B408qd3N.js +151 -0
  5. package/dist/{config-CT3H6Oum.js → config-DB58UVsk.js} +1 -1
  6. package/dist/{cpp-CO2abWii.js → cpp-C77X5wRk.js} +1 -1
  7. package/dist/{cpp-Cs32J8JC.js → cpp-DuOQ_23Z.js} +1 -1
  8. package/dist/{dist-DXjodKfp.js → dist-B4dyQ4mN.js} +1 -1
  9. package/dist/{dist-BkpKCrXQ.js → dist-BFlbXnjn.js} +1 -1
  10. package/dist/dist-BoJapv5W.js +28 -0
  11. package/dist/dist-BqLa1O1y.js +6 -0
  12. package/dist/dist-CJRlQ049.js +6 -0
  13. package/dist/{dist-CJxiVI4a.js → dist-DBpvb9b1.js} +1 -1
  14. package/dist/{dist-BIgiGgKu.js → dist-DRocX-cv.js} +1 -1
  15. package/dist/dist-DfjaG4Ra.js +6 -0
  16. package/dist/{dist-D2igTc4m.js → dist-DviSDQoT.js} +1 -1
  17. package/dist/dist-F28mE6nM.js +8 -0
  18. package/dist/{dist-CNOK8CHE.js → dist-TxeNlzAy.js} +1 -1
  19. package/dist/dist-y6lcdYKh.js +14 -0
  20. package/dist/element-COcjM0hI.js +521 -0
  21. package/dist/element.d.ts +26 -0
  22. package/dist/element.js +1 -1
  23. package/dist/hints-DpBIeoeG.js +6 -0
  24. package/dist/index.d.ts +3 -3
  25. package/dist/index.js +1 -1
  26. package/dist/{java-DeBiVPXO.js → java-Df5HdXMz.js} +1 -1
  27. package/dist/{java-8qjVCjsN.js → java-DyH3mSiH.js} +1 -1
  28. package/dist/{javascript-DLPaJJzf.js → javascript-BtHVyxzg.js} +2 -2
  29. package/dist/{javascript-B1tVx7AD.js → javascript-CWolHiSP.js} +1 -1
  30. package/dist/languages.d.ts +1 -1
  31. package/dist/{pyodide-BOoYEfX1.js → pyodide-3MPS4ySA.js} +2 -2
  32. package/dist/{pyodide-C8ImkXdD.js → pyodide-EUDn__Gx.js} +1 -1
  33. package/dist/react-CL1KABFm.js +9 -0
  34. package/dist/react-Db_rGDYu.js +4 -0
  35. package/dist/react-runtime-19.2.8.js +240 -0
  36. package/dist/react-vendor.generated-DMxIoCMn.js +6 -0
  37. package/dist/react-version.generated-BNNJmf7J.js +6 -0
  38. package/dist/react.d.ts +5 -1
  39. package/dist/react.js +1 -1
  40. package/dist/runtime/config.d.ts +15 -1
  41. package/dist/runtime/react/boot.d.ts +9 -0
  42. package/dist/runtime/react/compiler.d.ts +30 -0
  43. package/dist/runtime/react-vendor.generated.d.ts +5 -0
  44. package/dist/runtime/react-version.generated.d.ts +3 -0
  45. package/dist/runtime/react.d.ts +2 -0
  46. package/dist/standalone.js +214 -17
  47. package/dist/{hints-CCMgezw9.js → types-CfcYqU2K.js} +1 -1
  48. package/dist/types.d.ts +23 -0
  49. package/dist/worker-runtime-DvpugeXD.js +9 -0
  50. package/dist/{worker-runtime-sUPz1J56.js → worker-runtime-PykJQLB7.js} +1 -1
  51. package/package.json +21 -6
  52. package/dist/dist--J_vhCIU.js +0 -14
  53. package/dist/dist-BNvM_BAY.js +0 -6
  54. package/dist/dist-D7jBL3Ib.js +0 -28
  55. package/dist/dist-DfFrsBkU.js +0 -8
  56. package/dist/element-CQGYVEF7.js +0 -324
  57. package/dist/worker-runtime-DfYet3xy.js +0 -9
@@ -0,0 +1,6 @@
1
+ /*!
2
+ * code-playpad — MIT © 2026 Seung Hun Lee
3
+ * Bundles CodeMirror 6 and Lezer (MIT) © Marijn Haverbeke and others.
4
+ * Full third-party licences: THIRD-PARTY-NOTICES.txt in this package.
5
+ */
6
+ var e=`19.2.8`;export{e as t};
package/dist/react.d.ts CHANGED
@@ -16,6 +16,10 @@ export interface CodePlayPadProps {
16
16
  /** Bounds for `height="auto"`. A number means pixels. */
17
17
  minHeight?: number | string;
18
18
  maxHeight?: number | string;
19
+ /** language="react": the preview's height. A number means pixels. */
20
+ previewHeight?: number | string;
21
+ /** How to list several files: "tabs" (default) or "tree". */
22
+ fileView?: 'tabs' | 'tree';
19
23
  theme?: 'light' | 'dark' | 'auto';
20
24
  readOnly?: boolean;
21
25
  autoRun?: boolean;
@@ -38,7 +42,7 @@ export interface CodePlayPadProps {
38
42
  * which keeps React 18 (no non-string prop support on custom elements) working
39
43
  * the same as React 19.
40
44
  */
41
- export declare function CodePlayPad({ code, files, entry, stdin, language, height, minHeight, maxHeight, theme, readOnly, autoRun, persist, practice, className, style, onReady, onRun, onOutput, onError }: CodePlayPadProps): import("react").JSX.Element;
45
+ export declare function CodePlayPad({ code, files, entry, stdin, language, height, minHeight, maxHeight, previewHeight, fileView, theme, readOnly, autoRun, persist, practice, className, style, onReady, onRun, onOutput, onError }: CodePlayPadProps): import("react").JSX.Element;
42
46
  declare module 'react' {
43
47
  namespace JSX {
44
48
  interface IntrinsicElements {
package/dist/react.js CHANGED
@@ -1 +1 @@
1
- import{n as e}from"./element-CQGYVEF7.js";import{useEffect as t,useRef as n}from"react";import{jsx as r}from"react/jsx-runtime";e();function i({code:e=``,files:i,entry:a,stdin:o,language:s=`python`,height:c,minHeight:l,maxHeight:u,theme:d=`auto`,readOnly:f,autoRun:p,persist:m,practice:h,className:g,style:_,onReady:v,onRun:y,onOutput:b,onError:x}){let S=n(null),C=n({onReady:v,onRun:y,onOutput:b,onError:x});C.current={onReady:v,onRun:y,onOutput:b,onError:x},t(()=>{let e=S.current;if(!e)return;let t=(t,n)=>{let r=e=>n(C.current)?.(e.detail);return e.addEventListener(t,r),()=>e.removeEventListener(t,r)},n=[t(`py-ready`,e=>e.onReady),t(`py-run`,e=>e.onRun),t(`py-output`,e=>e.onOutput),t(`py-error`,e=>e.onError)];return()=>n.forEach(e=>e())},[]);let w=i?JSON.stringify(i):null;t(()=>{let t=S.current;t&&(w?t.files=JSON.parse(w):e!==t.code&&(t.code=e))},[e,w]),t(()=>{S.current&&o!==void 0&&(S.current.stdin=o)},[o]);let T=h?JSON.stringify(h):null;return t(()=>{S.current&&(S.current.practice=T?JSON.parse(T):null)},[T]),/* @__PURE__ */ r(`code-playpad`,{ref:S,language:s,theme:d,class:g,style:_,...c===void 0?{}:{height:String(c)},...l===void 0?{}:{"min-height":String(l)},...u===void 0?{}:{"max-height":String(u)},...f?{readonly:``}:{},...p?{autorun:``}:{},...m?{persist:m}:{},...a?{entry:a}:{},children:i?null:e})}export{i as CodePlayPad,i as default};
1
+ import{n as e}from"./element-COcjM0hI.js";import{useEffect as t,useRef as n}from"react";import{jsx as r}from"react/jsx-runtime";e();function i({code:e=``,files:i,entry:a,stdin:o,language:s=`python`,height:c,minHeight:l,maxHeight:u,previewHeight:d,fileView:f,theme:p=`auto`,readOnly:m,autoRun:h,persist:g,practice:_,className:v,style:y,onReady:b,onRun:x,onOutput:S,onError:C}){let w=n(null),T=n({onReady:b,onRun:x,onOutput:S,onError:C});T.current={onReady:b,onRun:x,onOutput:S,onError:C},t(()=>{let e=w.current;if(!e)return;let t=(t,n)=>{let r=e=>n(T.current)?.(e.detail);return e.addEventListener(t,r),()=>e.removeEventListener(t,r)},n=[t(`py-ready`,e=>e.onReady),t(`py-run`,e=>e.onRun),t(`py-output`,e=>e.onOutput),t(`py-error`,e=>e.onError)];return()=>n.forEach(e=>e())},[]);let E=i?JSON.stringify(i):null;t(()=>{let t=w.current;t&&(E?t.files=JSON.parse(E):e!==t.code&&(t.code=e))},[e,E]),t(()=>{w.current&&o!==void 0&&(w.current.stdin=o)},[o]);let D=_?JSON.stringify(_):null;return t(()=>{w.current&&(w.current.practice=D?JSON.parse(D):null)},[D]),/* @__PURE__ */ r(`code-playpad`,{ref:w,language:s,theme:p,class:v,style:y,...c===void 0?{}:{height:String(c)},...l===void 0?{}:{"min-height":String(l)},...u===void 0?{}:{"max-height":String(u)},...d===void 0?{}:{"preview-height":String(d)},...f?{"file-view":f}:{},...m?{readonly:``}:{},...h?{autorun:``}:{},...g?{persist:g}:{},...a?{entry:a}:{},children:i?null:e})}export{i as CodePlayPad,i as default};
@@ -6,6 +6,7 @@
6
6
  * every page would download it — including pages that only run JavaScript.
7
7
  * This module holds nothing but a few strings.
8
8
  */
9
+ import { REACT_VERSION } from './react-version.generated.js';
9
10
  /** Pinned so the CDN response is cacheable forever. */
10
11
  export declare const PYODIDE_VERSION = "314.0.5";
11
12
  /** Point Python at your own origin — strongly recommended in production, so you
@@ -42,4 +43,17 @@ export declare function configureCpp(options: {
42
43
  timeoutMs?: number;
43
44
  }): void;
44
45
  export declare function getCppConfig(): Readonly<typeof cppConfig>;
45
- export {};
46
+ export { REACT_VERSION };
47
+ /** React previews need no configuration. `runtimeURL` loads React in the frame
48
+ * from a URL of your own (`dist/react-runtime-<version>.js`) instead of sending
49
+ * it from the page. `nonce` is for host pages whose Content-Security-Policy
50
+ * forbids inline scripts or styles; by default it is read from the page's first
51
+ * `<script nonce>`. Call before a widget runs. */
52
+ export declare function configureReact(options: {
53
+ runtimeURL?: string;
54
+ nonce?: string;
55
+ }): void;
56
+ export declare function getReactConfig(): {
57
+ runtimeURL: string | null;
58
+ nonce: string | null;
59
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The one script written into the preview document. It runs first, wires the
3
+ * frame to the widget, and waits for the project: the code arrives over a port
4
+ * this script hands to its parent, and runs from created <script> elements, so
5
+ * the HTML parser never sees learner code and nothing in it needs escaping. A
6
+ * port rather than checking event.source, because a widget in a separate window
7
+ * is run by the opening page's script, which is then the sender.
8
+ */
9
+ export declare const REACT_BOOT_SOURCE: string;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * React projects as modules for the preview frame. Every file is parsed by
3
+ * acorn-jsx first: Sucrase accepts mismatched tags and can blame the wrong line
4
+ * for arrow components. The AST also gives the import list and the places for
5
+ * loop guards.
6
+ */
7
+ /** Packages a project can import. The vendor bundle defines exactly these. */
8
+ export declare const REACT_PACKAGES: string[];
9
+ /** What the loop guard is called inside compiled code; the boot script defines it. */
10
+ export declare const LOOP_GUARD = "__playpadLoopGuard";
11
+ export interface CompiledModule {
12
+ path: string;
13
+ kind: 'js' | 'css' | 'json';
14
+ text: string;
15
+ /** Import specifier -> project file. Packages come from the vendor bundle. */
16
+ links: Record<string, string>;
17
+ }
18
+ /** A problem with the learner's project, reported against one of its files. */
19
+ export declare class CompileError extends Error {
20
+ readonly file: string;
21
+ readonly reason: string;
22
+ readonly line?: number | undefined;
23
+ readonly column?: number | undefined;
24
+ readonly hint?: string | undefined;
25
+ constructor(file: string, reason: string, line?: number | undefined, column?: number | undefined, hint?: string | undefined);
26
+ }
27
+ /** Resolve an import as Vite does: against the importing file, trying the extensions a learner may leave off. */
28
+ export declare function resolveImport(files: Record<string, string>, from: string, spec: string): string | undefined;
29
+ /** Compile the entry files and everything they import. A file nothing imports is not compiled, as in Vite. */
30
+ export declare function compileProject(files: Record<string, string>, entries: string[]): CompiledModule[];
@@ -0,0 +1,5 @@
1
+ export declare const REACT_VENDOR: {
2
+ readonly version: "19.2.8";
3
+ readonly sha256: "b04fb09f1e1bd302bdf30f895a442e0c21b01864a166434fa7c94a92a053ee2f";
4
+ };
5
+ export declare const REACT_VENDOR_SOURCE: string;
@@ -0,0 +1,3 @@
1
+ export declare const REACT_VERSION = "19.2.8";
2
+ /** The runtime's file name in dist/, for hosts that serve it themselves (configureReact). */
3
+ export declare const REACT_RUNTIME_FILE = "react-runtime-19.2.8.js";
@@ -0,0 +1,2 @@
1
+ import type { Runtime } from '../types.js';
2
+ export declare const reactRuntime: Runtime;
@@ -3,7 +3,7 @@
3
3
  * Bundles CodeMirror 6 and Lezer (MIT) © Marijn Haverbeke and others.
4
4
  * Full third-party licences: THIRD-PARTY-NOTICES.txt in this package.
5
5
  */
6
- import{n as e,r as t,t as n}from"./hints-CCMgezw9.js";import{c as r,i,n as a,r as o,t as s}from"./config-CT3H6Oum.js";async function c(e){try{return await l(e)}catch(t){return console.warn(`[code-playpad] CodeMirror unavailable, using plain textarea:`,t),u(e)}}async function l(e){let[t,n,r,i,a,o]=await Promise.all([import(`./dist-Vr-fb58P.js`).then(e=>e.s),import(`./dist-D25hs99E.js`).then(e=>e.x),import(`./dist-D2igTc4m.js`),import(`./dist-DfFrsBkU.js`),import(`./dist-BNvM_BAY.js`),import(`./dist-DXjodKfp.js`)]),{EditorView:s,keymap:c,lineNumbers:l,highlightActiveLine:u,highlightActiveLineGutter:d,highlightSpecialChars:f,drawSelection:p,rectangularSelection:m,crosshairCursor:h}=t,{EditorState:g,Compartment:_}=n,{defaultKeymap:v,history:y,historyKeymap:b,indentWithTab:x}=r,{syntaxHighlighting:S,defaultHighlightStyle:C,indentOnInput:w,bracketMatching:T,foldGutter:E,foldKeymap:D}=i,{autocompletion:O,closeBrackets:k,closeBracketsKeymap:A,completionKeymap:j}=a,M=new _,N=new _,P=new _,F=[s.theme({"&":{color:`#1f2328`,backgroundColor:`#ffffff`},".cm-gutters":{backgroundColor:`#f6f8fa`,color:`#8b949e`,border:`none`},".cm-activeLine":{backgroundColor:`#f6f8fa88`},".cm-activeLineGutter":{backgroundColor:`#eaeef2`},".cm-cursor":{borderLeftColor:`#1f2328`},"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, ::selection":{backgroundColor:`#cfe3ff`}}),S(C,{fallback:!0})],I=e=>e?o.oneDark:F,L=c.of([{key:`Mod-Enter`,preventDefault:!0,run:()=>(e.onRun?.(),!0)},{key:`Shift-Enter`,preventDefault:!0,run:()=>(e.onRun?.(),!0)}]),R=e.dark,z=e.readOnly,B=e.language??[],V=t=>g.create({doc:t,extensions:[l(),d(),f(),y(),E(),p(),g.allowMultipleSelections.of(!0),w(),T(),k(),O(),m(),h(),u(),L,c.of([...A,...v,...b,...D,...j,x]),s.lineWrapping,P.of(B),M.of(I(R)),N.of(g.readOnly.of(z)),s.updateListener.of(t=>{t.docChanged&&e.onChange?.(t.state.doc.toString())})]}),H=new s({parent:e.parent,state:V(e.doc)}),U=/* @__PURE__ */ new Map,W=e.name??``;return{fallback:!1,getCode:()=>H.state.doc.toString(),setCode(e){H.dispatch({changes:{from:0,to:H.state.doc.length,insert:e}})},openFile(e,t){if(e===W)return;U.set(W,H.state);let n=U.get(e);H.setState(n??V(t)),W=e,n&&H.dispatch({effects:[M.reconfigure(I(R)),N.reconfigure(g.readOnly.of(z)),P.reconfigure(B)]})},fileCode(e,t){if(e===W)return H.state.doc.toString();let n=U.get(e);return n?n.doc.toString():t},forgetFiles(e){for(let t of[...U.keys()])e.includes(t)||U.delete(t)},setTheme(e){R=e,H.dispatch({effects:M.reconfigure(I(R))})},setReadOnly(e){z=e,H.dispatch({effects:N.reconfigure(g.readOnly.of(z))})},setLanguage(e){B=e,H.dispatch({effects:P.reconfigure(B)})},focus:()=>H.focus(),destroy:()=>H.destroy()}}function u(e){let t=document.createElement(`textarea`);t.className=`cp-fallback-editor`,t.spellcheck=!1,t.value=e.doc,t.readOnly=e.readOnly,t.addEventListener(`input`,()=>e.onChange?.(t.value)),t.addEventListener(`keydown`,t=>{(t.metaKey||t.ctrlKey)&&t.key===`Enter`&&(t.preventDefault(),e.onRun?.())}),e.parent.appendChild(t);let n=/* @__PURE__ */ new Map,r=e.name??``;return{fallback:!0,getCode:()=>t.value,setCode:e=>{t.value=e},openFile(e,i){e!==r&&(n.set(r,t.value),t.value=n.get(e)??i,r=e)},fileCode(e,i){return e===r?t.value:n.get(e)??i},forgetFiles(e){for(let t of[...n.keys()])e.includes(t)||n.delete(t)},setTheme:()=>{},setReadOnly:e=>{t.readOnly=e},setLanguage:()=>{},focus:()=>t.focus(),destroy:()=>t.remove()}}var d=/* @__PURE__ */ new Map,f=/* @__PURE__ */ new Map;function p(e,t){d.set(e,t)}function m(){return[...d.keys()]}function h(e){let t=f.get(e);if(t)return t;let n=d.get(e);if(!n)return Promise.reject(/* @__PURE__ */ Error(`Unknown runtime "${e}". Registered: ${m().join(`, `)||`none`}`));let r=n().catch(t=>{throw f.delete(e),t});return f.set(e,r),r}p(`python`,()=>import(`./pyodide-BOoYEfX1.js`).then(e=>e.pythonRuntime)),p(`javascript`,()=>import(`./javascript-DLPaJJzf.js`).then(e=>e.javascriptRuntime)),p(`typescript`,()=>import(`./javascript-DLPaJJzf.js`).then(e=>e.typescriptRuntime)),p(`java`,()=>import(`./java-DeBiVPXO.js`).then(e=>e.javaRuntime)),p(`c`,()=>import(`./cpp-Cs32J8JC.js`).then(e=>e.cRuntime)),p(`cpp`,()=>import(`./cpp-Cs32J8JC.js`).then(e=>e.cppRuntime));var g=String.raw`
6
+ import{n as e,t}from"./types-CfcYqU2K.js";import{t as n}from"./hints-DpBIeoeG.js";import{t as r}from"./react-version.generated-BNNJmf7J.js";import{a as i,i as a,n as o,r as s,t as c,u as l}from"./config-DB58UVsk.js";async function u(e){try{return await d(e)}catch(t){return console.warn(`[code-playpad] CodeMirror unavailable, using plain textarea:`,t),f(e)}}async function d(e){let[t,n,r,i,a,o]=await Promise.all([import(`./dist-Vr-fb58P.js`).then(e=>e.s),import(`./dist-D25hs99E.js`).then(e=>e.x),import(`./dist-DviSDQoT.js`),import(`./dist-F28mE6nM.js`),import(`./dist-CJRlQ049.js`).then(e=>e.n),import(`./dist-B4dyQ4mN.js`)]),{EditorView:s,keymap:c,lineNumbers:l,highlightActiveLine:u,highlightActiveLineGutter:d,highlightSpecialChars:f,drawSelection:p,rectangularSelection:m,crosshairCursor:h}=t,{EditorState:g,Compartment:_}=n,{defaultKeymap:v,history:y,historyKeymap:b,indentWithTab:x}=r,{syntaxHighlighting:S,defaultHighlightStyle:C,indentOnInput:w,bracketMatching:T,foldGutter:E,foldKeymap:D}=i,{autocompletion:O,closeBrackets:k,closeBracketsKeymap:A,completionKeymap:j}=a,M=new _,N=new _,P=new _,F=[s.theme({"&":{color:`#1f2328`,backgroundColor:`#ffffff`},".cm-gutters":{backgroundColor:`#f6f8fa`,color:`#8b949e`,border:`none`},".cm-activeLine":{backgroundColor:`#f6f8fa88`},".cm-activeLineGutter":{backgroundColor:`#eaeef2`},".cm-cursor":{borderLeftColor:`#1f2328`},"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, ::selection":{backgroundColor:`#cfe3ff`}}),S(C,{fallback:!0})],I=e=>e?o.oneDark:F,L=c.of([{key:`Mod-Enter`,preventDefault:!0,run:()=>(e.onRun?.(),!0)},{key:`Shift-Enter`,preventDefault:!0,run:()=>(e.onRun?.(),!0)}]),R=e.dark,z=e.readOnly,B=e.language??[],V=t=>g.create({doc:t,extensions:[l(),d(),f(),y(),E(),p(),g.allowMultipleSelections.of(!0),w(),T(),k(),O(),m(),h(),u(),L,c.of([...A,...v,...b,...D,...j,x]),s.lineWrapping,P.of(B),M.of(I(R)),N.of(g.readOnly.of(z)),s.updateListener.of(t=>{t.docChanged&&e.onChange?.(t.state.doc.toString())})]}),H=new s({parent:e.parent,state:V(e.doc)}),U=/* @__PURE__ */ new Map,W=e.name??``;return{fallback:!1,getCode:()=>H.state.doc.toString(),setCode(e){H.dispatch({changes:{from:0,to:H.state.doc.length,insert:e}})},openFile(e,t){if(e===W)return;U.set(W,H.state);let n=U.get(e);H.setState(n??V(t)),W=e,n&&H.dispatch({effects:[M.reconfigure(I(R)),N.reconfigure(g.readOnly.of(z)),P.reconfigure(B)]})},fileCode(e,t){if(e===W)return H.state.doc.toString();let n=U.get(e);return n?n.doc.toString():t},forgetFiles(e){for(let t of[...U.keys()])e.includes(t)||U.delete(t)},setTheme(e){R=e,H.dispatch({effects:M.reconfigure(I(R))})},setReadOnly(e){z=e,H.dispatch({effects:N.reconfigure(g.readOnly.of(z))})},setLanguage(e){B=e,H.dispatch({effects:P.reconfigure(B)})},focus:()=>H.focus(),destroy:()=>H.destroy()}}function f(e){let t=document.createElement(`textarea`);t.className=`cp-fallback-editor`,t.spellcheck=!1,t.value=e.doc,t.readOnly=e.readOnly,t.addEventListener(`input`,()=>e.onChange?.(t.value)),t.addEventListener(`keydown`,t=>{(t.metaKey||t.ctrlKey)&&t.key===`Enter`&&(t.preventDefault(),e.onRun?.())}),e.parent.appendChild(t);let n=/* @__PURE__ */ new Map,r=e.name??``;return{fallback:!0,getCode:()=>t.value,setCode:e=>{t.value=e},openFile(e,i){e!==r&&(n.set(r,t.value),t.value=n.get(e)??i,r=e)},fileCode(e,i){return e===r?t.value:n.get(e)??i},forgetFiles(e){for(let t of[...n.keys()])e.includes(t)||n.delete(t)},setTheme:()=>{},setReadOnly:e=>{t.readOnly=e},setLanguage:()=>{},focus:()=>t.focus(),destroy:()=>t.remove()}}var p=/* @__PURE__ */ new Map,m=/* @__PURE__ */ new Map;function h(e,t){p.set(e,t)}function g(){return[...p.keys()]}function _(e){let t=m.get(e);if(t)return t;let n=p.get(e);if(!n)return Promise.reject(/* @__PURE__ */ Error(`Unknown runtime "${e}". Registered: ${g().join(`, `)||`none`}`));let r=n().catch(t=>{throw m.delete(e),t});return m.set(e,r),r}h(`python`,()=>import(`./pyodide-3MPS4ySA.js`).then(e=>e.pythonRuntime)),h(`javascript`,()=>import(`./javascript-BtHVyxzg.js`).then(e=>e.javascriptRuntime)),h(`typescript`,()=>import(`./javascript-BtHVyxzg.js`).then(e=>e.typescriptRuntime)),h(`java`,()=>import(`./java-Df5HdXMz.js`).then(e=>e.javaRuntime)),h(`c`,()=>import(`./cpp-DuOQ_23Z.js`).then(e=>e.cRuntime)),h(`cpp`,()=>import(`./cpp-DuOQ_23Z.js`).then(e=>e.cppRuntime)),h(`react`,()=>import(`./react-CL1KABFm.js`).then(e=>e.reactRuntime));var v=String.raw`
7
7
  :host {
8
8
  --cp-bg: #ffffff;
9
9
  --cp-fg: #1f2328;
@@ -291,6 +291,186 @@ table.cp-table th { background: var(--cp-bg); }
291
291
  }
292
292
  .cp-progress[hidden] { display: none; }
293
293
 
294
+ /* language="react". The widget is the container: lesson columns are narrow even
295
+ on a large screen, so the viewport says nothing about the room there is. */
296
+ .cp-root.cp-has-preview { container-type: inline-size; }
297
+ .cp-preview-pane { display: none; }
298
+ .cp-has-preview .cp-preview-pane { display: flex; flex-direction: column; }
299
+ .cp-has-preview .cp-preview-pane .cp-output { flex: 1 1 auto; border-top: 0; min-height: 40px; }
300
+ .cp-preview {
301
+ position: relative;
302
+ flex: 0 0 var(--cp-preview-height, 320px);
303
+ height: var(--cp-preview-height, 320px);
304
+ border-top: 1px solid var(--cp-border);
305
+ background: var(--cp-surface);
306
+ overflow: hidden;
307
+ }
308
+ .cp-preview-frame {
309
+ display: block;
310
+ width: 100%;
311
+ height: 100%;
312
+ border: 0;
313
+ background: #ffffff;
314
+ }
315
+ .cp-preview-banner {
316
+ position: absolute;
317
+ left: 0;
318
+ right: 0;
319
+ bottom: 0;
320
+ max-height: 60%;
321
+ margin: 0;
322
+ padding: 10px 12px;
323
+ overflow: auto;
324
+ border-top: 3px solid var(--cp-danger);
325
+ background: var(--cp-bg);
326
+ color: var(--cp-danger);
327
+ font-family: var(--cp-font-mono);
328
+ font-size: 12.5px;
329
+ line-height: 1.5;
330
+ white-space: pre-wrap;
331
+ word-break: break-word;
332
+ }
333
+ .cp-preview-notice {
334
+ position: absolute;
335
+ top: 8px;
336
+ left: 8px;
337
+ right: 8px;
338
+ padding: 8px 10px;
339
+ border: 1px solid var(--cp-border);
340
+ border-left: 3px solid var(--cp-accent);
341
+ border-radius: 6px;
342
+ background: var(--cp-bg);
343
+ color: var(--cp-fg);
344
+ font-size: 13px;
345
+ white-space: pre-wrap;
346
+ }
347
+ .cp-preview-notice[hidden] { display: none; }
348
+ .cp-output .cp-warn { color: #9a6700; }
349
+ :host([data-resolved-theme="dark"]) .cp-output .cp-warn { color: #d29922; }
350
+ .cp-edited-note { font-size: 12px; color: var(--cp-muted); white-space: nowrap; }
351
+ .cp-edited-note[hidden] { display: none; }
352
+ .cp-tabs button.cp-edited::after { content: ' ●'; color: var(--cp-accent); }
353
+ .cp-tab-folder { opacity: 0.65; }
354
+
355
+ @container (max-width: 480px) {
356
+ .cp-tab-folder { display: none; }
357
+ }
358
+ /* The dividers between sections. */
359
+ .cp-split {
360
+ display: none;
361
+ flex: none;
362
+ background: var(--cp-surface);
363
+ border: solid var(--cp-border);
364
+ border-width: 0 1px;
365
+ touch-action: none;
366
+ cursor: col-resize;
367
+ }
368
+ .cp-split:hover, .cp-split:focus-visible { background: var(--cp-accent); outline: none; }
369
+ .cp-split-main, .cp-split-console {
370
+ width: auto;
371
+ height: 7px;
372
+ border-width: 1px 0;
373
+ cursor: row-resize;
374
+ }
375
+ .cp-has-preview .cp-split-main { display: block; }
376
+ .cp-has-preview .cp-split-console { display: block; }
377
+ .cp-split-console:has(+ .cp-output[hidden]) { display: none; }
378
+ .cp-dragging .cp-preview-frame { pointer-events: none; }
379
+ .cp-dragging { user-select: none; }
380
+ .cp-dragging-x { cursor: col-resize; }
381
+ .cp-dragging-y { cursor: row-resize; }
382
+ .cp-root.cp-editor-sized .cp-editor { height: var(--cp-editor-height) !important; flex: none !important; }
383
+ .cp-root.cp-editor-sized .cp-editor .cm-editor { height: 100% !important; max-height: none !important; }
384
+
385
+ /* Open in window. */
386
+ .cp-window-button { display: none; }
387
+ .cp-has-preview .cp-window-button { display: inline-block; }
388
+ :host([data-window]) .cp-window-button { display: none; }
389
+ .cp-window-note { display: none; align-items: center; gap: 8px; padding: 14px 12px; color: var(--cp-muted); }
390
+ .cp-root.cp-popped .cp-window-note { display: flex; }
391
+ .cp-root.cp-popped .cp-toolbar, .cp-root.cp-popped .cp-body { display: none; }
392
+ :host([data-window]) { height: 100%; margin: 0; contain: strict; }
393
+ :host([data-window]) .cp-root {
394
+ display: flex;
395
+ flex-direction: column;
396
+ height: 100%;
397
+ border: 0;
398
+ border-radius: 0;
399
+ }
400
+ :host([data-window]) .cp-body { flex: 1 1 0; min-height: 0; }
401
+ :host([data-window]) .cp-source, :host([data-window]) .cp-preview-pane { min-height: 0; }
402
+ :host([data-window]) .cp-root:not(.cp-editor-sized) .cp-editor { flex: 1 1 0; height: auto; min-height: 0; }
403
+ :host([data-window]) .cp-editor .cm-editor { height: 100%; max-height: none; }
404
+ :host([data-window]) .cp-preview-pane .cp-output { max-height: none; }
405
+ :host([data-window]) .cp-body { display: flex; flex-direction: column; }
406
+ :host([data-window]) .cp-source { flex: 1 1 0; display: flex; flex-direction: column; }
407
+ :host([data-window]) .cp-has-tree .cp-source { display: grid; }
408
+ :host([data-window]) .cp-preview-pane { flex: 1 1 0; }
409
+
410
+ /* file-view="tree": the files in a column beside the editor. */
411
+ .cp-root.cp-has-tree { container-type: inline-size; }
412
+ .cp-has-tree .cp-source {
413
+ display: grid;
414
+ grid-template-columns: var(--cp-tree-width, 200px) 7px minmax(0, 1fr);
415
+ grid-template-rows: 1fr auto;
416
+ }
417
+ .cp-has-tree .cp-source > :not(.cp-tabs, .cp-split-tree) { grid-column: 3; }
418
+ .cp-has-tree .cp-split-tree { display: block; grid-column: 2; grid-row: 1 / span 2; }
419
+ .cp-tabs.cp-tree {
420
+ display: block;
421
+ grid-column: 1;
422
+ grid-row: 1 / span 2;
423
+ padding: 6px 0;
424
+ overflow: auto;
425
+ border-bottom: 0;
426
+ }
427
+ .cp-tabs.cp-tree[hidden] { display: none; }
428
+ .cp-tabs.cp-tree button {
429
+ display: block;
430
+ width: 100%;
431
+ padding: 5px 8px 5px calc(22px + var(--cp-depth, 0) * 12px);
432
+ border-bottom: 0;
433
+ border-left: 2px solid transparent;
434
+ text-align: left;
435
+ overflow: hidden;
436
+ text-overflow: ellipsis;
437
+ }
438
+ .cp-tabs.cp-tree button[aria-pressed='true'] { border-left-color: var(--cp-accent); }
439
+ .cp-tabs.cp-tree button.cp-entry::before {
440
+ content: '▸';
441
+ display: inline-block;
442
+ width: 12px;
443
+ margin: 0 0 0 -12px;
444
+ }
445
+ .cp-tabs.cp-tree .cp-tree-folder {
446
+ padding-left: calc(8px + var(--cp-depth, 0) * 12px);
447
+ color: var(--cp-fg);
448
+ }
449
+ .cp-tabs.cp-tree .cp-tree-folder::before {
450
+ content: '⌄';
451
+ display: inline-block;
452
+ width: 14px;
453
+ color: var(--cp-muted);
454
+ }
455
+ .cp-tabs.cp-tree .cp-tree-folder[aria-expanded='false']::before { content: '›'; }
456
+ @container (max-width: 420px) {
457
+ .cp-has-tree .cp-source { display: block; }
458
+ .cp-has-tree .cp-split-tree { display: none; }
459
+ .cp-tabs.cp-tree { max-height: 150px; border-bottom: 1px solid var(--cp-border); }
460
+ }
461
+
462
+ @container (min-width: 760px) {
463
+ .cp-body { display: flex; align-items: stretch; }
464
+ .cp-source { flex: 0 0 var(--cp-source-width, calc(50% - 4px)); min-width: 0; }
465
+ .cp-preview-pane { flex: 1 1 0; min-width: 0; }
466
+ .cp-preview { border-top: 0; }
467
+ .cp-has-preview .cp-source:not(:has(.cp-tree)) { display: flex; flex-direction: column; }
468
+ .cp-has-preview .cp-source:not(:has(.cp-tree)) .cp-editor { flex: 1 1 auto; }
469
+ .cp-split.cp-split-main { width: 7px; height: auto; cursor: col-resize; border-width: 0 1px; }
470
+ :host([data-window]) .cp-body { flex-direction: row; }
471
+ :host([data-window]) .cp-source { flex: 0 0 var(--cp-source-width, calc(50% - 4px)); }
472
+ }
473
+
294
474
  @keyframes cp-slide {
295
475
  0% { background-position: -40% 0; }
296
476
  100% { background-position: 140% 0; }
@@ -299,31 +479,48 @@ table.cp-table th { background: var(--cp-bg); }
299
479
  @media (prefers-reduced-motion: reduce) {
300
480
  .cp-progress { animation: none; background-position: 0 0; background-size: 100% 100%; opacity: 0.4; }
301
481
  }
302
- `,_=e=>()=>import(`./dist-D7jBL3Ib.js`).then(t=>t.javascript(e)),v={py:()=>import(`./dist--J_vhCIU.js`).then(e=>e.python()),pyi:()=>import(`./dist--J_vhCIU.js`).then(e=>e.python()),js:_({}),mjs:_({}),cjs:_({}),jsx:_({jsx:!0}),ts:_({typescript:!0}),mts:_({typescript:!0}),cts:_({typescript:!0}),tsx:_({typescript:!0,jsx:!0}),json:()=>import(`./dist-BkpKCrXQ.js`).then(e=>e.json()),c:()=>import(`./dist-CNOK8CHE.js`).then(e=>e.cpp()),h:()=>import(`./dist-CNOK8CHE.js`).then(e=>e.cpp()),cpp:()=>import(`./dist-CNOK8CHE.js`).then(e=>e.cpp()),cc:()=>import(`./dist-CNOK8CHE.js`).then(e=>e.cpp()),cxx:()=>import(`./dist-CNOK8CHE.js`).then(e=>e.cpp()),hpp:()=>import(`./dist-CNOK8CHE.js`).then(e=>e.cpp()),hxx:()=>import(`./dist-CNOK8CHE.js`).then(e=>e.cpp()),java:()=>import(`./dist-CJxiVI4a.js`).then(e=>e.java())};async function y(e){let t=v[e.includes(`.`)?e.slice(e.lastIndexOf(`.`)+1).toLowerCase():``];return t?t().catch(()=>null):null}var b=`code-playpad`,x=1,S=`snippets`,C=`progress`,w=null;function T(){return typeof indexedDB>`u`?Promise.reject(/* @__PURE__ */ Error(`IndexedDB unavailable`)):(w||=new Promise((e,t)=>{let n=indexedDB.open(b,x);n.onupgradeneeded=()=>{let e=n.result;e.objectStoreNames.contains(S)||e.createObjectStore(S),e.objectStoreNames.contains(C)||e.createObjectStore(C,{keyPath:`id`})},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)}).catch(e=>{throw w=null,e}),w)}function E(e,t,n){return T().then(r=>new Promise((i,a)=>{let o=n(r.transaction(e,t).objectStore(e));o.onsuccess=()=>i(o.result),o.onerror=()=>a(o.error)}))}function D(e,t){return E(S,`readwrite`,n=>n.put(t,e)).then(()=>void 0)}function O(e){return E(S,`readonly`,t=>t.get(e)).then(e=>e??null)}function k(e){return E(S,`readwrite`,t=>t.delete(e)).then(()=>void 0)}function A(e,t={}){let n={completed:!0,...t,id:e,updatedAt:Date.now()};return E(C,`readwrite`,e=>e.put(n)).then(()=>n)}function j(e){return E(C,`readonly`,t=>t.get(e)).then(e=>e??null)}function M(){return E(C,`readonly`,e=>e.getAll())}var N=`code-playpad`;function P(e){let t=e.replace(/\t/g,` `).split(`
482
+ `,y=e=>()=>import(`./dist-BoJapv5W.js`).then(t=>t.javascript(e)),b={py:()=>import(`./dist-y6lcdYKh.js`).then(e=>e.python()),pyi:()=>import(`./dist-y6lcdYKh.js`).then(e=>e.python()),js:y({}),mjs:y({}),cjs:y({}),jsx:y({jsx:!0}),ts:y({typescript:!0}),mts:y({typescript:!0}),cts:y({typescript:!0}),tsx:y({typescript:!0,jsx:!0}),json:()=>import(`./dist-BFlbXnjn.js`).then(e=>e.json()),css:()=>import(`./dist-BqLa1O1y.js`).then(e=>e.css()),html:()=>import(`./dist-DfjaG4Ra.js`).then(e=>e.html()),c:()=>import(`./dist-TxeNlzAy.js`).then(e=>e.cpp()),h:()=>import(`./dist-TxeNlzAy.js`).then(e=>e.cpp()),cpp:()=>import(`./dist-TxeNlzAy.js`).then(e=>e.cpp()),cc:()=>import(`./dist-TxeNlzAy.js`).then(e=>e.cpp()),cxx:()=>import(`./dist-TxeNlzAy.js`).then(e=>e.cpp()),hpp:()=>import(`./dist-TxeNlzAy.js`).then(e=>e.cpp()),hxx:()=>import(`./dist-TxeNlzAy.js`).then(e=>e.cpp()),java:()=>import(`./dist-DBpvb9b1.js`).then(e=>e.java())};async function x(e,t){let n=e.includes(`.`)?e.slice(e.lastIndexOf(`.`)+1).toLowerCase():``,r=t===`react`&&n===`js`?b.jsx:b[n];return r?r().catch(()=>null):null}var S=`code-playpad`,C=1,w=`snippets`,T=`progress`,E=null;function D(){return typeof indexedDB>`u`?Promise.reject(/* @__PURE__ */ Error(`IndexedDB unavailable`)):(E||=new Promise((e,t)=>{let n=indexedDB.open(S,C);n.onupgradeneeded=()=>{let e=n.result;e.objectStoreNames.contains(w)||e.createObjectStore(w),e.objectStoreNames.contains(T)||e.createObjectStore(T,{keyPath:`id`})},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)}).catch(e=>{throw E=null,e}),E)}function O(e,t,n){return D().then(r=>new Promise((i,a)=>{let o=n(r.transaction(e,t).objectStore(e));o.onsuccess=()=>i(o.result),o.onerror=()=>a(o.error)}))}function k(e,t){return O(w,`readwrite`,n=>n.put(t,e)).then(()=>void 0)}function A(e){return O(w,`readonly`,t=>t.get(e)).then(e=>e??null)}function j(e){return O(w,`readwrite`,t=>t.delete(e)).then(()=>void 0)}function M(e,t={}){let n={completed:!0,...t,id:e,updatedAt:Date.now()};return O(T,`readwrite`,e=>e.put(n)).then(()=>n)}function N(e){return O(T,`readonly`,t=>t.get(e)).then(e=>e??null)}function P(){return O(T,`readonly`,e=>e.getAll())}var F=`code-playpad`;function I(e){let t=e.replace(/\t/g,` `).split(`
303
483
  `);for(;t.length&&t[0].trim()===``;)t.shift();for(;t.length&&t[t.length-1].trim()===``;)t.pop();let n=t.filter(e=>e.trim()!==``).reduce((e,t)=>Math.min(e,t.match(/^ */)[0].length),1/0);return(n===1/0?t:t.map(e=>e.slice(n))).join(`
304
- `)}var F=2e5,I=`playpad-file`,L={python:`main.py`,javascript:`main.js`,typescript:`main.ts`,java:`Main.java`,c:`main.c`,cpp:`main.cpp`};function R(e){return L[e]??`main.txt`}function z(e,t){let n={};for(let t of e.children){if(t.tagName.toLowerCase()!==I)continue;let e=t.getAttribute(`name`);e&&(n[e]=P(t.textContent??``))}if(Object.keys(n).length)return n;let r=[...e.childNodes].filter(e=>e.nodeType!==Node.ELEMENT_NODE||e.tagName.toLowerCase()!==I),i=r.some(e=>e.nodeType===Node.ELEMENT_NODE),a=P(r.filter(e=>!(i&&e.nodeType===Node.TEXT_NODE&&!(e.textContent??``).trim())).map(e=>e.textContent??``).join(``));return{[t]:a}}function B(e,t){try{let t=JSON.parse(e);if(t&&typeof t==`object`&&!Array.isArray(t)){let e=t;return Object.keys(e).length?e:null}}catch{}return e?{[t]:e}:null}var V=typeof HTMLElement>`u`?class{}:HTMLElement,H=class extends V{static get observedAttributes(){return[`language`,`height`,`min-height`,`max-height`,`theme`,`readonly`,`autorun`,`stdin`,`persist`,`entry`,`practice`]}#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u=null;#d=null;#f=null;#p=null;#m={};#h={};#g=`main.py`;#_=null;#v;#y=!1;#b=null;#x=!1;#S=!1;#C=null;#w=null;#T=null;#E=()=>this.#X();#D=null;#O=!0;#k=[];#A=null;#j=null;#M=null;#N=0;#P=!1;#F=null;constructor(){super(),this.#e=this.attachShadow({mode:`open`})}get code(){return this.#u?this.#u.getCode():this.#m[this.#g]??``}set code(e){this.#m[this.#g]=e,this.#V()}get practice(){if(this.#F)return this.#F;let e=this.getAttribute(`practice`);if(!e)return null;try{return JSON.parse(e)}catch{return null}}set practice(e){this.#F=e}get files(){return this.#K()}set files(e){let t=Object.keys(e);if(!t.length)return;let n=Object.keys(this.#h);n.length===1&&!this.#h[n[0]]&&(this.#h={...e}),this.#m={...e},t.includes(this.#g)||(this.#g=this.#G()),this.#u?.forgetFiles([]),this.#V(),this.#q(),this.#B()}get entry(){return this.#G()}set entry(e){this.setAttribute(`entry`,e)}openFile(e){e in this.#m&&(this.#u&&(this.#m[this.#g]=this.#u.getCode(),this.#u.openFile(e,this.#m[e]??``)),this.#g=e,this.#q(),this.#B())}get stdin(){return this.#l?this.#l.value:``}set stdin(e){this.#l&&(this.#l.value=e,this.#c.hidden=!1)}get language(){return this.getAttribute(`language`)||`python`}set language(e){this.setAttribute(`language`,e)}getCode(){return this.code}getFiles(){return this.#K()}reset(){this.#m={...this.#h},this.#g=this.#G(),this.#u?.forgetFiles([]),this.#V(),this.#q(),this.#$(),this.#s.hidden=!0,this.#Q(this.#f?.ready?`${this.#f.label} ready`:``,`idle`)}async run(){if(this.#y)return;await this.#d;let t=this.#K(),r=this.getAttribute(`entry`);if(r&&!(r in t))return this.#U(r,t);this.#H=!1;let i=this.#G(),a=t[i]??``;this.#y=!0,this.#x=!1,this.#n.disabled=!0,this.#r.hidden=!1,this.#$(),this.#s.hidden=!1;let o=this.practice;this.hasAttribute(`practice`)&&!o&&this.#ee(`The practice attribute is not valid JSON.
305
- `,`cp-err`),this.#oe(`py-run`,{code:a,entry:i,files:t,language:this.language,...o?{practice:o}:{}});try{let r=await this.#z();if(this.#x)throw new e;if(o&&!r.supportsPractice)throw Error(`Practice mode is not available for ${r.label}.`);this.#Q(`Queued…`,`busy`),this.#o.hidden=!1;let s=r.run(a,{stdin:this.#l.value,files:t,entry:i,onStart:()=>this.#Q(`Running…`,`busy`),onProgress:e=>this.#Q(e.message,`busy`),onStdout:e=>this.#ee(e),onStderr:e=>this.#ee(e,`cp-err`),onEcho:e=>this.#ee(e,`cp-in`),onStdinRequest:()=>this.#ne(),...o?{practice:o}:{}});this.#b={runtime:r,run:s};let c=await s;if(c.table&&this.#ae(c.table),c.value!==void 0&&this.#ee(`${c.value}\n`,`cp-value`),c.hint&&this.#ie(c.hint,n.has(c)),c.failed=r.statusDecidesFailure?c.failed===!0:!!c.stderr,c.failed)this.#Q(`Error · ${c.durationMs} ms`,`error`),this.#oe(`py-error`,{message:c.stderr??``,hint:c.hint,language:this.language});else if(c.cases){let e=c.cases.filter(e=>e.expected!==void 0).length,t=c.passed===e;this.#Q(e?`${c.passed} of ${e} passed · ${c.durationMs} ms`:`Done in ${c.durationMs} ms`,t?`ok`:`error`)}else this.#Q(`Done in ${c.durationMs} ms`,`ok`);return this.#oe(`py-output`,{...c,language:this.language}),c}catch(t){if(t instanceof e)this.#ee(`
484
+ `)}var L=2e5,R=`playpad-file`,z={python:`main.py`,javascript:`main.js`,typescript:`main.ts`,java:`Main.java`,c:`main.c`,cpp:`main.cpp`,react:`src/main.jsx`};function B(e){return z[e]??`main.txt`}var V=e=>e.tagName===`SCRIPT`&&e.getAttribute(`type`)===`text/plain`;function H(e){return[...e.children].filter(e=>e.tagName.toLowerCase()===R&&[...e.children].some(e=>!V(e))).map(e=>e.getAttribute(`name`)??``)}function U(e,t){let n={};for(let t of e.children){if(t.tagName.toLowerCase()!==R)continue;let e=t.getAttribute(`name`),r=[...t.children].find(V);e&&(n[e]=I((r??t).textContent??``))}if(Object.keys(n).length)return n;let r=[...e.childNodes].filter(e=>e.nodeType!==Node.ELEMENT_NODE||e.tagName.toLowerCase()!==R),i=r.some(e=>e.nodeType===Node.ELEMENT_NODE),a=I(r.filter(e=>!(i&&e.nodeType===Node.TEXT_NODE&&!(e.textContent??``).trim())).map(e=>e.textContent??``).join(``));return{[t]:a}}function W(e,t){try{let t=JSON.parse(e);if(t&&typeof t==`object`&&!Array.isArray(t)){let e=t;return Object.keys(e).length?e:null}}catch{}return e?{[t]:e}:null}var G=typeof HTMLElement>`u`?class{}:HTMLElement,K=class extends G{static get observedAttributes(){return[`language`,`height`,`min-height`,`max-height`,`preview-height`,`file-view`,`open-file`,`theme`,`readonly`,`autorun`,`stdin`,`persist`,`entry`,`practice`]}#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u=null;#d=null;#f=null;#p=null;#m={};#h={};#g=`main.py`;#_=null;#v;#y=!1;#b=null;#x=!1;#S=!1;#C=null;#w=null;#T=null;#E=()=>this.#ue();#D=null;#O=!0;#k=[];#A=null;#j=null;#M=null;#N=0;#P=!1;#F=null;#I;#L;#R=null;#z=[];#B=/* @__PURE__ */ new Set;#V=null;#H=null;#U=null;constructor(){super(),this.#e=this.attachShadow({mode:`open`})}get code(){return this.#u?this.#u.getCode():this.#m[this.#g]??``}set code(e){this.#m[this.#g]=e,this.#X()}get practice(){if(this.#F)return this.#F;let e=this.getAttribute(`practice`);if(!e)return null;try{return JSON.parse(e)}catch{return null}}set practice(e){this.#F=e}get files(){return this.#ne()}set files(e){let t=Object.keys(e);if(!t.length)return;let n=Object.keys(this.#h);n.length===1&&!this.#h[n[0]]&&(this.#h={...e}),this.#m={...e},this.#z=[],t.includes(this.#g)||(this.#g=this.#ee()),this.#u?.forgetFiles([]),this.#X(),this.#re(),this.#Y()}get entry(){return this.#ee()}set entry(e){this.setAttribute(`entry`,e)}openFile(e){if(e in this.#m){this.#u&&(this.#m[this.#g]=this.#u.getCode(),this.#u.openFile(e,this.#m[e]??``)),this.#g=e;for(let t=e.indexOf(`/`);t!==-1;t=e.indexOf(`/`,t+1))this.#B.delete(e.slice(0,t));this.#re(),this.#Y()}}get stdin(){return this.#l?this.#l.value:``}set stdin(e){this.#l&&(this.#l.value=e,this.#c.hidden=!1)}get language(){return this.getAttribute(`language`)||`python`}set language(e){this.setAttribute(`language`,e)}getCode(){return this.code}getFiles(){return this.#ne()}reset(){this.#m={...this.#h},this.#g=this.#ee(),this.#u?.forgetFiles([]),this.#X(),this.#re(),this.#pe(),this.#s.hidden=!0,this.#oe(),this.#R=null,this.#se(),this.#fe(this.#f?.ready?`${this.#f.label} ready`:``,`idle`)}async run(){if(this.#V)return this.#V.widget.run();if(this.#y)return;await this.#d;let e=this.#ne(),r=this.getAttribute(`entry`);if(r&&!(r in e))return this.#Q(r,e);this.#Z=!1;let i=this.#ee(),a=e[i]??``;this.#y=!0,this.#x=!1,this.#n.disabled=!0,this.#r.hidden=!1,this.#pe(),this.#s.hidden=!1;let o=this.practice;this.hasAttribute(`practice`)&&!o&&this.#me(`The practice attribute is not valid JSON.
485
+ `,`cp-err`),this.#ae()&&(this.#R=e,this.#se(),this.#z.length&&this.#me(`${this.#z.join(`, `)}: HTML tags in this file's markup were read as elements, so its code is incomplete. Write < as &lt;, or put the code in <script type="text/plain">. A <script> left unescaped runs on the host page.\n`,`cp-err`)),this.#be(`py-run`,{code:a,entry:i,files:e,language:this.language,...o?{practice:o}:{}});try{let r=await this.#J();if(this.#x)throw new t;if(o&&!r.supportsPractice)throw Error(`Practice mode is not available for ${r.label}.`);this.#fe(`Queued…`,`busy`),this.#o.hidden=!1;let s=r.run(a,{stdin:this.#l.value,files:e,entry:i,onStart:()=>this.#fe(`Running…`,`busy`),onProgress:e=>this.#fe(e.message,`busy`),onStdout:e=>this.#me(e),onStderr:e=>this.#me(e,`cp-err`),onEcho:e=>this.#me(e,`cp-in`),onStdinRequest:()=>this.#ge(),...o?{practice:o}:{},...this.#ae()?{preview:{host:this.#I,onStart:()=>this.#fe(`Running…`,`busy`),onConsole:(e,t)=>{this.#me(`${t}\n`,e===`error`?`cp-err`:e===`warn`?`cp-warn`:void 0),this.#xe(`playpad-console`,{level:e,text:t,language:this.language})},onRender:e=>this.#xe(`playpad-render`,{rootText:e,language:this.language}),onError:e=>{this.#fe(`Error`,`error`),this.#be(`py-error`,{...e,language:this.language})}}}:{}});this.#b={runtime:r,run:s};let c=await s;if(c.table&&this.#ye(c.table),c.value!==void 0&&this.#me(`${c.value}\n`,`cp-value`),c.hint&&this.#ve(c.hint,n.has(c)),c.failed=r.statusDecidesFailure?c.failed===!0:!!c.stderr,c.failed)this.#fe(`Error · ${c.durationMs} ms`,`error`),this.#be(`py-error`,{message:c.problem?.message??c.stderr??``,hint:c.hint,language:this.language,...c.problem??{}});else if(c.cases){let e=c.cases.filter(e=>e.expected!==void 0).length,t=c.passed===e;this.#fe(e?`${c.passed} of ${e} passed · ${c.durationMs} ms`:`Done in ${c.durationMs} ms`,t?`ok`:`error`)}else this.#fe(`Done in ${c.durationMs} ms`,`ok`);return this.#be(`py-output`,{...c,language:this.language}),c}catch(e){if(e instanceof t)this.#me(`
306
486
  [stopped]
307
- `,`cp-err`),this.#Q(`Stopped`,`error`);else{let e=t instanceof Error?t.message:String(t);this.#ee(e+`
308
- `,`cp-err`),this.#Q(`Failed to start`,`error`),this.#oe(`py-error`,{message:e,language:this.language})}return}finally{this.#b=null,this.#re(null),this.#te(),this.#y=!1,this.#n.disabled=!1,this.#r.hidden=!0,this.#o.hidden=!0}}stop(){this.#b?this.#b.runtime.stop?.(this.#b.run):this.#y&&(this.#x=!0)}prewarm(){return this.#z()}connectedCallback(){this.#P?this.#R():!this.textContent?.trim()&&document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,()=>this.isConnected&&this.#I(),{once:!0}):this.#I()}disconnectedCallback(){this.#C?.disconnect(),this.#C=null,this.#w?.removeEventListener(`change`,this.#E),this.#w=null,this.#T?.disconnect(),this.#T=null,this.#D&&clearTimeout(this.#D),this.#re(null),setTimeout(()=>{!this.isConnected&&this.#u&&(this.#_=this.#K(),this.#u.destroy(),this.#u=null,this.#d=null,this.#P=!1)},0)}attributeChangedCallback(e,t,n){if(this.#P)switch(e){case`theme`:this.#X();break;case`height`:case`min-height`:case`max-height`:this.#Z();break;case`readonly`:this.#u?.setReadOnly(n!==null);break;case`stdin`:this.#c.hidden=n===null&&!this.#l.value;break;case`entry`:this.#q();break;case`language`:this.#f=null,this.#p=null,this.#S=!1,this.#z().catch(()=>{})}}#I(){this.#P=!0,this.#h=z(this,this.#W()),this.#m=this.#_??{...this.#h},this.#g=this.#G(),this.#L(),this.#X(),this.#Z();let e=this.getAttribute(`persist`);this.#d=(async()=>{if(e&&this.#_==null){let t=await O(e).catch(()=>null),n=t==null?null:B(t,this.#W());if(n){let e={},t=Object.keys(this.#h),r=Object.keys(n);for(let r of t)e[r]=n[r]??this.#h[r];t.length===1&&r.length===1&&!(t[0]in n)&&(e[t[0]]=n[r[0]]),this.#m=e,this.#g=this.#G()}}this.#q();let t=await h(this.language).catch(()=>null),n=t?await t.editorLanguage().catch(()=>null):null;this.#u=await c({parent:this.#t,doc:this.#m[this.#g]??``,name:this.#g,dark:this.#Y(),readOnly:this.hasAttribute(`readonly`),language:n,onRun:()=>void this.run(),onChange:e=>this.#J(e)}),this.#_=null,this.#B()})(),this.#R()}#L(){let e=document.createElement(`style`);e.textContent=g;let t=document.createElement(`div`);t.className=`cp-root`,t.innerHTML=`
487
+ `,`cp-err`),this.#fe(`Stopped`,`error`);else{let t=e instanceof Error?e.message:String(e);this.#me(t+`
488
+ `,`cp-err`),this.#fe(`Failed to start`,`error`),this.#be(`py-error`,{message:t,language:this.language})}return}finally{this.#b=null,this.#_e(null),this.#he(),this.#y=!1,this.#n.disabled=!1,this.#r.hidden=!(this.#ae()&&this.#f?.hasLivePreview?.(this.#I)),this.#o.hidden=!0}}stop(){this.#V?this.#V.widget.stop():this.#b?this.#b.runtime.stop?.(this.#b.run):this.#y?this.#x=!0:this.#ae()&&this.#f?.hasLivePreview?.(this.#I)&&(this.#oe(),this.#r.hidden=!0,this.#fe(`Stopped`,`idle`))}openWindow(){if(this.#V)return this.#V.window.focus(),!0;if(this.#H)return!1;let e=window.open(``,`_blank`,`popup,width=1280,height=800`);if(!e)return this.#fe(`The browser blocked the new window`,`error`),!1;let t=this.#ne(),n=this.#g,r=document.createElement(this.localName);for(let e of[`language`,`entry`,`file-view`,`preview-height`,`theme`,`readonly`,`stdin`]){let t=this.getAttribute(e);t!==null&&r.setAttribute(e,t)}r.setAttribute(`data-window`,``),r.#H=this,r.#U={...this.#h},r.#_=t,this.#oe(),this.#r.hidden=!0,e.document.title=`Code playground`,e.document.documentElement.style.height=`100%`,e.document.body.style.cssText=`margin:0;height:100%`,e.document.body.append(r);let i=()=>this.closeWindow();return window.addEventListener(`pagehide`,i),this.#V={window:e,widget:r,onLeave:i,timer:setInterval(()=>{e.closed&&this.closeWindow()},300)},this.#e.querySelector(`.cp-root`)?.classList.add(`cp-popped`),r.#d?.then(()=>(r.openFile(n),r.run())),!0}closeWindow(){let e=this.#V;if(!e)return;this.#V=null,clearInterval(e.timer),window.removeEventListener(`pagehide`,e.onLeave);let{widget:t}=e,n=t.#ne(),r=t.#g;t.#oe(),t.remove(),e.window.closed||e.window.close(),this.#e.querySelector(`.cp-root`)?.classList.remove(`cp-popped`),this.files=n,this.openFile(r),this.#fe(``,`idle`)}prewarm(){return this.#J()}connectedCallback(){this.#P?this.#q():!this.textContent?.trim()&&document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,()=>this.isConnected&&this.#W(),{once:!0}):this.#W()}disconnectedCallback(){this.#C?.disconnect(),this.#C=null,this.#w?.removeEventListener(`change`,this.#E),this.#w=null,this.#T?.disconnect(),this.#T=null,this.#D&&clearTimeout(this.#D),this.#_e(null),setTimeout(()=>{this.isConnected||(this.closeWindow(),this.#oe(),this.#u&&(this.#_=this.#ne(),this.#u.destroy(),this.#u=null,this.#d=null,this.#P=!1))},0)}attributeChangedCallback(e,t,n){if(this.#P)switch(e){case`theme`:this.#ue();break;case`height`:case`min-height`:case`max-height`:case`preview-height`:this.#de();break;case`readonly`:this.#u?.setReadOnly(n!==null);break;case`stdin`:this.#c.hidden=n===null&&!this.#l.value;break;case`entry`:case`file-view`:this.#re();break;case`language`:this.#oe(),this.#e.querySelector(`.cp-root`)?.classList.toggle(`cp-has-preview`,this.#ae()),this.#f=null,this.#p=null,this.#S=!1,this.#J().catch(()=>{})}}#W(){this.#P=!0,this.#h=this.#U??U(this,this.#$()),this.#z=this.#ae()?H(this):[],this.#m=this.#_??{...this.#h},this.#g=this.#te(),this.#G(),this.#ue(),this.#de();let e=this.getAttribute(`persist`);this.#d=(async()=>{if(e&&this.#_==null){let t=await A(e).catch(()=>null),n=t==null?null:W(t,this.#$());if(n){let e={},t=Object.keys(this.#h),r=Object.keys(n);for(let r of t)e[r]=n[r]??this.#h[r];t.length===1&&r.length===1&&!(t[0]in n)&&(e[t[0]]=n[r[0]]),this.#m=e,this.#g=this.#te()}}this.#re();let t=await _(this.language).catch(()=>null),n=t?await t.editorLanguage().catch(()=>null):null;this.#u=await u({parent:this.#t,doc:this.#m[this.#g]??``,name:this.#g,dark:this.#le(),readOnly:this.hasAttribute(`readonly`),language:n,onRun:()=>void this.run(),onChange:e=>this.#ce(e)}),this.#_=null,this.#Y()})(),this.#q()}#G(){let e=document.createElement(`style`);e.textContent=v;let t=document.createElement(`div`);t.className=this.#ae()?`cp-root cp-has-preview`:`cp-root`,t.innerHTML=`
309
489
  <div class="cp-toolbar">
310
490
  <button class="cp-primary" part="run-button" data-action="run">Run</button>
311
491
  <button class="cp-danger" part="stop-button" data-action="stop" hidden>Stop</button>
312
492
  <button data-action="reset">Reset</button>
313
493
  <span class="cp-spacer"></span>
494
+ <button part="window-button" class="cp-window-button" data-action="window" title="Open in a separate window you can resize">Open in window</button>
495
+ <span class="cp-edited-note" hidden>Edited since the last run</span>
314
496
  <span class="cp-status" data-state="idle"></span>
315
497
  </div>
316
498
  <div class="cp-progress" hidden></div>
317
- <div class="cp-tabs" part="tabs" hidden></div>
318
- <div class="cp-editor"></div>
319
- <div class="cp-stdin" hidden>
320
- <label>Standard input — one value per line</label>
321
- <textarea rows="2" spellcheck="false"></textarea>
499
+ <div class="cp-window-note">
500
+ <span>Running in a separate window.</span>
501
+ <button data-action="show-window">Show window</button>
502
+ <button data-action="close-window">Bring back here</button>
322
503
  </div>
323
- <pre class="cp-output" part="output" hidden></pre>`,this.#e.replaceChildren(e,t),this.#n=t.querySelector(`[data-action="run"]`),this.#r=t.querySelector(`[data-action="stop"]`),this.#i=t.querySelector(`[data-action="reset"]`),this.#a=t.querySelector(`.cp-status`),this.#o=t.querySelector(`.cp-progress`),this.#v=t.querySelector(`.cp-tabs`),this.#t=t.querySelector(`.cp-editor`),this.#c=t.querySelector(`.cp-stdin`),this.#l=t.querySelector(`.cp-stdin textarea`),this.#s=t.querySelector(`.cp-output`),this.#c.hidden=!this.hasAttribute(`stdin`),this.#l.addEventListener(`input`,()=>this.#c.classList.remove(`cp-attention`)),this.#v.addEventListener(`click`,e=>{let t=e.target.closest(`button[data-file]`);t&&this.openFile(t.getAttribute(`data-file`))}),this.#n.addEventListener(`click`,()=>void this.run()),this.#r.addEventListener(`click`,()=>this.stop()),this.#i.addEventListener(`click`,()=>this.reset());let n=()=>void this.#z().catch(()=>{});this.#t.addEventListener(`pointerdown`,n,{once:!0}),this.#t.addEventListener(`focusin`,n,{once:!0})}#R(){this.#C||typeof IntersectionObserver>`u`||(this.#C=new IntersectionObserver(e=>{e.some(e=>e.isIntersecting)&&(this.#C?.disconnect(),this.#C=null,this.#z().then(()=>{this.hasAttribute(`autorun`)&&this.run()}).catch(()=>{}))},{rootMargin:`300px`}),this.#C.observe(this))}#z(){return this.#p||=(async()=>{let e=await h(this.language);this.#f=e,!e.ready&&!this.#H&&(this.#o.hidden=!1,this.#Q(`Loading ${e.label}…`,`busy`));try{await e.load(e=>{!this.#y&&!this.#H&&this.#Q(e.message,e.phase===`ready`?`ok`:`busy`)})}catch(e){this.#p=null,this.#Q(`Runtime unavailable`,`error`);let t=e instanceof Error?e.message:String(e);throw this.#ee(t+`
324
- `,`cp-err`),this.#s.hidden=!1,e}finally{this.#o.hidden=!0}return this.#B(),this.#S||(this.#S=!0,this.#H||this.#Q(`${e.label} ready`,`ok`),this.#oe(`py-ready`,{language:e.id,label:e.label})),e})(),this.#p}async#B(){if(!this.#u)return;let e=this.#g,t=await y(e);if(t){this.#g===e&&this.#u?.setLanguage(t);return}let n=e.includes(`.`)?null:await(this.#f??await h(this.language).catch(()=>null))?.editorLanguage().catch(()=>null);this.#g===e&&this.#u?.setLanguage(n??[])}#V(){this.#u?this.#u.setCode(this.#m[this.#g]??``):this.#d?.then(()=>{this.#u?.setCode(this.#m[this.#g]??``),this.#q()})}#H=!1;#U(e,t){let n=Object.keys(t),r=`This widget's entry is "${e}", but it has no file of that name${n.length?` (its files: ${n.join(`, `)})`:``}. Set entry to one of its files.\n`;this.#$(),this.#s.hidden=!1,this.#ee(r,`cp-err`),this.#H=!0,this.#Q(`Error · entry not found`,`error`);let i={stdout:``,stderr:r,durationMs:0,failed:!0};return this.#oe(`py-error`,{message:r,language:this.language}),this.#oe(`py-output`,{...i,language:this.language}),i}#W(){return this.getAttribute(`entry`)||R(this.language)}#G(){let e=Object.keys(this.#m),t=this.getAttribute(`entry`);if(t&&e.includes(t))return t;let n=R(this.language);return e.includes(n)?n:e[0]??n}#K(){let e={...this.#m};if(this.#u)for(let t of Object.keys(e))e[t]=this.#u.fileCode(t,e[t]);return e}#q(){let e=Object.keys(this.#m);if(this.#v.hidden=e.length<2,this.#v.hidden){this.#v.replaceChildren();return}let t=this.#G();this.#v.replaceChildren(...e.map(e=>{let n=document.createElement(`button`);return n.dataset.file=e,n.textContent=e,n.setAttribute(`aria-pressed`,String(e===this.#g)),e===t&&(n.classList.add(`cp-entry`),n.title=`entry point — this is the file Run executes`),n}))}#J(e){this.#m[this.#g]=e;let t=this.getAttribute(`persist`);if(!t)return;this.#D&&clearTimeout(this.#D);let n=JSON.stringify(this.#K());this.#D=setTimeout(()=>void D(t,n).catch(()=>{}),400)}#Y(){let e=this.getAttribute(`theme`)??`auto`;if(e===`dark`)return!0;if(e===`light`)return!1;let t=typeof document>`u`?``:getComputedStyle(document.documentElement).colorScheme,n=t.includes(`dark`);return n===t.includes(`light`)?!!this.#w?.matches:n}#X(){!this.#w&&typeof matchMedia==`function`&&(this.#w=matchMedia(`(prefers-color-scheme: dark)`),this.#w.addEventListener(`change`,this.#E)),!this.#T&&typeof MutationObserver==`function`&&typeof document<`u`&&(this.#T=new MutationObserver(this.#E),this.#T.observe(document.documentElement,{attributes:!0,attributeFilter:[`class`,`style`,`data-theme`,`data-color-scheme`,`color-scheme`]}));let e=this.#Y();this.setAttribute(`data-resolved-theme`,e?`dark`:`light`),this.#u?.setTheme(e)}#Z(){for(let[e,t]of[[`height`,`--cp-height`],[`min-height`,`--cp-min-height`],[`max-height`,`--cp-max-height`]]){let n=this.getAttribute(e);n===null||n===``?this.style.removeProperty(t):this.style.setProperty(t,/^\d+$/.test(n)?`${n}px`:n)}}#Q(e,t){this.#a.textContent=e,this.#a.dataset.state=t}#$(){this.#M&&clearTimeout(this.#M),this.#M=null,this.#k=[],this.#N=0,this.#s.replaceChildren(),this.#O=!0}#ee(e,t){if(!e)return;let n=t===`cp-err`&&!this.#O?`\n${e}`:e;this.#O=n.endsWith(`
325
- `),this.#k.push({text:n,className:t}),this.#M??=setTimeout(()=>this.#te(),16)}#te(){if(this.#M&&clearTimeout(this.#M),this.#M=null,!this.#k.length)return;let e=this.#k;this.#k=[];let t=document.createDocumentFragment(),n=``,r,i=()=>{if(!n)return;let e=document.createElement(`span`);r&&(e.className=r),e.textContent=n,t.appendChild(e),n=``};for(let t of e){if(this.#N>=F)break;let e=t.text;this.#N+e.length>F&&(e=e.slice(0,F-this.#N)+`
504
+ <div class="cp-body">
505
+ <div class="cp-source">
506
+ <div class="cp-tabs" part="tabs" hidden></div>
507
+ <div class="cp-split cp-split-tree" role="separator" tabindex="0" aria-orientation="vertical" aria-label="Resize the file tree"></div>
508
+ <div class="cp-editor"></div>
509
+ <div class="cp-stdin" hidden>
510
+ <label>Standard input — one value per line</label>
511
+ <textarea rows="2" spellcheck="false"></textarea>
512
+ </div>
513
+ </div>
514
+ <div class="cp-split cp-split-main" role="separator" tabindex="0" aria-label="Resize the code and the preview"></div>
515
+ <div class="cp-preview-pane">
516
+ <div class="cp-preview" part="preview"></div>
517
+ <div class="cp-split cp-split-console" role="separator" tabindex="0" aria-orientation="horizontal" aria-label="Resize the preview and the console"></div>
518
+ <pre class="cp-output" part="output" hidden></pre>
519
+ </div>
520
+ </div>`,this.#e.replaceChildren(e,t),this.#n=t.querySelector(`[data-action="run"]`),this.#r=t.querySelector(`[data-action="stop"]`),this.#i=t.querySelector(`[data-action="reset"]`),this.#a=t.querySelector(`.cp-status`),this.#o=t.querySelector(`.cp-progress`),this.#v=t.querySelector(`.cp-tabs`),this.#t=t.querySelector(`.cp-editor`),this.#c=t.querySelector(`.cp-stdin`),this.#l=t.querySelector(`.cp-stdin textarea`),this.#s=t.querySelector(`.cp-output`),this.#I=t.querySelector(`.cp-preview`),this.#L=t.querySelector(`.cp-edited-note`),this.#ae()||t.querySelector(`.cp-source`).after(this.#s),this.#c.hidden=!this.hasAttribute(`stdin`),this.#l.addEventListener(`input`,()=>this.#c.classList.remove(`cp-attention`)),this.#v.addEventListener(`click`,e=>{let t=e.target,n=t.closest(`button[data-file]`);n&&this.openFile(n.getAttribute(`data-file`));let r=t.closest(`button[data-folder]`)?.dataset.folder;r!==void 0&&(this.#B.delete(r)||this.#B.add(r),this.#re())}),this.#n.addEventListener(`click`,()=>void this.run()),this.#r.addEventListener(`click`,()=>this.stop()),this.#i.addEventListener(`click`,()=>this.reset()),t.querySelector(`[data-action="window"]`).addEventListener(`click`,()=>this.openWindow()),t.querySelector(`[data-action="show-window"]`).addEventListener(`click`,()=>this.openWindow()),t.querySelector(`[data-action="close-window"]`).addEventListener(`click`,()=>this.closeWindow()),this.#K(t);let n=()=>void this.#J().catch(()=>{});this.#t.addEventListener(`pointerdown`,n,{once:!0}),this.#t.addEventListener(`focusin`,n,{once:!0})}#K(e){let t=e.querySelector(`.cp-body`),n=e.querySelector(`.cp-source`),r=e.querySelector(`.cp-preview`),i=e.querySelector(`.cp-preview-pane`),a=this.#v,o=(e,t,n)=>Math.round(Math.max(t,Math.min(e,Math.max(t,n)))),s=(t,n)=>e.style.setProperty(t,`${n}px`),c=(t,n,r,i,a)=>{let o=()=>t.setAttribute(`aria-orientation`,n()===`x`?`vertical`:`horizontal`);t.addEventListener(`pointerdown`,a=>{a.preventDefault();let o=n()===`x`,s=o?a.clientX:a.clientY,c=r();t.setPointerCapture(a.pointerId),e.classList.add(`cp-dragging`,o?`cp-dragging-x`:`cp-dragging-y`);let l=e=>i(c+(o?e.clientX:e.clientY)-s),u=()=>{e.classList.remove(`cp-dragging`,`cp-dragging-x`,`cp-dragging-y`),t.removeEventListener(`pointermove`,l),t.removeEventListener(`pointerup`,u),t.removeEventListener(`pointercancel`,u)};t.addEventListener(`pointermove`,l),t.addEventListener(`pointerup`,u),t.addEventListener(`pointercancel`,u)}),t.addEventListener(`keydown`,e=>{let t={ArrowLeft:-24,ArrowUp:-24,ArrowRight:24,ArrowDown:24}[e.key];t&&(e.preventDefault(),i(r()+t))}),t.addEventListener(`dblclick`,a),t.addEventListener(`focus`,o),t.addEventListener(`pointerenter`,o)},l=()=>getComputedStyle(t).flexDirection===`row`&&getComputedStyle(t).display===`flex`;c(e.querySelector(`.cp-split-tree`),()=>`x`,()=>a.getBoundingClientRect().width,e=>s(`--cp-tree-width`,o(e,90,n.getBoundingClientRect().width-160)),()=>e.style.removeProperty(`--cp-tree-width`)),c(e.querySelector(`.cp-split-main`),()=>l()?`x`:`y`,()=>l()?n.getBoundingClientRect().width:this.#t.getBoundingClientRect().height,n=>{l()?s(`--cp-source-width`,o(n,200,t.getBoundingClientRect().width-200)):(s(`--cp-editor-height`,o(n,80,2e3)),e.classList.add(`cp-editor-sized`))},()=>{e.style.removeProperty(`--cp-source-width`),e.style.removeProperty(`--cp-editor-height`),e.classList.remove(`cp-editor-sized`)}),c(e.querySelector(`.cp-split-console`),()=>`y`,()=>r.getBoundingClientRect().height,e=>s(`--cp-preview-height`,o(e,60,l()||this.#H?i.getBoundingClientRect().height-40:2e3)),()=>e.style.removeProperty(`--cp-preview-height`))}#q(){this.#H||this.#C||typeof IntersectionObserver>`u`||(this.#C=new IntersectionObserver(e=>{e.some(e=>e.isIntersecting)&&(this.#C?.disconnect(),this.#C=null,this.#J().then(()=>{this.hasAttribute(`autorun`)&&this.run()}).catch(()=>{}))},{rootMargin:`300px`}),this.#C.observe(this))}#J(){return this.#p||=(async()=>{let e=await _(this.language);this.#f=e,!e.ready&&!this.#Z&&(this.#o.hidden=!1,this.#fe(`Loading ${e.label}…`,`busy`));try{await e.load(e=>{!this.#y&&!this.#Z&&this.#fe(e.message,e.phase===`ready`?`ok`:`busy`)})}catch(e){this.#p=null,this.#fe(`Runtime unavailable`,`error`);let t=e instanceof Error?e.message:String(e);throw this.#me(t+`
521
+ `,`cp-err`),this.#s.hidden=!1,e}finally{this.#o.hidden=!0}return this.#Y(),this.#S||(this.#S=!0,this.#Z||this.#fe(`${e.label} ready`,`ok`),this.#be(`py-ready`,{language:e.id,label:e.label})),e})(),this.#p}async#Y(){if(!this.#u)return;let e=this.#g,t=await x(e,this.language);if(t){this.#g===e&&this.#u?.setLanguage(t);return}let n=e.includes(`.`)?null:await(this.#f??await _(this.language).catch(()=>null))?.editorLanguage().catch(()=>null);this.#g===e&&this.#u?.setLanguage(n??[])}#X(){this.#u?this.#u.setCode(this.#m[this.#g]??``):this.#d?.then(()=>{this.#u?.setCode(this.#m[this.#g]??``),this.#re()})}#Z=!1;#Q(e,t){let n=Object.keys(t),r=`This widget's entry is "${e}", but it has no file of that name${n.length?` (its files: ${n.join(`, `)})`:``}. Set entry to one of its files.\n`;this.#pe(),this.#s.hidden=!1,this.#me(r,`cp-err`),this.#Z=!0,this.#fe(`Error · entry not found`,`error`);let i={stdout:``,stderr:r,durationMs:0,failed:!0};return this.#be(`py-error`,{message:r,language:this.language}),this.#be(`py-output`,{...i,language:this.language}),i}#$(){return this.getAttribute(`entry`)||B(this.language)}#ee(){let e=Object.keys(this.#m),t=this.getAttribute(`entry`);if(t&&e.includes(t))return t;let n=this.#ae()&&e.includes(`index.html`)?`index.html`:B(this.language);return e.includes(n)?n:e[0]??n}#te(){let e=this.getAttribute(`open-file`);return e&&e in this.#m?e:this.#ee()}#ne(){if(this.#V)return this.#V.widget.#ne();let e={...this.#m};if(this.#u)for(let t of Object.keys(e))e[t]=this.#u.fileCode(t,e[t]);return e}#re(){let e=Object.keys(this.#m);this.#v.hidden=e.length<2;let t=!this.#v.hidden&&this.getAttribute(`file-view`)===`tree`;if(this.#v.classList.toggle(`cp-tree`,t),this.#e.querySelector(`.cp-root`)?.classList.toggle(`cp-has-tree`,t),this.#v.hidden){this.#v.replaceChildren();return}if(t){this.#ie(e),this.#se();return}let n=this.#ee();this.#v.replaceChildren(...e.map(e=>{let t=document.createElement(`button`);t.dataset.file=e;let r=e.lastIndexOf(`/`)+1;if(r){let n=document.createElement(`span`);n.className=`cp-tab-folder`,n.textContent=e.slice(0,r),t.setAttribute(`aria-label`,e),t.append(n)}return t.append(e.slice(r)),t.setAttribute(`aria-pressed`,String(e===this.#g)),e===n&&(t.classList.add(`cp-entry`),t.title=`entry point — this is the file Run executes`),t})),this.#se()}#ie(e){let t=this.#ee(),n=[],r=(i,a)=>{let o=e.filter(e=>e.startsWith(i)).map(e=>e.slice(i.length)),s=[...new Set(o.filter(e=>e.includes(`/`)).map(e=>e.slice(0,e.indexOf(`/`))))].sort();for(let e of s){let t=i+e,o=!this.#B.has(t),s=document.createElement(`button`);s.className=`cp-tree-folder`,s.dataset.folder=t,s.textContent=e,s.setAttribute(`aria-expanded`,String(o)),s.style.setProperty(`--cp-depth`,String(a)),n.push(s),o&&r(`${t}/`,a+1)}for(let e of o.filter(e=>!e.includes(`/`)).sort()){let r=i+e,o=document.createElement(`button`);o.dataset.file=r,o.textContent=e,o.setAttribute(`aria-label`,r),o.setAttribute(`aria-pressed`,String(r===this.#g)),o.style.setProperty(`--cp-depth`,String(a)),r===t&&(o.classList.add(`cp-entry`),o.title=`entry point — this is the file Run executes`),n.push(o)}};r(``,0),this.#v.replaceChildren(...n)}#ae(){return this.language===`react`}#oe(){this.#I&&(this.#f?.dispose?.(this.#I),this.#I.replaceChildren())}#se(){if(!this.#ae())return;let e=this.#ne();for(let t of this.#v.querySelectorAll(`button[data-file]`)){let n=t.dataset.file;t.classList.toggle(`cp-edited`,e[n]!==this.#h[n])}let t=this.#R;this.#L.hidden=!t||Object.keys(e).every(n=>e[n]===t[n])}#ce(e){this.#m[this.#g]=e,this.#se();let t=this.getAttribute(`persist`);if(!t)return;this.#D&&clearTimeout(this.#D);let n=JSON.stringify(this.#ne());this.#D=setTimeout(()=>void k(t,n).catch(()=>{}),400)}#le(){let e=this.getAttribute(`theme`)??`auto`;if(e===`dark`)return!0;if(e===`light`)return!1;let t=typeof document>`u`?``:getComputedStyle(document.documentElement).colorScheme,n=t.includes(`dark`);return n===t.includes(`light`)?!!this.#w?.matches:n}#ue(){!this.#w&&typeof matchMedia==`function`&&(this.#w=matchMedia(`(prefers-color-scheme: dark)`),this.#w.addEventListener(`change`,this.#E)),!this.#T&&typeof MutationObserver==`function`&&typeof document<`u`&&(this.#T=new MutationObserver(this.#E),this.#T.observe(document.documentElement,{attributes:!0,attributeFilter:[`class`,`style`,`data-theme`,`data-color-scheme`,`color-scheme`]}));let e=this.#le();this.setAttribute(`data-resolved-theme`,e?`dark`:`light`),this.#u?.setTheme(e)}#de(){for(let[e,t]of[[`height`,`--cp-height`],[`min-height`,`--cp-min-height`],[`max-height`,`--cp-max-height`],[`preview-height`,`--cp-preview-height`]]){let n=this.getAttribute(e);n===null||n===``?this.style.removeProperty(t):this.style.setProperty(t,/^\d+$/.test(n)?`${n}px`:n)}}#fe(e,t){this.#a.textContent=e,this.#a.dataset.state=t}#pe(){this.#M&&clearTimeout(this.#M),this.#M=null,this.#k=[],this.#N=0,this.#s.replaceChildren(),this.#O=!0}#me(e,t){if(!e)return;let n=t===`cp-err`&&!this.#O?`\n${e}`:e;this.#O=n.endsWith(`
522
+ `),this.#k.push({text:n,className:t}),this.#M??=setTimeout(()=>this.#he(),16)}#he(){if(this.#M&&clearTimeout(this.#M),this.#M=null,!this.#k.length)return;let e=this.#k;this.#k=[];let t=document.createDocumentFragment(),n=``,r,i=()=>{if(!n)return;let e=document.createElement(`span`);r&&(e.className=r),e.textContent=n,t.appendChild(e),n=``};for(let t of e){if(this.#N>=L)break;let e=t.text;this.#N+e.length>L&&(e=e.slice(0,L-this.#N)+`
326
523
  … output truncated for display — the full text is in the playpad-output event
327
- `),this.#N+=t.text.length,r!==t.className&&(i(),r=t.className),n+=e}i(),this.#s.hidden=!1;let a=this.#s.querySelector(`.cp-prompt`);a?this.#s.insertBefore(t,a):this.#s.appendChild(t),this.#s.scrollTop=this.#s.scrollHeight}#ne(){return this.#te(),this.#re(null),new Promise(e=>{let t=document.createElement(`form`);t.className=`cp-prompt`;let n=document.createElement(`input`);n.type=`text`,n.setAttribute(`aria-label`,`Program input — press Enter to send`),n.autocapitalize=`off`,n.autocomplete=`off`,n.spellcheck=!1;let r=document.createElement(`button`);r.type=`submit`,r.className=`cp-send`,r.textContent=`⏎`,r.title=`Send this line (Enter)`;let i=document.createElement(`button`);i.type=`button`,i.className=`cp-eof`,i.textContent=`EOF`,i.title=`End of input (Ctrl-D) — makes input() raise EOFError`;let a=n=>{this.#A===e&&(this.#A=null,this.#j=null,t.remove(),n===null?this.#ee(`
328
- `,`cp-in`):this.#ee(n+`
329
- `,`cp-in`),this.#te(),e(n))};t.addEventListener(`submit`,e=>{e.preventDefault(),a(n.value)}),i.addEventListener(`click`,()=>a(null)),n.addEventListener(`keydown`,e=>{(e.key===`Escape`||e.key===`d`&&e.ctrlKey)&&(e.preventDefault(),a(null))}),t.append(n,r,i),this.#s.hidden=!1,this.#s.appendChild(t),this.#s.scrollTop=this.#s.scrollHeight,this.#A=e,this.#j=a,n.focus({preventScroll:!0})})}#re(e){this.#j?.(e),this.#j=null,this.#A=null}#ie(e,t){this.#te();let n=document.createElement(`div`);n.className=`cp-hint`,n.textContent=e,this.#s.hidden=!1,this.#s.appendChild(n),this.#s.scrollTop=this.#s.scrollHeight,t&&(this.#c.hidden=!1,this.#c.classList.add(`cp-attention`))}#ae(e){this.#te();let t=document.createElement(`table`);t.className=`cp-table`;let n=t.createTHead().insertRow();for(let t of e.columns){let e=document.createElement(`th`);e.textContent=t,n.appendChild(e)}let r=t.createTBody();for(let t of e.rows){let e=r.insertRow();for(let n of t)e.insertCell().textContent=n==null?``:String(n)}this.#s.hidden=!1,this.#s.appendChild(t)}#oe(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent(`playpad-${e.slice(3)}`,{detail:t,bubbles:!0,composed:!0}))}};function U(e=N){typeof window<`u`&&typeof customElements<`u`&&(customElements.get(e)||customElements.define(e,H))}U();export{H as CodePlayPadElement,s as PYODIDE_VERSION,e as RunStopped,t as WorkerUnavailable,M as allProgress,k as clearSnippet,a as configureCpp,o as configurePython,i as configureTypeScript,c as createEditor,U as defineCodePlayPad,j as getProgress,h as getRuntime,m as listRuntimes,O as loadSnippet,r as pyodideAssetUrls,p as registerRuntime,D as saveSnippet,A as setProgress};
524
+ `),this.#N+=t.text.length,r!==t.className&&(i(),r=t.className),n+=e}i(),this.#s.hidden=!1;let a=this.#s.querySelector(`.cp-prompt`);a?this.#s.insertBefore(t,a):this.#s.appendChild(t),this.#s.scrollTop=this.#s.scrollHeight}#ge(){return this.#he(),this.#_e(null),new Promise(e=>{let t=document.createElement(`form`);t.className=`cp-prompt`;let n=document.createElement(`input`);n.type=`text`,n.setAttribute(`aria-label`,`Program input — press Enter to send`),n.autocapitalize=`off`,n.autocomplete=`off`,n.spellcheck=!1;let r=document.createElement(`button`);r.type=`submit`,r.className=`cp-send`,r.textContent=`⏎`,r.title=`Send this line (Enter)`;let i=document.createElement(`button`);i.type=`button`,i.className=`cp-eof`,i.textContent=`EOF`,i.title=`End of input (Ctrl-D) — makes input() raise EOFError`;let a=n=>{this.#A===e&&(this.#A=null,this.#j=null,t.remove(),n===null?this.#me(`
525
+ `,`cp-in`):this.#me(n+`
526
+ `,`cp-in`),this.#he(),e(n))};t.addEventListener(`submit`,e=>{e.preventDefault(),a(n.value)}),i.addEventListener(`click`,()=>a(null)),n.addEventListener(`keydown`,e=>{(e.key===`Escape`||e.key===`d`&&e.ctrlKey)&&(e.preventDefault(),a(null))}),t.append(n,r,i),this.#s.hidden=!1,this.#s.appendChild(t),this.#s.scrollTop=this.#s.scrollHeight,this.#A=e,this.#j=a,n.focus({preventScroll:!0})})}#_e(e){this.#j?.(e),this.#j=null,this.#A=null}#ve(e,t){this.#he();let n=document.createElement(`div`);n.className=`cp-hint`,n.textContent=e,this.#s.hidden=!1,this.#s.appendChild(n),this.#s.scrollTop=this.#s.scrollHeight,t&&(this.#c.hidden=!1,this.#c.classList.add(`cp-attention`))}#ye(e){this.#he();let t=document.createElement(`table`);t.className=`cp-table`;let n=t.createTHead().insertRow();for(let t of e.columns){let e=document.createElement(`th`);e.textContent=t,n.appendChild(e)}let r=t.createTBody();for(let t of e.rows){let e=r.insertRow();for(let n of t)e.insertCell().textContent=n==null?``:String(n)}this.#s.hidden=!1,this.#s.appendChild(t)}#be(e,t){this.#xe(e,t),this.#xe(`playpad-${e.slice(3)}`,t)}#xe(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0})),this.#H?.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}};function q(e=F){typeof window<`u`&&typeof customElements<`u`&&(customElements.get(e)||customElements.define(e,K))}q();export{K as CodePlayPadElement,c as PYODIDE_VERSION,r as REACT_VERSION,t as RunStopped,e as WorkerUnavailable,P as allProgress,j as clearSnippet,o as configureCpp,s as configurePython,a as configureReact,i as configureTypeScript,u as createEditor,q as defineCodePlayPad,N as getProgress,_ as getRuntime,g as listRuntimes,A as loadSnippet,l as pyodideAssetUrls,h as registerRuntime,k as saveSnippet,M as setProgress};
@@ -3,4 +3,4 @@
3
3
  * Bundles CodeMirror 6 and Lezer (MIT) © Marijn Haverbeke and others.
4
4
  * Full third-party licences: THIRD-PARTY-NOTICES.txt in this package.
5
5
  */
6
- var e=class extends Error{constructor(e=`Execution stopped`){super(e),this.name=`RunStopped`}},t=class extends Error{constructor(e=`Web Workers are unavailable in this page`){super(e),this.name=`WorkerUnavailable`}},n=/* @__PURE__ */ new WeakSet;export{e as n,t as r,n as t};
6
+ var e=class extends Error{constructor(e=`Execution stopped`){super(e),this.name=`RunStopped`}},t=class extends Error{constructor(e=`Web Workers are unavailable in this page`){super(e),this.name=`WorkerUnavailable`}};export{t as n,e as t};
package/dist/types.d.ts CHANGED
@@ -20,6 +20,8 @@ export interface Result {
20
20
  compilerBytes: number;
21
21
  programBytes: number;
22
22
  };
23
+ /** React: the error that failed the run, with where it is when known. */
24
+ problem?: PreviewProblem;
23
25
  /** Practice mode: one result per case, in order. */
24
26
  cases?: CaseResult[];
25
27
  /** Practice mode: cases that passed, and cases run. */
@@ -98,6 +100,21 @@ export interface LoadProgress {
98
100
  /** name -> contents. Names are relative paths: "utils.py", "pkg/__init__.py",
99
101
  * "data.csv". Written into the runtime's filesystem before the run. */
100
102
  export type Files = Record<string, string>;
103
+ export interface PreviewProblem {
104
+ message: string;
105
+ file?: string;
106
+ line?: number;
107
+ column?: number;
108
+ }
109
+ /** Where a runtime that renders a page (React) shows it, and how it reports back. */
110
+ export interface PreviewBinding {
111
+ host: HTMLElement;
112
+ onStart?: () => void;
113
+ onConsole: (level: 'log' | 'info' | 'warn' | 'error', text: string) => void;
114
+ onRender: (rootText: string) => void;
115
+ /** An error after the run finished: in an event handler or a later render. */
116
+ onError: (problem: PreviewProblem) => void;
117
+ }
101
118
  export interface RunOptions {
102
119
  /** Progress for this run, including compiler downloads and compilation. */
103
120
  onProgress?: (progress: LoadProgress) => void;
@@ -123,6 +140,8 @@ export interface RunOptions {
123
140
  onStderr?: (chunk: string) => void;
124
141
  /** Practice mode, for runtimes that support it (`supportsPractice`). */
125
142
  practice?: PracticeSpec;
143
+ /** For runtimes that render a page (React). */
144
+ preview?: PreviewBinding;
126
145
  }
127
146
  export interface Runtime {
128
147
  /** stable id used by the registry, e.g. "python" */
@@ -139,6 +158,10 @@ export interface Runtime {
139
158
  * already executing kills the worker, which reboots. With no argument, kills
140
159
  * the worker and fails whichever run is active. */
141
160
  stop?(run?: Promise<Result>): void;
161
+ /** Runtimes that render a page: whether this preview's app is still running. */
162
+ hasLivePreview?(host: HTMLElement): boolean;
163
+ /** Runtimes that render a page: remove this preview's app. */
164
+ dispose?(host: HTMLElement): void;
142
165
  /** true once load() has resolved and the runtime is usable */
143
166
  readonly ready: boolean;
144
167
  /** Whether run() honors RunOptions.practice (Java). */
@@ -0,0 +1,9 @@
1
+ /*!
2
+ * code-playpad — MIT © 2026 Seung Hun Lee
3
+ * Bundles CodeMirror 6 and Lezer (MIT) © Marijn Haverbeke and others.
4
+ * Full third-party licences: THIRD-PARTY-NOTICES.txt in this package.
5
+ */
6
+ import{n as e,t}from"./types-CfcYqU2K.js";import{t as n}from"./hints-DpBIeoeG.js";var r=1,i=class{#e=null;#t=null;#n=`module`;#r=null;#i=null;#a=!1;#o=!1;#s=``;#c=/* @__PURE__ */ new Set;#l=[];#u=null;#d=!1;initPayload(){return{}}loadModule(e){return Promise.reject(/* @__PURE__ */ Error(`no module named ${e}`))}get ready(){return this.#a}get interactiveStdin(){return this.#o}get version(){return this.#s}load(t){t&&this.#c.add(t);let n=()=>{t&&this.#c.delete(t)};if(!this.#r){let t=new Promise((t,n)=>{this.#i={resolve:t,reject:n};let r;try{if(typeof Worker>`u`)throw Error(`Worker constructor missing`);let e=new Blob([this.source],{type:`text/javascript`});this.#t=URL.createObjectURL(e),r=new Worker(this.#t,{type:this.#n})}catch(t){this.#i=null,n(new e(`Could not start a Web Worker: ${t.message}`));return}this.#e=r,r.onmessage=e=>{let r=e.data;r.type===`ready`?(this.#s=r.version,this.#o=r.interactiveStdin===!0,this.#a=!0,this.#i=null,this.#h({phase:`ready`,message:`${this.label} ready`}),t()):r.type===`fatal`&&!this.#a?this.#p(r.message,t,n):this.#g(r)},r.onerror=e=>{let r=e.message||`Worker failed to start`;this.#a?this.#u&&this.#y(this.#u,Error(r)):this.#p(r,t,n)},r.postMessage({type:`init`,...this.initPayload()})});this.#r=t,t.catch(()=>{this.#r===t&&(this.#r=null)})}return this.#r.then(n,e=>{throw n(),e})}run(e,t={}){let n,i,a=new Promise((e,t)=>{n=e,i=t}),o,s=new Promise(e=>{o=e}),c={id:r++,code:e,options:t,stdout:``,stderr:``,resolve:n,reject:i,promise:a,started:!1,settled:!1,done:s,markDone:()=>{clearTimeout(c.timer),c.settled=!0,o()}};return this.#l.push(c),this.#b(),a}stop(e){if(e){let n=this.#l.findIndex(t=>t.promise===e);if(n!==-1){this.#y(this.#l.splice(n,1)[0],new t);return}let r=this.#u;if(!r||r.promise!==e||r.settled)return;if(!r.started){this.#y(r,new t);return}}this.#f()}#f(){let e=this.#e!==null,n=this.#i;if(this.#m(),this.#u&&this.#y(this.#u,new t),e){let e=this.load();n&&e.then(n.resolve,n.reject),e.catch(()=>{})}}#p(e,t,n){this.#m(),this.#n===`module`?(this.#n=`classic`,this.load().then(t,n)):n(Error(e))}#m(){this.#e?.terminate(),this.#e=null,this.#t&&=(URL.revokeObjectURL(this.#t),null),this.#r=null,this.#i=null,this.#a=!1}#h(e){for(let t of this.#c)t(e)}#g(e){if(e.type===`progress`){this.#h({phase:e.phase,message:e.message}),this.#u&&e.id===this.#u.id&&!this.#u.settled&&this.#u.options.onProgress?.({phase:e.phase,message:e.message});return}let t=this.#u;if(t&&`id`in e&&e.id===t.id)switch(e.type){case`stdout`:t.stdout+=e.text,t.options.onStdout?.(e.text);break;case`echo`:t.options.onEcho?.(e.text);break;case`stdin-request`:this.#v(t,e.request);break;case`module-request`:this.#_(t,e.name);break;case`stderr`:t.stderr+=e.text,t.options.onStderr?.(e.text);break;case`result`:t.resolve({stdout:t.stdout,stderr:t.stderr||void 0,value:e.value,durationMs:Math.round(e.durationMs),failed:!1,...e.memory?{memory:e.memory}:{},...e.cases?{cases:e.cases,passed:e.passed,total:e.total}:{}}),t.markDone();break;case`error`:case`fatal`:{let r=(t.stderr&&!t.stderr.endsWith(`
7
+ `)?`
8
+ `:``)+e.message+`
9
+ `;t.stderr+=r,t.options.onStderr?.(r);let i={stdout:t.stdout,stderr:t.stderr,hint:`hint`in e?e.hint:void 0,durationMs:Math.round(`durationMs`in e?e.durationMs:0),failed:!0,...`cases`in e&&e.cases?{cases:e.cases,passed:0,total:e.cases.length}:{}};`hintAbout`in e&&e.hintAbout===`stdin`&&n.add(i),t.resolve(i),t.markDone();break}}}#_(e,t){let n=this.#e,r=r=>{this.#e===n&&this.#u===e&&n?.postMessage({type:`module`,name:t,...r})};this.loadModule(t).then(e=>r({code:e}),e=>r({error:e instanceof Error?e.message:String(e)}))}#v(e,t){let n=this.#e,r=r=>{this.#e===n&&this.#u===e&&n?.postMessage({type:`stdin-response`,request:t,text:r})},i=e.options.onStdinRequest;i?i().then(r,()=>r(null)):r(null)}#y(e,t){e.reject(t),e.markDone()}async#b(){if(!this.#d){this.#d=!0;try{for(;this.#l.length;){let e=this.#l.shift();this.#u=e;try{if(await this.load(),e.settled)continue;e.started=!0,e.options.onStart?.(),e.options.timeoutMs&&Number.isFinite(e.options.timeoutMs)&&e.options.timeoutMs>0&&(e.timer=setTimeout(()=>{this.#u!==e||e.settled||(this.#g({type:`error`,id:e.id,message:`Run exceeded its wall-clock time limit.`,durationMs:e.options.timeoutMs}),this.#m())},e.options.timeoutMs)),this.#e.postMessage({type:`run`,id:e.id,code:e.code,stdin:e.options.stdin,files:e.options.files,entry:e.options.entry,...e.options.compilerLanguage?{compilerLanguage:e.options.compilerLanguage}:{},...e.options.practice?{practice:e.options.practice}:{}}),await e.done}catch(t){this.#y(e,t)}finally{this.#u=null}}}finally{this.#d=!1}}}};export{i as t};
@@ -1,4 +1,4 @@
1
- import{d as e,l as t,u as n}from"./element-CQGYVEF7.js";var r=1,i=class{#e=null;#t=null;#n=`module`;#r=null;#i=null;#a=!1;#o=!1;#s=``;#c=/* @__PURE__ */ new Set;#l=[];#u=null;#d=!1;initPayload(){return{}}loadModule(e){return Promise.reject(/* @__PURE__ */ Error(`no module named ${e}`))}get ready(){return this.#a}get interactiveStdin(){return this.#o}get version(){return this.#s}load(t){t&&this.#c.add(t);let n=()=>{t&&this.#c.delete(t)};if(!this.#r){let t=new Promise((t,n)=>{this.#i={resolve:t,reject:n};let r;try{if(typeof Worker>`u`)throw Error(`Worker constructor missing`);let e=new Blob([this.source],{type:`text/javascript`});this.#t=URL.createObjectURL(e),r=new Worker(this.#t,{type:this.#n})}catch(t){this.#i=null,n(new e(`Could not start a Web Worker: ${t.message}`));return}this.#e=r,r.onmessage=e=>{let r=e.data;r.type===`ready`?(this.#s=r.version,this.#o=r.interactiveStdin===!0,this.#a=!0,this.#i=null,this.#h({phase:`ready`,message:`${this.label} ready`}),t()):r.type===`fatal`&&!this.#a?this.#p(r.message,t,n):this.#g(r)},r.onerror=e=>{let r=e.message||`Worker failed to start`;this.#a?this.#u&&this.#y(this.#u,Error(r)):this.#p(r,t,n)},r.postMessage({type:`init`,...this.initPayload()})});this.#r=t,t.catch(()=>{this.#r===t&&(this.#r=null)})}return this.#r.then(n,e=>{throw n(),e})}run(e,t={}){let n,i,a=new Promise((e,t)=>{n=e,i=t}),o,s=new Promise(e=>{o=e}),c={id:r++,code:e,options:t,stdout:``,stderr:``,resolve:n,reject:i,promise:a,started:!1,settled:!1,done:s,markDone:()=>{clearTimeout(c.timer),c.settled=!0,o()}};return this.#l.push(c),this.#b(),a}stop(e){if(e){let t=this.#l.findIndex(t=>t.promise===e);if(t!==-1){this.#y(this.#l.splice(t,1)[0],new n);return}let r=this.#u;if(!r||r.promise!==e||r.settled)return;if(!r.started){this.#y(r,new n);return}}this.#f()}#f(){let e=this.#e!==null,t=this.#i;if(this.#m(),this.#u&&this.#y(this.#u,new n),e){let e=this.load();t&&e.then(t.resolve,t.reject),e.catch(()=>{})}}#p(e,t,n){this.#m(),this.#n===`module`?(this.#n=`classic`,this.load().then(t,n)):n(Error(e))}#m(){this.#e?.terminate(),this.#e=null,this.#t&&=(URL.revokeObjectURL(this.#t),null),this.#r=null,this.#i=null,this.#a=!1}#h(e){for(let t of this.#c)t(e)}#g(e){if(e.type===`progress`){this.#h({phase:e.phase,message:e.message}),this.#u&&e.id===this.#u.id&&!this.#u.settled&&this.#u.options.onProgress?.({phase:e.phase,message:e.message});return}let n=this.#u;if(n&&`id`in e&&e.id===n.id)switch(e.type){case`stdout`:n.stdout+=e.text,n.options.onStdout?.(e.text);break;case`echo`:n.options.onEcho?.(e.text);break;case`stdin-request`:this.#v(n,e.request);break;case`module-request`:this.#_(n,e.name);break;case`stderr`:n.stderr+=e.text,n.options.onStderr?.(e.text);break;case`result`:n.resolve({stdout:n.stdout,stderr:n.stderr||void 0,value:e.value,durationMs:Math.round(e.durationMs),failed:!1,...e.memory?{memory:e.memory}:{},...e.cases?{cases:e.cases,passed:e.passed,total:e.total}:{}}),n.markDone();break;case`error`:case`fatal`:{let r=(n.stderr&&!n.stderr.endsWith(`
1
+ import{d as e,l as t,u as n}from"./element-COcjM0hI.js";var r=1,i=class{#e=null;#t=null;#n=`module`;#r=null;#i=null;#a=!1;#o=!1;#s=``;#c=/* @__PURE__ */ new Set;#l=[];#u=null;#d=!1;initPayload(){return{}}loadModule(e){return Promise.reject(/* @__PURE__ */ Error(`no module named ${e}`))}get ready(){return this.#a}get interactiveStdin(){return this.#o}get version(){return this.#s}load(t){t&&this.#c.add(t);let n=()=>{t&&this.#c.delete(t)};if(!this.#r){let t=new Promise((t,n)=>{this.#i={resolve:t,reject:n};let r;try{if(typeof Worker>`u`)throw Error(`Worker constructor missing`);let e=new Blob([this.source],{type:`text/javascript`});this.#t=URL.createObjectURL(e),r=new Worker(this.#t,{type:this.#n})}catch(t){this.#i=null,n(new e(`Could not start a Web Worker: ${t.message}`));return}this.#e=r,r.onmessage=e=>{let r=e.data;r.type===`ready`?(this.#s=r.version,this.#o=r.interactiveStdin===!0,this.#a=!0,this.#i=null,this.#h({phase:`ready`,message:`${this.label} ready`}),t()):r.type===`fatal`&&!this.#a?this.#p(r.message,t,n):this.#g(r)},r.onerror=e=>{let r=e.message||`Worker failed to start`;this.#a?this.#u&&this.#y(this.#u,Error(r)):this.#p(r,t,n)},r.postMessage({type:`init`,...this.initPayload()})});this.#r=t,t.catch(()=>{this.#r===t&&(this.#r=null)})}return this.#r.then(n,e=>{throw n(),e})}run(e,t={}){let n,i,a=new Promise((e,t)=>{n=e,i=t}),o,s=new Promise(e=>{o=e}),c={id:r++,code:e,options:t,stdout:``,stderr:``,resolve:n,reject:i,promise:a,started:!1,settled:!1,done:s,markDone:()=>{clearTimeout(c.timer),c.settled=!0,o()}};return this.#l.push(c),this.#b(),a}stop(e){if(e){let t=this.#l.findIndex(t=>t.promise===e);if(t!==-1){this.#y(this.#l.splice(t,1)[0],new n);return}let r=this.#u;if(!r||r.promise!==e||r.settled)return;if(!r.started){this.#y(r,new n);return}}this.#f()}#f(){let e=this.#e!==null,t=this.#i;if(this.#m(),this.#u&&this.#y(this.#u,new n),e){let e=this.load();t&&e.then(t.resolve,t.reject),e.catch(()=>{})}}#p(e,t,n){this.#m(),this.#n===`module`?(this.#n=`classic`,this.load().then(t,n)):n(Error(e))}#m(){this.#e?.terminate(),this.#e=null,this.#t&&=(URL.revokeObjectURL(this.#t),null),this.#r=null,this.#i=null,this.#a=!1}#h(e){for(let t of this.#c)t(e)}#g(e){if(e.type===`progress`){this.#h({phase:e.phase,message:e.message}),this.#u&&e.id===this.#u.id&&!this.#u.settled&&this.#u.options.onProgress?.({phase:e.phase,message:e.message});return}let n=this.#u;if(n&&`id`in e&&e.id===n.id)switch(e.type){case`stdout`:n.stdout+=e.text,n.options.onStdout?.(e.text);break;case`echo`:n.options.onEcho?.(e.text);break;case`stdin-request`:this.#v(n,e.request);break;case`module-request`:this.#_(n,e.name);break;case`stderr`:n.stderr+=e.text,n.options.onStderr?.(e.text);break;case`result`:n.resolve({stdout:n.stdout,stderr:n.stderr||void 0,value:e.value,durationMs:Math.round(e.durationMs),failed:!1,...e.memory?{memory:e.memory}:{},...e.cases?{cases:e.cases,passed:e.passed,total:e.total}:{}}),n.markDone();break;case`error`:case`fatal`:{let r=(n.stderr&&!n.stderr.endsWith(`
2
2
  `)?`
3
3
  `:``)+e.message+`
4
4
  `;n.stderr+=r,n.options.onStderr?.(r);let i={stdout:n.stdout,stderr:n.stderr,hint:`hint`in e?e.hint:void 0,durationMs:Math.round(`durationMs`in e?e.durationMs:0),failed:!0,...`cases`in e&&e.cases?{cases:e.cases,passed:0,total:e.cases.length}:{}};`hintAbout`in e&&e.hintAbout===`stdin`&&t.add(i),n.resolve(i),n.markDone();break}}}#_(e,t){let n=this.#e,r=r=>{this.#e===n&&this.#u===e&&n?.postMessage({type:`module`,name:t,...r})};this.loadModule(t).then(e=>r({code:e}),e=>r({error:e instanceof Error?e.message:String(e)}))}#v(e,t){let n=this.#e,r=r=>{this.#e===n&&this.#u===e&&n?.postMessage({type:`stdin-response`,request:t,text:r})},i=e.options.onStdinRequest;i?i().then(r,()=>r(null)):r(null)}#y(e,t){e.reject(t),e.markDone()}async#b(){if(!this.#d){this.#d=!0;try{for(;this.#l.length;){let e=this.#l.shift();this.#u=e;try{if(await this.load(),e.settled)continue;e.started=!0,e.options.onStart?.(),e.options.timeoutMs&&Number.isFinite(e.options.timeoutMs)&&e.options.timeoutMs>0&&(e.timer=setTimeout(()=>{this.#u!==e||e.settled||(this.#g({type:`error`,id:e.id,message:`Run exceeded its wall-clock time limit.`,durationMs:e.options.timeoutMs}),this.#m())},e.options.timeoutMs)),this.#e.postMessage({type:`run`,id:e.id,code:e.code,stdin:e.options.stdin,files:e.options.files,entry:e.options.entry,...e.options.compilerLanguage?{compilerLanguage:e.options.compilerLanguage}:{},...e.options.practice?{practice:e.options.practice}:{}}),await e.done}catch(t){this.#y(e,t)}finally{this.#u=null}}}finally{this.#d=!1}}}};export{i as t};