File size: 4,220 Bytes
f56a29b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | # Code Playground Widget Generator
Generate a self-contained HTML code editor with execution and test validation.
## Supported Languages
- Python (via Pyodide CDN)
- JavaScript (native browser execution)
- TypeScript (via Babel CDN transpilation)
## Widget Config Schema
```json
{
"type": "code",
"language": "python",
"description": "...",
"starterCode": "def solution(x):\n # Your code here\n pass",
"testCases": [
{ "id": "t1", "input": "5", "expected": "25", "description": "Square the input" }
],
"hints": ["Think about multiplication", "What is x * x?"],
"solution": "def solution(x):\n return x * x",
"teacherActions": [
{ "id": "act1", "type": "speech", "content": "Try implementing the solution" }
]
}
```
## Python Execution Requirements (CRITICAL)
When generating Python widgets using Pyodide, follow these **mandatory patterns**:
### 1. Proper Stdout Capture Setup
**ALWAYS use this exact pattern for stdout capture:**
```javascript
// CORRECT - imports both sys AND io
await pyodide.runPythonAsync(`
import sys
import io
sys.stdout = io.StringIO()
`);
```
**NEVER do this (causes NameError):**
```javascript
// WRONG - missing import io
pyodide.runPython('import sys; sys.stdout = io.StringIO()');
```
### 2. Use Async Execution
- Always use `pyodide.runPythonAsync()` instead of `pyodide.runPython()`
- Async execution is more reliable and handles module loading correctly
- All Pyodide operations should be wrapped in async functions
### 3. Load Required Packages Before Execution
If user code needs packages like numpy, load them during initialization:
```javascript
await pyodide.loadPackage(['numpy']);
```
### 4. Wait for Pyodide Initialization
- Disable the run button until Pyodide is fully loaded
- Show loading status to users
- Check `pyodide !== null` before running code
### 5. Retrieve Output Correctly
```javascript
const output = pyodide.runPython('sys.stdout.getvalue()');
```
## Complete Python Widget Runtime Pattern
```javascript
let pyodide = null;
async function initPyodide() {
pyodide = await loadPyodide();
// Load any packages user code might need
await pyodide.loadPackage(['numpy']);
document.getElementById('run-btn').disabled = false;
document.getElementById('status').textContent = 'Python ready';
}
initPyodide();
async function runCode() {
if (!pyodide) {
alert('Python environment not ready');
return;
}
const code = editor.getValue();
try {
// MUST import sys AND io before using StringIO
await pyodide.runPythonAsync(`
import sys
import io
sys.stdout = io.StringIO()
`);
await pyodide.runPythonAsync(code);
const output = pyodide.runPython('sys.stdout.getvalue()');
document.getElementById('output').textContent = output;
} catch (e) {
document.getElementById('output').textContent = `Error: ${e.message}`;
}
}
```
## Technical Requirements
- Use CodeMirror or Monaco via CDN for editing
- Syntax highlighting for the language
- Run button with output display
- Test case validation with pass/fail indicators
- Hint button that reveals hints progressively
- Mobile-responsive layout
## Layout Guidelines
- Code editor should be visible and not overlap with output panel
- On mobile, stack editor above output (not side-by-side)
- Ensure editor has minimum height of 200px on mobile
- Test cases should be collapsible on small screens
## Output Format
Return ONLY the HTML document, no markdown fences or explanations.
**CRITICAL: Output EXACTLY ONE HTML document.**
- Do NOT duplicate content
- Do NOT include multiple `<!DOCTYPE html>` tags
- The output must end with exactly one `</html>` tag
## Quality Checklist
- [ ] Code editor is visible and usable on mobile
- [ ] Run button works correctly
- [ ] Output panel doesn't overlap editor
- [ ] Test cases show pass/fail clearly
- [ ] Hints reveal progressively
- [ ] **NO DUPLICATED HTML** - exactly ONE `<!DOCTYPE html>` tag
- [ ] **Python stdout uses correct import pattern** - imports BOTH `sys` AND `io`
- [ ] **Pyodide uses async execution** - `runPythonAsync()` not `runPython()`
|