Skip to content

Commit ac5923c

Browse files
Fix page freeze - replace PyScript with Skulpt for faster performance
1 parent cb6acb9 commit ac5923c

2 files changed

Lines changed: 69 additions & 64 deletions

File tree

docs/editor.html

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
<title>Python Code Editor - Practice Questions</title>
77
<link rel="stylesheet" href="css/style.css">
88
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9-
<!-- PyScript for running Python in browser -->
10-
<link rel="stylesheet" href="https://pyscript.net/releases/2024.1.1/core.css">
11-
<script type="module" src="https://pyscript.net/releases/2024.1.1/core.js"></script>
9+
<!-- Skulpt for fast Python execution in browser -->
10+
<script src="https://cdn.jsdelivr.net/npm/skulpt@1.2.0/dist/skulpt.min.js" defer></script>
11+
<script src="https://cdn.jsdelivr.net/npm/skulpt@1.2.0/dist/skulpt-stdlib.js" defer></script>
1212
</head>
1313
<body>
1414
<nav class="navbar">
@@ -124,53 +124,60 @@ <h3><i class="fas fa-terminal"></i> Output</h3>
124124
</div>
125125
</div>
126126

127-
<!-- PyScript code execution -->
128-
<script type="py" config='{"packages": []}' id="python-runner" style="display: none;">
129-
from js import document, console
130-
import sys
131-
from io import StringIO
132-
import traceback
133-
134-
def run_user_code():
135-
output_div = document.getElementById("output")
136-
loading_div = document.getElementById("loading")
137-
138-
# Get code from editor
139-
code = document.getElementById("code-editor").value
140-
141-
# Show loading
142-
loading_div.style.display = "block"
143-
output_div.innerHTML = ""
144-
145-
# Capture stdout
146-
old_stdout = sys.stdout
147-
sys.stdout = StringIO()
148-
149-
try:
150-
# Execute the code
151-
exec(code, {})
127+
<!-- Skulpt Python execution helper -->
128+
<script>
129+
// Skulpt output handler
130+
function outf(text) {
131+
const output = document.getElementById('output');
132+
const existingPre = output.querySelector('pre.output-success');
133+
if (existingPre) {
134+
existingPre.textContent += text;
135+
} else {
136+
output.innerHTML = '<pre class="output-success">' + text + '</pre>';
137+
}
138+
}
152139

153-
# Get output
154-
output = sys.stdout.getvalue()
140+
function builtinRead(x) {
141+
if (Sk.builtinFiles === undefined || Sk.builtinFiles["files"][x] === undefined)
142+
throw "File not found: '" + x + "'";
143+
return Sk.builtinFiles["files"][x];
144+
}
155145

156-
# Display output
157-
if output:
158-
output_div.innerHTML = f'<pre class="output-success">{output}</pre>'
159-
else:
160-
output_div.innerHTML = '<div class="output-info">Code executed successfully (no output)</div>'
146+
// Run Python code using Skulpt
147+
window.runPythonCode = function(code) {
148+
const output = document.getElementById('output');
149+
const loading = document.getElementById('loading');
161150

162-
except Exception as e:
163-
# Display error with traceback
164-
error_msg = traceback.format_exc()
165-
output_div.innerHTML = f'<pre class="output-error"><strong>Error:</strong>\n{error_msg}</pre>'
166-
167-
finally:
168-
# Restore stdout
169-
sys.stdout = old_stdout
170-
loading_div.style.display = "none"
171-
172-
# Make function available globally
173-
window.run_user_code = run_user_code
151+
// Show loading
152+
loading.style.display = 'block';
153+
output.innerHTML = '';
154+
155+
// Configure Skulpt
156+
Sk.configure({
157+
output: outf,
158+
read: builtinRead,
159+
__future__: Sk.python3
160+
});
161+
162+
// Run the code
163+
Sk.misceval.asyncToPromise(function() {
164+
return Sk.importMainWithBody("<stdin>", false, code, true);
165+
}).then(
166+
function(mod) {
167+
// Success
168+
loading.style.display = 'none';
169+
const outputContent = output.querySelector('pre');
170+
if (!outputContent || !outputContent.textContent.trim()) {
171+
output.innerHTML = '<div class="output-info">Code executed successfully (no output)</div>';
172+
}
173+
},
174+
function(err) {
175+
// Error
176+
loading.style.display = 'none';
177+
output.innerHTML = '<pre class="output-error"><strong>Error:</strong>\n' + err.toString() + '</pre>';
178+
}
179+
);
180+
};
174181
</script>
175182

176183
<script src="js/progress.js"></script>

docs/js/editor.js

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,22 @@ document.addEventListener('DOMContentLoaded', function() {
2929
});
3030

3131
function runCode() {
32-
// Check if PyScript is loaded
33-
if (typeof window.run_user_code === 'function') {
34-
// Call PyScript function
35-
window.run_user_code();
36-
} else if (typeof pyscript !== 'undefined') {
37-
// PyScript is available, try to run
38-
try {
39-
pyscript.run_user_code();
40-
} catch (e) {
41-
// Fallback: show that PyScript is loading
42-
document.getElementById('output').innerHTML =
43-
'<div class="output-info">⏳ PyScript is still loading... Please wait a moment and try again.</div>';
44-
}
45-
} else {
46-
// PyScript not loaded yet
47-
document.getElementById('output').innerHTML =
48-
'<div class="output-info">⏳ Python runtime is loading... This may take a few seconds on first visit. Please wait and try again.</div>';
32+
const code = document.getElementById('code-editor').value.trim();
33+
const outputDiv = document.getElementById('output');
34+
35+
if (!code) {
36+
outputDiv.innerHTML = '<div class="output-info">Please write some code first</div>';
37+
return;
4938
}
39+
40+
// Check if Skulpt is loaded
41+
if (typeof Sk === 'undefined') {
42+
outputDiv.innerHTML = '<div class="output-info">⏳ Python runtime is loading... Please wait a moment and try again.</div>';
43+
return;
44+
}
45+
46+
// Run Python code using Skulpt
47+
window.runPythonCode(code);
5048
}
5149

5250
function clearCode() {

0 commit comments

Comments
 (0)