@blaaiz/docs-core 0.5.0 → 0.7.0
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/{chunk-ZKOOKLZ3.js → chunk-6H6OB7YP.js} +17 -2
- package/dist/chunk-6H6OB7YP.js.map +1 -0
- package/dist/{chunk-ZWDLAW5M.js → chunk-L4PFRXIK.js} +231 -28
- package/dist/chunk-L4PFRXIK.js.map +1 -0
- package/dist/generator.cjs +161 -18
- package/dist/generator.cjs.map +1 -1
- package/dist/generator.d.cts +24 -0
- package/dist/generator.d.ts +24 -0
- package/dist/generator.js +140 -13
- package/dist/generator.js.map +1 -1
- package/dist/index.cjs +233 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +258 -7
- package/dist/index.d.ts +258 -7
- package/dist/index.js +1 -1
- package/dist/{navigation-CGqFIPlP.d.cts → navigation-DvgyWSZ4.d.cts} +22 -1
- package/dist/{navigation-CGqFIPlP.d.ts → navigation-DvgyWSZ4.d.ts} +22 -1
- package/dist/ui/api-try-it.cjs +19 -1
- package/dist/ui/api-try-it.cjs.map +1 -1
- package/dist/ui/api-try-it.d.cts +4 -2
- package/dist/ui/api-try-it.d.ts +4 -2
- package/dist/ui/api-try-it.js +5 -2
- package/dist/ui/api-try-it.js.map +1 -1
- package/dist/ui/ask-ai.cjs +26 -6
- package/dist/ui/ask-ai.cjs.map +1 -1
- package/dist/ui/ask-ai.d.cts +6 -1
- package/dist/ui/ask-ai.d.ts +6 -1
- package/dist/ui/ask-ai.js +26 -6
- package/dist/ui/ask-ai.js.map +1 -1
- package/dist/ui/copy-page.cjs +15 -0
- package/dist/ui/copy-page.cjs.map +1 -1
- package/dist/ui/copy-page.js +1 -1
- package/dist/ui.cjs +77 -6
- package/dist/ui.cjs.map +1 -1
- package/dist/ui.d.cts +99 -8
- package/dist/ui.d.ts +99 -8
- package/dist/ui.js +62 -8
- package/dist/ui.js.map +1 -1
- package/package.json +1 -1
- package/skills/SKILL.md +68 -27
- package/styles/api-reference.css +45 -2
- package/styles/ask-ai.css +28 -0
- package/styles/docs.css +96 -1
- package/styles/home.css +34 -1
- package/dist/chunk-ZKOOKLZ3.js.map +0 -1
- package/dist/chunk-ZWDLAW5M.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -970,6 +970,15 @@ function createProvider(resolved, apiKey, doFetch) {
|
|
|
970
970
|
return resolved.provider === "anthropic" ? createAnthropicProvider(providerOptions) : createOpenAiProvider(providerOptions);
|
|
971
971
|
}
|
|
972
972
|
function createAskAiRoute(options) {
|
|
973
|
+
if (options.config === void 0) {
|
|
974
|
+
return {
|
|
975
|
+
POST: () => Promise.resolve(
|
|
976
|
+
jsonResponse(404, {
|
|
977
|
+
error: "Ask AI is not enabled: docs.config.ts declares no ai block."
|
|
978
|
+
})
|
|
979
|
+
)
|
|
980
|
+
};
|
|
981
|
+
}
|
|
973
982
|
const resolved = resolveAiConfig(options.config);
|
|
974
983
|
if (typeof options.siteName !== "string" || options.siteName.trim() === "") {
|
|
975
984
|
throw new AiConfigError("siteName must be a non-empty string, e.g. theme.name.");
|
|
@@ -1363,6 +1372,22 @@ function validateFeatures(value) {
|
|
|
1363
1372
|
}
|
|
1364
1373
|
optionalBoolean(features["copyPage"], "features.copyPage");
|
|
1365
1374
|
}
|
|
1375
|
+
function validateNavbarAction(value, field) {
|
|
1376
|
+
const action = optionalObject(value, field);
|
|
1377
|
+
if (action === void 0) {
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
requireString(action["text"], `${field}.text`, "Example: 'Dashboard'.");
|
|
1381
|
+
requireString(action["href"], `${field}.href`, "Example: 'https://app.example.com'.");
|
|
1382
|
+
}
|
|
1383
|
+
function validateNavbar(value) {
|
|
1384
|
+
const navbar = optionalObject(value, "navbar");
|
|
1385
|
+
if (navbar === void 0) {
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
validateNavbarAction(navbar["primary"], "navbar.primary");
|
|
1389
|
+
validateNavbarAction(navbar["secondary"], "navbar.secondary");
|
|
1390
|
+
}
|
|
1366
1391
|
function validateSeo(value) {
|
|
1367
1392
|
const seo = optionalObject(value, "seo");
|
|
1368
1393
|
if (seo === void 0) {
|
|
@@ -1413,6 +1438,7 @@ function validateDocsConfig(config) {
|
|
|
1413
1438
|
validateTheme(config["theme"]);
|
|
1414
1439
|
validateAuth(config["auth"]);
|
|
1415
1440
|
validateProxy(config["proxy"]);
|
|
1441
|
+
validateNavbar(config["navbar"]);
|
|
1416
1442
|
validateFeatures(config["features"]);
|
|
1417
1443
|
validateSeo(config["seo"]);
|
|
1418
1444
|
if (config["ai"] !== void 0) {
|
|
@@ -1460,6 +1486,90 @@ function buildThemeCss(theme) {
|
|
|
1460
1486
|
return blocks.join("\n");
|
|
1461
1487
|
}
|
|
1462
1488
|
|
|
1489
|
+
// src/core/redirects.ts
|
|
1490
|
+
function redirectTarget(url, redirects) {
|
|
1491
|
+
const { pathname } = url;
|
|
1492
|
+
const markdown = pathname.endsWith(".md");
|
|
1493
|
+
const page = markdown ? pathname.slice(0, -3) : pathname;
|
|
1494
|
+
const destination = redirects[page];
|
|
1495
|
+
if (destination === void 0) {
|
|
1496
|
+
return null;
|
|
1497
|
+
}
|
|
1498
|
+
const target = new URL(url);
|
|
1499
|
+
target.pathname = markdown ? `${destination}.md` : destination;
|
|
1500
|
+
return target;
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
// src/core/llms-txt.ts
|
|
1504
|
+
function buildLlmsTxt(pages, options) {
|
|
1505
|
+
const origin = options.origin?.replace(/\/$/, "") ?? "";
|
|
1506
|
+
const lines = [`# ${options.name}`];
|
|
1507
|
+
if (options.description !== void 0 && options.description !== "") {
|
|
1508
|
+
lines.push("", `> ${options.description}`);
|
|
1509
|
+
}
|
|
1510
|
+
lines.push("", "## Docs", "");
|
|
1511
|
+
for (const page of pages) {
|
|
1512
|
+
const link = `[${page.title}](${origin}${page.url}.md)`;
|
|
1513
|
+
lines.push(
|
|
1514
|
+
page.description === void 0 || page.description === "" ? `- ${link}` : `- ${link}: ${page.description}`
|
|
1515
|
+
);
|
|
1516
|
+
}
|
|
1517
|
+
lines.push("");
|
|
1518
|
+
return lines.join("\n");
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
// src/core/code-samples.ts
|
|
1522
|
+
function singleQuote(value) {
|
|
1523
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
1524
|
+
}
|
|
1525
|
+
function isRecord(value) {
|
|
1526
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1527
|
+
}
|
|
1528
|
+
function bodyToString(body, mediaType) {
|
|
1529
|
+
if (typeof body === "string") {
|
|
1530
|
+
return body;
|
|
1531
|
+
}
|
|
1532
|
+
if (mediaType === "application/x-www-form-urlencoded" && isRecord(body)) {
|
|
1533
|
+
const params = new URLSearchParams();
|
|
1534
|
+
for (const [key, value] of Object.entries(body)) {
|
|
1535
|
+
if (value === void 0 || value === null) {
|
|
1536
|
+
continue;
|
|
1537
|
+
}
|
|
1538
|
+
const encoded = typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
|
|
1539
|
+
params.set(key, encoded);
|
|
1540
|
+
}
|
|
1541
|
+
return params.toString();
|
|
1542
|
+
}
|
|
1543
|
+
if (mediaType === "application/x-ndjson" && Array.isArray(body)) {
|
|
1544
|
+
return body.map((entry) => JSON.stringify(entry)).join("\n");
|
|
1545
|
+
}
|
|
1546
|
+
return JSON.stringify(body, null, 2);
|
|
1547
|
+
}
|
|
1548
|
+
var curlCodeUsage = {
|
|
1549
|
+
label: "cURL",
|
|
1550
|
+
lang: "bash",
|
|
1551
|
+
generate(data) {
|
|
1552
|
+
const lines = [`curl --request ${data.method.toUpperCase()}`, `--url ${singleQuote(data.url)}`];
|
|
1553
|
+
for (const [name, param] of Object.entries(data.header ?? {})) {
|
|
1554
|
+
lines.push(`--header ${singleQuote(`${name}: ${param.value}`)}`);
|
|
1555
|
+
}
|
|
1556
|
+
for (const [name, param] of Object.entries(data.cookie ?? {})) {
|
|
1557
|
+
lines.push(`--cookie ${singleQuote(`${name}=${param.value}`)}`);
|
|
1558
|
+
}
|
|
1559
|
+
if (isRecord(data.body) && data.bodyMediaType === "multipart/form-data") {
|
|
1560
|
+
for (const [key, value] of Object.entries(data.body)) {
|
|
1561
|
+
lines.push(
|
|
1562
|
+
`--form ${singleQuote(`${key}=${typeof value === "string" ? value : JSON.stringify(value)}`)}`
|
|
1563
|
+
);
|
|
1564
|
+
}
|
|
1565
|
+
} else if (data.body !== void 0 && data.body !== null && data.bodyMediaType !== void 0) {
|
|
1566
|
+
lines.push(`--header ${singleQuote(`Content-Type: ${data.bodyMediaType}`)}`);
|
|
1567
|
+
lines.push(`--data ${singleQuote(bodyToString(data.body, data.bodyMediaType))}`);
|
|
1568
|
+
}
|
|
1569
|
+
return lines.map((line, i) => i === 0 ? line : ` ${line}`).join(" \\\n");
|
|
1570
|
+
}
|
|
1571
|
+
};
|
|
1572
|
+
|
|
1463
1573
|
// src/core/seo.ts
|
|
1464
1574
|
function trimTrailingSlash(value) {
|
|
1465
1575
|
return value.replace(/\/+$/, "");
|
|
@@ -1562,6 +1672,7 @@ function firstDocFile(items) {
|
|
|
1562
1672
|
}
|
|
1563
1673
|
function planDocsTree(navigation, options = {}) {
|
|
1564
1674
|
const apiDir = options.apiDir ?? "api";
|
|
1675
|
+
const headings = (options.sidebar ?? "collapsible") === "headings";
|
|
1565
1676
|
const specs = [];
|
|
1566
1677
|
const apiPages = [];
|
|
1567
1678
|
const apiGroups = [];
|
|
@@ -1609,7 +1720,7 @@ function planDocsTree(navigation, options = {}) {
|
|
|
1609
1720
|
const at = apiGroups.length;
|
|
1610
1721
|
const sub = planApiItems(item.items, childDir);
|
|
1611
1722
|
apiGroups.splice(at, 0, { dir: childDir, title: item.title, children: sub });
|
|
1612
|
-
children.push({ order, folder });
|
|
1723
|
+
children.push({ order, folder, title: item.title });
|
|
1613
1724
|
order += 1;
|
|
1614
1725
|
continue;
|
|
1615
1726
|
}
|
|
@@ -1647,11 +1758,11 @@ function planDocsTree(navigation, options = {}) {
|
|
|
1647
1758
|
title: tab.title,
|
|
1648
1759
|
root: true,
|
|
1649
1760
|
...tab.icon ? { icon: tab.icon } : {},
|
|
1650
|
-
pages: planDocItems(tab.items, tabDir)
|
|
1761
|
+
pages: planDocItems(tab.items, tabDir, true)
|
|
1651
1762
|
}
|
|
1652
1763
|
});
|
|
1653
1764
|
}
|
|
1654
|
-
function planDocItems(items, dir) {
|
|
1765
|
+
function planDocItems(items, dir, tabLevel) {
|
|
1655
1766
|
const entries = [];
|
|
1656
1767
|
for (const item of items) {
|
|
1657
1768
|
if (item.kind === "doc") {
|
|
@@ -1666,10 +1777,18 @@ function planDocsTree(navigation, options = {}) {
|
|
|
1666
1777
|
continue;
|
|
1667
1778
|
}
|
|
1668
1779
|
if (groupDir === dir) {
|
|
1669
|
-
|
|
1780
|
+
if (headings) {
|
|
1781
|
+
entries.push(`---${item.title}---`);
|
|
1782
|
+
}
|
|
1783
|
+
entries.push(...planDocItems(item.items, dir, false));
|
|
1670
1784
|
continue;
|
|
1671
1785
|
}
|
|
1672
|
-
|
|
1786
|
+
const folder = groupDir.slice(dir.length + 1);
|
|
1787
|
+
if (headings && tabLevel) {
|
|
1788
|
+
entries.push(`---${item.title}---`, `...${folder}`);
|
|
1789
|
+
continue;
|
|
1790
|
+
}
|
|
1791
|
+
entries.push(folder);
|
|
1673
1792
|
}
|
|
1674
1793
|
return entries;
|
|
1675
1794
|
}
|
|
@@ -1684,7 +1803,14 @@ function planDocsTree(navigation, options = {}) {
|
|
|
1684
1803
|
}
|
|
1685
1804
|
metas.push({
|
|
1686
1805
|
path: `${groupDir}/meta.json`,
|
|
1687
|
-
content: {
|
|
1806
|
+
content: {
|
|
1807
|
+
title: group.title,
|
|
1808
|
+
// A nested group starts closed in the headings style, whatever the
|
|
1809
|
+
// site's defaultOpenLevel. On a tab-level group the flag is inert:
|
|
1810
|
+
// that folder is extracted, so no folder node renders it.
|
|
1811
|
+
...headings ? { defaultOpen: false } : {},
|
|
1812
|
+
pages: planDocItems(group.items, groupDir, false)
|
|
1813
|
+
}
|
|
1688
1814
|
});
|
|
1689
1815
|
return groupDir;
|
|
1690
1816
|
}
|
|
@@ -2117,10 +2243,67 @@ ${description ? `${description}
|
|
|
2117
2243
|
` : ""}${cleanBody(trimmedBody)}
|
|
2118
2244
|
`;
|
|
2119
2245
|
}
|
|
2246
|
+
function operationHead(operation) {
|
|
2247
|
+
let title;
|
|
2248
|
+
let description;
|
|
2249
|
+
try {
|
|
2250
|
+
const parsed = JSON.parse(operation.source);
|
|
2251
|
+
const exact = parsed.paths?.[operation.route]?.[operation.method.toLowerCase()];
|
|
2252
|
+
const first = Object.values(parsed.paths ?? {}).flatMap((item) => Object.values(item))[0];
|
|
2253
|
+
const named = exact ?? first;
|
|
2254
|
+
title = named?.summary ?? parsed.info?.title;
|
|
2255
|
+
description = named?.description ?? parsed.info?.description;
|
|
2256
|
+
} catch {
|
|
2257
|
+
}
|
|
2258
|
+
const head = [`# ${title ?? "API operation"}`];
|
|
2259
|
+
if (description !== void 0 && description !== "") {
|
|
2260
|
+
head.push("", `> ${description.replace(/\n/g, "\n> ")}`);
|
|
2261
|
+
}
|
|
2262
|
+
return head.join("\n");
|
|
2263
|
+
}
|
|
2264
|
+
function fenceFor(source) {
|
|
2265
|
+
const longest = source.match(/`+/g)?.reduce((max, run) => Math.max(max, run.length), 0) ?? 0;
|
|
2266
|
+
return "`".repeat(Math.max(4, longest + 1));
|
|
2267
|
+
}
|
|
2120
2268
|
function createMarkdownRoute(options) {
|
|
2269
|
+
const requestOrigin = (request) => {
|
|
2270
|
+
const url = new URL(request.url);
|
|
2271
|
+
const proto = request.headers.get("x-forwarded-proto") ?? url.protocol.replace(/:$/, "");
|
|
2272
|
+
const host = request.headers.get("x-forwarded-host") ?? request.headers.get("host") ?? url.host;
|
|
2273
|
+
return `${proto}://${host}`;
|
|
2274
|
+
};
|
|
2275
|
+
const respond = (request, markdown) => {
|
|
2276
|
+
const preamble = options.llmsTxtPath === void 0 ? "" : [
|
|
2277
|
+
"> ## Documentation Index",
|
|
2278
|
+
`> Fetch the complete documentation index at: ${requestOrigin(request)}${options.llmsTxtPath}`,
|
|
2279
|
+
"> Use this file to discover all available pages before exploring further.",
|
|
2280
|
+
"",
|
|
2281
|
+
""
|
|
2282
|
+
].join("\n");
|
|
2283
|
+
return new Response(`${preamble}${markdown}`, {
|
|
2284
|
+
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
2285
|
+
});
|
|
2286
|
+
};
|
|
2121
2287
|
return {
|
|
2122
|
-
async GET(
|
|
2288
|
+
async GET(request, context) {
|
|
2123
2289
|
const { slug } = await context.params;
|
|
2290
|
+
const operation = await options.loadOperationSource?.(slug);
|
|
2291
|
+
if (operation) {
|
|
2292
|
+
const fence = fenceFor(operation.source);
|
|
2293
|
+
return respond(
|
|
2294
|
+
request,
|
|
2295
|
+
[
|
|
2296
|
+
operationHead(operation),
|
|
2297
|
+
"",
|
|
2298
|
+
"## OpenAPI",
|
|
2299
|
+
"",
|
|
2300
|
+
`${fence}json ${operation.file} ${operation.method.toLowerCase()} ${operation.route}`,
|
|
2301
|
+
operation.source.trimEnd(),
|
|
2302
|
+
fence,
|
|
2303
|
+
""
|
|
2304
|
+
].join("\n")
|
|
2305
|
+
);
|
|
2306
|
+
}
|
|
2124
2307
|
const raw = await options.read(slug);
|
|
2125
2308
|
if (raw === null) {
|
|
2126
2309
|
return new Response("Not found", { status: 404 });
|
|
@@ -2134,12 +2317,32 @@ function createMarkdownRoute(options) {
|
|
|
2134
2317
|
if (markdown === null) {
|
|
2135
2318
|
return new Response("Not found", { status: 404 });
|
|
2136
2319
|
}
|
|
2137
|
-
return
|
|
2138
|
-
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
2139
|
-
});
|
|
2320
|
+
return respond(request, markdown);
|
|
2140
2321
|
}
|
|
2141
2322
|
};
|
|
2142
2323
|
}
|
|
2324
|
+
function markdownRewriteTarget(url, options = {}) {
|
|
2325
|
+
const baseUrl = (options.baseUrl ?? "/docs").replace(/\/+$/, "");
|
|
2326
|
+
const markdownBase = (options.markdownBase ?? "/md").replace(/\/+$/, "");
|
|
2327
|
+
const { pathname } = url;
|
|
2328
|
+
if (!pathname.endsWith(".md") || pathname.includes("%")) {
|
|
2329
|
+
return null;
|
|
2330
|
+
}
|
|
2331
|
+
const page = pathname.slice(0, -3);
|
|
2332
|
+
if (page !== baseUrl && !page.startsWith(`${baseUrl}/`)) {
|
|
2333
|
+
return null;
|
|
2334
|
+
}
|
|
2335
|
+
if (page.endsWith("/") || page.includes("//")) {
|
|
2336
|
+
return null;
|
|
2337
|
+
}
|
|
2338
|
+
const target = new URL(url);
|
|
2339
|
+
target.pathname = `${markdownBase}${page.slice(baseUrl.length)}`;
|
|
2340
|
+
return target;
|
|
2341
|
+
}
|
|
2342
|
+
function isMarkdownRouteRequest(url, options = {}) {
|
|
2343
|
+
const markdownBase = options.markdownBase ?? "/md";
|
|
2344
|
+
return url.pathname === markdownBase || url.pathname.startsWith(`${markdownBase}/`);
|
|
2345
|
+
}
|
|
2143
2346
|
|
|
2144
2347
|
// src/core/auth/domains.ts
|
|
2145
2348
|
function isAllowedEmail(email, allowedDomains) {
|
|
@@ -2923,7 +3126,7 @@ var InvalidNavigationError = class extends Error {
|
|
|
2923
3126
|
this.name = "InvalidNavigationError";
|
|
2924
3127
|
}
|
|
2925
3128
|
};
|
|
2926
|
-
function
|
|
3129
|
+
function isRecord2(value) {
|
|
2927
3130
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2928
3131
|
}
|
|
2929
3132
|
function parsePageString(entry) {
|
|
@@ -2946,7 +3149,7 @@ function parseItem(entry, path) {
|
|
|
2946
3149
|
if (typeof entry === "string") {
|
|
2947
3150
|
return parsePageString(entry);
|
|
2948
3151
|
}
|
|
2949
|
-
if (
|
|
3152
|
+
if (isRecord2(entry) && typeof entry["group"] === "string") {
|
|
2950
3153
|
return parseGroup(entry, path);
|
|
2951
3154
|
}
|
|
2952
3155
|
throw new InvalidNavigationError(
|
|
@@ -2971,7 +3174,7 @@ function parseGroup(group, path) {
|
|
|
2971
3174
|
};
|
|
2972
3175
|
}
|
|
2973
3176
|
function parseTab(tab, path) {
|
|
2974
|
-
if (!
|
|
3177
|
+
if (!isRecord2(tab) || typeof tab["tab"] !== "string") {
|
|
2975
3178
|
throw new InvalidNavigationError(`Tab at ${path} is missing a string "tab" title.`);
|
|
2976
3179
|
}
|
|
2977
3180
|
const items = tab["groups"] !== void 0 ? parseGroups(tab["groups"], `${path}.groups`) : parseItems(tab["pages"], `${path}.pages`);
|
|
@@ -2989,18 +3192,18 @@ function parseGroups(groups, path) {
|
|
|
2989
3192
|
}
|
|
2990
3193
|
return groups.map((group, index) => {
|
|
2991
3194
|
const groupPath = `${path}[${String(index)}]`;
|
|
2992
|
-
if (!
|
|
3195
|
+
if (!isRecord2(group)) {
|
|
2993
3196
|
throw new InvalidNavigationError(`Group at ${groupPath} must be an object.`);
|
|
2994
3197
|
}
|
|
2995
3198
|
return parseGroup(group, groupPath);
|
|
2996
3199
|
});
|
|
2997
3200
|
}
|
|
2998
3201
|
function parseNavigation(docsJson) {
|
|
2999
|
-
if (!
|
|
3202
|
+
if (!isRecord2(docsJson)) {
|
|
3000
3203
|
throw new InvalidNavigationError("docs.json must be an object.");
|
|
3001
3204
|
}
|
|
3002
3205
|
const navigation = docsJson["navigation"];
|
|
3003
|
-
if (!
|
|
3206
|
+
if (!isRecord2(navigation)) {
|
|
3004
3207
|
throw new InvalidNavigationError('docs.json must have a "navigation" object.');
|
|
3005
3208
|
}
|
|
3006
3209
|
const tabs = navigation["tabs"];
|
|
@@ -3017,7 +3220,7 @@ var OpenApiMergeError = class extends Error {
|
|
|
3017
3220
|
this.name = "OpenApiMergeError";
|
|
3018
3221
|
}
|
|
3019
3222
|
};
|
|
3020
|
-
function
|
|
3223
|
+
function isRecord3(value) {
|
|
3021
3224
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3022
3225
|
}
|
|
3023
3226
|
function collectServers(inputs, override) {
|
|
@@ -3031,7 +3234,7 @@ function collectServers(inputs, override) {
|
|
|
3031
3234
|
continue;
|
|
3032
3235
|
}
|
|
3033
3236
|
for (const server of servers) {
|
|
3034
|
-
if (
|
|
3237
|
+
if (isRecord3(server) && typeof server["url"] === "string" && !byUrl.has(server["url"])) {
|
|
3035
3238
|
byUrl.set(server["url"], server);
|
|
3036
3239
|
}
|
|
3037
3240
|
}
|
|
@@ -3046,7 +3249,7 @@ function collectTags(inputs) {
|
|
|
3046
3249
|
continue;
|
|
3047
3250
|
}
|
|
3048
3251
|
for (const tag of tags) {
|
|
3049
|
-
if (
|
|
3252
|
+
if (isRecord3(tag) && typeof tag["name"] === "string" && !byName.has(tag["name"])) {
|
|
3050
3253
|
byName.set(tag["name"], tag);
|
|
3051
3254
|
}
|
|
3052
3255
|
}
|
|
@@ -3057,11 +3260,11 @@ function mergeComponents(inputs) {
|
|
|
3057
3260
|
const merged = {};
|
|
3058
3261
|
for (const doc of inputs) {
|
|
3059
3262
|
const components = doc["components"];
|
|
3060
|
-
if (!
|
|
3263
|
+
if (!isRecord3(components)) {
|
|
3061
3264
|
continue;
|
|
3062
3265
|
}
|
|
3063
3266
|
for (const [section, value] of Object.entries(components)) {
|
|
3064
|
-
if (!
|
|
3267
|
+
if (!isRecord3(value)) {
|
|
3065
3268
|
continue;
|
|
3066
3269
|
}
|
|
3067
3270
|
const target = merged[section] ?? (merged[section] = {});
|
|
@@ -3079,12 +3282,12 @@ function assemblePaths(inputs) {
|
|
|
3079
3282
|
const paths = {};
|
|
3080
3283
|
for (const doc of inputs) {
|
|
3081
3284
|
const docPaths = doc["paths"];
|
|
3082
|
-
if (!
|
|
3285
|
+
if (!isRecord3(docPaths)) {
|
|
3083
3286
|
throw new OpenApiMergeError('Each OpenAPI input must have a "paths" object.');
|
|
3084
3287
|
}
|
|
3085
3288
|
const docSecurity = doc["security"];
|
|
3086
3289
|
for (const [route, pathItem] of Object.entries(docPaths)) {
|
|
3087
|
-
if (!
|
|
3290
|
+
if (!isRecord3(pathItem)) {
|
|
3088
3291
|
throw new OpenApiMergeError(`Path item for "${route}" must be an object.`);
|
|
3089
3292
|
}
|
|
3090
3293
|
const target = paths[route] ?? (paths[route] = {});
|
|
@@ -3095,7 +3298,7 @@ function assemblePaths(inputs) {
|
|
|
3095
3298
|
);
|
|
3096
3299
|
}
|
|
3097
3300
|
let resolved = operation;
|
|
3098
|
-
if (HTTP_METHODS2.has(method.toLowerCase()) &&
|
|
3301
|
+
if (HTTP_METHODS2.has(method.toLowerCase()) && isRecord3(operation) && !("security" in operation) && Array.isArray(docSecurity)) {
|
|
3099
3302
|
resolved = { ...operation, security: docSecurity };
|
|
3100
3303
|
}
|
|
3101
3304
|
target[method] = resolved;
|
|
@@ -3106,7 +3309,7 @@ function assemblePaths(inputs) {
|
|
|
3106
3309
|
}
|
|
3107
3310
|
function mergeOpenApiDocuments(inputs, options) {
|
|
3108
3311
|
const records = inputs.map((input, index) => {
|
|
3109
|
-
if (!
|
|
3312
|
+
if (!isRecord3(input)) {
|
|
3110
3313
|
throw new OpenApiMergeError(`OpenAPI input at index ${String(index)} must be an object.`);
|
|
3111
3314
|
}
|
|
3112
3315
|
return input;
|
|
@@ -3130,6 +3333,7 @@ exports.OpenApiMergeError = OpenApiMergeError;
|
|
|
3130
3333
|
exports.ProxyTargetError = ProxyTargetError;
|
|
3131
3334
|
exports.SESSION_COOKIE = SESSION_COOKIE;
|
|
3132
3335
|
exports.assertAllowedTarget = assertAllowedTarget;
|
|
3336
|
+
exports.buildLlmsTxt = buildLlmsTxt;
|
|
3133
3337
|
exports.buildMetadata = buildMetadata;
|
|
3134
3338
|
exports.buildRobots = buildRobots;
|
|
3135
3339
|
exports.buildSearchIndex = buildSearchIndex;
|
|
@@ -3147,14 +3351,18 @@ exports.createSignOut = createSignOut;
|
|
|
3147
3351
|
exports.createSiteAuth = createSiteAuth;
|
|
3148
3352
|
exports.createTryItProxy = createTryItProxy;
|
|
3149
3353
|
exports.createTryItProxyRoute = createTryItProxyRoute;
|
|
3354
|
+
exports.curlCodeUsage = curlCodeUsage;
|
|
3150
3355
|
exports.defineDocsConfig = defineDocsConfig;
|
|
3151
3356
|
exports.isAllowedEmail = isAllowedEmail;
|
|
3357
|
+
exports.isMarkdownRouteRequest = isMarkdownRouteRequest;
|
|
3358
|
+
exports.markdownRewriteTarget = markdownRewriteTarget;
|
|
3152
3359
|
exports.mdxToMarkdown = mdxToMarkdown;
|
|
3153
3360
|
exports.mergeOpenApiDocuments = mergeOpenApiDocuments;
|
|
3154
3361
|
exports.openApiOperationToMarkdown = openApiOperationToMarkdown;
|
|
3155
3362
|
exports.parseNavigation = parseNavigation;
|
|
3156
3363
|
exports.planDocsTree = planDocsTree;
|
|
3157
3364
|
exports.readCookie = readCookie;
|
|
3365
|
+
exports.redirectTarget = redirectTarget;
|
|
3158
3366
|
exports.resolveAiConfig = resolveAiConfig;
|
|
3159
3367
|
exports.searchIndex = searchIndex;
|
|
3160
3368
|
exports.signSession = signSession;
|