File size: 4,571 Bytes
9fd0d3c
 
3e2c114
 
0dea17b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3e2c114
0dea17b
 
 
 
 
 
3e2c114
 
 
 
 
 
 
 
 
 
9a770de
3e2c114
 
 
 
 
09b1f7a
3e2c114
 
0dea17b
3e2c114
 
 
 
9a770de
3e2c114
9a770de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3e2c114
9a770de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3e2c114
 
c94f5bc
3e2c114
 
 
 
3ab14b8
3e2c114
3ab14b8
3e2c114
 
 
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
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()