eubottura commited on
Commit
0faa3e4
·
verified ·
1 Parent(s): 0580550

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +656 -19
index.html CHANGED
@@ -1,19 +1,656 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Transcribe JSON to SRT Converter</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <style>
9
+ :root {
10
+ --primary-color: #4a6fa5;
11
+ --secondary-color: #166088;
12
+ --accent-color: #4fc3f7;
13
+ --background-color: #f8f9fa;
14
+ --text-color: #333;
15
+ --light-gray: #e9ecef;
16
+ --dark-gray: #6c757d;
17
+ --success-color: #28a745;
18
+ --error-color: #dc3545;
19
+ --border-radius: 8px;
20
+ --box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
21
+ --transition: all 0.3s ease;
22
+ }
23
+
24
+ * {
25
+ margin: 0;
26
+ padding: 0;
27
+ box-sizing: border-box;
28
+ }
29
+
30
+ body {
31
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
32
+ line-height: 1.6;
33
+ color: var(--text-color);
34
+ background-color: var(--background-color);
35
+ padding: 20px;
36
+ min-height: 100vh;
37
+ }
38
+
39
+ .container {
40
+ max-width: 1200px;
41
+ margin: 0 auto;
42
+ padding: 20px;
43
+ }
44
+
45
+ header {
46
+ display: flex;
47
+ justify-content: space-between;
48
+ align-items: center;
49
+ margin-bottom: 30px;
50
+ padding-bottom: 20px;
51
+ border-bottom: 1px solid var(--light-gray);
52
+ }
53
+
54
+ .logo {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: 10px;
58
+ }
59
+
60
+ .logo i {
61
+ font-size: 24px;
62
+ color: var(--primary-color);
63
+ }
64
+
65
+ .logo span {
66
+ font-size: 20px;
67
+ font-weight: 600;
68
+ color: var(--primary-color);
69
+ }
70
+
71
+ .anycoder-link {
72
+ font-size: 14px;
73
+ color: var(--dark-gray);
74
+ text-decoration: none;
75
+ }
76
+
77
+ .anycoder-link:hover {
78
+ color: var(--primary-color);
79
+ }
80
+
81
+ .converter-card {
82
+ background: white;
83
+ border-radius: var(--border-radius);
84
+ box-shadow: var(--box-shadow);
85
+ padding: 30px;
86
+ margin-bottom: 30px;
87
+ }
88
+
89
+ h1 {
90
+ color: var(--secondary-color);
91
+ margin-bottom: 20px;
92
+ font-size: 28px;
93
+ text-align: center;
94
+ }
95
+
96
+ .description {
97
+ text-align: center;
98
+ color: var(--dark-gray);
99
+ margin-bottom: 30px;
100
+ font-size: 16px;
101
+ }
102
+
103
+ .input-section {
104
+ display: flex;
105
+ flex-direction: column;
106
+ gap: 20px;
107
+ margin-bottom: 30px;
108
+ }
109
+
110
+ .input-group {
111
+ display: flex;
112
+ flex-direction: column;
113
+ gap: 8px;
114
+ }
115
+
116
+ label {
117
+ font-weight: 500;
118
+ color: var(--secondary-color);
119
+ font-size: 14px;
120
+ }
121
+
122
+ textarea, input {
123
+ padding: 12px;
124
+ border: 1px solid var(--light-gray);
125
+ border-radius: var(--border-radius);
126
+ font-family: inherit;
127
+ font-size: 14px;
128
+ transition: var(--transition);
129
+ }
130
+
131
+ textarea:focus, input:focus {
132
+ outline: none;
133
+ border-color: var(--accent-color);
134
+ box-shadow: 0 0 0 2px rgba(79, 195, 247, 0.2);
135
+ }
136
+
137
+ .word-break-control {
138
+ display: flex;
139
+ align-items: center;
140
+ gap: 10px;
141
+ }
142
+
143
+ .word-break-input {
144
+ width: 80px;
145
+ }
146
+
147
+ .buttons {
148
+ display: flex;
149
+ gap: 15px;
150
+ margin-top: 20px;
151
+ }
152
+
153
+ button {
154
+ padding: 12px 24px;
155
+ border: none;
156
+ border-radius: var(--border-radius);
157
+ font-weight: 500;
158
+ cursor: pointer;
159
+ transition: var(--transition);
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 8px;
163
+ }
164
+
165
+ .convert-btn {
166
+ background-color: var(--primary-color);
167
+ color: white;
168
+ }
169
+
170
+ .convert-btn:hover {
171
+ background-color: var(--secondary-color);
172
+ transform: translateY(-2px);
173
+ }
174
+
175
+ .clear-btn {
176
+ background-color: var(--light-gray);
177
+ color: var(--text-color);
178
+ }
179
+
180
+ .clear-btn:hover {
181
+ background-color: var(--dark-gray);
182
+ color: white;
183
+ }
184
+
185
+ .output-section {
186
+ margin-top: 30px;
187
+ }
188
+
189
+ .output-header {
190
+ display: flex;
191
+ justify-content: space-between;
192
+ align-items: center;
193
+ margin-bottom: 15px;
194
+ }
195
+
196
+ .output-title {
197
+ font-weight: 600;
198
+ color: var(--secondary-color);
199
+ }
200
+
201
+ .copy-btn {
202
+ background-color: var(--accent-color);
203
+ color: white;
204
+ padding: 8px 16px;
205
+ }
206
+
207
+ .copy-btn:hover {
208
+ background-color: #3ba8e6;
209
+ }
210
+
211
+ #output {
212
+ width: 100%;
213
+ min-height: 200px;
214
+ padding: 15px;
215
+ border: 1px solid var(--light-gray);
216
+ border-radius: var(--border-radius);
217
+ font-family: 'Courier New', Courier, monospace;
218
+ font-size: 14px;
219
+ background-color: #f8f9fa;
220
+ white-space: pre-wrap;
221
+ overflow-x: auto;
222
+ }
223
+
224
+ .status-message {
225
+ margin-top: 20px;
226
+ padding: 12px;
227
+ border-radius: var(--border-radius);
228
+ display: none;
229
+ }
230
+
231
+ .success {
232
+ background-color: rgba(40, 167, 69, 0.1);
233
+ color: var(--success-color);
234
+ border: 1px solid rgba(40, 167, 69, 0.2);
235
+ }
236
+
237
+ .error {
238
+ background-color: rgba(220, 53, 69, 0.1);
239
+ color: var(--error-color);
240
+ border: 1px solid rgba(220, 53, 69, 0.2);
241
+ }
242
+
243
+ .example-section {
244
+ margin-top: 40px;
245
+ padding: 20px;
246
+ background-color: white;
247
+ border-radius: var(--border-radius);
248
+ box-shadow: var(--box-shadow);
249
+ }
250
+
251
+ .example-header {
252
+ display: flex;
253
+ justify-content: space-between;
254
+ align-items: center;
255
+ margin-bottom: 15px;
256
+ }
257
+
258
+ .example-title {
259
+ font-weight: 600;
260
+ color: var(--secondary-color);
261
+ }
262
+
263
+ .example-json {
264
+ background-color: #f8f9fa;
265
+ padding: 15px;
266
+ border-radius: var(--border-radius);
267
+ font-family: 'Courier New', Courier, monospace;
268
+ font-size: 13px;
269
+ white-space: pre-wrap;
270
+ border: 1px solid var(--light-gray);
271
+ }
272
+
273
+ .toggle-example {
274
+ background: none;
275
+ border: none;
276
+ color: var(--primary-color);
277
+ cursor: pointer;
278
+ font-weight: 500;
279
+ display: flex;
280
+ align-items: center;
281
+ gap: 5px;
282
+ }
283
+
284
+ .toggle-example:hover {
285
+ text-decoration: underline;
286
+ }
287
+
288
+ @media (max-width: 768px) {
289
+ .container {
290
+ padding: 10px;
291
+ }
292
+
293
+ .converter-card {
294
+ padding: 20px;
295
+ }
296
+
297
+ .buttons {
298
+ flex-direction: column;
299
+ }
300
+
301
+ button {
302
+ width: 100%;
303
+ justify-content: center;
304
+ }
305
+
306
+ .word-break-control {
307
+ flex-direction: column;
308
+ align-items: flex-start;
309
+ }
310
+
311
+ .word-break-input {
312
+ width: 100%;
313
+ }
314
+ }
315
+
316
+ @media (max-width: 480px) {
317
+ h1 {
318
+ font-size: 24px;
319
+ }
320
+
321
+ .description {
322
+ font-size: 14px;
323
+ }
324
+
325
+ textarea, input {
326
+ font-size: 13px;
327
+ }
328
+ }
329
+ </style>
330
+ </head>
331
+ <body>
332
+ <div class="container">
333
+ <header>
334
+ <div class="logo">
335
+ <i class="fas fa-robot"></i>
336
+ <span>Transcribe Converter</span>
337
+ </div>
338
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank">Built with anycoder</a>
339
+ </header>
340
+
341
+ <div class="converter-card">
342
+ <h1>JSON to SRT Converter</h1>
343
+ <p class="description">Convert Amazon Transcribe JSON format to SRT subtitles with configurable segmentation</p>
344
+
345
+ <div class="input-section">
346
+ <div class="input-group">
347
+ <label for="jsonInput">Transcribe JSON Input</label>
348
+ <textarea id="jsonInput" rows="10" placeholder='Paste your Transcribe JSON here. Example format:
349
+ {
350
+ "text": "Full transcription text...",
351
+ "chunks": [
352
+ {
353
+ "text": "First segment...",
354
+ "start": 0.0,
355
+ "end": 2.5
356
+ },
357
+ ...
358
+ ]
359
+ }'></textarea>
360
+ </div>
361
+
362
+ <div class="input-group">
363
+ <label>Segmentation Settings</label>
364
+ <div class="word-break-control">
365
+ <span>Word break threshold:</span>
366
+ <input type="number" id="wordBreakThreshold" class="word-break-input" min="1" max="50" value="10">
367
+ <span>words</span>
368
+ </div>
369
+ <p style="font-size: 12px; color: var(--dark-gray); margin-top: 5px;">
370
+ Subtitles will break at sentence boundaries or when reaching this word count
371
+ </p>
372
+ </div>
373
+ </div>
374
+
375
+ <div class="buttons">
376
+ <button class="convert-btn" id="convertBtn">
377
+ <i class="fas fa-exchange-alt"></i>
378
+ Convert to SRT
379
+ </button>
380
+ <button class="clear-btn" id="clearBtn">
381
+ <i class="fas fa-times"></i>
382
+ Clear All
383
+ </button>
384
+ </div>
385
+
386
+ <div class="output-section">
387
+ <div class="output-header">
388
+ <div class="output-title">SRT Output</div>
389
+ <button class="copy-btn" id="copyBtn">
390
+ <i class="fas fa-copy"></i>
391
+ Copy to Clipboard
392
+ </button>
393
+ </div>
394
+ <div id="output" readonly></div>
395
+ </div>
396
+
397
+ <div class="status-message" id="statusMessage"></div>
398
+ </div>
399
+
400
+ <div class="example-section">
401
+ <div class="example-header">
402
+ <div class="example-title">Example JSON Input</div>
403
+ <button class="toggle-example" id="toggleExample">
404
+ <i class="fas fa-chevron-down"></i>
405
+ Show Example
406
+ </button>
407
+ </div>
408
+ <div class="example-json" id="exampleJson" style="display: none;">
409
+ {
410
+ "text": "Hello world. This is a test transcription. We're going to demonstrate how this converter works with multiple sentences and different timing segments. Each sentence should ideally become its own subtitle segment.",
411
+ "chunks": [
412
+ {
413
+ "text": "Hello world.",
414
+ "start": 0.0,
415
+ "end": 1.2
416
+ },
417
+ {
418
+ "text": "This is a test transcription.",
419
+ "start": 1.2,
420
+ "end": 3.5
421
+ },
422
+ {
423
+ "text": "We're going to demonstrate",
424
+ "start": 3.5,
425
+ "end": 5.8
426
+ },
427
+ {
428
+ "text": "how this converter works",
429
+ "start": 5.8,
430
+ "end": 7.2
431
+ },
432
+ {
433
+ "text": "with multiple sentences",
434
+ "start": 7.2,
435
+ "end": 8.9
436
+ },
437
+ {
438
+ "text": "and different timing segments.",
439
+ "start": 8.9,
440
+ "end": 10.5
441
+ },
442
+ {
443
+ "text": "Each sentence should ideally become its own subtitle segment.",
444
+ "start": 10.5,
445
+ "end": 13.8
446
+ }
447
+ ]
448
+ }
449
+ </div>
450
+ </div>
451
+ </div>
452
+
453
+ <script>
454
+ document.addEventListener('DOMContentLoaded', function() {
455
+ const jsonInput = document.getElementById('jsonInput');
456
+ const wordBreakThreshold = document.getElementById('wordBreakThreshold');
457
+ const convertBtn = document.getElementById('convertBtn');
458
+ const clearBtn = document.getElementById('clearBtn');
459
+ const copyBtn = document.getElementById('copyBtn');
460
+ const output = document.getElementById('output');
461
+ const statusMessage = document.getElementById('statusMessage');
462
+ const toggleExample = document.getElementById('toggleExample');
463
+ const exampleJson = document.getElementById('exampleJson');
464
+
465
+ // Toggle example visibility
466
+ toggleExample.addEventListener('click', function() {
467
+ const isVisible = exampleJson.style.display === 'block';
468
+ exampleJson.style.display = isVisible ? 'none' : 'block';
469
+ toggleExample.innerHTML = `
470
+ <i class="fas fa-chevron-${isVisible ? 'down' : 'up'}"></i>
471
+ ${isVisible ? 'Show Example' : 'Hide Example'}
472
+ `;
473
+ });
474
+
475
+ // Clear all inputs and outputs
476
+ clearBtn.addEventListener('click', function() {
477
+ jsonInput.value = '';
478
+ output.value = '';
479
+ statusMessage.style.display = 'none';
480
+ });
481
+
482
+ // Copy output to clipboard
483
+ copyBtn.addEventListener('click', function() {
484
+ if (output.value.trim() === '') {
485
+ showStatus('No content to copy', 'error');
486
+ return;
487
+ }
488
+
489
+ navigator.clipboard.writeText(output.value)
490
+ .then(() => {
491
+ showStatus('SRT content copied to clipboard!', 'success');
492
+ })
493
+ .catch(err => {
494
+ showStatus('Failed to copy: ' + err, 'error');
495
+ });
496
+ });
497
+
498
+ // Convert JSON to SRT
499
+ convertBtn.addEventListener('click', function() {
500
+ try {
501
+ const jsonText = jsonInput.value.trim();
502
+ if (!jsonText) {
503
+ throw new Error('Please provide JSON input');
504
+ }
505
+
506
+ const jsonData = JSON.parse(jsonText);
507
+ validateJsonStructure(jsonData);
508
+
509
+ const threshold = parseInt(wordBreakThreshold.value);
510
+ if (isNaN(threshold) || threshold < 1 || threshold > 50) {
511
+ throw new Error('Word break threshold must be between 1 and 50');
512
+ }
513
+
514
+ const srtContent = convertToSRT(jsonData, threshold);
515
+ output.value = srtContent;
516
+ showStatus('Conversion successful!', 'success');
517
+ } catch (error) {
518
+ showStatus('Error: ' + error.message, 'error');
519
+ console.error(error);
520
+ }
521
+ });
522
+
523
+ // Validate JSON structure
524
+ function validateJsonStructure(jsonData) {
525
+ if (!jsonData || typeof jsonData !== 'object') {
526
+ throw new Error('Invalid JSON structure');
527
+ }
528
+
529
+ if (!jsonData.text || typeof jsonData.text !== 'string') {
530
+ throw new Error('Missing or invalid "text" field');
531
+ }
532
+
533
+ if (!jsonData.chunks || !Array.isArray(jsonData.chunks) || jsonData.chunks.length === 0) {
534
+ throw new Error('Missing or invalid "chunks" array');
535
+ }
536
+
537
+ for (let i = 0; i < jsonData.chunks.length; i++) {
538
+ const chunk = jsonData.chunks[i];
539
+ if (!chunk.text || typeof chunk.text !== 'string') {
540
+ throw new Error(`Chunk ${i + 1} missing or invalid "text" field`);
541
+ }
542
+ if (typeof chunk.start !== 'number' || typeof chunk.end !== 'number') {
543
+ throw new Error(`Chunk ${i + 1} missing or invalid timestamp fields`);
544
+ }
545
+ if (chunk.start < 0 || chunk.end <= chunk.start) {
546
+ throw new Error(`Chunk ${i + 1} has invalid timestamp values`);
547
+ }
548
+ }
549
+ }
550
+
551
+ // Convert JSON to SRT format
552
+ function convertToSRT(jsonData, wordThreshold) {
553
+ let srt = '';
554
+ let currentSegment = {
555
+ text: '',
556
+ startTime: null,
557
+ endTime: null,
558
+ wordCount: 0
559
+ };
560
+ let segmentNumber = 1;
561
+
562
+ // Process each chunk
563
+ for (const chunk of jsonData.chunks) {
564
+ const chunkText = chunk.text.trim();
565
+ if (!chunkText) continue;
566
+
567
+ // Split chunk text into sentences (simple approach)
568
+ const sentences = splitIntoSentences(chunkText);
569
+
570
+ for (const sentence of sentences) {
571
+ const words = sentence.split(/\s+/).filter(word => word.length > 0);
572
+ const wordCount = words.length;
573
+
574
+ // Check if we need to start a new segment
575
+ if (currentSegment.startTime === null ||
576
+ (currentSegment.wordCount + wordCount > wordThreshold &&
577
+ currentSegment.wordCount > 0)) {
578
+ // Save previous segment if it exists
579
+ if (currentSegment.startTime !== null) {
580
+ srt += formatSRTSegment(segmentNumber++, currentSegment);
581
+ }
582
+ // Start new segment
583
+ currentSegment = {
584
+ text: sentence,
585
+ startTime: chunk.start,
586
+ endTime: chunk.end,
587
+ wordCount: wordCount
588
+ };
589
+ } else {
590
+ // Add to current segment
591
+ currentSegment.text += ' ' + sentence;
592
+ currentSegment.endTime = chunk.end;
593
+ currentSegment.wordCount += wordCount;
594
+ }
595
+ }
596
+ }
597
+
598
+ // Add the last segment
599
+ if (currentSegment.startTime !== null) {
600
+ srt += formatSRTSegment(segmentNumber, currentSegment);
601
+ }
602
+
603
+ return srt;
604
+ }
605
+
606
+ // Simple sentence splitting (can be enhanced)
607
+ function splitIntoSentences(text) {
608
+ // Split on common sentence terminators followed by whitespace or end of string
609
+ return text.split(/[.!?]+(?=\s|$)/)
610
+ .map(s => s.trim())
611
+ .filter(s => s.length > 0);
612
+ }
613
+
614
+ // Format a single SRT segment
615
+ function formatSRTSegment(number, segment) {
616
+ return `${number}\n` +
617
+ `${formatTime(segment.startTime)} --> ${formatTime(segment.endTime)}\n` +
618
+ `${segment.text.trim()}\n\n`;
619
+ }
620
+
621
+ // Format time in SRT format (HH:MM:SS,mmm)
622
+ function formatTime(seconds) {
623
+ if (seconds === null || seconds === undefined) return '00:00:00,000';
624
+
625
+ const date = new Date(seconds * 1000);
626
+ const hours = String(date.getUTCHours()).padStart(2, '0');
627
+ const minutes = String(date.getUTCMinutes()).padStart(2, '0');
628
+ const secs = String(date.getUTCSeconds()).padStart(2, '0');
629
+ const millis = String(Math.floor(date.getUTCMilliseconds())).padStart(3, '0');
630
+
631
+ return `${hours}:${minutes}:${secs},${millis}`;
632
+ }
633
+
634
+ // Show status message
635
+ function showStatus(message, type) {
636
+ statusMessage.textContent = message;
637
+ statusMessage.className = 'status-message ' + type;
638
+ statusMessage.style.display = 'block';
639
+
640
+ // Hide after 5 seconds
641
+ setTimeout(() => {
642
+ statusMessage.style.display = 'none';
643
+ }, 5000);
644
+ }
645
+
646
+ // Load example JSON when clicking the example button
647
+ document.getElementById('exampleJson').addEventListener('click', function() {
648
+ if (jsonInput.value.trim() === '') {
649
+ jsonInput.value = this.textContent.trim();
650
+ showStatus('Example JSON loaded!', 'success');
651
+ }
652
+ });
653
+ });
654
+ </script>
655
+ </body>
656
+ </html>