broadfield-dev commited on
Commit
17cccd0
·
verified ·
1 Parent(s): 20083c5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +153 -53
app.py CHANGED
@@ -1,78 +1,178 @@
1
  import gradio as gr
2
- import re
3
 
4
  def update_ui(code):
5
  try:
6
- # Extract HTML, CSS, and JavaScript using regex
7
- html_content = re.search(r'<html[^>]*>[\s\S]*?<\/html>', code, re.IGNORECASE)
8
- if html_content:
9
- html_content = html_content.group(0)
10
- else:
11
- html_content = code # If no <html> tag, assume all is HTML content
12
-
13
- # Extract CSS if present in a <style> tag
14
- css_content = re.search(r'<style[^>]*>[\s\S]*?<\/style>', code, re.IGNORECASE)
15
- css_string = ''
16
- if css_content:
17
- css_string = css_content.group(0)
18
-
19
- # Remove <style> tags for direct application
20
- css_only = re.sub(r'<style>|<\/style>', '', css_string) if css_string else ''
21
-
22
- # Extract JavaScript if present in a <script> tag
23
- js_content = re.search(r'<script[^>]*>[\s\S]*?<\/script>', code, re.IGNORECASE)
24
- js_string = ''
25
- if js_content:
26
- js_string = js_content.group(0)
27
-
28
- # Remove <script> tags for Gradio's js= parameter
29
- js_only = re.sub(r'<script>|<\/script>', '', js_string) if js_string else ''
30
-
31
- # Combine HTML with CSS for preview, but we'll handle JS separately
32
- ui_output = f"""
33
- <style>{css_only}</style>
34
- {html_content}
35
- """
36
- return ui_output, js_only, None
37
  except Exception as e:
38
- return "", "", str(e)
39
 
40
  def interface():
41
  with gr.Blocks() as demo:
42
  gr.Markdown("# Learn Frontend UI")
43
  with gr.Row():
44
- code_input = gr.Code(label="Write your HTML/CSS/JS here", lines=500, language="html")
45
  with gr.Column():
46
  ui_preview = gr.HTML(label="UI Preview")
47
  error_output = gr.Textbox(label="Error", interactive=False)
48
- # Hidden output to store JavaScript for _js execution
49
- js_output = gr.Textbox(visible=False)
50
 
51
- # Use _js to execute JavaScript in the browser context
52
  code_input.change(
53
- fn=update_ui,
54
- inputs=code_input,
55
- outputs=[ui_preview, js_output, error_output],
56
  js="""
57
- function(code, ui_output, js_code) {
58
- // Create a temporary div to parse the HTML
59
  const tempDiv = document.createElement('div');
60
- tempDiv.innerHTML = ui_output;
61
 
62
- // If there's JavaScript code, execute it
63
- if (js_code) {
64
- const script = document.createElement('script');
65
- script.textContent = js_code;
66
- document.body.appendChild(script);
67
- // Clean up script tag after execution to prevent duplicates
68
- setTimeout(() => script.remove(), 0);
69
- }
70
 
71
- // Return the HTML content for Gradio to display
72
- return tempDiv.innerHTML;
 
 
 
 
73
  }
74
  """
75
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  return demo
77
 
78
  if __name__ == "__main__":
 
1
  import gradio as gr
 
2
 
3
  def update_ui(code):
4
  try:
5
+ # For the preview, we'll return the code as-is to be rendered in an iframe-like manner
6
+ # Gradio's HTML component can render HTML/CSS directly, but JS needs special handling
7
+ return f"""
8
+ <div style="border: 1px solid #ccc; padding: 10px; height: 400px; overflow: auto;">
9
+ {code}
10
+ </div>
11
+ """, None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  except Exception as e:
13
+ return "", str(e)
14
 
15
  def interface():
16
  with gr.Blocks() as demo:
17
  gr.Markdown("# Learn Frontend UI")
18
  with gr.Row():
19
+ code_input = gr.Code(label="Write your HTML/CSS/JS here", language="html")
20
  with gr.Column():
21
  ui_preview = gr.HTML(label="UI Preview")
22
  error_output = gr.Textbox(label="Error", interactive=False)
 
 
23
 
24
+ # JavaScript execution needs to be handled client-side, so we use _js to inject it
25
  code_input.change(
26
+ fn=update_ui,
27
+ inputs=code_input,
28
+ outputs=[ui_preview, error_output],
29
  js="""
30
+ function(code) {
31
+ // Create a temporary div to parse the HTML/CSS/JS
32
  const tempDiv = document.createElement('div');
33
+ tempDiv.innerHTML = code;
34
 
35
+ // Handle JavaScript by creating new script elements
36
+ const scripts = tempDiv.querySelectorAll('script');
37
+ scripts.forEach(script => {
38
+ const newScript = document.createElement('script');
39
+ newScript.textContent = script.textContent;
40
+ document.body.appendChild(newScript);
41
+ script.remove(); // Remove original script to avoid double execution
42
+ });
43
 
44
+ // Wrap the content in a styled div for better presentation
45
+ return `
46
+ <div style="border: 1px solid #ccc; padding: 10px; height: 400px; overflow: auto;">
47
+ ${tempDiv.innerHTML}
48
+ </div>
49
+ `;
50
  }
51
  """
52
  )
53
+
54
+ # Add example section
55
+ with gr.Accordion("HTML/CSS/JS Code Examples", open=False):
56
+ with gr.Column():
57
+ example_buttons = []
58
+ example_codes = [
59
+ ('<h1>Hello World</h1>', "Basic Heading"),
60
+ ('<p style="color: red;">This is a paragraph.</p>', "Styled Paragraph"),
61
+ ('<button onclick="alert(\'Button clicked!\')">Click me</button>', "Interactive Button"),
62
+ ("""
63
+ <style>
64
+ .box {
65
+ width: 100px;
66
+ height: 100px;
67
+ background-color: blue;
68
+ }
69
+ </style>
70
+ <div class="box"></div>
71
+ """, "CSS Box"),
72
+ ("""
73
+ <style>
74
+ .container {
75
+ display: flex;
76
+ justify-content: space-between;
77
+ }
78
+ </style>
79
+ <div class="container">
80
+ <div style="background-color: red; width: 50px; height: 50px;"></div>
81
+ <div style="background-color: green; width: 50px; height: 50px;"></div>
82
+ </div>
83
+ """, "Flexbox Layout"),
84
+ ("""
85
+ <!DOCTYPE html>
86
+ <html lang="en">
87
+ <head>
88
+ <meta charset="UTF-8">
89
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
90
+ <title>Snake Game</title>
91
+ <style>
92
+ body {
93
+ display: flex;
94
+ justify-content: center;
95
+ align-items: center;
96
+ height: 100vh;
97
+ background-color: #000;
98
+ margin: 0;
99
+ }
100
+ #gameCanvas {
101
+ border: 1px solid #fff;
102
+ }
103
+ </style>
104
+ </head>
105
+ <body>
106
+ <canvas id="gameCanvas" width="400" height="400"></canvas>
107
+ <script>
108
+ const canvas = document.getElementById('gameCanvas');
109
+ const ctx = canvas.getContext('2d');
110
+ const grid = 20;
111
+ let count = 0;
112
+ let snake = {
113
+ x: grid * 5,
114
+ y: grid * 5,
115
+ dx: grid,
116
+ dy: 0,
117
+ cells: [],
118
+ maxCells: 4
119
+ };
120
+ let apple = {x: 0, y: 0};
121
+ let score = 0;
122
+
123
+ function gameLoop() {
124
+ requestAnimationFrame(gameLoop);
125
+ if (++count < 4) return;
126
+ count = 0;
127
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
128
+ snake.x += snake.dx;
129
+ snake.y += snake.dy;
130
+ if (snake.x < 0) snake.x = canvas.width - grid;
131
+ else if (snake.x >= canvas.width) snake.x = 0;
132
+ if (snake.y < 0) snake.y = canvas.height - grid;
133
+ else if (snake.y >= canvas.height) snake.y = 0;
134
+ snake.cells.unshift({x: snake.x, y: snake.y});
135
+ if (snake.cells.length > snake.maxCells) snake.cells.pop();
136
+ ctx.fillStyle = 'red';
137
+ ctx.fillRect(apple.x, apple.y, grid - 1, grid - 1);
138
+ ctx.fillStyle = 'green';
139
+ snake.cells.forEach(function(cell, index) {
140
+ ctx.fillRect(cell.x, cell.y, grid - 1, grid - 1);
141
+ if (index !== 0 && cell.x === snake.x && cell.y === snake.y) {
142
+ snake.maxCells = 4;
143
+ score = 0;
144
+ }
145
+ });
146
+ if (snake.x === apple.x && snake.y === apple.y) {
147
+ snake.maxCells++;
148
+ score++;
149
+ apple.x = Math.floor(Math.random() * 20) * grid;
150
+ apple.y = Math.floor(Math.random() * 20) * grid;
151
+ }
152
+ ctx.fillStyle = 'white';
153
+ ctx.font = '20px Arial';
154
+ ctx.fillText('Score: ' + score, 10, 20);
155
+ }
156
+ document.addEventListener('keydown', function(e) {
157
+ if (e.which === 37 && snake.dx === 0) { snake.dx = -grid; snake.dy = 0; }
158
+ else if (e.which === 38 && snake.dy === 0) { snake.dx = 0; snake.dy = -grid; }
159
+ else if (e.which === 39 && snake.dx === 0) { snake.dx = grid; snake.dy = 0; }
160
+ else if (e.which === 40 && snake.dy === 0) { snake.dx = 0; snake.dy = grid; }
161
+ });
162
+ apple.x = Math.floor(Math.random() * 20) * grid;
163
+ apple.y = Math.floor(Math.random() * 20) * grid;
164
+ requestAnimationFrame(gameLoop);
165
+ </script>
166
+ </body>
167
+ </html>
168
+ """, "Snake Game"),
169
+ ]
170
+
171
+ for code, label in example_codes:
172
+ button = gr.Button(label)
173
+ example_buttons.append(button)
174
+ button.click(fn=lambda x=code: x, outputs=code_input)
175
+
176
  return demo
177
 
178
  if __name__ == "__main__":