@thallylabs/migrate 0.2.42 → 0.2.43
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 +8 -0
- package/dist/index.d.ts +34 -1
- package/dist/index.js +549 -204
- package/dist/index.js.map +1 -1
- package/dist/url-migration.js +226 -41
- package/dist/url-migration.js.map +1 -1
- package/package.json +1 -1
package/dist/url-migration.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/url-run.ts
|
|
2
|
-
import { createHash as
|
|
2
|
+
import { createHash as createHash5 } from "crypto";
|
|
3
3
|
import { load as load7 } from "cheerio";
|
|
4
4
|
import { parse as parse2, postprocess, preprocess } from "micromark";
|
|
5
|
-
import
|
|
5
|
+
import remarkParse5 from "remark-parse";
|
|
6
6
|
import remarkMdx4 from "remark-mdx";
|
|
7
|
-
import { unified as
|
|
7
|
+
import { unified as unified5 } from "unified";
|
|
8
8
|
|
|
9
9
|
// src/navigation.ts
|
|
10
10
|
import { existsSync, lstatSync, readFileSync, realpathSync as realpathSync2 } from "fs";
|
|
@@ -497,15 +497,15 @@ function createMigrationAssetCache() {
|
|
|
497
497
|
load(url, acquire) {
|
|
498
498
|
const existing = get(url);
|
|
499
499
|
if (existing) return existing;
|
|
500
|
-
const
|
|
500
|
+
const request2 = Promise.resolve().then(acquire).then((asset) => {
|
|
501
501
|
pending.delete(url);
|
|
502
502
|
return remember(url, asset);
|
|
503
503
|
}, (error) => {
|
|
504
504
|
pending.delete(url);
|
|
505
505
|
throw error;
|
|
506
506
|
});
|
|
507
|
-
pending.set(url,
|
|
508
|
-
return
|
|
507
|
+
pending.set(url, request2);
|
|
508
|
+
return request2;
|
|
509
509
|
},
|
|
510
510
|
delete(url) {
|
|
511
511
|
settled.delete(url);
|
|
@@ -1884,16 +1884,27 @@ function projectMigrationMedia(html, base) {
|
|
|
1884
1884
|
}
|
|
1885
1885
|
|
|
1886
1886
|
// src/url-identity.ts
|
|
1887
|
-
import { createHash as
|
|
1887
|
+
import { createHash as createHash4 } from "crypto";
|
|
1888
1888
|
import { load as load6 } from "cheerio";
|
|
1889
1889
|
|
|
1890
1890
|
// src/url.ts
|
|
1891
1891
|
import { load as load5 } from "cheerio";
|
|
1892
1892
|
import remarkMdx3 from "remark-mdx";
|
|
1893
|
-
import
|
|
1893
|
+
import remarkParse4 from "remark-parse";
|
|
1894
1894
|
import TurndownService from "turndown";
|
|
1895
|
-
import { unified as
|
|
1896
|
-
import { parse as
|
|
1895
|
+
import { unified as unified4 } from "unified";
|
|
1896
|
+
import { parse as parseYaml3, stringify as stringifyYaml2 } from "yaml";
|
|
1897
|
+
|
|
1898
|
+
// src/url-openapi.ts
|
|
1899
|
+
import { createHash as createHash2 } from "crypto";
|
|
1900
|
+
|
|
1901
|
+
// src/remote-spec.ts
|
|
1902
|
+
import { lookup } from "dns/promises";
|
|
1903
|
+
import { request } from "https";
|
|
1904
|
+
import { isIP } from "net";
|
|
1905
|
+
|
|
1906
|
+
// src/spec-exclude.ts
|
|
1907
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
1897
1908
|
|
|
1898
1909
|
// src/analytics.ts
|
|
1899
1910
|
var HOSTNAME_LABEL = "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?";
|
|
@@ -1905,8 +1916,8 @@ import { compileSync } from "@mdx-js/mdx";
|
|
|
1905
1916
|
import { nameToEmoji } from "gemoji";
|
|
1906
1917
|
import remarkGfm2 from "remark-gfm";
|
|
1907
1918
|
import remarkMdx2 from "remark-mdx";
|
|
1908
|
-
import
|
|
1909
|
-
import { unified as
|
|
1919
|
+
import remarkParse3 from "remark-parse";
|
|
1920
|
+
import { unified as unified3 } from "unified";
|
|
1910
1921
|
|
|
1911
1922
|
// src/builtin-components.ts
|
|
1912
1923
|
var THALLY_BUILTIN_COMPONENTS = /* @__PURE__ */ new Set([
|
|
@@ -2343,13 +2354,13 @@ function unresolvedExpressionNames(expression, pageNames) {
|
|
|
2343
2354
|
}
|
|
2344
2355
|
|
|
2345
2356
|
// src/frontmatter.ts
|
|
2346
|
-
import { parse as
|
|
2357
|
+
import { parse as parseYaml2 } from "yaml";
|
|
2347
2358
|
function salvageFrontmatterLines(matter) {
|
|
2348
2359
|
const data = {};
|
|
2349
2360
|
for (const line of matter.split(/\r?\n/)) {
|
|
2350
2361
|
if (!/^[A-Za-z_][\w-]*:\s?/.test(line)) continue;
|
|
2351
2362
|
try {
|
|
2352
|
-
const parsedLine =
|
|
2363
|
+
const parsedLine = parseYaml2(line);
|
|
2353
2364
|
if (parsedLine && typeof parsedLine === "object" && !Array.isArray(parsedLine)) {
|
|
2354
2365
|
Object.assign(data, parsedLine);
|
|
2355
2366
|
}
|
|
@@ -2373,7 +2384,7 @@ function parseFrontmatter(raw) {
|
|
|
2373
2384
|
return { content, data: {} };
|
|
2374
2385
|
}
|
|
2375
2386
|
try {
|
|
2376
|
-
const parsed =
|
|
2387
|
+
const parsed = parseYaml2(matter);
|
|
2377
2388
|
return {
|
|
2378
2389
|
content,
|
|
2379
2390
|
data: parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {}
|
|
@@ -2387,13 +2398,103 @@ function parseFrontmatter(raw) {
|
|
|
2387
2398
|
}
|
|
2388
2399
|
}
|
|
2389
2400
|
|
|
2401
|
+
// src/fence-meta.ts
|
|
2402
|
+
import remarkParse2 from "remark-parse";
|
|
2403
|
+
import { unified as unified2 } from "unified";
|
|
2404
|
+
function delimitedEnd(meta, start) {
|
|
2405
|
+
const opening = meta[start];
|
|
2406
|
+
if (opening === '"' || opening === "'") {
|
|
2407
|
+
let close = start + 1;
|
|
2408
|
+
while (close < meta.length && meta[close] !== opening) close += meta[close] === "\\" && meta[close + 1] === opening ? 2 : 1;
|
|
2409
|
+
return close < meta.length ? close + 1 : close;
|
|
2410
|
+
}
|
|
2411
|
+
if (opening !== "{") return void 0;
|
|
2412
|
+
let depth = 0;
|
|
2413
|
+
let quote = "";
|
|
2414
|
+
for (let index = start; index < meta.length; index++) {
|
|
2415
|
+
const char = meta[index];
|
|
2416
|
+
if (quote) {
|
|
2417
|
+
if (char === quote) quote = "";
|
|
2418
|
+
} else if (char === '"' || char === "'") quote = char;
|
|
2419
|
+
else if (char === "{") depth++;
|
|
2420
|
+
else if (char === "}" && --depth === 0) return index + 1;
|
|
2421
|
+
}
|
|
2422
|
+
return meta.length;
|
|
2423
|
+
}
|
|
2424
|
+
function tokens(meta) {
|
|
2425
|
+
const result = [];
|
|
2426
|
+
let index = 0;
|
|
2427
|
+
while (index < meta.length) {
|
|
2428
|
+
if (/\s/.test(meta[index])) {
|
|
2429
|
+
index++;
|
|
2430
|
+
continue;
|
|
2431
|
+
}
|
|
2432
|
+
const start = index;
|
|
2433
|
+
const delimited = delimitedEnd(meta, index);
|
|
2434
|
+
if (delimited !== void 0) {
|
|
2435
|
+
result.push({ start, end: delimited, value: meta.slice(start, delimited), quoted: meta[start] !== "{", group: meta[start] === "{" });
|
|
2436
|
+
index = delimited;
|
|
2437
|
+
continue;
|
|
2438
|
+
}
|
|
2439
|
+
const key = /^([A-Za-z][\w-]*)=/.exec(meta.slice(index));
|
|
2440
|
+
if (key) {
|
|
2441
|
+
index += key[0].length;
|
|
2442
|
+
const groupEnd = delimitedEnd(meta, index);
|
|
2443
|
+
if (groupEnd !== void 0) index = groupEnd;
|
|
2444
|
+
else while (index < meta.length && !/\s/.test(meta[index])) index++;
|
|
2445
|
+
result.push({ start, end: index, key: key[1], value: meta.slice(start, index) });
|
|
2446
|
+
continue;
|
|
2447
|
+
}
|
|
2448
|
+
while (index < meta.length && !/\s/.test(meta[index])) {
|
|
2449
|
+
if (index > start && meta[index] === "{" && /^\{[\d,\s-]*\}/.test(meta.slice(index))) break;
|
|
2450
|
+
index++;
|
|
2451
|
+
}
|
|
2452
|
+
result.push({ start, end: index, value: meta.slice(start, index) });
|
|
2453
|
+
}
|
|
2454
|
+
return result;
|
|
2455
|
+
}
|
|
2456
|
+
function normalizeMintlifyCodeFences(body, warn) {
|
|
2457
|
+
const tree = unified2().use(remarkParse2).parse(body);
|
|
2458
|
+
const edits = [];
|
|
2459
|
+
const removed = /* @__PURE__ */ new Set();
|
|
2460
|
+
const unknown = /* @__PURE__ */ new Set();
|
|
2461
|
+
const supported = /* @__PURE__ */ new Set(["title", "filename", "framework", "tag", "icon", "highlight", "focus", "wrap", "lines", "expandable", "nocopy"]);
|
|
2462
|
+
function visit(node) {
|
|
2463
|
+
if (node.type === "code" && node.position?.start.offset !== void 0) {
|
|
2464
|
+
const start = node.position.start.offset;
|
|
2465
|
+
const lineEnd = body.indexOf("\n", start);
|
|
2466
|
+
const end = lineEnd < 0 ? body.length : lineEnd;
|
|
2467
|
+
const line = body.slice(start, end);
|
|
2468
|
+
const opening = /^([`~]{3,}[^\s]*)([ \t]+)(.*?)(\r?)$/.exec(line);
|
|
2469
|
+
if (opening) {
|
|
2470
|
+
const meta = opening[3];
|
|
2471
|
+
const kept = tokens(meta).filter((token) => {
|
|
2472
|
+
if (token.key === "theme" || !token.key && !token.quoted && !token.group && token.value === "twoslash") {
|
|
2473
|
+
removed.add(token.key ?? token.value);
|
|
2474
|
+
return false;
|
|
2475
|
+
}
|
|
2476
|
+
if (token.key && !supported.has(token.key)) unknown.add(token.key);
|
|
2477
|
+
return true;
|
|
2478
|
+
});
|
|
2479
|
+
const normalized = kept.map((token) => meta.slice(token.start, token.end)).join(" ");
|
|
2480
|
+
if (normalized !== meta && kept.length !== tokens(meta).length) edits.push({ start, end, value: `${opening[1]}${normalized ? ` ${normalized}` : ""}${opening[4]}` });
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
for (const child of node.children ?? []) visit(child);
|
|
2484
|
+
}
|
|
2485
|
+
visit(tree);
|
|
2486
|
+
if (removed.size) warn?.(`Removed unsupported Mintlify code-fence options: ${[...removed].join(", ")}. Code examples and supported display options were preserved.`);
|
|
2487
|
+
if (unknown.size) warn?.(`Unsupported Mintlify code-fence options are ignored: ${[...unknown].join(", ")}. Review these renderer-specific options.`);
|
|
2488
|
+
return edits.sort((a, b) => b.start - a.start).reduce((text2, edit) => text2.slice(0, edit.start) + edit.value + text2.slice(edit.end), body);
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2390
2491
|
// src/mdx.ts
|
|
2391
2492
|
function titleFromId(id) {
|
|
2392
2493
|
const value = id.split("/").at(-1) ?? id;
|
|
2393
2494
|
if (value === "introduction") return "Introduction";
|
|
2394
2495
|
return value.split(/[-_]/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
2395
2496
|
}
|
|
2396
|
-
var descriptionParser =
|
|
2497
|
+
var descriptionParser = unified3().use(remarkParse3).use(remarkGfm2).use(remarkMdx2);
|
|
2397
2498
|
function plainText(node) {
|
|
2398
2499
|
if (node.type === "text" || node.type === "inlineCode") return node.value ?? "";
|
|
2399
2500
|
if (node.type === "image") return node.alt ?? "";
|
|
@@ -3408,13 +3509,41 @@ function externalPageUrl(value) {
|
|
|
3408
3509
|
}
|
|
3409
3510
|
function parseMarkdownPage(input) {
|
|
3410
3511
|
const parsed = parseFrontmatter(input.raw);
|
|
3512
|
+
if (input.platform === "mintlify") {
|
|
3513
|
+
const supported = /* @__PURE__ */ new Set([
|
|
3514
|
+
"title",
|
|
3515
|
+
"description",
|
|
3516
|
+
"sidebarTitle",
|
|
3517
|
+
"navTitle",
|
|
3518
|
+
"icon",
|
|
3519
|
+
"iconType",
|
|
3520
|
+
"tag",
|
|
3521
|
+
"badge",
|
|
3522
|
+
"keywords",
|
|
3523
|
+
"mode",
|
|
3524
|
+
"hidden",
|
|
3525
|
+
"noindex",
|
|
3526
|
+
"url",
|
|
3527
|
+
"openapi",
|
|
3528
|
+
"api",
|
|
3529
|
+
"authMethod",
|
|
3530
|
+
"playground",
|
|
3531
|
+
// Access settings are enforced by the repository classifier, never lost here.
|
|
3532
|
+
"groups",
|
|
3533
|
+
"public",
|
|
3534
|
+
...PAGE_META_FIELDS.map(([field]) => field)
|
|
3535
|
+
]);
|
|
3536
|
+
const dropped = Object.keys(parsed.data).filter((key) => !supported.has(key));
|
|
3537
|
+
if (dropped.length) input.warn?.(`Unsupported Mintlify frontmatter fields were omitted: ${dropped.join(", ")}. Review their behavior before publishing.`);
|
|
3538
|
+
}
|
|
3411
3539
|
const fallbackIdentity = {
|
|
3412
3540
|
id: input.id,
|
|
3413
3541
|
navigationId: input.navigationId ?? input.id,
|
|
3414
3542
|
...input.locale ? { locale: input.locale } : {}
|
|
3415
3543
|
};
|
|
3416
3544
|
const identity = input.resolveIdentity?.(parsed.data, fallbackIdentity) ?? fallbackIdentity;
|
|
3417
|
-
const
|
|
3545
|
+
const normalized = normalizeMdx(parsed.content, input.platform);
|
|
3546
|
+
const body = removeUndefinedExpressions(injectReactHookImports(input.platform === "mintlify" ? normalizeMintlifyCodeFences(normalized, input.warn) : normalized), input.warn).trim();
|
|
3418
3547
|
const keywords = Array.isArray(parsed.data.keywords) ? parsed.data.keywords.filter((value) => typeof value === "string") : [];
|
|
3419
3548
|
const heading = leadingPageHeading(body);
|
|
3420
3549
|
const title = typeof parsed.data.title === "string" && parsed.data.title.trim() ? parsed.data.title.trim() : heading?.title ?? titleFromId(identity.navigationId);
|
|
@@ -3487,7 +3616,7 @@ function apiFrontmatter(data, warn) {
|
|
|
3487
3616
|
}
|
|
3488
3617
|
|
|
3489
3618
|
// src/url-static-content.ts
|
|
3490
|
-
import { createHash as
|
|
3619
|
+
import { createHash as createHash3 } from "crypto";
|
|
3491
3620
|
import { load as load4 } from "cheerio";
|
|
3492
3621
|
function projectMigrationSvg(html) {
|
|
3493
3622
|
const $ = load4(html, { xmlMode: true }, false);
|
|
@@ -3496,7 +3625,7 @@ function projectMigrationSvg(html) {
|
|
|
3496
3625
|
if (svg.attr("xmlns") === void 0) svg.attr("xmlns", "http://www.w3.org/2000/svg");
|
|
3497
3626
|
const content = Buffer.from($.xml(svg));
|
|
3498
3627
|
if (!isPassiveSvg(content)) return null;
|
|
3499
|
-
const sha256 =
|
|
3628
|
+
const sha256 = createHash3("sha256").update(content).digest("hex");
|
|
3500
3629
|
const labelled = (svg.attr("aria-labelledby") ?? "").split(/\s+/).filter(Boolean).map((id) => svg.find("[id]").filter((_index, node) => $(node).attr("id") === id).text().trim()).filter(Boolean);
|
|
3501
3630
|
const alternative = svg.attr("aria-label")?.trim() || labelled.join(" ") || svg.children("title").text().trim() || svg.children("desc").text().trim() || svg.find("text").text().trim();
|
|
3502
3631
|
return { asset: { path: `migration-assets/${sha256}.svg`, content }, alternative };
|
|
@@ -3609,6 +3738,32 @@ function projectCapturedTabs($, root) {
|
|
|
3609
3738
|
}
|
|
3610
3739
|
}
|
|
3611
3740
|
|
|
3741
|
+
// src/redirects.ts
|
|
3742
|
+
function trimTrailingSlashes(route) {
|
|
3743
|
+
let end = route.length;
|
|
3744
|
+
while (end > 0 && route[end - 1] === "/") end--;
|
|
3745
|
+
return route.slice(0, end);
|
|
3746
|
+
}
|
|
3747
|
+
function exactRoute(route) {
|
|
3748
|
+
return route.startsWith("/") && !/[?:*#()[\]{}]/.test(route) ? trimTrailingSlashes(route) || "/" : null;
|
|
3749
|
+
}
|
|
3750
|
+
function literalRoute(route) {
|
|
3751
|
+
return exactRoute(route)?.toLowerCase() ?? null;
|
|
3752
|
+
}
|
|
3753
|
+
function resolveDotSegments(route) {
|
|
3754
|
+
const segments = [];
|
|
3755
|
+
for (const segment of route.split("/").slice(1)) {
|
|
3756
|
+
const dots = segment.replace(/%2e/gi, ".");
|
|
3757
|
+
if (dots === "..") segments.pop();
|
|
3758
|
+
else if (dots !== ".") segments.push(segment);
|
|
3759
|
+
}
|
|
3760
|
+
return `/${segments.join("/")}`;
|
|
3761
|
+
}
|
|
3762
|
+
function destinationRoute(destination) {
|
|
3763
|
+
const route = destination.startsWith("//") ? null : exactRoute(destination.split(/[?#]/, 1)[0]);
|
|
3764
|
+
return route === null ? null : resolveDotSegments(route);
|
|
3765
|
+
}
|
|
3766
|
+
|
|
3612
3767
|
// src/url.ts
|
|
3613
3768
|
var MAX_LOCAL_RESPONSE_BYTES = 8e6;
|
|
3614
3769
|
var MAX_EMBEDDED_SCHEMA_BYTES = 2e6;
|
|
@@ -3688,8 +3843,8 @@ var MINTLIFY_ARTICLE_LABELS = [
|
|
|
3688
3843
|
{ baseUrl: "Select base URL", permalink: "Navigate to header" },
|
|
3689
3844
|
{ baseUrl: "\u9009\u62E9\u57FA\u7840URL", permalink: "\u5BFC\u822A\u5230\u6807\u9898" }
|
|
3690
3845
|
];
|
|
3691
|
-
var remoteMarkdownParser =
|
|
3692
|
-
var embeddedOpenApiParser =
|
|
3846
|
+
var remoteMarkdownParser = unified4().use(remarkParse4).use(remarkMdx3);
|
|
3847
|
+
var embeddedOpenApiParser = unified4().use(remarkParse4);
|
|
3693
3848
|
function validateMigrationUrl(value) {
|
|
3694
3849
|
let url;
|
|
3695
3850
|
try {
|
|
@@ -3729,10 +3884,10 @@ async function readResponseBody(response) {
|
|
|
3729
3884
|
}
|
|
3730
3885
|
return new TextDecoder().decode(body);
|
|
3731
3886
|
}
|
|
3732
|
-
var defaultMigrationFetcher = async (url,
|
|
3887
|
+
var defaultMigrationFetcher = async (url, request2) => {
|
|
3733
3888
|
const response = await fetch(url, {
|
|
3734
3889
|
headers: {
|
|
3735
|
-
Accept:
|
|
3890
|
+
Accept: request2.accept,
|
|
3736
3891
|
"User-Agent": "Thally-Migrate/1.0 (+https://thally.io)"
|
|
3737
3892
|
},
|
|
3738
3893
|
redirect: "follow",
|
|
@@ -4206,7 +4361,7 @@ function extractEmbeddedOpenApi(content) {
|
|
|
4206
4361
|
const opening = lines[0].match(/^ {0,3}(`{3,}|~{3,})/);
|
|
4207
4362
|
const closing = lines.at(-1)?.match(/^ {0,3}(`{3,}|~{3,})[\t ]*$/);
|
|
4208
4363
|
if (!opening || !closing || opening[1][0] !== closing[1][0] || closing[1].length < opening[1].length) return { content };
|
|
4209
|
-
const parsed =
|
|
4364
|
+
const parsed = parseYaml3(node.value ?? "", { maxAliasCount: 50 });
|
|
4210
4365
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return { content };
|
|
4211
4366
|
const document = parsed;
|
|
4212
4367
|
if (typeof document.openapi !== "string" && typeof document.swagger !== "string") return { content };
|
|
@@ -4736,7 +4891,7 @@ function observedMigrationArticleIdentity(document) {
|
|
|
4736
4891
|
canonical2.pathname = canonical2.pathname.replace(/\/+$/, "") || "/";
|
|
4737
4892
|
const removed = [...source.searchParams].filter(([key, value]) => !canonical2.searchParams.getAll(key).includes(value));
|
|
4738
4893
|
const sectionAnchor = removed.length === 1 && anchors.includes(removed[0][1]) ? removed[0][1] : void 0;
|
|
4739
|
-
return { canonicalUrl: canonical2.href, articleSha256:
|
|
4894
|
+
return { canonicalUrl: canonical2.href, articleSha256: createHash4("sha256").update(payload).digest("hex"), ...sectionAnchor ? { sectionAnchor } : {} };
|
|
4740
4895
|
}
|
|
4741
4896
|
|
|
4742
4897
|
// src/url-api-schema-controls.ts
|
|
@@ -4829,8 +4984,8 @@ function apiSchemaTabGroups(body, document, operation) {
|
|
|
4829
4984
|
let schema;
|
|
4830
4985
|
let scope;
|
|
4831
4986
|
if (title === "body") {
|
|
4832
|
-
const
|
|
4833
|
-
schema = object2(object2(
|
|
4987
|
+
const request2 = resolve2(document, selected.requestBody);
|
|
4988
|
+
schema = object2(object2(request2?.content)?.[media[0]])?.schema;
|
|
4834
4989
|
scope = `request:${media[0]}`;
|
|
4835
4990
|
} else if (title === "response") {
|
|
4836
4991
|
const statuses = heading.find('button[aria-haspopup="menu"]').toArray().map((button) => $(button).text().trim()).filter((text2) => /^(?:[1-5]\d{2}|default)$/.test(text2));
|
|
@@ -4929,8 +5084,8 @@ function apiSchemaDisclosureGroups(body, document, operation) {
|
|
|
4929
5084
|
schemas = [object2(object2(response?.content)?.[media[0]])?.schema];
|
|
4930
5085
|
prefix = "response";
|
|
4931
5086
|
} else if (media.length === 1 && !statuses.length) {
|
|
4932
|
-
const
|
|
4933
|
-
schemas = [object2(object2(
|
|
5087
|
+
const request2 = resolve2(document, selected.requestBody);
|
|
5088
|
+
schemas = [object2(object2(request2?.content)?.[media[0]])?.schema];
|
|
4934
5089
|
prefix = "body";
|
|
4935
5090
|
} else if (!media.length && !statuses.length) {
|
|
4936
5091
|
const head = $(chain[0]).find(".param-head[id]").filter((_index, element) => $(element).closest(fieldSelector)[0] === chain[0]).first().attr("id") ?? "";
|
|
@@ -5063,8 +5218,8 @@ function apiOperationCodeControls(body, specification, operation) {
|
|
|
5063
5218
|
const metadata = object2(resolveValue(value));
|
|
5064
5219
|
const declaration = resolveValue(metadata?.openapi);
|
|
5065
5220
|
if (typeof declaration !== "string") return false;
|
|
5066
|
-
const
|
|
5067
|
-
return
|
|
5221
|
+
const tokens2 = declaration.trim().split(/\s+/);
|
|
5222
|
+
return tokens2.at(-2)?.toLowerCase() === operation.method.toLowerCase() && tokens2.at(-1) === operation.path;
|
|
5068
5223
|
};
|
|
5069
5224
|
const active = /* @__PURE__ */ new Set();
|
|
5070
5225
|
const visit = (input, provider, group, depth, owners = []) => {
|
|
@@ -5110,9 +5265,9 @@ function apiOperationCodeControls(body, specification, operation) {
|
|
|
5110
5265
|
const hint = object2(resolveValue(scope?.pageMetadata)), metadata = object2(resolveValue(props.pageMetadata));
|
|
5111
5266
|
const declaration = resolveValue(hint?.openapi);
|
|
5112
5267
|
if (typeof declaration !== "string" || typeof hint?.href !== "string" || !hint.href || hint.href !== metadata?.href) return false;
|
|
5113
|
-
const
|
|
5268
|
+
const tokens2 = declaration.trim().split(/\s+/);
|
|
5114
5269
|
const template = (path) => path.split("/").map((segment) => /^\{[^{}\/]+\}$/.test(segment) ? "{}" : segment).join("/");
|
|
5115
|
-
return
|
|
5270
|
+
return tokens2.at(-2)?.toLowerCase() === operation.method.toLowerCase() && template(tokens2.at(-1) ?? "") === template(operation.path);
|
|
5116
5271
|
})()) generatedControllers += 1;
|
|
5117
5272
|
}
|
|
5118
5273
|
let local = group;
|
|
@@ -5221,14 +5376,14 @@ function apiOperationCodeControls(body, specification, operation) {
|
|
|
5221
5376
|
|
|
5222
5377
|
// src/url-run.ts
|
|
5223
5378
|
var CONVERTER_VERSION = "url-evidence-v7";
|
|
5224
|
-
var parser2 =
|
|
5379
|
+
var parser2 = unified5().use(remarkParse5).use(remarkMdx4);
|
|
5225
5380
|
var ACCEPT = "text/html,application/xhtml+xml";
|
|
5226
5381
|
var MAX_RESPONSE_BYTES = 8e6;
|
|
5227
5382
|
var MAX_ASSET_BYTES = 1e7;
|
|
5228
5383
|
var MAX_RECORDS = 1e5;
|
|
5229
5384
|
var LOCALES = /* @__PURE__ */ new Set(["ar", "cs", "da", "de", "el", "en", "es", "fi", "fr", "he", "hi", "hu", "id", "it", "ja", "ko", "ms", "nl", "no", "pl", "pt", "pt-br", "ro", "ru", "sk", "sv", "th", "tr", "uk", "vi", "zh", "zh-cn", "zh-hans", "zh-hant"]);
|
|
5230
5385
|
function hash(value) {
|
|
5231
|
-
return
|
|
5386
|
+
return createHash5("sha256").update(value).digest("hex");
|
|
5232
5387
|
}
|
|
5233
5388
|
function canonicalJson(value) {
|
|
5234
5389
|
const canonical2 = (value2) => Array.isArray(value2) ? value2.map(canonical2) : value2 !== null && typeof value2 === "object" ? Object.fromEntries(Object.entries(value2).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, field]) => [key, canonical2(field)])) : value2;
|
|
@@ -5749,7 +5904,7 @@ async function runUrlMigration(options) {
|
|
|
5749
5904
|
} catch {
|
|
5750
5905
|
}
|
|
5751
5906
|
}
|
|
5752
|
-
const capture = (
|
|
5907
|
+
const capture = (request2) => initial && canonical(request2.url.href, sourceUrl) === sourceUrl ? initial : acquire(request2);
|
|
5753
5908
|
const requestedScope = options.scopePath ?? options.checkpoint?.scopePath ?? inferredScope ?? (source.pathname.endsWith("/") ? source.pathname : source.pathname.slice(0, source.pathname.lastIndexOf("/")) || "/");
|
|
5754
5909
|
let scopeEnd = requestedScope.length;
|
|
5755
5910
|
while (scopeEnd > 0 && requestedScope.charCodeAt(scopeEnd - 1) === 47) scopeEnd--;
|
|
@@ -6493,16 +6648,16 @@ function rewriteMarkdownDestinations(body, rewrite) {
|
|
|
6493
6648
|
}
|
|
6494
6649
|
|
|
6495
6650
|
// src/components.ts
|
|
6496
|
-
import { createHash as
|
|
6651
|
+
import { createHash as createHash6 } from "crypto";
|
|
6497
6652
|
import { existsSync as existsSync2, lstatSync as lstatSync2, readFileSync as readFileSync2 } from "fs";
|
|
6498
6653
|
import { basename, dirname as dirname2, extname as extname3, posix as posix2, relative as relative3, resolve as resolve3 } from "path";
|
|
6499
6654
|
import postcss from "postcss";
|
|
6500
6655
|
import selectorParser from "postcss-selector-parser";
|
|
6501
6656
|
import remarkMdx5 from "remark-mdx";
|
|
6502
|
-
import
|
|
6657
|
+
import remarkParse6 from "remark-parse";
|
|
6503
6658
|
import ts2 from "typescript";
|
|
6504
|
-
import { unified as
|
|
6505
|
-
var parser3 =
|
|
6659
|
+
import { unified as unified6 } from "unified";
|
|
6660
|
+
var parser3 = unified6().use(remarkParse6).use(remarkMdx5);
|
|
6506
6661
|
var DOCUSAURUS_THEME_SHIMS = {
|
|
6507
6662
|
"@theme/CodeBlock": {
|
|
6508
6663
|
filename: "docusaurus-code-block.tsx",
|
|
@@ -6542,7 +6697,7 @@ function applyReplacements(source, replacements) {
|
|
|
6542
6697
|
);
|
|
6543
6698
|
}
|
|
6544
6699
|
function hash2(value) {
|
|
6545
|
-
return
|
|
6700
|
+
return createHash6("sha256").update(value).digest("hex").slice(0, 12);
|
|
6546
6701
|
}
|
|
6547
6702
|
function sourceFile(source, filename) {
|
|
6548
6703
|
return ts2.createSourceFile(filename, source, ts2.ScriptTarget.Latest, true, scriptKindFor(filename));
|
|
@@ -6619,6 +6774,32 @@ function renderPage(bundle, page) {
|
|
|
6619
6774
|
function isIntegrationsObject(value) {
|
|
6620
6775
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
6621
6776
|
}
|
|
6777
|
+
function mergeRedirects(existing = [], incoming = []) {
|
|
6778
|
+
const redirects = [...existing];
|
|
6779
|
+
const key = (source) => literalRoute(source) ?? trimTrailingSlashes(source).toLowerCase();
|
|
6780
|
+
const destinationKey = (destination) => literalRoute(destinationRoute(destination) ?? "");
|
|
6781
|
+
const sources = new Set(existing.map((redirect) => key(redirect.source)));
|
|
6782
|
+
for (const redirect of incoming) {
|
|
6783
|
+
const source = key(redirect.source);
|
|
6784
|
+
if (sources.has(source)) continue;
|
|
6785
|
+
const visited = /* @__PURE__ */ new Set([source]);
|
|
6786
|
+
let destination = destinationKey(redirect.destination);
|
|
6787
|
+
let cycle = false;
|
|
6788
|
+
while (destination) {
|
|
6789
|
+
if (visited.has(destination)) {
|
|
6790
|
+
cycle = true;
|
|
6791
|
+
break;
|
|
6792
|
+
}
|
|
6793
|
+
visited.add(destination);
|
|
6794
|
+
const next = redirects.find((candidate) => literalRoute(candidate.source) === destination);
|
|
6795
|
+
destination = next ? destinationKey(next.destination) : null;
|
|
6796
|
+
}
|
|
6797
|
+
if (cycle) continue;
|
|
6798
|
+
redirects.push(redirect);
|
|
6799
|
+
sources.add(source);
|
|
6800
|
+
}
|
|
6801
|
+
return redirects;
|
|
6802
|
+
}
|
|
6622
6803
|
function mergeMigrationConfig(existing, incoming) {
|
|
6623
6804
|
const tabs = existing.tabs.filter((tab) => tab.tab.toLowerCase() !== "changelog");
|
|
6624
6805
|
const names = new Set(tabs.map((tab) => tab.tab.toLowerCase()));
|
|
@@ -6686,6 +6867,10 @@ function mergeMigrationConfig(existing, incoming) {
|
|
|
6686
6867
|
...incoming,
|
|
6687
6868
|
...existing,
|
|
6688
6869
|
tabs,
|
|
6870
|
+
...existing.redirects || incoming.redirects ? { redirects: mergeRedirects(existing.redirects, incoming.redirects) } : {},
|
|
6871
|
+
// A starter's primary action must not discard a newly imported logo.
|
|
6872
|
+
// Owner-authored fields, including an explicit null logo, remain authoritative.
|
|
6873
|
+
...incoming.navbar || existing.navbar ? { navbar: { ...incoming.navbar, ...existing.navbar } } : {},
|
|
6689
6874
|
// Collection presentation belongs to the imported information
|
|
6690
6875
|
// architecture; starter defaults must not coerce source dropdowns to tabs.
|
|
6691
6876
|
navigation: incoming.navigation ?? existing.navigation,
|