@thallylabs/migrate 0.2.40 → 0.2.41
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/README.md +60 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +469 -59
- package/dist/index.js.map +1 -1
- package/dist/url-migration.d.ts +2 -2
- package/dist/url-migration.js +40 -6
- package/dist/url-migration.js.map +1 -1
- package/dist/{url-run-DFnoqEi-.d.ts → url-run-mSKFqHx_.d.ts} +33 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1370,8 +1370,29 @@ ${trimmed.slice(0, marker).trimEnd()}`;
|
|
|
1370
1370
|
function headingIdMarker(id) {
|
|
1371
1371
|
return `{/* #${id} */}`;
|
|
1372
1372
|
}
|
|
1373
|
+
var HEADING_ID_WORD = /[\p{L}\p{M}\p{N}_+&/@\u2019\u201c\u201d\u2014\u2013\u2192]/u;
|
|
1373
1374
|
function mintlifyHeadingSlug(text3) {
|
|
1374
|
-
|
|
1375
|
+
const chars = [...text3.replace(/[\u200b*]/g, "").normalize("NFC").trim().toLowerCase()];
|
|
1376
|
+
const isWord = (char) => char !== void 0 && HEADING_ID_WORD.test(char);
|
|
1377
|
+
let id = "";
|
|
1378
|
+
let afterDash = false;
|
|
1379
|
+
let endsWithDash = false;
|
|
1380
|
+
chars.forEach((char, index) => {
|
|
1381
|
+
const before = chars[index - 1];
|
|
1382
|
+
const after = chars[index + 1];
|
|
1383
|
+
endsWithDash = false;
|
|
1384
|
+
if (isWord(char)) {
|
|
1385
|
+
id += char;
|
|
1386
|
+
afterDash = false;
|
|
1387
|
+
} else if (/[\s-]/.test(char) || char === "." && isWord(after) || char === "(" && isWord(before) && (isWord(after) || after === "{") || char === ")" && after !== void 0 && !/\s/.test(after)) {
|
|
1388
|
+
if (id && !afterDash) id += "-";
|
|
1389
|
+
afterDash = true;
|
|
1390
|
+
endsWithDash = true;
|
|
1391
|
+
} else if (char === "{" || char === ":" || char === '"') {
|
|
1392
|
+
afterDash = false;
|
|
1393
|
+
}
|
|
1394
|
+
});
|
|
1395
|
+
return endsWithDash ? id.replace(/-$/, "") : id;
|
|
1375
1396
|
}
|
|
1376
1397
|
function thallyHeadingSlug(text3) {
|
|
1377
1398
|
return text3.normalize("NFC").toLowerCase().replace(/[^\p{L}\p{M}\p{N}]+/gu, "-").replace(/(^-|-$)/g, "");
|
|
@@ -1383,7 +1404,7 @@ function typesetQuotes(text3) {
|
|
|
1383
1404
|
}).join("");
|
|
1384
1405
|
}
|
|
1385
1406
|
function plainHeadingText(source) {
|
|
1386
|
-
return source.replace(/\{\/\*[\s\S]*?\*\/\}/g, " ").replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/<\/?[A-Za-z][^>]*>/g, "").replace(/`([^`]*)`/g, "$1").replace(/(\*\*|__|~~|\*)/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/\\([\\`*_{}[\]()#+.!&<>|~-])/g, "$1");
|
|
1407
|
+
return source.replace(/\{\/\*[\s\S]*?\*\/\}/g, " ").replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/<\/?[A-Za-z][^>]*>/g, "").replace(/`([^`]*)`/g, "$1").replace(/(?<!\\)(\*\*|__|~~|\*)/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/\\([\\`*_{}[\]()#+.!&<>|~-])/g, "$1");
|
|
1387
1408
|
}
|
|
1388
1409
|
function markMintlifyHeadings(body) {
|
|
1389
1410
|
let fence;
|
|
@@ -2587,7 +2608,7 @@ function normalizeMdx(body, platform, unwrapMdxCodeBlocks = true) {
|
|
|
2587
2608
|
}
|
|
2588
2609
|
if (runMintlify) rewritten = normalizeMintlifyParameterAnchors(rewritten);
|
|
2589
2610
|
rewritten = replaceOutsideCode(rewritten, (segment) => {
|
|
2590
|
-
let result = convertHtmlStyleAttributes(segment).replace(/<!--([\s\S]*?)-->/g, (_match, content) => mdxComment(content)).replace(/<Danger(\s[^>]*)?>/g, "<Error$1>").replace(/<\/Danger>/g, "</Error>").replace(/<Warn(\s[^>]*)?>/g, "<Warning$1>").replace(/<\/Warn>/g, "</Warning>").replace(/<
|
|
2611
|
+
let result = convertHtmlStyleAttributes(segment).replace(/<!--([\s\S]*?)-->/g, (_match, content) => mdxComment(content)).replace(/<Danger(\s[^>]*)?>/g, "<Error$1>").replace(/<\/Danger>/g, "</Error>").replace(/<Warn(\s[^>]*)?>/g, "<Warning$1>").replace(/<\/Warn>/g, "</Warning>").replace(/<Tree\.Folder/g, "<Folder").replace(/<\/Tree\.Folder>/g, "</Folder>").replace(/<Tree\.File/g, "<File").replace(/<\/Tree\.File>/g, "</File>");
|
|
2591
2612
|
if (runDocusaurus) {
|
|
2592
2613
|
result = result.replace(/<TabItem\b([^<>]*)>/g, (_match, attributes) => {
|
|
2593
2614
|
const title = attributes.match(/\blabel=(?:"([^"]*)"|'([^']*)')/)?.slice(1).find(Boolean) ?? attributes.match(/\bvalue=(?:"([^"]*)"|'([^']*)')/)?.slice(1).find(Boolean) ?? "Tab";
|
|
@@ -2596,7 +2617,7 @@ function normalizeMdx(body, platform, unwrapMdxCodeBlocks = true) {
|
|
|
2596
2617
|
result = normalizeDocusaurusLinkTags(result).replace(/<(?:DocCardList|TOCInline)\b[^<>]*\/>/g, "");
|
|
2597
2618
|
}
|
|
2598
2619
|
if (runMintlify) {
|
|
2599
|
-
result = normalizeMintlifyUpdateLabels(result).replace(/<FileTree(\s[^>]*)?>/g, "<Tree$1>").replace(/<\/FileTree>/g, "</Tree>").replace(/<GitHub\.Repo/g, "<GitHub").replace(/<\/GitHub\.Repo>/g, "</GitHub>").replace(/<Column(\s[^>]*)?>/g, "<div$1>").replace(/<\/Column>/g, "</div>");
|
|
2620
|
+
result = normalizeMintlifyUpdateLabels(result).replace(/<FileTree(\s[^>]*)?>/g, "<Tree$1>").replace(/<\/FileTree>/g, "</Tree>").replace(/<GitHub\.Repo/g, "<GitHub").replace(/<\/GitHub\.Repo>/g, "</GitHub>").replace(/<Callout(\s[^<>]*)?>/g, (tag) => tag.replace(/(\s)type=(?:"[^"]*"|'[^']*'|\{[^{}]*\})/, '$1type="info"')).replace(/<Column(\s[^>]*)?>/g, "<div$1>").replace(/<\/Column>/g, "</div>");
|
|
2600
2621
|
result = pinStepsTitleSize(result);
|
|
2601
2622
|
}
|
|
2602
2623
|
if (runFern) {
|
|
@@ -2615,6 +2636,16 @@ function normalizeMdx(body, platform, unwrapMdxCodeBlocks = true) {
|
|
|
2615
2636
|
}
|
|
2616
2637
|
return normalizeFlowParagraphContainers(normalized);
|
|
2617
2638
|
}
|
|
2639
|
+
function externalPageUrl(value) {
|
|
2640
|
+
const url = typeof value === "string" ? value.trim() : "";
|
|
2641
|
+
if (!/^https?:\/\/[^\s]+$/i.test(url)) return void 0;
|
|
2642
|
+
try {
|
|
2643
|
+
new URL(url);
|
|
2644
|
+
return url;
|
|
2645
|
+
} catch {
|
|
2646
|
+
return void 0;
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2618
2649
|
function parseMarkdownPage(input) {
|
|
2619
2650
|
const parsed = parseFrontmatter(input.raw);
|
|
2620
2651
|
const fallbackIdentity = {
|
|
@@ -2639,6 +2670,7 @@ function parseMarkdownPage(input) {
|
|
|
2639
2670
|
const badge = typeof parsed.data.tag === "string" && parsed.data.tag.trim() ? parsed.data.tag.trim() : typeof parsed.data.badge === "string" && parsed.data.badge.trim() ? parsed.data.badge.trim() : void 0;
|
|
2640
2671
|
const sourceMode = typeof parsed.data.mode === "string" ? parsed.data.mode : void 0;
|
|
2641
2672
|
const mode = sourceMode === "frame" ? "wide" : ["default", "wide", "custom", "center", "home"].includes(sourceMode ?? "") ? sourceMode : void 0;
|
|
2673
|
+
const externalUrl = input.platform === "mintlify" ? externalPageUrl(parsed.data.url) : void 0;
|
|
2642
2674
|
const description = typeof parsed.data.description === "string" && parsed.data.description.trim() ? parsed.data.description.trim() : typeof parsed.data.openapi === "string" && parsed.data.openapi.trim() ? "" : firstParagraph(body);
|
|
2643
2675
|
const page = {
|
|
2644
2676
|
id: identity.id,
|
|
@@ -2654,7 +2686,9 @@ function parseMarkdownPage(input) {
|
|
|
2654
2686
|
keywords,
|
|
2655
2687
|
mode,
|
|
2656
2688
|
hidden: parsed.data.hidden === true ? true : void 0,
|
|
2657
|
-
|
|
2689
|
+
// The path of a page that links elsewhere redirects, so it has no business in a sitemap.
|
|
2690
|
+
noindex: parsed.data.noindex === true || parsed.data.noindex === "true" || externalUrl ? true : void 0,
|
|
2691
|
+
...externalUrl ? { externalUrl } : {},
|
|
2658
2692
|
...Object.keys(meta).length > 0 ? { meta } : {},
|
|
2659
2693
|
openapi: typeof parsed.data.openapi === "string" ? parsed.data.openapi.trim() : void 0,
|
|
2660
2694
|
...apiFrontmatter(parsed.data, input.warn),
|
|
@@ -4391,12 +4425,17 @@ function addMintlifyHomepageRedirects(config, pages) {
|
|
|
4391
4425
|
const homepage = config.tabs.filter((tab) => !tab.hidden).map((tab) => firstPage([...tab.pages ?? [], ...tab.groups ?? []])).find(Boolean);
|
|
4392
4426
|
if (!homepage) return config;
|
|
4393
4427
|
const redirects = [...config.redirects ?? []];
|
|
4394
|
-
const
|
|
4428
|
+
const routeKey = (route) => (route.split(/[?#]/, 1)[0].replace(/\/$/, "") || "/").toLowerCase();
|
|
4429
|
+
const sources = new Set(redirects.map((redirect) => routeKey(redirect.source)));
|
|
4395
4430
|
const roots = ["", ...(config.i18n?.locales ?? []).filter((locale) => locale.code !== config.i18n?.defaultLocale).filter((locale) => homepage !== "introduction" || pages.some((page) => page.locale === locale.code && page.navigationId === homepage)).map((locale) => locale.code)];
|
|
4431
|
+
const homeLinksElsewhere = pages.some((page) => page.id === "introduction" && page.externalUrl);
|
|
4396
4432
|
for (const locale of roots) {
|
|
4433
|
+
if (!locale && homeLinksElsewhere) continue;
|
|
4397
4434
|
const source = locale ? `/${locale}` : "/";
|
|
4398
4435
|
if (sources.has(source.toLowerCase())) continue;
|
|
4399
|
-
|
|
4436
|
+
const destination = `${locale ? `/${locale}` : ""}/${homepage}`;
|
|
4437
|
+
if (redirects.some((redirect) => routeKey(redirect.source) === destination.toLowerCase() && routeKey(redirect.destination) === source.toLowerCase())) continue;
|
|
4438
|
+
redirects.push({ source, destination, permanent: true });
|
|
4400
4439
|
}
|
|
4401
4440
|
return { ...config, redirects };
|
|
4402
4441
|
}
|
|
@@ -4593,7 +4632,7 @@ function mergeApiGroups(existing, incoming) {
|
|
|
4593
4632
|
return merged.length > 0 ? merged : void 0;
|
|
4594
4633
|
}
|
|
4595
4634
|
var hasNavigationChildren = (node) => ["groups", "pages"].some((key) => Array.isArray(node[key]) && node[key].length > 0);
|
|
4596
|
-
function mintlifyNavigationApiReferences(config) {
|
|
4635
|
+
function mintlifyNavigationApiReferences(config, tabFor) {
|
|
4597
4636
|
const navigation = objectValue2(config.navigation) ?? config;
|
|
4598
4637
|
const references = [];
|
|
4599
4638
|
const defaultLanguage = pickDefaultLanguage(
|
|
@@ -4617,7 +4656,7 @@ function mintlifyNavigationApiReferences(config) {
|
|
|
4617
4656
|
references.push({
|
|
4618
4657
|
value,
|
|
4619
4658
|
kind,
|
|
4620
|
-
tabLabel,
|
|
4659
|
+
tabLabel: tabFor?.(node) ?? tabLabel,
|
|
4621
4660
|
...sibling,
|
|
4622
4661
|
...typeof directory2 === "string" && directory2.trim() ? { directory: directory2.trim() } : {},
|
|
4623
4662
|
...operations.length > 0 ? { operations } : {},
|
|
@@ -4972,6 +5011,21 @@ function convertNavigationValues(values, context) {
|
|
|
4972
5011
|
return page ? [page] : [];
|
|
4973
5012
|
});
|
|
4974
5013
|
}
|
|
5014
|
+
var API_TAB_CONTAINER = /* @__PURE__ */ Symbol("apiTabContainer");
|
|
5015
|
+
function takeApiTabSlots(tabs) {
|
|
5016
|
+
const slots = [];
|
|
5017
|
+
const real = [];
|
|
5018
|
+
tabs.forEach((tab, index) => {
|
|
5019
|
+
const container = tab[API_TAB_CONTAINER];
|
|
5020
|
+
if (!container) {
|
|
5021
|
+
real.push(tab);
|
|
5022
|
+
return;
|
|
5023
|
+
}
|
|
5024
|
+
const template = Object.fromEntries(Object.entries(tab).filter(([key]) => key !== "groups"));
|
|
5025
|
+
slots.push({ container, slot: { tab: template, preceding: tabs.slice(0, index).map((earlier) => earlier.tab).reverse() } });
|
|
5026
|
+
});
|
|
5027
|
+
return { tabs: real, slots };
|
|
5028
|
+
}
|
|
4975
5029
|
function convertContainerToTabs(containerValue, context, fallbackTab, trace, depth = 0) {
|
|
4976
5030
|
const rawContainer = objectValue2(containerValue);
|
|
4977
5031
|
if (!rawContainer) return [];
|
|
@@ -5048,6 +5102,17 @@ function convertContainerToTabs(containerValue, context, fallbackTab, trace, dep
|
|
|
5048
5102
|
...convertNavigationValues(values, context),
|
|
5049
5103
|
...Array.isArray(container.menu) ? convertMenuItems(container.menu, context) : []
|
|
5050
5104
|
];
|
|
5105
|
+
if (children.length === 0 && depth > 0 && context.operationGroups && !context.otherLanguage && !context.operations.gated && !context.operations.hidden && specSource(rawContainer.openapi) && operationGroups(rawContainer).length > 0) {
|
|
5106
|
+
const placeholder2 = {
|
|
5107
|
+
tab: fallbackTab,
|
|
5108
|
+
groups: [],
|
|
5109
|
+
...containerPresentation(container),
|
|
5110
|
+
...projectedHref(container.href) ? { href: projectedHref(container.href) } : {},
|
|
5111
|
+
...container.hidden === true ? { hidden: true } : {},
|
|
5112
|
+
[API_TAB_CONTAINER]: rawContainer
|
|
5113
|
+
};
|
|
5114
|
+
return [placeholder2];
|
|
5115
|
+
}
|
|
5051
5116
|
return children.length > 0 ? [{
|
|
5052
5117
|
tab: fallbackTab,
|
|
5053
5118
|
...hasRootNodes ? { pages: children } : { groups: children },
|
|
@@ -5228,6 +5293,8 @@ function projectedCompatibleConfig(config, warnings) {
|
|
|
5228
5293
|
return {
|
|
5229
5294
|
// Mintlify pages show a group eyebrow above the title and no breadcrumb trail.
|
|
5230
5295
|
breadcrumbs: false,
|
|
5296
|
+
// Mintlify typesets straight quotes in prose as curly ones.
|
|
5297
|
+
smartQuotes: true,
|
|
5231
5298
|
// `styling.eyebrows: "breadcrumbs"` shows the whole group path; "section" (the default) shows the nearest group.
|
|
5232
5299
|
...objectValue2(config.styling)?.eyebrows === "breadcrumbs" ? { eyebrow: "path" } : {},
|
|
5233
5300
|
...projectedTheme(config.theme) ? { theme: projectedTheme(config.theme) } : {},
|
|
@@ -5479,6 +5546,9 @@ function projectMintlifyNavigation(config, options = {}) {
|
|
|
5479
5546
|
}
|
|
5480
5547
|
}
|
|
5481
5548
|
}
|
|
5549
|
+
const taken = takeApiTabSlots(tabs);
|
|
5550
|
+
tabs = taken.tabs;
|
|
5551
|
+
const apiTabSlots = taken.slots;
|
|
5482
5552
|
if (tabs.length === 0) {
|
|
5483
5553
|
warnings.push({
|
|
5484
5554
|
code: "unsupported-config",
|
|
@@ -5524,6 +5594,7 @@ function projectMintlifyNavigation(config, options = {}) {
|
|
|
5524
5594
|
}) : [];
|
|
5525
5595
|
if (versions.length > 1) {
|
|
5526
5596
|
tabs = annotateVersions(tabs);
|
|
5597
|
+
for (const entry of apiTabSlots) [entry.slot.tab] = annotateVersions([entry.slot.tab]);
|
|
5527
5598
|
for (const [locale, items] of Object.entries(localizedNavigation)) localizedNavigation[locale] = annotateVersions(items);
|
|
5528
5599
|
}
|
|
5529
5600
|
const redirects = Array.isArray(config.redirects) ? config.redirects.flatMap((value) => {
|
|
@@ -5547,11 +5618,13 @@ function projectMintlifyNavigation(config, options = {}) {
|
|
|
5547
5618
|
}];
|
|
5548
5619
|
}) : [];
|
|
5549
5620
|
collectReferenceAccess(navigation, OPEN_NAVIGATION_ACCESS, options.pathPrefix, appearances);
|
|
5621
|
+
const keepsCollectionNamedGroup = [tabs, ...Object.values(localizedNavigation)].some((items) => items.some((item) => item.groups?.some((group) => group.group === (item.displayLabel ?? item.tab))));
|
|
5550
5622
|
return {
|
|
5551
5623
|
docsConfig: {
|
|
5552
5624
|
tabs,
|
|
5553
|
-
...projectionTrace.rootContainerKind === "dropdowns" || versions.length > 1 || shortcuts.length > 0 ? { navigation: {
|
|
5625
|
+
...projectionTrace.rootContainerKind === "dropdowns" || versions.length > 1 || shortcuts.length > 0 || keepsCollectionNamedGroup ? { navigation: {
|
|
5554
5626
|
...projectionTrace.rootContainerKind === "dropdowns" ? { display: "dropdown" } : {},
|
|
5627
|
+
...keepsCollectionNamedGroup ? { groupHeadings: "all" } : {},
|
|
5555
5628
|
...versions.length > 1 ? { versions } : {},
|
|
5556
5629
|
...shortcuts.length > 0 ? { shortcuts } : {}
|
|
5557
5630
|
} } : {},
|
|
@@ -5563,6 +5636,7 @@ function projectMintlifyNavigation(config, options = {}) {
|
|
|
5563
5636
|
pageReferences: references,
|
|
5564
5637
|
referenceAccess: appearances,
|
|
5565
5638
|
gatedSourceRefs,
|
|
5639
|
+
apiTabSlots,
|
|
5566
5640
|
warnings
|
|
5567
5641
|
};
|
|
5568
5642
|
}
|
|
@@ -9074,6 +9148,9 @@ function destinationRoute(destination) {
|
|
|
9074
9148
|
function pageRoutes(pages) {
|
|
9075
9149
|
return pages.flatMap((page) => [`/${page.id}`, `/${page.id.replace(/\/index$/, "")}`]);
|
|
9076
9150
|
}
|
|
9151
|
+
function pageEntryRoutes(page) {
|
|
9152
|
+
return [.../* @__PURE__ */ new Set([...pageRoutes([page]), ...page.id === "introduction" ? ["/"] : []])];
|
|
9153
|
+
}
|
|
9077
9154
|
function servedRoutes(pages) {
|
|
9078
9155
|
return new Set(pageRoutes(pages).map((route) => route.toLowerCase()));
|
|
9079
9156
|
}
|
|
@@ -9138,11 +9215,13 @@ function dropConflictingRedirects(config, pages, warnings) {
|
|
|
9138
9215
|
const loopingByCase = [];
|
|
9139
9216
|
const folded = redirectChains();
|
|
9140
9217
|
const asWritten = redirectChains();
|
|
9218
|
+
const rootRedirected = config.redirects.some((redirect) => literalRoute(redirect.source) === "/");
|
|
9141
9219
|
const redirects = config.redirects.filter((redirect) => {
|
|
9142
9220
|
const source = literalRoute(redirect.source);
|
|
9143
9221
|
if (!source) return true;
|
|
9144
9222
|
const writtenSource = exactRoute(redirect.source);
|
|
9145
|
-
|
|
9223
|
+
const retiresRootAlias = source === "/introduction" && !rootRedirected && destinationRoute(redirect.destination) === "/";
|
|
9224
|
+
if (served.has(source) && !retiresRootAlias) {
|
|
9146
9225
|
const hides = servedAsWritten.has(writtenSource) ? hidden : hiddenByCase;
|
|
9147
9226
|
hides.push(redirect.source);
|
|
9148
9227
|
return false;
|
|
@@ -12337,12 +12416,19 @@ function mintlifyTopLevelApiReferences(config) {
|
|
|
12337
12416
|
function specFileCandidates(files) {
|
|
12338
12417
|
return files.filter((file) => /\.(?:json|ya?ml)$/i.test(file.relativePath)).map((file) => ({ sourcePath: file.relativePath, filename: specRefBaseName(file.relativePath) }));
|
|
12339
12418
|
}
|
|
12340
|
-
function resolveMintlifyApiSpecs(mintlifyConfig, files, warnings, remoteSpecs, nameSpec, pages = []) {
|
|
12419
|
+
function resolveMintlifyApiSpecs(mintlifyConfig, files, warnings, remoteSpecs, nameSpec, pages = [], apiTabSlots = []) {
|
|
12341
12420
|
if (!mintlifyConfig) return [];
|
|
12421
|
+
const slotByContainer = new Map(apiTabSlots.map(({ container, slot }) => [container, slot]));
|
|
12422
|
+
const slotByLabel = new Map(apiTabSlots.map(({ slot }) => [slot.tab.tab, slot]));
|
|
12342
12423
|
const references = [
|
|
12343
12424
|
...mintlifyTopLevelApiReferences(mintlifyConfig),
|
|
12344
|
-
...mintlifyNavigationApiReferences(mintlifyConfig)
|
|
12425
|
+
...mintlifyNavigationApiReferences(mintlifyConfig, (container) => slotByContainer.get(container)?.tab.tab)
|
|
12345
12426
|
];
|
|
12427
|
+
const endpointPagesOf = (reference) => {
|
|
12428
|
+
const directory2 = reference.groups ? endpointDirectory(reference.directory) : void 0;
|
|
12429
|
+
const slot = reference.tabLabel ? slotByLabel.get(reference.tabLabel) : void 0;
|
|
12430
|
+
return directory2 === void 0 ? void 0 : { directory: directory2, ...slot ? { slot } : {} };
|
|
12431
|
+
};
|
|
12346
12432
|
const known = new Set(references.map((reference) => canonicalSpecRef(reference.value)));
|
|
12347
12433
|
const specFiles = specFileCandidates(files);
|
|
12348
12434
|
const namedFiles = /* @__PURE__ */ new Map();
|
|
@@ -12383,6 +12469,14 @@ function resolveMintlifyApiSpecs(mintlifyConfig, files, warnings, remoteSpecs, n
|
|
|
12383
12469
|
if (reference.groups) {
|
|
12384
12470
|
const merged = mergeApiGroups(shared.target.groups, reference.groups);
|
|
12385
12471
|
if (merged) shared.target.groups = merged;
|
|
12472
|
+
const own2 = endpointPagesOf(reference);
|
|
12473
|
+
if (shared.directory === void 0) {
|
|
12474
|
+
shared.directory = own2?.directory ?? null;
|
|
12475
|
+
if (own2) shared.target.endpointPages = own2;
|
|
12476
|
+
} else if (shared.directory !== (own2?.directory ?? null)) {
|
|
12477
|
+
shared.directory = null;
|
|
12478
|
+
delete shared.target.endpointPages;
|
|
12479
|
+
}
|
|
12386
12480
|
} else if (listsNothing(reference)) {
|
|
12387
12481
|
shared.unlisted = true;
|
|
12388
12482
|
delete shared.target.groups;
|
|
@@ -12401,11 +12495,12 @@ function resolveMintlifyApiSpecs(mintlifyConfig, files, warnings, remoteSpecs, n
|
|
|
12401
12495
|
continue;
|
|
12402
12496
|
}
|
|
12403
12497
|
if (/^https:\/\//i.test(reference.value)) {
|
|
12404
|
-
const
|
|
12498
|
+
const pagesTarget = endpointPagesOf(reference);
|
|
12499
|
+
const remote = { url: reference.value, ...reference.tabLabel ? { tabLabel: reference.tabLabel } : {}, ...reference.parentTab ? { parentTab: reference.parentTab } : {}, ...reference.icon ? { icon: reference.icon } : {}, ...reference.hidden ? { hidden: true } : {}, ...groups ? { groups } : {}, ...groups && pagesTarget ? { endpointPages: pagesTarget } : {} };
|
|
12405
12500
|
mountDirectory(remote, reference);
|
|
12406
12501
|
remoteSpecs.push(remote);
|
|
12407
12502
|
remoteByKey.set(dedupeKey, remote);
|
|
12408
|
-
groupTargets.set(dedupeKey, { target: remote, unlisted: listsNothing(reference), withheld: reference.operationsWithheld === true });
|
|
12503
|
+
groupTargets.set(dedupeKey, { target: remote, unlisted: listsNothing(reference), withheld: reference.operationsWithheld === true, ...groups ? { directory: pagesTarget?.directory ?? null } : {} });
|
|
12409
12504
|
warnings.push({
|
|
12410
12505
|
code: "unsupported-config",
|
|
12411
12506
|
message: `The remote OpenAPI spec "${reference.value}"${tabSuffix} requires a network download before this import is complete.`,
|
|
@@ -12426,12 +12521,12 @@ function resolveMintlifyApiSpecs(mintlifyConfig, files, warnings, remoteSpecs, n
|
|
|
12426
12521
|
});
|
|
12427
12522
|
continue;
|
|
12428
12523
|
}
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12524
|
+
const directoryWarning = reference.directory ? {
|
|
12525
|
+
code: "unsupported-config",
|
|
12526
|
+
message: `The OpenAPI spec "${reference.value}"${tabSuffix} was limited to pages under "${reference.directory}" in the source, but Thally's API reference always covers a whole tab, so it was migrated as the tab's full API reference. Links in page bodies and Mintlify endpoint URLs under "${reference.directory}/<tag>/<operation>" are redirected to the matching endpoints where one exists (a separate warning counts any endpoint redirects that were skipped); check any other links to "${reference.directory}/..." manually.`
|
|
12527
|
+
} : void 0;
|
|
12528
|
+
const deferWarning = Boolean(groups && endpointPagesOf(reference));
|
|
12529
|
+
if (directoryWarning && !deferWarning) warnings.push(directoryWarning);
|
|
12435
12530
|
const content = readSpecFile(match.absolutePath, match.relativePath, warnings);
|
|
12436
12531
|
if (!content) continue;
|
|
12437
12532
|
const spec = {
|
|
@@ -12444,10 +12539,11 @@ function resolveMintlifyApiSpecs(mintlifyConfig, files, warnings, remoteSpecs, n
|
|
|
12444
12539
|
...reference.pageOnly ? { pageOnly: true } : {},
|
|
12445
12540
|
sourcePath: match.relativePath,
|
|
12446
12541
|
directory: reference.directory,
|
|
12447
|
-
...groups ? { groups } : {}
|
|
12542
|
+
...groups ? { groups } : {},
|
|
12543
|
+
...deferWarning ? { endpointPages: endpointPagesOf(reference), directoryWarning } : {}
|
|
12448
12544
|
};
|
|
12449
12545
|
specs.push(spec);
|
|
12450
|
-
groupTargets.set(dedupeKey, { target: spec, unlisted: listsNothing(reference), withheld: reference.operationsWithheld === true });
|
|
12546
|
+
groupTargets.set(dedupeKey, { target: spec, unlisted: listsNothing(reference), withheld: reference.operationsWithheld === true, ...groups ? { directory: endpointPagesOf(reference)?.directory ?? null } : {} });
|
|
12451
12547
|
}
|
|
12452
12548
|
for (const { target: target2, unlisted, withheld } of groupTargets.values()) {
|
|
12453
12549
|
if (withheld && !unlisted && !target2.groups) target2.navigation = false;
|
|
@@ -12503,20 +12599,52 @@ function apiTabSpecIds(tabs) {
|
|
|
12503
12599
|
}
|
|
12504
12600
|
var flagged = (value) => value === true || value === "true";
|
|
12505
12601
|
var isWithheld = (node) => flagged(node["x-hidden"]) || flagged(node["x-excluded"]);
|
|
12602
|
+
var isRecord2 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
12603
|
+
function resolveLocalSpecRef(document, ref) {
|
|
12604
|
+
if (ref !== "#" && !ref.startsWith("#/")) return void 0;
|
|
12605
|
+
let node = document;
|
|
12606
|
+
for (const segment of ref.slice(2).split("/").filter(Boolean)) {
|
|
12607
|
+
if (!isRecord2(node) && !Array.isArray(node)) return void 0;
|
|
12608
|
+
let decoded = segment;
|
|
12609
|
+
try {
|
|
12610
|
+
decoded = decodeURIComponent(segment);
|
|
12611
|
+
} catch {
|
|
12612
|
+
}
|
|
12613
|
+
node = node[decoded.replace(/~1/g, "/").replace(/~0/g, "~")];
|
|
12614
|
+
}
|
|
12615
|
+
return node;
|
|
12616
|
+
}
|
|
12617
|
+
function viewSpecPathItem(document, entry) {
|
|
12618
|
+
const chain = [entry];
|
|
12619
|
+
let current = entry;
|
|
12620
|
+
while (typeof current.$ref === "string") {
|
|
12621
|
+
const target2 = resolveLocalSpecRef(document, current.$ref);
|
|
12622
|
+
if (!isRecord2(target2) || chain.includes(target2)) break;
|
|
12623
|
+
chain.push(target2);
|
|
12624
|
+
current = target2;
|
|
12625
|
+
}
|
|
12626
|
+
const item = Object.assign({}, ...[...chain].reverse());
|
|
12627
|
+
delete item.$ref;
|
|
12628
|
+
return { item, withheld: chain.some(isWithheld) };
|
|
12629
|
+
}
|
|
12506
12630
|
function parseOpenApiOperationsForLinking(content) {
|
|
12507
|
-
|
|
12631
|
+
const document = readSpecDocument(content);
|
|
12632
|
+
return visibleOperations(document, isRecord2(document) ? document.paths : void 0);
|
|
12633
|
+
}
|
|
12634
|
+
function readSpecDocument(content) {
|
|
12508
12635
|
try {
|
|
12509
|
-
|
|
12636
|
+
return parseSpecDocument(content.toString("utf8")).document;
|
|
12510
12637
|
} catch {
|
|
12511
|
-
return
|
|
12638
|
+
return void 0;
|
|
12512
12639
|
}
|
|
12513
|
-
|
|
12514
|
-
|
|
12640
|
+
}
|
|
12641
|
+
function visibleOperations(document, entries) {
|
|
12642
|
+
if (!isRecord2(entries)) return [];
|
|
12515
12643
|
const operations = [];
|
|
12516
|
-
for (const [path, pathItem] of Object.entries(
|
|
12517
|
-
if (!pathItem
|
|
12518
|
-
const item = pathItem;
|
|
12519
|
-
if (
|
|
12644
|
+
for (const [path, pathItem] of Object.entries(entries)) {
|
|
12645
|
+
if (!isRecord2(pathItem)) continue;
|
|
12646
|
+
const { item, withheld } = viewSpecPathItem(document, pathItem);
|
|
12647
|
+
if (withheld) continue;
|
|
12520
12648
|
for (const method of OPENAPI_HTTP_METHODS) {
|
|
12521
12649
|
const operation = item[method];
|
|
12522
12650
|
if (!operation || typeof operation !== "object") continue;
|
|
@@ -12528,7 +12656,8 @@ function parseOpenApiOperationsForLinking(content) {
|
|
|
12528
12656
|
path,
|
|
12529
12657
|
tag: tags[0],
|
|
12530
12658
|
summary: typeof op.summary === "string" ? op.summary : void 0,
|
|
12531
|
-
operationId: typeof op.operationId === "string" ? op.operationId : void 0
|
|
12659
|
+
operationId: typeof op.operationId === "string" ? op.operationId : void 0,
|
|
12660
|
+
description: typeof op.description === "string" ? op.description : void 0
|
|
12532
12661
|
});
|
|
12533
12662
|
}
|
|
12534
12663
|
}
|
|
@@ -12549,13 +12678,26 @@ function servedOperations(source, parsed) {
|
|
|
12549
12678
|
});
|
|
12550
12679
|
}
|
|
12551
12680
|
var mountPrefix = (directory2) => directory2.replace(/^\/+|\/+$/g, "").toLowerCase();
|
|
12681
|
+
function mintlifyEndpointUrl(directory2, operation) {
|
|
12682
|
+
const tag = mintlifyUrlSlug(operation.tag ?? "default");
|
|
12683
|
+
const leaf = mintlifyUrlSlug(operation.summary?.trim() || operation.operationId?.trim() || `${operation.method} ${operation.path}`);
|
|
12684
|
+
return {
|
|
12685
|
+
tag,
|
|
12686
|
+
leaf,
|
|
12687
|
+
url: `${directory2}/${tag}/${leaf}`.replace(/^\/+|\/+$/g, ""),
|
|
12688
|
+
title: operation.summary?.trim() || operation.operationId?.trim() || `${operation.method.toUpperCase()} ${operation.path}`
|
|
12689
|
+
};
|
|
12690
|
+
}
|
|
12552
12691
|
function apiOperationLinkMap(sources, docsConfig, otherMounts = []) {
|
|
12553
12692
|
const map = /* @__PURE__ */ new Map();
|
|
12554
12693
|
const prefixLandings = /* @__PURE__ */ new Map();
|
|
12555
12694
|
const mintlifyPages = /* @__PURE__ */ new Map();
|
|
12556
12695
|
const duplicatePages = [];
|
|
12557
12696
|
const parsedByFile = /* @__PURE__ */ new Map();
|
|
12558
|
-
const bound =
|
|
12697
|
+
const bound = [
|
|
12698
|
+
...apiTabSpecIds(docsConfig.tabs).flatMap(({ tab, specId }) => sources.filter((entry) => !entry.endpointPages && tab.api?.source === specAssetPath(entry.filename) && (!entry.tab || entry.tab === tab.tab)).map((source) => ({ source, specId }))),
|
|
12699
|
+
...sources.filter((entry) => entry.endpointPages).map((source) => ({ source }))
|
|
12700
|
+
];
|
|
12559
12701
|
const mounts = new Set([...bound.map(({ source }) => source.prefix ? mountPrefix(source.prefix) : ""), ...otherMounts.map(mountPrefix)].filter(Boolean));
|
|
12560
12702
|
const underDeeperMount = (route, own2) => {
|
|
12561
12703
|
const lower = route.toLowerCase();
|
|
@@ -12565,9 +12707,12 @@ function apiOperationLinkMap(sources, docsConfig, otherMounts = []) {
|
|
|
12565
12707
|
if (!source.prefix) return;
|
|
12566
12708
|
const base = source.prefix.replace(/^\/+|\/+$/g, "");
|
|
12567
12709
|
const prefix = mountPrefix(source.prefix);
|
|
12568
|
-
if (prefix) prefixLandings.set(prefix, specId === "default" ? "/api" : `/api/${specId}`);
|
|
12710
|
+
if (prefix && specId !== void 0) prefixLandings.set(prefix, specId === "default" ? "/api" : `/api/${specId}`);
|
|
12569
12711
|
for (const operation of servedOperations(source, parsedByFile)) {
|
|
12570
|
-
const
|
|
12712
|
+
const endpoint = mintlifyEndpointUrl(base, operation);
|
|
12713
|
+
if (specId === void 0 && (!endpoint.tag || !endpoint.leaf)) continue;
|
|
12714
|
+
const thallyHref = specId === void 0 ? `/${endpoint.url}` : `/api/${specId}/${thallyOperationSlugSegments(operation.path, operation.method).join("/")}`;
|
|
12715
|
+
if (specId === void 0 && prefix && !prefixLandings.has(prefix)) prefixLandings.set(prefix, thallyHref);
|
|
12571
12716
|
const leafCandidates = /* @__PURE__ */ new Set();
|
|
12572
12717
|
if (operation.operationId) {
|
|
12573
12718
|
const parts = operation.operationId.split(/[_.]/).filter(Boolean);
|
|
@@ -12580,17 +12725,17 @@ function apiOperationLinkMap(sources, docsConfig, otherMounts = []) {
|
|
|
12580
12725
|
if (operation.operationId) leafCandidates.add(mintlifyOperationSlugSegment(operation.operationId));
|
|
12581
12726
|
leafCandidates.add(mintlifyOperationSlugSegment(`${operation.method} ${operation.path}`));
|
|
12582
12727
|
const tagSegment = mintlifyOperationSlugSegment(operation.tag ?? "default");
|
|
12583
|
-
const mintlifyTag
|
|
12584
|
-
const mintlifyLeaf = mintlifyUrlSlug(operation.summary?.trim() || operation.operationId?.trim() || `${operation.method} ${operation.path}`);
|
|
12585
|
-
const canonical2 = `${base}/${mintlifyTag}/${mintlifyLeaf}`.replace(/^\/+|\/+$/g, "");
|
|
12728
|
+
const { tag: mintlifyTag, leaf: mintlifyLeaf, url: canonical2 } = endpoint;
|
|
12586
12729
|
if (mintlifyTag && mintlifyLeaf && !underDeeperMount(canonical2, prefix)) {
|
|
12587
|
-
if (
|
|
12588
|
-
|
|
12730
|
+
if (specId !== void 0) {
|
|
12731
|
+
if (!mintlifyPages.has(canonical2)) mintlifyPages.set(canonical2, thallyHref);
|
|
12732
|
+
else if (mintlifyPages.get(canonical2) !== thallyHref && !duplicatePages.includes(canonical2)) duplicatePages.push(canonical2);
|
|
12733
|
+
}
|
|
12589
12734
|
if (!map.has(canonical2.toLowerCase())) map.set(canonical2.toLowerCase(), thallyHref);
|
|
12590
12735
|
}
|
|
12591
12736
|
const tagRoot = `${base}/${mintlifyTag}`.replace(/^\/+|\/+$/g, "");
|
|
12592
12737
|
if (mintlifyTag && !underDeeperMount(tagRoot, prefix)) {
|
|
12593
|
-
if (!mintlifyPages.has(tagRoot)) mintlifyPages.set(tagRoot, thallyHref);
|
|
12738
|
+
if (specId !== void 0 && !mintlifyPages.has(tagRoot)) mintlifyPages.set(tagRoot, thallyHref);
|
|
12594
12739
|
if (!map.has(tagRoot.toLowerCase())) map.set(tagRoot.toLowerCase(), thallyHref);
|
|
12595
12740
|
}
|
|
12596
12741
|
for (const leaf of leafCandidates) {
|
|
@@ -12631,6 +12776,150 @@ function linkApiMounts(sources, docsConfig, pages, warnings, reservedMounts = []
|
|
|
12631
12776
|
rewriteApiLinksInPages(pages, maps.operationLinks, maps.prefixLandings, warnings, { mounts: reservedMounts, redirects: docsConfig.redirects });
|
|
12632
12777
|
return mintlifyEndpointRedirects(maps, pages, docsConfig.redirects ?? [], warnings);
|
|
12633
12778
|
}
|
|
12779
|
+
var DEFAULT_ENDPOINT_DIRECTORY = "api-reference";
|
|
12780
|
+
function endpointDirectory(directory2) {
|
|
12781
|
+
const value = (directory2 ?? DEFAULT_ENDPOINT_DIRECTORY).replace(/^\/+|\/+$/g, "");
|
|
12782
|
+
const plain = (segment) => /^[\p{L}\p{N}_&-][\p{L}\p{N}_&.-]*$/u.test(segment) && Buffer.byteLength(`${segment}.mdx`) <= 255;
|
|
12783
|
+
return value && value.split("/").every(plain) ? value : void 0;
|
|
12784
|
+
}
|
|
12785
|
+
function createEndpointPageLedger(pages) {
|
|
12786
|
+
return { owners: new Map(pages.map((page) => [page.id.toLowerCase(), { id: page.id, operation: null }])), duplicates: [], unnamed: [] };
|
|
12787
|
+
}
|
|
12788
|
+
function reportEndpointPages(ledger, warnings) {
|
|
12789
|
+
const names = (urls) => `${urls.slice(0, 10).join(", ")}${urls.length > 10 ? ", ..." : ""}`;
|
|
12790
|
+
if (ledger.duplicates.length > 0) {
|
|
12791
|
+
warnings.push({
|
|
12792
|
+
code: "unsupported-config",
|
|
12793
|
+
message: `${ledger.duplicates.length} Mintlify endpoint URL${ledger.duplicates.length === 1 ? " is" : "s are"} shared by more than one operation (same tag and summary), so only the first operation has a page at each: ${names(ledger.duplicates.map((url) => `/${url}`))}.`
|
|
12794
|
+
});
|
|
12795
|
+
}
|
|
12796
|
+
if (ledger.unnamed.length > 0) {
|
|
12797
|
+
warnings.push({
|
|
12798
|
+
code: "unsupported-config",
|
|
12799
|
+
message: `${ledger.unnamed.length} listed operation${ledger.unnamed.length === 1 ? " has" : "s have"} no page because ${ledger.unnamed.length === 1 ? "its" : "their"} tag or title leaves no usable page name: ${names(ledger.unnamed)}.`
|
|
12800
|
+
});
|
|
12801
|
+
}
|
|
12802
|
+
}
|
|
12803
|
+
function endpointDescription(description, title) {
|
|
12804
|
+
const text3 = (description ?? "").split(/\r?\n\s*\r?\n/, 1)[0].replace(/<[^>]*>/g, " ").replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/[`*~]|__/g, "").replace(/^\s*#+\s*/, "").replace(/\s+/g, " ").trim();
|
|
12805
|
+
const sentence = /^(.+?[.!?])(?=\s|$)/.exec(text3)?.[1] ?? text3;
|
|
12806
|
+
const limited = sentence.length > 300 ? `${sentence.slice(0, 297).replace(/\s+\S*$/, "")}...` : sentence;
|
|
12807
|
+
return limited || title;
|
|
12808
|
+
}
|
|
12809
|
+
function insertEndpointTab(tabs, tab, preceding) {
|
|
12810
|
+
if (preceding.length === 0) {
|
|
12811
|
+
tabs.unshift(tab);
|
|
12812
|
+
return;
|
|
12813
|
+
}
|
|
12814
|
+
for (const label of preceding) {
|
|
12815
|
+
const index = tabs.findIndex((candidate) => candidate.tab === label);
|
|
12816
|
+
if (index !== -1) {
|
|
12817
|
+
tabs.splice(index + 1, 0, tab);
|
|
12818
|
+
return;
|
|
12819
|
+
}
|
|
12820
|
+
}
|
|
12821
|
+
tabs.push(tab);
|
|
12822
|
+
}
|
|
12823
|
+
function addEndpointPages(options) {
|
|
12824
|
+
const { tabs, pages, ledger, spec } = options;
|
|
12825
|
+
const operations = parseOpenApiOperationsForLinking(spec.content);
|
|
12826
|
+
if (operations.length === 0) return null;
|
|
12827
|
+
const existing = spec.tabLabel ? tabs.find((tab) => tab.tab === spec.tabLabel) : tabs.find((tab) => !tab.hidden && tab.tab.toLowerCase().includes("api"));
|
|
12828
|
+
if (existing?.api) return null;
|
|
12829
|
+
const byKey = new Map(operations.map((operation) => [`${operation.method} ${operation.path}`, operation]));
|
|
12830
|
+
const listed = [];
|
|
12831
|
+
const pageFor = (reference) => {
|
|
12832
|
+
const [method, ...path] = reference.trim().split(/\s+/);
|
|
12833
|
+
const operation = byKey.get(`${method.toLowerCase()} ${path.join(" ")}`);
|
|
12834
|
+
if (!operation) return void 0;
|
|
12835
|
+
const key = `${operation.method.toUpperCase()} ${operation.path}`;
|
|
12836
|
+
const endpoint = mintlifyEndpointUrl(spec.target.directory, operation);
|
|
12837
|
+
if (!endpoint.tag || !endpoint.leaf || Buffer.byteLength(`${endpoint.tag}.mdx`) > 255 || Buffer.byteLength(`${endpoint.leaf}.mdx`) > 255) {
|
|
12838
|
+
if (!ledger.unnamed.includes(key)) ledger.unnamed.push(key);
|
|
12839
|
+
return void 0;
|
|
12840
|
+
}
|
|
12841
|
+
const identity = `${spec.assetPath} ${key}`;
|
|
12842
|
+
const owner = ledger.owners.get(endpoint.url.toLowerCase());
|
|
12843
|
+
if (owner && owner.operation !== null && owner.operation !== identity) {
|
|
12844
|
+
if (!ledger.duplicates.includes(endpoint.url)) ledger.duplicates.push(endpoint.url);
|
|
12845
|
+
return void 0;
|
|
12846
|
+
}
|
|
12847
|
+
if (!owner) {
|
|
12848
|
+
pages.push({
|
|
12849
|
+
id: endpoint.url,
|
|
12850
|
+
navigationId: endpoint.url,
|
|
12851
|
+
title: endpoint.title,
|
|
12852
|
+
description: endpointDescription(operation.description, endpoint.title),
|
|
12853
|
+
// The summary belongs to metadata; keep full spec prose in the safe
|
|
12854
|
+
// operation Markdown renderer rather than copying it into executable MDX.
|
|
12855
|
+
descriptionPlacement: "operation",
|
|
12856
|
+
keywords: [],
|
|
12857
|
+
body: "",
|
|
12858
|
+
source: "docs.json",
|
|
12859
|
+
openapi: `${spec.assetPath} ${key}`
|
|
12860
|
+
});
|
|
12861
|
+
ledger.owners.set(endpoint.url.toLowerCase(), { id: endpoint.url, operation: identity });
|
|
12862
|
+
}
|
|
12863
|
+
listed.push(key);
|
|
12864
|
+
return owner?.id ?? endpoint.url;
|
|
12865
|
+
};
|
|
12866
|
+
const convert2 = (nodes) => nodes.flatMap((node) => {
|
|
12867
|
+
if (typeof node === "string") {
|
|
12868
|
+
const id = pageFor(node);
|
|
12869
|
+
return id ? [id] : [];
|
|
12870
|
+
}
|
|
12871
|
+
const pagesOf = convert2(node.pages);
|
|
12872
|
+
return pagesOf.length > 0 ? [{ group: node.group, ...node.icon ? { icon: node.icon } : {}, pages: pagesOf }] : [];
|
|
12873
|
+
});
|
|
12874
|
+
const groups = convert2(spec.groups);
|
|
12875
|
+
if (groups.length === 0) return null;
|
|
12876
|
+
if (existing) {
|
|
12877
|
+
if (existing.groups || !existing.pages) existing.groups = [...existing.groups ?? [], ...groups];
|
|
12878
|
+
else existing.pages = [...existing.pages, ...groups];
|
|
12879
|
+
} else {
|
|
12880
|
+
const { slot } = spec.target;
|
|
12881
|
+
const tab = {
|
|
12882
|
+
...slot?.tab ?? { tab: spec.tabLabel ?? "API Reference", ...spec.icon ? { icon: spec.icon } : {}, ...spec.hidden ? { hidden: true } : {} },
|
|
12883
|
+
groups
|
|
12884
|
+
};
|
|
12885
|
+
if (slot) insertEndpointTab(tabs, tab, slot.preceding);
|
|
12886
|
+
else insertApiTab(tabs, tab, spec.parentTab);
|
|
12887
|
+
}
|
|
12888
|
+
if (!tabs.some((tab) => tab.api?.source === spec.assetPath)) {
|
|
12889
|
+
insertApiTab(tabs, { tab: `OpenAPI: ${spec.source}`, hidden: true, api: { source: spec.assetPath } });
|
|
12890
|
+
}
|
|
12891
|
+
return { operations: listed };
|
|
12892
|
+
}
|
|
12893
|
+
function specLookupOrder(tabs, versions = []) {
|
|
12894
|
+
const collected = (tab) => !tab.hidden || Boolean(tab.version && versions.some((version) => version.label === tab.version));
|
|
12895
|
+
const sources = [...tabs.filter(collected), ...tabs.filter((tab) => !collected(tab))].flatMap((tab) => tab.api ? [tab.api.source] : []);
|
|
12896
|
+
return [...new Set(sources)];
|
|
12897
|
+
}
|
|
12898
|
+
function publishedOperationKeys(content) {
|
|
12899
|
+
const document = readSpecDocument(content);
|
|
12900
|
+
const table = (field) => visibleOperations(document, isRecord2(document) ? document[field] : void 0);
|
|
12901
|
+
return /* @__PURE__ */ new Set([
|
|
12902
|
+
...table("paths").map((operation) => `${operation.method} ${operation.path}`),
|
|
12903
|
+
...table("webhooks").map((operation) => `webhook ${operation.path}`)
|
|
12904
|
+
]);
|
|
12905
|
+
}
|
|
12906
|
+
function qualifyDisplacedBareRefs(options) {
|
|
12907
|
+
const { pages, before, after, content, qualifier } = options;
|
|
12908
|
+
if (before.join("\n") === after.join("\n")) return;
|
|
12909
|
+
const published = /* @__PURE__ */ new Map();
|
|
12910
|
+
const firstPublishing = (order, key) => order.find((source) => {
|
|
12911
|
+
if (!published.has(source)) published.set(source, publishedOperationKeys(content(source) ?? Buffer.alloc(0)));
|
|
12912
|
+
return published.get(source).has(key);
|
|
12913
|
+
});
|
|
12914
|
+
for (const page of pages) {
|
|
12915
|
+
const ref = page.openapi ? splitOpenApiRef(page.openapi) : null;
|
|
12916
|
+
if (!ref || ref.specRef) continue;
|
|
12917
|
+
const [method, ...rest] = ref.operation.trim().split(/\s+/);
|
|
12918
|
+
const key = `${method.toLowerCase()} ${rest.join(" ")}`;
|
|
12919
|
+
const reached = firstPublishing(before, key);
|
|
12920
|
+
if (reached !== void 0 && reached !== firstPublishing(after, key)) page.openapi = withSpecRef(ref, qualifier(reached));
|
|
12921
|
+
}
|
|
12922
|
+
}
|
|
12634
12923
|
function rewriteApiLinksInPages(pages, operationLinks, prefixLandings, warnings, answered = {}) {
|
|
12635
12924
|
if (operationLinks.size === 0 && prefixLandings.size === 0) return;
|
|
12636
12925
|
const unmatched = /* @__PURE__ */ new Set();
|
|
@@ -13878,6 +14167,7 @@ function migrateRepository(options) {
|
|
|
13878
14167
|
const referenceOrder = /* @__PURE__ */ new Map();
|
|
13879
14168
|
let docusaurusSidebars = null;
|
|
13880
14169
|
let mintlifyConfig = null;
|
|
14170
|
+
let mintlifyApiTabSlots = [];
|
|
13881
14171
|
const mintlifyNavigationAccess = /* @__PURE__ */ new Map();
|
|
13882
14172
|
let fernRawConfig = null;
|
|
13883
14173
|
let fernBasePath = "";
|
|
@@ -13922,6 +14212,7 @@ function migrateRepository(options) {
|
|
|
13922
14212
|
}
|
|
13923
14213
|
});
|
|
13924
14214
|
docsConfig = projected.docsConfig;
|
|
14215
|
+
mintlifyApiTabSlots = projected.apiTabSlots;
|
|
13925
14216
|
warnings.push(...projected.warnings);
|
|
13926
14217
|
for (const repo of projected.gatedSourceRefs) gatedSourceRepos.add(repo.toLowerCase());
|
|
13927
14218
|
for (const appearance of projected.referenceAccess) {
|
|
@@ -15029,7 +15320,8 @@ ${warnings.map((warning) => `- ${warning.message}`).join("\n")}`);
|
|
|
15029
15320
|
warnings.push({ code: "gated-page", message: sharedSpecMessage(path, excluded), source: path });
|
|
15030
15321
|
};
|
|
15031
15322
|
const nameSpec = createSpecAssetNamer();
|
|
15032
|
-
const
|
|
15323
|
+
const generatedEndpointPages = /* @__PURE__ */ new Set();
|
|
15324
|
+
const allSpecs = resolveMintlifyApiSpecs(mintlifyConfig, files, warnings, remoteApiSpecs, nameSpec, pages.filter((page) => !restrictedPages.has(page)), mintlifyApiTabSlots);
|
|
15033
15325
|
const navigation = navigationSpecContext(mintlifyConfig, (path) => resolvePageIdentity(path)?.id ?? null);
|
|
15034
15326
|
const defaultSources = /* @__PURE__ */ new Set([
|
|
15035
15327
|
...allSpecs.filter((spec) => !spec.pageOnly && spec.tabLabel === void 0).map((spec) => spec.sourcePath),
|
|
@@ -15072,12 +15364,61 @@ ${warnings.map((warning) => `- ${warning.message}`).join("\n")}`);
|
|
|
15072
15364
|
spec.pageReferenced = namedByPages.has(spec);
|
|
15073
15365
|
spec.generatedNavigation = Boolean(spec.directory) && !publishedSpecRefs.some((ref) => specRefMatches(ref, spec.sourcePath, true));
|
|
15074
15366
|
}
|
|
15075
|
-
|
|
15367
|
+
const listingSpecs = resolvedSpecs.filter((spec) => spec.groups && spec.endpointPages);
|
|
15368
|
+
const unbound = docsConfig;
|
|
15369
|
+
docsConfig = injectOpenApiSpecs(docsConfig, resolvedSpecs.filter((spec) => !listingSpecs.includes(spec)), warnings);
|
|
15370
|
+
const ledger = createEndpointPageLedger(pages);
|
|
15371
|
+
const tabs = docsConfig.tabs.map((tab) => ({ ...tab }));
|
|
15372
|
+
const pagesBefore = pages.length;
|
|
15373
|
+
const endpointSpecs = /* @__PURE__ */ new Set();
|
|
15374
|
+
for (const spec of listingSpecs) {
|
|
15375
|
+
if (!spec.groups || !spec.endpointPages) continue;
|
|
15376
|
+
const added = addEndpointPages({
|
|
15377
|
+
tabs,
|
|
15378
|
+
pages,
|
|
15379
|
+
ledger,
|
|
15380
|
+
spec: {
|
|
15381
|
+
assetPath: specAssetPath(spec.filename),
|
|
15382
|
+
source: spec.sourcePath,
|
|
15383
|
+
content: spec.content,
|
|
15384
|
+
groups: spec.groups,
|
|
15385
|
+
target: spec.endpointPages,
|
|
15386
|
+
tabLabel: spec.tabLabel,
|
|
15387
|
+
parentTab: spec.parentTab,
|
|
15388
|
+
icon: spec.icon,
|
|
15389
|
+
hidden: spec.hidden
|
|
15390
|
+
}
|
|
15391
|
+
});
|
|
15392
|
+
if (!added) continue;
|
|
15393
|
+
spec.endpointOperations = added.operations;
|
|
15394
|
+
endpointSpecs.add(spec);
|
|
15395
|
+
}
|
|
15396
|
+
reportEndpointPages(ledger, warnings);
|
|
15397
|
+
for (const spec of resolvedSpecs) if (spec.directoryWarning && !endpointSpecs.has(spec)) warnings.push(spec.directoryWarning);
|
|
15398
|
+
for (const page of pages.slice(pagesBefore)) generatedEndpointPages.add(page);
|
|
15399
|
+
docsConfig = injectOpenApiSpecs({ ...docsConfig, tabs }, listingSpecs.filter((spec) => !endpointSpecs.has(spec)), warnings);
|
|
15400
|
+
if (remoteApiSpecs.length === 0 && endpointSpecs.size > 0) {
|
|
15401
|
+
const bySource = new Map(resolvedSpecs.map((spec) => [specAssetPath(spec.filename), spec]));
|
|
15402
|
+
qualifyDisplacedBareRefs({
|
|
15403
|
+
pages,
|
|
15404
|
+
before: specLookupOrder(injectOpenApiSpecs(unbound, resolvedSpecs).tabs, docsConfig.navigation?.versions),
|
|
15405
|
+
after: specLookupOrder(docsConfig.tabs, docsConfig.navigation?.versions),
|
|
15406
|
+
content: (source) => bySource.get(source)?.content,
|
|
15407
|
+
qualifier: (source) => bySource.get(source)?.sourcePath ?? source
|
|
15408
|
+
});
|
|
15409
|
+
}
|
|
15410
|
+
const mountOf = (spec) => endpointSpecs.has(spec) ? { prefix: spec.endpointPages?.directory, operations: spec.endpointOperations } : { prefix: spec.directory };
|
|
15076
15411
|
if (remoteApiSpecs.length > 0) {
|
|
15077
|
-
localApiMounts.push(...resolvedSpecs.flatMap((spec) =>
|
|
15412
|
+
localApiMounts.push(...resolvedSpecs.flatMap((spec) => {
|
|
15413
|
+
const { prefix, operations } = mountOf(spec);
|
|
15414
|
+
return prefix ? [{ filename: spec.filename, directory: prefix, ...spec.tabLabel ? { tab: spec.tabLabel } : {}, ...operations ? { endpointOperations: operations } : {} }] : [];
|
|
15415
|
+
}));
|
|
15078
15416
|
} else {
|
|
15079
15417
|
const endpointRedirects = linkApiMounts(
|
|
15080
|
-
resolvedSpecs.map((spec) =>
|
|
15418
|
+
resolvedSpecs.map((spec) => {
|
|
15419
|
+
const { prefix, operations } = mountOf(spec);
|
|
15420
|
+
return { filename: spec.filename, content: spec.content, prefix, ...operations ? { endpointPages: true, operations } : {}, ...spec.tabLabel ? { tab: spec.tabLabel } : {} };
|
|
15421
|
+
}),
|
|
15081
15422
|
docsConfig,
|
|
15082
15423
|
pages,
|
|
15083
15424
|
warnings
|
|
@@ -15134,7 +15475,7 @@ ${warnings.map((warning) => `- ${warning.message}`).join("\n")}`);
|
|
|
15134
15475
|
}
|
|
15135
15476
|
return sameName ? "the file could not be read as an OpenAPI document" : `no file exists at "${key}"`;
|
|
15136
15477
|
};
|
|
15137
|
-
rewriteMintlifyPageSpecRefs(pages, pageSpecs, new Set(remoteApiSpecs.map((spec) => spec.url)), warnings, explainMissingSpec);
|
|
15478
|
+
rewriteMintlifyPageSpecRefs(pages.filter((page) => !generatedEndpointPages.has(page)), pageSpecs, new Set(remoteApiSpecs.map((spec) => spec.url)), warnings, explainMissingSpec);
|
|
15138
15479
|
if (docsConfig.tabs.some((tab) => tab.api)) docsConfig = { ...docsConfig, api: { ...docsConfig.api, specLink: false } };
|
|
15139
15480
|
}
|
|
15140
15481
|
if (platform === "mintlify") {
|
|
@@ -15356,6 +15697,24 @@ ${body}`;
|
|
|
15356
15697
|
if (docsConfig.redirects) {
|
|
15357
15698
|
docsConfig = dropConflictingRedirects(dropUnroutableRedirects(docsConfig, warnings), [...pages, ...sourceRefPages], warnings);
|
|
15358
15699
|
}
|
|
15700
|
+
const redirectSources = new Map((docsConfig.redirects ?? []).map((redirect) => [(redirect.source.replace(/\/+$/, "") || "/").toLowerCase(), redirect.destination]));
|
|
15701
|
+
const linkRedirects = [];
|
|
15702
|
+
for (const page of [...pages, ...sourceRefPages]) {
|
|
15703
|
+
if (!page.externalUrl) continue;
|
|
15704
|
+
for (const source of pageEntryRoutes(page)) {
|
|
15705
|
+
const existing = redirectSources.get(source.toLowerCase());
|
|
15706
|
+
if (existing !== void 0) {
|
|
15707
|
+
warnings.push({
|
|
15708
|
+
code: "unsupported-config",
|
|
15709
|
+
message: `Page "${page.id}" links to ${stripControlCharacters(page.externalUrl)}, but "${source}" already redirects to ${stripControlCharacters(existing)}; that redirect was kept, so "${source}" does not open the link.`
|
|
15710
|
+
});
|
|
15711
|
+
continue;
|
|
15712
|
+
}
|
|
15713
|
+
redirectSources.set(source.toLowerCase(), page.externalUrl);
|
|
15714
|
+
linkRedirects.push({ source, destination: page.externalUrl, permanent: false });
|
|
15715
|
+
}
|
|
15716
|
+
}
|
|
15717
|
+
if (linkRedirects.length > 0) docsConfig = { ...docsConfig, redirects: [...docsConfig.redirects ?? [], ...linkRedirects] };
|
|
15359
15718
|
if (pages.length === 0) {
|
|
15360
15719
|
const reasons = warnings.map((warning) => warning.message);
|
|
15361
15720
|
throw new Error(reasons.length ? `No importable Markdown or MDX pages were found in the repository. Warnings encountered during migration:
|
|
@@ -15439,7 +15798,7 @@ ${reasons.map((reason) => `- ${reason}`).join("\n")}` : "No importable Markdown
|
|
|
15439
15798
|
});
|
|
15440
15799
|
}
|
|
15441
15800
|
if (!docsConfig.navigation?.display && docsConfig.tabs.filter((tab) => !tab.hidden).length > 6) {
|
|
15442
|
-
docsConfig = { ...docsConfig, navigation: { display: "dropdown" } };
|
|
15801
|
+
docsConfig = { ...docsConfig, navigation: { display: "dropdown", ...docsConfig.navigation?.groupHeadings ? { groupHeadings: docsConfig.navigation.groupHeadings } : {} } };
|
|
15443
15802
|
}
|
|
15444
15803
|
const themeColors = mintlifyConfig ? mintlifyThemeColors(mintlifyConfig.colors) : fernRawConfig ? fernThemeColors(fernRawConfig.colors) ?? (fernRawConfig["global-theme"] === "nvidia" ? { primary: "#76B900" } : void 0) : isTopLevelDocusaurus ? presentation?.colors ?? readDocusaurusThemeColor(docusaurusProjectRoot) : void 0;
|
|
15445
15804
|
const assetPaths = new Set(assets.map((asset) => asset.path));
|
|
@@ -15635,7 +15994,7 @@ function renderPage(bundle, page) {
|
|
|
15635
15994
|
page.icon ? `icon: ${yamlString(page.icon)}` : null,
|
|
15636
15995
|
page.iconType ? `iconType: ${yamlString(page.iconType)}` : null,
|
|
15637
15996
|
`description: ${yamlString(page.description)}`,
|
|
15638
|
-
page.descriptionPlacement === "body" ?
|
|
15997
|
+
page.descriptionPlacement === "body" || page.descriptionPlacement === "operation" ? `descriptionPlacement: ${page.descriptionPlacement}` : null,
|
|
15639
15998
|
page.badge ? `badge: ${yamlString(page.badge)}` : null,
|
|
15640
15999
|
page.keywords.length > 0 ? `keywords: [${page.keywords.map(yamlString).join(", ")}]` : null,
|
|
15641
16000
|
page.mode ? `mode: ${yamlString(page.mode)}` : null,
|
|
@@ -18164,6 +18523,12 @@ function slug(value) {
|
|
|
18164
18523
|
function operationTarget(specId, operation) {
|
|
18165
18524
|
return `/api/${specId}/${thallyOperationSlugSegments(operation.path, operation.method).join("/")}`;
|
|
18166
18525
|
}
|
|
18526
|
+
function bindApiTab(tabs, reference, api) {
|
|
18527
|
+
const tab = reference.tabLabel ? tabs.find((candidate) => candidate.tab === reference.tabLabel) : tabs.find((candidate) => candidate.tab.toLowerCase().includes("api"));
|
|
18528
|
+
if (tab) tab.api = api;
|
|
18529
|
+
else insertApiTab(tabs, { tab: reference.tabLabel ?? "API Reference", ...reference.icon ? { icon: reference.icon } : {}, ...reference.hidden ? { hidden: true } : {}, api }, reference.parentTab);
|
|
18530
|
+
return tab?.tab ?? reference.tabLabel ?? "API Reference";
|
|
18531
|
+
}
|
|
18167
18532
|
async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
18168
18533
|
if (!bundle.remoteApiSpecs?.length) return bundle;
|
|
18169
18534
|
const assets = [...bundle.assets];
|
|
@@ -18172,7 +18537,8 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
18172
18537
|
const warnings = [...bundle.warnings];
|
|
18173
18538
|
const pages = bundle.pages.map((page) => ({ ...page }));
|
|
18174
18539
|
const authoredLinks = /* @__PURE__ */ new Set();
|
|
18175
|
-
const
|
|
18540
|
+
const ledger = createEndpointPageLedger(pages);
|
|
18541
|
+
const pagesBefore = pages.length;
|
|
18176
18542
|
const endpointUrls = /* @__PURE__ */ new Map();
|
|
18177
18543
|
for (const page of bundle.pages) {
|
|
18178
18544
|
for (const match of page.body.matchAll(/\/[a-z0-9_/-]+/gi)) {
|
|
@@ -18183,6 +18549,10 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
18183
18549
|
}
|
|
18184
18550
|
}
|
|
18185
18551
|
const bound = [];
|
|
18552
|
+
const apiTabs = bundle.docsConfig.tabs.map((tab) => ({ ...tab }));
|
|
18553
|
+
for (const mount of bundle.localApiMounts ?? []) {
|
|
18554
|
+
if (mount.endpointOperations) bindApiTab(apiTabs, { tabLabel: mount.tab }, { source: `openapi/${mount.filename}` });
|
|
18555
|
+
}
|
|
18186
18556
|
for (const reference of bundle.remoteApiSpecs) {
|
|
18187
18557
|
for (let index = warnings.length - 1; index >= 0; index--) {
|
|
18188
18558
|
if (warnings[index].source === reference.url && warnings[index].message.includes("requires a network download")) warnings.splice(index, 1);
|
|
@@ -18202,11 +18572,29 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
18202
18572
|
const ref = page.openapi ? splitOpenApiRef(page.openapi) : null;
|
|
18203
18573
|
if (ref?.specRef === reference.url) page.openapi = withSpecRef(ref, `openapi/${filename}`);
|
|
18204
18574
|
}
|
|
18205
|
-
|
|
18575
|
+
bindApiTab(apiTabs, reference, { source: `openapi/${filename}` });
|
|
18576
|
+
const endpoint = reference.groups && reference.endpointPages ? addEndpointPages({
|
|
18577
|
+
tabs,
|
|
18578
|
+
pages,
|
|
18579
|
+
ledger,
|
|
18580
|
+
spec: {
|
|
18581
|
+
assetPath: `openapi/${filename}`,
|
|
18582
|
+
source: reference.url,
|
|
18583
|
+
content: body,
|
|
18584
|
+
groups: reference.groups,
|
|
18585
|
+
target: reference.endpointPages,
|
|
18586
|
+
tabLabel: reference.tabLabel,
|
|
18587
|
+
parentTab: reference.parentTab,
|
|
18588
|
+
icon: reference.icon,
|
|
18589
|
+
hidden: reference.hidden
|
|
18590
|
+
}
|
|
18591
|
+
}) : null;
|
|
18592
|
+
if (endpoint) {
|
|
18593
|
+
bound.push({ reference, filename, content: body, operations, tabName: reference.tabLabel ?? "API Reference", endpointOperations: endpoint.operations });
|
|
18594
|
+
continue;
|
|
18595
|
+
}
|
|
18206
18596
|
const api = { source: `openapi/${filename}`, ...reference.navigation === false ? { navigation: false } : {}, ...reference.groups ? { groups: reference.groups } : {} };
|
|
18207
|
-
|
|
18208
|
-
else insertApiTab(tabs, { tab: reference.tabLabel ?? "API Reference", ...reference.icon ? { icon: reference.icon } : {}, ...reference.hidden ? { hidden: true } : {}, api }, reference.parentTab);
|
|
18209
|
-
bound.push({ reference, filename, content: body, operations, tabName: tab?.tab ?? reference.tabLabel ?? "API Reference" });
|
|
18597
|
+
bound.push({ reference, filename, content: body, operations, tabName: bindApiTab(tabs, reference, api) });
|
|
18210
18598
|
} catch (error) {
|
|
18211
18599
|
warnings.push({
|
|
18212
18600
|
code: "fetch-failed",
|
|
@@ -18215,19 +18603,22 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
18215
18603
|
});
|
|
18216
18604
|
}
|
|
18217
18605
|
}
|
|
18606
|
+
const pageMounts = bound.flatMap(({ reference, endpointOperations }) => endpointOperations && reference.endpointPages ? [reference.endpointPages.directory] : []);
|
|
18218
18607
|
const directories = [
|
|
18219
18608
|
...(bundle.localApiMounts ?? []).map(({ directory: directory2 }) => directory2),
|
|
18220
|
-
...bundle.remoteApiSpecs.flatMap((reference) => (reference.directories ?? []).map(({ directory: directory2 }) => directory2))
|
|
18609
|
+
...bundle.remoteApiSpecs.flatMap((reference) => (reference.directories ?? []).map(({ directory: directory2 }) => directory2)),
|
|
18610
|
+
...pageMounts
|
|
18221
18611
|
];
|
|
18222
18612
|
const endpointRedirects = linkApiMounts(
|
|
18223
18613
|
[
|
|
18224
|
-
...(bundle.localApiMounts ?? []).map(({ filename, directory: directory2, tab }) => ({
|
|
18614
|
+
...(bundle.localApiMounts ?? []).map(({ filename, directory: directory2, tab, endpointOperations }) => ({
|
|
18225
18615
|
filename,
|
|
18226
18616
|
content: Buffer.from(assets.find((asset) => asset.path === `openapi/${filename}`)?.content ?? []),
|
|
18227
18617
|
prefix: directory2,
|
|
18618
|
+
...endpointOperations ? { endpointPages: true, operations: endpointOperations } : {},
|
|
18228
18619
|
...tab ? { tab } : {}
|
|
18229
18620
|
})),
|
|
18230
|
-
...bound.flatMap(({ reference, filename, content, tabName }) => (reference.directories ?? []).map(({ directory: directory2, operations: listed }) => ({ filename, content, prefix: directory2, tab: tabName, ...listed ? { operations: listed } : {} })))
|
|
18621
|
+
...bound.flatMap(({ reference, filename, content, tabName, endpointOperations }) => endpointOperations && reference.endpointPages ? [{ filename, content, prefix: reference.endpointPages.directory, tab: tabName, endpointPages: true, operations: endpointOperations }] : (reference.directories ?? []).map(({ directory: directory2, operations: listed }) => ({ filename, content, prefix: directory2, tab: tabName, ...listed ? { operations: listed } : {} })))
|
|
18231
18622
|
],
|
|
18232
18623
|
{ ...bundle.docsConfig, tabs, redirects },
|
|
18233
18624
|
pages,
|
|
@@ -18238,6 +18629,18 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
18238
18629
|
redirects.push(redirect);
|
|
18239
18630
|
endpointUrls.set(literalRoute(redirect.source) ?? redirect.source, redirect.destination);
|
|
18240
18631
|
}
|
|
18632
|
+
reportEndpointPages(ledger, warnings);
|
|
18633
|
+
qualifyDisplacedBareRefs({
|
|
18634
|
+
pages,
|
|
18635
|
+
before: specLookupOrder(apiTabs, bundle.docsConfig.navigation?.versions),
|
|
18636
|
+
after: specLookupOrder(tabs, bundle.docsConfig.navigation?.versions),
|
|
18637
|
+
content: (source) => {
|
|
18638
|
+
const asset = assets.find((entry) => entry.path === source);
|
|
18639
|
+
return asset ? Buffer.from(asset.content) : void 0;
|
|
18640
|
+
},
|
|
18641
|
+
qualifier: (source) => source
|
|
18642
|
+
});
|
|
18643
|
+
const served = servedRoutes(pages);
|
|
18241
18644
|
const existingSources = new Set(redirects.map((redirect) => literalRoute(redirect.source) ?? redirect.source.toLowerCase()));
|
|
18242
18645
|
const mounts = directories.map(mountPrefix).filter(Boolean);
|
|
18243
18646
|
const underMount = (source) => mounts.some((prefix) => source.toLowerCase() === `/${prefix}` || source.toLowerCase().startsWith(`/${prefix}/`));
|
|
@@ -18262,12 +18665,19 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
18262
18665
|
const endpoint = endpointUrls.get(literalRoute(redirect.destination) ?? "");
|
|
18263
18666
|
return endpoint ? { ...redirect, destination: endpoint } : redirect;
|
|
18264
18667
|
});
|
|
18668
|
+
const boundConfig = { ...bundle.docsConfig, tabs, ...direct.length > 0 ? { redirects: direct } : {} };
|
|
18669
|
+
const newPages = pages.slice(pagesBefore);
|
|
18670
|
+
const withDirectories = bundle.platform === "mintlify" && newPages.length > 0 ? addMintlifyDirectoryRedirects(boundConfig, newPages) : boundConfig;
|
|
18671
|
+
const linkRedirects = new Set(pages.flatMap((page) => page.externalUrl ? pageEntryRoutes(page).map((source) => `${source} ${page.externalUrl}`) : []));
|
|
18672
|
+
const isLinkRedirect = (redirect) => linkRedirects.has(`${redirect.source} ${redirect.destination}`);
|
|
18673
|
+
const links = (withDirectories.redirects ?? []).filter(isLinkRedirect);
|
|
18674
|
+
const unchecked = links.length > 0 ? { ...withDirectories, redirects: withDirectories.redirects.filter((redirect) => !isLinkRedirect(redirect)) } : withDirectories;
|
|
18675
|
+
const checked = dropConflictingRedirects(dropUnroutableRedirects(unchecked, warnings), pages, warnings);
|
|
18265
18676
|
return {
|
|
18266
18677
|
...bundle,
|
|
18267
18678
|
pages,
|
|
18268
18679
|
assets,
|
|
18269
|
-
|
|
18270
|
-
docsConfig: dropConflictingRedirects(dropUnroutableRedirects({ ...bundle.docsConfig, tabs, ...direct.length > 0 ? { redirects: direct } : {} }, warnings), pages, warnings),
|
|
18680
|
+
docsConfig: links.length > 0 ? { ...checked, redirects: [...checked.redirects ?? [], ...links] } : checked,
|
|
18271
18681
|
warnings
|
|
18272
18682
|
};
|
|
18273
18683
|
}
|