@jsenv/server 16.1.2 → 16.2.1
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.
- package/dist/client/default_body_4xx_5xx/4xx.html +25 -24
- package/dist/client/route_inspector/route_inspector.html +597 -300
- package/dist/formidable_index/formidable_index.js +4 -4
- package/dist/formidable_index/jsenv_server_node_modules.js +1108 -260
- package/dist/jsenv_server.js +33 -9
- package/dist/ws/ws.js +15 -1
- package/package.json +37 -23
- package/src/cookies/cookie.js +42 -0
- package/src/cookies/cookie_map.js +18 -0
- package/src/interfacing_with_node/from_node_request.js +7 -6
- package/src/router/router.js +5 -3
- package/src/service_controller.js +13 -0
- package/src/services/autoreload_on_server_restart/client/autoreload_on_server_restart.js +25 -24
- package/src/services/open_file/jsenv_service_open_file.js +9 -1
- package/src/services/route_inspector/client/code_block.js +43 -21
- package/src/services/route_inspector/client/route_inspector.html +536 -264
- package/src/start_server.js +1 -1
|
@@ -55,6 +55,10 @@
|
|
|
55
55
|
color: dodgerblue;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
html {
|
|
59
|
+
scrollbar-gutter: stable both-edges;
|
|
60
|
+
}
|
|
61
|
+
|
|
58
62
|
body {
|
|
59
63
|
font-family:
|
|
60
64
|
system-ui,
|
|
@@ -81,32 +85,35 @@
|
|
|
81
85
|
aside {
|
|
82
86
|
width: 250px;
|
|
83
87
|
flex-shrink: 0;
|
|
84
|
-
border-radius: 6px;
|
|
85
|
-
overflow: hidden;
|
|
86
|
-
background: var(--background-color);
|
|
87
88
|
transition:
|
|
88
89
|
width 0.3s ease,
|
|
89
90
|
margin-left 0.3s ease;
|
|
90
|
-
|
|
91
|
-
overflow-y: auto;
|
|
91
|
+
height: 100%;
|
|
92
92
|
margin-right: 20px;
|
|
93
|
-
|
|
94
|
-
padding-left: 10px;
|
|
93
|
+
position: fixed;
|
|
95
94
|
}
|
|
96
95
|
main {
|
|
97
96
|
flex-grow: 1;
|
|
98
97
|
flex-basis: 0;
|
|
99
98
|
min-width: 0;
|
|
100
99
|
transition: margin-left 0.3s ease;
|
|
101
|
-
padding-top:
|
|
100
|
+
padding-top: 20px;
|
|
102
101
|
padding-right: 20px;
|
|
102
|
+
margin-left: 280px;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
.header_row {
|
|
106
106
|
display: flex;
|
|
107
|
-
align-items:
|
|
107
|
+
align-items: flex-start;
|
|
108
108
|
gap: 10px;
|
|
109
109
|
}
|
|
110
|
+
.header_title {
|
|
111
|
+
margin: 0;
|
|
112
|
+
line-height: 1;
|
|
113
|
+
display: flex;
|
|
114
|
+
gap: 10px;
|
|
115
|
+
align-items: center;
|
|
116
|
+
}
|
|
110
117
|
.note_button_open {
|
|
111
118
|
background: none;
|
|
112
119
|
border: none;
|
|
@@ -334,11 +341,58 @@
|
|
|
334
341
|
}
|
|
335
342
|
}
|
|
336
343
|
|
|
337
|
-
.
|
|
344
|
+
.route_container > * {
|
|
338
345
|
margin-top: 20px;
|
|
339
346
|
flex-grow: 1;
|
|
340
347
|
min-width: 0; /* Prevent flexbox from expanding beyond available space */
|
|
341
348
|
}
|
|
349
|
+
.route_group_details {
|
|
350
|
+
margin: 0 0 15px;
|
|
351
|
+
}
|
|
352
|
+
.summary_marker {
|
|
353
|
+
width: 24px;
|
|
354
|
+
height: 24px;
|
|
355
|
+
}
|
|
356
|
+
.route_group_details > summary {
|
|
357
|
+
cursor: pointer;
|
|
358
|
+
list-style: none;
|
|
359
|
+
border-bottom: 1px solid var(--border-color);
|
|
360
|
+
margin-bottom: 7px;
|
|
361
|
+
}
|
|
362
|
+
.route_group_details > summary::marker {
|
|
363
|
+
display: none;
|
|
364
|
+
}
|
|
365
|
+
.route_group_details[open] > summary .summary_marker {
|
|
366
|
+
transform: rotate(180deg);
|
|
367
|
+
}
|
|
368
|
+
.route_group_summary_container {
|
|
369
|
+
display: flex;
|
|
370
|
+
align-items: center;
|
|
371
|
+
padding: 5px;
|
|
372
|
+
}
|
|
373
|
+
.route_group_name {
|
|
374
|
+
display: flex;
|
|
375
|
+
border-radius: 3px;
|
|
376
|
+
font-family: sans-serif;
|
|
377
|
+
font-size: 14px;
|
|
378
|
+
font-weight: 700;
|
|
379
|
+
min-width: 80px;
|
|
380
|
+
padding: 6px 0;
|
|
381
|
+
text-align: center;
|
|
382
|
+
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
|
|
383
|
+
gap: 0.3em;
|
|
384
|
+
}
|
|
385
|
+
.route_group_description {
|
|
386
|
+
margin-left: 8px;
|
|
387
|
+
font-family: monospace;
|
|
388
|
+
font-size: 16px;
|
|
389
|
+
font-weight: 600;
|
|
390
|
+
word-break: break-word;
|
|
391
|
+
margin-top: 0;
|
|
392
|
+
margin-bottom: 0;
|
|
393
|
+
user-select: none;
|
|
394
|
+
}
|
|
395
|
+
|
|
342
396
|
.route_details {
|
|
343
397
|
margin-bottom: 8px;
|
|
344
398
|
box-shadow: 0 0 3px rgba(0, 0, 0, 0.19);
|
|
@@ -355,6 +409,9 @@
|
|
|
355
409
|
.route_details > summary::marker {
|
|
356
410
|
display: none;
|
|
357
411
|
}
|
|
412
|
+
.route_details:open > summary .summary_marker {
|
|
413
|
+
transform: rotate(180deg);
|
|
414
|
+
}
|
|
358
415
|
.route_summary_container {
|
|
359
416
|
display: flex;
|
|
360
417
|
align-items: center;
|
|
@@ -381,25 +438,32 @@
|
|
|
381
438
|
margin-top: 0;
|
|
382
439
|
margin-bottom: 0;
|
|
383
440
|
}
|
|
384
|
-
.route_details[data-method="HEAD"]
|
|
441
|
+
.route_details[data-method="HEAD"],
|
|
442
|
+
.route_group_details[data-method="HEAD"] {
|
|
385
443
|
--method-color: var(--method-head-color);
|
|
386
444
|
}
|
|
387
|
-
.route_details[data-method="OPTIONS"]
|
|
445
|
+
.route_details[data-method="OPTIONS"],
|
|
446
|
+
.route_group_details[data-method="OPTIONS"] {
|
|
388
447
|
--method-color: var(--method-options-color);
|
|
389
448
|
}
|
|
390
|
-
.route_details[data-method="GET"]
|
|
449
|
+
.route_details[data-method="GET"],
|
|
450
|
+
.route_group_details[data-method="GET"] {
|
|
391
451
|
--method-color: var(--method-get-color);
|
|
392
452
|
}
|
|
393
|
-
.route_details[data-method="POST"]
|
|
453
|
+
.route_details[data-method="POST"],
|
|
454
|
+
.route_group_details[data-method="POST"] {
|
|
394
455
|
--method-color: var(--method-post-color);
|
|
395
456
|
}
|
|
396
|
-
.route_details[data-method="PUT"]
|
|
457
|
+
.route_details[data-method="PUT"],
|
|
458
|
+
.route_group_details[data-method="PUT"] {
|
|
397
459
|
--method-color: var(--method-put-color);
|
|
398
460
|
}
|
|
399
|
-
.route_details[data-method="PATCH"]
|
|
461
|
+
.route_details[data-method="PATCH"],
|
|
462
|
+
.route_group_details[data-method="PATCH"] {
|
|
400
463
|
--method-color: var(--method-patch-color);
|
|
401
464
|
}
|
|
402
|
-
.route_details[data-method="DELETE"]
|
|
465
|
+
.route_details[data-method="DELETE"],
|
|
466
|
+
.route_group_details[data-method="DELETE"] {
|
|
403
467
|
--method-color: var(--method-delete-color);
|
|
404
468
|
}
|
|
405
469
|
|
|
@@ -428,10 +492,11 @@
|
|
|
428
492
|
|
|
429
493
|
.filter_container {
|
|
430
494
|
margin-bottom: 20px;
|
|
431
|
-
border-radius: 4px;
|
|
432
495
|
overflow: hidden;
|
|
433
|
-
|
|
496
|
+
overflow-y: auto;
|
|
497
|
+
border-right: 1px solid var(--border-color);
|
|
434
498
|
background: var(--secondary-color);
|
|
499
|
+
height: 100%;
|
|
435
500
|
}
|
|
436
501
|
.filter_container::marker {
|
|
437
502
|
display: none;
|
|
@@ -445,16 +510,23 @@
|
|
|
445
510
|
justify-content: space-between;
|
|
446
511
|
user-select: none;
|
|
447
512
|
}
|
|
448
|
-
.filter:open .
|
|
513
|
+
.filter:open > summary .summary_marker {
|
|
449
514
|
transform: rotate(180deg);
|
|
450
515
|
}
|
|
516
|
+
.summary_text {
|
|
517
|
+
overflow: hidden;
|
|
518
|
+
width: 100%;
|
|
519
|
+
display: block;
|
|
520
|
+
white-space: nowrap;
|
|
521
|
+
text-overflow: ellipsis;
|
|
522
|
+
}
|
|
451
523
|
.filter_list {
|
|
452
524
|
background: var(--background-color);
|
|
453
|
-
border-top: 1px solid var(--border-color);
|
|
454
525
|
overflow: hidden;
|
|
455
526
|
}
|
|
456
527
|
.filter_item {
|
|
457
528
|
margin: 15px;
|
|
529
|
+
margin-left: 0;
|
|
458
530
|
}
|
|
459
531
|
.filter_badge {
|
|
460
532
|
background-color: var(--primary-color);
|
|
@@ -506,7 +578,6 @@
|
|
|
506
578
|
overflow: hidden;
|
|
507
579
|
}
|
|
508
580
|
.filter_text[data-method] {
|
|
509
|
-
border-left: 5px solid var(--method-color);
|
|
510
581
|
padding-left: 4px;
|
|
511
582
|
}
|
|
512
583
|
.filter_text[data-method="all"] {
|
|
@@ -566,33 +637,41 @@
|
|
|
566
637
|
transparent
|
|
567
638
|
);
|
|
568
639
|
}
|
|
640
|
+
|
|
641
|
+
.status_pill {
|
|
642
|
+
display: flex;
|
|
643
|
+
align-self: stretch;
|
|
644
|
+
width: 0.4em;
|
|
645
|
+
}
|
|
569
646
|
</style>
|
|
570
647
|
<div class="container">
|
|
571
648
|
<aside></aside>
|
|
572
649
|
<main>
|
|
573
650
|
<div class="header_row">
|
|
574
|
-
<h1
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
<svg
|
|
581
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
582
|
-
viewBox="0 0 24 24"
|
|
583
|
-
width="24"
|
|
584
|
-
height="24"
|
|
585
|
-
fill="none"
|
|
586
|
-
stroke="currentColor"
|
|
587
|
-
stroke-width="2"
|
|
588
|
-
stroke-linecap="round"
|
|
589
|
-
stroke-linejoin="round"
|
|
651
|
+
<h1 class="header_title">
|
|
652
|
+
Route inspector
|
|
653
|
+
<button
|
|
654
|
+
class="note_button_open"
|
|
655
|
+
aria-label="Show information"
|
|
656
|
+
title="About HTTP Methods"
|
|
590
657
|
>
|
|
591
|
-
<
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
658
|
+
<svg
|
|
659
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
660
|
+
viewBox="0 0 24 24"
|
|
661
|
+
width="24"
|
|
662
|
+
height="24"
|
|
663
|
+
fill="none"
|
|
664
|
+
stroke="currentColor"
|
|
665
|
+
stroke-width="2"
|
|
666
|
+
stroke-linecap="round"
|
|
667
|
+
stroke-linejoin="round"
|
|
668
|
+
>
|
|
669
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
670
|
+
<line x1="12" y1="16" x2="12" y2="12"></line>
|
|
671
|
+
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
|
672
|
+
</svg>
|
|
673
|
+
</button>
|
|
674
|
+
</h1>
|
|
596
675
|
<div style="flex: 1"></div>
|
|
597
676
|
<div class="theme-toggle">
|
|
598
677
|
<button id="theme-toggle-btn" aria-label="Toggle dark/light mode">
|
|
@@ -700,7 +779,7 @@
|
|
|
700
779
|
import { render } from "preact";
|
|
701
780
|
import { html } from "htm/preact";
|
|
702
781
|
import { signal, computed } from "@preact/signals";
|
|
703
|
-
import {
|
|
782
|
+
import { useRef, useCallback } from "preact/hooks";
|
|
704
783
|
|
|
705
784
|
const routesLoadingSignal = signal(false);
|
|
706
785
|
const routeLoadingErrorSignal = signal(null);
|
|
@@ -763,11 +842,18 @@
|
|
|
763
842
|
if (routes.length === 0) {
|
|
764
843
|
return null;
|
|
765
844
|
}
|
|
766
|
-
return html`
|
|
845
|
+
return html`
|
|
846
|
+
<div>
|
|
847
|
+
<${FiltersPanel} routes="${routes}" />
|
|
848
|
+
</div>`;
|
|
767
849
|
};
|
|
768
850
|
|
|
769
851
|
const App = () => {
|
|
770
|
-
return html`
|
|
852
|
+
return html`
|
|
853
|
+
<div>
|
|
854
|
+
<${Toolbox} />
|
|
855
|
+
<${RouteResults} />
|
|
856
|
+
</div>`;
|
|
771
857
|
};
|
|
772
858
|
const ProgressBar = ({ width = "100%", height = 6, loading }) => {
|
|
773
859
|
if (!loading) {
|
|
@@ -776,11 +862,11 @@
|
|
|
776
862
|
return html`
|
|
777
863
|
<div
|
|
778
864
|
class="progress-bar"
|
|
779
|
-
style
|
|
865
|
+
style="${{
|
|
780
866
|
width: typeof Number(width) === "number" ? `${width}px` : width,
|
|
781
867
|
height:
|
|
782
868
|
typeof Number(height) === "number" ? `${height}px` : height,
|
|
783
|
-
}}
|
|
869
|
+
}}"
|
|
784
870
|
>
|
|
785
871
|
<div class="progress-container progress-indeterminate">
|
|
786
872
|
<div class="progress-bar-long"></div>
|
|
@@ -789,19 +875,20 @@
|
|
|
789
875
|
</div>
|
|
790
876
|
`;
|
|
791
877
|
};
|
|
792
|
-
const
|
|
878
|
+
const RouteResults = () => {
|
|
793
879
|
const routes = routesSignal.value;
|
|
794
880
|
const loading = routesLoadingSignal.value;
|
|
795
881
|
const routeLoadingError = routeLoadingErrorSignal.value;
|
|
882
|
+
const [groupBy] = useGroupByUrlStringParam();
|
|
796
883
|
|
|
797
884
|
if (loading) {
|
|
798
|
-
return html`<${ProgressBar} width="150" loading
|
|
885
|
+
return html`<${ProgressBar} width="150" loading="${true}" />`;
|
|
799
886
|
}
|
|
800
887
|
|
|
801
888
|
if (routeLoadingError) {
|
|
802
889
|
return html`<p>
|
|
803
|
-
|
|
804
|
-
|
|
890
|
+
Error loading routes: ${routeLoadingError.message}
|
|
891
|
+
</p>`;
|
|
805
892
|
}
|
|
806
893
|
|
|
807
894
|
if (!routes || routes.length === 0) {
|
|
@@ -809,10 +896,74 @@
|
|
|
809
896
|
}
|
|
810
897
|
|
|
811
898
|
return html`<div class="route_container">
|
|
812
|
-
|
|
899
|
+
${groupBy
|
|
900
|
+
? html`<${RouteGroups} groupBy="${groupBy}" routes="${routes}" />`
|
|
901
|
+
: html`<${RouteList} routes="${routes}" />`}
|
|
902
|
+
</div>`;
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
const RouteGroups = ({ groupBy, routes }) => {
|
|
906
|
+
const groups = {};
|
|
907
|
+
for (const route of routes) {
|
|
908
|
+
const groupKey =
|
|
909
|
+
groupBy === "by_method"
|
|
910
|
+
? route.method
|
|
911
|
+
: route.meta.packageName || NO_PACKAGE_NAME;
|
|
912
|
+
if (!groups[groupKey]) {
|
|
913
|
+
groups[groupKey] = [];
|
|
914
|
+
}
|
|
915
|
+
groups[groupKey].push(route);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
return html`
|
|
919
|
+
<ul style="margin-left: 0; padding: 0">
|
|
920
|
+
<li style="list-style: none; padding: 0;">
|
|
921
|
+
${Object.entries(groups).map(([groupKey, groupRoutes]) => {
|
|
922
|
+
const groupText =
|
|
923
|
+
groupBy === "by_method"
|
|
924
|
+
? html`<span
|
|
925
|
+
style="margin-left: 0.5em; display: inline-flex; gap: 0.5em;"
|
|
926
|
+
>
|
|
927
|
+
<${MethodsStatusPill} methodNames="${[groupKey]}" />
|
|
928
|
+
<span>${groupKey}</span>
|
|
929
|
+
</span>`
|
|
930
|
+
: html`<span>${groupKey}</span>`;
|
|
931
|
+
|
|
932
|
+
return html`
|
|
933
|
+
<details
|
|
934
|
+
class="route_group_details"
|
|
935
|
+
data-method="${groupBy === "by_method"
|
|
936
|
+
? groupKey
|
|
937
|
+
: undefined}"
|
|
938
|
+
>
|
|
939
|
+
<summary>
|
|
940
|
+
<div class="route_group_summary_container">
|
|
941
|
+
<span class="route_group_name">
|
|
942
|
+
${groupBy === "by_method" ? "method" : "package"}:
|
|
943
|
+
${groupText}
|
|
944
|
+
</span>
|
|
945
|
+
<span class="route_group_description">
|
|
946
|
+
<span class="filter_count">
|
|
947
|
+
${groupRoutes.length}
|
|
948
|
+
</span>
|
|
949
|
+
</span>
|
|
950
|
+
<span style="flex: 1"></span>
|
|
951
|
+
<span class="summary_marker">
|
|
952
|
+
<${ArrowDown} />
|
|
953
|
+
</span>
|
|
954
|
+
</div>
|
|
955
|
+
</summary>
|
|
956
|
+
<${RouteList} routes="${groupRoutes}" />
|
|
957
|
+
</details>`;
|
|
958
|
+
})}
|
|
959
|
+
</li>
|
|
960
|
+
</ul>`;
|
|
961
|
+
};
|
|
962
|
+
|
|
963
|
+
const RouteList = ({ routes }) => {
|
|
964
|
+
return html`<div class="route_list">
|
|
813
965
|
${routes.map((route) => html`<${RouteDetails} ...${route} />`)}
|
|
814
|
-
</div
|
|
815
|
-
</div>`;
|
|
966
|
+
</div>`;
|
|
816
967
|
};
|
|
817
968
|
|
|
818
969
|
const documentUrlSignal = signal(window.location.href);
|
|
@@ -891,6 +1042,13 @@
|
|
|
891
1042
|
};
|
|
892
1043
|
}
|
|
893
1044
|
|
|
1045
|
+
const useGroupByUrlStringParam = () => {
|
|
1046
|
+
const availableGroupByValues = ["by_method", "by_package"];
|
|
1047
|
+
return useUrlStringParam("groupBy", {
|
|
1048
|
+
availableValues: availableGroupByValues,
|
|
1049
|
+
});
|
|
1050
|
+
};
|
|
1051
|
+
|
|
894
1052
|
const useMethodUrlStringParam = () => {
|
|
895
1053
|
const availableMethodNames = availableMethodNamesSignal.value;
|
|
896
1054
|
return useUrlStringParam("method", {
|
|
@@ -905,6 +1063,66 @@
|
|
|
905
1063
|
});
|
|
906
1064
|
};
|
|
907
1065
|
|
|
1066
|
+
let Toolbox;
|
|
1067
|
+
groups: {
|
|
1068
|
+
Toolbox = () => {
|
|
1069
|
+
return html``;
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
const StatusPill = ({ children, color }) => {
|
|
1074
|
+
return html`
|
|
1075
|
+
<span
|
|
1076
|
+
class="status_pill"
|
|
1077
|
+
style="${{
|
|
1078
|
+
background: color,
|
|
1079
|
+
}}"
|
|
1080
|
+
>
|
|
1081
|
+
${children}
|
|
1082
|
+
</span>`;
|
|
1083
|
+
};
|
|
1084
|
+
const buildLinearGradient = (colors) => {
|
|
1085
|
+
const percentagePerColor = Math.floor(100 / (colors.length - 1));
|
|
1086
|
+
const gradientSteps = [];
|
|
1087
|
+
let progress = 0;
|
|
1088
|
+
let index = 0;
|
|
1089
|
+
for (const color of colors) {
|
|
1090
|
+
if (index === colors.length - 1) {
|
|
1091
|
+
progress = 100;
|
|
1092
|
+
}
|
|
1093
|
+
gradientSteps.push(`${color} ${progress}%`);
|
|
1094
|
+
progress += percentagePerColor;
|
|
1095
|
+
index++;
|
|
1096
|
+
}
|
|
1097
|
+
const gradient = `linear-gradient(to bottom, ${gradientSteps.join(", ")})`;
|
|
1098
|
+
return gradient;
|
|
1099
|
+
};
|
|
1100
|
+
const MethodsStatusPill = ({ methodNames }) => {
|
|
1101
|
+
if (methodNames.length === 1) {
|
|
1102
|
+
return html`
|
|
1103
|
+
<${StatusPill}
|
|
1104
|
+
color="${getMethodColor(methodNames[0])}"
|
|
1105
|
+
/>
|
|
1106
|
+
`;
|
|
1107
|
+
}
|
|
1108
|
+
const colors = methodNames.map((methodName) =>
|
|
1109
|
+
getMethodColor(methodName),
|
|
1110
|
+
);
|
|
1111
|
+
const linearGradient = buildLinearGradient(colors);
|
|
1112
|
+
return html`
|
|
1113
|
+
<${StatusPill}
|
|
1114
|
+
color="${linearGradient}"
|
|
1115
|
+
/>
|
|
1116
|
+
`;
|
|
1117
|
+
};
|
|
1118
|
+
const getMethodColor = (methodName) => {
|
|
1119
|
+
const bodyStyle = window.getComputedStyle(document.body);
|
|
1120
|
+
const methodColor = bodyStyle.getPropertyValue(
|
|
1121
|
+
`--method-${methodName.toLowerCase()}-color`,
|
|
1122
|
+
);
|
|
1123
|
+
return methodColor;
|
|
1124
|
+
};
|
|
1125
|
+
|
|
908
1126
|
let FiltersPanel;
|
|
909
1127
|
filters: {
|
|
910
1128
|
FiltersPanel = ({ routes }) => {
|
|
@@ -912,57 +1130,81 @@
|
|
|
912
1130
|
<div class="filter_container">
|
|
913
1131
|
<div class="filter_list">
|
|
914
1132
|
<div class="filter_item">
|
|
915
|
-
<${
|
|
1133
|
+
<${GroupSelector} />
|
|
916
1134
|
</div>
|
|
917
1135
|
<div class="filter_item">
|
|
918
|
-
<${
|
|
1136
|
+
<${MethodFilter} routes="${routes}" />
|
|
1137
|
+
</div>
|
|
1138
|
+
<div class="filter_item">
|
|
1139
|
+
<${PackageFilter} routes="${routes}" />
|
|
919
1140
|
</div>
|
|
920
1141
|
</div>
|
|
921
1142
|
</div>
|
|
922
1143
|
`;
|
|
923
1144
|
};
|
|
1145
|
+
|
|
1146
|
+
const GroupSelector = () => {
|
|
1147
|
+
const [groupBy, setGroupBy] = useGroupByUrlStringParam();
|
|
1148
|
+
const label = html`
|
|
1149
|
+
<span>
|
|
1150
|
+
Group: ${groupBy || "none"}
|
|
1151
|
+
</span>`;
|
|
1152
|
+
const options = [
|
|
1153
|
+
{
|
|
1154
|
+
value: "",
|
|
1155
|
+
text: html`
|
|
1156
|
+
<span class="filter_text">
|
|
1157
|
+
none
|
|
1158
|
+
</span>
|
|
1159
|
+
`,
|
|
1160
|
+
selected: !groupBy,
|
|
1161
|
+
},
|
|
1162
|
+
{
|
|
1163
|
+
value: "by_method",
|
|
1164
|
+
text: html`
|
|
1165
|
+
<span class="filter_text">
|
|
1166
|
+
by method
|
|
1167
|
+
</span>
|
|
1168
|
+
`,
|
|
1169
|
+
selected: groupBy === "by_method",
|
|
1170
|
+
},
|
|
1171
|
+
{
|
|
1172
|
+
value: "by_package",
|
|
1173
|
+
text: html`
|
|
1174
|
+
<span class="filter_text">
|
|
1175
|
+
by package
|
|
1176
|
+
</span>
|
|
1177
|
+
`,
|
|
1178
|
+
selected: groupBy === "by_package",
|
|
1179
|
+
},
|
|
1180
|
+
];
|
|
1181
|
+
|
|
1182
|
+
return html`
|
|
1183
|
+
<${FilterSelector}
|
|
1184
|
+
label="${label}"
|
|
1185
|
+
options="${options}"
|
|
1186
|
+
onChange="${(groupByToSelect) => {
|
|
1187
|
+
setGroupBy(groupByToSelect);
|
|
1188
|
+
}}"
|
|
1189
|
+
/>
|
|
1190
|
+
`;
|
|
1191
|
+
};
|
|
924
1192
|
const MethodFilter = ({ routes }) => {
|
|
925
1193
|
const availableMethodNames = availableMethodNamesSignal.value;
|
|
926
1194
|
const availableMethodRepartition = methodRepartitionSignal.value;
|
|
927
1195
|
const [selectedMethod, setSelectedMethod] = useMethodUrlStringParam();
|
|
928
1196
|
|
|
929
|
-
// "all" border image is a combination of available method colors
|
|
930
|
-
const getMethodColor = (methodName) => {
|
|
931
|
-
const bodyStyle = window.getComputedStyle(document.body);
|
|
932
|
-
const methodColor = bodyStyle.getPropertyValue(
|
|
933
|
-
`--method-${methodName.toLowerCase()}-color`,
|
|
934
|
-
);
|
|
935
|
-
return methodColor;
|
|
936
|
-
};
|
|
937
|
-
const percentagePerColor = Math.floor(
|
|
938
|
-
100 / (availableMethodNames.length - 1),
|
|
939
|
-
);
|
|
940
|
-
const gradientSteps = [];
|
|
941
|
-
let progress = 0;
|
|
942
|
-
let index = 0;
|
|
943
|
-
for (const methodName of availableMethodNames) {
|
|
944
|
-
if (index === availableMethodNames.length - 1) {
|
|
945
|
-
progress = 100;
|
|
946
|
-
}
|
|
947
|
-
gradientSteps.push(`${getMethodColor(methodName)} ${progress}%`);
|
|
948
|
-
progress += percentagePerColor;
|
|
949
|
-
index++;
|
|
950
|
-
}
|
|
951
|
-
const gradient = `linear-gradient(to bottom, ${gradientSteps.join(", ")})`;
|
|
952
|
-
|
|
953
1197
|
const options = [
|
|
954
1198
|
{
|
|
955
1199
|
value: "",
|
|
956
1200
|
text: html`
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
>
|
|
965
|
-
<span class="filter_count">${routes.length}</span>
|
|
1201
|
+
<${MethodsStatusPill}
|
|
1202
|
+
methodNames="${availableMethodNames}"
|
|
1203
|
+
/>
|
|
1204
|
+
<span class="filter_text" data-method="all">all</span>
|
|
1205
|
+
<span class="filter_count">
|
|
1206
|
+
${routes.length}
|
|
1207
|
+
</span>
|
|
966
1208
|
`,
|
|
967
1209
|
selected: !selectedMethod,
|
|
968
1210
|
},
|
|
@@ -970,8 +1212,14 @@
|
|
|
970
1212
|
return {
|
|
971
1213
|
value: availableMethodName,
|
|
972
1214
|
text: html`
|
|
973
|
-
|
|
974
|
-
|
|
1215
|
+
<${MethodsStatusPill}
|
|
1216
|
+
methodNames="${[availableMethodName]}"
|
|
1217
|
+
/>
|
|
1218
|
+
<span
|
|
1219
|
+
class="filter_text"
|
|
1220
|
+
data-method="${availableMethodName}"
|
|
1221
|
+
>
|
|
1222
|
+
${availableMethodName}
|
|
975
1223
|
</span>
|
|
976
1224
|
<span class="filter_count">
|
|
977
1225
|
${availableMethodRepartition[availableMethodName]}
|
|
@@ -982,13 +1230,24 @@
|
|
|
982
1230
|
}),
|
|
983
1231
|
];
|
|
984
1232
|
|
|
1233
|
+
const label = html`<span
|
|
1234
|
+
style="display: flex; align-items: center; gap: 5px"
|
|
1235
|
+
>
|
|
1236
|
+
<${MethodsStatusPill}
|
|
1237
|
+
methodNames="${selectedMethod
|
|
1238
|
+
? [selectedMethod]
|
|
1239
|
+
: availableMethodNames}"
|
|
1240
|
+
/>
|
|
1241
|
+
<span>Methods: ${selectedMethod || "all"}</span>
|
|
1242
|
+
</span>`;
|
|
1243
|
+
|
|
985
1244
|
return html`
|
|
986
1245
|
<${FilterSelector}
|
|
987
|
-
label="
|
|
988
|
-
options
|
|
989
|
-
onChange
|
|
1246
|
+
label="${label}"
|
|
1247
|
+
options="${options}"
|
|
1248
|
+
onChange="${(methodToSelect) => {
|
|
990
1249
|
setSelectedMethod(methodToSelect);
|
|
991
|
-
}}
|
|
1250
|
+
}}"
|
|
992
1251
|
/>
|
|
993
1252
|
`;
|
|
994
1253
|
};
|
|
@@ -1020,13 +1279,20 @@
|
|
|
1020
1279
|
};
|
|
1021
1280
|
}),
|
|
1022
1281
|
];
|
|
1282
|
+
|
|
1283
|
+
const label = html`
|
|
1284
|
+
<span>
|
|
1285
|
+
Packages: ${selectedPackageName || "all"}
|
|
1286
|
+
</span>
|
|
1287
|
+
`;
|
|
1288
|
+
|
|
1023
1289
|
return html`
|
|
1024
1290
|
<${FilterSelector}
|
|
1025
|
-
label="
|
|
1026
|
-
options
|
|
1027
|
-
onChange
|
|
1291
|
+
label="${label}"
|
|
1292
|
+
options="${options}"
|
|
1293
|
+
onChange="${(packageNameToSelect) => {
|
|
1028
1294
|
setSelectedPackageName(packageNameToSelect);
|
|
1029
|
-
}}
|
|
1295
|
+
}}"
|
|
1030
1296
|
/>
|
|
1031
1297
|
`;
|
|
1032
1298
|
};
|
|
@@ -1041,66 +1307,68 @@
|
|
|
1041
1307
|
|
|
1042
1308
|
return html`<details open class="filter">
|
|
1043
1309
|
<summary class="filter_summary">
|
|
1044
|
-
|
|
1045
|
-
|
|
1310
|
+
<span class="summary_text">${label}</span>
|
|
1311
|
+
<span class="summary_marker">
|
|
1312
|
+
<${ArrowDown} />
|
|
1313
|
+
</span>
|
|
1046
1314
|
</summary>
|
|
1047
1315
|
<form ref=${formRef} class="filter_form">
|
|
1048
1316
|
${options.map((option) => {
|
|
1049
1317
|
return html`<label>
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1318
|
+
<input
|
|
1319
|
+
type="${multiple ? "checkbox" : "radio"}"
|
|
1320
|
+
name="${label}"
|
|
1321
|
+
checked="${option.selected}"
|
|
1322
|
+
value="${option.value}"
|
|
1323
|
+
onChange="${multiple
|
|
1324
|
+
? () => {
|
|
1325
|
+
const formNode = formRef.current;
|
|
1326
|
+
// even if we create a checkbox list the HTML spec
|
|
1327
|
+
// return a radio node list and we have to gather the checked values
|
|
1328
|
+
const radioNodeList = formNode.elements[label];
|
|
1329
|
+
const selectedValues = [];
|
|
1330
|
+
for (const checkboxNode of Array.from(
|
|
1331
|
+
radioNodeList,
|
|
1332
|
+
)) {
|
|
1333
|
+
if (checkboxNode.checked) {
|
|
1334
|
+
selectedValues.push(checkboxNode.value);
|
|
1335
|
+
}
|
|
1067
1336
|
}
|
|
1337
|
+
onChange(selectedValues);
|
|
1068
1338
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
${option.text}
|
|
1079
|
-
</label>`;
|
|
1339
|
+
: () => {
|
|
1340
|
+
const formNode = formRef.current;
|
|
1341
|
+
const radioNodeList = formNode.elements[label];
|
|
1342
|
+
const selectedValue = radioNodeList.value;
|
|
1343
|
+
onChange(selectedValue);
|
|
1344
|
+
}}"
|
|
1345
|
+
/>
|
|
1346
|
+
${option.text}
|
|
1347
|
+
</label>`;
|
|
1080
1348
|
})}
|
|
1081
1349
|
</form>
|
|
1082
1350
|
${
|
|
1083
1351
|
actions &&
|
|
1084
1352
|
html` <div class="filter_actions">
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1353
|
+
<button
|
|
1354
|
+
type="button"
|
|
1355
|
+
class="filter_button"
|
|
1356
|
+
onClick="${() => {
|
|
1357
|
+
onChange(options.map((option) => option.value));
|
|
1358
|
+
}}"
|
|
1359
|
+
>
|
|
1360
|
+
Select All
|
|
1361
|
+
</button>
|
|
1362
|
+
<button
|
|
1363
|
+
type="button"
|
|
1364
|
+
class="filter_button"
|
|
1365
|
+
onClick="${() => {
|
|
1366
|
+
onChange([]);
|
|
1367
|
+
}}"
|
|
1368
|
+
>
|
|
1369
|
+
Clear All
|
|
1370
|
+
</button>
|
|
1371
|
+
</div>`
|
|
1104
1372
|
}
|
|
1105
1373
|
</div>`;
|
|
1106
1374
|
};
|
|
@@ -1120,7 +1388,6 @@
|
|
|
1120
1388
|
clientCodeExample,
|
|
1121
1389
|
declarationSource,
|
|
1122
1390
|
}) => {
|
|
1123
|
-
const [opened, setOpened] = useState(false);
|
|
1124
1391
|
const [selectedMethod] = useUrlStringParam("method");
|
|
1125
1392
|
const [selectedPackageName] = usePackageUrlStringParam();
|
|
1126
1393
|
|
|
@@ -1132,37 +1399,38 @@
|
|
|
1132
1399
|
return null;
|
|
1133
1400
|
}
|
|
1134
1401
|
|
|
1135
|
-
return html`<details
|
|
1136
|
-
|
|
1137
|
-
onToggle=${(e) => {
|
|
1138
|
-
setOpened(e.newState === "open");
|
|
1139
|
-
}}
|
|
1140
|
-
data-method=${method}
|
|
1141
|
-
>
|
|
1142
|
-
<summary>
|
|
1143
|
-
<div class="route_summary_container">
|
|
1402
|
+
return html`<details class="route_details" data-method="${method}">
|
|
1403
|
+
<summary class="route_summary_container">
|
|
1144
1404
|
<span class="route_method">${method}</span>
|
|
1145
1405
|
<p class="route_resource">${resource}</p>
|
|
1406
|
+
${method === "GET"
|
|
1407
|
+
? html`<a
|
|
1408
|
+
style="display:inline-flex; margin-left: 5px;"
|
|
1409
|
+
href="${resource}"
|
|
1410
|
+
><${OpenLink}
|
|
1411
|
+
/></a>`
|
|
1412
|
+
: null}
|
|
1146
1413
|
<span style="flex:1"></span>
|
|
1147
|
-
<${RouteBadge} meta
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1414
|
+
<${RouteBadge} meta="${meta}" />
|
|
1415
|
+
<span class="summary_marker">
|
|
1416
|
+
<${ArrowDown} />
|
|
1417
|
+
</span>
|
|
1418
|
+
</summary>
|
|
1419
|
+
<${RouteDetailsContent}
|
|
1420
|
+
method="${method}"
|
|
1421
|
+
resource="${resource}"
|
|
1422
|
+
description="${description}"
|
|
1423
|
+
availableMediaTypes="${availableMediaTypes}"
|
|
1424
|
+
availableLanguages="${availableLanguages}"
|
|
1425
|
+
availableVersions="${availableVersions}"
|
|
1426
|
+
availableEncodings="${availableEncodings}"
|
|
1427
|
+
acceptedMediaTypes="${acceptedMediaTypes}"
|
|
1428
|
+
websocket="${websocket}"
|
|
1429
|
+
clientCodeExample="${clientCodeExample}"
|
|
1430
|
+
declarationSource="${declarationSource}"
|
|
1431
|
+
meta="${meta}"
|
|
1432
|
+
/>
|
|
1433
|
+
</details>`;
|
|
1166
1434
|
};
|
|
1167
1435
|
|
|
1168
1436
|
const RouteBadge = ({ meta }) => {
|
|
@@ -1171,9 +1439,9 @@
|
|
|
1171
1439
|
}
|
|
1172
1440
|
let text = meta.packageName;
|
|
1173
1441
|
let title = `This endpoint is declared by ${meta.packageName}`;
|
|
1174
|
-
return html`<span title
|
|
1175
|
-
|
|
1176
|
-
|
|
1442
|
+
return html`<span title="${title}" class="route_owner_name"
|
|
1443
|
+
>${text}</span
|
|
1444
|
+
>`;
|
|
1177
1445
|
};
|
|
1178
1446
|
|
|
1179
1447
|
const RouteDetailsContent = ({
|
|
@@ -1191,51 +1459,51 @@
|
|
|
1191
1459
|
meta,
|
|
1192
1460
|
}) => {
|
|
1193
1461
|
return html`<div class="route_details_content">
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1462
|
+
<${RoutedeclarationSource}
|
|
1463
|
+
meta="${meta}"
|
|
1464
|
+
declarationSource="${declarationSource}"
|
|
1465
|
+
/>
|
|
1466
|
+
<p style="margin-top: 0"><strong>Description:</strong></p>
|
|
1467
|
+
<p class="route_description">
|
|
1468
|
+
${description || "No description available"}
|
|
1469
|
+
</p>
|
|
1470
|
+
${availableMediaTypes.length > 0 &&
|
|
1471
|
+
html`<${RouteContentNegotiationSection}
|
|
1472
|
+
type="content-type"
|
|
1473
|
+
title="Available media types"
|
|
1474
|
+
availableValues="${availableMediaTypes}"
|
|
1475
|
+
/>`}
|
|
1476
|
+
${availableLanguages.length > 0 &&
|
|
1477
|
+
html`<${RouteContentNegotiationSection}
|
|
1478
|
+
type="language"
|
|
1479
|
+
title="Available languages"
|
|
1480
|
+
availableValues="${availableLanguages}"
|
|
1481
|
+
/>`}
|
|
1482
|
+
${availableVersions.length > 0 &&
|
|
1483
|
+
html`<${RouteContentNegotiationSection}
|
|
1484
|
+
type="version"
|
|
1485
|
+
title="Available versions"
|
|
1486
|
+
availableValues="${availableVersions}"
|
|
1487
|
+
/>`}
|
|
1488
|
+
${availableEncodings.length > 0 &&
|
|
1489
|
+
html`<${RouteContentNegotiationSection}
|
|
1490
|
+
type="encoding"
|
|
1491
|
+
title="Available encodings"
|
|
1492
|
+
availableValues="${availableEncodings}"
|
|
1493
|
+
/>`}
|
|
1494
|
+
${acceptedMediaTypes.length > 0 &&
|
|
1495
|
+
html`<${RouteAcceptableContentSection}
|
|
1496
|
+
acceptedMediaTypes="${acceptedMediaTypes}"
|
|
1497
|
+
/>`}
|
|
1498
|
+
<p style="margin-bottom:0; font-weight:bold">Example:</p>
|
|
1499
|
+
<${RouteCodeExample}
|
|
1500
|
+
method="${method}"
|
|
1501
|
+
resource="${resource}"
|
|
1502
|
+
availableMediaTypes="${availableMediaTypes}"
|
|
1503
|
+
websocket="${websocket}"
|
|
1504
|
+
clientCodeExample="${clientCodeExample}"
|
|
1505
|
+
/>
|
|
1506
|
+
</div>`;
|
|
1239
1507
|
};
|
|
1240
1508
|
const RoutedeclarationSource = ({ meta, declarationSource }) => {
|
|
1241
1509
|
if (!declarationSource) {
|
|
@@ -1244,8 +1512,8 @@
|
|
|
1244
1512
|
return html`<p style="margin-top: 0"><strong>Declaration:</strong></p>
|
|
1245
1513
|
<p>
|
|
1246
1514
|
<${RouteDeclarationText}
|
|
1247
|
-
ownerLink
|
|
1248
|
-
declarationLink
|
|
1515
|
+
ownerLink="${meta.ownerLink}"
|
|
1516
|
+
declarationLink="${meta.declarationLink}"
|
|
1249
1517
|
/>
|
|
1250
1518
|
</p>`;
|
|
1251
1519
|
};
|
|
@@ -1259,23 +1527,23 @@
|
|
|
1259
1527
|
availableValues,
|
|
1260
1528
|
}) => {
|
|
1261
1529
|
return html`<div class="route_content_nego" data-nego-type="${type}">
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1530
|
+
<p class="route_content_nego_title">${title}:</p>
|
|
1531
|
+
<ul>
|
|
1532
|
+
${availableValues.map(
|
|
1533
|
+
(availableValue) => html`<li>${availableValue}</li>`,
|
|
1534
|
+
)}
|
|
1535
|
+
</ul>
|
|
1536
|
+
</div>`;
|
|
1269
1537
|
};
|
|
1270
1538
|
const RouteAcceptableContentSection = ({ acceptedMediaTypes }) => {
|
|
1271
1539
|
return html`<div class="route_accepted_content_type">
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1540
|
+
<p><strong>Accepted content types:</strong></p>
|
|
1541
|
+
<ul>
|
|
1542
|
+
${acceptedMediaTypes.map(
|
|
1543
|
+
(acceptedMediaType) => html`<li>${acceptedMediaType}</li>`,
|
|
1544
|
+
)}
|
|
1545
|
+
</ul>
|
|
1546
|
+
</div>`;
|
|
1279
1547
|
};
|
|
1280
1548
|
|
|
1281
1549
|
const RouteCodeExample = ({
|
|
@@ -1327,33 +1595,37 @@
|
|
|
1327
1595
|
}
|
|
1328
1596
|
|
|
1329
1597
|
return html`<code-block lang="js" data-escaped data-copy-button
|
|
1330
|
-
|
|
1331
|
-
|
|
1598
|
+
>${jsSource}</code-block
|
|
1599
|
+
>`;
|
|
1332
1600
|
};
|
|
1333
1601
|
|
|
1334
|
-
const ArrowDown = () => {
|
|
1602
|
+
const ArrowDown = ({ width = 24, height = 24 }) => {
|
|
1335
1603
|
return html`<svg
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
</svg>`;
|
|
1604
|
+
viewBox="0 -960 960 960"
|
|
1605
|
+
width="${width}"
|
|
1606
|
+
height="${height}"
|
|
1607
|
+
fill="currentColor"
|
|
1608
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1609
|
+
>
|
|
1610
|
+
<path d="M480-345 240-585l56-56 184 184 184-184 56 56-240 240Z" />
|
|
1611
|
+
</svg>`;
|
|
1345
1612
|
};
|
|
1346
|
-
const
|
|
1613
|
+
const OpenLink = () => {
|
|
1347
1614
|
return html`<svg
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1615
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1616
|
+
viewBox="0 0 64 64"
|
|
1617
|
+
stroke-width="3"
|
|
1618
|
+
stroke="currentColor"
|
|
1619
|
+
fill="none"
|
|
1620
|
+
width="24"
|
|
1621
|
+
height="24"
|
|
1622
|
+
>
|
|
1623
|
+
<path
|
|
1624
|
+
d="M55.4,32V53.58a1.81,1.81,0,0,1-1.82,1.82H10.42A1.81,1.81,0,0,1,8.6,53.58V10.42A1.81,1.81,0,0,1,10.42,8.6H32"
|
|
1625
|
+
/>
|
|
1626
|
+
<polyline points="40.32 8.6 55.4 8.6 55.4 24.18" />
|
|
1627
|
+
<line x1="19.32" y1="45.72" x2="54.61" y2="8.91" />
|
|
1628
|
+
</svg>`;
|
|
1357
1629
|
};
|
|
1358
1630
|
|
|
1359
1631
|
render(html`<${Sidebar} />`, document.querySelector("aside"));
|