learningspaces / app.py
tiahchia's picture
Update app.py
1df8851 verified
import gradio as gr
import html
import io
from contextlib import redirect_stdout
# --- Python runner ---
def run_python(code):
f = io.StringIO()
try:
with redirect_stdout(f):
exec(code, {}, {})
except Exception as e:
f.write(str(e))
output = f.getvalue()
return f'<pre style="color:#00ff00; font-family: monospace;">{html.escape(output)}</pre>'
# --- Web runner (working sandbox-safe version) ---
def run_web(code):
# Wrap HTML fragment in full document if needed
if "<html" in code.lower() or "<!doctype" in code.lower():
html_content = code
else:
html_content = f"""
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<style>
body {{
font-family: monospace;
background: #1e1e1e;
color: #00ff00;
padding: 20px;
}}
a {{
color: #00ffff;
}}
img {{
border-radius: 8px;
margin-top: 10px;
}}
button {{
background-color: #00ff00;
color: #1e1e1e;
border: none;
border-radius: 4px;
padding: 6px 12px;
cursor: pointer;
margin-top: 10px;
}}
button:hover {{
background-color: #00cc00;
}}
</style>
</head>
<body>
{code}
</body>
</html>
"""
# Escape quotes for safe embedding
safe_html = html_content.replace('"', "&quot;").replace("'", "&apos;")
# Allow interactive content inside iframe safely
return f"""
<iframe
style="width:100%; height:400px; border:none; border-radius:8px; background:#1e1e1e;"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
srcdoc="{safe_html}">
</iframe>
"""
# --- JavaScript runner ---
def run_js(code):
return f'<iframe style="width:100%; height:100%; border:none; border-radius:8px; background:#1e1e1e;" srcdoc="<script>{html.escape(code)}</script>"></iframe>'
# --- Bash runner (simulated) ---
def run_bash(code):
return f'<pre style="color:#00ff00; font-family: monospace;">$ {html.escape(code)}\nCommand simulated.</pre>'
# --- Main runner ---
def run_code(code, lang):
if lang == "Python":
return run_python(code)
elif lang == "JavaScript":
return run_js(code)
elif lang == "Bash":
return run_bash(code)
else:
return run_web(code)
# --- Starter templates ---
starter_python = """# Python example
print("Hello World!")
for i in range(5):
print(f"Line {i+1}")"""
starter_web = """<h1 style="background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);
-webkit-background-clip: text; color: transparent;">
Hello, Rainbow World!
</h1>"""
starter_js = """// JavaScript example
console.log("Hello JavaScript!");
for(let i=0;i<5;i++){
console.log("Line "+(i+1));
}"""
starter_bash = """# Bash example
echo "Hello Bash!"
for i in {1..5}; do
echo "Line $i"
done"""
# --- Gradio app ---
with gr.Blocks(css="""
body {
margin:0; padding:0;
font-family:'Poppins', sans-serif;
overflow-x:hidden;
color:#e0e0e0;
background: linear-gradient(to bottom, #0a0a23, #1a0a3a, #00001a);
}
.gradio-container { max-width:1200px; margin:auto; padding:20px; }
.gr-column { display:flex; flex-direction: column; gap:8px !important; }
#editor-container, #output-panel {
width:100% !important;
margin:0 !important;
padding:8px !important;
border-radius:8px;
box-sizing:border-box;
}
#output-panel {
height:150px !important;
background:#1e1e1e;
color:#00ff00;
overflow:auto;
box-shadow:0 4px 8px rgba(0,0,0,0.5);
font-family: monospace;
}
#editor-container .CodeMirror {
height:300px !important;
min-height:300px !important;
font-family: monospace;
font-size:14px;
white-space: pre-wrap;
overflow-wrap: break-word;
border-radius:8px;
padding:8px !important;
}
.gr-radio { color:#e0e0e0; margin:0 0 8px 0 !important; font-size:0.95em; }
button, .gr-button { background-color:#F714C5 !important; color:#fff !important; border-radius:6px !important; padding:8px 16px !important; }
footer { display:none !important; }
header { background:#000000; padding:16px; color:#F714C5; font-size:1.4em; text-align:center; margin-top:20px; }
header img { vertical-align:middle; height:20px; margin-right:8px; }
canvas#particles { position:fixed; top:0; left:0; width:100%; height:100%; z-index:0; pointer-events:none; }
""") as demo:
# --- Particle background ---
gr.HTML("""<canvas id="particles"></canvas>
<script>
const canvas = document.getElementById('particles');
const ctx = canvas.getContext('2d');
let stars = [];
function resize(){ canvas.width = window.innerWidth; canvas.height = window.innerHeight; }
window.addEventListener('resize', resize); resize();
for(let i=0;i<150;i++){
stars.push({ x: Math.random()*canvas.width, y: Math.random()*canvas.height,
r: Math.random()*1.5, dx: (Math.random()-0.5)*0.3, dy: (Math.random()-0.5)*0.3 });
}
function animate(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(let s of stars){
ctx.beginPath(); ctx.arc(s.x,s.y,s.r,0,Math.PI*2); ctx.fillStyle='white'; ctx.fill();
s.x+=s.dx; s.y+=s.dy;
if(s.x<0) s.x=canvas.width; if(s.x>canvas.width) s.x=0;
if(s.y<0) s.y=canvas.height; if(s.y>canvas.height) s.y=0;
}
requestAnimationFrame(animate);
}
animate();
</script>""")
# --- Header ---
gr.Markdown("""
<h2 style="color:#F714C5; text-align:center; margin-bottom:10px;">
𝙸'πš– πšƒπš’πšŠπš‘ & πšπš‘πš’πšœ πš’πšœ πš–πš’ πšŒπš˜πš–πš™πš’πš•πšŽπš›, πš‘πšŠπš™πš™πš’ πšŒπš˜πšπš’πš—πš!
</h2>
""")
# --- Language selector ---
lang_selector = gr.Radio(
choices=["Python", "Web (HTML/CSS/JS)", "JavaScript", "Bash"],
value="Web (HTML/CSS/JS)",
label="Select Language"
)
# --- Output above input ---
with gr.Column():
output_frame = gr.HTML(label="Output", elem_id="output-panel")
code_input = gr.Code(
value=starter_web,
language="html",
label="Type your code here",
interactive=True,
lines=15
)
render_button = gr.Button("Render")
# --- Footer ---
gr.Markdown("""
<header>
<img src="https://simpleandstatic.com/favicon.ico" alt="Logo" />
πš‚πš’πš–πš™πš•πšŽ & πš‚πšπšŠπšπš’πšŒ
</header>
""")
# --- Update template on language change ---
def update_template(lang):
if lang == "Python":
return starter_python
elif lang == "JavaScript":
return starter_js
elif lang == "Bash":
return starter_bash
else:
return starter_web
lang_selector.change(update_template, inputs=lang_selector, outputs=code_input)
render_button.click(run_code, inputs=[code_input, lang_selector], outputs=output_frame)
demo.launch()