chuckfinca Claude Opus 4.6 (1M context) commited on
Commit
350eca4
·
1 Parent(s): 78c1ba6

Inject JS via gr.Blocks(js=) instead of inline script tags

Browse files

Gradio strips script tags from gr.HTML for security. Move all
JS to the js= parameter and CSS to css= parameter on Blocks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +24 -27
app.py CHANGED
@@ -252,29 +252,29 @@ CUSTOM_HTML = """
252
  </div>
253
  </div>
254
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
- <style>""" + _CHAT_UI_CSS + """</style>
257
- <script>""" + _CHAT_UI_JS + """</script>
258
- <style>
259
- #explorer-app { font-family: var(--font-family, 'Inter', system-ui, sans-serif); max-width: 800px; margin: 0 auto; }
260
- #setup-panel { padding: 24px 0; }
261
- .setup-field { margin-bottom: 16px; }
262
- .setup-field label { display: block; font-size: 13px; color: #6B7280; margin-bottom: 4px; }
263
- #token-input { width: 100%; padding: 8px 12px; border: 1px solid #E5E7EB; border-radius: 4px; font-family: inherit; font-size: 14px; }
264
- #token-input:focus { outline: none; border-color: #4682B4; }
265
- .drop-zone { border: 2px dashed #E5E7EB; border-radius: 8px; padding: 32px; text-align: center; color: #9CA3AF; cursor: pointer; transition: border-color 0.2s; }
266
- .drop-zone.drag-over { border-color: #4682B4; background: #f0f7ff; }
267
- .drop-zone p { margin: 0; }
268
- .file-label { color: #4682B4; cursor: pointer; text-decoration: underline; }
269
- #file-list { margin-top: 8px; font-size: 13px; color: #374151; text-align: left; }
270
- #file-list div { padding: 2px 0; }
271
- #start-btn { width: 100%; padding: 10px; background: #4682B4; color: white; border: none; border-radius: 4px; font-family: inherit; font-size: 14px; cursor: pointer; margin-top: 8px; }
272
- #start-btn:disabled { background: #D1D5DB; cursor: default; }
273
- #start-btn:not(:disabled):hover { background: #3a6f9a; }
274
- #chat-panel { padding-top: 8px; }
275
- </style>
276
- <script>
277
- (function() {
278
  var API_BASE = window.location.origin;
279
  var tokenInput = document.getElementById('token-input');
280
  var fileInput = document.getElementById('file-input');
@@ -320,7 +320,6 @@ CUSTOM_HTML = """
320
  startBtn.disabled = true;
321
  startBtn.textContent = 'Uploading...';
322
 
323
- // Step 1: Upload files to Gradio's file endpoint
324
  var formData = new FormData();
325
  selectedFiles.forEach(function(f) { formData.append('files', f); });
326
 
@@ -330,7 +329,6 @@ CUSTOM_HTML = """
330
  })
331
  .then(function(r) { return r.json(); })
332
  .then(function(uploadedPaths) {
333
- // Step 2: Call our setup endpoint with the server file paths
334
  return fetch(API_BASE + '/gradio_api/call/upload', {
335
  method: 'POST',
336
  headers: { 'Content-Type': 'application/json' },
@@ -418,7 +416,7 @@ CUSTOM_HTML = """
418
  finalHtml += '<div class="chat-stats">' + eventData.stats + '</div>';
419
  }
420
  if (eventData.trace_html) {
421
- finalHtml += '<button class="chat-trace-toggle" onclick="this.nextElementSibling.classList.toggle(\'open\')">trace</button>';
422
  finalHtml += '<div class="chat-trace">' + eventData.trace_html + '</div>';
423
  }
424
  turn.innerHTML = '<div class="chat-question">' + escapeHtml(question) + '</div>' + finalHtml;
@@ -455,12 +453,11 @@ CUSTOM_HTML = """
455
  });
456
  });
457
  })();
458
- </script>
459
  """
460
 
461
 
462
  def build_app() -> gr.Blocks:
463
- with gr.Blocks(title="Document Explorer") as demo:
464
  gr.HTML(CUSTOM_HTML)
465
 
466
  # Hidden state for file upload workspace
 
252
  </div>
253
  </div>
254
  </div>
255
+ """
256
+
257
+ CUSTOM_CSS = _CHAT_UI_CSS + """
258
+ #explorer-app { font-family: var(--font-family, 'Inter', system-ui, sans-serif); max-width: 800px; margin: 0 auto; }
259
+ #setup-panel { padding: 24px 0; }
260
+ .setup-field { margin-bottom: 16px; }
261
+ .setup-field label { display: block; font-size: 13px; color: #6B7280; margin-bottom: 4px; }
262
+ #token-input { width: 100%; padding: 8px 12px; border: 1px solid #E5E7EB; border-radius: 4px; font-family: inherit; font-size: 14px; }
263
+ #token-input:focus { outline: none; border-color: #4682B4; }
264
+ .drop-zone { border: 2px dashed #E5E7EB; border-radius: 8px; padding: 32px; text-align: center; color: #9CA3AF; cursor: pointer; transition: border-color 0.2s; }
265
+ .drop-zone.drag-over { border-color: #4682B4; background: #f0f7ff; }
266
+ .drop-zone p { margin: 0; }
267
+ .file-label { color: #4682B4; cursor: pointer; text-decoration: underline; }
268
+ #file-list { margin-top: 8px; font-size: 13px; color: #374151; text-align: left; }
269
+ #file-list div { padding: 2px 0; }
270
+ #start-btn { width: 100%; padding: 10px; background: #4682B4; color: white; border: none; border-radius: 4px; font-family: inherit; font-size: 14px; cursor: pointer; margin-top: 8px; }
271
+ #start-btn:disabled { background: #D1D5DB; cursor: default; }
272
+ #start-btn:not(:disabled):hover { background: #3a6f9a; }
273
+ #chat-panel { padding-top: 8px; }
274
+ """
275
 
276
+ CUSTOM_JS = _CHAT_UI_JS + """
277
+ ;(function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  var API_BASE = window.location.origin;
279
  var tokenInput = document.getElementById('token-input');
280
  var fileInput = document.getElementById('file-input');
 
320
  startBtn.disabled = true;
321
  startBtn.textContent = 'Uploading...';
322
 
 
323
  var formData = new FormData();
324
  selectedFiles.forEach(function(f) { formData.append('files', f); });
325
 
 
329
  })
330
  .then(function(r) { return r.json(); })
331
  .then(function(uploadedPaths) {
 
332
  return fetch(API_BASE + '/gradio_api/call/upload', {
333
  method: 'POST',
334
  headers: { 'Content-Type': 'application/json' },
 
416
  finalHtml += '<div class="chat-stats">' + eventData.stats + '</div>';
417
  }
418
  if (eventData.trace_html) {
419
+ finalHtml += '<button class="chat-trace-toggle" onclick="this.nextElementSibling.classList.toggle(\\'open\\')">trace</button>';
420
  finalHtml += '<div class="chat-trace">' + eventData.trace_html + '</div>';
421
  }
422
  turn.innerHTML = '<div class="chat-question">' + escapeHtml(question) + '</div>' + finalHtml;
 
453
  });
454
  });
455
  })();
 
456
  """
457
 
458
 
459
  def build_app() -> gr.Blocks:
460
+ with gr.Blocks(title="Document Explorer", css=CUSTOM_CSS, js=CUSTOM_JS) as demo:
461
  gr.HTML(CUSTOM_HTML)
462
 
463
  # Hidden state for file upload workspace