@emeryld/rrroutes-export 1.0.18 → 1.0.19
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/package.json +1 -1
- package/tools/finalized-leaves-viewer.html +545 -150
package/package.json
CHANGED
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
|
|
25
25
|
body {
|
|
26
26
|
margin: 0;
|
|
27
|
-
font-family:
|
|
27
|
+
font-family:
|
|
28
|
+
'Iosevka Web', 'SFMono-Regular', Menlo, Consolas, monospace;
|
|
28
29
|
color: var(--text);
|
|
29
30
|
background: var(--bg);
|
|
30
31
|
}
|
|
@@ -61,7 +62,10 @@
|
|
|
61
62
|
.primary-row {
|
|
62
63
|
display: grid;
|
|
63
64
|
gap: 10px;
|
|
64
|
-
grid-template-columns: minmax(220px, 0.9fr) minmax(300px, 1.4fr) minmax(
|
|
65
|
+
grid-template-columns: minmax(220px, 0.9fr) minmax(300px, 1.4fr) minmax(
|
|
66
|
+
220px,
|
|
67
|
+
1fr
|
|
68
|
+
);
|
|
65
69
|
align-items: end;
|
|
66
70
|
}
|
|
67
71
|
|
|
@@ -374,6 +378,31 @@
|
|
|
374
378
|
gap: 4px;
|
|
375
379
|
}
|
|
376
380
|
|
|
381
|
+
.changelog-diff-line {
|
|
382
|
+
display: flex;
|
|
383
|
+
flex-wrap: wrap;
|
|
384
|
+
gap: 6px;
|
|
385
|
+
align-items: baseline;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.changelog-op.added {
|
|
389
|
+
font-weight: 700;
|
|
390
|
+
color: var(--ok);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.changelog-op.changed {
|
|
394
|
+
font-weight: 700;
|
|
395
|
+
color: var(--accent);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.changelog-op.removed {
|
|
399
|
+
color: var(--danger);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.changelog-schema-type {
|
|
403
|
+
color: var(--schema-accent);
|
|
404
|
+
}
|
|
405
|
+
|
|
377
406
|
.schema-block {
|
|
378
407
|
border-top: 1px solid var(--border);
|
|
379
408
|
padding: 8px 0 2px;
|
|
@@ -497,15 +526,29 @@
|
|
|
497
526
|
</label>
|
|
498
527
|
<label class="control-block">
|
|
499
528
|
<span class="control-label">Search text</span>
|
|
500
|
-
<input
|
|
529
|
+
<input
|
|
530
|
+
id="searchInput"
|
|
531
|
+
type="text"
|
|
532
|
+
placeholder="Type to search..."
|
|
533
|
+
/>
|
|
501
534
|
</label>
|
|
502
535
|
<div class="control-block">
|
|
503
536
|
<span class="control-label">Quick filters</span>
|
|
504
537
|
<div class="quick-toggles">
|
|
505
|
-
<button
|
|
538
|
+
<button
|
|
539
|
+
id="caseSensitive"
|
|
540
|
+
class="pill-toggle"
|
|
541
|
+
type="button"
|
|
542
|
+
aria-pressed="false"
|
|
543
|
+
>
|
|
506
544
|
Case sensitive
|
|
507
545
|
</button>
|
|
508
|
-
<button
|
|
546
|
+
<button
|
|
547
|
+
id="regexSearch"
|
|
548
|
+
class="pill-toggle"
|
|
549
|
+
type="button"
|
|
550
|
+
aria-pressed="false"
|
|
551
|
+
>
|
|
509
552
|
Regex
|
|
510
553
|
</button>
|
|
511
554
|
</div>
|
|
@@ -514,11 +557,21 @@
|
|
|
514
557
|
|
|
515
558
|
<div class="scope-row">
|
|
516
559
|
<div class="scope-actions">
|
|
517
|
-
<button id="selectAllFields" class="scope-action" type="button">
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
<button id="
|
|
521
|
-
|
|
560
|
+
<button id="selectAllFields" class="scope-action" type="button">
|
|
561
|
+
All
|
|
562
|
+
</button>
|
|
563
|
+
<button id="clearAllFields" class="scope-action" type="button">
|
|
564
|
+
None
|
|
565
|
+
</button>
|
|
566
|
+
<button id="coreFields" class="scope-action" type="button">
|
|
567
|
+
Core
|
|
568
|
+
</button>
|
|
569
|
+
<button id="schemasOnlyFields" class="scope-action" type="button">
|
|
570
|
+
Schema
|
|
571
|
+
</button>
|
|
572
|
+
<button id="sourceOnlyFields" class="scope-action" type="button">
|
|
573
|
+
Source
|
|
574
|
+
</button>
|
|
522
575
|
</div>
|
|
523
576
|
<div id="fieldChipGroups" class="scope-groups"></div>
|
|
524
577
|
</div>
|
|
@@ -549,10 +602,20 @@
|
|
|
549
602
|
<div class="scope-group">
|
|
550
603
|
<div class="scope-group-title">Views</div>
|
|
551
604
|
<div class="scope-group-chips">
|
|
552
|
-
<button
|
|
605
|
+
<button
|
|
606
|
+
id="tabLeaves"
|
|
607
|
+
class="field-chip"
|
|
608
|
+
type="button"
|
|
609
|
+
aria-pressed="true"
|
|
610
|
+
>
|
|
553
611
|
Leaves
|
|
554
612
|
</button>
|
|
555
|
-
<button
|
|
613
|
+
<button
|
|
614
|
+
id="tabChangelog"
|
|
615
|
+
class="field-chip"
|
|
616
|
+
type="button"
|
|
617
|
+
aria-pressed="false"
|
|
618
|
+
>
|
|
556
619
|
Changelog
|
|
557
620
|
</button>
|
|
558
621
|
</div>
|
|
@@ -564,7 +627,10 @@
|
|
|
564
627
|
<div id="activeFilterChips" class="chips filters"></div>
|
|
565
628
|
</div>
|
|
566
629
|
|
|
567
|
-
<div id="status" class="meta">
|
|
630
|
+
<div id="status" class="meta">
|
|
631
|
+
Load a leaves export, changelog export, or unified bundle JSON to
|
|
632
|
+
begin.
|
|
633
|
+
</div>
|
|
568
634
|
</div>
|
|
569
635
|
|
|
570
636
|
<div id="results"></div>
|
|
@@ -582,10 +648,22 @@
|
|
|
582
648
|
label: 'description',
|
|
583
649
|
get: (leaf) => [leaf.cfg?.description],
|
|
584
650
|
},
|
|
585
|
-
{
|
|
651
|
+
{
|
|
652
|
+
id: 'docsGroup',
|
|
653
|
+
label: 'docsGroup',
|
|
654
|
+
get: (leaf) => [leaf.cfg?.docsGroup],
|
|
655
|
+
},
|
|
586
656
|
{ id: 'tags', label: 'tags', get: (leaf) => leaf.cfg?.tags || [] },
|
|
587
|
-
{
|
|
588
|
-
|
|
657
|
+
{
|
|
658
|
+
id: 'stability',
|
|
659
|
+
label: 'stability',
|
|
660
|
+
get: (leaf) => [leaf.cfg?.stability],
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
id: 'docsMeta',
|
|
664
|
+
label: 'docsMeta',
|
|
665
|
+
get: (leaf) => [leaf.cfg?.docsMeta],
|
|
666
|
+
},
|
|
589
667
|
{
|
|
590
668
|
id: 'sourceDefinition',
|
|
591
669
|
label: 'source definition',
|
|
@@ -614,7 +692,8 @@
|
|
|
614
692
|
{
|
|
615
693
|
id: 'types',
|
|
616
694
|
label: 'types',
|
|
617
|
-
get: (leaf, schemaFlatByLeaf) =>
|
|
695
|
+
get: (leaf, schemaFlatByLeaf) =>
|
|
696
|
+
schemaTypeTokens(schemaFlatByLeaf?.[leaf.key]),
|
|
618
697
|
},
|
|
619
698
|
{
|
|
620
699
|
id: 'params',
|
|
@@ -704,23 +783,23 @@
|
|
|
704
783
|
{
|
|
705
784
|
id: 'core',
|
|
706
785
|
label: 'Core fields',
|
|
707
|
-
fieldIds: SEARCH_FIELDS.filter((field) =>
|
|
708
|
-
(field
|
|
709
|
-
),
|
|
786
|
+
fieldIds: SEARCH_FIELDS.filter((field) =>
|
|
787
|
+
CORE_FIELD_IDS.has(field.id),
|
|
788
|
+
).map((field) => field.id),
|
|
710
789
|
},
|
|
711
790
|
{
|
|
712
791
|
id: 'schema',
|
|
713
792
|
label: 'Schema fields',
|
|
714
|
-
fieldIds: SEARCH_FIELDS.filter((field) =>
|
|
715
|
-
(field
|
|
716
|
-
),
|
|
793
|
+
fieldIds: SEARCH_FIELDS.filter((field) =>
|
|
794
|
+
SCHEMA_SCOPE_FIELD_IDS.has(field.id),
|
|
795
|
+
).map((field) => field.id),
|
|
717
796
|
},
|
|
718
797
|
{
|
|
719
798
|
id: 'source',
|
|
720
799
|
label: 'Source fields',
|
|
721
|
-
fieldIds: SEARCH_FIELDS.filter((field) =>
|
|
722
|
-
(field
|
|
723
|
-
),
|
|
800
|
+
fieldIds: SEARCH_FIELDS.filter((field) =>
|
|
801
|
+
SOURCE_FIELD_IDS.has(field.id),
|
|
802
|
+
).map((field) => field.id),
|
|
724
803
|
},
|
|
725
804
|
]
|
|
726
805
|
|
|
@@ -757,7 +836,9 @@
|
|
|
757
836
|
},
|
|
758
837
|
[VIEW_IDS.changelog]: {
|
|
759
838
|
fieldDefs: CHANGELOG_TIMELINE_FIELDS,
|
|
760
|
-
defaultSelected: new Set(
|
|
839
|
+
defaultSelected: new Set(
|
|
840
|
+
CHANGELOG_TIMELINE_FIELDS.map((field) => field.id),
|
|
841
|
+
),
|
|
761
842
|
},
|
|
762
843
|
}
|
|
763
844
|
|
|
@@ -770,8 +851,12 @@
|
|
|
770
851
|
viewerMode: VIEWER_MODE.leaves,
|
|
771
852
|
availableTabs: new Set([VIEW_IDS.leaves]),
|
|
772
853
|
selectedFieldIdsByTab: {
|
|
773
|
-
[VIEW_IDS.leaves]: new Set(
|
|
774
|
-
|
|
854
|
+
[VIEW_IDS.leaves]: new Set(
|
|
855
|
+
TAB_CONFIG[VIEW_IDS.leaves].defaultSelected,
|
|
856
|
+
),
|
|
857
|
+
[VIEW_IDS.changelog]: new Set(
|
|
858
|
+
TAB_CONFIG[VIEW_IDS.changelog].defaultSelected,
|
|
859
|
+
),
|
|
775
860
|
},
|
|
776
861
|
}
|
|
777
862
|
|
|
@@ -780,7 +865,9 @@
|
|
|
780
865
|
const caseSensitiveToggle = document.getElementById('caseSensitive')
|
|
781
866
|
const regexSearchToggle = document.getElementById('regexSearch')
|
|
782
867
|
const typeMatchModeInput = document.getElementById('typeMatchMode')
|
|
783
|
-
const schemaRowsMatchOnlyToggle = document.getElementById(
|
|
868
|
+
const schemaRowsMatchOnlyToggle = document.getElementById(
|
|
869
|
+
'schemaRowsMatchOnly',
|
|
870
|
+
)
|
|
784
871
|
const fieldChipGroups = document.getElementById('fieldChipGroups')
|
|
785
872
|
const activeFilterChips = document.getElementById('activeFilterChips')
|
|
786
873
|
const selectAllFieldsBtn = document.getElementById('selectAllFields')
|
|
@@ -807,7 +894,9 @@
|
|
|
807
894
|
}
|
|
808
895
|
|
|
809
896
|
function applyViewerModeMeta() {
|
|
810
|
-
const meta =
|
|
897
|
+
const meta =
|
|
898
|
+
VIEWER_MODE_META[state.viewerMode] ||
|
|
899
|
+
VIEWER_MODE_META[VIEWER_MODE.leaves]
|
|
811
900
|
document.title = meta.title
|
|
812
901
|
if (viewerHeadingEl) viewerHeadingEl.textContent = meta.heading
|
|
813
902
|
}
|
|
@@ -919,7 +1008,8 @@
|
|
|
919
1008
|
function toTokens(value) {
|
|
920
1009
|
if (value === null || value === undefined) return []
|
|
921
1010
|
if (typeof value === 'string') return [value]
|
|
922
|
-
if (typeof value === 'number' || typeof value === 'boolean')
|
|
1011
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
1012
|
+
return [String(value)]
|
|
923
1013
|
if (Array.isArray(value)) return value.flatMap((item) => toTokens(item))
|
|
924
1014
|
if (typeof value === 'object') return [JSON.stringify(value)]
|
|
925
1015
|
return []
|
|
@@ -958,7 +1048,8 @@
|
|
|
958
1048
|
function schemaSectionToSearchTokens(flatSchema, sectionName) {
|
|
959
1049
|
if (!flatSchema || typeof flatSchema !== 'object') return []
|
|
960
1050
|
const sectionEntries = Object.entries(flatSchema).filter(
|
|
961
|
-
([path]) =>
|
|
1051
|
+
([path]) =>
|
|
1052
|
+
path === sectionName || path.startsWith(`${sectionName}.`),
|
|
962
1053
|
)
|
|
963
1054
|
|
|
964
1055
|
if (sectionEntries.length === 0) return []
|
|
@@ -1006,12 +1097,20 @@
|
|
|
1006
1097
|
return Array.from(tokens)
|
|
1007
1098
|
}
|
|
1008
1099
|
|
|
1009
|
-
function schemaEntryMatchesActiveFilter(
|
|
1100
|
+
function schemaEntryMatchesActiveFilter(
|
|
1101
|
+
sectionName,
|
|
1102
|
+
fullPath,
|
|
1103
|
+
info,
|
|
1104
|
+
engine,
|
|
1105
|
+
selectedIds,
|
|
1106
|
+
) {
|
|
1010
1107
|
if (!engine.active) return true
|
|
1011
1108
|
|
|
1012
1109
|
let matched = false
|
|
1013
1110
|
if (selectedIds.includes(sectionName)) {
|
|
1014
|
-
matched = schemaEntryTokens(fullPath, info).some((token) =>
|
|
1111
|
+
matched = schemaEntryTokens(fullPath, info).some((token) =>
|
|
1112
|
+
engine.test(token),
|
|
1113
|
+
)
|
|
1015
1114
|
}
|
|
1016
1115
|
|
|
1017
1116
|
if (!matched && selectedIds.includes('types')) {
|
|
@@ -1025,7 +1124,9 @@
|
|
|
1025
1124
|
}
|
|
1026
1125
|
|
|
1027
1126
|
if (typeMatchModeInput.value === 'exact' && !engine.regex) {
|
|
1028
|
-
const needle = engine.caseSensitive
|
|
1127
|
+
const needle = engine.caseSensitive
|
|
1128
|
+
? engine.query
|
|
1129
|
+
: engine.query.toLowerCase()
|
|
1029
1130
|
const normalized = engine.caseSensitive
|
|
1030
1131
|
? typeTokens
|
|
1031
1132
|
: typeTokens.map((token) => token.toLowerCase())
|
|
@@ -1047,8 +1148,14 @@
|
|
|
1047
1148
|
return SEARCH_FIELDS.some((field) => {
|
|
1048
1149
|
if (!selectedIds.includes(field.id)) return false
|
|
1049
1150
|
const tokens = toTokens(field.get(leaf, schemaFlatByLeaf, payload))
|
|
1050
|
-
if (
|
|
1051
|
-
|
|
1151
|
+
if (
|
|
1152
|
+
field.id === 'types' &&
|
|
1153
|
+
typeMatchModeInput.value === 'exact' &&
|
|
1154
|
+
!engine.regex
|
|
1155
|
+
) {
|
|
1156
|
+
const needle = engine.caseSensitive
|
|
1157
|
+
? engine.query
|
|
1158
|
+
: engine.query.toLowerCase()
|
|
1052
1159
|
const normalized = engine.caseSensitive
|
|
1053
1160
|
? tokens
|
|
1054
1161
|
: tokens.map((token) => String(token).toLowerCase())
|
|
@@ -1086,14 +1193,25 @@
|
|
|
1086
1193
|
}
|
|
1087
1194
|
|
|
1088
1195
|
function setHighlighted(node, text, engine, selectedIds, fieldIds) {
|
|
1089
|
-
node.innerHTML = highlightWithFieldScope(
|
|
1196
|
+
node.innerHTML = highlightWithFieldScope(
|
|
1197
|
+
text,
|
|
1198
|
+
engine,
|
|
1199
|
+
selectedIds,
|
|
1200
|
+
fieldIds,
|
|
1201
|
+
)
|
|
1090
1202
|
}
|
|
1091
1203
|
|
|
1092
1204
|
function kv(key, value, engine, selectedIds, fieldIds) {
|
|
1093
1205
|
const box = el('div', 'kv')
|
|
1094
1206
|
box.appendChild(el('div', 'k', key))
|
|
1095
1207
|
const valueNode = el('div', 'v mono')
|
|
1096
|
-
setHighlighted(
|
|
1208
|
+
setHighlighted(
|
|
1209
|
+
valueNode,
|
|
1210
|
+
value === undefined ? '—' : String(value),
|
|
1211
|
+
engine,
|
|
1212
|
+
selectedIds,
|
|
1213
|
+
fieldIds,
|
|
1214
|
+
)
|
|
1097
1215
|
box.appendChild(valueNode)
|
|
1098
1216
|
return box
|
|
1099
1217
|
}
|
|
@@ -1158,7 +1276,12 @@
|
|
|
1158
1276
|
link.href = href
|
|
1159
1277
|
link.target = '_blank'
|
|
1160
1278
|
link.rel = 'noopener noreferrer'
|
|
1161
|
-
link.innerHTML = highlightWithFieldScope(
|
|
1279
|
+
link.innerHTML = highlightWithFieldScope(
|
|
1280
|
+
label,
|
|
1281
|
+
engine,
|
|
1282
|
+
selectedIds,
|
|
1283
|
+
fieldIds,
|
|
1284
|
+
)
|
|
1162
1285
|
labelNode.appendChild(link)
|
|
1163
1286
|
box.appendChild(labelNode)
|
|
1164
1287
|
return box
|
|
@@ -1194,7 +1317,11 @@
|
|
|
1194
1317
|
|
|
1195
1318
|
function getSchemaSource(source, sectionName) {
|
|
1196
1319
|
const schemaKey = SCHEMA_SOURCE_KEYS_BY_SECTION[sectionName]
|
|
1197
|
-
if (
|
|
1320
|
+
if (
|
|
1321
|
+
!schemaKey ||
|
|
1322
|
+
!source?.schemas ||
|
|
1323
|
+
typeof source.schemas !== 'object'
|
|
1324
|
+
) {
|
|
1198
1325
|
return {
|
|
1199
1326
|
schemaKey,
|
|
1200
1327
|
sourceValue: undefined,
|
|
@@ -1208,8 +1335,11 @@
|
|
|
1208
1335
|
}
|
|
1209
1336
|
|
|
1210
1337
|
function resolveSchemaSourceLabel(schemaKey, sourceValue) {
|
|
1211
|
-
if (!sourceValue || typeof sourceValue !== 'object')
|
|
1212
|
-
|
|
1338
|
+
if (!sourceValue || typeof sourceValue !== 'object')
|
|
1339
|
+
return schemaKey || 'schema'
|
|
1340
|
+
return (
|
|
1341
|
+
sourceValue.sourceName || sourceValue.tag || schemaKey || 'schema'
|
|
1342
|
+
)
|
|
1213
1343
|
}
|
|
1214
1344
|
|
|
1215
1345
|
function createTreeNode(name = '') {
|
|
@@ -1226,7 +1356,10 @@
|
|
|
1226
1356
|
Object.entries(entries)
|
|
1227
1357
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
1228
1358
|
.forEach(([fullPath, info]) => {
|
|
1229
|
-
const trimmed =
|
|
1359
|
+
const trimmed =
|
|
1360
|
+
fullPath === sectionName
|
|
1361
|
+
? ''
|
|
1362
|
+
: fullPath.slice(sectionName.length + 1)
|
|
1230
1363
|
const segments = trimmed ? trimmed.split('.') : []
|
|
1231
1364
|
|
|
1232
1365
|
let current = root
|
|
@@ -1268,10 +1401,13 @@
|
|
|
1268
1401
|
|
|
1269
1402
|
const appendTypeCell = (row, info) => {
|
|
1270
1403
|
const type = el('span', 'tree-pill')
|
|
1271
|
-
setHighlighted(
|
|
1272
|
-
|
|
1273
|
-
'
|
|
1274
|
-
|
|
1404
|
+
setHighlighted(
|
|
1405
|
+
type,
|
|
1406
|
+
info?.type || info?.kind || '—',
|
|
1407
|
+
engine,
|
|
1408
|
+
selectedIds,
|
|
1409
|
+
[sectionName, 'types'],
|
|
1410
|
+
)
|
|
1275
1411
|
row.appendChild(type)
|
|
1276
1412
|
}
|
|
1277
1413
|
|
|
@@ -1292,7 +1428,13 @@
|
|
|
1292
1428
|
.sort((a, b) => a.localeCompare(b))
|
|
1293
1429
|
.forEach((key) =>
|
|
1294
1430
|
container.appendChild(
|
|
1295
|
-
renderTreeNode(
|
|
1431
|
+
renderTreeNode(
|
|
1432
|
+
node.children[key],
|
|
1433
|
+
engine,
|
|
1434
|
+
selectedIds,
|
|
1435
|
+
sectionName,
|
|
1436
|
+
false,
|
|
1437
|
+
),
|
|
1296
1438
|
),
|
|
1297
1439
|
)
|
|
1298
1440
|
details.appendChild(container)
|
|
@@ -1313,7 +1455,8 @@
|
|
|
1313
1455
|
|
|
1314
1456
|
const grouped = splitFlatSchemaBySection(flatSchema)
|
|
1315
1457
|
let hasAnySchemaEntries = false
|
|
1316
|
-
const limitToMatchedRows =
|
|
1458
|
+
const limitToMatchedRows =
|
|
1459
|
+
isPressed(schemaRowsMatchOnlyToggle) && engine.active
|
|
1317
1460
|
|
|
1318
1461
|
SCHEMA_SECTIONS.forEach((sectionName) => {
|
|
1319
1462
|
const rawEntries = grouped[sectionName]
|
|
@@ -1322,7 +1465,13 @@
|
|
|
1322
1465
|
const entries = limitToMatchedRows
|
|
1323
1466
|
? Object.fromEntries(
|
|
1324
1467
|
Object.entries(rawEntries).filter(([fullPath, info]) =>
|
|
1325
|
-
schemaEntryMatchesActiveFilter(
|
|
1468
|
+
schemaEntryMatchesActiveFilter(
|
|
1469
|
+
sectionName,
|
|
1470
|
+
fullPath,
|
|
1471
|
+
info,
|
|
1472
|
+
engine,
|
|
1473
|
+
selectedIds,
|
|
1474
|
+
),
|
|
1326
1475
|
),
|
|
1327
1476
|
)
|
|
1328
1477
|
: rawEntries
|
|
@@ -1351,7 +1500,9 @@
|
|
|
1351
1500
|
}
|
|
1352
1501
|
|
|
1353
1502
|
const tree = buildSchemaTree(entries, sectionName)
|
|
1354
|
-
block.appendChild(
|
|
1503
|
+
block.appendChild(
|
|
1504
|
+
renderTreeNode(tree, engine, selectedIds, sectionName, true),
|
|
1505
|
+
)
|
|
1355
1506
|
|
|
1356
1507
|
section.appendChild(block)
|
|
1357
1508
|
})
|
|
@@ -1378,7 +1529,9 @@
|
|
|
1378
1529
|
const overview = el('div', 'section')
|
|
1379
1530
|
overview.appendChild(el('h3', '', 'Overview'))
|
|
1380
1531
|
const topGrid = el('div', 'grid-3')
|
|
1381
|
-
topGrid.appendChild(
|
|
1532
|
+
topGrid.appendChild(
|
|
1533
|
+
kv('group', cfg.docsGroup, engine, selectedIds, 'docsGroup'),
|
|
1534
|
+
)
|
|
1382
1535
|
topGrid.appendChild(
|
|
1383
1536
|
kv(
|
|
1384
1537
|
'tags',
|
|
@@ -1388,10 +1541,22 @@
|
|
|
1388
1541
|
'tags',
|
|
1389
1542
|
),
|
|
1390
1543
|
)
|
|
1391
|
-
topGrid.appendChild(
|
|
1544
|
+
topGrid.appendChild(
|
|
1545
|
+
kv('stability', cfg.stability, engine, selectedIds, 'stability'),
|
|
1546
|
+
)
|
|
1392
1547
|
overview.appendChild(topGrid)
|
|
1393
|
-
overview.appendChild(
|
|
1394
|
-
|
|
1548
|
+
overview.appendChild(
|
|
1549
|
+
kv('summary', cfg.summary, engine, selectedIds, 'summary'),
|
|
1550
|
+
)
|
|
1551
|
+
overview.appendChild(
|
|
1552
|
+
kv(
|
|
1553
|
+
'description',
|
|
1554
|
+
cfg.description,
|
|
1555
|
+
engine,
|
|
1556
|
+
selectedIds,
|
|
1557
|
+
'description',
|
|
1558
|
+
),
|
|
1559
|
+
)
|
|
1395
1560
|
|
|
1396
1561
|
const iconRow = el('div', 'icon-row')
|
|
1397
1562
|
if (cfg.feed) {
|
|
@@ -1417,13 +1582,6 @@
|
|
|
1417
1582
|
}
|
|
1418
1583
|
content.appendChild(overview)
|
|
1419
1584
|
|
|
1420
|
-
const fullConfig = el('div', 'section')
|
|
1421
|
-
fullConfig.appendChild(el('h3', '', 'Configuration (full)'))
|
|
1422
|
-
const cfgJson = el('pre', 'mono')
|
|
1423
|
-
cfgJson.textContent = JSON.stringify(cfg, null, 2)
|
|
1424
|
-
fullConfig.appendChild(cfgJson)
|
|
1425
|
-
content.appendChild(fullConfig)
|
|
1426
|
-
|
|
1427
1585
|
const files = el('div', 'section')
|
|
1428
1586
|
if (Array.isArray(cfg.bodyFiles) && cfg.bodyFiles.length > 0) {
|
|
1429
1587
|
files.appendChild(el('h3', '', 'Body Files'))
|
|
@@ -1441,11 +1599,22 @@
|
|
|
1441
1599
|
const source = sourceByLeaf[leaf.key]
|
|
1442
1600
|
if (source?.definition) {
|
|
1443
1601
|
overview.appendChild(
|
|
1444
|
-
createSourceRow(
|
|
1602
|
+
createSourceRow(
|
|
1603
|
+
'definition',
|
|
1604
|
+
source.definition,
|
|
1605
|
+
engine,
|
|
1606
|
+
selectedIds,
|
|
1607
|
+
'sourceDefinition',
|
|
1608
|
+
),
|
|
1445
1609
|
)
|
|
1446
1610
|
}
|
|
1447
1611
|
|
|
1448
|
-
const separatedSchemas = renderSeparatedSchemas(
|
|
1612
|
+
const separatedSchemas = renderSeparatedSchemas(
|
|
1613
|
+
flatSchema,
|
|
1614
|
+
engine,
|
|
1615
|
+
selectedIds,
|
|
1616
|
+
source,
|
|
1617
|
+
)
|
|
1449
1618
|
if (separatedSchemas) {
|
|
1450
1619
|
content.appendChild(separatedSchemas)
|
|
1451
1620
|
}
|
|
@@ -1453,12 +1622,22 @@
|
|
|
1453
1622
|
const routeHistory = state.changelogPayload?.byRoute?.[leaf.key]
|
|
1454
1623
|
if (Array.isArray(routeHistory) && routeHistory.length > 0) {
|
|
1455
1624
|
const commitBySha = new Map(
|
|
1456
|
-
(state.changelogPayload?.commits || []).map((commit) => [
|
|
1625
|
+
(state.changelogPayload?.commits || []).map((commit) => [
|
|
1626
|
+
commit.sha,
|
|
1627
|
+
commit,
|
|
1628
|
+
]),
|
|
1457
1629
|
)
|
|
1458
1630
|
const commitOrder = new Map(
|
|
1459
|
-
(state.changelogPayload?.commits || []).map((commit, index) => [
|
|
1631
|
+
(state.changelogPayload?.commits || []).map((commit, index) => [
|
|
1632
|
+
commit.sha,
|
|
1633
|
+
index,
|
|
1634
|
+
]),
|
|
1635
|
+
)
|
|
1636
|
+
const routeHistoryNewestFirst = sortEventsNewestFirst(
|
|
1637
|
+
routeHistory,
|
|
1638
|
+
commitBySha,
|
|
1639
|
+
commitOrder,
|
|
1460
1640
|
)
|
|
1461
|
-
const routeHistoryNewestFirst = sortEventsNewestFirst(routeHistory, commitBySha, commitOrder)
|
|
1462
1641
|
const routeChangelogSection = el('div', 'section')
|
|
1463
1642
|
const routeChangelogDetails = el('details')
|
|
1464
1643
|
const routeChangelogSummary = el(
|
|
@@ -1525,18 +1704,134 @@
|
|
|
1525
1704
|
return parts.join(', ')
|
|
1526
1705
|
}
|
|
1527
1706
|
|
|
1707
|
+
function schemaFlags(nullable, optional) {
|
|
1708
|
+
return `${nullable ? '-' : ''}${optional ? '?' : ''}`
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
function formatEntryTypeLabel(entry) {
|
|
1712
|
+
if (!entry || typeof entry !== 'object') return null
|
|
1713
|
+
const type = typeof entry.type === 'string' ? entry.type : 'unknown'
|
|
1714
|
+
return `${type}${schemaFlags(Boolean(entry.nullable), Boolean(entry.optional))}`
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
function formatPathLabel(path, entry) {
|
|
1718
|
+
const basePath = typeof path === 'string' ? path : ''
|
|
1719
|
+
return `${basePath}${schemaFlags(Boolean(entry?.nullable), Boolean(entry?.optional))}`
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
function parseSignatureTypeLabel(signature) {
|
|
1723
|
+
if (typeof signature !== 'string') return null
|
|
1724
|
+
const typeMatch = signature.match(/(?:^|,\s*)type=([^,]+)/)
|
|
1725
|
+
const nullableMatch = signature.match(/(?:^|,\s*)nullable=(true|false)/)
|
|
1726
|
+
const optionalMatch = signature.match(/(?:^|,\s*)optional=(true|false)/)
|
|
1727
|
+
if (!typeMatch) return null
|
|
1728
|
+
const type = typeMatch[1]
|
|
1729
|
+
const nullable = nullableMatch?.[1] === 'true'
|
|
1730
|
+
const optional = optionalMatch?.[1] === 'true'
|
|
1731
|
+
return `${type}${schemaFlags(nullable, optional)}`
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
function formatSourceTypeLabel(signatures) {
|
|
1735
|
+
if (!Array.isArray(signatures) || signatures.length === 0) return null
|
|
1736
|
+
const labels = signatures
|
|
1737
|
+
.map((item) => parseSignatureTypeLabel(item))
|
|
1738
|
+
.filter(Boolean)
|
|
1739
|
+
if (labels.length === 0) return null
|
|
1740
|
+
return labels.join(' | ')
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
function schemaDiffOperation(op) {
|
|
1744
|
+
if (op === 'added') {
|
|
1745
|
+
return { symbol: '+', word: 'added', className: 'added' }
|
|
1746
|
+
}
|
|
1747
|
+
if (op === 'removed') {
|
|
1748
|
+
return { symbol: '-', word: 'removed', className: 'removed' }
|
|
1749
|
+
}
|
|
1750
|
+
return { symbol: '*', word: 'changed', className: 'changed' }
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
function buildSchemaDiffLine(op, beforeType, pathLabel, afterType) {
|
|
1754
|
+
if (!pathLabel) return null
|
|
1755
|
+
const line = el('div', 'meta mono changelog-diff-line')
|
|
1756
|
+
const operation = schemaDiffOperation(op)
|
|
1757
|
+
line.appendChild(
|
|
1758
|
+
el(
|
|
1759
|
+
'span',
|
|
1760
|
+
`changelog-op ${operation.className}`,
|
|
1761
|
+
`${operation.symbol} ${operation.word}`,
|
|
1762
|
+
),
|
|
1763
|
+
)
|
|
1764
|
+
if (beforeType) {
|
|
1765
|
+
line.appendChild(el('span', 'changelog-schema-type', beforeType))
|
|
1766
|
+
}
|
|
1767
|
+
line.appendChild(el('span', '', pathLabel))
|
|
1768
|
+
if (operation.className === 'changed' && afterType) {
|
|
1769
|
+
line.appendChild(el('span', '', '->'))
|
|
1770
|
+
line.appendChild(el('span', 'changelog-schema-type', afterType))
|
|
1771
|
+
}
|
|
1772
|
+
return line
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
function buildLegacySchemaDiffLine(text) {
|
|
1776
|
+
return el('div', 'meta mono', text)
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1528
1779
|
function formatSchemaDiffLine(delta) {
|
|
1529
1780
|
if (!delta || typeof delta !== 'object') return null
|
|
1530
1781
|
if ('section' in delta) {
|
|
1531
1782
|
const location = `${delta.section}.${delta.path}`
|
|
1532
|
-
if (delta.op === 'added')
|
|
1533
|
-
|
|
1534
|
-
|
|
1783
|
+
if (delta.op === 'added') {
|
|
1784
|
+
const afterType = formatSourceTypeLabel(delta.after)
|
|
1785
|
+
if (afterType) return buildSchemaDiffLine(delta.op, afterType, location)
|
|
1786
|
+
return buildLegacySchemaDiffLine(
|
|
1787
|
+
`added ${location}: ${JSON.stringify(delta.after || [])}`,
|
|
1788
|
+
)
|
|
1789
|
+
}
|
|
1790
|
+
if (delta.op === 'removed') {
|
|
1791
|
+
const beforeType = formatSourceTypeLabel(delta.before)
|
|
1792
|
+
if (beforeType)
|
|
1793
|
+
return buildSchemaDiffLine(delta.op, beforeType, location)
|
|
1794
|
+
return buildLegacySchemaDiffLine(
|
|
1795
|
+
`removed ${location}: ${JSON.stringify(delta.before || [])}`,
|
|
1796
|
+
)
|
|
1797
|
+
}
|
|
1798
|
+
const beforeType = formatSourceTypeLabel(delta.before)
|
|
1799
|
+
const afterType = formatSourceTypeLabel(delta.after)
|
|
1800
|
+
if (beforeType || afterType) {
|
|
1801
|
+
return buildSchemaDiffLine(
|
|
1802
|
+
delta.op,
|
|
1803
|
+
beforeType || 'unknown',
|
|
1804
|
+
location,
|
|
1805
|
+
afterType || 'unknown',
|
|
1806
|
+
)
|
|
1807
|
+
}
|
|
1808
|
+
return buildLegacySchemaDiffLine(
|
|
1809
|
+
`changed ${location}: ${JSON.stringify(delta.before || [])} -> ${JSON.stringify(delta.after || [])}`,
|
|
1810
|
+
)
|
|
1535
1811
|
}
|
|
1536
1812
|
if ('path' in delta) {
|
|
1537
|
-
if (delta.op === 'added')
|
|
1538
|
-
|
|
1539
|
-
|
|
1813
|
+
if (delta.op === 'added') {
|
|
1814
|
+
const afterType = formatEntryTypeLabel(delta.after)
|
|
1815
|
+
const pathLabel = formatPathLabel(delta.path, delta.after)
|
|
1816
|
+
if (afterType) return buildSchemaDiffLine(delta.op, afterType, pathLabel)
|
|
1817
|
+
return buildLegacySchemaDiffLine(
|
|
1818
|
+
`added ${delta.path}: ${formatRouteSchemaEntry(delta.after)}`,
|
|
1819
|
+
)
|
|
1820
|
+
}
|
|
1821
|
+
if (delta.op === 'removed') {
|
|
1822
|
+
const beforeType = formatEntryTypeLabel(delta.before)
|
|
1823
|
+
const pathLabel = formatPathLabel(delta.path, delta.before)
|
|
1824
|
+
if (beforeType)
|
|
1825
|
+
return buildSchemaDiffLine(delta.op, beforeType, pathLabel)
|
|
1826
|
+
return buildLegacySchemaDiffLine(
|
|
1827
|
+
`removed ${delta.path}: ${formatRouteSchemaEntry(delta.before)}`,
|
|
1828
|
+
)
|
|
1829
|
+
}
|
|
1830
|
+
const beforeType = formatEntryTypeLabel(delta.before) || 'unknown'
|
|
1831
|
+
const afterType = formatEntryTypeLabel(delta.after) || 'unknown'
|
|
1832
|
+
const pathLabel =
|
|
1833
|
+
formatPathLabel(delta.path, delta.after || delta.before) || delta.path
|
|
1834
|
+
return buildSchemaDiffLine(delta.op, beforeType, pathLabel, afterType)
|
|
1540
1835
|
}
|
|
1541
1836
|
return null
|
|
1542
1837
|
}
|
|
@@ -1561,17 +1856,21 @@
|
|
|
1561
1856
|
card.appendChild(el('div', 'meta', commitMeta))
|
|
1562
1857
|
card.appendChild(el('div', 'mono', event.type))
|
|
1563
1858
|
if (Array.isArray(event.schemaDiff) && event.schemaDiff.length > 0) {
|
|
1564
|
-
card.appendChild(
|
|
1859
|
+
card.appendChild(
|
|
1860
|
+
el('div', 'meta', `schema changes: ${event.schemaDiff.length}`),
|
|
1861
|
+
)
|
|
1565
1862
|
const schemaChanges = el('div')
|
|
1566
1863
|
event.schemaDiff.forEach((delta) => {
|
|
1567
|
-
const
|
|
1568
|
-
if (!
|
|
1569
|
-
schemaChanges.appendChild(
|
|
1864
|
+
const lineNode = formatSchemaDiffLine(delta)
|
|
1865
|
+
if (!lineNode) return
|
|
1866
|
+
schemaChanges.appendChild(lineNode)
|
|
1570
1867
|
})
|
|
1571
1868
|
card.appendChild(schemaChanges)
|
|
1572
1869
|
}
|
|
1573
1870
|
if (Array.isArray(event.cfgDiff) && event.cfgDiff.length > 0) {
|
|
1574
|
-
card.appendChild(
|
|
1871
|
+
card.appendChild(
|
|
1872
|
+
el('div', 'meta', `cfg changes: ${event.cfgDiff.length}`),
|
|
1873
|
+
)
|
|
1575
1874
|
const cfgChanges = el('div')
|
|
1576
1875
|
event.cfgDiff.forEach((diff) => {
|
|
1577
1876
|
const line = formatCfgDiffLine(diff)
|
|
@@ -1580,8 +1879,17 @@
|
|
|
1580
1879
|
})
|
|
1581
1880
|
card.appendChild(cfgChanges)
|
|
1582
1881
|
}
|
|
1583
|
-
if (
|
|
1584
|
-
|
|
1882
|
+
if (
|
|
1883
|
+
Array.isArray(event.impactedRoutes) &&
|
|
1884
|
+
event.impactedRoutes.length > 0
|
|
1885
|
+
) {
|
|
1886
|
+
card.appendChild(
|
|
1887
|
+
el(
|
|
1888
|
+
'div',
|
|
1889
|
+
'meta',
|
|
1890
|
+
`impacted routes: ${event.impactedRoutes.length}`,
|
|
1891
|
+
),
|
|
1892
|
+
)
|
|
1585
1893
|
}
|
|
1586
1894
|
return card
|
|
1587
1895
|
}
|
|
@@ -1601,14 +1909,16 @@
|
|
|
1601
1909
|
|
|
1602
1910
|
function renderChangelogEventLines(event, commitBySha, contextLabel) {
|
|
1603
1911
|
const row = el('div', 'changelog-line-item')
|
|
1604
|
-
row.appendChild(
|
|
1912
|
+
row.appendChild(
|
|
1913
|
+
el('div', 'meta', buildCommitMetaLine(event, commitBySha)),
|
|
1914
|
+
)
|
|
1605
1915
|
row.appendChild(el('div', 'mono', `${contextLabel} (${event.type})`))
|
|
1606
1916
|
|
|
1607
1917
|
if (Array.isArray(event.schemaDiff) && event.schemaDiff.length > 0) {
|
|
1608
1918
|
event.schemaDiff.forEach((delta) => {
|
|
1609
|
-
const
|
|
1610
|
-
if (!
|
|
1611
|
-
row.appendChild(
|
|
1919
|
+
const lineNode = formatSchemaDiffLine(delta)
|
|
1920
|
+
if (!lineNode) return
|
|
1921
|
+
row.appendChild(lineNode)
|
|
1612
1922
|
})
|
|
1613
1923
|
}
|
|
1614
1924
|
if (Array.isArray(event.cfgDiff) && event.cfgDiff.length > 0) {
|
|
@@ -1618,9 +1928,16 @@
|
|
|
1618
1928
|
row.appendChild(el('div', 'meta mono', line))
|
|
1619
1929
|
})
|
|
1620
1930
|
}
|
|
1621
|
-
if (
|
|
1931
|
+
if (
|
|
1932
|
+
Array.isArray(event.impactedRoutes) &&
|
|
1933
|
+
event.impactedRoutes.length > 0
|
|
1934
|
+
) {
|
|
1622
1935
|
row.appendChild(
|
|
1623
|
-
el(
|
|
1936
|
+
el(
|
|
1937
|
+
'div',
|
|
1938
|
+
'meta mono',
|
|
1939
|
+
`impacted routes: ${event.impactedRoutes.join(', ')}`,
|
|
1940
|
+
),
|
|
1624
1941
|
)
|
|
1625
1942
|
}
|
|
1626
1943
|
|
|
@@ -1643,7 +1960,9 @@
|
|
|
1643
1960
|
const indexB = commitOrder.get(b?.commitSha) ?? -1
|
|
1644
1961
|
if (indexA !== indexB) return indexB - indexA
|
|
1645
1962
|
|
|
1646
|
-
return String(b?.commitSha || '').localeCompare(
|
|
1963
|
+
return String(b?.commitSha || '').localeCompare(
|
|
1964
|
+
String(a?.commitSha || ''),
|
|
1965
|
+
)
|
|
1647
1966
|
}
|
|
1648
1967
|
|
|
1649
1968
|
function sortEventsNewestFirst(events, commitBySha, commitOrder) {
|
|
@@ -1654,8 +1973,12 @@
|
|
|
1654
1973
|
|
|
1655
1974
|
function buildChronologicalEvents(payload) {
|
|
1656
1975
|
if (!payload) return []
|
|
1657
|
-
const commitBySha = new Map(
|
|
1658
|
-
|
|
1976
|
+
const commitBySha = new Map(
|
|
1977
|
+
(payload.commits || []).map((commit) => [commit.sha, commit]),
|
|
1978
|
+
)
|
|
1979
|
+
const commitOrder = new Map(
|
|
1980
|
+
(payload.commits || []).map((commit, index) => [commit.sha, index]),
|
|
1981
|
+
)
|
|
1659
1982
|
const rows = []
|
|
1660
1983
|
let sequence = 0
|
|
1661
1984
|
|
|
@@ -1673,24 +1996,27 @@
|
|
|
1673
1996
|
})
|
|
1674
1997
|
})
|
|
1675
1998
|
|
|
1676
|
-
Object.entries(payload.bySourceObject || {}).forEach(
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1999
|
+
Object.entries(payload.bySourceObject || {}).forEach(
|
|
2000
|
+
([sourceObjectId, events]) => {
|
|
2001
|
+
;(events || []).forEach((event) => {
|
|
2002
|
+
rows.push({
|
|
2003
|
+
eventKind: 'source',
|
|
2004
|
+
sourceObjectId,
|
|
2005
|
+
displayName: event.displayName || sourceObjectId,
|
|
2006
|
+
event,
|
|
2007
|
+
commit: commitBySha.get(event.commitSha),
|
|
2008
|
+
commitSort: commitTimestamp(commitBySha.get(event.commitSha)),
|
|
2009
|
+
commitIndex: commitOrder.get(event.commitSha) ?? -1,
|
|
2010
|
+
eventIndex: sequence++,
|
|
2011
|
+
})
|
|
1687
2012
|
})
|
|
1688
|
-
}
|
|
1689
|
-
|
|
2013
|
+
},
|
|
2014
|
+
)
|
|
1690
2015
|
|
|
1691
2016
|
rows.sort((a, b) => {
|
|
1692
2017
|
if (a.commitSort !== b.commitSort) return b.commitSort - a.commitSort
|
|
1693
|
-
if (a.commitIndex !== b.commitIndex)
|
|
2018
|
+
if (a.commitIndex !== b.commitIndex)
|
|
2019
|
+
return b.commitIndex - a.commitIndex
|
|
1694
2020
|
return b.eventIndex - a.eventIndex
|
|
1695
2021
|
})
|
|
1696
2022
|
|
|
@@ -1709,7 +2035,8 @@
|
|
|
1709
2035
|
function matchesGenericItem(item, fieldDefs, engine, selectedIds) {
|
|
1710
2036
|
if (!engine.active) return true
|
|
1711
2037
|
return fieldDefs.some((field) => {
|
|
1712
|
-
if (selectedIds.length > 0 && !selectedIds.includes(field.id))
|
|
2038
|
+
if (selectedIds.length > 0 && !selectedIds.includes(field.id))
|
|
2039
|
+
return false
|
|
1713
2040
|
const tokens = toTokens(field.get(item))
|
|
1714
2041
|
return tokens.some((token) => engine.test(token))
|
|
1715
2042
|
})
|
|
@@ -1728,8 +2055,14 @@
|
|
|
1728
2055
|
function renderTabButtons() {
|
|
1729
2056
|
setPressed(tabLeavesBtn, state.activeTab === VIEW_IDS.leaves)
|
|
1730
2057
|
setPressed(tabChangelogBtn, state.activeTab === VIEW_IDS.changelog)
|
|
1731
|
-
tabLeavesBtn.style.display = state.availableTabs.has(VIEW_IDS.leaves)
|
|
1732
|
-
|
|
2058
|
+
tabLeavesBtn.style.display = state.availableTabs.has(VIEW_IDS.leaves)
|
|
2059
|
+
? ''
|
|
2060
|
+
: 'none'
|
|
2061
|
+
tabChangelogBtn.style.display = state.availableTabs.has(
|
|
2062
|
+
VIEW_IDS.changelog,
|
|
2063
|
+
)
|
|
2064
|
+
? ''
|
|
2065
|
+
: 'none'
|
|
1733
2066
|
const isLeavesTab = state.activeTab === VIEW_IDS.leaves
|
|
1734
2067
|
coreFieldsBtn.style.display = isLeavesTab ? '' : 'none'
|
|
1735
2068
|
schemasOnlyFieldsBtn.style.display = isLeavesTab ? '' : 'none'
|
|
@@ -1745,7 +2078,9 @@
|
|
|
1745
2078
|
if (engine.error) {
|
|
1746
2079
|
statusEl.textContent = `Invalid regex: ${engine.error}`
|
|
1747
2080
|
resultsEl.innerHTML = ''
|
|
1748
|
-
resultsEl.appendChild(
|
|
2081
|
+
resultsEl.appendChild(
|
|
2082
|
+
el('div', 'empty', 'Fix the regex to continue.'),
|
|
2083
|
+
)
|
|
1749
2084
|
renderActiveFilterChips({
|
|
1750
2085
|
selectedIds: selectedFieldIds(),
|
|
1751
2086
|
hasRegexError: true,
|
|
@@ -1758,16 +2093,27 @@
|
|
|
1758
2093
|
renderTabButtons()
|
|
1759
2094
|
renderActiveFilterChips({ selectedIds, hasRegexError: false })
|
|
1760
2095
|
if (state.activeTab === VIEW_IDS.leaves) {
|
|
1761
|
-
const filtered = state.leaves.filter((leaf) =>
|
|
2096
|
+
const filtered = state.leaves.filter((leaf) =>
|
|
2097
|
+
matchesLeaf(leaf, engine, selectedIds),
|
|
2098
|
+
)
|
|
1762
2099
|
statusEl.textContent = `${filtered.length} / ${state.leaves.length} routes matched.`
|
|
1763
|
-
renderCollection(
|
|
2100
|
+
renderCollection(
|
|
2101
|
+
filtered,
|
|
2102
|
+
(leaf) => renderLeaf(leaf, engine, selectedIds),
|
|
2103
|
+
'No matches.',
|
|
2104
|
+
)
|
|
1764
2105
|
} else {
|
|
1765
2106
|
const fieldDefs = currentFieldDefs()
|
|
1766
2107
|
const items = changelogItemsByTab(state.activeTab)
|
|
1767
|
-
const filtered = items.filter((item) =>
|
|
2108
|
+
const filtered = items.filter((item) =>
|
|
2109
|
+
matchesGenericItem(item, fieldDefs, engine, selectedIds),
|
|
2110
|
+
)
|
|
1768
2111
|
statusEl.textContent = `${filtered.length} / ${items.length} changelog events matched.`
|
|
1769
2112
|
const commitBySha = new Map(
|
|
1770
|
-
(state.changelogPayload?.commits || []).map((commit) => [
|
|
2113
|
+
(state.changelogPayload?.commits || []).map((commit) => [
|
|
2114
|
+
commit.sha,
|
|
2115
|
+
commit,
|
|
2116
|
+
]),
|
|
1771
2117
|
)
|
|
1772
2118
|
if (state.viewerMode === VIEWER_MODE.changelog) {
|
|
1773
2119
|
renderCollection(
|
|
@@ -1777,7 +2123,11 @@
|
|
|
1777
2123
|
item.eventKind === 'route'
|
|
1778
2124
|
? `Route: ${item.routeKey}`
|
|
1779
2125
|
: `Source: ${item.displayName || item.sourceObjectId}`
|
|
1780
|
-
return renderChangelogEventLines(
|
|
2126
|
+
return renderChangelogEventLines(
|
|
2127
|
+
item.event,
|
|
2128
|
+
commitBySha,
|
|
2129
|
+
contextLabel,
|
|
2130
|
+
)
|
|
1781
2131
|
},
|
|
1782
2132
|
'No matches.',
|
|
1783
2133
|
)
|
|
@@ -1799,15 +2149,17 @@
|
|
|
1799
2149
|
}
|
|
1800
2150
|
|
|
1801
2151
|
function selectedFieldIds() {
|
|
1802
|
-
const selected =
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
2152
|
+
const selected =
|
|
2153
|
+
state.selectedFieldIdsByTab[state.activeTab] || new Set()
|
|
2154
|
+
return currentFieldDefs()
|
|
2155
|
+
.filter((field) => selected.has(field.id))
|
|
2156
|
+
.map((field) => field.id)
|
|
1806
2157
|
}
|
|
1807
2158
|
|
|
1808
2159
|
function renderFieldChips() {
|
|
1809
2160
|
const fieldDefs = currentFieldDefs()
|
|
1810
|
-
const selected =
|
|
2161
|
+
const selected =
|
|
2162
|
+
state.selectedFieldIdsByTab[state.activeTab] || new Set()
|
|
1811
2163
|
fieldChipGroups.innerHTML = ''
|
|
1812
2164
|
const groups =
|
|
1813
2165
|
state.activeTab === VIEW_IDS.leaves
|
|
@@ -1815,7 +2167,10 @@
|
|
|
1815
2167
|
: [
|
|
1816
2168
|
{
|
|
1817
2169
|
id: 'tabFields',
|
|
1818
|
-
label:
|
|
2170
|
+
label:
|
|
2171
|
+
state.activeTab === VIEW_IDS.changelog
|
|
2172
|
+
? 'Changelog fields'
|
|
2173
|
+
: 'Source fields',
|
|
1819
2174
|
fieldIds: fieldDefs.map((field) => field.id),
|
|
1820
2175
|
},
|
|
1821
2176
|
]
|
|
@@ -1854,7 +2209,9 @@
|
|
|
1854
2209
|
function setFieldSelection(allowedIds, options = {}) {
|
|
1855
2210
|
const { rerender = true } = options
|
|
1856
2211
|
state.selectedFieldIdsByTab[state.activeTab] = new Set(
|
|
1857
|
-
currentFieldDefs()
|
|
2212
|
+
currentFieldDefs()
|
|
2213
|
+
.map((field) => field.id)
|
|
2214
|
+
.filter((id) => allowedIds.has(id)),
|
|
1858
2215
|
)
|
|
1859
2216
|
renderFieldChips()
|
|
1860
2217
|
if (rerender) renderResults()
|
|
@@ -1866,7 +2223,10 @@
|
|
|
1866
2223
|
setPressed(regexSearchToggle, false)
|
|
1867
2224
|
typeMatchModeInput.value = 'contains'
|
|
1868
2225
|
setPressed(schemaRowsMatchOnlyToggle, false)
|
|
1869
|
-
setFieldSelection(
|
|
2226
|
+
setFieldSelection(
|
|
2227
|
+
new Set(currentFieldDefs().map((field) => field.id)),
|
|
2228
|
+
{ rerender: false },
|
|
2229
|
+
)
|
|
1870
2230
|
renderResults()
|
|
1871
2231
|
}
|
|
1872
2232
|
|
|
@@ -1931,12 +2291,16 @@
|
|
|
1931
2291
|
}
|
|
1932
2292
|
|
|
1933
2293
|
if (chipModels.length === 0) {
|
|
1934
|
-
activeFilterChips.appendChild(
|
|
2294
|
+
activeFilterChips.appendChild(
|
|
2295
|
+
el('span', 'empty', 'No active filters'),
|
|
2296
|
+
)
|
|
1935
2297
|
return
|
|
1936
2298
|
}
|
|
1937
2299
|
|
|
1938
2300
|
chipModels.forEach((chipModel) => {
|
|
1939
|
-
const chip = document.createElement(
|
|
2301
|
+
const chip = document.createElement(
|
|
2302
|
+
chipModel.onClick ? 'button' : 'span',
|
|
2303
|
+
)
|
|
1940
2304
|
chip.className = chipModel.onClick ? 'chip chip-btn' : 'chip'
|
|
1941
2305
|
chip.textContent = chipModel.text
|
|
1942
2306
|
if (chipModel.onClick) {
|
|
@@ -1953,10 +2317,14 @@
|
|
|
1953
2317
|
search: searchInput.value,
|
|
1954
2318
|
caseSensitive: isPressed(caseSensitiveToggle),
|
|
1955
2319
|
regex: isPressed(regexSearchToggle),
|
|
1956
|
-
typeMatchMode:
|
|
2320
|
+
typeMatchMode:
|
|
2321
|
+
typeMatchModeInput.value === 'exact' ? 'exact' : 'contains',
|
|
1957
2322
|
schemaRowsMatchOnly: isPressed(schemaRowsMatchOnlyToggle),
|
|
1958
2323
|
selectedFieldsByTab: Object.fromEntries(
|
|
1959
|
-
Object.entries(state.selectedFieldIdsByTab).map(([key, value]) => [
|
|
2324
|
+
Object.entries(state.selectedFieldIdsByTab).map(([key, value]) => [
|
|
2325
|
+
key,
|
|
2326
|
+
Array.from(value),
|
|
2327
|
+
]),
|
|
1960
2328
|
),
|
|
1961
2329
|
}
|
|
1962
2330
|
}
|
|
@@ -1965,7 +2333,9 @@
|
|
|
1965
2333
|
if (isHydratingFromUrl) return
|
|
1966
2334
|
|
|
1967
2335
|
const data = collectFilterState()
|
|
1968
|
-
const params = new URLSearchParams(
|
|
2336
|
+
const params = new URLSearchParams(
|
|
2337
|
+
window.location.hash.replace(/^#/, ''),
|
|
2338
|
+
)
|
|
1969
2339
|
const serialized = encodeURIComponent(JSON.stringify(data))
|
|
1970
2340
|
params.set(URL_PARAM_KEY, serialized)
|
|
1971
2341
|
const nextHash = params.toString()
|
|
@@ -1975,7 +2345,9 @@
|
|
|
1975
2345
|
}
|
|
1976
2346
|
|
|
1977
2347
|
function hydrateFilterStateFromUrl() {
|
|
1978
|
-
const params = new URLSearchParams(
|
|
2348
|
+
const params = new URLSearchParams(
|
|
2349
|
+
window.location.hash.replace(/^#/, ''),
|
|
2350
|
+
)
|
|
1979
2351
|
const raw = params.get(URL_PARAM_KEY)
|
|
1980
2352
|
if (!raw) return
|
|
1981
2353
|
|
|
@@ -1991,20 +2363,32 @@
|
|
|
1991
2363
|
if (parsed.activeTab === 'changelogRoute') {
|
|
1992
2364
|
state.activeTab = VIEW_IDS.changelog
|
|
1993
2365
|
}
|
|
1994
|
-
if (typeof parsed.search === 'string')
|
|
2366
|
+
if (typeof parsed.search === 'string')
|
|
2367
|
+
searchInput.value = parsed.search
|
|
1995
2368
|
setPressed(caseSensitiveToggle, Boolean(parsed.caseSensitive))
|
|
1996
2369
|
setPressed(regexSearchToggle, Boolean(parsed.regex))
|
|
1997
|
-
if (
|
|
2370
|
+
if (
|
|
2371
|
+
parsed.typeMatchMode === 'exact' ||
|
|
2372
|
+
parsed.typeMatchMode === 'contains'
|
|
2373
|
+
) {
|
|
1998
2374
|
typeMatchModeInput.value = parsed.typeMatchMode
|
|
1999
2375
|
}
|
|
2000
|
-
setPressed(
|
|
2376
|
+
setPressed(
|
|
2377
|
+
schemaRowsMatchOnlyToggle,
|
|
2378
|
+
Boolean(parsed.schemaRowsMatchOnly),
|
|
2379
|
+
)
|
|
2001
2380
|
|
|
2002
|
-
if (
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2381
|
+
if (
|
|
2382
|
+
parsed.selectedFieldsByTab &&
|
|
2383
|
+
typeof parsed.selectedFieldsByTab === 'object'
|
|
2384
|
+
) {
|
|
2385
|
+
Object.entries(parsed.selectedFieldsByTab).forEach(
|
|
2386
|
+
([tabId, ids]) => {
|
|
2387
|
+
if (!Array.isArray(ids)) return
|
|
2388
|
+
if (!state.selectedFieldIdsByTab[tabId]) return
|
|
2389
|
+
state.selectedFieldIdsByTab[tabId] = new Set(ids)
|
|
2390
|
+
},
|
|
2391
|
+
)
|
|
2008
2392
|
}
|
|
2009
2393
|
} catch (error) {
|
|
2010
2394
|
// Ignore malformed hash state.
|
|
@@ -2070,15 +2454,13 @@
|
|
|
2070
2454
|
}
|
|
2071
2455
|
|
|
2072
2456
|
if (state.leavesPayload && state.changelogPayload) {
|
|
2073
|
-
statusEl.textContent =
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
} commits.`
|
|
2457
|
+
statusEl.textContent = `Loaded unified bundle with ${state.leaves.length} routes and ${
|
|
2458
|
+
state.changelogPayload.commits?.length || 0
|
|
2459
|
+
} commits.`
|
|
2077
2460
|
} else if (state.leavesPayload) {
|
|
2078
2461
|
statusEl.textContent = `Loaded payload with ${state.leaves.length} routes.`
|
|
2079
2462
|
} else if (state.changelogPayload) {
|
|
2080
|
-
statusEl.textContent =
|
|
2081
|
-
`Loaded changelog payload with ${state.changelogPayload.commits?.length || 0} commits.`
|
|
2463
|
+
statusEl.textContent = `Loaded changelog payload with ${state.changelogPayload.commits?.length || 0} commits.`
|
|
2082
2464
|
} else {
|
|
2083
2465
|
statusEl.textContent = 'No payload loaded.'
|
|
2084
2466
|
}
|
|
@@ -2104,7 +2486,8 @@
|
|
|
2104
2486
|
try {
|
|
2105
2487
|
await handleFile(file)
|
|
2106
2488
|
} catch (error) {
|
|
2107
|
-
statusEl.textContent =
|
|
2489
|
+
statusEl.textContent =
|
|
2490
|
+
error instanceof Error ? error.message : String(error)
|
|
2108
2491
|
resultsEl.innerHTML = ''
|
|
2109
2492
|
}
|
|
2110
2493
|
})
|
|
@@ -2124,16 +2507,28 @@
|
|
|
2124
2507
|
renderResults()
|
|
2125
2508
|
})
|
|
2126
2509
|
|
|
2127
|
-
tabLeavesBtn.addEventListener('click', () =>
|
|
2128
|
-
|
|
2510
|
+
tabLeavesBtn.addEventListener('click', () =>
|
|
2511
|
+
setActiveTab(VIEW_IDS.leaves),
|
|
2512
|
+
)
|
|
2513
|
+
tabChangelogBtn.addEventListener('click', () =>
|
|
2514
|
+
setActiveTab(VIEW_IDS.changelog),
|
|
2515
|
+
)
|
|
2129
2516
|
|
|
2130
2517
|
selectAllFieldsBtn.addEventListener('click', () =>
|
|
2131
2518
|
setFieldSelection(new Set(currentFieldDefs().map((field) => field.id))),
|
|
2132
2519
|
)
|
|
2133
|
-
clearAllFieldsBtn.addEventListener('click', () =>
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2520
|
+
clearAllFieldsBtn.addEventListener('click', () =>
|
|
2521
|
+
setFieldSelection(new Set()),
|
|
2522
|
+
)
|
|
2523
|
+
coreFieldsBtn.addEventListener('click', () =>
|
|
2524
|
+
setFieldSelection(CORE_FIELD_IDS),
|
|
2525
|
+
)
|
|
2526
|
+
schemasOnlyFieldsBtn.addEventListener('click', () =>
|
|
2527
|
+
setFieldSelection(SCHEMA_SCOPE_FIELD_IDS),
|
|
2528
|
+
)
|
|
2529
|
+
sourceOnlyFieldsBtn.addEventListener('click', () =>
|
|
2530
|
+
setFieldSelection(SOURCE_FIELD_IDS),
|
|
2531
|
+
)
|
|
2137
2532
|
resetFiltersBtn.addEventListener('click', resetFiltersToDefault)
|
|
2138
2533
|
|
|
2139
2534
|
renderFieldChips()
|