@emeryld/rrroutes-contract 2.2.2 → 2.2.3
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/index.cjs +258 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +258 -152
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -489,7 +489,7 @@ var CSS_STYLES = `:root {
|
|
|
489
489
|
|
|
490
490
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
491
491
|
|
|
492
|
-
/* Tag Pastel Palette
|
|
492
|
+
/* Tag Pastel Palette */
|
|
493
493
|
--tag-0-bg: rgba(254, 202, 202, 0.2); --tag-0-fg: #fca5a5; /* Red */
|
|
494
494
|
--tag-1-bg: rgba(253, 230, 138, 0.2); --tag-1-fg: #fcd34d; /* Amber */
|
|
495
495
|
--tag-2-bg: rgba(187, 247, 208, 0.2); --tag-2-fg: #86efac; /* Green */
|
|
@@ -573,28 +573,27 @@ body {
|
|
|
573
573
|
/* New Wrapper for Search and Methods */
|
|
574
574
|
.left-column {
|
|
575
575
|
display: flex;
|
|
576
|
-
flex-direction: column;
|
|
577
|
-
gap: 16px;
|
|
578
|
-
flex-basis: 300px;
|
|
576
|
+
flex-direction: column;
|
|
577
|
+
gap: 16px;
|
|
578
|
+
flex-basis: 300px;
|
|
579
579
|
min-width: 250px;
|
|
580
580
|
}
|
|
581
581
|
|
|
582
582
|
.search-box {
|
|
583
|
-
|
|
584
|
-
width: 100%; /* Make search fill the left-column width */
|
|
583
|
+
width: 100%;
|
|
585
584
|
position: relative;
|
|
586
585
|
}
|
|
587
586
|
|
|
588
587
|
/* Tag Filter Group */
|
|
589
588
|
.filter-group.tag-filters-container {
|
|
590
|
-
flex: 1;
|
|
589
|
+
flex: 1;
|
|
591
590
|
min-width: 200px;
|
|
592
591
|
}
|
|
593
592
|
|
|
594
593
|
/* Method Filter Group */
|
|
595
594
|
.filter-group.method-filters-container {
|
|
596
|
-
/* Stays inside the left-column, no need for 100% basis */
|
|
597
595
|
}
|
|
596
|
+
|
|
598
597
|
.search-input {
|
|
599
598
|
width: 100%;
|
|
600
599
|
background: rgba(2, 6, 23, 0.6);
|
|
@@ -675,14 +674,21 @@ body {
|
|
|
675
674
|
border-color: var(--accent-primary);
|
|
676
675
|
}
|
|
677
676
|
|
|
678
|
-
/*
|
|
679
|
-
.
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
border-
|
|
677
|
+
/* Tag filter pills */
|
|
678
|
+
.tag-filter-pill {
|
|
679
|
+
display: inline-block;
|
|
680
|
+
padding: 3px 8px;
|
|
681
|
+
border-radius: 4px;
|
|
682
|
+
font-size: 11px;
|
|
683
|
+
font-weight: 600;
|
|
684
|
+
background: rgba(30, 41, 59, 0.5);
|
|
685
|
+
color: var(--text-muted);
|
|
686
|
+
border: 1px solid transparent;
|
|
687
|
+
transition: all 0.15s;
|
|
683
688
|
}
|
|
684
|
-
.pill-checkbox.colored-tag
|
|
685
|
-
|
|
689
|
+
.pill-checkbox.colored-tag input:checked + .tag-filter-pill {
|
|
690
|
+
border-color: var(--accent-primary);
|
|
691
|
+
box-shadow: 0 0 0 1px var(--accent-glow);
|
|
686
692
|
}
|
|
687
693
|
|
|
688
694
|
/* Group Jump Links */
|
|
@@ -762,8 +768,8 @@ body {
|
|
|
762
768
|
padding: 12px 16px;
|
|
763
769
|
display: flex;
|
|
764
770
|
align-items: center;
|
|
765
|
-
gap: 12px;
|
|
766
|
-
flex-wrap: wrap;
|
|
771
|
+
gap: 12px;
|
|
772
|
+
flex-wrap: wrap;
|
|
767
773
|
}
|
|
768
774
|
|
|
769
775
|
/* Item 1: Method */
|
|
@@ -784,7 +790,7 @@ body {
|
|
|
784
790
|
.m-PATCH { background: var(--method-patch-bg); color: var(--method-patch); border: 1px solid rgba(45, 212, 191, 0.3); }
|
|
785
791
|
.m-DELETE { background: var(--method-delete-bg); color: var(--method-delete); border: 1px solid rgba(248, 113, 113, 0.3); }
|
|
786
792
|
|
|
787
|
-
/* Item 2: Path
|
|
793
|
+
/* Item 2: Path */
|
|
788
794
|
.path-container {
|
|
789
795
|
font-family: var(--font-mono);
|
|
790
796
|
font-size: 13px;
|
|
@@ -811,7 +817,7 @@ body {
|
|
|
811
817
|
}
|
|
812
818
|
.path-container:hover .copy-icon { opacity: 1; }
|
|
813
819
|
|
|
814
|
-
/* Item 3: Tags
|
|
820
|
+
/* Item 3: Tags */
|
|
815
821
|
.tags-container {
|
|
816
822
|
display: flex;
|
|
817
823
|
align-items: center;
|
|
@@ -881,6 +887,11 @@ body {
|
|
|
881
887
|
}
|
|
882
888
|
.summary-text { font-size: 14px; color: var(--text-main); line-height: 1.5; }
|
|
883
889
|
|
|
890
|
+
.description-text {
|
|
891
|
+
font-size: 12px;
|
|
892
|
+
opacity: 0.7;
|
|
893
|
+
}
|
|
894
|
+
|
|
884
895
|
/* Tables */
|
|
885
896
|
.schema-table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
886
897
|
.schema-table th {
|
|
@@ -896,6 +907,13 @@ body {
|
|
|
896
907
|
.req-true { color: #4ade80; background: rgba(74, 222, 128, 0.1); }
|
|
897
908
|
.req-false { color: #94a3b8; background: rgba(148, 163, 184, 0.1); }
|
|
898
909
|
|
|
910
|
+
.schema-subtitle {
|
|
911
|
+
font-size: 11px;
|
|
912
|
+
font-weight: 600;
|
|
913
|
+
margin-bottom: 4px;
|
|
914
|
+
color: #64748b;
|
|
915
|
+
}
|
|
916
|
+
|
|
899
917
|
.empty-message { text-align: center; padding: 40px; color: var(--text-muted); }
|
|
900
918
|
`;
|
|
901
919
|
var DOCS_JS = `
|
|
@@ -906,7 +924,7 @@ var DOCS_JS = `
|
|
|
906
924
|
} catch(e) { console.error('Failed to parse docs', e); }
|
|
907
925
|
|
|
908
926
|
// State
|
|
909
|
-
|
|
927
|
+
const filters = {
|
|
910
928
|
search: '',
|
|
911
929
|
methods: new Set(),
|
|
912
930
|
tags: new Set()
|
|
@@ -925,14 +943,13 @@ var DOCS_JS = `
|
|
|
925
943
|
// Initialization
|
|
926
944
|
function init() {
|
|
927
945
|
populateFilters();
|
|
928
|
-
render();
|
|
929
946
|
setupGlobalListeners();
|
|
947
|
+
render();
|
|
930
948
|
}
|
|
931
949
|
|
|
932
950
|
// Tag Coloring Logic
|
|
933
951
|
function getTagColorClass(tagName) {
|
|
934
952
|
if (tagName === 'not-implemented') return 'not-implemented';
|
|
935
|
-
// Simple string hash to select color index
|
|
936
953
|
let hash = 0;
|
|
937
954
|
for (let i = 0; i < tagName.length; i++) {
|
|
938
955
|
hash = tagName.charCodeAt(i) + ((hash << 5) - hash);
|
|
@@ -951,55 +968,87 @@ var DOCS_JS = `
|
|
|
951
968
|
}
|
|
952
969
|
|
|
953
970
|
function populateFilters() {
|
|
971
|
+
if (!elMethodFilters || !elTagFilters) return;
|
|
972
|
+
|
|
954
973
|
// Extract unique values
|
|
955
974
|
const allMethods = new Set(leaves.map(l => (l.method || 'GET').toUpperCase()));
|
|
956
975
|
const allTags = new Set(leaves.flatMap(l => (l.cfg && l.cfg.tags) ? l.cfg.tags : []));
|
|
957
976
|
|
|
958
977
|
// Setup Method Checkboxes
|
|
959
978
|
const sortedMethods = Array.from(allMethods).sort();
|
|
960
|
-
elMethodFilters.innerHTML = sortedMethods.map(m =>
|
|
961
|
-
<label class="pill-checkbox">
|
|
962
|
-
<input type="checkbox" value="
|
|
963
|
-
<span
|
|
964
|
-
</label>
|
|
965
|
-
|
|
979
|
+
elMethodFilters.innerHTML = sortedMethods.map(m => (
|
|
980
|
+
'<label class="pill-checkbox">' +
|
|
981
|
+
'<input type="checkbox" value="' + escapeAttr(m) + '" checked>' +
|
|
982
|
+
'<span>' + escapeHtml(m) + '</span>' +
|
|
983
|
+
'</label>'
|
|
984
|
+
)).join('');
|
|
966
985
|
sortedMethods.forEach(m => filters.methods.add(m));
|
|
967
986
|
|
|
968
|
-
//
|
|
987
|
+
// Attach listeners to method checkboxes
|
|
988
|
+
elMethodFilters.querySelectorAll('input[type="checkbox"]').forEach(function(cb) {
|
|
989
|
+
cb.addEventListener('change', updateFilters);
|
|
990
|
+
});
|
|
991
|
+
|
|
992
|
+
// Setup Tag Checkboxes
|
|
969
993
|
if (allTags.size > 0) {
|
|
970
994
|
elTagFilters.innerHTML = Array.from(allTags).sort().map(t => {
|
|
971
995
|
const colorClass = getTagColorClass(t);
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
<
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
\`;
|
|
996
|
+
return (
|
|
997
|
+
'<label class="pill-checkbox colored-tag">' +
|
|
998
|
+
'<input type="checkbox" value="' + escapeAttr(t) + '">' +
|
|
999
|
+
'<span class="tag-filter-pill ' + colorClass + '">' + escapeHtml(t) + '</span>' +
|
|
1000
|
+
'</label>'
|
|
1001
|
+
);
|
|
979
1002
|
}).join('');
|
|
1003
|
+
|
|
1004
|
+
// Attach listeners to tag checkboxes
|
|
1005
|
+
elTagFilters.querySelectorAll('input[type="checkbox"]').forEach(function(cb) {
|
|
1006
|
+
cb.addEventListener('change', updateFilters);
|
|
1007
|
+
});
|
|
980
1008
|
}
|
|
981
1009
|
}
|
|
982
1010
|
|
|
983
|
-
|
|
984
|
-
|
|
1011
|
+
function updateFilters() {
|
|
1012
|
+
if (elSearch) {
|
|
1013
|
+
filters.search = elSearch.value.toLowerCase();
|
|
1014
|
+
}
|
|
1015
|
+
|
|
985
1016
|
filters.methods.clear();
|
|
986
|
-
elMethodFilters
|
|
1017
|
+
if (elMethodFilters) {
|
|
1018
|
+
elMethodFilters.querySelectorAll('input[type="checkbox"]:checked').forEach(function(cb) {
|
|
1019
|
+
filters.methods.add(cb.value);
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
|
|
987
1023
|
filters.tags.clear();
|
|
988
|
-
elTagFilters
|
|
1024
|
+
if (elTagFilters) {
|
|
1025
|
+
elTagFilters.querySelectorAll('input[type="checkbox"]:checked').forEach(function(cb) {
|
|
1026
|
+
filters.tags.add(cb.value);
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
|
|
989
1030
|
render();
|
|
990
1031
|
}
|
|
991
1032
|
|
|
1033
|
+
function setupGlobalListeners() {
|
|
1034
|
+
if (elSearch) {
|
|
1035
|
+
elSearch.addEventListener('input', updateFilters);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
992
1039
|
// Core Render Logic
|
|
993
1040
|
function render() {
|
|
1041
|
+
if (!elRouteList || !elOverview) return;
|
|
1042
|
+
|
|
994
1043
|
// 1. Filter Data
|
|
995
|
-
const filtered = leaves.filter(leaf
|
|
1044
|
+
const filtered = leaves.filter(function(leaf) {
|
|
996
1045
|
const m = (leaf.method || 'GET').toUpperCase();
|
|
997
1046
|
const t = (leaf.cfg && leaf.cfg.tags) ? leaf.cfg.tags : [];
|
|
998
1047
|
const path = (leaf.path || '').toLowerCase();
|
|
999
1048
|
const summary = (leaf.cfg && leaf.cfg.summary || '').toLowerCase();
|
|
1000
1049
|
|
|
1001
1050
|
if (!filters.methods.has(m)) return false;
|
|
1002
|
-
if (filters.tags.size > 0 && !t.some(tag
|
|
1051
|
+
if (filters.tags.size > 0 && !t.some(function(tag) { return filters.tags.has(tag); })) return false;
|
|
1003
1052
|
if (filters.search && !path.includes(filters.search) && !summary.includes(filters.search)) return false;
|
|
1004
1053
|
|
|
1005
1054
|
return true;
|
|
@@ -1013,7 +1062,7 @@ var DOCS_JS = `
|
|
|
1013
1062
|
|
|
1014
1063
|
// 2. Group Data
|
|
1015
1064
|
const groups = {};
|
|
1016
|
-
filtered.forEach(leaf
|
|
1065
|
+
filtered.forEach(function(leaf) {
|
|
1017
1066
|
const gName = (leaf.cfg && leaf.cfg.docsGroup) ? leaf.cfg.docsGroup : 'UNGROUPED';
|
|
1018
1067
|
if (!groups[gName]) groups[gName] = [];
|
|
1019
1068
|
groups[gName].push(leaf);
|
|
@@ -1021,19 +1070,23 @@ var DOCS_JS = `
|
|
|
1021
1070
|
|
|
1022
1071
|
const sortedGroupNames = Object.keys(groups).sort(sortGroups);
|
|
1023
1072
|
|
|
1024
|
-
// 3. Render Overview Chips
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1073
|
+
// 3. Render Overview Chips
|
|
1074
|
+
elOverview.innerHTML = (
|
|
1075
|
+
'<span class="overview-label">JUMP TO:</span>' +
|
|
1076
|
+
sortedGroupNames.map(function(gName) {
|
|
1077
|
+
return (
|
|
1078
|
+
'<a href="#group-' + escapeAttr(gName) + '" ' +
|
|
1079
|
+
'class="group-chip" data-group="' + escapeAttr(gName) + '">' +
|
|
1080
|
+
escapeHtml(gName) +
|
|
1081
|
+
'</a>'
|
|
1082
|
+
);
|
|
1083
|
+
}).join('')
|
|
1084
|
+
);
|
|
1031
1085
|
|
|
1032
1086
|
// 4. Render Groups & Cards
|
|
1033
|
-
const html = sortedGroupNames.map(gName
|
|
1087
|
+
const html = sortedGroupNames.map(function(gName) {
|
|
1034
1088
|
const routes = groups[gName];
|
|
1035
|
-
|
|
1036
|
-
routes.sort((a, b) => {
|
|
1089
|
+
routes.sort(function(a, b) {
|
|
1037
1090
|
const pA = a.path || '';
|
|
1038
1091
|
const pB = b.path || '';
|
|
1039
1092
|
if (pA < pB) return -1;
|
|
@@ -1041,23 +1094,27 @@ var DOCS_JS = `
|
|
|
1041
1094
|
return (a.method || '').localeCompare(b.method || '');
|
|
1042
1095
|
});
|
|
1043
1096
|
|
|
1044
|
-
return
|
|
1045
|
-
<div class="api-group" id="group
|
|
1046
|
-
<div class="group-header">
|
|
1047
|
-
<h2 class="group-title"
|
|
1048
|
-
<div class="group-actions">
|
|
1049
|
-
<button
|
|
1050
|
-
<button
|
|
1051
|
-
</div>
|
|
1052
|
-
</div>
|
|
1053
|
-
<div class="cards-list">
|
|
1054
|
-
|
|
1055
|
-
</div>
|
|
1056
|
-
</div>
|
|
1057
|
-
|
|
1097
|
+
return (
|
|
1098
|
+
'<div class="api-group" id="group-' + escapeAttr(gName) + '">' +
|
|
1099
|
+
'<div class="group-header">' +
|
|
1100
|
+
'<h2 class="group-title">' + escapeHtml(gName) + '</h2>' +
|
|
1101
|
+
'<div class="group-actions">' +
|
|
1102
|
+
'<button type="button" data-group="' + escapeAttr(gName) + '" data-action="expand">Expand All</button>' +
|
|
1103
|
+
'<button type="button" data-group="' + escapeAttr(gName) + '" data-action="collapse">Collapse All</button>' +
|
|
1104
|
+
'</div>' +
|
|
1105
|
+
'</div>' +
|
|
1106
|
+
'<div class="cards-list">' +
|
|
1107
|
+
routes.map(renderCard).join('') +
|
|
1108
|
+
'</div>' +
|
|
1109
|
+
'</div>'
|
|
1110
|
+
);
|
|
1058
1111
|
}).join('');
|
|
1059
1112
|
|
|
1060
1113
|
elRouteList.innerHTML = html;
|
|
1114
|
+
|
|
1115
|
+
// Wire up interactions that depend on rendered DOM
|
|
1116
|
+
wireOverviewInteractions();
|
|
1117
|
+
wireCardInteractions();
|
|
1061
1118
|
}
|
|
1062
1119
|
|
|
1063
1120
|
// Card Renderer
|
|
@@ -1069,35 +1126,33 @@ var DOCS_JS = `
|
|
|
1069
1126
|
const description = cfg.description || '';
|
|
1070
1127
|
const tags = cfg.tags || [];
|
|
1071
1128
|
|
|
1072
|
-
|
|
1073
|
-
const tagBadges = tags.map(t => {
|
|
1129
|
+
const tagBadges = tags.map(function(t) {
|
|
1074
1130
|
const cClass = getTagColorClass(t);
|
|
1075
|
-
return
|
|
1131
|
+
return '<span class="status-badge ' + cClass + '">' + escapeHtml(t) + '</span>';
|
|
1076
1132
|
}).join('');
|
|
1077
1133
|
|
|
1078
|
-
const headerHtml =
|
|
1079
|
-
<div class="card-header">
|
|
1080
|
-
<span class="method-badge m
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
<span class="
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
</div>
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
</div></div>\`;
|
|
1134
|
+
const headerHtml =
|
|
1135
|
+
'<div class="card-header">' +
|
|
1136
|
+
'<span class="method-badge m-' + escapeAttr(method) + '">' + escapeHtml(method) + '</span>' +
|
|
1137
|
+
'<div class="path-container" data-path="' + escapeAttr(path) + '" title="Click to copy path">' +
|
|
1138
|
+
'<span class="path-text">' + escapeHtml(path) + '</span>' +
|
|
1139
|
+
'<span class="copy-icon">\u{1F4CB}</span>' +
|
|
1140
|
+
'</div>' +
|
|
1141
|
+
'<div class="tags-container">' +
|
|
1142
|
+
tagBadges +
|
|
1143
|
+
'</div>' +
|
|
1144
|
+
'<div class="header-spacer"></div>' +
|
|
1145
|
+
'<div class="expand-icon">\u25BC</div>' +
|
|
1146
|
+
'</div>';
|
|
1147
|
+
|
|
1148
|
+
let contentHtml =
|
|
1149
|
+
'<div class="section-block"><div class="summary-text">' +
|
|
1150
|
+
'<strong>' + escapeHtml(summary) + '</strong>' +
|
|
1151
|
+
(description
|
|
1152
|
+
? '<br><span class="description-text">' + escapeHtml(description) + '</span>'
|
|
1153
|
+
: ''
|
|
1154
|
+
) +
|
|
1155
|
+
'</div></div>';
|
|
1101
1156
|
|
|
1102
1157
|
if (cfg.paramsSchema || cfg.querySchema) {
|
|
1103
1158
|
contentHtml += '<div class="section-block"><div class="section-title">Parameters</div>';
|
|
@@ -1107,96 +1162,150 @@ var DOCS_JS = `
|
|
|
1107
1162
|
}
|
|
1108
1163
|
|
|
1109
1164
|
if (cfg.bodySchema) {
|
|
1110
|
-
contentHtml +=
|
|
1111
|
-
<div class="section-block">
|
|
1112
|
-
<div class="section-title">Request Body
|
|
1113
|
-
|
|
1114
|
-
</div>
|
|
1115
|
-
\`;
|
|
1165
|
+
contentHtml +=
|
|
1166
|
+
'<div class="section-block">' +
|
|
1167
|
+
'<div class="section-title">Request Body ' + (cfg.hasBody ? '' : '(Optional)') + '</div>' +
|
|
1168
|
+
renderSchemaTable(cfg.bodySchema) +
|
|
1169
|
+
'</div>';
|
|
1116
1170
|
}
|
|
1117
1171
|
|
|
1118
1172
|
if (cfg.outputSchema) {
|
|
1119
|
-
contentHtml +=
|
|
1120
|
-
<div class="section-block">
|
|
1121
|
-
<div class="section-title">Response Schema</div>
|
|
1122
|
-
|
|
1123
|
-
</div>
|
|
1124
|
-
\`;
|
|
1173
|
+
contentHtml +=
|
|
1174
|
+
'<div class="section-block">' +
|
|
1175
|
+
'<div class="section-title">Response Schema</div>' +
|
|
1176
|
+
renderSchemaTable(cfg.outputSchema) +
|
|
1177
|
+
'</div>';
|
|
1125
1178
|
}
|
|
1126
1179
|
|
|
1127
|
-
return
|
|
1128
|
-
<article class="endpoint-card" data-expanded="false"
|
|
1129
|
-
|
|
1130
|
-
<div class="card-body"
|
|
1131
|
-
|
|
1132
|
-
</div>
|
|
1133
|
-
</article>
|
|
1134
|
-
|
|
1180
|
+
return (
|
|
1181
|
+
'<article class="endpoint-card" data-expanded="false">' +
|
|
1182
|
+
headerHtml +
|
|
1183
|
+
'<div class="card-body">' +
|
|
1184
|
+
contentHtml +
|
|
1185
|
+
'</div>' +
|
|
1186
|
+
'</article>'
|
|
1187
|
+
);
|
|
1135
1188
|
}
|
|
1136
1189
|
|
|
1137
1190
|
function renderSchemaTable(node, title) {
|
|
1138
1191
|
let rows = '';
|
|
1139
1192
|
if (node.kind === 'object' && node.properties) {
|
|
1140
|
-
Object.keys(node.properties).forEach(key
|
|
1193
|
+
Object.keys(node.properties).forEach(function(key) {
|
|
1141
1194
|
const prop = node.properties[key];
|
|
1142
1195
|
const reqClass = prop.optional ? 'req-false' : 'req-true';
|
|
1143
1196
|
const reqText = prop.optional ? 'OPT' : 'REQ';
|
|
1144
|
-
rows +=
|
|
1145
|
-
<tr>
|
|
1146
|
-
<td class="col-name"
|
|
1147
|
-
<td class="col-type"
|
|
1148
|
-
<td><span class="req-badge
|
|
1149
|
-
<td
|
|
1150
|
-
</tr>
|
|
1151
|
-
\`;
|
|
1197
|
+
rows +=
|
|
1198
|
+
'<tr>' +
|
|
1199
|
+
'<td class="col-name">' + escapeHtml(key) + '</td>' +
|
|
1200
|
+
'<td class="col-type">' + escapeHtml(getTypeLabel(prop)) + '</td>' +
|
|
1201
|
+
'<td><span class="req-badge ' + reqClass + '">' + reqText + '</span></td>' +
|
|
1202
|
+
'<td>' + escapeHtml(prop.description || '') + '</td>' +
|
|
1203
|
+
'</tr>';
|
|
1152
1204
|
});
|
|
1153
1205
|
} else {
|
|
1154
|
-
rows =
|
|
1206
|
+
rows = '<tr><td colspan="4">Type: ' + escapeHtml(getTypeLabel(node)) + '</td></tr>';
|
|
1155
1207
|
}
|
|
1156
|
-
return
|
|
1157
|
-
|
|
1158
|
-
<table class="schema-table"
|
|
1159
|
-
|
|
1208
|
+
return (
|
|
1209
|
+
(title ? '<div class="schema-subtitle">' + escapeHtml(title) + '</div>' : '') +
|
|
1210
|
+
'<table class="schema-table">' + rows + '</table>'
|
|
1211
|
+
);
|
|
1160
1212
|
}
|
|
1161
1213
|
|
|
1162
1214
|
function getTypeLabel(node) {
|
|
1163
1215
|
if (!node) return 'any';
|
|
1164
|
-
if (node.kind === 'array') return
|
|
1165
|
-
if (node.enumValues) return
|
|
1216
|
+
if (node.kind === 'array') return getTypeLabel(node.element) + '[]';
|
|
1217
|
+
if (node.enumValues) return 'enum(' + node.enumValues.join('|') + ')';
|
|
1166
1218
|
return node.kind || 'any';
|
|
1167
1219
|
}
|
|
1168
1220
|
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1221
|
+
// Interactions
|
|
1222
|
+
|
|
1223
|
+
function wireOverviewInteractions() {
|
|
1224
|
+
if (!elOverview || !elRouteList) return;
|
|
1225
|
+
|
|
1226
|
+
// group chips
|
|
1227
|
+
elOverview.querySelectorAll('.group-chip').forEach(function(chip) {
|
|
1228
|
+
chip.addEventListener('click', function(e) {
|
|
1229
|
+
e.preventDefault();
|
|
1230
|
+
const gName = chip.getAttribute('data-group');
|
|
1231
|
+
if (gName) scrollToGroup(gName);
|
|
1232
|
+
});
|
|
1233
|
+
});
|
|
1234
|
+
|
|
1235
|
+
// expand/collapse buttons
|
|
1236
|
+
elRouteList.querySelectorAll('.group-actions button').forEach(function(btn) {
|
|
1237
|
+
btn.addEventListener('click', function() {
|
|
1238
|
+
const gName = btn.getAttribute('data-group');
|
|
1239
|
+
const action = btn.getAttribute('data-action');
|
|
1240
|
+
if (!gName || !action) return;
|
|
1241
|
+
toggleGroup(gName, action === 'expand');
|
|
1242
|
+
});
|
|
1243
|
+
});
|
|
1172
1244
|
}
|
|
1173
1245
|
|
|
1174
|
-
|
|
1175
|
-
if (
|
|
1246
|
+
function wireCardInteractions() {
|
|
1247
|
+
if (!elRouteList) return;
|
|
1248
|
+
|
|
1249
|
+
// card expand/collapse
|
|
1250
|
+
elRouteList.querySelectorAll('.endpoint-card').forEach(function(card) {
|
|
1251
|
+
card.addEventListener('click', function(e) {
|
|
1252
|
+
var target = e.target;
|
|
1253
|
+
if (target && target.closest && target.closest('.path-container')) {
|
|
1254
|
+
// handled separately for copy
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
toggleCard(card);
|
|
1258
|
+
});
|
|
1259
|
+
});
|
|
1260
|
+
|
|
1261
|
+
// copy path
|
|
1262
|
+
elRouteList.querySelectorAll('.path-container').forEach(function(pc) {
|
|
1263
|
+
pc.addEventListener('click', function(e) {
|
|
1264
|
+
e.stopPropagation();
|
|
1265
|
+
const text = pc.getAttribute('data-path') || '';
|
|
1266
|
+
copyText(text);
|
|
1267
|
+
});
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
function toggleCard(card) {
|
|
1176
1272
|
const isExpanded = card.getAttribute('data-expanded') === 'true';
|
|
1177
|
-
card.setAttribute('data-expanded', !isExpanded);
|
|
1178
|
-
}
|
|
1273
|
+
card.setAttribute('data-expanded', String(!isExpanded));
|
|
1274
|
+
}
|
|
1179
1275
|
|
|
1180
|
-
|
|
1276
|
+
function toggleGroup(gName, expand) {
|
|
1181
1277
|
const group = document.getElementById('group-' + gName);
|
|
1182
1278
|
if (!group) return;
|
|
1183
|
-
group.querySelectorAll('.endpoint-card').forEach(c
|
|
1184
|
-
|
|
1279
|
+
group.querySelectorAll('.endpoint-card').forEach(function(c) {
|
|
1280
|
+
c.setAttribute('data-expanded', String(!!expand));
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1185
1283
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
navigator.clipboard.writeText(text)
|
|
1189
|
-
|
|
1190
|
-
|
|
1284
|
+
function copyText(text) {
|
|
1285
|
+
if (!navigator.clipboard || !text) return;
|
|
1286
|
+
navigator.clipboard.writeText(text).catch(function() {
|
|
1287
|
+
// ignore
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1191
1290
|
|
|
1192
|
-
|
|
1193
|
-
e.preventDefault();
|
|
1291
|
+
function scrollToGroup(gName) {
|
|
1194
1292
|
const el = document.getElementById('group-' + gName);
|
|
1195
|
-
if(el) window.scrollTo({ top: el.offsetTop - 220, behavior: 'smooth' });
|
|
1293
|
+
if (el) window.scrollTo({ top: el.offsetTop - 220, behavior: 'smooth' });
|
|
1196
1294
|
}
|
|
1197
1295
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1296
|
+
// Escaping helpers
|
|
1297
|
+
function escapeHtml(str) {
|
|
1298
|
+
if (!str && str !== 0) return '';
|
|
1299
|
+
return String(str)
|
|
1300
|
+
.replace(/&/g, '&')
|
|
1301
|
+
.replace(/</g, '<')
|
|
1302
|
+
.replace(/>/g, '>')
|
|
1303
|
+
.replace(/"/g, '"')
|
|
1304
|
+
.replace(/'/g, ''');
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
function escapeAttr(str) {
|
|
1308
|
+
return escapeHtml(str);
|
|
1200
1309
|
}
|
|
1201
1310
|
|
|
1202
1311
|
init();
|
|
@@ -1226,12 +1335,9 @@ function renderLeafDocsHTML(leaves, options = {}) {
|
|
|
1226
1335
|
|
|
1227
1336
|
<div class="controls-container">
|
|
1228
1337
|
<div class="filters-row">
|
|
1229
|
-
|
|
1230
1338
|
<div class="left-column">
|
|
1231
|
-
|
|
1232
1339
|
<div class="filter-group method-filters-container">
|
|
1233
1340
|
<div class="filter-label">Search</div>
|
|
1234
|
-
|
|
1235
1341
|
<div class="search-box">
|
|
1236
1342
|
<span class="search-icon">\u{1F50D}</span>
|
|
1237
1343
|
<input type="text" id="searchInput" class="search-input" placeholder="Filter endpoints...">
|