raffel 1.1.49 → 1.1.51-next.ce68de0
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/docs/ui/assets/raffel-docs.css +43 -0
- package/dist/docs/ui/assets/raffel-docs.js +117 -32
- package/dist/docs/ui/runtime/index.js +117 -32
- package/dist/docs/ui/runtime/index.js.map +1 -1
- package/dist/docs/ui/style-sections/layout-navigation.d.ts +1 -1
- package/dist/docs/ui/style-sections/layout-navigation.d.ts.map +1 -1
- package/dist/docs/ui/style-sections/layout-navigation.js +10 -0
- package/dist/docs/ui/style-sections/layout-navigation.js.map +1 -1
- package/dist/docs/ui/style-sections/schema-code.d.ts +1 -1
- package/dist/docs/ui/style-sections/schema-code.d.ts.map +1 -1
- package/dist/docs/ui/style-sections/schema-code.js +33 -0
- package/dist/docs/ui/style-sections/schema-code.js.map +1 -1
- package/dist/ui/docs/ui/style-sections/layout-navigation.d.ts +1 -1
- package/dist/ui/docs/ui/style-sections/layout-navigation.d.ts.map +1 -1
- package/dist/ui/docs/ui/style-sections/schema-code.d.ts +1 -1
- package/dist/ui/docs/ui/style-sections/schema-code.d.ts.map +1 -1
- package/package.json +2 -6
|
@@ -684,6 +684,16 @@
|
|
|
684
684
|
gap: 0;
|
|
685
685
|
}
|
|
686
686
|
|
|
687
|
+
/* Drop the (empty) TOC gutter on endpoint views so the operation's
|
|
688
|
+
two-column content — docs + samples panel — can use the full width. */
|
|
689
|
+
.main-shell.main-shell-no-toc {
|
|
690
|
+
grid-template-columns: minmax(0, 1fr);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
.main-shell.main-shell-no-toc .toc {
|
|
694
|
+
display: none;
|
|
695
|
+
}
|
|
696
|
+
|
|
687
697
|
/* ========== SIDEBAR ========== */
|
|
688
698
|
.sidebar {
|
|
689
699
|
background: var(--sidebar-bg);
|
|
@@ -3535,6 +3545,39 @@
|
|
|
3535
3545
|
|
|
3536
3546
|
.http-code-copy:hover { color: var(--text-color); border-color: var(--text-muted); }
|
|
3537
3547
|
|
|
3548
|
+
/* Right panel (third column): keep request/response samples dark & legible
|
|
3549
|
+
regardless of the active theme, matching ReDoc's sample column. */
|
|
3550
|
+
.endpoint-right .endpoint-right-section + .endpoint-right-section {
|
|
3551
|
+
margin-top: 24px;
|
|
3552
|
+
}
|
|
3553
|
+
|
|
3554
|
+
.endpoint-right .http-code-samples {
|
|
3555
|
+
background: rgba(0,0,0,0.25);
|
|
3556
|
+
border-color: rgba(255,255,255,0.1);
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3559
|
+
.endpoint-right .http-code-samples .code-tabs {
|
|
3560
|
+
background: rgba(0,0,0,0.2);
|
|
3561
|
+
border-color: rgba(255,255,255,0.1);
|
|
3562
|
+
}
|
|
3563
|
+
|
|
3564
|
+
.endpoint-right .http-code-sample-pre {
|
|
3565
|
+
color: var(--code-panel-text);
|
|
3566
|
+
}
|
|
3567
|
+
|
|
3568
|
+
.endpoint-right .code-tab {
|
|
3569
|
+
color: #90a4ae;
|
|
3570
|
+
}
|
|
3571
|
+
|
|
3572
|
+
.endpoint-right .code-tab.active {
|
|
3573
|
+
background: rgba(255,255,255,0.12);
|
|
3574
|
+
color: #fff;
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3577
|
+
.endpoint-right .response-subhead {
|
|
3578
|
+
color: #90a4ae;
|
|
3579
|
+
}
|
|
3580
|
+
|
|
3538
3581
|
/* ========== TRY IT OUT ========== */
|
|
3539
3582
|
.try-it-out {
|
|
3540
3583
|
background: rgba(0,0,0,0.2);
|
|
@@ -1385,20 +1385,76 @@ function renderCodeExamples(endpoint, data) {
|
|
|
1385
1385
|
return wrap;
|
|
1386
1386
|
}
|
|
1387
1387
|
// Append a JSON example block to a container.
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1388
|
+
// Syntax-highlight a JSON value into HTML using the .sample-json token classes.
|
|
1389
|
+
function highlightJsonHtml(value) {
|
|
1390
|
+
let json = JSON.stringify(value, null, 2);
|
|
1391
|
+
if (json === undefined)
|
|
1392
|
+
return '';
|
|
1393
|
+
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1394
|
+
return json.replace(/("(?:\\.|[^"\\])*"(\s*:)?|\b(?:true|false|null)\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g, (match, _token, colon) => {
|
|
1395
|
+
let cls = 'json-number';
|
|
1396
|
+
if (match[0] === '"')
|
|
1397
|
+
cls = colon ? 'json-key' : 'json-string';
|
|
1398
|
+
else if (match === 'true' || match === 'false')
|
|
1399
|
+
cls = 'json-boolean';
|
|
1400
|
+
else if (match === 'null')
|
|
1401
|
+
cls = 'json-null';
|
|
1402
|
+
return `<span class="${cls}">${match}</span>`;
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
// Right-panel response samples: one status tab per response, each showing the
|
|
1406
|
+
// generated JSON example (colorized) — ReDoc's response sample switcher.
|
|
1407
|
+
function renderResponseSamples(responses) {
|
|
1408
|
+
const wrap = doc.createElement('div');
|
|
1409
|
+
const tabs = doc.createElement('div');
|
|
1410
|
+
tabs.className = 'sample-tabs';
|
|
1411
|
+
const contents = doc.createElement('div');
|
|
1412
|
+
contents.className = 'sample-contents';
|
|
1413
|
+
const entries = Object.entries(responses);
|
|
1414
|
+
entries.forEach(([status, resp], index) => {
|
|
1415
|
+
const statusClass = status.startsWith('2') ? 'status-2xx'
|
|
1416
|
+
: status.startsWith('4') ? 'status-4xx'
|
|
1417
|
+
: status.startsWith('5') ? 'status-5xx'
|
|
1418
|
+
: '';
|
|
1419
|
+
const tab = doc.createElement('button');
|
|
1420
|
+
tab.type = 'button';
|
|
1421
|
+
tab.className = `sample-tab ${statusClass}${index === 0 ? ' active' : ''}`;
|
|
1422
|
+
tab.textContent = status;
|
|
1423
|
+
const content = doc.createElement('div');
|
|
1424
|
+
content.className = `sample-content${index === 0 ? ' active' : ''}`;
|
|
1425
|
+
const ct = resp.content ? Object.keys(resp.content)[0] : null;
|
|
1426
|
+
const schema = ct ? resp.content[ct]?.schema : null;
|
|
1427
|
+
const example = schema ? generateExampleFromSchema(schema) : null;
|
|
1428
|
+
if (example !== null && example !== undefined) {
|
|
1429
|
+
if (ct) {
|
|
1430
|
+
const typeLine = doc.createElement('div');
|
|
1431
|
+
typeLine.className = 'sample-content-type';
|
|
1432
|
+
typeLine.textContent = ct;
|
|
1433
|
+
content.appendChild(typeLine);
|
|
1434
|
+
}
|
|
1435
|
+
const pre = doc.createElement('pre');
|
|
1436
|
+
pre.className = 'sample-json';
|
|
1437
|
+
pre.innerHTML = highlightJsonHtml(example);
|
|
1438
|
+
content.appendChild(pre);
|
|
1439
|
+
}
|
|
1440
|
+
else {
|
|
1441
|
+
const empty = doc.createElement('div');
|
|
1442
|
+
empty.className = 'no-example';
|
|
1443
|
+
empty.textContent = resp.description || 'No response body.';
|
|
1444
|
+
content.appendChild(empty);
|
|
1445
|
+
}
|
|
1446
|
+
tab.onclick = () => {
|
|
1447
|
+
tabs.querySelectorAll('.sample-tab').forEach((t) => t.classList.remove('active'));
|
|
1448
|
+
contents.querySelectorAll('.sample-content').forEach((c) => c.classList.remove('active'));
|
|
1449
|
+
tab.classList.add('active');
|
|
1450
|
+
content.classList.add('active');
|
|
1451
|
+
};
|
|
1452
|
+
tabs.appendChild(tab);
|
|
1453
|
+
contents.appendChild(content);
|
|
1454
|
+
});
|
|
1455
|
+
wrap.appendChild(tabs);
|
|
1456
|
+
wrap.appendChild(contents);
|
|
1457
|
+
return wrap;
|
|
1402
1458
|
}
|
|
1403
1459
|
function renderSchemaTree(parent, schema, depth = 0) {
|
|
1404
1460
|
if (!schema)
|
|
@@ -1541,7 +1597,6 @@ function renderResponseAccordion(status, resp, openByDefault) {
|
|
|
1541
1597
|
sub.textContent = `Response Body${contentType ? ` · ${contentType}` : ''}`;
|
|
1542
1598
|
block.appendChild(sub);
|
|
1543
1599
|
renderSchemaTree(block, schema);
|
|
1544
|
-
appendJsonExample(block, generateExampleFromSchema(schema));
|
|
1545
1600
|
body.appendChild(block);
|
|
1546
1601
|
}
|
|
1547
1602
|
if (!body.children.length) {
|
|
@@ -1562,6 +1617,15 @@ function renderEndpointDetails(endpoint) {
|
|
|
1562
1617
|
appendProtocolConsole(container, { doc, spec, wsSpec, streamsSpec, jsonrpcSpec, activeProtocol, endpoint, data, esc, escapeAttr });
|
|
1563
1618
|
const appendMany = (items) => items.forEach(([title, value]) => appendSchemaSubsection(container, title, value));
|
|
1564
1619
|
if (activeProtocol === 'http') {
|
|
1620
|
+
// Two-column operation layout (ReDoc-style): the left column carries the
|
|
1621
|
+
// contract (params + schemas + responses); the right column is a sticky
|
|
1622
|
+
// dark panel with the request samples and response examples.
|
|
1623
|
+
const content = doc.createElement('div');
|
|
1624
|
+
content.className = 'endpoint-content';
|
|
1625
|
+
const left = doc.createElement('div');
|
|
1626
|
+
left.className = 'endpoint-left';
|
|
1627
|
+
const right = doc.createElement('div');
|
|
1628
|
+
right.className = 'endpoint-right';
|
|
1565
1629
|
const params = (data.parameters ?? []);
|
|
1566
1630
|
if (params.length > 0) {
|
|
1567
1631
|
const section = doc.createElement('div');
|
|
@@ -1578,7 +1642,7 @@ function renderEndpointDetails(endpoint) {
|
|
|
1578
1642
|
if (inGroup.length > 0)
|
|
1579
1643
|
section.appendChild(renderParamGroup(title, inGroup));
|
|
1580
1644
|
});
|
|
1581
|
-
|
|
1645
|
+
left.appendChild(section);
|
|
1582
1646
|
}
|
|
1583
1647
|
const reqBody = data.requestBody;
|
|
1584
1648
|
if (reqBody?.content) {
|
|
@@ -1586,12 +1650,10 @@ function renderEndpointDetails(endpoint) {
|
|
|
1586
1650
|
section.className = 'endpoint-subsection';
|
|
1587
1651
|
const contentType = Object.keys(reqBody.content)[0];
|
|
1588
1652
|
section.innerHTML = `<div class="subsection-label">REQUEST BODY${reqBody.required ? ' <span style="color:#ef4444">required</span>' : ''}${contentType ? ` · ${esc(contentType)}` : ''}</div>`;
|
|
1589
|
-
const
|
|
1590
|
-
if (
|
|
1591
|
-
renderSchemaTree(section,
|
|
1592
|
-
|
|
1593
|
-
}
|
|
1594
|
-
container.appendChild(section);
|
|
1653
|
+
const bodyContent = reqBody.content[contentType];
|
|
1654
|
+
if (bodyContent?.schema)
|
|
1655
|
+
renderSchemaTree(section, bodyContent.schema);
|
|
1656
|
+
left.appendChild(section);
|
|
1595
1657
|
}
|
|
1596
1658
|
const responses = data.responses;
|
|
1597
1659
|
if (responses && Object.keys(responses).length > 0) {
|
|
@@ -1611,14 +1673,25 @@ function renderEndpointDetails(endpoint) {
|
|
|
1611
1673
|
if (first)
|
|
1612
1674
|
first.classList.add('open');
|
|
1613
1675
|
}
|
|
1614
|
-
|
|
1676
|
+
left.appendChild(section);
|
|
1677
|
+
}
|
|
1678
|
+
// Right column: request samples (cURL / JavaScript / Python / Rust).
|
|
1679
|
+
const samplesSection = doc.createElement('div');
|
|
1680
|
+
samplesSection.className = 'endpoint-right-section';
|
|
1681
|
+
samplesSection.innerHTML = '<div class="endpoint-right-header">Request samples</div>';
|
|
1682
|
+
samplesSection.appendChild(renderCodeExamples(endpoint, data));
|
|
1683
|
+
right.appendChild(samplesSection);
|
|
1684
|
+
// Right column: response samples (JSON examples per status code).
|
|
1685
|
+
if (responses && Object.keys(responses).length > 0) {
|
|
1686
|
+
const respSamples = doc.createElement('div');
|
|
1687
|
+
respSamples.className = 'endpoint-right-section';
|
|
1688
|
+
respSamples.innerHTML = '<div class="endpoint-right-header">Response samples</div>';
|
|
1689
|
+
respSamples.appendChild(renderResponseSamples(responses));
|
|
1690
|
+
right.appendChild(respSamples);
|
|
1615
1691
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
examplesSection.innerHTML = '<div class="subsection-label">REQUEST SAMPLES</div>';
|
|
1620
|
-
examplesSection.appendChild(renderCodeExamples(endpoint, data));
|
|
1621
|
-
container.appendChild(examplesSection);
|
|
1692
|
+
content.appendChild(left);
|
|
1693
|
+
content.appendChild(right);
|
|
1694
|
+
container.appendChild(content);
|
|
1622
1695
|
}
|
|
1623
1696
|
if (activeProtocol === 'websocket') {
|
|
1624
1697
|
appendInfoGrid(container, [['Channel Type', data.type], ['Path', endpoint.path]]);
|
|
@@ -1901,23 +1974,35 @@ function pageNavCard(entry, label, direction) {
|
|
|
1901
1974
|
button.onclick = () => setDocsPage(entry.path);
|
|
1902
1975
|
return button;
|
|
1903
1976
|
}
|
|
1977
|
+
function setTocColumn(visible) {
|
|
1978
|
+
const shell = doc.querySelector?.('.main-shell');
|
|
1979
|
+
if (shell)
|
|
1980
|
+
shell.classList.toggle('main-shell-no-toc', !visible);
|
|
1981
|
+
}
|
|
1904
1982
|
function renderToc(root) {
|
|
1905
1983
|
const toc = byId('pageToc');
|
|
1906
1984
|
if (!toc)
|
|
1907
1985
|
return;
|
|
1908
1986
|
toc.textContent = '';
|
|
1909
|
-
if (tocConfig.enabled === false)
|
|
1987
|
+
if (tocConfig.enabled === false) {
|
|
1988
|
+
setTocColumn(false);
|
|
1910
1989
|
return;
|
|
1911
|
-
|
|
1990
|
+
}
|
|
1991
|
+
if (root.querySelector?.('[data-markdown-ignore-all="true"]')) {
|
|
1992
|
+
setTocColumn(false);
|
|
1912
1993
|
return;
|
|
1994
|
+
}
|
|
1913
1995
|
const min = Number(tocConfig.minLevel ?? 2);
|
|
1914
1996
|
const max = Number(tocConfig.maxLevel ?? 3);
|
|
1915
1997
|
const headings = Array.from(root.querySelectorAll('h1,h2,h3,h4,h5,h6') ?? []).filter((heading) => {
|
|
1916
1998
|
const level = Number(heading.tagName.slice(1));
|
|
1917
1999
|
return heading.id && level >= min && level <= max && heading.dataset?.markdownIgnore !== 'true';
|
|
1918
2000
|
});
|
|
1919
|
-
if (headings.length === 0)
|
|
2001
|
+
if (headings.length === 0) {
|
|
2002
|
+
setTocColumn(false);
|
|
1920
2003
|
return;
|
|
2004
|
+
}
|
|
2005
|
+
setTocColumn(true);
|
|
1921
2006
|
const title = doc.createElement('div');
|
|
1922
2007
|
title.className = 'toc-title';
|
|
1923
2008
|
title.textContent = 'On this page';
|
|
@@ -1385,20 +1385,76 @@ function renderCodeExamples(endpoint, data) {
|
|
|
1385
1385
|
return wrap;
|
|
1386
1386
|
}
|
|
1387
1387
|
// Append a JSON example block to a container.
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1388
|
+
// Syntax-highlight a JSON value into HTML using the .sample-json token classes.
|
|
1389
|
+
function highlightJsonHtml(value) {
|
|
1390
|
+
let json = JSON.stringify(value, null, 2);
|
|
1391
|
+
if (json === undefined)
|
|
1392
|
+
return '';
|
|
1393
|
+
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1394
|
+
return json.replace(/("(?:\\.|[^"\\])*"(\s*:)?|\b(?:true|false|null)\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g, (match, _token, colon) => {
|
|
1395
|
+
let cls = 'json-number';
|
|
1396
|
+
if (match[0] === '"')
|
|
1397
|
+
cls = colon ? 'json-key' : 'json-string';
|
|
1398
|
+
else if (match === 'true' || match === 'false')
|
|
1399
|
+
cls = 'json-boolean';
|
|
1400
|
+
else if (match === 'null')
|
|
1401
|
+
cls = 'json-null';
|
|
1402
|
+
return `<span class="${cls}">${match}</span>`;
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
// Right-panel response samples: one status tab per response, each showing the
|
|
1406
|
+
// generated JSON example (colorized) — ReDoc's response sample switcher.
|
|
1407
|
+
function renderResponseSamples(responses) {
|
|
1408
|
+
const wrap = doc.createElement('div');
|
|
1409
|
+
const tabs = doc.createElement('div');
|
|
1410
|
+
tabs.className = 'sample-tabs';
|
|
1411
|
+
const contents = doc.createElement('div');
|
|
1412
|
+
contents.className = 'sample-contents';
|
|
1413
|
+
const entries = Object.entries(responses);
|
|
1414
|
+
entries.forEach(([status, resp], index) => {
|
|
1415
|
+
const statusClass = status.startsWith('2') ? 'status-2xx'
|
|
1416
|
+
: status.startsWith('4') ? 'status-4xx'
|
|
1417
|
+
: status.startsWith('5') ? 'status-5xx'
|
|
1418
|
+
: '';
|
|
1419
|
+
const tab = doc.createElement('button');
|
|
1420
|
+
tab.type = 'button';
|
|
1421
|
+
tab.className = `sample-tab ${statusClass}${index === 0 ? ' active' : ''}`;
|
|
1422
|
+
tab.textContent = status;
|
|
1423
|
+
const content = doc.createElement('div');
|
|
1424
|
+
content.className = `sample-content${index === 0 ? ' active' : ''}`;
|
|
1425
|
+
const ct = resp.content ? Object.keys(resp.content)[0] : null;
|
|
1426
|
+
const schema = ct ? resp.content[ct]?.schema : null;
|
|
1427
|
+
const example = schema ? generateExampleFromSchema(schema) : null;
|
|
1428
|
+
if (example !== null && example !== undefined) {
|
|
1429
|
+
if (ct) {
|
|
1430
|
+
const typeLine = doc.createElement('div');
|
|
1431
|
+
typeLine.className = 'sample-content-type';
|
|
1432
|
+
typeLine.textContent = ct;
|
|
1433
|
+
content.appendChild(typeLine);
|
|
1434
|
+
}
|
|
1435
|
+
const pre = doc.createElement('pre');
|
|
1436
|
+
pre.className = 'sample-json';
|
|
1437
|
+
pre.innerHTML = highlightJsonHtml(example);
|
|
1438
|
+
content.appendChild(pre);
|
|
1439
|
+
}
|
|
1440
|
+
else {
|
|
1441
|
+
const empty = doc.createElement('div');
|
|
1442
|
+
empty.className = 'no-example';
|
|
1443
|
+
empty.textContent = resp.description || 'No response body.';
|
|
1444
|
+
content.appendChild(empty);
|
|
1445
|
+
}
|
|
1446
|
+
tab.onclick = () => {
|
|
1447
|
+
tabs.querySelectorAll('.sample-tab').forEach((t) => t.classList.remove('active'));
|
|
1448
|
+
contents.querySelectorAll('.sample-content').forEach((c) => c.classList.remove('active'));
|
|
1449
|
+
tab.classList.add('active');
|
|
1450
|
+
content.classList.add('active');
|
|
1451
|
+
};
|
|
1452
|
+
tabs.appendChild(tab);
|
|
1453
|
+
contents.appendChild(content);
|
|
1454
|
+
});
|
|
1455
|
+
wrap.appendChild(tabs);
|
|
1456
|
+
wrap.appendChild(contents);
|
|
1457
|
+
return wrap;
|
|
1402
1458
|
}
|
|
1403
1459
|
function renderSchemaTree(parent, schema, depth = 0) {
|
|
1404
1460
|
if (!schema)
|
|
@@ -1541,7 +1597,6 @@ function renderResponseAccordion(status, resp, openByDefault) {
|
|
|
1541
1597
|
sub.textContent = `Response Body${contentType ? ` · ${contentType}` : ''}`;
|
|
1542
1598
|
block.appendChild(sub);
|
|
1543
1599
|
renderSchemaTree(block, schema);
|
|
1544
|
-
appendJsonExample(block, generateExampleFromSchema(schema));
|
|
1545
1600
|
body.appendChild(block);
|
|
1546
1601
|
}
|
|
1547
1602
|
if (!body.children.length) {
|
|
@@ -1562,6 +1617,15 @@ function renderEndpointDetails(endpoint) {
|
|
|
1562
1617
|
appendProtocolConsole(container, { doc, spec, wsSpec, streamsSpec, jsonrpcSpec, activeProtocol, endpoint, data, esc, escapeAttr });
|
|
1563
1618
|
const appendMany = (items) => items.forEach(([title, value]) => appendSchemaSubsection(container, title, value));
|
|
1564
1619
|
if (activeProtocol === 'http') {
|
|
1620
|
+
// Two-column operation layout (ReDoc-style): the left column carries the
|
|
1621
|
+
// contract (params + schemas + responses); the right column is a sticky
|
|
1622
|
+
// dark panel with the request samples and response examples.
|
|
1623
|
+
const content = doc.createElement('div');
|
|
1624
|
+
content.className = 'endpoint-content';
|
|
1625
|
+
const left = doc.createElement('div');
|
|
1626
|
+
left.className = 'endpoint-left';
|
|
1627
|
+
const right = doc.createElement('div');
|
|
1628
|
+
right.className = 'endpoint-right';
|
|
1565
1629
|
const params = (data.parameters ?? []);
|
|
1566
1630
|
if (params.length > 0) {
|
|
1567
1631
|
const section = doc.createElement('div');
|
|
@@ -1578,7 +1642,7 @@ function renderEndpointDetails(endpoint) {
|
|
|
1578
1642
|
if (inGroup.length > 0)
|
|
1579
1643
|
section.appendChild(renderParamGroup(title, inGroup));
|
|
1580
1644
|
});
|
|
1581
|
-
|
|
1645
|
+
left.appendChild(section);
|
|
1582
1646
|
}
|
|
1583
1647
|
const reqBody = data.requestBody;
|
|
1584
1648
|
if (reqBody?.content) {
|
|
@@ -1586,12 +1650,10 @@ function renderEndpointDetails(endpoint) {
|
|
|
1586
1650
|
section.className = 'endpoint-subsection';
|
|
1587
1651
|
const contentType = Object.keys(reqBody.content)[0];
|
|
1588
1652
|
section.innerHTML = `<div class="subsection-label">REQUEST BODY${reqBody.required ? ' <span style="color:#ef4444">required</span>' : ''}${contentType ? ` · ${esc(contentType)}` : ''}</div>`;
|
|
1589
|
-
const
|
|
1590
|
-
if (
|
|
1591
|
-
renderSchemaTree(section,
|
|
1592
|
-
|
|
1593
|
-
}
|
|
1594
|
-
container.appendChild(section);
|
|
1653
|
+
const bodyContent = reqBody.content[contentType];
|
|
1654
|
+
if (bodyContent?.schema)
|
|
1655
|
+
renderSchemaTree(section, bodyContent.schema);
|
|
1656
|
+
left.appendChild(section);
|
|
1595
1657
|
}
|
|
1596
1658
|
const responses = data.responses;
|
|
1597
1659
|
if (responses && Object.keys(responses).length > 0) {
|
|
@@ -1611,14 +1673,25 @@ function renderEndpointDetails(endpoint) {
|
|
|
1611
1673
|
if (first)
|
|
1612
1674
|
first.classList.add('open');
|
|
1613
1675
|
}
|
|
1614
|
-
|
|
1676
|
+
left.appendChild(section);
|
|
1677
|
+
}
|
|
1678
|
+
// Right column: request samples (cURL / JavaScript / Python / Rust).
|
|
1679
|
+
const samplesSection = doc.createElement('div');
|
|
1680
|
+
samplesSection.className = 'endpoint-right-section';
|
|
1681
|
+
samplesSection.innerHTML = '<div class="endpoint-right-header">Request samples</div>';
|
|
1682
|
+
samplesSection.appendChild(renderCodeExamples(endpoint, data));
|
|
1683
|
+
right.appendChild(samplesSection);
|
|
1684
|
+
// Right column: response samples (JSON examples per status code).
|
|
1685
|
+
if (responses && Object.keys(responses).length > 0) {
|
|
1686
|
+
const respSamples = doc.createElement('div');
|
|
1687
|
+
respSamples.className = 'endpoint-right-section';
|
|
1688
|
+
respSamples.innerHTML = '<div class="endpoint-right-header">Response samples</div>';
|
|
1689
|
+
respSamples.appendChild(renderResponseSamples(responses));
|
|
1690
|
+
right.appendChild(respSamples);
|
|
1615
1691
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
examplesSection.innerHTML = '<div class="subsection-label">REQUEST SAMPLES</div>';
|
|
1620
|
-
examplesSection.appendChild(renderCodeExamples(endpoint, data));
|
|
1621
|
-
container.appendChild(examplesSection);
|
|
1692
|
+
content.appendChild(left);
|
|
1693
|
+
content.appendChild(right);
|
|
1694
|
+
container.appendChild(content);
|
|
1622
1695
|
}
|
|
1623
1696
|
if (activeProtocol === 'websocket') {
|
|
1624
1697
|
appendInfoGrid(container, [['Channel Type', data.type], ['Path', endpoint.path]]);
|
|
@@ -1901,23 +1974,35 @@ function pageNavCard(entry, label, direction) {
|
|
|
1901
1974
|
button.onclick = () => setDocsPage(entry.path);
|
|
1902
1975
|
return button;
|
|
1903
1976
|
}
|
|
1977
|
+
function setTocColumn(visible) {
|
|
1978
|
+
const shell = doc.querySelector?.('.main-shell');
|
|
1979
|
+
if (shell)
|
|
1980
|
+
shell.classList.toggle('main-shell-no-toc', !visible);
|
|
1981
|
+
}
|
|
1904
1982
|
function renderToc(root) {
|
|
1905
1983
|
const toc = byId('pageToc');
|
|
1906
1984
|
if (!toc)
|
|
1907
1985
|
return;
|
|
1908
1986
|
toc.textContent = '';
|
|
1909
|
-
if (tocConfig.enabled === false)
|
|
1987
|
+
if (tocConfig.enabled === false) {
|
|
1988
|
+
setTocColumn(false);
|
|
1910
1989
|
return;
|
|
1911
|
-
|
|
1990
|
+
}
|
|
1991
|
+
if (root.querySelector?.('[data-markdown-ignore-all="true"]')) {
|
|
1992
|
+
setTocColumn(false);
|
|
1912
1993
|
return;
|
|
1994
|
+
}
|
|
1913
1995
|
const min = Number(tocConfig.minLevel ?? 2);
|
|
1914
1996
|
const max = Number(tocConfig.maxLevel ?? 3);
|
|
1915
1997
|
const headings = Array.from(root.querySelectorAll('h1,h2,h3,h4,h5,h6') ?? []).filter((heading) => {
|
|
1916
1998
|
const level = Number(heading.tagName.slice(1));
|
|
1917
1999
|
return heading.id && level >= min && level <= max && heading.dataset?.markdownIgnore !== 'true';
|
|
1918
2000
|
});
|
|
1919
|
-
if (headings.length === 0)
|
|
2001
|
+
if (headings.length === 0) {
|
|
2002
|
+
setTocColumn(false);
|
|
1920
2003
|
return;
|
|
2004
|
+
}
|
|
2005
|
+
setTocColumn(true);
|
|
1921
2006
|
const title = doc.createElement('div');
|
|
1922
2007
|
title.className = 'toc-title';
|
|
1923
2008
|
title.textContent = 'On this page';
|