tomo2chin2 commited on
Commit
b688ee9
·
verified ·
1 Parent(s): 1119dd0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -247
app.py CHANGED
@@ -1,268 +1,84 @@
1
  import gradio as gr
2
- import re
3
- import html
4
- from bs4 import BeautifulSoup
5
 
6
- def sanitize_html(html_code):
7
- """Sanitize HTML input for security and formatting"""
8
- # Basic sanitization
9
- try:
10
- soup = BeautifulSoup(html_code, 'html.parser')
11
-
12
- # Remove potentially dangerous tags
13
- for script in soup(["script", "iframe", "object", "embed"]):
14
- script.decompose()
15
-
16
- # Get sanitized HTML
17
- sanitized = str(soup)
18
- except:
19
- # Fallback if BeautifulSoup fails
20
- sanitized = html.escape(html_code)
21
- sanitized = f"<pre>{sanitized}</pre>"
22
-
23
- # Create full HTML document with styling to prevent horizontal scroll
24
  return f"""
25
- <!DOCTYPE html>
26
- <html>
27
- <head>
28
- <meta charset="UTF-8">
29
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
30
- <style>
31
- body {{
32
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
33
- margin: 0;
34
- padding: 20px;
35
- background-color: #f8fafc;
36
- color: #334155;
37
- line-height: 1.6;
38
- overflow-x: hidden;
39
- max-width: 100%;
40
- }}
41
-
42
- * {{
43
- max-width: 100%;
44
- box-sizing: border-box;
45
- }}
46
-
47
- img, video, table, pre, div {{
48
- max-width: 100% !important;
49
- height: auto !important;
50
- overflow-x: hidden !important;
51
- }}
52
-
53
- table {{
54
- border-collapse: collapse;
55
- margin: 10px 0;
56
- }}
57
-
58
- pre {{
59
- white-space: pre-wrap;
60
- background-color: #f1f5f9;
61
- padding: 10px;
62
- border-radius: 5px;
63
- overflow-x: hidden;
64
- }}
65
- </style>
66
- </head>
67
- <body>
68
- {sanitized}
69
- </body>
70
- </html>
71
  """
72
 
73
- def update_iframe(html_code):
74
- """Process HTML input for the iframe"""
75
- if not html_code.strip():
76
- return """
77
- <!DOCTYPE html>
78
- <html>
79
- <head>
80
- <style>
81
- body {
82
- display: flex;
83
- justify-content: center;
84
- align-items: center;
85
- height: 100vh;
86
- margin: 0;
87
- font-family: 'Inter', sans-serif;
88
- color: #94a3b8;
89
- text-align: center;
90
- background-color: #f8fafc;
91
- }
92
- </style>
93
- </head>
94
- <body>
95
- <div>Enter HTML code for preview</div>
96
- </body>
97
- </html>
98
- """
99
- return sanitize_html(html_code)
100
-
101
- # Create elegant theme inspired by Intercontinental Hotel Ishigaki
102
- theme = gr.themes.Soft(
103
- primary_hue="indigo",
104
  secondary_hue="blue",
105
  neutral_hue="slate",
106
- font=gr.themes.GoogleFont("Inter"),
107
- font_mono=gr.themes.GoogleFont("IBM Plex Mono"),
108
- ).set(
109
- button_primary_background_fill="*primary_500",
110
- button_primary_background_fill_hover="*primary_600",
111
- button_primary_text_color="white",
112
- button_secondary_background_fill="white",
113
- button_secondary_background_fill_hover="*neutral_100",
114
- button_secondary_text_color="*neutral_800",
115
- block_title_text_color="*primary_700",
116
- block_label_text_color="*neutral_600",
117
- background_fill_primary="white",
118
- block_background_fill="*neutral_50",
119
- input_background_fill="white",
120
- )
121
 
122
- # Custom CSS for elegant styling
123
- css = """
124
- .gradio-container {
125
- max-width: 1200px !important;
126
- margin: 0 auto !important;
127
- background-color: #ffffff !important;
128
- box-shadow: 0 4px 30px rgba(0, 0, 0, 0.03) !important;
129
- border-radius: 16px !important;
130
- overflow: hidden !important;
131
- }
 
132
 
133
- .header-container {
134
- background: linear-gradient(135deg, #e0f2fe, #f0f9ff) !important;
135
- padding: 2rem 1.5rem 1.5rem !important;
136
- border-bottom: 1px solid rgba(0, 0, 0, 0.03) !important;
137
- margin-bottom: 1.5rem !important;
138
- }
139
 
140
- .header-title {
141
- font-weight: 300 !important;
142
- color: #1e40af !important;
143
- font-size: 2rem !important;
144
- margin: 0 !important;
145
- letter-spacing: -0.02em !important;
146
- }
147
 
148
- .header-subtitle {
149
- color: #475569 !important;
150
- font-weight: 400 !important;
151
- margin-top: 0.5rem !important;
152
- }
153
 
154
- .input-panel {
155
- background-color: white !important;
156
- border-radius: 10px !important;
157
- padding: 0.5rem !important;
158
- border: 1px solid #e2e8f0 !important;
159
- }
160
 
161
- .preview-container {
162
- border: 1px solid #e2e8f0 !important;
163
- border-radius: 10px !important;
164
- overflow: hidden !important;
165
- }
 
166
 
167
- .preview-container iframe {
168
- border: none !important;
169
- background-color: white !important;
170
- }
171
 
172
- .footer {
173
- text-align: center !important;
174
- padding: 1.5rem !important;
175
- color: #94a3b8 !important;
176
- font-size: 0.8rem !important;
177
- border-top: 1px solid #f1f5f9 !important;
178
- margin-top: 2rem !important;
179
- }
180
 
181
- /* Responsive adjustments */
182
- @media (max-width: 768px) {
183
- .header-title {
184
- font-size: 1.5rem !important;
185
- }
186
-
187
- .two-column {
188
- flex-direction: column !important;
189
- }
190
- }
191
- """
 
 
 
 
 
 
 
192
 
193
- # Create the Gradio interface
194
- with gr.Blocks(theme=theme, css=css) as demo:
195
- # Header
196
- with gr.Column(elem_classes=["header-container"]):
197
- gr.Markdown("# HTML Previewer", elem_classes=["header-title"])
198
- gr.Markdown("Elegant HTML visualization inspired by Intercontinental Ishigaki",
199
- elem_classes=["header-subtitle"])
200
-
201
- # Main content with responsive layout
202
- with gr.Row(equal_height=True, elem_classes=["two-column"]) as layout_row:
203
- # Input panel
204
- with gr.Column(scale=1, elem_classes=["input-panel"]):
205
- html_input = gr.Code(
206
- label="HTML Code",
207
- language="html",
208
- value="<!-- Enter your HTML here -->",
209
- lines=15,
210
- elem_id="html-input"
211
- )
212
-
213
- with gr.Row():
214
- clear_btn = gr.Button("Clear", variant="secondary")
215
- copy_btn = gr.Button("Copy HTML", variant="secondary")
216
-
217
- # Preview panel
218
- with gr.Column(scale=1, elem_classes=["preview-container"]):
219
- html_preview = gr.HTML(label="Preview", elem_id="preview-container")
220
-
221
- # Footer
222
- with gr.Column(elem_classes=["footer"]):
223
- gr.Markdown("*Designed with the elegant simplicity of Intercontinental Hotel Ishigaki's Club Lounge in mind*")
224
-
225
- # Event handlers
226
- html_input.change(
227
- fn=update_iframe,
228
- inputs=html_input,
229
- outputs=html_preview,
230
- api_name=False,
231
- _js="""
232
- function(html_code) {
233
- // This is client-side handling of the preview
234
- const iframe = document.createElement('iframe');
235
- iframe.style.width = '100%';
236
- iframe.style.height = '500px';
237
- iframe.style.border = 'none';
238
- iframe.style.borderRadius = '8px';
239
-
240
- // Create preview element
241
- const previewContainer = document.getElementById('preview-container');
242
- previewContainer.innerHTML = '';
243
- previewContainer.appendChild(iframe);
244
-
245
- // Set content
246
- const iframeDoc = iframe.contentWindow.document;
247
- iframeDoc.open();
248
- iframeDoc.write(html_code);
249
- iframeDoc.close();
250
-
251
- return html_code;
252
- }
253
- """
254
  )
255
-
256
- clear_btn.click(fn=lambda: "<!-- Enter your HTML here -->", inputs=None, outputs=html_input)
257
- copy_btn.click(fn=None, inputs=None, outputs=None,
258
- _js="""
259
- function() {
260
- const code = document.getElementById('html-input').querySelector('textarea').value;
261
- navigator.clipboard.writeText(code);
262
- return null;
263
- }
264
- """)
265
 
266
- # Launch the app
267
  if __name__ == "__main__":
268
  demo.launch()
 
1
  import gradio as gr
 
 
 
2
 
3
+ def display_html(html_code):
4
+ """
5
+ 入力されたHTMLコードをgr.HTMLコンポーネントに表示する関数。
6
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  return f"""
8
+ <div style='overflow-x: hidden; height: 80vh; width:100%;'>
9
+ {html_code}
10
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  """
12
 
13
+ # インターコンチネンタルホテル石垣島のクラブラウンジ風のテーマ設定。
14
+ # 白基調で、少し青みがかったアクセントを加える。
15
+ theme = gr.themes.Base(
16
+ primary_hue="slate", # 全体の基本色を少し青みがかったグレーに
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  secondary_hue="blue",
18
  neutral_hue="slate",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ ).set(
21
+ body_background_fill="#f8f9fa", # 非常に薄いグレー
22
+ body_text_color="black",
23
+ button_primary_background_fill="#e0f2fe", # ごく薄い水色
24
+ button_primary_background_fill_hover="#bae6fd",
25
+ button_primary_text_color="black",
26
+ border_color_primary="#d1d5db", # やや濃いグレー
27
+ block_background_fill="white",
28
+ block_title_text_color="#3b82f6", #青色
29
+ block_label_text_color="#1d4ed8", #濃い青
30
+ block_border_color="white",
31
 
32
+ )
 
 
 
 
 
33
 
 
 
 
 
 
 
 
34
 
35
+ with gr.Blocks(theme=theme, title="HTML Viewer") as demo: #themeを指定
36
+ gr.Markdown(
37
+ """
38
+ # HTML Viewer
 
39
 
40
+ 入力されたHTMLコードを、プレビュー表示します。
 
 
 
 
 
41
 
42
+ * 横スクロール禁止、縦スクロール許可
43
+ * レスポンシブデザイン (Gradio デフォルト)
44
+ * スマホでの表示は、PC版を縮小したようなイメージ
45
+ * インターコンチネンタル石垣島のクラブラウンジ風の、白く爽やかな外観
46
+ """)
47
+ with gr.Row():
48
 
49
+ with gr.Column(scale=1):
 
 
 
50
 
51
+ input_textbox = gr.Textbox(
52
+ label="HTMLコードを入力",
53
+ placeholder="ここにHTMLコードを貼り付けてください...",
54
+ lines=10
55
+ )
56
+ submit_button = gr.Button("表示")
57
+ with gr.Column(scale=3):
58
+ output_html = gr.HTML(label="プレビュー",)
59
 
60
+ submit_button.click(
61
+ display_html,
62
+ inputs=input_textbox,
63
+ outputs=output_html
64
+ )
65
+ #サンプル
66
+ gr.Examples(
67
+ [["<h1>Hello world</h1>"],["""
68
+ <!DOCTYPE html>
69
+ <html>
70
+ <head>
71
+ <title>サンプルページ</title>
72
+ </head>
73
+ <body>
74
+ <h1 style='color:blue';>Hello world!</h1>
75
+ <p>サンプル</p>
76
+ </body>
77
+ </html>"""]],
78
 
79
+ inputs = input_textbox
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  )
 
 
 
 
 
 
 
 
 
 
81
 
82
+
83
  if __name__ == "__main__":
84
  demo.launch()