fragment-ts 1.2.6 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -227,7 +227,7 @@ class DocGenerator {
|
|
|
227
227
|
return schema;
|
|
228
228
|
}
|
|
229
229
|
renderHtml(spec, templatePath) {
|
|
230
|
-
let template =
|
|
230
|
+
let template = MODERN_DARK_TEMPLATE;
|
|
231
231
|
if (templatePath) {
|
|
232
232
|
const resolved = path.isAbsolute(templatePath)
|
|
233
233
|
? templatePath
|
|
@@ -322,112 +322,168 @@ function resolveModuleName(controller) {
|
|
|
322
322
|
function sanitizeModuleName(name) {
|
|
323
323
|
return name.replace(/[^a-zA-Z0-9-_]+/g, "-");
|
|
324
324
|
}
|
|
325
|
-
const
|
|
325
|
+
const MODERN_DARK_TEMPLATE = `<!doctype html>
|
|
326
326
|
<html lang="en">
|
|
327
327
|
<head>
|
|
328
328
|
<meta charset="utf-8" />
|
|
329
329
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
330
330
|
<title><%= spec.info.title %></title>
|
|
331
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
332
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
333
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
331
334
|
<style>
|
|
332
|
-
* {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
--
|
|
341
|
-
--
|
|
342
|
-
--
|
|
343
|
-
--
|
|
344
|
-
--
|
|
345
|
-
--
|
|
346
|
-
|
|
347
|
-
--
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
335
|
+
* {
|
|
336
|
+
box-sizing: border-box;
|
|
337
|
+
margin: 0;
|
|
338
|
+
padding: 0;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
:root {
|
|
342
|
+
/* Dark Theme Colors */
|
|
343
|
+
--bg-primary: #0a0a0a;
|
|
344
|
+
--bg-secondary: #111111;
|
|
345
|
+
--bg-tertiary: #1a1a1a;
|
|
346
|
+
--bg-elevated: #1f1f1f;
|
|
347
|
+
--bg-hover: #252525;
|
|
348
|
+
--bg-active: #2a2a2a;
|
|
349
|
+
|
|
350
|
+
--border-subtle: #2a2a2a;
|
|
351
|
+
--border-default: #333333;
|
|
352
|
+
--border-strong: #3f3f3f;
|
|
353
|
+
|
|
354
|
+
--text-primary: #ffffff;
|
|
355
|
+
--text-secondary: #a1a1a1;
|
|
356
|
+
--text-tertiary: #737373;
|
|
357
|
+
--text-inverse: #0a0a0a;
|
|
358
|
+
|
|
359
|
+
--accent-blue: #3b82f6;
|
|
360
|
+
--accent-blue-hover: #2563eb;
|
|
361
|
+
--accent-green: #10b981;
|
|
362
|
+
--accent-yellow: #f59e0b;
|
|
363
|
+
--accent-orange: #f97316;
|
|
364
|
+
--accent-red: #ef4444;
|
|
365
|
+
--accent-purple: #8b5cf6;
|
|
366
|
+
|
|
367
|
+
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.5);
|
|
368
|
+
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.5);
|
|
369
|
+
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.6);
|
|
370
|
+
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.7);
|
|
371
|
+
|
|
372
|
+
--radius-sm: 6px;
|
|
373
|
+
--radius-md: 8px;
|
|
374
|
+
--radius-lg: 12px;
|
|
375
|
+
--radius-xl: 16px;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
body {
|
|
379
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", sans-serif;
|
|
380
|
+
background: var(--bg-primary);
|
|
381
|
+
color: var(--text-primary);
|
|
355
382
|
line-height: 1.6;
|
|
383
|
+
-webkit-font-smoothing: antialiased;
|
|
384
|
+
-moz-osx-font-smoothing: grayscale;
|
|
356
385
|
}
|
|
357
386
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
387
|
+
/* Header */
|
|
388
|
+
.header {
|
|
389
|
+
position: sticky;
|
|
390
|
+
top: 0;
|
|
391
|
+
z-index: 1000;
|
|
392
|
+
background: rgba(10, 10, 10, 0.8);
|
|
393
|
+
backdrop-filter: blur(12px);
|
|
394
|
+
border-bottom: 1px solid var(--border-default);
|
|
363
395
|
}
|
|
364
396
|
|
|
365
397
|
.header-content {
|
|
366
|
-
max-width:
|
|
398
|
+
max-width: 1600px;
|
|
367
399
|
margin: 0 auto;
|
|
400
|
+
padding: 0 24px;
|
|
401
|
+
height: 64px;
|
|
402
|
+
display: flex;
|
|
403
|
+
align-items: center;
|
|
404
|
+
justify-content: space-between;
|
|
368
405
|
}
|
|
369
406
|
|
|
370
|
-
.header
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
background: linear-gradient(135deg, var(--color-primary) 0%, #60a5fa 100%);
|
|
375
|
-
-webkit-background-clip: text;
|
|
376
|
-
-webkit-text-fill-color: transparent;
|
|
377
|
-
background-clip: text;
|
|
407
|
+
.header-brand {
|
|
408
|
+
display: flex;
|
|
409
|
+
align-items: center;
|
|
410
|
+
gap: 12px;
|
|
378
411
|
}
|
|
379
412
|
|
|
380
|
-
.header-
|
|
413
|
+
.header-logo {
|
|
414
|
+
font-size: 24px;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.header-title {
|
|
418
|
+
font-size: 18px;
|
|
419
|
+
font-weight: 600;
|
|
420
|
+
color: var(--text-primary);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.header-nav {
|
|
381
424
|
display: flex;
|
|
382
|
-
gap: 1.5rem;
|
|
383
425
|
align-items: center;
|
|
384
|
-
|
|
426
|
+
gap: 8px;
|
|
385
427
|
}
|
|
386
428
|
|
|
387
|
-
.
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
font-size: 0.875rem;
|
|
396
|
-
color: var(--color-text-muted);
|
|
429
|
+
.header-link {
|
|
430
|
+
padding: 8px 16px;
|
|
431
|
+
color: var(--text-secondary);
|
|
432
|
+
text-decoration: none;
|
|
433
|
+
border-radius: var(--radius-md);
|
|
434
|
+
font-size: 14px;
|
|
435
|
+
font-weight: 500;
|
|
436
|
+
transition: all 0.2s;
|
|
397
437
|
}
|
|
398
438
|
|
|
399
|
-
.
|
|
400
|
-
|
|
439
|
+
.header-link:hover {
|
|
440
|
+
color: var(--text-primary);
|
|
441
|
+
background: var(--bg-hover);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.header-link.active {
|
|
445
|
+
color: var(--text-primary);
|
|
446
|
+
background: var(--bg-active);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.theme-toggle {
|
|
450
|
+
padding: 8px;
|
|
451
|
+
background: none;
|
|
452
|
+
border: none;
|
|
453
|
+
color: var(--text-secondary);
|
|
454
|
+
cursor: pointer;
|
|
455
|
+
border-radius: var(--radius-md);
|
|
456
|
+
transition: all 0.2s;
|
|
457
|
+
font-size: 20px;
|
|
458
|
+
display: flex;
|
|
401
459
|
align-items: center;
|
|
402
|
-
|
|
403
|
-
background: var(--color-success);
|
|
404
|
-
color: white;
|
|
405
|
-
border-radius: 0.5rem;
|
|
406
|
-
font-size: 0.75rem;
|
|
407
|
-
font-weight: 600;
|
|
408
|
-
text-transform: uppercase;
|
|
409
|
-
letter-spacing: 0.05em;
|
|
460
|
+
justify-content: center;
|
|
410
461
|
}
|
|
411
462
|
|
|
463
|
+
.theme-toggle:hover {
|
|
464
|
+
background: var(--bg-hover);
|
|
465
|
+
color: var(--text-primary);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/* Layout */
|
|
412
469
|
.container {
|
|
413
|
-
max-width:
|
|
470
|
+
max-width: 1600px;
|
|
414
471
|
margin: 0 auto;
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
grid-template-columns: 280px 1fr;
|
|
418
|
-
gap: 2rem;
|
|
472
|
+
display: flex;
|
|
473
|
+
gap: 0;
|
|
419
474
|
}
|
|
420
475
|
|
|
476
|
+
/* Sidebar */
|
|
421
477
|
.sidebar {
|
|
478
|
+
width: 280px;
|
|
479
|
+
flex-shrink: 0;
|
|
480
|
+
background: var(--bg-secondary);
|
|
481
|
+
border-right: 1px solid var(--border-default);
|
|
482
|
+
height: calc(100vh - 64px);
|
|
422
483
|
position: sticky;
|
|
423
|
-
top:
|
|
424
|
-
height: fit-content;
|
|
425
|
-
max-height: calc(100vh - 4rem);
|
|
484
|
+
top: 64px;
|
|
426
485
|
overflow-y: auto;
|
|
427
|
-
|
|
428
|
-
border: 1px solid var(--color-border);
|
|
429
|
-
border-radius: 0.75rem;
|
|
430
|
-
padding: 1.5rem;
|
|
486
|
+
overflow-x: hidden;
|
|
431
487
|
}
|
|
432
488
|
|
|
433
489
|
.sidebar::-webkit-scrollbar {
|
|
@@ -435,239 +491,443 @@ const DEFAULT_TEMPLATE = `<!doctype html>
|
|
|
435
491
|
}
|
|
436
492
|
|
|
437
493
|
.sidebar::-webkit-scrollbar-track {
|
|
438
|
-
background:
|
|
494
|
+
background: transparent;
|
|
439
495
|
}
|
|
440
496
|
|
|
441
497
|
.sidebar::-webkit-scrollbar-thumb {
|
|
442
|
-
background: var(--
|
|
498
|
+
background: var(--border-strong);
|
|
443
499
|
border-radius: 3px;
|
|
444
500
|
}
|
|
445
501
|
|
|
446
|
-
.sidebar
|
|
447
|
-
|
|
448
|
-
font-size: 0.875rem;
|
|
449
|
-
text-transform: uppercase;
|
|
450
|
-
letter-spacing: 0.05em;
|
|
451
|
-
color: var(--color-text-muted);
|
|
452
|
-
font-weight: 600;
|
|
502
|
+
.sidebar::-webkit-scrollbar-thumb:hover {
|
|
503
|
+
background: #4a4a4a;
|
|
453
504
|
}
|
|
454
505
|
|
|
455
|
-
.
|
|
456
|
-
|
|
506
|
+
.sidebar-section {
|
|
507
|
+
padding: 24px 16px 16px;
|
|
508
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
457
509
|
}
|
|
458
510
|
|
|
459
|
-
.
|
|
511
|
+
.sidebar-section:last-child {
|
|
512
|
+
border-bottom: none;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.sidebar-title {
|
|
516
|
+
font-size: 11px;
|
|
460
517
|
font-weight: 600;
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
518
|
+
text-transform: uppercase;
|
|
519
|
+
letter-spacing: 0.8px;
|
|
520
|
+
color: var(--text-tertiary);
|
|
521
|
+
margin-bottom: 12px;
|
|
522
|
+
padding: 0 12px;
|
|
464
523
|
}
|
|
465
524
|
|
|
466
|
-
.
|
|
525
|
+
.sidebar-item {
|
|
467
526
|
display: flex;
|
|
468
|
-
|
|
469
|
-
gap:
|
|
527
|
+
align-items: center;
|
|
528
|
+
gap: 10px;
|
|
529
|
+
padding: 9px 12px;
|
|
530
|
+
color: var(--text-secondary);
|
|
531
|
+
text-decoration: none;
|
|
532
|
+
border-radius: var(--radius-sm);
|
|
533
|
+
font-size: 13px;
|
|
534
|
+
font-weight: 500;
|
|
535
|
+
transition: all 0.15s;
|
|
536
|
+
cursor: pointer;
|
|
537
|
+
border: none;
|
|
538
|
+
background: none;
|
|
539
|
+
width: 100%;
|
|
540
|
+
text-align: left;
|
|
541
|
+
margin-bottom: 2px;
|
|
470
542
|
}
|
|
471
543
|
|
|
472
|
-
.
|
|
473
|
-
|
|
474
|
-
color: var(--
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
544
|
+
.sidebar-item:hover {
|
|
545
|
+
background: var(--bg-hover);
|
|
546
|
+
color: var(--text-primary);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
.sidebar-item.active {
|
|
550
|
+
background: var(--bg-active);
|
|
551
|
+
color: var(--text-primary);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.sidebar-icon {
|
|
555
|
+
font-size: 16px;
|
|
556
|
+
opacity: 0.8;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.method-badge-nav {
|
|
560
|
+
display: inline-flex;
|
|
561
|
+
align-items: center;
|
|
562
|
+
justify-content: center;
|
|
563
|
+
width: 45px;
|
|
564
|
+
padding: 2px 6px;
|
|
565
|
+
border-radius: 4px;
|
|
566
|
+
font-size: 9px;
|
|
567
|
+
font-weight: 700;
|
|
568
|
+
font-family: 'JetBrains Mono', monospace;
|
|
569
|
+
letter-spacing: 0.3px;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
.sidebar-item-text {
|
|
573
|
+
flex: 1;
|
|
574
|
+
overflow: hidden;
|
|
575
|
+
text-overflow: ellipsis;
|
|
576
|
+
white-space: nowrap;
|
|
577
|
+
font-size: 12px;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/* Search */
|
|
581
|
+
.search-box {
|
|
582
|
+
padding: 16px;
|
|
583
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
.search-input {
|
|
587
|
+
width: 100%;
|
|
588
|
+
padding: 10px 12px 10px 36px;
|
|
589
|
+
background: var(--bg-tertiary);
|
|
590
|
+
border: 1px solid var(--border-default);
|
|
591
|
+
border-radius: var(--radius-md);
|
|
592
|
+
color: var(--text-primary);
|
|
593
|
+
font-size: 13px;
|
|
594
|
+
font-family: inherit;
|
|
478
595
|
transition: all 0.2s;
|
|
479
|
-
display: block;
|
|
480
596
|
}
|
|
481
597
|
|
|
482
|
-
.
|
|
483
|
-
|
|
484
|
-
color: var(--
|
|
485
|
-
|
|
598
|
+
.search-input:focus {
|
|
599
|
+
outline: none;
|
|
600
|
+
border-color: var(--accent-blue);
|
|
601
|
+
background: var(--bg-elevated);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.search-input::placeholder {
|
|
605
|
+
color: var(--text-tertiary);
|
|
486
606
|
}
|
|
487
607
|
|
|
488
|
-
.
|
|
608
|
+
.search-container {
|
|
609
|
+
position: relative;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.search-icon {
|
|
613
|
+
position: absolute;
|
|
614
|
+
left: 12px;
|
|
615
|
+
top: 50%;
|
|
616
|
+
transform: translateY(-50%);
|
|
617
|
+
color: var(--text-tertiary);
|
|
618
|
+
pointer-events: none;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/* Main Content */
|
|
622
|
+
.main {
|
|
623
|
+
flex: 1;
|
|
624
|
+
padding: 32px;
|
|
489
625
|
min-width: 0;
|
|
626
|
+
background: var(--bg-primary);
|
|
490
627
|
}
|
|
491
628
|
|
|
492
|
-
.
|
|
493
|
-
|
|
629
|
+
.main-header {
|
|
630
|
+
margin-bottom: 32px;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
.main-title {
|
|
634
|
+
font-size: 32px;
|
|
494
635
|
font-weight: 700;
|
|
495
|
-
margin:
|
|
496
|
-
|
|
636
|
+
margin-bottom: 8px;
|
|
637
|
+
background: linear-gradient(135deg, var(--text-primary) 0%, var(--text-secondary) 100%);
|
|
638
|
+
-webkit-background-clip: text;
|
|
639
|
+
-webkit-text-fill-color: transparent;
|
|
640
|
+
background-clip: text;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.main-subtitle {
|
|
644
|
+
font-size: 15px;
|
|
645
|
+
color: var(--text-secondary);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.section {
|
|
649
|
+
margin-bottom: 48px;
|
|
497
650
|
}
|
|
498
651
|
|
|
499
|
-
.
|
|
500
|
-
|
|
652
|
+
.section-title {
|
|
653
|
+
font-size: 24px;
|
|
654
|
+
font-weight: 700;
|
|
655
|
+
margin-bottom: 24px;
|
|
656
|
+
padding-bottom: 12px;
|
|
657
|
+
border-bottom: 1px solid var(--border-default);
|
|
658
|
+
display: flex;
|
|
659
|
+
align-items: center;
|
|
660
|
+
gap: 12px;
|
|
501
661
|
}
|
|
502
662
|
|
|
663
|
+
/* Endpoint Card */
|
|
503
664
|
.endpoint {
|
|
504
|
-
background: var(--
|
|
505
|
-
border: 1px solid var(--
|
|
506
|
-
border-radius:
|
|
507
|
-
margin-bottom:
|
|
665
|
+
background: var(--bg-secondary);
|
|
666
|
+
border: 1px solid var(--border-default);
|
|
667
|
+
border-radius: var(--radius-lg);
|
|
668
|
+
margin-bottom: 16px;
|
|
508
669
|
overflow: hidden;
|
|
509
|
-
transition: all 0.
|
|
670
|
+
transition: all 0.2s;
|
|
510
671
|
}
|
|
511
672
|
|
|
512
673
|
.endpoint:hover {
|
|
513
|
-
border-color: var(--
|
|
674
|
+
border-color: var(--border-strong);
|
|
514
675
|
box-shadow: var(--shadow-md);
|
|
515
676
|
}
|
|
516
677
|
|
|
517
678
|
.endpoint-header {
|
|
518
|
-
padding:
|
|
679
|
+
padding: 20px 24px;
|
|
519
680
|
cursor: pointer;
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
transition: background 0.2s;
|
|
681
|
+
user-select: none;
|
|
682
|
+
background: var(--bg-secondary);
|
|
683
|
+
transition: all 0.2s;
|
|
524
684
|
}
|
|
525
685
|
|
|
526
686
|
.endpoint-header:hover {
|
|
527
|
-
background:
|
|
687
|
+
background: var(--bg-tertiary);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
.endpoint.expanded .endpoint-header {
|
|
691
|
+
background: var(--bg-tertiary);
|
|
692
|
+
border-bottom: 1px solid var(--border-default);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.endpoint-title-row {
|
|
696
|
+
display: flex;
|
|
697
|
+
align-items: center;
|
|
698
|
+
gap: 12px;
|
|
699
|
+
margin-bottom: 8px;
|
|
528
700
|
}
|
|
529
701
|
|
|
530
702
|
.method-badge {
|
|
531
703
|
display: inline-flex;
|
|
532
704
|
align-items: center;
|
|
533
705
|
justify-content: center;
|
|
534
|
-
min-width:
|
|
535
|
-
padding:
|
|
536
|
-
border-radius:
|
|
537
|
-
font-size:
|
|
706
|
+
min-width: 72px;
|
|
707
|
+
padding: 6px 14px;
|
|
708
|
+
border-radius: var(--radius-sm);
|
|
709
|
+
font-size: 11px;
|
|
538
710
|
font-weight: 700;
|
|
711
|
+
font-family: 'JetBrains Mono', monospace;
|
|
539
712
|
text-transform: uppercase;
|
|
540
|
-
letter-spacing: 0.
|
|
713
|
+
letter-spacing: 0.5px;
|
|
541
714
|
}
|
|
542
715
|
|
|
543
|
-
.method-get { background: var(--
|
|
544
|
-
.method-post { background: var(--
|
|
545
|
-
.method-put { background: var(--
|
|
546
|
-
.method-
|
|
547
|
-
.method-
|
|
716
|
+
.method-get { background: var(--accent-green); color: var(--text-inverse); }
|
|
717
|
+
.method-post { background: var(--accent-blue); color: white; }
|
|
718
|
+
.method-put { background: var(--accent-yellow); color: var(--text-inverse); }
|
|
719
|
+
.method-patch { background: var(--accent-purple); color: white; }
|
|
720
|
+
.method-delete { background: var(--accent-red); color: white; }
|
|
548
721
|
|
|
549
722
|
.endpoint-path {
|
|
550
|
-
font-family: "JetBrains Mono", "Fira Code", "Courier New", monospace;
|
|
551
|
-
font-size: 0.9rem;
|
|
552
|
-
color: var(--color-text);
|
|
553
|
-
font-weight: 500;
|
|
554
723
|
flex: 1;
|
|
724
|
+
font-family: 'JetBrains Mono', monospace;
|
|
725
|
+
font-size: 14px;
|
|
726
|
+
font-weight: 500;
|
|
727
|
+
color: var(--text-primary);
|
|
728
|
+
overflow: hidden;
|
|
729
|
+
text-overflow: ellipsis;
|
|
730
|
+
white-space: nowrap;
|
|
555
731
|
}
|
|
556
732
|
|
|
557
733
|
.expand-icon {
|
|
558
|
-
|
|
559
|
-
height: 20px;
|
|
734
|
+
color: var(--text-tertiary);
|
|
560
735
|
transition: transform 0.3s;
|
|
561
|
-
|
|
736
|
+
font-size: 18px;
|
|
562
737
|
}
|
|
563
738
|
|
|
564
739
|
.endpoint.expanded .expand-icon {
|
|
565
740
|
transform: rotate(180deg);
|
|
566
741
|
}
|
|
567
742
|
|
|
743
|
+
.endpoint-summary {
|
|
744
|
+
color: var(--text-secondary);
|
|
745
|
+
font-size: 14px;
|
|
746
|
+
margin: 0;
|
|
747
|
+
line-height: 1.5;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
.endpoint-tags {
|
|
751
|
+
display: flex;
|
|
752
|
+
gap: 8px;
|
|
753
|
+
margin-top: 12px;
|
|
754
|
+
flex-wrap: wrap;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
.tag {
|
|
758
|
+
padding: 4px 10px;
|
|
759
|
+
background: var(--bg-elevated);
|
|
760
|
+
border: 1px solid var(--border-default);
|
|
761
|
+
border-radius: 12px;
|
|
762
|
+
font-size: 11px;
|
|
763
|
+
color: var(--text-secondary);
|
|
764
|
+
font-weight: 500;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/* Endpoint Body */
|
|
568
768
|
.endpoint-body {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
769
|
+
display: none;
|
|
770
|
+
padding: 24px;
|
|
771
|
+
background: var(--bg-tertiary);
|
|
572
772
|
}
|
|
573
773
|
|
|
574
774
|
.endpoint.expanded .endpoint-body {
|
|
575
|
-
|
|
576
|
-
|
|
775
|
+
display: block;
|
|
776
|
+
animation: slideDown 0.3s ease-out;
|
|
577
777
|
}
|
|
578
778
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
779
|
+
@keyframes slideDown {
|
|
780
|
+
from {
|
|
781
|
+
opacity: 0;
|
|
782
|
+
transform: translateY(-8px);
|
|
783
|
+
}
|
|
784
|
+
to {
|
|
785
|
+
opacity: 1;
|
|
786
|
+
transform: translateY(0);
|
|
787
|
+
}
|
|
582
788
|
}
|
|
583
789
|
|
|
584
|
-
.
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
790
|
+
.content-section {
|
|
791
|
+
margin-bottom: 28px;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.content-section:last-child {
|
|
795
|
+
margin-bottom: 0;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
.content-title {
|
|
799
|
+
font-size: 13px;
|
|
800
|
+
font-weight: 600;
|
|
801
|
+
margin-bottom: 16px;
|
|
802
|
+
color: var(--text-primary);
|
|
803
|
+
text-transform: uppercase;
|
|
804
|
+
letter-spacing: 0.5px;
|
|
805
|
+
display: flex;
|
|
806
|
+
align-items: center;
|
|
807
|
+
gap: 8px;
|
|
588
808
|
}
|
|
589
809
|
|
|
590
|
-
.
|
|
591
|
-
color: var(--
|
|
592
|
-
margin: 0
|
|
593
|
-
|
|
810
|
+
.description-text {
|
|
811
|
+
color: var(--text-secondary);
|
|
812
|
+
margin: 0 0 20px;
|
|
813
|
+
line-height: 1.7;
|
|
814
|
+
font-size: 14px;
|
|
594
815
|
}
|
|
595
816
|
|
|
596
|
-
|
|
817
|
+
/* Tabs */
|
|
818
|
+
.tabs {
|
|
597
819
|
display: flex;
|
|
598
|
-
gap:
|
|
599
|
-
|
|
600
|
-
|
|
820
|
+
gap: 4px;
|
|
821
|
+
margin-bottom: 16px;
|
|
822
|
+
background: var(--bg-elevated);
|
|
823
|
+
padding: 4px;
|
|
824
|
+
border-radius: var(--radius-md);
|
|
825
|
+
width: fit-content;
|
|
601
826
|
}
|
|
602
827
|
|
|
603
|
-
.
|
|
604
|
-
padding:
|
|
605
|
-
background:
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
font-size:
|
|
828
|
+
.tab {
|
|
829
|
+
padding: 8px 16px;
|
|
830
|
+
background: transparent;
|
|
831
|
+
border: none;
|
|
832
|
+
cursor: pointer;
|
|
833
|
+
font-size: 13px;
|
|
609
834
|
font-weight: 500;
|
|
835
|
+
color: var(--text-secondary);
|
|
836
|
+
transition: all 0.2s;
|
|
837
|
+
border-radius: var(--radius-sm);
|
|
838
|
+
font-family: inherit;
|
|
610
839
|
}
|
|
611
840
|
|
|
612
|
-
.
|
|
613
|
-
|
|
841
|
+
.tab:hover {
|
|
842
|
+
color: var(--text-primary);
|
|
843
|
+
background: var(--bg-hover);
|
|
614
844
|
}
|
|
615
845
|
|
|
616
|
-
.
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
846
|
+
.tab.active {
|
|
847
|
+
color: var(--text-primary);
|
|
848
|
+
background: var(--bg-secondary);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
.tab-content {
|
|
852
|
+
display: none;
|
|
623
853
|
}
|
|
624
854
|
|
|
855
|
+
.tab-content.active {
|
|
856
|
+
display: block;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/* Code Block */
|
|
625
860
|
.code-block {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
border
|
|
861
|
+
position: relative;
|
|
862
|
+
background: var(--bg-primary);
|
|
863
|
+
border: 1px solid var(--border-default);
|
|
864
|
+
border-radius: var(--radius-md);
|
|
629
865
|
overflow: hidden;
|
|
630
866
|
}
|
|
631
867
|
|
|
632
868
|
.code-header {
|
|
633
869
|
display: flex;
|
|
634
|
-
justify-content: space-between;
|
|
635
870
|
align-items: center;
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
871
|
+
justify-content: space-between;
|
|
872
|
+
padding: 10px 16px;
|
|
873
|
+
background: var(--bg-secondary);
|
|
874
|
+
border-bottom: 1px solid var(--border-default);
|
|
639
875
|
}
|
|
640
876
|
|
|
641
877
|
.code-language {
|
|
642
|
-
font-size:
|
|
643
|
-
color: var(--color-text-muted);
|
|
644
|
-
text-transform: uppercase;
|
|
878
|
+
font-size: 11px;
|
|
645
879
|
font-weight: 600;
|
|
880
|
+
color: var(--text-tertiary);
|
|
881
|
+
text-transform: uppercase;
|
|
882
|
+
letter-spacing: 0.5px;
|
|
883
|
+
font-family: 'JetBrains Mono', monospace;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.code-actions {
|
|
887
|
+
display: flex;
|
|
888
|
+
gap: 8px;
|
|
646
889
|
}
|
|
647
890
|
|
|
648
891
|
.copy-btn {
|
|
649
|
-
padding:
|
|
650
|
-
background: var(--
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
border-radius:
|
|
654
|
-
font-size: 0.75rem;
|
|
892
|
+
padding: 6px 12px;
|
|
893
|
+
background: var(--bg-tertiary);
|
|
894
|
+
border: 1px solid var(--border-default);
|
|
895
|
+
color: var(--text-secondary);
|
|
896
|
+
border-radius: var(--radius-sm);
|
|
655
897
|
cursor: pointer;
|
|
898
|
+
font-size: 11px;
|
|
899
|
+
font-weight: 600;
|
|
656
900
|
transition: all 0.2s;
|
|
901
|
+
font-family: inherit;
|
|
902
|
+
display: flex;
|
|
903
|
+
align-items: center;
|
|
904
|
+
gap: 6px;
|
|
657
905
|
}
|
|
658
906
|
|
|
659
907
|
.copy-btn:hover {
|
|
660
|
-
background: var(--
|
|
908
|
+
background: var(--bg-hover);
|
|
909
|
+
color: var(--text-primary);
|
|
910
|
+
border-color: var(--border-strong);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.copy-btn:active {
|
|
914
|
+
transform: scale(0.95);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
.copy-btn.copied {
|
|
918
|
+
background: var(--accent-green);
|
|
661
919
|
color: white;
|
|
920
|
+
border-color: var(--accent-green);
|
|
662
921
|
}
|
|
663
922
|
|
|
664
923
|
pre {
|
|
665
924
|
margin: 0;
|
|
666
|
-
padding:
|
|
925
|
+
padding: 16px;
|
|
667
926
|
overflow-x: auto;
|
|
668
|
-
font-family:
|
|
669
|
-
font-size:
|
|
927
|
+
font-family: 'JetBrains Mono', monospace;
|
|
928
|
+
font-size: 13px;
|
|
670
929
|
line-height: 1.6;
|
|
930
|
+
color: var(--text-primary);
|
|
671
931
|
}
|
|
672
932
|
|
|
673
933
|
pre::-webkit-scrollbar {
|
|
@@ -675,340 +935,659 @@ const DEFAULT_TEMPLATE = `<!doctype html>
|
|
|
675
935
|
}
|
|
676
936
|
|
|
677
937
|
pre::-webkit-scrollbar-track {
|
|
678
|
-
background: var(--
|
|
938
|
+
background: var(--bg-secondary);
|
|
679
939
|
}
|
|
680
940
|
|
|
681
941
|
pre::-webkit-scrollbar-thumb {
|
|
682
|
-
background: var(--
|
|
942
|
+
background: var(--border-strong);
|
|
683
943
|
border-radius: 4px;
|
|
684
944
|
}
|
|
685
945
|
|
|
686
|
-
|
|
687
|
-
.
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
946
|
+
/* Response Status */
|
|
947
|
+
.response-item {
|
|
948
|
+
margin-bottom: 16px;
|
|
949
|
+
background: var(--bg-elevated);
|
|
950
|
+
border: 1px solid var(--border-default);
|
|
951
|
+
border-radius: var(--radius-md);
|
|
952
|
+
overflow: hidden;
|
|
953
|
+
}
|
|
691
954
|
|
|
692
|
-
.response-status {
|
|
693
|
-
|
|
955
|
+
.response-item.status-2xx { border-left: 3px solid var(--accent-green); }
|
|
956
|
+
.response-item.status-4xx { border-left: 3px solid var(--accent-yellow); }
|
|
957
|
+
.response-item.status-5xx { border-left: 3px solid var(--accent-red); }
|
|
958
|
+
|
|
959
|
+
.response-header {
|
|
960
|
+
display: flex;
|
|
694
961
|
align-items: center;
|
|
695
|
-
gap:
|
|
696
|
-
padding:
|
|
697
|
-
background: var(--
|
|
698
|
-
border-
|
|
699
|
-
margin-bottom: 0.75rem;
|
|
700
|
-
font-family: "JetBrains Mono", monospace;
|
|
701
|
-
font-size: 0.875rem;
|
|
962
|
+
gap: 12px;
|
|
963
|
+
padding: 16px;
|
|
964
|
+
background: var(--bg-secondary);
|
|
965
|
+
border-bottom: 1px solid var(--border-default);
|
|
702
966
|
}
|
|
703
967
|
|
|
704
|
-
.status-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
968
|
+
.status-code {
|
|
969
|
+
font-family: 'JetBrains Mono', monospace;
|
|
970
|
+
font-size: 13px;
|
|
971
|
+
font-weight: 700;
|
|
972
|
+
padding: 4px 10px;
|
|
973
|
+
border-radius: var(--radius-sm);
|
|
974
|
+
background: var(--bg-tertiary);
|
|
975
|
+
}
|
|
708
976
|
|
|
709
|
-
.
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
977
|
+
.status-2xx .status-code { color: var(--accent-green); }
|
|
978
|
+
.status-4xx .status-code { color: var(--accent-yellow); }
|
|
979
|
+
.status-5xx .status-code { color: var(--accent-red); }
|
|
980
|
+
|
|
981
|
+
.response-description {
|
|
982
|
+
color: var(--text-secondary);
|
|
983
|
+
font-size: 14px;
|
|
984
|
+
flex: 1;
|
|
713
985
|
}
|
|
714
986
|
|
|
715
|
-
.
|
|
716
|
-
|
|
717
|
-
border: 1px solid var(--color-border);
|
|
718
|
-
border-radius: 0.75rem;
|
|
719
|
-
padding: 1.5rem;
|
|
720
|
-
margin-bottom: 1rem;
|
|
987
|
+
.response-content {
|
|
988
|
+
padding: 16px;
|
|
721
989
|
}
|
|
722
990
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
991
|
+
/* Schema Section */
|
|
992
|
+
.schema-section {
|
|
993
|
+
background: var(--bg-secondary);
|
|
994
|
+
border: 1px solid var(--border-default);
|
|
995
|
+
border-radius: var(--radius-lg);
|
|
996
|
+
padding: 24px;
|
|
997
|
+
margin-bottom: 20px;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.schema-item {
|
|
1001
|
+
margin-bottom: 32px;
|
|
1002
|
+
padding-bottom: 32px;
|
|
1003
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
729
1004
|
}
|
|
730
1005
|
|
|
731
|
-
.
|
|
732
|
-
margin-
|
|
733
|
-
padding:
|
|
734
|
-
|
|
735
|
-
border: 1px solid rgba(59, 130, 246, 0.2);
|
|
736
|
-
border-radius: 0.5rem;
|
|
1006
|
+
.schema-item:last-child {
|
|
1007
|
+
margin-bottom: 0;
|
|
1008
|
+
padding-bottom: 0;
|
|
1009
|
+
border-bottom: none;
|
|
737
1010
|
}
|
|
738
1011
|
|
|
739
|
-
.
|
|
740
|
-
font-size:
|
|
1012
|
+
.schema-name {
|
|
1013
|
+
font-size: 20px;
|
|
741
1014
|
font-weight: 700;
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
letter-spacing: 0.05em;
|
|
1015
|
+
margin-bottom: 16px;
|
|
1016
|
+
color: var(--text-primary);
|
|
1017
|
+
font-family: 'JetBrains Mono', monospace;
|
|
746
1018
|
}
|
|
747
1019
|
|
|
748
|
-
|
|
1020
|
+
/* Property Table */
|
|
1021
|
+
.property-table {
|
|
749
1022
|
width: 100%;
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
border-radius:
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
border: none;
|
|
765
|
-
border-radius: 0.375rem;
|
|
1023
|
+
border-collapse: collapse;
|
|
1024
|
+
font-size: 13px;
|
|
1025
|
+
background: var(--bg-tertiary);
|
|
1026
|
+
border-radius: var(--radius-md);
|
|
1027
|
+
overflow: hidden;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
.property-table thead {
|
|
1031
|
+
background: var(--bg-elevated);
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
.property-table th {
|
|
1035
|
+
text-align: left;
|
|
1036
|
+
padding: 14px 16px;
|
|
766
1037
|
font-weight: 600;
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
1038
|
+
color: var(--text-primary);
|
|
1039
|
+
font-size: 12px;
|
|
1040
|
+
text-transform: uppercase;
|
|
1041
|
+
letter-spacing: 0.5px;
|
|
1042
|
+
border-bottom: 1px solid var(--border-default);
|
|
770
1043
|
}
|
|
771
1044
|
|
|
772
|
-
.
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
1045
|
+
.property-table td {
|
|
1046
|
+
padding: 14px 16px;
|
|
1047
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
1048
|
+
vertical-align: top;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
.property-table tbody tr:last-child td {
|
|
1052
|
+
border-bottom: none;
|
|
776
1053
|
}
|
|
777
1054
|
|
|
778
|
-
|
|
1055
|
+
.property-table tbody tr:hover {
|
|
1056
|
+
background: var(--bg-elevated);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.property-name {
|
|
1060
|
+
font-family: 'JetBrains Mono', monospace;
|
|
1061
|
+
font-weight: 600;
|
|
1062
|
+
color: var(--text-primary);
|
|
1063
|
+
font-size: 13px;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
.property-type {
|
|
1067
|
+
font-family: 'JetBrains Mono', monospace;
|
|
1068
|
+
color: var(--accent-blue);
|
|
1069
|
+
font-size: 12px;
|
|
1070
|
+
font-weight: 500;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
.required-badge {
|
|
1074
|
+
display: inline-block;
|
|
1075
|
+
padding: 2px 8px;
|
|
1076
|
+
background: var(--accent-red);
|
|
1077
|
+
color: white;
|
|
1078
|
+
border-radius: 4px;
|
|
1079
|
+
font-size: 10px;
|
|
1080
|
+
font-weight: 700;
|
|
1081
|
+
margin-left: 8px;
|
|
1082
|
+
text-transform: uppercase;
|
|
1083
|
+
letter-spacing: 0.3px;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/* Syntax Highlighting */
|
|
1087
|
+
.hljs-string { color: #a5d6ff; }
|
|
1088
|
+
.hljs-number { color: #79c0ff; }
|
|
1089
|
+
.hljs-literal { color: #ff7b72; }
|
|
1090
|
+
.hljs-attr { color: #7ee787; }
|
|
1091
|
+
.hljs-punctuation { color: #e6edf3; }
|
|
1092
|
+
|
|
1093
|
+
/* Utility Classes */
|
|
1094
|
+
.flex { display: flex; }
|
|
1095
|
+
.items-center { align-items: center; }
|
|
1096
|
+
.gap-2 { gap: 8px; }
|
|
1097
|
+
.gap-3 { gap: 12px; }
|
|
1098
|
+
.mb-2 { margin-bottom: 8px; }
|
|
1099
|
+
.mb-4 { margin-bottom: 16px; }
|
|
1100
|
+
|
|
1101
|
+
/* Responsive */
|
|
1102
|
+
@media (max-width: 1200px) {
|
|
779
1103
|
.container {
|
|
780
|
-
|
|
1104
|
+
flex-direction: column;
|
|
781
1105
|
}
|
|
1106
|
+
|
|
782
1107
|
.sidebar {
|
|
1108
|
+
width: 100%;
|
|
1109
|
+
height: auto;
|
|
783
1110
|
position: static;
|
|
784
|
-
|
|
1111
|
+
border-right: none;
|
|
1112
|
+
border-bottom: 1px solid var(--border-default);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
@media (max-width: 768px) {
|
|
1117
|
+
.main {
|
|
1118
|
+
padding: 20px 16px;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
.endpoint-header {
|
|
1122
|
+
padding: 16px;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
.endpoint-body {
|
|
1126
|
+
padding: 16px;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
.method-badge {
|
|
1130
|
+
min-width: 60px;
|
|
1131
|
+
font-size: 10px;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
.endpoint-path {
|
|
1135
|
+
font-size: 12px;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
.header-content {
|
|
1139
|
+
padding: 0 16px;
|
|
785
1140
|
}
|
|
786
1141
|
}
|
|
1142
|
+
|
|
1143
|
+
/* Animations */
|
|
1144
|
+
@keyframes fadeIn {
|
|
1145
|
+
from { opacity: 0; }
|
|
1146
|
+
to { opacity: 1; }
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
.fade-in {
|
|
1150
|
+
animation: fadeIn 0.3s ease-out;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
/* Loading State */
|
|
1154
|
+
.loading {
|
|
1155
|
+
display: flex;
|
|
1156
|
+
align-items: center;
|
|
1157
|
+
justify-content: center;
|
|
1158
|
+
padding: 40px;
|
|
1159
|
+
color: var(--text-tertiary);
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
.spinner {
|
|
1163
|
+
width: 40px;
|
|
1164
|
+
height: 40px;
|
|
1165
|
+
border: 3px solid var(--border-default);
|
|
1166
|
+
border-top-color: var(--accent-blue);
|
|
1167
|
+
border-radius: 50%;
|
|
1168
|
+
animation: spin 0.8s linear infinite;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
@keyframes spin {
|
|
1172
|
+
to { transform: rotate(360deg); }
|
|
1173
|
+
}
|
|
787
1174
|
</style>
|
|
788
1175
|
</head>
|
|
789
1176
|
<body>
|
|
790
|
-
|
|
1177
|
+
<!-- Header -->
|
|
1178
|
+
<header class="header">
|
|
791
1179
|
<div class="header-content">
|
|
792
|
-
<
|
|
793
|
-
|
|
794
|
-
<span class="
|
|
795
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
796
|
-
<path d="M8 1L10.5 6L16 7L12 11L13 16L8 13.5L3 16L4 11L0 7L5.5 6L8 1Z" fill="currentColor"/>
|
|
797
|
-
</svg>
|
|
798
|
-
Version <%= spec.info.version %>
|
|
799
|
-
</span>
|
|
800
|
-
<span class="openapi-badge">OpenAPI 3.0.0</span>
|
|
1180
|
+
<div class="header-brand">
|
|
1181
|
+
<span class="header-logo">🔷</span>
|
|
1182
|
+
<span class="header-title"><%= spec.info.title %></span>
|
|
801
1183
|
</div>
|
|
1184
|
+
<nav class="header-nav">
|
|
1185
|
+
<a href="#" class="header-link active">Docs</a>
|
|
1186
|
+
<a href="#" class="header-link">API</a>
|
|
1187
|
+
<a href="#" class="header-link">GitHub</a>
|
|
1188
|
+
<button class="theme-toggle" onclick="toggleTheme()">☀️</button>
|
|
1189
|
+
</nav>
|
|
802
1190
|
</div>
|
|
803
|
-
</
|
|
804
|
-
|
|
1191
|
+
</header>
|
|
1192
|
+
|
|
1193
|
+
<!-- Main Container -->
|
|
805
1194
|
<div class="container">
|
|
1195
|
+
<!-- Sidebar -->
|
|
806
1196
|
<aside class="sidebar">
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
});
|
|
821
|
-
%>
|
|
1197
|
+
<!-- Search -->
|
|
1198
|
+
<div class="search-box">
|
|
1199
|
+
<div class="search-container">
|
|
1200
|
+
<span class="search-icon">🔍</span>
|
|
1201
|
+
<input
|
|
1202
|
+
type="text"
|
|
1203
|
+
class="search-input"
|
|
1204
|
+
placeholder="Search endpoints..."
|
|
1205
|
+
id="searchInput"
|
|
1206
|
+
oninput="filterEndpoints(this.value)"
|
|
1207
|
+
/>
|
|
1208
|
+
</div>
|
|
1209
|
+
</div>
|
|
822
1210
|
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
1211
|
+
<!-- Navigation -->
|
|
1212
|
+
<div class="sidebar-section">
|
|
1213
|
+
<div class="sidebar-title">Endpoints</div>
|
|
1214
|
+
<% const paths = spec.paths || {}; %>
|
|
1215
|
+
<% Object.entries(paths).forEach(([pathKey, ops]) => { %>
|
|
1216
|
+
<% Object.entries(ops).forEach(([verb, operation]) => { %>
|
|
1217
|
+
<button
|
|
1218
|
+
class="sidebar-item endpoint-nav-item"
|
|
1219
|
+
onclick="scrollToEndpoint('<%= pathKey %>-<%= verb %>')"
|
|
1220
|
+
data-path="<%= pathKey %>"
|
|
1221
|
+
data-method="<%= verb %>"
|
|
1222
|
+
>
|
|
1223
|
+
<span class="method-badge-nav method-<%= verb %>"><%= verb.toUpperCase() %></span>
|
|
1224
|
+
<span class="sidebar-item-text"><%= pathKey %></span>
|
|
1225
|
+
</button>
|
|
1226
|
+
<% }) %>
|
|
1227
|
+
<% }) %>
|
|
1228
|
+
</div>
|
|
1229
|
+
|
|
1230
|
+
<% if (spec.components?.schemas && Object.keys(spec.components.schemas).length > 0) { %>
|
|
1231
|
+
<div class="sidebar-section">
|
|
1232
|
+
<div class="sidebar-title">Schemas</div>
|
|
1233
|
+
<button class="sidebar-item" onclick="scrollToSchemas()">
|
|
1234
|
+
<span class="sidebar-icon">📦</span>
|
|
1235
|
+
<span class="sidebar-item-text">View All Schemas</span>
|
|
1236
|
+
</button>
|
|
833
1237
|
</div>
|
|
834
|
-
<% }
|
|
1238
|
+
<% } %>
|
|
835
1239
|
</aside>
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1240
|
+
|
|
1241
|
+
<!-- Main Content -->
|
|
1242
|
+
<main class="main">
|
|
1243
|
+
<!-- Header -->
|
|
1244
|
+
<div class="main-header">
|
|
1245
|
+
<h1 class="main-title"><%= spec.info.title %></h1>
|
|
1246
|
+
<p class="main-subtitle">Version <%= spec.info.version %> • OpenAPI 3.0.0</p>
|
|
1247
|
+
</div>
|
|
1248
|
+
|
|
1249
|
+
<!-- Endpoints Section -->
|
|
1250
|
+
<section class="section">
|
|
1251
|
+
<h2 class="section-title">
|
|
1252
|
+
<span>📡</span>
|
|
1253
|
+
<span>API Endpoints</span>
|
|
1254
|
+
</h2>
|
|
840
1255
|
|
|
841
1256
|
<% Object.entries(paths).forEach(([pathKey, ops]) => { %>
|
|
842
1257
|
<% Object.entries(ops).forEach(([verb, operation]) => { %>
|
|
843
|
-
<
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
1258
|
+
<article
|
|
1259
|
+
class="endpoint"
|
|
1260
|
+
id="<%= pathKey %>-<%= verb %>"
|
|
1261
|
+
data-path="<%= pathKey %>"
|
|
1262
|
+
data-method="<%= verb %>"
|
|
1263
|
+
>
|
|
1264
|
+
<!-- Endpoint Header -->
|
|
1265
|
+
<header class="endpoint-header" onclick="toggleEndpoint(this)">
|
|
1266
|
+
<div class="endpoint-title-row">
|
|
1267
|
+
<span class="method-badge method-<%= verb %>"><%= verb.toUpperCase() %></span>
|
|
1268
|
+
<code class="endpoint-path"><%= pathKey %></code>
|
|
1269
|
+
<span class="expand-icon">▼</span>
|
|
1270
|
+
</div>
|
|
1271
|
+
|
|
1272
|
+
<% if (operation.summary) { %>
|
|
1273
|
+
<p class="endpoint-summary"><%= operation.summary %></p>
|
|
1274
|
+
<% } %>
|
|
1275
|
+
|
|
1276
|
+
<% if (operation.tags && operation.tags.length > 0) { %>
|
|
1277
|
+
<div class="endpoint-tags">
|
|
1278
|
+
<% operation.tags.forEach(tag => { %>
|
|
1279
|
+
<span class="tag"><%= tag %></span>
|
|
1280
|
+
<% }) %>
|
|
1281
|
+
</div>
|
|
1282
|
+
<% } %>
|
|
1283
|
+
</header>
|
|
851
1284
|
|
|
1285
|
+
<!-- Endpoint Body -->
|
|
852
1286
|
<div class="endpoint-body">
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
<
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1287
|
+
<% if (operation.description) { %>
|
|
1288
|
+
<div class="content-section">
|
|
1289
|
+
<p class="description-text"><%= operation.description %></p>
|
|
1290
|
+
</div>
|
|
1291
|
+
<% } %>
|
|
1292
|
+
|
|
1293
|
+
<!-- Request Body -->
|
|
1294
|
+
<% if (operation.requestBody) { %>
|
|
1295
|
+
<div class="content-section">
|
|
1296
|
+
<h4 class="content-title">
|
|
1297
|
+
<span>📤</span>
|
|
1298
|
+
<span>Request Body</span>
|
|
1299
|
+
</h4>
|
|
1300
|
+
|
|
1301
|
+
<div class="tabs">
|
|
1302
|
+
<button class="tab active" onclick="switchTab(this, 'request-example-<%= pathKey %>-<%= verb %>')">
|
|
1303
|
+
Example
|
|
1304
|
+
</button>
|
|
1305
|
+
<button class="tab" onclick="switchTab(this, 'request-schema-<%= pathKey %>-<%= verb %>')">
|
|
1306
|
+
Schema
|
|
1307
|
+
</button>
|
|
867
1308
|
</div>
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
<% if (operation.requestBody) { %>
|
|
871
|
-
<div class="subsection">
|
|
872
|
-
<div class="subsection-title">Request Body</div>
|
|
1309
|
+
|
|
1310
|
+
<div id="request-example-<%= pathKey %>-<%= verb %>" class="tab-content active">
|
|
873
1311
|
<div class="code-block">
|
|
874
1312
|
<div class="code-header">
|
|
875
1313
|
<span class="code-language">JSON</span>
|
|
876
|
-
<
|
|
1314
|
+
<div class="code-actions">
|
|
1315
|
+
<button class="copy-btn" onclick="copyCode(this)">
|
|
1316
|
+
<span>📋</span>
|
|
1317
|
+
<span>Copy</span>
|
|
1318
|
+
</button>
|
|
1319
|
+
</div>
|
|
1320
|
+
</div>
|
|
1321
|
+
<pre><%= JSON.stringify(operation.requestBody.content?.['application/json']?.example || operation.requestBody, null, 2) %></pre>
|
|
1322
|
+
</div>
|
|
1323
|
+
</div>
|
|
1324
|
+
|
|
1325
|
+
<div id="request-schema-<%= pathKey %>-<%= verb %>" class="tab-content">
|
|
1326
|
+
<div class="code-block">
|
|
1327
|
+
<div class="code-header">
|
|
1328
|
+
<span class="code-language">Schema</span>
|
|
1329
|
+
<div class="code-actions">
|
|
1330
|
+
<button class="copy-btn" onclick="copyCode(this)">
|
|
1331
|
+
<span>📋</span>
|
|
1332
|
+
<span>Copy</span>
|
|
1333
|
+
</button>
|
|
1334
|
+
</div>
|
|
877
1335
|
</div>
|
|
878
|
-
<pre><%=
|
|
1336
|
+
<pre><%= JSON.stringify(operation.requestBody.content?.['application/json']?.schema || {}, null, 2) %></pre>
|
|
879
1337
|
</div>
|
|
880
1338
|
</div>
|
|
881
|
-
|
|
1339
|
+
</div>
|
|
1340
|
+
<% } %>
|
|
1341
|
+
|
|
1342
|
+
<!-- Responses -->
|
|
1343
|
+
<div class="content-section">
|
|
1344
|
+
<h4 class="content-title">
|
|
1345
|
+
<span>📥</span>
|
|
1346
|
+
<span>Responses</span>
|
|
1347
|
+
</h4>
|
|
882
1348
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
<%
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
<span><%=
|
|
1349
|
+
<% const responses = operation.responses || {}; %>
|
|
1350
|
+
<% Object.entries(responses).forEach(([status, response]) => { %>
|
|
1351
|
+
<% const statusClass = status.startsWith('2') ? 'status-2xx' : status.startsWith('4') ? 'status-4xx' : status.startsWith('5') ? 'status-5xx' : ''; %>
|
|
1352
|
+
<div class="response-item <%= statusClass %>">
|
|
1353
|
+
<div class="response-header">
|
|
1354
|
+
<span class="status-code"><%= status %></span>
|
|
1355
|
+
<span class="response-description"><%= response.description || 'Response' %></span>
|
|
889
1356
|
</div>
|
|
1357
|
+
|
|
890
1358
|
<% if (response.content?.['application/json']) { %>
|
|
891
|
-
<div class="
|
|
892
|
-
<div class="
|
|
893
|
-
<
|
|
894
|
-
|
|
1359
|
+
<div class="response-content">
|
|
1360
|
+
<div class="tabs">
|
|
1361
|
+
<button class="tab active" onclick="switchTab(this, 'response-example-<%= pathKey %>-<%= verb %>-<%= status %>')">
|
|
1362
|
+
Example
|
|
1363
|
+
</button>
|
|
1364
|
+
<button class="tab" onclick="switchTab(this, 'response-schema-<%= pathKey %>-<%= verb %>-<%= status %>')">
|
|
1365
|
+
Schema
|
|
1366
|
+
</button>
|
|
1367
|
+
</div>
|
|
1368
|
+
|
|
1369
|
+
<div id="response-example-<%= pathKey %>-<%= verb %>-<%= status %>" class="tab-content active">
|
|
1370
|
+
<div class="code-block">
|
|
1371
|
+
<div class="code-header">
|
|
1372
|
+
<span class="code-language">JSON</span>
|
|
1373
|
+
<div class="code-actions">
|
|
1374
|
+
<button class="copy-btn" onclick="copyCode(this)">
|
|
1375
|
+
<span>📋</span>
|
|
1376
|
+
<span>Copy</span>
|
|
1377
|
+
</button>
|
|
1378
|
+
</div>
|
|
1379
|
+
</div>
|
|
1380
|
+
<pre><%= JSON.stringify(response.content['application/json'].example || {}, null, 2) %></pre>
|
|
1381
|
+
</div>
|
|
1382
|
+
</div>
|
|
1383
|
+
|
|
1384
|
+
<div id="response-schema-<%= pathKey %>-<%= verb %>-<%= status %>" class="tab-content">
|
|
1385
|
+
<div class="code-block">
|
|
1386
|
+
<div class="code-header">
|
|
1387
|
+
<span class="code-language">Schema</span>
|
|
1388
|
+
<div class="code-actions">
|
|
1389
|
+
<button class="copy-btn" onclick="copyCode(this)">
|
|
1390
|
+
<span>📋</span>
|
|
1391
|
+
<span>Copy</span>
|
|
1392
|
+
</button>
|
|
1393
|
+
</div>
|
|
1394
|
+
</div>
|
|
1395
|
+
<pre><%= JSON.stringify(response.content['application/json'].schema || {}, null, 2) %></pre>
|
|
1396
|
+
</div>
|
|
895
1397
|
</div>
|
|
896
|
-
<pre><%= syntaxHighlight(JSON.stringify(response.content['application/json'].example || response.content['application/json'].schema || {}, null, 2)) %></pre>
|
|
897
1398
|
</div>
|
|
898
1399
|
<% } %>
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
<div class="try-it">
|
|
903
|
-
<div class="try-it-title">Try it out</div>
|
|
904
|
-
<input type="text" class="try-it-input" placeholder="Base URL (e.g., http://localhost:3000)" value="http://localhost:3000">
|
|
905
|
-
<button class="try-it-btn" onclick="tryEndpoint(this, '<%= verb %>', '<%= pathKey %>')">Send Request</button>
|
|
906
|
-
</div>
|
|
1400
|
+
</div>
|
|
1401
|
+
<% }) %>
|
|
907
1402
|
</div>
|
|
908
1403
|
</div>
|
|
909
|
-
</
|
|
1404
|
+
</article>
|
|
910
1405
|
<% }) %>
|
|
911
1406
|
<% }) %>
|
|
912
|
-
</
|
|
913
|
-
|
|
1407
|
+
</section>
|
|
1408
|
+
|
|
1409
|
+
<!-- Schemas Section -->
|
|
914
1410
|
<% if (spec.components?.schemas && Object.keys(spec.components.schemas).length > 0) { %>
|
|
915
|
-
<
|
|
916
|
-
<h2 class="section-title">
|
|
917
|
-
|
|
918
|
-
<
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
1411
|
+
<section class="section" id="schemas-section">
|
|
1412
|
+
<h2 class="section-title">
|
|
1413
|
+
<span>📦</span>
|
|
1414
|
+
<span>Data Schemas</span>
|
|
1415
|
+
</h2>
|
|
1416
|
+
|
|
1417
|
+
<div class="schema-section">
|
|
1418
|
+
<% Object.entries(spec.components.schemas).forEach(([schemaName, schema]) => { %>
|
|
1419
|
+
<div class="schema-item">
|
|
1420
|
+
<h3 class="schema-name"><%= schemaName %></h3>
|
|
1421
|
+
|
|
1422
|
+
<% if (schema.properties) { %>
|
|
1423
|
+
<table class="property-table">
|
|
1424
|
+
<thead>
|
|
1425
|
+
<tr>
|
|
1426
|
+
<th>Property</th>
|
|
1427
|
+
<th>Type</th>
|
|
1428
|
+
<th>Description</th>
|
|
1429
|
+
</tr>
|
|
1430
|
+
</thead>
|
|
1431
|
+
<tbody>
|
|
1432
|
+
<% Object.entries(schema.properties).forEach(([propName, propSchema]) => { %>
|
|
1433
|
+
<tr>
|
|
1434
|
+
<td>
|
|
1435
|
+
<span class="property-name"><%= propName %></span>
|
|
1436
|
+
<% if (schema.required && schema.required.includes(propName)) { %>
|
|
1437
|
+
<span class="required-badge">Required</span>
|
|
1438
|
+
<% } %>
|
|
1439
|
+
</td>
|
|
1440
|
+
<td>
|
|
1441
|
+
<span class="property-type"><%= propSchema.type || 'object' %></span>
|
|
1442
|
+
</td>
|
|
1443
|
+
<td class="description-text">
|
|
1444
|
+
<%= propSchema.description || '—' %>
|
|
1445
|
+
</td>
|
|
1446
|
+
</tr>
|
|
1447
|
+
<% }) %>
|
|
1448
|
+
</tbody>
|
|
1449
|
+
</table>
|
|
1450
|
+
<% } else { %>
|
|
1451
|
+
<div class="code-block">
|
|
1452
|
+
<div class="code-header">
|
|
1453
|
+
<span class="code-language">Schema</span>
|
|
1454
|
+
<div class="code-actions">
|
|
1455
|
+
<button class="copy-btn" onclick="copyCode(this)">
|
|
1456
|
+
<span>📋</span>
|
|
1457
|
+
<span>Copy</span>
|
|
1458
|
+
</button>
|
|
1459
|
+
</div>
|
|
1460
|
+
</div>
|
|
1461
|
+
<pre><%= JSON.stringify(schema, null, 2) %></pre>
|
|
1462
|
+
</div>
|
|
1463
|
+
<% } %>
|
|
926
1464
|
</div>
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
</
|
|
1465
|
+
<% }) %>
|
|
1466
|
+
</div>
|
|
1467
|
+
</section>
|
|
930
1468
|
<% } %>
|
|
931
1469
|
</main>
|
|
932
1470
|
</div>
|
|
933
|
-
|
|
1471
|
+
|
|
934
1472
|
<script>
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
1473
|
+
// Toggle endpoint expansion
|
|
1474
|
+
function toggleEndpoint(header) {
|
|
1475
|
+
const endpoint = header.closest('.endpoint');
|
|
1476
|
+
endpoint.classList.toggle('expanded');
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
// Switch between tabs
|
|
1480
|
+
function switchTab(button, targetId) {
|
|
1481
|
+
const tabGroup = button.closest('.tabs');
|
|
1482
|
+
const parent = tabGroup.parentElement;
|
|
1483
|
+
|
|
1484
|
+
// Update tab buttons
|
|
1485
|
+
tabGroup.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
|
|
1486
|
+
button.classList.add('active');
|
|
1487
|
+
|
|
1488
|
+
// Update tab content
|
|
1489
|
+
parent.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
|
|
1490
|
+
document.getElementById(targetId).classList.add('active');
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
// Copy code to clipboard
|
|
947
1494
|
function copyCode(button) {
|
|
948
|
-
const codeBlock = button.closest('.code-block')
|
|
949
|
-
const
|
|
1495
|
+
const codeBlock = button.closest('.code-block');
|
|
1496
|
+
const pre = codeBlock.querySelector('pre');
|
|
1497
|
+
const text = pre.textContent;
|
|
1498
|
+
|
|
950
1499
|
navigator.clipboard.writeText(text).then(() => {
|
|
951
|
-
|
|
952
|
-
|
|
1500
|
+
const textSpan = button.querySelector('span:last-child');
|
|
1501
|
+
const originalText = textSpan.textContent;
|
|
1502
|
+
|
|
1503
|
+
button.classList.add('copied');
|
|
1504
|
+
textSpan.textContent = 'Copied!';
|
|
1505
|
+
|
|
1506
|
+
setTimeout(() => {
|
|
1507
|
+
button.classList.remove('copied');
|
|
1508
|
+
textSpan.textContent = originalText;
|
|
1509
|
+
}, 2000);
|
|
953
1510
|
});
|
|
954
1511
|
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1512
|
+
|
|
1513
|
+
// Scroll to endpoint
|
|
1514
|
+
function scrollToEndpoint(id) {
|
|
1515
|
+
const element = document.getElementById(id);
|
|
1516
|
+
if (element) {
|
|
1517
|
+
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1518
|
+
|
|
1519
|
+
// Highlight the element
|
|
1520
|
+
element.style.animation = 'none';
|
|
1521
|
+
setTimeout(() => {
|
|
1522
|
+
element.style.animation = 'fadeIn 0.5s ease-out';
|
|
1523
|
+
}, 10);
|
|
1524
|
+
|
|
1525
|
+
if (!element.classList.contains('expanded')) {
|
|
1526
|
+
setTimeout(() => {
|
|
1527
|
+
element.querySelector('.endpoint-header').click();
|
|
1528
|
+
}, 300);
|
|
1529
|
+
}
|
|
963
1530
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
headers: {
|
|
972
|
-
'Content-Type': 'application/json'
|
|
973
|
-
}
|
|
974
|
-
});
|
|
975
|
-
|
|
976
|
-
const data = await response.json();
|
|
977
|
-
alert('Response (' + response.status + '):\\n' + JSON.stringify(data, null, 2));
|
|
978
|
-
} catch (error) {
|
|
979
|
-
alert('Error: ' + error.message);
|
|
980
|
-
} finally {
|
|
981
|
-
button.textContent = 'Send Request';
|
|
982
|
-
button.disabled = false;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
// Scroll to schemas section
|
|
1534
|
+
function scrollToSchemas() {
|
|
1535
|
+
const element = document.getElementById('schemas-section');
|
|
1536
|
+
if (element) {
|
|
1537
|
+
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
983
1538
|
}
|
|
984
1539
|
}
|
|
985
|
-
|
|
986
|
-
//
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1540
|
+
|
|
1541
|
+
// Filter endpoints by search
|
|
1542
|
+
function filterEndpoints(query) {
|
|
1543
|
+
const searchTerm = query.toLowerCase().trim();
|
|
1544
|
+
const navItems = document.querySelectorAll('.endpoint-nav-item');
|
|
1545
|
+
const endpoints = document.querySelectorAll('.endpoint');
|
|
1546
|
+
|
|
1547
|
+
navItems.forEach((item, index) => {
|
|
1548
|
+
const path = item.dataset.path.toLowerCase();
|
|
1549
|
+
const method = item.dataset.method.toLowerCase();
|
|
1550
|
+
const match = path.includes(searchTerm) || method.includes(searchTerm);
|
|
1551
|
+
|
|
1552
|
+
item.style.display = match ? 'flex' : 'none';
|
|
1553
|
+
if (endpoints[index]) {
|
|
1554
|
+
endpoints[index].style.display = match ? 'block' : 'none';
|
|
994
1555
|
}
|
|
995
1556
|
});
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
// Theme toggle (placeholder)
|
|
1560
|
+
function toggleTheme() {
|
|
1561
|
+
alert('Theme toggle functionality can be implemented here');
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
// Auto-expand first endpoint on load
|
|
1565
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
1566
|
+
const firstEndpoint = document.querySelector('.endpoint');
|
|
1567
|
+
if (firstEndpoint) {
|
|
1568
|
+
firstEndpoint.classList.add('expanded');
|
|
1569
|
+
}
|
|
1570
|
+
});
|
|
1571
|
+
|
|
1572
|
+
// Keyboard shortcuts
|
|
1573
|
+
document.addEventListener('keydown', (e) => {
|
|
1574
|
+
// Ctrl/Cmd + K to focus search
|
|
1575
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
|
1576
|
+
e.preventDefault();
|
|
1577
|
+
document.getElementById('searchInput').focus();
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
// Escape to clear search
|
|
1581
|
+
if (e.key === 'Escape') {
|
|
1582
|
+
const searchInput = document.getElementById('searchInput');
|
|
1583
|
+
if (searchInput === document.activeElement) {
|
|
1584
|
+
searchInput.value = '';
|
|
1585
|
+
filterEndpoints('');
|
|
1586
|
+
searchInput.blur();
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
996
1589
|
});
|
|
997
1590
|
</script>
|
|
998
|
-
|
|
999
|
-
<%
|
|
1000
|
-
function syntaxHighlight(json) {
|
|
1001
|
-
return json
|
|
1002
|
-
.replace(/&/g, '&')
|
|
1003
|
-
.replace(/</g, '<')
|
|
1004
|
-
.replace(/>/g, '>')
|
|
1005
|
-
.replace(/"([^"]+)":/g, '<span class="json-key">"$1"</span>:')
|
|
1006
|
-
.replace(/: "([^"]*)"/g, ': <span class="json-string">"$1"</span>')
|
|
1007
|
-
.replace(/: (-?\d+\.?\d*)/g, ': <span class="json-number">$1</span>')
|
|
1008
|
-
.replace(/: (true|false)/g, ': <span class="json-boolean">$1</span>')
|
|
1009
|
-
.replace(/: (null)/g, ': <span class="json-null">$1</span>');
|
|
1010
|
-
}
|
|
1011
|
-
%>
|
|
1012
1591
|
</body>
|
|
1013
1592
|
</html>`;
|
|
1014
1593
|
//# sourceMappingURL=doc-generator.js.map
|