@thallylabs/migrate 0.2.41 → 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 +20 -1
- package/dist/index.d.ts +36 -3
- package/dist/index.js +655 -227
- package/dist/index.js.map +1 -1
- package/dist/url-migration.d.ts +2 -2
- package/dist/url-migration.js +332 -64
- package/dist/url-migration.js.map +1 -1
- package/dist/{url-run-mSKFqHx_.d.ts → url-run-CPzQfjRW.d.ts} +2 -0
- package/package.json +2 -1
package/dist/url-migration.js
CHANGED
|
@@ -1,9 +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
|
-
import
|
|
4
|
+
import { parse as parse2, postprocess, preprocess } from "micromark";
|
|
5
|
+
import remarkParse5 from "remark-parse";
|
|
5
6
|
import remarkMdx4 from "remark-mdx";
|
|
6
|
-
import { unified as
|
|
7
|
+
import { unified as unified5 } from "unified";
|
|
7
8
|
|
|
8
9
|
// src/navigation.ts
|
|
9
10
|
import { existsSync, lstatSync, readFileSync, realpathSync as realpathSync2 } from "fs";
|
|
@@ -496,15 +497,15 @@ function createMigrationAssetCache() {
|
|
|
496
497
|
load(url, acquire) {
|
|
497
498
|
const existing = get(url);
|
|
498
499
|
if (existing) return existing;
|
|
499
|
-
const
|
|
500
|
+
const request2 = Promise.resolve().then(acquire).then((asset) => {
|
|
500
501
|
pending.delete(url);
|
|
501
502
|
return remember(url, asset);
|
|
502
503
|
}, (error) => {
|
|
503
504
|
pending.delete(url);
|
|
504
505
|
throw error;
|
|
505
506
|
});
|
|
506
|
-
pending.set(url,
|
|
507
|
-
return
|
|
507
|
+
pending.set(url, request2);
|
|
508
|
+
return request2;
|
|
508
509
|
},
|
|
509
510
|
delete(url) {
|
|
510
511
|
settled.delete(url);
|
|
@@ -1815,7 +1816,10 @@ var VIDEO_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
|
1815
1816
|
"width",
|
|
1816
1817
|
"height",
|
|
1817
1818
|
"preload",
|
|
1818
|
-
"aria-label"
|
|
1819
|
+
"aria-label",
|
|
1820
|
+
// Publisher asset provenance does not change playback and is never emitted.
|
|
1821
|
+
// Keep this explicit: arbitrary data attributes may drive custom controls.
|
|
1822
|
+
"data-path"
|
|
1819
1823
|
]);
|
|
1820
1824
|
var YOUTUBE_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
1821
1825
|
"src",
|
|
@@ -1880,16 +1884,27 @@ function projectMigrationMedia(html, base) {
|
|
|
1880
1884
|
}
|
|
1881
1885
|
|
|
1882
1886
|
// src/url-identity.ts
|
|
1883
|
-
import { createHash as
|
|
1887
|
+
import { createHash as createHash4 } from "crypto";
|
|
1884
1888
|
import { load as load6 } from "cheerio";
|
|
1885
1889
|
|
|
1886
1890
|
// src/url.ts
|
|
1887
1891
|
import { load as load5 } from "cheerio";
|
|
1888
1892
|
import remarkMdx3 from "remark-mdx";
|
|
1889
|
-
import
|
|
1893
|
+
import remarkParse4 from "remark-parse";
|
|
1890
1894
|
import TurndownService from "turndown";
|
|
1891
|
-
import { unified as
|
|
1892
|
-
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";
|
|
1893
1908
|
|
|
1894
1909
|
// src/analytics.ts
|
|
1895
1910
|
var HOSTNAME_LABEL = "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?";
|
|
@@ -1901,8 +1916,8 @@ import { compileSync } from "@mdx-js/mdx";
|
|
|
1901
1916
|
import { nameToEmoji } from "gemoji";
|
|
1902
1917
|
import remarkGfm2 from "remark-gfm";
|
|
1903
1918
|
import remarkMdx2 from "remark-mdx";
|
|
1904
|
-
import
|
|
1905
|
-
import { unified as
|
|
1919
|
+
import remarkParse3 from "remark-parse";
|
|
1920
|
+
import { unified as unified3 } from "unified";
|
|
1906
1921
|
|
|
1907
1922
|
// src/builtin-components.ts
|
|
1908
1923
|
var THALLY_BUILTIN_COMPONENTS = /* @__PURE__ */ new Set([
|
|
@@ -2339,13 +2354,13 @@ function unresolvedExpressionNames(expression, pageNames) {
|
|
|
2339
2354
|
}
|
|
2340
2355
|
|
|
2341
2356
|
// src/frontmatter.ts
|
|
2342
|
-
import { parse as
|
|
2357
|
+
import { parse as parseYaml2 } from "yaml";
|
|
2343
2358
|
function salvageFrontmatterLines(matter) {
|
|
2344
2359
|
const data = {};
|
|
2345
2360
|
for (const line of matter.split(/\r?\n/)) {
|
|
2346
2361
|
if (!/^[A-Za-z_][\w-]*:\s?/.test(line)) continue;
|
|
2347
2362
|
try {
|
|
2348
|
-
const parsedLine =
|
|
2363
|
+
const parsedLine = parseYaml2(line);
|
|
2349
2364
|
if (parsedLine && typeof parsedLine === "object" && !Array.isArray(parsedLine)) {
|
|
2350
2365
|
Object.assign(data, parsedLine);
|
|
2351
2366
|
}
|
|
@@ -2369,7 +2384,7 @@ function parseFrontmatter(raw) {
|
|
|
2369
2384
|
return { content, data: {} };
|
|
2370
2385
|
}
|
|
2371
2386
|
try {
|
|
2372
|
-
const parsed =
|
|
2387
|
+
const parsed = parseYaml2(matter);
|
|
2373
2388
|
return {
|
|
2374
2389
|
content,
|
|
2375
2390
|
data: parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {}
|
|
@@ -2383,13 +2398,103 @@ function parseFrontmatter(raw) {
|
|
|
2383
2398
|
}
|
|
2384
2399
|
}
|
|
2385
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
|
+
|
|
2386
2491
|
// src/mdx.ts
|
|
2387
2492
|
function titleFromId(id) {
|
|
2388
2493
|
const value = id.split("/").at(-1) ?? id;
|
|
2389
2494
|
if (value === "introduction") return "Introduction";
|
|
2390
2495
|
return value.split(/[-_]/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
2391
2496
|
}
|
|
2392
|
-
var descriptionParser =
|
|
2497
|
+
var descriptionParser = unified3().use(remarkParse3).use(remarkGfm2).use(remarkMdx2);
|
|
2393
2498
|
function plainText(node) {
|
|
2394
2499
|
if (node.type === "text" || node.type === "inlineCode") return node.value ?? "";
|
|
2395
2500
|
if (node.type === "image") return node.alt ?? "";
|
|
@@ -3404,13 +3509,41 @@ function externalPageUrl(value) {
|
|
|
3404
3509
|
}
|
|
3405
3510
|
function parseMarkdownPage(input) {
|
|
3406
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
|
+
}
|
|
3407
3539
|
const fallbackIdentity = {
|
|
3408
3540
|
id: input.id,
|
|
3409
3541
|
navigationId: input.navigationId ?? input.id,
|
|
3410
3542
|
...input.locale ? { locale: input.locale } : {}
|
|
3411
3543
|
};
|
|
3412
3544
|
const identity = input.resolveIdentity?.(parsed.data, fallbackIdentity) ?? fallbackIdentity;
|
|
3413
|
-
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();
|
|
3414
3547
|
const keywords = Array.isArray(parsed.data.keywords) ? parsed.data.keywords.filter((value) => typeof value === "string") : [];
|
|
3415
3548
|
const heading = leadingPageHeading(body);
|
|
3416
3549
|
const title = typeof parsed.data.title === "string" && parsed.data.title.trim() ? parsed.data.title.trim() : heading?.title ?? titleFromId(identity.navigationId);
|
|
@@ -3483,7 +3616,7 @@ function apiFrontmatter(data, warn) {
|
|
|
3483
3616
|
}
|
|
3484
3617
|
|
|
3485
3618
|
// src/url-static-content.ts
|
|
3486
|
-
import { createHash as
|
|
3619
|
+
import { createHash as createHash3 } from "crypto";
|
|
3487
3620
|
import { load as load4 } from "cheerio";
|
|
3488
3621
|
function projectMigrationSvg(html) {
|
|
3489
3622
|
const $ = load4(html, { xmlMode: true }, false);
|
|
@@ -3492,7 +3625,7 @@ function projectMigrationSvg(html) {
|
|
|
3492
3625
|
if (svg.attr("xmlns") === void 0) svg.attr("xmlns", "http://www.w3.org/2000/svg");
|
|
3493
3626
|
const content = Buffer.from($.xml(svg));
|
|
3494
3627
|
if (!isPassiveSvg(content)) return null;
|
|
3495
|
-
const sha256 =
|
|
3628
|
+
const sha256 = createHash3("sha256").update(content).digest("hex");
|
|
3496
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);
|
|
3497
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();
|
|
3498
3631
|
return { asset: { path: `migration-assets/${sha256}.svg`, content }, alternative };
|
|
@@ -3605,6 +3738,32 @@ function projectCapturedTabs($, root) {
|
|
|
3605
3738
|
}
|
|
3606
3739
|
}
|
|
3607
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
|
+
|
|
3608
3767
|
// src/url.ts
|
|
3609
3768
|
var MAX_LOCAL_RESPONSE_BYTES = 8e6;
|
|
3610
3769
|
var MAX_EMBEDDED_SCHEMA_BYTES = 2e6;
|
|
@@ -3684,8 +3843,8 @@ var MINTLIFY_ARTICLE_LABELS = [
|
|
|
3684
3843
|
{ baseUrl: "Select base URL", permalink: "Navigate to header" },
|
|
3685
3844
|
{ baseUrl: "\u9009\u62E9\u57FA\u7840URL", permalink: "\u5BFC\u822A\u5230\u6807\u9898" }
|
|
3686
3845
|
];
|
|
3687
|
-
var remoteMarkdownParser =
|
|
3688
|
-
var embeddedOpenApiParser =
|
|
3846
|
+
var remoteMarkdownParser = unified4().use(remarkParse4).use(remarkMdx3);
|
|
3847
|
+
var embeddedOpenApiParser = unified4().use(remarkParse4);
|
|
3689
3848
|
function validateMigrationUrl(value) {
|
|
3690
3849
|
let url;
|
|
3691
3850
|
try {
|
|
@@ -3725,10 +3884,10 @@ async function readResponseBody(response) {
|
|
|
3725
3884
|
}
|
|
3726
3885
|
return new TextDecoder().decode(body);
|
|
3727
3886
|
}
|
|
3728
|
-
var defaultMigrationFetcher = async (url,
|
|
3887
|
+
var defaultMigrationFetcher = async (url, request2) => {
|
|
3729
3888
|
const response = await fetch(url, {
|
|
3730
3889
|
headers: {
|
|
3731
|
-
Accept:
|
|
3890
|
+
Accept: request2.accept,
|
|
3732
3891
|
"User-Agent": "Thally-Migrate/1.0 (+https://thally.io)"
|
|
3733
3892
|
},
|
|
3734
3893
|
redirect: "follow",
|
|
@@ -4202,7 +4361,7 @@ function extractEmbeddedOpenApi(content) {
|
|
|
4202
4361
|
const opening = lines[0].match(/^ {0,3}(`{3,}|~{3,})/);
|
|
4203
4362
|
const closing = lines.at(-1)?.match(/^ {0,3}(`{3,}|~{3,})[\t ]*$/);
|
|
4204
4363
|
if (!opening || !closing || opening[1][0] !== closing[1][0] || closing[1].length < opening[1].length) return { content };
|
|
4205
|
-
const parsed =
|
|
4364
|
+
const parsed = parseYaml3(node.value ?? "", { maxAliasCount: 50 });
|
|
4206
4365
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return { content };
|
|
4207
4366
|
const document = parsed;
|
|
4208
4367
|
if (typeof document.openapi !== "string" && typeof document.swagger !== "string") return { content };
|
|
@@ -4732,7 +4891,7 @@ function observedMigrationArticleIdentity(document) {
|
|
|
4732
4891
|
canonical2.pathname = canonical2.pathname.replace(/\/+$/, "") || "/";
|
|
4733
4892
|
const removed = [...source.searchParams].filter(([key, value]) => !canonical2.searchParams.getAll(key).includes(value));
|
|
4734
4893
|
const sectionAnchor = removed.length === 1 && anchors.includes(removed[0][1]) ? removed[0][1] : void 0;
|
|
4735
|
-
return { canonicalUrl: canonical2.href, articleSha256:
|
|
4894
|
+
return { canonicalUrl: canonical2.href, articleSha256: createHash4("sha256").update(payload).digest("hex"), ...sectionAnchor ? { sectionAnchor } : {} };
|
|
4736
4895
|
}
|
|
4737
4896
|
|
|
4738
4897
|
// src/url-api-schema-controls.ts
|
|
@@ -4825,8 +4984,8 @@ function apiSchemaTabGroups(body, document, operation) {
|
|
|
4825
4984
|
let schema;
|
|
4826
4985
|
let scope;
|
|
4827
4986
|
if (title === "body") {
|
|
4828
|
-
const
|
|
4829
|
-
schema = object2(object2(
|
|
4987
|
+
const request2 = resolve2(document, selected.requestBody);
|
|
4988
|
+
schema = object2(object2(request2?.content)?.[media[0]])?.schema;
|
|
4830
4989
|
scope = `request:${media[0]}`;
|
|
4831
4990
|
} else if (title === "response") {
|
|
4832
4991
|
const statuses = heading.find('button[aria-haspopup="menu"]').toArray().map((button) => $(button).text().trim()).filter((text2) => /^(?:[1-5]\d{2}|default)$/.test(text2));
|
|
@@ -4925,8 +5084,8 @@ function apiSchemaDisclosureGroups(body, document, operation) {
|
|
|
4925
5084
|
schemas = [object2(object2(response?.content)?.[media[0]])?.schema];
|
|
4926
5085
|
prefix = "response";
|
|
4927
5086
|
} else if (media.length === 1 && !statuses.length) {
|
|
4928
|
-
const
|
|
4929
|
-
schemas = [object2(object2(
|
|
5087
|
+
const request2 = resolve2(document, selected.requestBody);
|
|
5088
|
+
schemas = [object2(object2(request2?.content)?.[media[0]])?.schema];
|
|
4930
5089
|
prefix = "body";
|
|
4931
5090
|
} else if (!media.length && !statuses.length) {
|
|
4932
5091
|
const head = $(chain[0]).find(".param-head[id]").filter((_index, element) => $(element).closest(fieldSelector)[0] === chain[0]).first().attr("id") ?? "";
|
|
@@ -5059,8 +5218,8 @@ function apiOperationCodeControls(body, specification, operation) {
|
|
|
5059
5218
|
const metadata = object2(resolveValue(value));
|
|
5060
5219
|
const declaration = resolveValue(metadata?.openapi);
|
|
5061
5220
|
if (typeof declaration !== "string") return false;
|
|
5062
|
-
const
|
|
5063
|
-
return
|
|
5221
|
+
const tokens2 = declaration.trim().split(/\s+/);
|
|
5222
|
+
return tokens2.at(-2)?.toLowerCase() === operation.method.toLowerCase() && tokens2.at(-1) === operation.path;
|
|
5064
5223
|
};
|
|
5065
5224
|
const active = /* @__PURE__ */ new Set();
|
|
5066
5225
|
const visit = (input, provider, group, depth, owners = []) => {
|
|
@@ -5106,9 +5265,9 @@ function apiOperationCodeControls(body, specification, operation) {
|
|
|
5106
5265
|
const hint = object2(resolveValue(scope?.pageMetadata)), metadata = object2(resolveValue(props.pageMetadata));
|
|
5107
5266
|
const declaration = resolveValue(hint?.openapi);
|
|
5108
5267
|
if (typeof declaration !== "string" || typeof hint?.href !== "string" || !hint.href || hint.href !== metadata?.href) return false;
|
|
5109
|
-
const
|
|
5268
|
+
const tokens2 = declaration.trim().split(/\s+/);
|
|
5110
5269
|
const template = (path) => path.split("/").map((segment) => /^\{[^{}\/]+\}$/.test(segment) ? "{}" : segment).join("/");
|
|
5111
|
-
return
|
|
5270
|
+
return tokens2.at(-2)?.toLowerCase() === operation.method.toLowerCase() && template(tokens2.at(-1) ?? "") === template(operation.path);
|
|
5112
5271
|
})()) generatedControllers += 1;
|
|
5113
5272
|
}
|
|
5114
5273
|
let local = group;
|
|
@@ -5216,15 +5375,15 @@ function apiOperationCodeControls(body, specification, operation) {
|
|
|
5216
5375
|
}
|
|
5217
5376
|
|
|
5218
5377
|
// src/url-run.ts
|
|
5219
|
-
var CONVERTER_VERSION = "url-evidence-
|
|
5220
|
-
var parser2 =
|
|
5221
|
-
var ACCEPT = "text/
|
|
5378
|
+
var CONVERTER_VERSION = "url-evidence-v7";
|
|
5379
|
+
var parser2 = unified5().use(remarkParse5).use(remarkMdx4);
|
|
5380
|
+
var ACCEPT = "text/html,application/xhtml+xml";
|
|
5222
5381
|
var MAX_RESPONSE_BYTES = 8e6;
|
|
5223
5382
|
var MAX_ASSET_BYTES = 1e7;
|
|
5224
5383
|
var MAX_RECORDS = 1e5;
|
|
5225
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"]);
|
|
5226
5385
|
function hash(value) {
|
|
5227
|
-
return
|
|
5386
|
+
return createHash5("sha256").update(value).digest("hex");
|
|
5228
5387
|
}
|
|
5229
5388
|
function canonicalJson(value) {
|
|
5230
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;
|
|
@@ -5248,6 +5407,11 @@ function canonical(value, base) {
|
|
|
5248
5407
|
return null;
|
|
5249
5408
|
}
|
|
5250
5409
|
}
|
|
5410
|
+
function sameRouteMarkdownRepresentation(alternate, primary) {
|
|
5411
|
+
const target2 = new URL(alternate), source = new URL(primary);
|
|
5412
|
+
const directory2 = (path) => path.replace(/\.mdx?$/i, "").replace(/\/index\/?$/i, "").replace(/\/$/, "");
|
|
5413
|
+
return target2.origin === source.origin && target2.search === source.search && directory2(target2.pathname) === directory2(source.pathname) && /\.mdx?$/i.test(target2.pathname);
|
|
5414
|
+
}
|
|
5251
5415
|
function classifyMigrationResponse(document) {
|
|
5252
5416
|
if (document.status && document.status >= 400) return "unsupported";
|
|
5253
5417
|
if (/\/(?:llms(?:-full)?|robots)\.txt$|\/sitemap[^/]*\.xml$|\/search(?:\.html)?$/i.test(document.finalUrl.pathname) || /\.(?:json|ya?ml)$/i.test(document.finalUrl.pathname) || /(?:xml|json)/i.test(document.contentType)) return "index";
|
|
@@ -5498,7 +5662,7 @@ function resolveMigrationRecord(records, record) {
|
|
|
5498
5662
|
}
|
|
5499
5663
|
return record;
|
|
5500
5664
|
}
|
|
5501
|
-
function navigationConfig(checkpoint, records) {
|
|
5665
|
+
function navigationConfig(checkpoint, records, occurrencePages = /* @__PURE__ */ new Map()) {
|
|
5502
5666
|
const navigation = checkpoint.navigation;
|
|
5503
5667
|
const shortcuts = [];
|
|
5504
5668
|
const collectShortcuts = (nodes) => {
|
|
@@ -5523,7 +5687,7 @@ function navigationConfig(checkpoint, records) {
|
|
|
5523
5687
|
const project = (nodes) => nodes.flatMap((node) => {
|
|
5524
5688
|
const record = node.url ? records.get(canonical(node.url, node.url) ?? "") : void 0;
|
|
5525
5689
|
const target2 = resolveMigrationRecord(records, record);
|
|
5526
|
-
const page = target2?.page;
|
|
5690
|
+
const page = occurrencePages.get(node) ?? target2?.page;
|
|
5527
5691
|
const children = project(node.children ?? []);
|
|
5528
5692
|
if (children.length) {
|
|
5529
5693
|
const contains = (entries) => entries.some((entry) => typeof entry === "string" ? entry === (page && projection.navigationId(page)) : contains(entry.pages));
|
|
@@ -5740,7 +5904,7 @@ async function runUrlMigration(options) {
|
|
|
5740
5904
|
} catch {
|
|
5741
5905
|
}
|
|
5742
5906
|
}
|
|
5743
|
-
const capture = (
|
|
5907
|
+
const capture = (request2) => initial && canonical(request2.url.href, sourceUrl) === sourceUrl ? initial : acquire(request2);
|
|
5744
5908
|
const requestedScope = options.scopePath ?? options.checkpoint?.scopePath ?? inferredScope ?? (source.pathname.endsWith("/") ? source.pathname : source.pathname.slice(0, source.pathname.lastIndexOf("/")) || "/");
|
|
5745
5909
|
let scopeEnd = requestedScope.length;
|
|
5746
5910
|
while (scopeEnd > 0 && requestedScope.charCodeAt(scopeEnd - 1) === 47) scopeEnd--;
|
|
@@ -5823,8 +5987,19 @@ async function runUrlMigration(options) {
|
|
|
5823
5987
|
if (!record.evidence) continue;
|
|
5824
5988
|
const final = canonical(record.evidence.finalUrl, sourceUrl);
|
|
5825
5989
|
if (!final) continue;
|
|
5826
|
-
if (record.outcome === "imported")
|
|
5827
|
-
|
|
5990
|
+
if (record.outcome === "imported") {
|
|
5991
|
+
enqueueArticleLinks(record.evidence.links, final, record.url);
|
|
5992
|
+
for (const reference of record.evidence.markdownRepresentations ?? []) {
|
|
5993
|
+
const alternate = canonical(reference, final);
|
|
5994
|
+
if (!alternate || !sameRouteMarkdownRepresentation(alternate, final)) continue;
|
|
5995
|
+
enqueue(alternate, final, "declared-markdown-representation");
|
|
5996
|
+
const sibling = records.get(alternate);
|
|
5997
|
+
if (sibling && sibling.representationOf !== record.url) {
|
|
5998
|
+
sibling.representationOf = record.url;
|
|
5999
|
+
changed.push(sibling);
|
|
6000
|
+
}
|
|
6001
|
+
}
|
|
6002
|
+
} else if (record.outcome === "excluded") {
|
|
5828
6003
|
if (classifyMigrationResponse({ finalUrl: new URL(final), contentType: record.evidence.contentType, body: "" }) === "index") {
|
|
5829
6004
|
for (const link of record.evidence.links) enqueue(link, final, record.url);
|
|
5830
6005
|
}
|
|
@@ -5907,6 +6082,7 @@ async function runUrlMigration(options) {
|
|
|
5907
6082
|
let claimedId;
|
|
5908
6083
|
let claimedFinal;
|
|
5909
6084
|
let markdownRepresentation;
|
|
6085
|
+
const markdownRepresentations = [];
|
|
5910
6086
|
let exactKey;
|
|
5911
6087
|
try {
|
|
5912
6088
|
delete record.reason;
|
|
@@ -5999,13 +6175,13 @@ async function runUrlMigration(options) {
|
|
|
5999
6175
|
$('link[rel="alternate"][type="text/markdown"][href]').each((_index, node) => {
|
|
6000
6176
|
const alternate = canonical($(node).attr("href"), final);
|
|
6001
6177
|
if (!alternate) return;
|
|
6002
|
-
|
|
6003
|
-
const directory2 = (path) => path.replace(/\.mdx?$/i, "").replace(/\/index\/?$/i, "").replace(/\/$/, "");
|
|
6004
|
-
if (target2.origin !== primary.origin || target2.search !== primary.search || directory2(target2.pathname) !== directory2(primary.pathname) || !/\.mdx?$/i.test(target2.pathname)) return;
|
|
6178
|
+
if (!sameRouteMarkdownRepresentation(alternate, final)) return;
|
|
6005
6179
|
enqueue(alternate, final, "declared-markdown-representation");
|
|
6006
6180
|
const sibling = records.get(alternate);
|
|
6181
|
+
if (!sibling) return;
|
|
6007
6182
|
sibling.representationOf = record.url;
|
|
6008
6183
|
markdownRepresentation ??= alternate;
|
|
6184
|
+
markdownRepresentations.push(alternate);
|
|
6009
6185
|
changed.push(sibling);
|
|
6010
6186
|
});
|
|
6011
6187
|
}
|
|
@@ -6018,7 +6194,8 @@ async function runUrlMigration(options) {
|
|
|
6018
6194
|
}
|
|
6019
6195
|
enqueueNavigation(observedNavigation, final);
|
|
6020
6196
|
}
|
|
6021
|
-
|
|
6197
|
+
const replacesRepresentation = imported >= maxPages && markdownRepresentations.some((url) => records.get(url)?.page);
|
|
6198
|
+
if (imported >= maxPages && !replacesRepresentation) {
|
|
6022
6199
|
record.outcome = "excluded";
|
|
6023
6200
|
record.reason = "A discovery endpoint resolved to an article after the selected page limit.";
|
|
6024
6201
|
return;
|
|
@@ -6037,14 +6214,17 @@ async function runUrlMigration(options) {
|
|
|
6037
6214
|
const locale = language.locale;
|
|
6038
6215
|
const navigationId = locale ? id.split("/").filter((segment) => segment.toLowerCase() !== locale.toLowerCase()).join("/") || "introduction" : id;
|
|
6039
6216
|
const identityId = locale ? `${locale}/${navigationId}` : id;
|
|
6040
|
-
|
|
6217
|
+
const owner = records.get(usedIds.get(identityId) ?? "");
|
|
6218
|
+
const sharesDeclaredRepresentation = owner && (owner.representationOf === record.url || record.representationOf === owner.url);
|
|
6219
|
+
if (owner && owner !== record && !sharesDeclaredRepresentation) {
|
|
6041
6220
|
record.outcome = "failed";
|
|
6042
6221
|
record.reason = `Destination collision for ${identityId}.`;
|
|
6043
6222
|
return;
|
|
6044
6223
|
}
|
|
6045
|
-
usedIds.set(identityId, record.url);
|
|
6224
|
+
if (!owner || owner === record || owner.representationOf === record.url) usedIds.set(identityId, record.url);
|
|
6046
6225
|
claimedId = identityId;
|
|
6047
6226
|
const evidence = evidenceOf(document);
|
|
6227
|
+
if (markdownRepresentations.length) evidence.markdownRepresentations = markdownRepresentations;
|
|
6048
6228
|
const page = convert(document, id);
|
|
6049
6229
|
if (!page) {
|
|
6050
6230
|
record.outcome = "failed";
|
|
@@ -6255,6 +6435,7 @@ ${difference}`;
|
|
|
6255
6435
|
if (!primary || primary === record) continue;
|
|
6256
6436
|
const winner = primary.outcome === "imported" ? primary : record.outcome === "imported" && primary.outcome === "failed" ? record : void 0;
|
|
6257
6437
|
if (!winner) continue;
|
|
6438
|
+
if (winner.page) usedIds.set(winner.page.id, winner.url);
|
|
6258
6439
|
const alternate = winner === primary ? record : primary;
|
|
6259
6440
|
if (alternate.outcome === "alias" && alternate.aliasOf === winner.url) continue;
|
|
6260
6441
|
if (alternate.outcome === "imported") {
|
|
@@ -6276,7 +6457,17 @@ ${difference}`;
|
|
|
6276
6457
|
settleArticleIdentities();
|
|
6277
6458
|
while (cursor < pending.length && !options.signal?.aborted && !budgetExhausted && cursor < (options.maxCaptures ?? Infinity)) {
|
|
6278
6459
|
if (imported >= maxPages) {
|
|
6279
|
-
const index = pending.findIndex((record, position) =>
|
|
6460
|
+
const index = pending.findIndex((record, position) => {
|
|
6461
|
+
if (position < cursor || record.outcome !== "pending") return false;
|
|
6462
|
+
const url = new URL(record.url);
|
|
6463
|
+
if (isDiscoveryIndex(url, source)) return true;
|
|
6464
|
+
if (/\.mdx?$/i.test(url.pathname)) return false;
|
|
6465
|
+
return [".md", ".mdx", "/index.md", "/index.mdx"].some((extension) => {
|
|
6466
|
+
const alternate = new URL(url);
|
|
6467
|
+
alternate.pathname = alternate.pathname.replace(/\/index$/i, "") + extension;
|
|
6468
|
+
return records.get(alternate.href)?.outcome === "imported";
|
|
6469
|
+
});
|
|
6470
|
+
});
|
|
6280
6471
|
if (index < 0) break;
|
|
6281
6472
|
pending.splice(cursor, 0, pending.splice(index, 1)[0]);
|
|
6282
6473
|
}
|
|
@@ -6300,19 +6491,60 @@ ${difference}`;
|
|
|
6300
6491
|
}
|
|
6301
6492
|
const navigationLabels = /* @__PURE__ */ new Map();
|
|
6302
6493
|
const navigationIssues = [];
|
|
6494
|
+
const navigationOccurrences = /* @__PURE__ */ new Map();
|
|
6303
6495
|
const labelPages = (nodes) => {
|
|
6304
6496
|
for (const node of nodes) {
|
|
6305
6497
|
const entry = node.url ? records.get(canonical(node.url, sourceUrl) ?? "") : void 0;
|
|
6306
6498
|
const target2 = resolveMigrationRecord(records, entry);
|
|
6307
|
-
if (target2?.page && node.label && !node.children?.length && !entry
|
|
6308
|
-
const
|
|
6309
|
-
|
|
6310
|
-
|
|
6499
|
+
if (entry && target2?.page && node.label && !node.children?.length && !entry.aliasAnchor) {
|
|
6500
|
+
const occurrences = navigationOccurrences.get(target2) ?? [];
|
|
6501
|
+
occurrences.push({ node, entry });
|
|
6502
|
+
navigationOccurrences.set(target2, occurrences);
|
|
6311
6503
|
}
|
|
6312
6504
|
labelPages(node.children ?? []);
|
|
6313
6505
|
}
|
|
6314
6506
|
};
|
|
6315
6507
|
labelPages(checkpoint.navigation);
|
|
6508
|
+
const occurrencePages = /* @__PURE__ */ new Map();
|
|
6509
|
+
const navigationAliases = /* @__PURE__ */ new Map();
|
|
6510
|
+
const occupiedPageIds = new Set(checkpoint.records.flatMap((record) => record.page ? [projection.pageId(record.page)] : []));
|
|
6511
|
+
const navigationRedirects = [];
|
|
6512
|
+
for (const [target2, occurrences] of navigationOccurrences) {
|
|
6513
|
+
const final = target2.evidence && canonical(target2.evidence.finalUrl, sourceUrl);
|
|
6514
|
+
const primary = occurrences.find(({ entry }) => entry.url === final) ?? occurrences.find(({ entry }) => entry === target2) ?? occurrences[0];
|
|
6515
|
+
navigationLabels.set(target2.url, primary.node.label);
|
|
6516
|
+
for (const { node, entry } of occurrences) {
|
|
6517
|
+
if (node.label === primary.node.label) continue;
|
|
6518
|
+
const existing = navigationAliases.get(entry.url);
|
|
6519
|
+
if (existing?.page.navTitle === node.label && existing.target === target2) {
|
|
6520
|
+
occurrencePages.set(node, existing.page);
|
|
6521
|
+
continue;
|
|
6522
|
+
}
|
|
6523
|
+
const sourceRoute = new URL(entry.url);
|
|
6524
|
+
const id = inScope(sourceRoute, source, scopePath) ? idForUrl(sourceRoute, scopePath) : null;
|
|
6525
|
+
const locale = projection.canonicalLocale(target2.page);
|
|
6526
|
+
let navigationId = id && (locale ? id.split("/").filter((segment) => segment.toLowerCase() !== locale.toLowerCase()).join("/") || "introduction" : id);
|
|
6527
|
+
const legacyPrefix = locale && `${locale.toLowerCase()}-`;
|
|
6528
|
+
if (navigationId && legacyPrefix && projection.navigationId(target2.page) !== target2.page.navigationId && navigationId.toLowerCase().startsWith(legacyPrefix)) navigationId = navigationId.slice(legacyPrefix.length);
|
|
6529
|
+
const page = navigationId ? {
|
|
6530
|
+
...target2.page,
|
|
6531
|
+
id: locale ? `${locale}/${navigationId}` : navigationId,
|
|
6532
|
+
navigationId,
|
|
6533
|
+
...locale ? { locale } : {},
|
|
6534
|
+
navTitle: node.label,
|
|
6535
|
+
source: entry.url,
|
|
6536
|
+
noindex: true
|
|
6537
|
+
} : void 0;
|
|
6538
|
+
if (!page || existing || occupiedPageIds.has(projection.pageId(page))) {
|
|
6539
|
+
navigationIssues.push({ code: "unsupported-component", source: target2.url, message: `This page has multiple source navigation labels (${primary.node.label}, ${node.label}); their source routes cannot retain distinct sidebar titles safely.` });
|
|
6540
|
+
continue;
|
|
6541
|
+
}
|
|
6542
|
+
occupiedPageIds.add(projection.pageId(page));
|
|
6543
|
+
navigationAliases.set(entry.url, { page, target: target2 });
|
|
6544
|
+
occurrencePages.set(node, page);
|
|
6545
|
+
navigationRedirects.push({ source: projection.route(page), destination: projection.route(target2.page), permanent: true });
|
|
6546
|
+
}
|
|
6547
|
+
}
|
|
6316
6548
|
const pages = checkpoint.records.flatMap((record) => record.page ? [{ ...record.page, id: projection.pageId(record.page), navigationId: projection.navigationId(record.page), ...projection.canonicalLocale(record.page) ? { locale: projection.canonicalLocale(record.page) } : {}, ...navigationLabels.has(record.url) ? { navTitle: navigationLabels.get(record.url) } : {}, body: rewriteMarkdownDestinations(record.page.body, (value) => {
|
|
6317
6549
|
let url;
|
|
6318
6550
|
try {
|
|
@@ -6333,6 +6565,10 @@ ${difference}`;
|
|
|
6333
6565
|
const hasBrokenSourceAnchor = Boolean(url.hash && destination?.outcome === "imported" && destination.evidence && !destination.evidence.anchors.includes(anchor));
|
|
6334
6566
|
return `${route}${hasBrokenSourceAnchor ? "" : effectiveHash}`;
|
|
6335
6567
|
}) }] : []);
|
|
6568
|
+
const projectedPages = new Map(pages.map((page) => [page.id, page]));
|
|
6569
|
+
for (const { page, target: target2 } of navigationAliases.values()) {
|
|
6570
|
+
pages.push({ ...page, id: projection.pageId(page), body: projectedPages.get(projection.pageId(target2.page)).body });
|
|
6571
|
+
}
|
|
6336
6572
|
const validation = validateUrlMigration(checkpoint, Boolean(options.signal?.aborted));
|
|
6337
6573
|
validation.issues.push(...navigationIssues);
|
|
6338
6574
|
if (navigationIssues.length && validation.status === "passed") validation.status = "partial";
|
|
@@ -6353,12 +6589,12 @@ ${difference}`;
|
|
|
6353
6589
|
platform: options.platform ?? "generic",
|
|
6354
6590
|
pages,
|
|
6355
6591
|
assets: [...assets.values()],
|
|
6356
|
-
docsConfig: navigationConfig(checkpoint, records) ?? buildNavigationFromPages(pages),
|
|
6592
|
+
docsConfig: navigationConfig(checkpoint, records, occurrencePages) ?? buildNavigationFromPages(pages),
|
|
6357
6593
|
warnings: [...validation.issues, ...validation.warnings ?? []].map((issue) => ({ code: issue.code === "missing-page" ? "missing-page" : "unsupported-config", message: issue.message, source: issue.source })),
|
|
6358
6594
|
urlMigrationValidation: validation,
|
|
6359
6595
|
stats: { discovered: records.size, imported: pages.length, skipped: records.size - pages.length }
|
|
6360
6596
|
};
|
|
6361
|
-
if (projection.redirects.length) bundle.docsConfig.redirects = projection.redirects;
|
|
6597
|
+
if (projection.redirects.length || navigationRedirects.length) bundle.docsConfig.redirects = [...projection.redirects, ...navigationRedirects];
|
|
6362
6598
|
if (projection.locales.length) {
|
|
6363
6599
|
const locales = [.../* @__PURE__ */ new Set([projection.defaultLocale, ...projection.locales])];
|
|
6364
6600
|
bundle.docsConfig.i18n = { ...bundle.docsConfig.i18n, defaultLocale: projection.defaultLocale, locales: locales.map((code) => ({ code, label: code === "en" ? "English" : code })) };
|
|
@@ -6376,9 +6612,11 @@ function rewriteMarkdownDestinations(body, rewrite) {
|
|
|
6376
6612
|
const original = body.slice(start, end);
|
|
6377
6613
|
const replacement = rewrite(node.url);
|
|
6378
6614
|
if (replacement === node.url) return null;
|
|
6379
|
-
const
|
|
6380
|
-
|
|
6381
|
-
|
|
6615
|
+
const destinations = postprocess(parse2().document().write(preprocess()(original, void 0, true))).filter(([event, token]) => event === "enter" && ["resourceDestinationString", "definitionDestinationString", "autolinkProtocol", "autolinkEmail"].includes(token.type));
|
|
6616
|
+
const destination = destinations.at(-1)?.[1];
|
|
6617
|
+
if (!destination) return null;
|
|
6618
|
+
const escaped = replacement.replace(/[\\&()<>]/g, "\\$&").replace(/[\t\n\r ]/g, (character) => encodeURIComponent(character));
|
|
6619
|
+
return { start: start + destination.start.offset, end: start + destination.end.offset, replacement: escaped };
|
|
6382
6620
|
}).filter((edit) => edit !== null).sort((a, b) => b.start - a.start);
|
|
6383
6621
|
for (const node of markdownNodes(body)) for (const attribute of node.attributes ?? []) {
|
|
6384
6622
|
if (!attribute.name || !["src", "poster", "href", "srcSet", "srcset", "img", "primaryHref", "secondaryHref"].includes(attribute.name) || !attribute.position) continue;
|
|
@@ -6410,16 +6648,16 @@ function rewriteMarkdownDestinations(body, rewrite) {
|
|
|
6410
6648
|
}
|
|
6411
6649
|
|
|
6412
6650
|
// src/components.ts
|
|
6413
|
-
import { createHash as
|
|
6651
|
+
import { createHash as createHash6 } from "crypto";
|
|
6414
6652
|
import { existsSync as existsSync2, lstatSync as lstatSync2, readFileSync as readFileSync2 } from "fs";
|
|
6415
6653
|
import { basename, dirname as dirname2, extname as extname3, posix as posix2, relative as relative3, resolve as resolve3 } from "path";
|
|
6416
6654
|
import postcss from "postcss";
|
|
6417
6655
|
import selectorParser from "postcss-selector-parser";
|
|
6418
6656
|
import remarkMdx5 from "remark-mdx";
|
|
6419
|
-
import
|
|
6657
|
+
import remarkParse6 from "remark-parse";
|
|
6420
6658
|
import ts2 from "typescript";
|
|
6421
|
-
import { unified as
|
|
6422
|
-
var parser3 =
|
|
6659
|
+
import { unified as unified6 } from "unified";
|
|
6660
|
+
var parser3 = unified6().use(remarkParse6).use(remarkMdx5);
|
|
6423
6661
|
var DOCUSAURUS_THEME_SHIMS = {
|
|
6424
6662
|
"@theme/CodeBlock": {
|
|
6425
6663
|
filename: "docusaurus-code-block.tsx",
|
|
@@ -6459,7 +6697,7 @@ function applyReplacements(source, replacements) {
|
|
|
6459
6697
|
);
|
|
6460
6698
|
}
|
|
6461
6699
|
function hash2(value) {
|
|
6462
|
-
return
|
|
6700
|
+
return createHash6("sha256").update(value).digest("hex").slice(0, 12);
|
|
6463
6701
|
}
|
|
6464
6702
|
function sourceFile(source, filename) {
|
|
6465
6703
|
return ts2.createSourceFile(filename, source, ts2.ScriptTarget.Latest, true, scriptKindFor(filename));
|
|
@@ -6536,6 +6774,32 @@ function renderPage(bundle, page) {
|
|
|
6536
6774
|
function isIntegrationsObject(value) {
|
|
6537
6775
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
6538
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
|
+
}
|
|
6539
6803
|
function mergeMigrationConfig(existing, incoming) {
|
|
6540
6804
|
const tabs = existing.tabs.filter((tab) => tab.tab.toLowerCase() !== "changelog");
|
|
6541
6805
|
const names = new Set(tabs.map((tab) => tab.tab.toLowerCase()));
|
|
@@ -6603,6 +6867,10 @@ function mergeMigrationConfig(existing, incoming) {
|
|
|
6603
6867
|
...incoming,
|
|
6604
6868
|
...existing,
|
|
6605
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 } } : {},
|
|
6606
6874
|
// Collection presentation belongs to the imported information
|
|
6607
6875
|
// architecture; starter defaults must not coerce source dropdowns to tabs.
|
|
6608
6876
|
navigation: incoming.navigation ?? existing.navigation,
|