Spaces:
Running
Running
import gradio as gr | |
def update_ui(code): | |
try: | |
# Strip out scripts and handle them separately to avoid security issues | |
from bs4 import BeautifulSoup | |
soup = BeautifulSoup(code, 'html.parser') | |
scripts = soup.find_all('script') | |
for script in scripts: | |
script.decompose() # Remove script tags from HTML to prevent direct execution | |
# Rebuild HTML without scripts for direct rendering | |
html_content = str(soup) | |
# Collect script content | |
js_content = '\n'.join([script.string for script in scripts if script.string]) | |
# Return HTML wrapped in a div and scripts in a way that Gradio can handle | |
return f""" | |
<div style="border: 1px solid #ccc; padding: 10px; height: 400px; overflow: auto;"> | |
{html_content} | |
</div> | |
<script> | |
{js_content} | |
</script> | |
""", None | |
except Exception as e: | |
return "", str(e) | |
def interface(): | |
with gr.Blocks() as demo: | |
gr.Markdown("# Learn Frontend UI") | |
with gr.Row(): | |
code_input = gr.Code(label="Write your HTML/CSS/JS here", language="html") | |
with gr.Column(): | |
ui_preview = gr.HTML(label="UI Preview") | |
error_output = gr.Textbox(label="Error", interactive=False) | |
code_input.change( | |
fn=update_ui, | |
inputs=code_input, | |
outputs=[ui_preview, error_output] | |
) | |
# Example codes remain the same, but ensure the snake game is full HTML | |
with gr.Accordion("HTML/CSS/JS Code Examples", open=False): | |
with gr.Column(): | |
example_buttons = [] | |
example_codes = [ | |
# ... (other examples remain unchanged) | |
(""" | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<style> | |
body { margin: 0; padding: 0; } | |
#gameCanvas { border: 1px solid black; } | |
</style> | |
</head> | |
<body> | |
<canvas id="gameCanvas" width="400" height="400"></canvas> | |
<script> | |
let canvas = document.getElementById('gameCanvas'); | |
let ctx = canvas.getContext('2d'); | |
let snake = [{x: 10, y: 10}]; | |
let food = {x: 15, y: 15}; | |
let gameLoop; | |
function init() { | |
gameLoop = setInterval(game, 100); | |
} | |
function game() { | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
snake.unshift({x: snake[0].x, y: snake[0].y}); | |
snake[0].x += 1; // Simple movement for demonstration | |
if(snake[0].x > 39) snake[0].x = 0; // Wrap around | |
ctx.fillStyle = "green"; | |
snake.forEach(part => { | |
ctx.fillRect(part.x * 10, part.y * 10, 10, 10); | |
}); | |
ctx.fillStyle = "red"; | |
ctx.fillRect(food.x * 10, food.y * 10, 10, 10); | |
if(snake[0].x == food.x && snake[0].y == food.y) { | |
food.x = Math.floor(Math.random() * 40); | |
food.y = Math.floor(Math.random() * 40); | |
} else { | |
snake.pop(); | |
} | |
} | |
// Start the game | |
init(); | |
</script> | |
</body> | |
</html> | |
""", "Snake Game"), | |
] | |
for code, label in example_codes: | |
button = gr.Button(label) | |
example_buttons.append(button) | |
button.click(fn=lambda x=code: x, outputs=code_input) | |
return demo | |
if __name__ == "__main__": | |
demo = interface() | |
demo.launch() |