@thallylabs/migrate 0.2.39 → 0.2.40
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 +44 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2323 -641
- package/dist/index.js.map +1 -1
- package/dist/svg-policy.js +6 -0
- package/dist/svg-policy.js.map +1 -1
- package/dist/url-migration.d.ts +2 -2
- package/dist/url-migration.js +1785 -107
- package/dist/url-migration.js.map +1 -1
- package/dist/{url-run-BOZvcGs1.d.ts → url-run-DFnoqEi-.d.ts} +14 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/repository.ts
|
|
2
2
|
import { compileSync as compileSync2 } from "@mdx-js/mdx";
|
|
3
|
-
import { createHash as
|
|
3
|
+
import { createHash as createHash4 } from "crypto";
|
|
4
4
|
import { spawn } from "child_process";
|
|
5
5
|
import {
|
|
6
6
|
closeSync,
|
|
@@ -4362,14 +4362,14 @@ function addMintlifyDirectoryRedirects(config, pages) {
|
|
|
4362
4362
|
for (const page of pagesByNavigationId.get(navigationId) ?? []) {
|
|
4363
4363
|
const segments = page.id.split("/");
|
|
4364
4364
|
for (let length = 1; length < segments.length; length++) {
|
|
4365
|
-
const
|
|
4366
|
-
if (!firstDescendantByDirectory.has(
|
|
4365
|
+
const directory2 = segments.slice(0, length).join("/");
|
|
4366
|
+
if (!firstDescendantByDirectory.has(directory2)) firstDescendantByDirectory.set(directory2, page);
|
|
4367
4367
|
}
|
|
4368
4368
|
}
|
|
4369
4369
|
}
|
|
4370
|
-
for (const [
|
|
4371
|
-
if (pageIds.has(
|
|
4372
|
-
const source = `/${
|
|
4370
|
+
for (const [directory2, landing] of firstDescendantByDirectory) {
|
|
4371
|
+
if (pageIds.has(directory2.toLowerCase())) continue;
|
|
4372
|
+
const source = `/${directory2}`;
|
|
4373
4373
|
if (hasAuthoredRedirect(source)) continue;
|
|
4374
4374
|
redirects.push({ source, destination: `/${landing.id}`, permanent: false });
|
|
4375
4375
|
redirectSources.add(source.toLowerCase());
|
|
@@ -4607,10 +4607,10 @@ function mintlifyNavigationApiReferences(config) {
|
|
|
4607
4607
|
function collect(node, tabLabel, gated, otherLanguage, hidden, sibling) {
|
|
4608
4608
|
for (const kind of ["openapi", "asyncapi"]) {
|
|
4609
4609
|
const value = specSource(node[kind]);
|
|
4610
|
-
const
|
|
4610
|
+
const directory2 = objectValue2(node[kind])?.directory;
|
|
4611
4611
|
if (value) {
|
|
4612
4612
|
const listed = listedOperations(node);
|
|
4613
|
-
const operations = typeof
|
|
4613
|
+
const operations = typeof directory2 === "string" && directory2.trim() ? listed : [];
|
|
4614
4614
|
const groups = gated || otherLanguage || hidden ? [] : operationGroups(node);
|
|
4615
4615
|
const tooDeepOnly = groups.length === 0 && listed.length > 0 && !gated && !hidden && groupOperationKeys(operationGroups(node, SWEEP_DEPTH_LIMIT)).length === listed.length;
|
|
4616
4616
|
const operationsWithheld = !otherLanguage && (hidden || groups.length === 0 && listed.length > 0 && !tooDeepOnly);
|
|
@@ -4619,7 +4619,7 @@ function mintlifyNavigationApiReferences(config) {
|
|
|
4619
4619
|
kind,
|
|
4620
4620
|
tabLabel,
|
|
4621
4621
|
...sibling,
|
|
4622
|
-
...typeof
|
|
4622
|
+
...typeof directory2 === "string" && directory2.trim() ? { directory: directory2.trim() } : {},
|
|
4623
4623
|
...operations.length > 0 ? { operations } : {},
|
|
4624
4624
|
...groups.length > 0 ? { groups } : {},
|
|
4625
4625
|
...operationsWithheld ? { operationsWithheld: true } : {},
|
|
@@ -5840,16 +5840,16 @@ function registerFolder(object3, parentSegments, context) {
|
|
|
5840
5840
|
const label = typeof object3.title === "string" && object3.title.trim() ? object3.title.trim() : titleCase2(basename2(folder));
|
|
5841
5841
|
const segment = typeof object3.slug === "string" || object3["skip-slug"] === true ? segmentFor(object3, label, context) : fernBasicSlug(basename2(folder));
|
|
5842
5842
|
const segments = segment ? [...parentSegments, segment] : parentSegments;
|
|
5843
|
-
const visit = (
|
|
5843
|
+
const visit = (directory2, routeSegments, depth) => {
|
|
5844
5844
|
if (depth > 12 || context.descriptors.length >= 5e3) {
|
|
5845
5845
|
context.navigationWalk.incomplete = true;
|
|
5846
5846
|
warnOnce2(context, "fern-folder-limit", "Fern folder navigation exceeded its depth or page budget; remaining access rules could not be classified.");
|
|
5847
5847
|
return [];
|
|
5848
5848
|
}
|
|
5849
5849
|
const pages2 = [];
|
|
5850
|
-
const entries = readdirSync(
|
|
5850
|
+
const entries = readdirSync(directory2, { withFileTypes: true }).filter((entry) => !entry.name.startsWith(".") && !entry.isSymbolicLink()).sort((left, right) => Number(left.name !== "index.mdx" && left.name !== "index.md") - Number(right.name !== "index.mdx" && right.name !== "index.md") || left.name.localeCompare(right.name));
|
|
5851
5851
|
for (const entry of entries) {
|
|
5852
|
-
const path = resolveWithin(
|
|
5852
|
+
const path = resolveWithin(directory2, entry.name);
|
|
5853
5853
|
if (entry.isDirectory()) {
|
|
5854
5854
|
const nested = visit(path, [...routeSegments, fernBasicSlug(entry.name)], depth + 1);
|
|
5855
5855
|
if (nested.length) pages2.push({ group: titleCase2(entry.name), pages: nested });
|
|
@@ -6839,9 +6839,9 @@ function readDocusaurusRedirects(repositoryRoot, warnings) {
|
|
|
6839
6839
|
const literal = namedExportObjectLiteralText(moduleSource, identifier);
|
|
6840
6840
|
return literal ? redirectEntriesFromObjectLiteralText(literal, warnings) : [];
|
|
6841
6841
|
}
|
|
6842
|
-
function readCategoryMetadata(contentRoot,
|
|
6842
|
+
function readCategoryMetadata(contentRoot, directory2) {
|
|
6843
6843
|
for (const filename of CATEGORY_FILENAMES) {
|
|
6844
|
-
const path = resolveWithin(contentRoot, posix3.join(
|
|
6844
|
+
const path = resolveWithin(contentRoot, posix3.join(directory2, filename));
|
|
6845
6845
|
try {
|
|
6846
6846
|
withinRealRoot(path, contentRoot);
|
|
6847
6847
|
} catch {
|
|
@@ -7128,9 +7128,9 @@ function autogeneratedItems(dirName, context) {
|
|
|
7128
7128
|
item: descriptor.navigationId
|
|
7129
7129
|
}));
|
|
7130
7130
|
const groups = [...childDirectories].map((segment) => {
|
|
7131
|
-
const
|
|
7132
|
-
const metadata = readCategoryMetadata(context.contentRoot,
|
|
7133
|
-
const pages2 = autogeneratedItems(
|
|
7131
|
+
const directory2 = normalizedDir ? posix3.join(normalizedDir, segment) : segment;
|
|
7132
|
+
const metadata = readCategoryMetadata(context.contentRoot, directory2);
|
|
7133
|
+
const pages2 = autogeneratedItems(directory2, context);
|
|
7134
7134
|
if (pages2.length === 1 && typeof pages2[0] === "string" && !metadata.label && metadata.position === void 0 && !metadata.link) {
|
|
7135
7135
|
const onlyPage = context.descriptors.find((descriptor) => descriptor.navigationId === pages2[0]);
|
|
7136
7136
|
if (onlyPage && /(?:^|\/)(?:index|readme)\.mdx?$/i.test(onlyPage.sourcePath)) {
|
|
@@ -7141,7 +7141,7 @@ function autogeneratedItems(dirName, context) {
|
|
|
7141
7141
|
};
|
|
7142
7142
|
}
|
|
7143
7143
|
}
|
|
7144
|
-
const landing = generatedIndexPage(metadata.label ?? titleCase3(segment), metadata.link, context,
|
|
7144
|
+
const landing = generatedIndexPage(metadata.label ?? titleCase3(segment), metadata.link, context, directory2);
|
|
7145
7145
|
if (landing && !pages2.includes(landing)) pages2.unshift(landing);
|
|
7146
7146
|
return {
|
|
7147
7147
|
position: metadata.position ?? Number.MAX_SAFE_INTEGER,
|
|
@@ -7249,11 +7249,11 @@ function readDocusaurusPresentation(repositoryRoot) {
|
|
|
7249
7249
|
if (/\btheme\(/.test(css) || /\.s[ac]ss$/.test(relative7)) {
|
|
7250
7250
|
const candidateDirectory = resolveWithin(repositoryRoot, "build/assets/css");
|
|
7251
7251
|
if (existsSync4(candidateDirectory)) {
|
|
7252
|
-
const
|
|
7253
|
-
const compiled = readdirSync2(
|
|
7252
|
+
const directory2 = withinRealRoot(candidateDirectory, repositoryRoot);
|
|
7253
|
+
const compiled = readdirSync2(directory2).filter((name) => /^styles[.\w-]*\.css$/.test(name)).sort().slice(0, 8);
|
|
7254
7254
|
let totalBytes = 0;
|
|
7255
7255
|
css = compiled.map((name) => {
|
|
7256
|
-
const path2 = withinRealRoot(resolveWithin(
|
|
7256
|
+
const path2 = withinRealRoot(resolveWithin(directory2, name), repositoryRoot);
|
|
7257
7257
|
const stat = lstatSync4(path2);
|
|
7258
7258
|
if (!stat.isFile()) return "";
|
|
7259
7259
|
totalBytes += stat.size;
|
|
@@ -7552,11 +7552,11 @@ import { lstatSync as lstatSync5, readdirSync as readdirSync3, readFileSync as r
|
|
|
7552
7552
|
import { isAbsolute as isAbsolute2, join, relative as relative5, resolve as resolve3, sep as sep2 } from "path";
|
|
7553
7553
|
|
|
7554
7554
|
// src/url.ts
|
|
7555
|
-
import { load as
|
|
7556
|
-
import
|
|
7557
|
-
import
|
|
7555
|
+
import { load as load4 } from "cheerio";
|
|
7556
|
+
import remarkMdx4 from "remark-mdx";
|
|
7557
|
+
import remarkParse4 from "remark-parse";
|
|
7558
7558
|
import TurndownService from "turndown";
|
|
7559
|
-
import { unified as
|
|
7559
|
+
import { unified as unified4 } from "unified";
|
|
7560
7560
|
import { parse as parseYaml5, stringify as stringifyYaml2 } from "yaml";
|
|
7561
7561
|
|
|
7562
7562
|
// src/analytics.ts
|
|
@@ -7850,139 +7850,1339 @@ function projectMigrationMedia(html, base) {
|
|
|
7850
7850
|
}
|
|
7851
7851
|
}
|
|
7852
7852
|
|
|
7853
|
-
// src/
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7853
|
+
// src/url-static-content.ts
|
|
7854
|
+
import { createHash as createHash2 } from "crypto";
|
|
7855
|
+
import { load as load3 } from "cheerio";
|
|
7856
|
+
|
|
7857
|
+
// src/svg-policy.ts
|
|
7858
|
+
import { Parser } from "htmlparser2";
|
|
7859
|
+
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
7860
|
+
var XLINK_NAMESPACE = "http://www.w3.org/1999/xlink";
|
|
7861
|
+
var ALLOWED_ELEMENTS = /* @__PURE__ */ new Set([
|
|
7862
|
+
"svg",
|
|
7863
|
+
"g",
|
|
7864
|
+
"defs",
|
|
7865
|
+
"symbol",
|
|
7866
|
+
"use",
|
|
7867
|
+
"title",
|
|
7868
|
+
"desc",
|
|
7869
|
+
"path",
|
|
7870
|
+
"rect",
|
|
7871
|
+
"circle",
|
|
7872
|
+
"ellipse",
|
|
7873
|
+
"line",
|
|
7874
|
+
"polyline",
|
|
7875
|
+
"polygon",
|
|
7876
|
+
"text",
|
|
7877
|
+
"tspan",
|
|
7878
|
+
"textpath",
|
|
7879
|
+
"lineargradient",
|
|
7880
|
+
"radialgradient",
|
|
7881
|
+
"stop",
|
|
7882
|
+
"clippath",
|
|
7883
|
+
"mask",
|
|
7884
|
+
"pattern",
|
|
7885
|
+
"marker",
|
|
7886
|
+
"filter",
|
|
7887
|
+
"feblend",
|
|
7888
|
+
"fecolormatrix",
|
|
7889
|
+
"fecomponenttransfer",
|
|
7890
|
+
"fecomposite",
|
|
7891
|
+
"feconvolvematrix",
|
|
7892
|
+
"fediffuselighting",
|
|
7893
|
+
"fedisplacementmap",
|
|
7894
|
+
"fedistantlight",
|
|
7895
|
+
"fedropshadow",
|
|
7896
|
+
"feflood",
|
|
7897
|
+
"fefunca",
|
|
7898
|
+
"fefuncb",
|
|
7899
|
+
"fefuncg",
|
|
7900
|
+
"fefuncr",
|
|
7901
|
+
"fegaussianblur",
|
|
7902
|
+
"femerge",
|
|
7903
|
+
"femergenode",
|
|
7904
|
+
"femorphology",
|
|
7905
|
+
"feoffset",
|
|
7906
|
+
"fepointlight",
|
|
7907
|
+
"fespecularlighting",
|
|
7908
|
+
"fespotlight",
|
|
7909
|
+
"fetile",
|
|
7910
|
+
"feturbulence"
|
|
7911
|
+
]);
|
|
7912
|
+
var ALLOWED_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
7913
|
+
"xmlns",
|
|
7914
|
+
"xmlns:xlink",
|
|
7915
|
+
"xml:space",
|
|
7916
|
+
"version",
|
|
7917
|
+
"baseprofile",
|
|
7918
|
+
"id",
|
|
7919
|
+
"class",
|
|
7920
|
+
"viewbox",
|
|
7921
|
+
"preserveaspectratio",
|
|
7922
|
+
"width",
|
|
7923
|
+
"height",
|
|
7924
|
+
"x",
|
|
7925
|
+
"y",
|
|
7926
|
+
"x1",
|
|
7927
|
+
"y1",
|
|
7928
|
+
"x2",
|
|
7929
|
+
"y2",
|
|
7930
|
+
"cx",
|
|
7931
|
+
"cy",
|
|
7932
|
+
"r",
|
|
7933
|
+
"rx",
|
|
7934
|
+
"ry",
|
|
7935
|
+
"d",
|
|
7936
|
+
"points",
|
|
7937
|
+
"pathlength",
|
|
7938
|
+
"transform",
|
|
7939
|
+
"transform-origin",
|
|
7940
|
+
"fill",
|
|
7941
|
+
"fill-opacity",
|
|
7942
|
+
"fill-rule",
|
|
7943
|
+
"stroke",
|
|
7944
|
+
"stroke-width",
|
|
7945
|
+
// Some SVG exporters persist React spellings. These remain fixed static
|
|
7946
|
+
// drawing attributes; accepting them never grants arbitrary JSX execution.
|
|
7947
|
+
"fillrule",
|
|
7948
|
+
"cliprule",
|
|
7949
|
+
"stroke-opacity",
|
|
7950
|
+
"stroke-linecap",
|
|
7951
|
+
"stroke-linejoin",
|
|
7952
|
+
"stroke-miterlimit",
|
|
7953
|
+
"stroke-dasharray",
|
|
7954
|
+
"stroke-dashoffset",
|
|
7955
|
+
"opacity",
|
|
7956
|
+
"color",
|
|
7957
|
+
"display",
|
|
7958
|
+
"visibility",
|
|
7959
|
+
"overflow",
|
|
7960
|
+
"clip-path",
|
|
7961
|
+
"clip-rule",
|
|
7962
|
+
"clippathunits",
|
|
7963
|
+
"mask",
|
|
7964
|
+
"maskunits",
|
|
7965
|
+
"maskcontentunits",
|
|
7966
|
+
"filter",
|
|
7967
|
+
"filterunits",
|
|
7968
|
+
"primitiveunits",
|
|
7969
|
+
"marker-start",
|
|
7970
|
+
"marker-mid",
|
|
7971
|
+
"marker-end",
|
|
7972
|
+
"markerwidth",
|
|
7973
|
+
"markerheight",
|
|
7974
|
+
"markerunits",
|
|
7975
|
+
"refx",
|
|
7976
|
+
"refy",
|
|
7977
|
+
"orient",
|
|
7978
|
+
"patternunits",
|
|
7979
|
+
"patterncontentunits",
|
|
7980
|
+
"patterntransform",
|
|
7981
|
+
"gradientunits",
|
|
7982
|
+
"gradienttransform",
|
|
7983
|
+
"spreadmethod",
|
|
7984
|
+
"fx",
|
|
7985
|
+
"fy",
|
|
7986
|
+
"fr",
|
|
7987
|
+
"offset",
|
|
7988
|
+
"stop-color",
|
|
7989
|
+
"stop-opacity",
|
|
7990
|
+
"font-family",
|
|
7991
|
+
"font-size",
|
|
7992
|
+
"font-weight",
|
|
7993
|
+
"font-style",
|
|
7994
|
+
"font-variant",
|
|
7995
|
+
"letter-spacing",
|
|
7996
|
+
"word-spacing",
|
|
7997
|
+
"text-anchor",
|
|
7998
|
+
"dominant-baseline",
|
|
7999
|
+
"alignment-baseline",
|
|
8000
|
+
"baseline-shift",
|
|
8001
|
+
"text-decoration",
|
|
8002
|
+
"dx",
|
|
8003
|
+
"dy",
|
|
8004
|
+
"rotate",
|
|
8005
|
+
"textlength",
|
|
8006
|
+
"lengthadjust",
|
|
8007
|
+
"startoffset",
|
|
8008
|
+
"writing-mode",
|
|
8009
|
+
"direction",
|
|
8010
|
+
"unicode-bidi",
|
|
8011
|
+
"shape-rendering",
|
|
8012
|
+
"text-rendering",
|
|
8013
|
+
"image-rendering",
|
|
8014
|
+
"color-interpolation",
|
|
8015
|
+
"color-interpolation-filters",
|
|
8016
|
+
"vector-effect",
|
|
8017
|
+
"paint-order",
|
|
8018
|
+
"mix-blend-mode",
|
|
8019
|
+
"isolation",
|
|
8020
|
+
"in",
|
|
8021
|
+
"in2",
|
|
8022
|
+
"result",
|
|
8023
|
+
"stddeviation",
|
|
8024
|
+
"mode",
|
|
8025
|
+
"type",
|
|
8026
|
+
"values",
|
|
8027
|
+
"tablevalues",
|
|
8028
|
+
"slope",
|
|
8029
|
+
"intercept",
|
|
8030
|
+
"amplitude",
|
|
8031
|
+
"exponent",
|
|
8032
|
+
"operator",
|
|
8033
|
+
"k1",
|
|
8034
|
+
"k2",
|
|
8035
|
+
"k3",
|
|
8036
|
+
"k4",
|
|
8037
|
+
"radius",
|
|
8038
|
+
"scale",
|
|
8039
|
+
"xchannelselector",
|
|
8040
|
+
"ychannelselector",
|
|
8041
|
+
"basefrequency",
|
|
8042
|
+
"numoctaves",
|
|
8043
|
+
"seed",
|
|
8044
|
+
"stitchtiles",
|
|
8045
|
+
"flood-color",
|
|
8046
|
+
"flood-opacity",
|
|
8047
|
+
"lighting-color",
|
|
8048
|
+
"surfacescale",
|
|
8049
|
+
"diffuseconstant",
|
|
8050
|
+
"specularconstant",
|
|
8051
|
+
"specularexponent",
|
|
8052
|
+
"kernelmatrix",
|
|
8053
|
+
"kernelunitlength",
|
|
8054
|
+
"order",
|
|
8055
|
+
"divisor",
|
|
8056
|
+
"bias",
|
|
8057
|
+
"targetx",
|
|
8058
|
+
"targety",
|
|
8059
|
+
"edgemode",
|
|
8060
|
+
"preservealpha",
|
|
8061
|
+
"azimuth",
|
|
8062
|
+
"elevation",
|
|
8063
|
+
"z",
|
|
8064
|
+
"pointsatx",
|
|
8065
|
+
"pointsaty",
|
|
8066
|
+
"pointsatz",
|
|
8067
|
+
"limitingconeangle",
|
|
8068
|
+
"aria-hidden",
|
|
8069
|
+
"aria-label",
|
|
8070
|
+
"aria-labelledby",
|
|
8071
|
+
"aria-describedby",
|
|
8072
|
+
"role",
|
|
8073
|
+
"focusable",
|
|
8074
|
+
// Validated below: only in-document fragment references.
|
|
8075
|
+
"href",
|
|
8076
|
+
"xlink:href"
|
|
8077
|
+
]);
|
|
8078
|
+
function hasExternalReference(value) {
|
|
8079
|
+
if (value.includes("\\")) return true;
|
|
8080
|
+
const compact = value.replace(/[\u0000- ]/gu, "").toLowerCase();
|
|
8081
|
+
if (/(?:java|vb)script:|data:|expression\(|@import|<|>/u.test(compact)) {
|
|
8082
|
+
return true;
|
|
7867
8083
|
}
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
return route === null ? null : resolveDotSegments(route);
|
|
8084
|
+
for (const match of compact.matchAll(/url\(([^)]*)\)/gu)) {
|
|
8085
|
+
if (!/^["']?#[a-z0-9_.:-]+["']?$/u.test(match[1])) return true;
|
|
8086
|
+
}
|
|
8087
|
+
return compact.replace(/url\(([^)]*)\)/gu, "").includes("url(");
|
|
7873
8088
|
}
|
|
7874
|
-
function
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
8089
|
+
function utf8SvgText(content) {
|
|
8090
|
+
const hasUtf8Bom = content[0] === 239 && content[1] === 187 && content[2] === 191;
|
|
8091
|
+
const body = hasUtf8Bom ? content.subarray(3) : content;
|
|
8092
|
+
if (body[0] === 254 && body[1] === 255 || body[0] === 255 && body[1] === 254 || body[0] === 0 && body[1] === 0 || body.includes(0)) {
|
|
8093
|
+
return null;
|
|
8094
|
+
}
|
|
8095
|
+
const text3 = body.toString("utf8");
|
|
8096
|
+
if (text3.includes("\uFFFD")) return null;
|
|
8097
|
+
const declaration = /^<\?xml\b[^>]*\?>/iu.exec(text3);
|
|
8098
|
+
if (declaration) {
|
|
8099
|
+
const encoding = /\bencoding\s*=\s*["']([^"']*)["']/iu.exec(declaration[0]);
|
|
8100
|
+
if (encoding && !/^utf-?8$/iu.test(encoding[1].trim())) return null;
|
|
8101
|
+
} else if (/<\?xml\b/iu.test(text3)) {
|
|
8102
|
+
return null;
|
|
8103
|
+
}
|
|
8104
|
+
return text3;
|
|
7879
8105
|
}
|
|
7880
|
-
function
|
|
7881
|
-
|
|
8106
|
+
function isPassiveSvg(content) {
|
|
8107
|
+
const text3 = utf8SvgText(Buffer.from(content.buffer, content.byteOffset, content.byteLength));
|
|
8108
|
+
if (text3 === null) return false;
|
|
8109
|
+
let isPassive = true;
|
|
8110
|
+
let depth = 0;
|
|
8111
|
+
let sawRoot = false;
|
|
8112
|
+
const openStarts = [];
|
|
8113
|
+
const fail = () => {
|
|
8114
|
+
isPassive = false;
|
|
8115
|
+
};
|
|
8116
|
+
const parser4 = new Parser(
|
|
8117
|
+
{
|
|
8118
|
+
onopentag(name, attributes) {
|
|
8119
|
+
const element = name.toLowerCase();
|
|
8120
|
+
if (depth === 0) {
|
|
8121
|
+
if (sawRoot || element !== "svg") fail();
|
|
8122
|
+
sawRoot = true;
|
|
8123
|
+
}
|
|
8124
|
+
depth += 1;
|
|
8125
|
+
openStarts.push(parser4.startIndex);
|
|
8126
|
+
if (element.includes(":") || !ALLOWED_ELEMENTS.has(element)) fail();
|
|
8127
|
+
for (const [rawName, value] of Object.entries(attributes)) {
|
|
8128
|
+
const attribute = rawName.toLowerCase();
|
|
8129
|
+
if (!ALLOWED_ATTRIBUTES.has(attribute)) {
|
|
8130
|
+
fail();
|
|
8131
|
+
continue;
|
|
8132
|
+
}
|
|
8133
|
+
if (attribute === "xmlns" && value !== SVG_NAMESPACE) fail();
|
|
8134
|
+
if (attribute === "xmlns:xlink" && value !== XLINK_NAMESPACE) fail();
|
|
8135
|
+
if ((attribute === "href" || attribute === "xlink:href") && !/^#[A-Za-z0-9_.:-]+$/u.test(value.trim())) {
|
|
8136
|
+
fail();
|
|
8137
|
+
}
|
|
8138
|
+
if (hasExternalReference(value)) fail();
|
|
8139
|
+
}
|
|
8140
|
+
},
|
|
8141
|
+
onclosetag(_name, isImplied) {
|
|
8142
|
+
depth -= 1;
|
|
8143
|
+
const start = openStarts.pop();
|
|
8144
|
+
if (isImplied && start !== parser4.startIndex) fail();
|
|
8145
|
+
},
|
|
8146
|
+
// DOCTYPE (and with it custom entities) or any other declaration other
|
|
8147
|
+
// than the XML prolog.
|
|
8148
|
+
onprocessinginstruction(name) {
|
|
8149
|
+
if (name.toLowerCase() !== "?xml") fail();
|
|
8150
|
+
},
|
|
8151
|
+
oncdatastart: fail,
|
|
8152
|
+
ontext(value) {
|
|
8153
|
+
if (depth === 0 && value.trim()) fail();
|
|
8154
|
+
},
|
|
8155
|
+
onerror: fail
|
|
8156
|
+
},
|
|
8157
|
+
{ xmlMode: true, decodeEntities: true, recognizeSelfClosing: true }
|
|
8158
|
+
);
|
|
8159
|
+
try {
|
|
8160
|
+
parser4.write(text3);
|
|
8161
|
+
parser4.end();
|
|
8162
|
+
} catch {
|
|
8163
|
+
return false;
|
|
8164
|
+
}
|
|
8165
|
+
return isPassive && sawRoot && depth === 0;
|
|
7882
8166
|
}
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
const
|
|
7887
|
-
const
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
8167
|
+
|
|
8168
|
+
// src/url-static-content.ts
|
|
8169
|
+
function projectMigrationSvg(html) {
|
|
8170
|
+
const $ = load3(html, { xmlMode: true }, false);
|
|
8171
|
+
const svg = $.root().children();
|
|
8172
|
+
if (svg.length !== 1 || !svg.is("svg")) return null;
|
|
8173
|
+
if (svg.attr("xmlns") === void 0) svg.attr("xmlns", "http://www.w3.org/2000/svg");
|
|
8174
|
+
const content = Buffer.from($.xml(svg));
|
|
8175
|
+
if (!isPassiveSvg(content)) return null;
|
|
8176
|
+
const sha256 = createHash2("sha256").update(content).digest("hex");
|
|
8177
|
+
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);
|
|
8178
|
+
const alternative = svg.attr("aria-label")?.trim() || labelled.join(" ") || svg.children("title").text().trim() || svg.children("desc").text().trim() || svg.find("text").text().trim();
|
|
8179
|
+
return { asset: { path: `migration-assets/${sha256}.svg`, content }, alternative };
|
|
8180
|
+
}
|
|
8181
|
+
function projectProtectedEmails($, root) {
|
|
8182
|
+
root.find("[data-cfemail]").each((_index, node) => {
|
|
8183
|
+
const element = $(node);
|
|
8184
|
+
const anchor = element.is("a") ? element : element.closest("a");
|
|
8185
|
+
const href = anchor.attr("href") ?? "";
|
|
8186
|
+
if (!anchor.length || !/^\/cdn-cgi\/l\/email-protection(?:#[a-f\d]+)?$/i.test(href)) return;
|
|
8187
|
+
const encoded = element.attr("data-cfemail") ?? "";
|
|
8188
|
+
if (!/^(?:[a-f\d]{2}){4,1024}$/i.test(encoded)) return;
|
|
8189
|
+
const bytes = Buffer.from(encoded, "hex");
|
|
8190
|
+
const payload = Uint8Array.from(bytes.subarray(1), (byte) => byte ^ bytes[0]);
|
|
8191
|
+
let email;
|
|
8192
|
+
try {
|
|
8193
|
+
email = new TextDecoder("utf-8", { fatal: true }).decode(payload);
|
|
8194
|
+
} catch {
|
|
8195
|
+
return;
|
|
7892
8196
|
}
|
|
7893
|
-
if (
|
|
7894
|
-
|
|
7895
|
-
|
|
8197
|
+
if (!/^[^@\s<>?#[\]\u0000-\u001f\u007f]+@[^@\s<>?#[\]\u0000-\u001f\u007f]+\.[^@\s<>?#[\]\u0000-\u001f\u007f]+$/u.test(email)) return;
|
|
8198
|
+
anchor.attr("href", `mailto:${email}`);
|
|
8199
|
+
if (/^\[email\s+protected\]$/i.test(element.text().trim())) element.text(email);
|
|
8200
|
+
element.removeAttr("data-cfemail");
|
|
7896
8201
|
});
|
|
7897
|
-
|
|
7898
|
-
|
|
7899
|
-
|
|
7900
|
-
|
|
8202
|
+
}
|
|
8203
|
+
function hasCompleteCapturedPanel($, panel) {
|
|
8204
|
+
const busy = '[aria-busy="true"],[role="progressbar"]';
|
|
8205
|
+
if (panel.is(busy) || panel.find(busy).length) return false;
|
|
8206
|
+
const copy = panel.clone();
|
|
8207
|
+
copy.find('script,style,button,[role="tablist"]').remove();
|
|
8208
|
+
return Boolean(copy.text().trim() || copy.find("img[src],svg").length);
|
|
8209
|
+
}
|
|
8210
|
+
function projectCapturedDisclosures($, root) {
|
|
8211
|
+
const ids = /* @__PURE__ */ new Map();
|
|
8212
|
+
root.find("[id]").each((_index, node) => {
|
|
8213
|
+
const id = $(node).attr("id");
|
|
8214
|
+
ids.set(id, ids.has(id) ? ids.get(id).add(node) : $(node));
|
|
8215
|
+
});
|
|
8216
|
+
root.find("button[aria-expanded][aria-controls],summary[aria-expanded][aria-controls]").each((_index, node) => {
|
|
8217
|
+
const control = $(node);
|
|
8218
|
+
if (control.is('[role="tab"],[aria-haspopup],[aria-busy="true"]')) return;
|
|
8219
|
+
const id = control.attr("id"), target2 = control.attr("aria-controls");
|
|
8220
|
+
const panel = target2 ? ids.get(target2) : void 0;
|
|
8221
|
+
const nativeSummary = control.is("summary") && control.parent().is("details");
|
|
8222
|
+
let owner = control.parent();
|
|
8223
|
+
if (owner.is("h1,h2,h3,h4,h5,h6")) owner = owner.parent();
|
|
8224
|
+
const labels2 = panel?.attr("aria-labelledby")?.trim().split(/\s+/);
|
|
8225
|
+
const ownedLabels = labels2?.every((label) => ids.get(label)?.length === 1 && (label === id || nativeSummary && control.find("[id]").toArray().some((element) => $(element).attr("id") === label)));
|
|
8226
|
+
if (!nativeSummary && !id || id && ids.get(id)?.length !== 1 || !panel || panel.length !== 1 || panel.attr("role") !== "region" && !(nativeSummary && panel.is('[data-component-part="expandable-content"]')) || labels2 && !ownedLabels || !panel.parents().toArray().some((parent) => parent === owner[0]) || nativeSummary && panel.parent()[0] !== owner[0] || !hasCompleteCapturedPanel($, panel)) return;
|
|
8227
|
+
if (!nativeSummary) node.name = "span";
|
|
8228
|
+
control.removeAttr("aria-expanded aria-controls role type");
|
|
8229
|
+
panel.removeAttr("hidden aria-hidden");
|
|
8230
|
+
});
|
|
8231
|
+
}
|
|
8232
|
+
function projectCapturedTabs($, root) {
|
|
8233
|
+
root.find("[data-thally-static-tabs],[data-thally-static-tab]").removeAttr("data-thally-static-tabs data-thally-static-tab");
|
|
8234
|
+
const ids = /* @__PURE__ */ new Map();
|
|
8235
|
+
root.find("[id]").each((_index, node) => {
|
|
8236
|
+
const id = $(node).attr("id");
|
|
8237
|
+
ids.set(id, ids.has(id) ? ids.get(id).add(node) : $(node));
|
|
8238
|
+
});
|
|
8239
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
8240
|
+
const groups = root.find('[role="tablist"]').toArray();
|
|
8241
|
+
if (groups.length > 256 || root.find('[role="tab"]').length > 1024) return;
|
|
8242
|
+
for (const groupNode of groups.reverse()) {
|
|
8243
|
+
const group = $(groupNode);
|
|
8244
|
+
const tabs = group.find('[role="tab"]').toArray().filter((node) => $(node).closest('[role="tablist"]')[0] === groupNode);
|
|
8245
|
+
if (!tabs.length || group.is('[aria-busy="true"]')) continue;
|
|
8246
|
+
if (group.text().replace(/\s+/g, "") !== tabs.map((node) => $(node).text()).join("").replace(/\s+/g, "")) continue;
|
|
8247
|
+
let container = group.parent();
|
|
8248
|
+
const explicit = tabs.every((tab) => Boolean($(tab).attr("aria-controls")));
|
|
8249
|
+
const panels = [];
|
|
8250
|
+
if (explicit) {
|
|
8251
|
+
for (const tab of tabs) {
|
|
8252
|
+
const panel = ids.get($(tab).attr("aria-controls"));
|
|
8253
|
+
const tabId = $(tab).attr("id");
|
|
8254
|
+
if (!panel || panel.length !== 1 || !panel.is('[role="tabpanel"]') || panel.find('[role="tablist"]').toArray().includes(groupNode) || tabId && ids.get(tabId)?.length !== 1 || panel.attr("aria-labelledby") !== void 0 && panel.attr("aria-labelledby") !== tabId) break;
|
|
8255
|
+
panels.push(panel);
|
|
8256
|
+
}
|
|
8257
|
+
for (let depth = 0; depth < 16 && container.length && panels.some((panel) => !panel.parents().toArray().some((parent) => parent === container[0])); depth += 1) container = container.parent();
|
|
8258
|
+
if (!container.length || !container.find('[role="tablist"]').toArray().includes(groupNode)) continue;
|
|
8259
|
+
} else {
|
|
8260
|
+
if (tabs.some((tab) => $(tab).attr("aria-controls"))) continue;
|
|
8261
|
+
container = group.closest(".code-group,.tabs-container,.tabs.tab-container");
|
|
8262
|
+
if (!container.length) continue;
|
|
8263
|
+
const owners = container.find('[role="tablist"]').toArray().filter((node) => $(node).closest(".code-group,.tabs-container,.tabs.tab-container")[0] === container[0]);
|
|
8264
|
+
if (owners.length !== 1) continue;
|
|
8265
|
+
panels.push(...container.find('[role="tabpanel"]').toArray().filter((node) => $(node).closest(".code-group,.tabs-container,.tabs.tab-container")[0] === container[0]).map((node) => $(node)));
|
|
8266
|
+
}
|
|
8267
|
+
if (panels.length !== tabs.length || new Set(panels.map((panel) => panel[0])).size !== panels.length || panels.some((panel) => claimed.has(panel[0]) || !hasCompleteCapturedPanel($, panel))) continue;
|
|
8268
|
+
const unowned = container.find('[role="tabpanel"]').toArray().filter((node) => !panels.some((panel) => panel[0] === node || $(node).parents().toArray().some((parent) => parent === panel[0])));
|
|
8269
|
+
if (unowned.length) continue;
|
|
8270
|
+
const residual = container.clone();
|
|
8271
|
+
residual.find('[role="tablist"],[role="tabpanel"]').remove();
|
|
8272
|
+
const hasSurroundingContent = Boolean(residual.text().trim() || residual.find("a[href],pre,img,svg,table,video,audio,iframe,form,input,textarea,select,object,embed,canvas,math").length);
|
|
8273
|
+
if (!hasSurroundingContent) container.attr("data-thally-static-tabs", "");
|
|
8274
|
+
panels.forEach((panel, index) => {
|
|
8275
|
+
claimed.add(panel[0]);
|
|
8276
|
+
const label = $(tabs[index]).text().trim() || `Tab ${index + 1}`;
|
|
8277
|
+
if (hasSurroundingContent) panel.prepend($("<p></p>").append($("<strong></strong>").text(label)));
|
|
8278
|
+
else panel.attr("data-thally-static-tab", label);
|
|
8279
|
+
panel.removeAttr("role hidden aria-hidden aria-labelledby");
|
|
8280
|
+
const id = $(tabs[index]).attr("id");
|
|
8281
|
+
if (id) panel.prepend($("<span></span>").attr("id", id));
|
|
7901
8282
|
});
|
|
8283
|
+
const groupId = group.attr("id");
|
|
8284
|
+
if (groupId) group.replaceWith($("<span></span>").attr("id", groupId));
|
|
8285
|
+
else group.remove();
|
|
7902
8286
|
}
|
|
7903
|
-
if (redirects.length === config.redirects.length) return config;
|
|
7904
|
-
const result = { ...config, redirects };
|
|
7905
|
-
if (redirects.length === 0) delete result.redirects;
|
|
7906
|
-
return result;
|
|
7907
8287
|
}
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
8288
|
+
|
|
8289
|
+
// src/url-flight-content.ts
|
|
8290
|
+
import { createHash as createHash3 } from "crypto";
|
|
8291
|
+
import remarkMdx3 from "remark-mdx";
|
|
8292
|
+
import remarkParse3 from "remark-parse";
|
|
8293
|
+
import remarkGfm2 from "remark-gfm";
|
|
8294
|
+
import { unified as unified3 } from "unified";
|
|
8295
|
+
var parser2 = unified3().use(remarkParse3).use(remarkGfm2).use(remarkMdx3);
|
|
8296
|
+
var MAX_SOURCE_BYTES = 8e6;
|
|
8297
|
+
var sourceTrees = /* @__PURE__ */ new Map();
|
|
8298
|
+
var cachedSourceBytes = 0;
|
|
8299
|
+
var MAX_CACHED_SOURCE_BYTES = 1e6;
|
|
8300
|
+
var UNRESOLVED_FLIGHT_VALUE = /* @__PURE__ */ Symbol("unresolved-flight-value");
|
|
8301
|
+
var expansionBudget = () => ({ visited: 0, bytes: 0, exceeded: false });
|
|
8302
|
+
function chargeExpansion(budget, value) {
|
|
8303
|
+
if (budget.exceeded) return false;
|
|
8304
|
+
budget.bytes += Buffer.byteLength(value);
|
|
8305
|
+
if (budget.bytes > MAX_SOURCE_BYTES) budget.exceeded = true;
|
|
8306
|
+
return !budget.exceeded;
|
|
8307
|
+
}
|
|
8308
|
+
function chargeProjectedText(budget, value) {
|
|
8309
|
+
if (budget.exceeded) return false;
|
|
8310
|
+
let bytes = Buffer.byteLength(value);
|
|
8311
|
+
for (const character of value) bytes += character === "&" ? 4 : character === "<" || character === ">" ? 3 : character === '"' ? 5 : 0;
|
|
8312
|
+
budget.bytes += bytes + 128;
|
|
8313
|
+
if (budget.bytes > MAX_SOURCE_BYTES) budget.exceeded = true;
|
|
8314
|
+
return !budget.exceeded;
|
|
8315
|
+
}
|
|
8316
|
+
var flightDocuments = /* @__PURE__ */ new WeakMap();
|
|
8317
|
+
function renderedRouteSlot(value) {
|
|
8318
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => key !== "children")) return void 0;
|
|
8319
|
+
const child = value.children;
|
|
8320
|
+
if (!Array.isArray(child) || child.length < 2) return void 0;
|
|
8321
|
+
const segment = child[0], payload = child[1];
|
|
8322
|
+
if (!(typeof segment === "string" || Array.isArray(segment) && segment.every((part) => typeof part === "string"))) return void 0;
|
|
8323
|
+
return Array.isArray(payload) && payload[0] === "$" || typeof payload === "string" && /^\$L?[a-f\d]+$/i.test(payload) ? child : void 0;
|
|
8324
|
+
}
|
|
8325
|
+
function readMigrationFlightDocument($) {
|
|
8326
|
+
flightTextRecords($);
|
|
8327
|
+
return flightDocuments.get($);
|
|
8328
|
+
}
|
|
8329
|
+
function literalJson(value) {
|
|
8330
|
+
if (Buffer.byteLength(value) > MAX_SOURCE_BYTES) return void 0;
|
|
8331
|
+
let depth = 0, quoted = false, escaped = false;
|
|
8332
|
+
for (const character of value) {
|
|
8333
|
+
if (quoted) {
|
|
8334
|
+
if (escaped) escaped = false;
|
|
8335
|
+
else if (character === "\\") escaped = true;
|
|
8336
|
+
else if (character === '"') quoted = false;
|
|
8337
|
+
} else if (character === '"') quoted = true;
|
|
8338
|
+
else if (character === "[" || character === "{") {
|
|
8339
|
+
if (++depth > 96) return void 0;
|
|
8340
|
+
} else if (character === "]" || character === "}") {
|
|
8341
|
+
if (--depth < 0) return void 0;
|
|
7921
8342
|
}
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
8343
|
+
}
|
|
8344
|
+
if (depth !== 0 || quoted) return void 0;
|
|
8345
|
+
try {
|
|
8346
|
+
return JSON.parse(value);
|
|
8347
|
+
} catch {
|
|
8348
|
+
return void 0;
|
|
8349
|
+
}
|
|
8350
|
+
}
|
|
8351
|
+
function flightTextRecords($) {
|
|
8352
|
+
const cached = flightDocuments.get($);
|
|
8353
|
+
if (cached) return cached.sources;
|
|
8354
|
+
const chunks = [];
|
|
8355
|
+
let size = 0;
|
|
8356
|
+
$("script").each((_index, node) => {
|
|
8357
|
+
const match = /^\s*self\.__next_f\.push\(\s*(\[[\s\S]*\])\s*\)\s*;?\s*$/.exec($(node).text());
|
|
8358
|
+
if (!match) return;
|
|
8359
|
+
const envelope = literalJson(match[1]);
|
|
8360
|
+
if (Array.isArray(envelope) && envelope.length === 2 && envelope[0] === 1 && typeof envelope[1] === "string") {
|
|
8361
|
+
size += Buffer.byteLength(envelope[1]);
|
|
8362
|
+
if (size <= MAX_SOURCE_BYTES) chunks.push(envelope[1]);
|
|
8363
|
+
}
|
|
8364
|
+
});
|
|
8365
|
+
if (size > MAX_SOURCE_BYTES) return [];
|
|
8366
|
+
const bytes = Buffer.from(chunks.join(""));
|
|
8367
|
+
const texts = /* @__PURE__ */ new Map();
|
|
8368
|
+
const modules = /* @__PURE__ */ new Map();
|
|
8369
|
+
const records = /* @__PURE__ */ new Map();
|
|
8370
|
+
let cursor = 0;
|
|
8371
|
+
while (cursor < bytes.length && texts.size + modules.size + records.size <= 1e4) {
|
|
8372
|
+
const colon = bytes.indexOf(58, cursor);
|
|
8373
|
+
if (colon < 0 || colon - cursor > 16 || !/^[a-f\d]*$/i.test(bytes.toString("utf8", cursor, colon))) break;
|
|
8374
|
+
const id = bytes.toString("utf8", cursor, colon);
|
|
8375
|
+
cursor = colon + 1;
|
|
8376
|
+
if (bytes[cursor] === 84) {
|
|
8377
|
+
const comma = bytes.indexOf(44, cursor + 1);
|
|
8378
|
+
const length = comma < 0 ? "" : bytes.toString("utf8", cursor + 1, comma);
|
|
8379
|
+
if (!/^[a-f\d]{1,8}$/i.test(length)) break;
|
|
8380
|
+
const end = comma + 1 + Number.parseInt(length, 16);
|
|
8381
|
+
if (end > bytes.length) break;
|
|
8382
|
+
const text3 = bytes.toString("utf8", comma + 1, end);
|
|
8383
|
+
if (text3.includes("\uFFFD")) return [];
|
|
8384
|
+
if (texts.has(id) || records.has(id) || modules.has(id)) return [];
|
|
8385
|
+
texts.set(id, text3);
|
|
8386
|
+
cursor = end;
|
|
8387
|
+
} else {
|
|
8388
|
+
const newline = bytes.indexOf(10, cursor);
|
|
8389
|
+
const end = newline < 0 ? bytes.length : newline;
|
|
8390
|
+
const line = bytes.toString("utf8", cursor, end);
|
|
8391
|
+
if (id && (texts.has(id) || records.has(id) || modules.has(id))) return [];
|
|
8392
|
+
if (line.startsWith("I[")) {
|
|
8393
|
+
const moduleRecord = literalJson(line.slice(1));
|
|
8394
|
+
if (id && Array.isArray(moduleRecord) && typeof moduleRecord[2] === "string") modules.set(id, moduleRecord[2]);
|
|
8395
|
+
} else if (id && /^[\[{"\d-]|^(?:true|false|null)$/.test(line)) records.set(id, literalJson(line));
|
|
8396
|
+
cursor = end + 1;
|
|
8397
|
+
}
|
|
8398
|
+
}
|
|
8399
|
+
if (texts.size + modules.size + records.size > 1e4) return [];
|
|
8400
|
+
const selected = /* @__PURE__ */ new Set();
|
|
8401
|
+
let visited = 0;
|
|
8402
|
+
let hasIncompleteSourceTree = false;
|
|
8403
|
+
const active = /* @__PURE__ */ new Set();
|
|
8404
|
+
const seenReferences = /* @__PURE__ */ new Set();
|
|
8405
|
+
const visit = (value, inArticle, depth) => {
|
|
8406
|
+
if (depth > 96 || ++visited > 1e5) {
|
|
8407
|
+
hasIncompleteSourceTree = true;
|
|
8408
|
+
return;
|
|
8409
|
+
}
|
|
8410
|
+
if (typeof value === "string") {
|
|
8411
|
+
const reference = /^\$L?([a-f\d]+)$/i.exec(value)?.[1];
|
|
8412
|
+
if (reference && active.has(reference)) hasIncompleteSourceTree = true;
|
|
8413
|
+
const identity = `${reference}:${inArticle}`;
|
|
8414
|
+
if (reference && records.has(reference) && !active.has(reference) && !seenReferences.has(identity)) {
|
|
8415
|
+
seenReferences.add(identity);
|
|
8416
|
+
active.add(reference);
|
|
8417
|
+
visit(records.get(reference), inArticle, depth + 1);
|
|
8418
|
+
active.delete(reference);
|
|
8419
|
+
}
|
|
8420
|
+
return;
|
|
8421
|
+
}
|
|
8422
|
+
if (Array.isArray(value)) {
|
|
8423
|
+
const moduleId = value[0] === "$" && typeof value[1] === "string" ? /^\$L([a-f\d]+)$/i.exec(value[1])?.[1] : void 0;
|
|
8424
|
+
const component = moduleId ? modules.get(moduleId) : void 0;
|
|
8425
|
+
const isArticle = inArticle || component === "PageArticle";
|
|
8426
|
+
const props = value[3];
|
|
8427
|
+
if (isArticle && component === "CopyMarkdownButton" && props && typeof props === "object" && !Array.isArray(props)) {
|
|
8428
|
+
const reference = /^\$([a-f\d]+)$/i.exec(String(props.content ?? ""))?.[1];
|
|
8429
|
+
if (reference && texts.has(reference)) selected.add(texts.get(reference));
|
|
8430
|
+
}
|
|
8431
|
+
if (value[0] === "$" && props && typeof props === "object" && !Array.isArray(props)) {
|
|
8432
|
+
visit(props.children, isArticle, depth + 1);
|
|
8433
|
+
return;
|
|
8434
|
+
}
|
|
8435
|
+
for (const child of value) visit(child, isArticle, depth + 1);
|
|
8436
|
+
} else if (depth === 0 && value && typeof value === "object" && Array.isArray(value.f)) {
|
|
8437
|
+
visit(value.f, inArticle, depth + 1);
|
|
8438
|
+
} else {
|
|
8439
|
+
const slot = renderedRouteSlot(value);
|
|
8440
|
+
if (slot) visit(slot, inArticle, depth + 1);
|
|
7926
8441
|
}
|
|
7927
|
-
return end === source;
|
|
7928
8442
|
};
|
|
7929
|
-
|
|
8443
|
+
visit(records.get("0"), false, 0);
|
|
8444
|
+
const sources = visited > 1e5 || hasIncompleteSourceTree ? [] : [...selected];
|
|
8445
|
+
flightDocuments.set($, { texts, modules, records, sources });
|
|
8446
|
+
return sources;
|
|
7930
8447
|
}
|
|
7931
|
-
function
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
const
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
const loopingByCase = [];
|
|
7939
|
-
const folded = redirectChains();
|
|
7940
|
-
const asWritten = redirectChains();
|
|
7941
|
-
const redirects = config.redirects.filter((redirect) => {
|
|
7942
|
-
const source = literalRoute(redirect.source);
|
|
7943
|
-
if (!source) return true;
|
|
7944
|
-
const writtenSource = exactRoute(redirect.source);
|
|
7945
|
-
if (served.has(source)) {
|
|
7946
|
-
const hides = servedAsWritten.has(writtenSource) ? hidden : hiddenByCase;
|
|
7947
|
-
hides.push(redirect.source);
|
|
7948
|
-
return false;
|
|
8448
|
+
function descendants(root) {
|
|
8449
|
+
const result = [];
|
|
8450
|
+
let exceeded = false;
|
|
8451
|
+
const visit = (node, depth) => {
|
|
8452
|
+
if (depth > 96 || result.length >= 1e5) {
|
|
8453
|
+
exceeded = true;
|
|
8454
|
+
return;
|
|
7949
8455
|
}
|
|
7950
|
-
|
|
7951
|
-
const
|
|
7952
|
-
|
|
7953
|
-
|
|
7954
|
-
|
|
7955
|
-
|
|
7956
|
-
|
|
7957
|
-
|
|
7958
|
-
|
|
7959
|
-
|
|
8456
|
+
result.push(node);
|
|
8457
|
+
for (const child of node.children ?? []) visit(child, depth + 1);
|
|
8458
|
+
};
|
|
8459
|
+
visit(root, 0);
|
|
8460
|
+
return exceeded ? [] : result;
|
|
8461
|
+
}
|
|
8462
|
+
function sourceText(node) {
|
|
8463
|
+
if (["mdxjsEsm", "mdxFlowExpression", "mdxTextExpression"].includes(node.type)) return "";
|
|
8464
|
+
return node.value ?? (node.children ?? []).map(sourceText).join("");
|
|
8465
|
+
}
|
|
8466
|
+
function sourceNodes(source) {
|
|
8467
|
+
const key = createHash3("sha256").update(source).digest("hex");
|
|
8468
|
+
const cached = sourceTrees.get(key);
|
|
8469
|
+
if (cached) {
|
|
8470
|
+
sourceTrees.delete(key);
|
|
8471
|
+
sourceTrees.set(key, cached);
|
|
8472
|
+
return cached.nodes;
|
|
8473
|
+
}
|
|
8474
|
+
let nodes;
|
|
8475
|
+
try {
|
|
8476
|
+
nodes = descendants(parser2.parse(source));
|
|
8477
|
+
} catch {
|
|
8478
|
+
nodes = [];
|
|
8479
|
+
}
|
|
8480
|
+
const bytes = Buffer.byteLength(source);
|
|
8481
|
+
if (bytes <= MAX_CACHED_SOURCE_BYTES) {
|
|
8482
|
+
while (sourceTrees.size >= 4 || cachedSourceBytes + bytes > MAX_CACHED_SOURCE_BYTES) {
|
|
8483
|
+
const oldest = sourceTrees.keys().next().value;
|
|
8484
|
+
if (oldest === void 0) break;
|
|
8485
|
+
cachedSourceBytes -= sourceTrees.get(oldest).bytes;
|
|
8486
|
+
sourceTrees.delete(oldest);
|
|
7960
8487
|
}
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
8488
|
+
sourceTrees.set(key, { bytes, nodes });
|
|
8489
|
+
cachedSourceBytes += bytes;
|
|
8490
|
+
}
|
|
8491
|
+
return nodes;
|
|
8492
|
+
}
|
|
8493
|
+
function codeText(value) {
|
|
8494
|
+
return value.replace(/\n+$/, "");
|
|
8495
|
+
}
|
|
8496
|
+
function labelText(value) {
|
|
8497
|
+
return value.trim().replace(/\s+/g, " ");
|
|
8498
|
+
}
|
|
8499
|
+
function renderedCode($, node) {
|
|
8500
|
+
const copy = $(node).clone();
|
|
8501
|
+
copy.find("code > span.line").each((_index, line) => {
|
|
8502
|
+
if (!$(line).children().length && $(line).text() === " ") $(line).text("");
|
|
7964
8503
|
});
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
8504
|
+
return codeText(copy.text());
|
|
8505
|
+
}
|
|
8506
|
+
function isOrderedSubsequence(values, source) {
|
|
8507
|
+
let cursor = 0;
|
|
8508
|
+
for (const value of values) {
|
|
8509
|
+
while (cursor < source.length && source[cursor] !== value) cursor += 1;
|
|
8510
|
+
if (cursor === source.length) return false;
|
|
8511
|
+
cursor += 1;
|
|
7970
8512
|
}
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
8513
|
+
return true;
|
|
8514
|
+
}
|
|
8515
|
+
function matchesSourceCode(rendered, source) {
|
|
8516
|
+
const actual = codeText(rendered).split("\n"), declared = codeText(source).split("\n");
|
|
8517
|
+
if (actual.length !== declared.length) return false;
|
|
8518
|
+
return declared.every((line, index) => {
|
|
8519
|
+
const directive = /\/\/\s*\[!code (?:\+\+|--|highlight|focus|error|warning)(?::\d+)?\]\s*$/.exec(line);
|
|
8520
|
+
return directive ? line.slice(0, directive.index).replace(/[\t ]+$/, "") === actual[index].replace(/[\t ]+$/, "") : line === actual[index];
|
|
8521
|
+
});
|
|
8522
|
+
}
|
|
8523
|
+
function matchesSourceCodeSequence(rendered, source) {
|
|
8524
|
+
let cursor = 0;
|
|
8525
|
+
for (const value of rendered) {
|
|
8526
|
+
while (cursor < source.length && !matchesSourceCode(value, source[cursor].value ?? "")) cursor += 1;
|
|
8527
|
+
if (cursor === source.length) return false;
|
|
8528
|
+
cursor += 1;
|
|
7977
8529
|
}
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
8530
|
+
return true;
|
|
8531
|
+
}
|
|
8532
|
+
function hasStaticProps(document, element, allowed) {
|
|
8533
|
+
const common = /* @__PURE__ */ new Set(["children", "className", "style", "id", ...allowed]);
|
|
8534
|
+
return Object.entries(element.props).every(([key, value]) => key === "ref" ? flightValue(document, value) === void 0 : common.has(key));
|
|
8535
|
+
}
|
|
8536
|
+
function flightValue(document, value) {
|
|
8537
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8538
|
+
for (let depth = 0; depth < 32 && typeof value === "string"; depth += 1) {
|
|
8539
|
+
if (value.startsWith("$$")) return value.slice(1);
|
|
8540
|
+
const reference = /^\$L?([a-f\d]+)(?::(.+))?$/i.exec(value);
|
|
8541
|
+
if (!reference) return value === "$undefined" ? void 0 : value.startsWith("$") ? UNRESOLVED_FLIGHT_VALUE : value;
|
|
8542
|
+
if (seen.has(value)) return UNRESOLVED_FLIGHT_VALUE;
|
|
8543
|
+
seen.add(value);
|
|
8544
|
+
if (document.texts.has(reference[1])) return reference[2] ? UNRESOLVED_FLIGHT_VALUE : document.texts.get(reference[1]);
|
|
8545
|
+
if (!document.records.has(reference[1]) || document.records.get(reference[1]) === void 0) return UNRESOLVED_FLIGHT_VALUE;
|
|
8546
|
+
value = document.records.get(reference[1]);
|
|
8547
|
+
if (reference[2]) for (const key of reference[2].split(":")) {
|
|
8548
|
+
if (key === "props" && Array.isArray(value) && value[0] === "$" && typeof value[1] === "string" && value[3] && typeof value[3] === "object" && !Array.isArray(value[3])) {
|
|
8549
|
+
value = value[3];
|
|
8550
|
+
continue;
|
|
8551
|
+
}
|
|
8552
|
+
if (!value || typeof value !== "object" || !Object.hasOwn(value, key)) return UNRESOLVED_FLIGHT_VALUE;
|
|
8553
|
+
value = value[key];
|
|
8554
|
+
}
|
|
7983
8555
|
}
|
|
7984
|
-
|
|
7985
|
-
|
|
8556
|
+
return typeof value === "string" && /^\$L?[a-f\d]+(?::|$)/i.test(value) ? UNRESOLVED_FLIGHT_VALUE : value;
|
|
8557
|
+
}
|
|
8558
|
+
function resolveMigrationFlightValue(document, input) {
|
|
8559
|
+
const value = flightValue(document, input);
|
|
8560
|
+
return value === UNRESOLVED_FLIGHT_VALUE ? { resolved: false, value: void 0 } : { resolved: true, value };
|
|
8561
|
+
}
|
|
8562
|
+
function flightElement(document, value) {
|
|
8563
|
+
const node = flightValue(document, value);
|
|
8564
|
+
if (!Array.isArray(node) || node[0] !== "$" || typeof node[1] !== "string" || !node[3] || typeof node[3] !== "object" || Array.isArray(node[3])) return void 0;
|
|
8565
|
+
const moduleId = /^\$L?([a-f\d]+)$/i.exec(node[1])?.[1];
|
|
8566
|
+
const symbol = moduleId ? document.records.get(moduleId) : void 0;
|
|
8567
|
+
const kind = moduleId ? document.modules.get(moduleId) ?? (symbol === "$Sreact.fragment" ? "Fragment" : symbol === "$Sreact.suspense" ? "Suspense" : void 0) : node[1];
|
|
8568
|
+
return kind ? { kind, props: node[3] } : void 0;
|
|
8569
|
+
}
|
|
8570
|
+
function visitFlightTree(document, root, visit, skipUnresolvedBranches = false) {
|
|
8571
|
+
const budget = expansionBudget();
|
|
8572
|
+
let hasUnresolvedValue = false;
|
|
8573
|
+
const walk2 = (raw, depth) => {
|
|
8574
|
+
if (budget.exceeded) return;
|
|
8575
|
+
if (depth > 96 || ++budget.visited > 1e5) {
|
|
8576
|
+
budget.exceeded = true;
|
|
8577
|
+
return;
|
|
8578
|
+
}
|
|
8579
|
+
const value = flightValue(document, raw);
|
|
8580
|
+
if (value === UNRESOLVED_FLIGHT_VALUE) {
|
|
8581
|
+
hasUnresolvedValue = true;
|
|
8582
|
+
return;
|
|
8583
|
+
}
|
|
8584
|
+
if (typeof value === "string" && !chargeExpansion(budget, value)) return;
|
|
8585
|
+
const element = flightElement(document, value);
|
|
8586
|
+
if (element) {
|
|
8587
|
+
if (visit(element, value, budget) !== false) walk2(element.props.children, depth + 1);
|
|
8588
|
+
} else if (Array.isArray(value)) {
|
|
8589
|
+
for (const child of value) walk2(child, depth + 1);
|
|
8590
|
+
} else if (depth === 0 && value && typeof value === "object" && Array.isArray(value.f)) {
|
|
8591
|
+
walk2(value.f, depth + 1);
|
|
8592
|
+
} else {
|
|
8593
|
+
const slot = renderedRouteSlot(value);
|
|
8594
|
+
if (slot) walk2(slot, depth + 1);
|
|
8595
|
+
}
|
|
8596
|
+
};
|
|
8597
|
+
walk2(root, 0);
|
|
8598
|
+
return !budget.exceeded && (skipUnresolvedBranches || !hasUnresolvedValue);
|
|
8599
|
+
}
|
|
8600
|
+
function flightLiteralText(document, raw, depth = 0, code = false, budget = expansionBudget()) {
|
|
8601
|
+
if (budget.exceeded || depth > 96 || ++budget.visited > 1e5) {
|
|
8602
|
+
budget.exceeded = true;
|
|
8603
|
+
return null;
|
|
8604
|
+
}
|
|
8605
|
+
const value = flightValue(document, raw);
|
|
8606
|
+
if (value === null || value === void 0 || typeof value === "boolean") return "";
|
|
8607
|
+
if (typeof value === "string" || typeof value === "number") return chargeExpansion(budget, String(value)) ? String(value) : null;
|
|
8608
|
+
const element = flightElement(document, value);
|
|
8609
|
+
if (element) {
|
|
8610
|
+
if (["script", "style"].includes(element.kind) || element.props.dangerouslySetInnerHTML !== void 0) return null;
|
|
8611
|
+
if (code && element.kind === "span" && element.props.className === "line" && element.props.children === " ") return "";
|
|
8612
|
+
return flightLiteralText(document, element.props.children, depth + 1, code, budget);
|
|
8613
|
+
}
|
|
8614
|
+
if (!Array.isArray(value)) return null;
|
|
8615
|
+
let text3 = "";
|
|
8616
|
+
for (const child of value) {
|
|
8617
|
+
const literal = flightLiteralText(document, child, depth + 1, code, budget);
|
|
8618
|
+
if (literal === null) return null;
|
|
8619
|
+
text3 += literal;
|
|
8620
|
+
}
|
|
8621
|
+
return text3;
|
|
8622
|
+
}
|
|
8623
|
+
function flightCode(document, element, budget = expansionBudget()) {
|
|
8624
|
+
if (!["CodeBlock", "Pre", "pre"].includes(element.kind)) return null;
|
|
8625
|
+
if (!hasStaticProps(document, element, ["language", "lang", "data-language", "tabIndex", "icon"])) return null;
|
|
8626
|
+
const value = flightLiteralText(document, element.props.children, 0, true, budget);
|
|
8627
|
+
if (value === null) return null;
|
|
8628
|
+
const language = [element.props.language, element.props.lang, element.props["data-language"]].find((value2) => typeof value2 === "string" && /^[A-Za-z0-9_+-]{1,64}$/.test(value2));
|
|
8629
|
+
return { value, ...typeof language === "string" ? { language } : {} };
|
|
8630
|
+
}
|
|
8631
|
+
function flightTabCode(document, raw, depth = 0, budget = expansionBudget()) {
|
|
8632
|
+
if (budget.exceeded || depth > 96 || ++budget.visited > 1e5) {
|
|
8633
|
+
budget.exceeded = true;
|
|
8634
|
+
return null;
|
|
8635
|
+
}
|
|
8636
|
+
const value = flightValue(document, raw);
|
|
8637
|
+
if (value === null || value === void 0 || typeof value === "boolean" || typeof value === "string" && !value.trim()) return [];
|
|
8638
|
+
const element = flightElement(document, value);
|
|
8639
|
+
if (element) {
|
|
8640
|
+
const code = flightCode(document, element, budget);
|
|
8641
|
+
if (code) return [code];
|
|
8642
|
+
if (!["div", "figure"].includes(element.kind) || !hasStaticProps(document, element, []) || element.props.id !== void 0) return null;
|
|
8643
|
+
return flightTabCode(document, element.props.children, depth + 1, budget);
|
|
8644
|
+
}
|
|
8645
|
+
if (!Array.isArray(value)) return null;
|
|
8646
|
+
const result = [];
|
|
8647
|
+
for (const child of value) {
|
|
8648
|
+
const code = flightTabCode(document, child, depth + 1, budget);
|
|
8649
|
+
if (code === null) return null;
|
|
8650
|
+
result.push(...code);
|
|
8651
|
+
}
|
|
8652
|
+
return result;
|
|
8653
|
+
}
|
|
8654
|
+
function htmlLiteral(value) {
|
|
8655
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
8656
|
+
}
|
|
8657
|
+
function flightStaticHtml(document, source, prefix, budget = expansionBudget()) {
|
|
8658
|
+
let visited = 0;
|
|
8659
|
+
const reserve = (bytes) => {
|
|
8660
|
+
budget.bytes += bytes;
|
|
8661
|
+
if (budget.bytes > MAX_SOURCE_BYTES) budget.exceeded = true;
|
|
8662
|
+
};
|
|
8663
|
+
const literal = (value) => {
|
|
8664
|
+
if (budget.exceeded) return "";
|
|
8665
|
+
let bytes = Buffer.byteLength(value);
|
|
8666
|
+
for (const character of value) bytes += character === "&" ? 4 : character === "<" || character === ">" ? 3 : character === '"' ? 5 : 0;
|
|
8667
|
+
reserve(bytes);
|
|
8668
|
+
return budget.exceeded ? "" : htmlLiteral(value);
|
|
8669
|
+
};
|
|
8670
|
+
let tabIndex = 0;
|
|
8671
|
+
const render = (raw, depth) => {
|
|
8672
|
+
if (budget.exceeded || depth > 96 || ++visited > 1e5) return null;
|
|
8673
|
+
const value = flightValue(document, raw);
|
|
8674
|
+
if (value === null || value === void 0 || typeof value === "boolean") return "";
|
|
8675
|
+
if (typeof value === "string" || typeof value === "number") return literal(String(value));
|
|
8676
|
+
const element = flightElement(document, value);
|
|
8677
|
+
if (!element) {
|
|
8678
|
+
if (!Array.isArray(value)) return null;
|
|
8679
|
+
const children2 = value.map((child) => render(child, depth + 1));
|
|
8680
|
+
return children2.some((child) => child === null) ? null : children2.join("");
|
|
8681
|
+
}
|
|
8682
|
+
reserve(128);
|
|
8683
|
+
if (budget.exceeded) return null;
|
|
8684
|
+
const code = flightCode(document, element, budget);
|
|
8685
|
+
if (code) return `<pre${code.language ? ` data-language="${literal(code.language)}"` : ""}><code>${literal(code.value)}</code></pre>`;
|
|
8686
|
+
if (element.kind === "svg") {
|
|
8687
|
+
const svg = (raw2, depth2) => {
|
|
8688
|
+
if (budget.exceeded || depth2 > 96 || ++visited > 1e5) return null;
|
|
8689
|
+
const value2 = flightValue(document, raw2);
|
|
8690
|
+
if (value2 === null || value2 === void 0 || typeof value2 === "boolean") return "";
|
|
8691
|
+
if (typeof value2 === "string" || typeof value2 === "number") return literal(String(value2));
|
|
8692
|
+
const node = flightElement(document, value2);
|
|
8693
|
+
if (!node) {
|
|
8694
|
+
if (!Array.isArray(value2)) return null;
|
|
8695
|
+
const children3 = value2.map((child) => svg(child, depth2 + 1));
|
|
8696
|
+
return children3.some((child) => child === null) ? null : children3.join("");
|
|
8697
|
+
}
|
|
8698
|
+
if (!/^[a-z][a-zA-Z\d]*$/.test(node.kind)) return null;
|
|
8699
|
+
const attributes2 = [];
|
|
8700
|
+
for (const [rawName, rawValue] of Object.entries(node.props)) {
|
|
8701
|
+
if (rawName === "children") continue;
|
|
8702
|
+
const value3 = flightValue(document, rawValue);
|
|
8703
|
+
if (value3 === void 0) continue;
|
|
8704
|
+
if (!["string", "number", "boolean"].includes(typeof value3)) return null;
|
|
8705
|
+
const spellings = {
|
|
8706
|
+
className: "class",
|
|
8707
|
+
strokeWidth: "stroke-width",
|
|
8708
|
+
strokeLinecap: "stroke-linecap",
|
|
8709
|
+
strokeLinejoin: "stroke-linejoin",
|
|
8710
|
+
strokeMiterlimit: "stroke-miterlimit",
|
|
8711
|
+
strokeDasharray: "stroke-dasharray",
|
|
8712
|
+
strokeDashoffset: "stroke-dashoffset",
|
|
8713
|
+
fillRule: "fill-rule",
|
|
8714
|
+
clipRule: "clip-rule",
|
|
8715
|
+
fillOpacity: "fill-opacity",
|
|
8716
|
+
strokeOpacity: "stroke-opacity",
|
|
8717
|
+
clipPath: "clip-path",
|
|
8718
|
+
fontSize: "font-size"
|
|
8719
|
+
};
|
|
8720
|
+
const name = spellings[rawName] ?? rawName;
|
|
8721
|
+
if (!/^[a-zA-Z][a-zA-Z\d:._-]*$/.test(name)) return null;
|
|
8722
|
+
reserve(name.length + 4);
|
|
8723
|
+
if (budget.exceeded) return null;
|
|
8724
|
+
attributes2.push(` ${name}="${literal(String(value3))}"`);
|
|
8725
|
+
}
|
|
8726
|
+
const children2 = svg(node.props.children, depth2 + 1);
|
|
8727
|
+
return children2 === null ? null : `<${node.kind}${attributes2.join("")}>${children2}</${node.kind}>`;
|
|
8728
|
+
};
|
|
8729
|
+
const html = svg(value, depth + 1);
|
|
8730
|
+
return html !== null && isPassiveSvg(Buffer.from(html)) ? html : null;
|
|
8731
|
+
}
|
|
8732
|
+
if (element.kind === "ThemedImage") {
|
|
8733
|
+
if (Object.keys(element.props).some((key) => !["lightSrc", "darkSrc", "alt", "caption"].includes(key))) return null;
|
|
8734
|
+
const light = flightValue(document, element.props.lightSrc), dark = flightValue(document, element.props.darkSrc);
|
|
8735
|
+
const alt = flightValue(document, element.props.alt);
|
|
8736
|
+
if (typeof light !== "string" || typeof dark !== "string" || typeof alt !== "string") return null;
|
|
8737
|
+
const caption = render(element.props.caption, depth + 1);
|
|
8738
|
+
if (caption === null) return null;
|
|
8739
|
+
return `<figure><picture><source media="(prefers-color-scheme: dark)" srcset="${literal(dark)}"><img src="${literal(light)}" alt="${literal(alt)}"></picture>${caption ? `<figcaption>${caption}</figcaption>` : ""}</figure>`;
|
|
8740
|
+
}
|
|
8741
|
+
if (element.kind === "Tabs") {
|
|
8742
|
+
if (!hasStaticProps(document, element, ["items", "defaultIndex", "groupId", "persist"])) return null;
|
|
8743
|
+
const children2 = flightValue(document, element.props.children);
|
|
8744
|
+
const tabs = flightElement(document, children2) ? [children2] : Array.isArray(children2) ? children2 : [];
|
|
8745
|
+
const labels2 = flightValue(document, element.props.items);
|
|
8746
|
+
const group = tabIndex++;
|
|
8747
|
+
const choices = [];
|
|
8748
|
+
for (const [index, rawTab] of tabs.entries()) {
|
|
8749
|
+
const tab = flightElement(document, rawTab);
|
|
8750
|
+
const label = tab?.props.value ?? tab?.props.title;
|
|
8751
|
+
if (tab?.kind !== "Tab" || !hasStaticProps(document, tab, ["value", "title"]) || typeof label !== "string" || !label.trim()) return null;
|
|
8752
|
+
const html = render(tab.props.children, depth + 1);
|
|
8753
|
+
if (html === null) return null;
|
|
8754
|
+
choices.push({ label, html, id: `${prefix}-${group}-${index}` });
|
|
8755
|
+
}
|
|
8756
|
+
if (!choices.length || labels2 !== void 0 && (!Array.isArray(labels2) || JSON.stringify(labels2) !== JSON.stringify(choices.map((choice) => choice.label)))) return null;
|
|
8757
|
+
return `<div><div role="tablist">${choices.map((choice) => `<button role="tab" id="${choice.id}-tab" aria-controls="${choice.id}-panel">${literal(choice.label)}</button>`).join("")}</div>${choices.map((choice) => `<div role="tabpanel" id="${choice.id}-panel" aria-labelledby="${choice.id}-tab">${choice.html}</div>`).join("")}</div>`;
|
|
8758
|
+
}
|
|
8759
|
+
const children = render(element.props.children, depth + 1);
|
|
8760
|
+
if (children === null) return null;
|
|
8761
|
+
if (["Fragment", "Suspense", "Accordions"].includes(element.kind)) return hasStaticProps(document, element, ["type", "defaultValue", "collapsible"]) ? children : null;
|
|
8762
|
+
if (element.kind === "Accordion") {
|
|
8763
|
+
if (!hasStaticProps(document, element, ["title", "defaultOpen", "value"])) return null;
|
|
8764
|
+
const title = flightLiteralText(document, element.props.title);
|
|
8765
|
+
return title === null ? null : `<details open><summary>${literal(title)}</summary>${children}</details>`;
|
|
8766
|
+
}
|
|
8767
|
+
if (element.kind === "Callout") {
|
|
8768
|
+
if (!hasStaticProps(document, element, ["title", "type", "icon"])) return null;
|
|
8769
|
+
const title = element.props.title === void 0 ? "" : flightLiteralText(document, element.props.title);
|
|
8770
|
+
return title === null ? null : `<blockquote>${title ? `<p><strong>${literal(title)}</strong></p>` : ""}${children}</blockquote>`;
|
|
8771
|
+
}
|
|
8772
|
+
const isStaticLink = element.kind === "default" && typeof element.props.href === "string" && Object.keys(element.props).every((key) => ["href", "children", "ref", "prefetch", "replace", "scroll", "className", "target", "rel"].includes(key)) && ["ref", "prefetch", "replace", "scroll"].every((key) => flightValue(document, element.props[key]) === void 0);
|
|
8773
|
+
const tag = element.kind === "Heading" ? element.props.as ?? "h2" : element.kind === "Link" || isStaticLink ? "a" : element.kind;
|
|
8774
|
+
if (typeof tag !== "string" || !/^(?:p|div|section|span|em|strong|a|ul|ol|li|blockquote|table|thead|tbody|tr|td|th|code|h[1-6]|br|hr|img|picture|source|figure|figcaption|sup|sub|details|summary)$/.test(tag) || element.props.dangerouslySetInnerHTML !== void 0) return null;
|
|
8775
|
+
const semanticAttributes = tag === "a" ? ["href", "title", "target", "rel"] : tag === "img" ? ["src", "alt", "width", "height", "srcSet", "srcset", "sizes", "title", "loading", "decoding"] : tag === "source" ? ["srcSet", "srcset", "sizes", "media", "type", "width", "height"] : tag === "details" ? ["open"] : [];
|
|
8776
|
+
if (!isStaticLink && !hasStaticProps(document, element, [...semanticAttributes, ...element.kind === "Heading" ? ["as"] : []])) return null;
|
|
8777
|
+
const attributes = [];
|
|
8778
|
+
for (const name of ["id", ...semanticAttributes]) {
|
|
8779
|
+
if (element.props[name] === void 0) continue;
|
|
8780
|
+
const attribute = flightValue(document, element.props[name]);
|
|
8781
|
+
if (name === "open" && typeof attribute === "boolean") {
|
|
8782
|
+
if (attribute) attributes.push(" open");
|
|
8783
|
+
continue;
|
|
8784
|
+
}
|
|
8785
|
+
if (typeof attribute !== "string" && typeof attribute !== "number") return null;
|
|
8786
|
+
reserve(name.length + 4);
|
|
8787
|
+
if (budget.exceeded) return null;
|
|
8788
|
+
attributes.push(` ${name === "srcSet" ? "srcset" : name}="${literal(String(attribute))}"`);
|
|
8789
|
+
}
|
|
8790
|
+
if (["br", "hr", "img", "source"].includes(tag)) return `<${tag}${attributes.join("")}>`;
|
|
8791
|
+
return `<${tag}${attributes.join("")}>${children}</${tag}>`;
|
|
8792
|
+
};
|
|
8793
|
+
const result = render(source, 0);
|
|
8794
|
+
return budget.exceeded ? null : result;
|
|
8795
|
+
}
|
|
8796
|
+
function recoverFlightDisclosures($, root, document, article, projectionBudget) {
|
|
8797
|
+
const disclosures = [];
|
|
8798
|
+
if (!visitFlightTree(document, article, (element) => {
|
|
8799
|
+
if (element.kind === "Accordion") {
|
|
8800
|
+
disclosures.push(element);
|
|
8801
|
+
return false;
|
|
8802
|
+
}
|
|
8803
|
+
})) return;
|
|
8804
|
+
const controls = root.find("button[aria-expanded][aria-controls]").toArray();
|
|
8805
|
+
if (controls.length !== disclosures.length) return;
|
|
8806
|
+
const projections = [];
|
|
8807
|
+
for (const [index, control] of controls.entries()) {
|
|
8808
|
+
const button = $(control), source = disclosures[index];
|
|
8809
|
+
if (!hasStaticProps(document, source, ["title", "defaultOpen", "value"])) continue;
|
|
8810
|
+
const title = flightLiteralText(document, source.props.title);
|
|
8811
|
+
const id = button.attr("id"), target2 = button.attr("aria-controls");
|
|
8812
|
+
const panel = root.find("[id]").filter((_index, node) => $(node).attr("id") === target2);
|
|
8813
|
+
if (!id || !target2 || title === null || labelText(title) !== labelText(button.text()) || panel.length !== 1 || panel.attr("role") !== "region" || panel.attr("aria-labelledby") !== id || root.find("[id]").filter((_index, node) => $(node).attr("id") === id).length !== 1 || panel.is('[aria-busy="true"]') || panel.find('[aria-busy="true"],[role="progressbar"]').length) continue;
|
|
8814
|
+
let html;
|
|
8815
|
+
if (!panel.text().trim() && !panel.children().length) {
|
|
8816
|
+
const prefix = `thally-flight-${createHash3("sha256").update(target2).digest("hex").slice(0, 16)}`;
|
|
8817
|
+
const rendered = flightStaticHtml(document, source.props.children, prefix, projectionBudget);
|
|
8818
|
+
if (rendered === null || !rendered.trim()) continue;
|
|
8819
|
+
html = rendered;
|
|
8820
|
+
}
|
|
8821
|
+
projections.push({ control, panel, html });
|
|
8822
|
+
}
|
|
8823
|
+
if (projectionBudget.exceeded) return;
|
|
8824
|
+
for (const { control, panel, html } of projections) {
|
|
8825
|
+
const button = $(control);
|
|
8826
|
+
if (html !== void 0) panel.html(html);
|
|
8827
|
+
control.name = "span";
|
|
8828
|
+
button.removeAttr("aria-expanded aria-controls role type");
|
|
8829
|
+
panel.removeAttr("hidden aria-hidden");
|
|
8830
|
+
button.parent("h1,h2,h3,h4,h5,h6").attr("data-thally-static-disclosure-heading", "");
|
|
8831
|
+
}
|
|
8832
|
+
}
|
|
8833
|
+
function recoverFlightTreeTabs($, root, projectionBudget) {
|
|
8834
|
+
flightTextRecords($);
|
|
8835
|
+
const document = flightDocuments.get($);
|
|
8836
|
+
if (!document) return;
|
|
8837
|
+
const articles = [];
|
|
8838
|
+
if (!visitFlightTree(document, document.records.get("0"), (element, raw) => {
|
|
8839
|
+
if (element.kind === "PageArticle" || element.kind === "article") {
|
|
8840
|
+
articles.push(raw);
|
|
8841
|
+
return false;
|
|
8842
|
+
}
|
|
8843
|
+
}, true)) return;
|
|
8844
|
+
const title = labelText(root.find("h1").first().text());
|
|
8845
|
+
const authored = root.children(".prose").length === 1 ? root.children(".prose") : root;
|
|
8846
|
+
const renderedParagraphs = authored.find("p").toArray().filter((node) => !$(node).parents("pre,button,nav,aside,footer").length).map((node) => labelText($(node).text())).filter(Boolean);
|
|
8847
|
+
const visibleCode = root.find("pre").toArray().map((node) => renderedCode($, node));
|
|
8848
|
+
const candidates = articles.filter((article) => {
|
|
8849
|
+
const headings = [], paragraphs = [], code = [], disclosureLabels = [];
|
|
8850
|
+
const complete2 = visitFlightTree(document, article, (element, _raw, budget) => {
|
|
8851
|
+
if (element.kind === "Accordion") {
|
|
8852
|
+
const label = flightLiteralText(document, element.props.title, 0, false, budget);
|
|
8853
|
+
if (label !== null) disclosureLabels.push(labelText(label));
|
|
8854
|
+
}
|
|
8855
|
+
if (element.kind === "p") paragraphs.push(labelText(flightLiteralText(document, element.props.children, 0, false, budget) ?? ""));
|
|
8856
|
+
const block = flightCode(document, element, budget);
|
|
8857
|
+
if (block) {
|
|
8858
|
+
code.push(codeText(block.value));
|
|
8859
|
+
return false;
|
|
8860
|
+
}
|
|
8861
|
+
});
|
|
8862
|
+
const completeHeadings = visitFlightTree(document, article, (element, _raw, budget) => {
|
|
8863
|
+
if (element.kind === "Accordion" || ["CodeBlock", "pre", "Pre"].includes(element.kind)) return false;
|
|
8864
|
+
const heading = /^h[1-6]$/.test(element.kind) ? element.kind : element.kind === "Heading" ? element.props.as : void 0;
|
|
8865
|
+
if (typeof heading === "string" && /^h[1-6]$/.test(heading)) headings.push(`${heading}:${labelText(flightLiteralText(document, element.props.children, 0, false, budget) ?? "")}`);
|
|
8866
|
+
});
|
|
8867
|
+
const renderedHeadings = root.find("h1,h2,h3,h4,h5,h6").toArray().filter((node) => {
|
|
8868
|
+
const control = $(node).children("button[aria-expanded][aria-controls]").first();
|
|
8869
|
+
if (!control.length || !disclosureLabels.includes(labelText(control.text()))) return true;
|
|
8870
|
+
const copy = $(node).clone();
|
|
8871
|
+
copy.find("button").remove();
|
|
8872
|
+
const id = control.attr("id"), target2 = control.attr("aria-controls");
|
|
8873
|
+
const panel = root.find("[id]").filter((_index, candidate) => $(candidate).attr("id") === target2);
|
|
8874
|
+
return Boolean(copy.text().trim() || !id || panel.length !== 1 || panel.attr("aria-labelledby") !== id);
|
|
8875
|
+
}).map((node) => `${node.name}:${labelText($(node).text())}`);
|
|
8876
|
+
return complete2 && completeHeadings && title && headings[0] === `h1:${title}` && headings.length === renderedHeadings.length && headings.every((heading, index) => heading === renderedHeadings[index]) && isOrderedSubsequence(renderedParagraphs, paragraphs) && isOrderedSubsequence(visibleCode, code);
|
|
8877
|
+
});
|
|
8878
|
+
if (candidates.length !== 1) return;
|
|
8879
|
+
recoverFlightDisclosures($, root, document, candidates[0], projectionBudget);
|
|
8880
|
+
const sourceGroups = [];
|
|
8881
|
+
if (!visitFlightTree(document, candidates[0], (element, _raw, budget) => {
|
|
8882
|
+
if (element.kind !== "Tabs") return;
|
|
8883
|
+
if (!hasStaticProps(document, element, ["items", "defaultIndex", "groupId", "persist"])) {
|
|
8884
|
+
sourceGroups.push([]);
|
|
8885
|
+
return false;
|
|
8886
|
+
}
|
|
8887
|
+
const children = flightValue(document, element.props.children);
|
|
8888
|
+
const nodes = flightElement(document, children) ? [children] : Array.isArray(children) ? children : [];
|
|
8889
|
+
const group = [];
|
|
8890
|
+
for (const raw of nodes) {
|
|
8891
|
+
const tab = flightElement(document, raw);
|
|
8892
|
+
const label = tab?.props.value ?? tab?.props.title;
|
|
8893
|
+
const code = tab?.kind === "Tab" && hasStaticProps(document, tab, ["value", "title"]) ? flightTabCode(document, tab.props.children, 0, budget) : null;
|
|
8894
|
+
if (typeof label !== "string" || !label.trim() || !code?.length) {
|
|
8895
|
+
sourceGroups.push([]);
|
|
8896
|
+
return false;
|
|
8897
|
+
}
|
|
8898
|
+
group.push({ label: labelText(label), code });
|
|
8899
|
+
}
|
|
8900
|
+
const items = flightValue(document, element.props.items);
|
|
8901
|
+
if (items !== void 0 && (!Array.isArray(items) || JSON.stringify(items) !== JSON.stringify(group.map((tab) => tab.label))) || items === void 0 && nodes.some((raw) => typeof flightElement(document, raw)?.props.title !== "string")) sourceGroups.push([]);
|
|
8902
|
+
else sourceGroups.push(group);
|
|
8903
|
+
return false;
|
|
8904
|
+
})) return;
|
|
8905
|
+
const groups = root.find('[role="tablist"]').toArray();
|
|
8906
|
+
if (sourceGroups.length !== groups.length) return;
|
|
8907
|
+
groups.forEach((group, index) => {
|
|
8908
|
+
const tabs = $(group).find('[role="tab"]').toArray().filter((node) => $(node).closest('[role="tablist"]')[0] === group);
|
|
8909
|
+
const source = sourceGroups[index];
|
|
8910
|
+
if (!tabs.length || source.length !== tabs.length) return;
|
|
8911
|
+
const panels = [];
|
|
8912
|
+
for (const [position, tab] of tabs.entries()) {
|
|
8913
|
+
const id = $(tab).attr("id"), target2 = $(tab).attr("aria-controls");
|
|
8914
|
+
const panel = root.find("[id]").filter((_index, node) => $(node).attr("id") === target2);
|
|
8915
|
+
if (!id || !target2 || panel.length !== 1 || panel.attr("role") !== "tabpanel" || panel.attr("aria-labelledby") !== id || !panel.parents().toArray().includes($(group).parent()[0]) || labelText($(tab).text()) !== source[position].label || panel.is('[aria-busy="true"]') || panel.find('[aria-busy="true"],[role="progressbar"]').length) return;
|
|
8916
|
+
if (panel.text().trim() || panel.children().length) {
|
|
8917
|
+
const copy = panel.clone();
|
|
8918
|
+
copy.find("pre,button,style,script").remove();
|
|
8919
|
+
const blocks = panel.find("pre").toArray().map((node) => renderedCode($, node));
|
|
8920
|
+
if (copy.text().trim() || blocks.length !== source[position].code.length || !blocks.every((block, index2) => block === codeText(source[position].code[index2].value))) return;
|
|
8921
|
+
}
|
|
8922
|
+
panels.push(panel);
|
|
8923
|
+
}
|
|
8924
|
+
if (new Set(panels.map((panel) => panel[0])).size !== panels.length) return;
|
|
8925
|
+
panels.forEach((panel, position) => {
|
|
8926
|
+
if (panel.text().trim() || panel.children().length) return;
|
|
8927
|
+
for (const block of source[position].code) {
|
|
8928
|
+
if (!chargeProjectedText(projectionBudget, block.value)) return;
|
|
8929
|
+
}
|
|
8930
|
+
for (const block of source[position].code) {
|
|
8931
|
+
const pre = $("<pre></pre>").append($("<code></code>").text(block.value));
|
|
8932
|
+
if (block.language) pre.attr("data-language", block.language);
|
|
8933
|
+
panel.append(pre);
|
|
8934
|
+
}
|
|
8935
|
+
});
|
|
8936
|
+
});
|
|
8937
|
+
const declarations2 = [];
|
|
8938
|
+
if (!visitFlightTree(document, candidates[0], (element, _raw, budget) => {
|
|
8939
|
+
const code = flightCode(document, element, budget);
|
|
8940
|
+
if (code) {
|
|
8941
|
+
declarations2.push(code);
|
|
8942
|
+
return false;
|
|
8943
|
+
}
|
|
8944
|
+
})) return;
|
|
8945
|
+
root.find("pre").each((_index, node) => {
|
|
8946
|
+
const payload = renderedCode($, node);
|
|
8947
|
+
const matches = declarations2.filter((code) => codeText(code.value) === payload);
|
|
8948
|
+
const languages = new Set(matches.map((code) => code.language ?? ""));
|
|
8949
|
+
const language = matches[0]?.language;
|
|
8950
|
+
if (languages.size !== 1 || !language || $(node).attr("language") || $(node).attr("data-language") || $(node).find('code[language],code[data-language],code[class*="language-"],code[class*="lang-"]').length || /(?:^|\s)(?:language-|lang-)/.test($(node).attr("class") ?? "")) return;
|
|
8951
|
+
$(node).attr("data-language", language);
|
|
8952
|
+
});
|
|
8953
|
+
}
|
|
8954
|
+
function sourceTabs(nodes) {
|
|
8955
|
+
return nodes.filter((node) => node.name === "Tabs").map((group) => {
|
|
8956
|
+
const result = [];
|
|
8957
|
+
for (const tab of group.children ?? []) {
|
|
8958
|
+
if (tab.type === "text" && !tab.value?.trim()) continue;
|
|
8959
|
+
if (tab.name !== "Tab") return [];
|
|
8960
|
+
const label = tab.attributes?.find((attribute) => attribute.type === "mdxJsxAttribute" && attribute.name === "value")?.value;
|
|
8961
|
+
if (typeof label !== "string" || !label.trim() || tab.attributes?.some((attribute) => attribute.type !== "mdxJsxAttribute" || !["value", "title"].includes(attribute.name ?? "") || typeof attribute.value !== "string")) return [];
|
|
8962
|
+
const content = (tab.children ?? []).filter((child) => child.type !== "text" || child.value?.trim());
|
|
8963
|
+
if (!content.length || content.some((child) => child.type !== "code")) return [];
|
|
8964
|
+
result.push({ label: labelText(label), code: content });
|
|
8965
|
+
}
|
|
8966
|
+
return result;
|
|
8967
|
+
});
|
|
8968
|
+
}
|
|
8969
|
+
function recoverFlightArticleCode($, root) {
|
|
8970
|
+
root.find("[data-thally-static-disclosure-heading]").removeAttr("data-thally-static-disclosure-heading");
|
|
8971
|
+
if (root.find('[role="tablist"]').length > 256 || root.find('[role="tab"]').length > 1024) return;
|
|
8972
|
+
const projectionBudget = expansionBudget();
|
|
8973
|
+
recoverFlightTreeTabs($, root, projectionBudget);
|
|
8974
|
+
const renderedHeadings = root.find("h1,h2,h3,h4,h5,h6").toArray().filter((node) => $(node).attr("data-thally-static-disclosure-heading") === void 0);
|
|
8975
|
+
const headingText = renderedHeadings.map((node) => labelText($(node).text()));
|
|
8976
|
+
const existingCode = root.find("pre").toArray().map((node) => renderedCode($, node));
|
|
8977
|
+
if (!headingText.length || !existingCode.length) return;
|
|
8978
|
+
const prose = root.clone();
|
|
8979
|
+
prose.find("pre,button,script,style,nav,footer,aside").remove();
|
|
8980
|
+
const renderedProse = labelText(prose.text());
|
|
8981
|
+
const candidates = [];
|
|
8982
|
+
for (const source2 of flightTextRecords($)) {
|
|
8983
|
+
if (!/^#\s+\S/m.test(source2) || !/^\s*`{3,}/m.test(source2)) continue;
|
|
8984
|
+
const nodes = sourceNodes(source2);
|
|
8985
|
+
const headings = nodes.filter((node) => node.type === "heading").map((node, index) => {
|
|
8986
|
+
const text3 = labelText(sourceText(node));
|
|
8987
|
+
const anchor = /\s+\[#([A-Za-z\d_.:-]+)\]$/.exec(text3);
|
|
8988
|
+
return anchor && $(renderedHeadings[index]).attr("id") === anchor[1] ? text3.slice(0, anchor.index) : text3;
|
|
8989
|
+
});
|
|
8990
|
+
if (JSON.stringify(headings) !== JSON.stringify(headingText)) continue;
|
|
8991
|
+
let proseCursor = 0;
|
|
8992
|
+
let hasMatchingProse = true;
|
|
8993
|
+
for (const paragraph of nodes.filter((node) => node.type === "paragraph" || node.type === "tableCell")) {
|
|
8994
|
+
const text3 = labelText(sourceText(paragraph));
|
|
8995
|
+
if (!text3) continue;
|
|
8996
|
+
const position = renderedProse.indexOf(text3, proseCursor);
|
|
8997
|
+
if (position < 0) {
|
|
8998
|
+
hasMatchingProse = false;
|
|
8999
|
+
break;
|
|
9000
|
+
}
|
|
9001
|
+
proseCursor = position + text3.length;
|
|
9002
|
+
}
|
|
9003
|
+
if (!hasMatchingProse) continue;
|
|
9004
|
+
const sourceCode2 = nodes.filter((node) => node.type === "code");
|
|
9005
|
+
if (matchesSourceCodeSequence(existingCode, sourceCode2)) candidates.push({ nodes, groups: sourceTabs(nodes) });
|
|
9006
|
+
}
|
|
9007
|
+
if (candidates.length !== 1) return;
|
|
9008
|
+
const source = candidates[0];
|
|
9009
|
+
const groups = root.find('[role="tablist"]').toArray();
|
|
9010
|
+
if (groups.length === source.groups.length) groups.forEach((group, index) => {
|
|
9011
|
+
const tabs = $(group).find('[role="tab"]').toArray().filter((tab) => $(tab).closest('[role="tablist"]')[0] === group);
|
|
9012
|
+
const sourceGroup = source.groups[index];
|
|
9013
|
+
if (!tabs.length || tabs.length !== sourceGroup.length) return;
|
|
9014
|
+
const panels = [];
|
|
9015
|
+
for (const [position, tab] of tabs.entries()) {
|
|
9016
|
+
const control = $(tab).attr("aria-controls");
|
|
9017
|
+
const tabId = $(tab).attr("id");
|
|
9018
|
+
const panel = root.find("[id]").filter((_index, node) => $(node).attr("id") === control);
|
|
9019
|
+
if (!control || panel.length !== 1 || !panel.is('[role="tabpanel"]') || !tabId || root.find("[id]").filter((_index, node) => $(node).attr("id") === tabId).length !== 1 || panel.attr("aria-labelledby") !== tabId || !panel.parents().toArray().includes($(group).parent()[0]) || labelText($(tab).text()) !== sourceGroup[position].label || panel.is('[aria-busy="true"]') || panel.find('[aria-busy="true"],[role="progressbar"]').length) return;
|
|
9020
|
+
if (panel.text().trim() || panel.children().length) {
|
|
9021
|
+
const code = panel.find("pre").toArray().map((node) => renderedCode($, node));
|
|
9022
|
+
const clone = panel.clone();
|
|
9023
|
+
clone.find("pre,button,script,style").remove();
|
|
9024
|
+
const declared = sourceGroup[position].code;
|
|
9025
|
+
if (clone.text().trim() || code.length !== declared.length || !code.every((value, index2) => matchesSourceCode(value, declared[index2].value ?? ""))) return;
|
|
9026
|
+
}
|
|
9027
|
+
panels.push(panel);
|
|
9028
|
+
}
|
|
9029
|
+
if (new Set(panels.map((panel) => panel[0])).size !== panels.length) return;
|
|
9030
|
+
panels.forEach((panel, position) => {
|
|
9031
|
+
if (panel.text().trim() || panel.children().length) return;
|
|
9032
|
+
for (const code of sourceGroup[position].code) if (!chargeProjectedText(projectionBudget, code.value ?? "")) return;
|
|
9033
|
+
for (const code of sourceGroup[position].code) {
|
|
9034
|
+
const pre = $("<pre></pre>").append($("<code></code>").text(code.value ?? ""));
|
|
9035
|
+
if (code.lang && /^[A-Za-z0-9_+-]{1,64}$/.test(code.lang)) pre.attr("data-language", code.lang);
|
|
9036
|
+
panel.append(pre);
|
|
9037
|
+
}
|
|
9038
|
+
});
|
|
9039
|
+
});
|
|
9040
|
+
const sourceCode = source.nodes.filter((node) => node.type === "code");
|
|
9041
|
+
let cursor = 0;
|
|
9042
|
+
root.find("pre").each((_index, node) => {
|
|
9043
|
+
const payload = renderedCode($, node);
|
|
9044
|
+
while (cursor < sourceCode.length && !matchesSourceCode(payload, sourceCode[cursor].value ?? "")) cursor += 1;
|
|
9045
|
+
const code = sourceCode[cursor++];
|
|
9046
|
+
if (!code?.lang || !/^[A-Za-z0-9_+-]{1,64}$/.test(code.lang)) return;
|
|
9047
|
+
const languages = new Set(sourceCode.filter((candidate) => matchesSourceCode(payload, candidate.value ?? "")).map((candidate) => candidate.lang ?? ""));
|
|
9048
|
+
if (languages.size !== 1) return;
|
|
9049
|
+
if (!$(node).attr("language") && !$(node).attr("data-language") && !$(node).find('code[language],code[data-language],code[class*="language-"],code[class*="lang-"]').length && !/(?:^|\s)(?:language-|lang-)/.test($(node).attr("class") ?? "")) $(node).attr("data-language", code.lang);
|
|
9050
|
+
});
|
|
9051
|
+
}
|
|
9052
|
+
|
|
9053
|
+
// src/redirects.ts
|
|
9054
|
+
var LISTED = 10;
|
|
9055
|
+
function exactRoute(route) {
|
|
9056
|
+
return route.startsWith("/") && !/[?:*#()[\]{}]/.test(route) ? route.replace(/\/+$/, "") || "/" : null;
|
|
9057
|
+
}
|
|
9058
|
+
function literalRoute(route) {
|
|
9059
|
+
return exactRoute(route)?.toLowerCase() ?? null;
|
|
9060
|
+
}
|
|
9061
|
+
function resolveDotSegments(route) {
|
|
9062
|
+
const segments = [];
|
|
9063
|
+
for (const segment of route.split("/").slice(1)) {
|
|
9064
|
+
const dots = segment.replace(/%2e/gi, ".");
|
|
9065
|
+
if (dots === "..") segments.pop();
|
|
9066
|
+
else if (dots !== ".") segments.push(segment);
|
|
9067
|
+
}
|
|
9068
|
+
return `/${segments.join("/")}`;
|
|
9069
|
+
}
|
|
9070
|
+
function destinationRoute(destination) {
|
|
9071
|
+
const route = destination.startsWith("//") ? null : exactRoute(destination.split(/[?#]/, 1)[0]);
|
|
9072
|
+
return route === null ? null : resolveDotSegments(route);
|
|
9073
|
+
}
|
|
9074
|
+
function pageRoutes(pages) {
|
|
9075
|
+
return pages.flatMap((page) => [`/${page.id}`, `/${page.id.replace(/\/index$/, "")}`]);
|
|
9076
|
+
}
|
|
9077
|
+
function servedRoutes(pages) {
|
|
9078
|
+
return new Set(pageRoutes(pages).map((route) => route.toLowerCase()));
|
|
9079
|
+
}
|
|
9080
|
+
function list(sources) {
|
|
9081
|
+
return `${sources.slice(0, LISTED).join(", ")}${sources.length > LISTED ? ", ..." : ""}`;
|
|
9082
|
+
}
|
|
9083
|
+
var ROUTE_PATTERN_OPERATORS = /[+?()[\]{}]/;
|
|
9084
|
+
function dropUnroutableRedirects(config, warnings) {
|
|
9085
|
+
if (!config.redirects?.length) return config;
|
|
9086
|
+
const unmatchable = [];
|
|
9087
|
+
const redirects = config.redirects.filter((redirect) => {
|
|
9088
|
+
const source = exactRoute(redirect.source);
|
|
9089
|
+
if (source && source === exactRoute(redirect.destination)) {
|
|
9090
|
+
warnings.push({ code: "unsupported-config", message: `Self-redirect from ${redirect.source} to ${redirect.destination} was omitted.` });
|
|
9091
|
+
return false;
|
|
9092
|
+
}
|
|
9093
|
+
if (!ROUTE_PATTERN_OPERATORS.test(redirect.source)) return true;
|
|
9094
|
+
unmatchable.push(redirect.source);
|
|
9095
|
+
return false;
|
|
9096
|
+
});
|
|
9097
|
+
if (unmatchable.length > 0) {
|
|
9098
|
+
warnings.push({
|
|
9099
|
+
code: "unsupported-config",
|
|
9100
|
+
message: `Skipped ${unmatchable.length} redirect${unmatchable.length === 1 ? "" : "s"} from ${list(unmatchable)}: ${unmatchable.length === 1 ? "that address has" : "those addresses have"} a character (+ ? ( ) [ ] { }) that Next.js reads as route syntax and cannot match literally, so visits to ${unmatchable.length === 1 ? "it" : "them"} will not redirect.`
|
|
9101
|
+
});
|
|
9102
|
+
}
|
|
9103
|
+
if (redirects.length === config.redirects.length) return config;
|
|
9104
|
+
const result = { ...config, redirects };
|
|
9105
|
+
if (redirects.length === 0) delete result.redirects;
|
|
9106
|
+
return result;
|
|
9107
|
+
}
|
|
9108
|
+
function redirectChains() {
|
|
9109
|
+
const kept = /* @__PURE__ */ new Map();
|
|
9110
|
+
const terminal = /* @__PURE__ */ new Set();
|
|
9111
|
+
const has = (source) => kept.has(source) || terminal.has(source);
|
|
9112
|
+
const add = (source, destination) => {
|
|
9113
|
+
if (destination === null) terminal.add(source);
|
|
9114
|
+
else kept.set(source, destination);
|
|
9115
|
+
};
|
|
9116
|
+
const closesLoop = (source, destination) => {
|
|
9117
|
+
let end = destination;
|
|
9118
|
+
for (let steps = 0; kept.has(end); steps++) {
|
|
9119
|
+
if (steps >= kept.size) return true;
|
|
9120
|
+
end = kept.get(end);
|
|
9121
|
+
}
|
|
9122
|
+
for (let step = destination; step !== end; ) {
|
|
9123
|
+
const next = kept.get(step);
|
|
9124
|
+
kept.set(step, end);
|
|
9125
|
+
step = next;
|
|
9126
|
+
}
|
|
9127
|
+
return end === source;
|
|
9128
|
+
};
|
|
9129
|
+
return { has, add, closesLoop };
|
|
9130
|
+
}
|
|
9131
|
+
function dropConflictingRedirects(config, pages, warnings) {
|
|
9132
|
+
if (!config.redirects?.length) return config;
|
|
9133
|
+
const served = servedRoutes(pages);
|
|
9134
|
+
const servedAsWritten = new Set(pageRoutes(pages));
|
|
9135
|
+
const hidden = [];
|
|
9136
|
+
const hiddenByCase = [];
|
|
9137
|
+
const looping = [];
|
|
9138
|
+
const loopingByCase = [];
|
|
9139
|
+
const folded = redirectChains();
|
|
9140
|
+
const asWritten = redirectChains();
|
|
9141
|
+
const redirects = config.redirects.filter((redirect) => {
|
|
9142
|
+
const source = literalRoute(redirect.source);
|
|
9143
|
+
if (!source) return true;
|
|
9144
|
+
const writtenSource = exactRoute(redirect.source);
|
|
9145
|
+
if (served.has(source)) {
|
|
9146
|
+
const hides = servedAsWritten.has(writtenSource) ? hidden : hiddenByCase;
|
|
9147
|
+
hides.push(redirect.source);
|
|
9148
|
+
return false;
|
|
9149
|
+
}
|
|
9150
|
+
const writtenDestination = destinationRoute(redirect.destination);
|
|
9151
|
+
const destination = writtenDestination?.toLowerCase() ?? null;
|
|
9152
|
+
const firesFolded = !folded.has(source);
|
|
9153
|
+
const firesAsWritten = !asWritten.has(writtenSource);
|
|
9154
|
+
const loopsFolded = firesFolded && destination !== null && folded.closesLoop(source, destination);
|
|
9155
|
+
const loopsAsWritten = firesAsWritten && writtenDestination !== null && asWritten.closesLoop(writtenSource, writtenDestination);
|
|
9156
|
+
if (loopsFolded || loopsAsWritten) {
|
|
9157
|
+
const loops = loopsAsWritten ? looping : loopingByCase;
|
|
9158
|
+
loops.push(`${redirect.source} -> ${redirect.destination}`);
|
|
9159
|
+
return false;
|
|
9160
|
+
}
|
|
9161
|
+
if (firesFolded) folded.add(source, destination);
|
|
9162
|
+
if (firesAsWritten) asWritten.add(writtenSource, writtenDestination);
|
|
9163
|
+
return true;
|
|
9164
|
+
});
|
|
9165
|
+
if (hidden.length > 0) {
|
|
9166
|
+
warnings.push({
|
|
9167
|
+
code: "unsupported-config",
|
|
9168
|
+
message: `Skipped ${hidden.length} redirect${hidden.length === 1 ? "" : "s"} from ${list(hidden)}: ${hidden.length === 1 ? "that URL is" : "those URLs are"} also ${hidden.length === 1 ? "a page" : "pages"} in this site, and a redirect would hide ${hidden.length === 1 ? "it" : "them"}. To redirect instead, delete the page and add the redirect to docs.json.`
|
|
9169
|
+
});
|
|
9170
|
+
}
|
|
9171
|
+
if (hiddenByCase.length > 0) {
|
|
9172
|
+
const one = hiddenByCase.length === 1;
|
|
9173
|
+
warnings.push({
|
|
9174
|
+
code: "unsupported-config",
|
|
9175
|
+
message: `Skipped ${hiddenByCase.length} redirect${one ? "" : "s"} from ${list(hiddenByCase)}: ${one ? "that URL differs" : "those URLs differ"} only in letter case from ${one ? "a page" : "pages"} in this site, so on a server that ignores letter case ${one ? "it" : "they"} would hide ${one ? "that page" : "those pages"}. If your host matches URLs case-sensitively, add ${one ? "it" : "them"} back to docs.json.`
|
|
9176
|
+
});
|
|
9177
|
+
}
|
|
9178
|
+
if (looping.length > 0) {
|
|
9179
|
+
warnings.push({
|
|
9180
|
+
code: "unsupported-config",
|
|
9181
|
+
message: `Skipped ${looping.length} redirect${looping.length === 1 ? "" : "s"} that would send visitors in a circle: ${list(looping)}. Check these redirects in the source docs.`
|
|
9182
|
+
});
|
|
9183
|
+
}
|
|
9184
|
+
if (loopingByCase.length > 0) {
|
|
9185
|
+
const one = loopingByCase.length === 1;
|
|
7986
9186
|
warnings.push({
|
|
7987
9187
|
code: "unsupported-config",
|
|
7988
9188
|
message: `Skipped ${loopingByCase.length} redirect${one ? "" : "s"} that would send visitors in a circle on a server that ignores letter case, since the addresses involved differ only in letter case: ${list(loopingByCase)}. If your host matches URLs case-sensitively, add ${one ? "it" : "them"} back to docs.json.`
|
|
@@ -7998,7 +9198,8 @@ function dropConflictingRedirects(config, pages, warnings) {
|
|
|
7998
9198
|
var DEFAULT_MAX_PAGES = 1e3;
|
|
7999
9199
|
var DEFAULT_MAX_TOTAL_BYTES = 1e8;
|
|
8000
9200
|
var MAX_DISCOVERED_URLS = 1e5;
|
|
8001
|
-
var MAX_LOCAL_RESPONSE_BYTES =
|
|
9201
|
+
var MAX_LOCAL_RESPONSE_BYTES = 8e6;
|
|
9202
|
+
var MAX_EMBEDDED_SCHEMA_BYTES = 2e6;
|
|
8002
9203
|
var MAX_SITEMAP_DOCUMENTS = 25;
|
|
8003
9204
|
var PORTABLE_MDX_COMPONENTS = /* @__PURE__ */ new Set([
|
|
8004
9205
|
"Accordion",
|
|
@@ -8110,8 +9311,8 @@ var MINTLIFY_ARTICLE_LABELS = [
|
|
|
8110
9311
|
{ baseUrl: "Select base URL", permalink: "Navigate to header" },
|
|
8111
9312
|
{ baseUrl: "\u9009\u62E9\u57FA\u7840URL", permalink: "\u5BFC\u822A\u5230\u6807\u9898" }
|
|
8112
9313
|
];
|
|
8113
|
-
var remoteMarkdownParser =
|
|
8114
|
-
var embeddedOpenApiParser =
|
|
9314
|
+
var remoteMarkdownParser = unified4().use(remarkParse4).use(remarkMdx4);
|
|
9315
|
+
var embeddedOpenApiParser = unified4().use(remarkParse4);
|
|
8115
9316
|
function validateMigrationUrl(value) {
|
|
8116
9317
|
let url;
|
|
8117
9318
|
try {
|
|
@@ -8128,7 +9329,7 @@ function validateMigrationUrl(value) {
|
|
|
8128
9329
|
}
|
|
8129
9330
|
async function readResponseBody(response) {
|
|
8130
9331
|
const contentLength = Number(response.headers.get("content-length") ?? 0);
|
|
8131
|
-
if (contentLength > MAX_LOCAL_RESPONSE_BYTES) throw new Error("A documentation response exceeded the
|
|
9332
|
+
if (contentLength > MAX_LOCAL_RESPONSE_BYTES) throw new Error("A documentation response exceeded the 8 MB import limit.");
|
|
8132
9333
|
if (!response.body) return "";
|
|
8133
9334
|
const reader = response.body.getReader();
|
|
8134
9335
|
const chunks = [];
|
|
@@ -8139,7 +9340,7 @@ async function readResponseBody(response) {
|
|
|
8139
9340
|
size += value.byteLength;
|
|
8140
9341
|
if (size > MAX_LOCAL_RESPONSE_BYTES) {
|
|
8141
9342
|
await reader.cancel();
|
|
8142
|
-
throw new Error("A documentation response exceeded the
|
|
9343
|
+
throw new Error("A documentation response exceeded the 8 MB import limit.");
|
|
8143
9344
|
}
|
|
8144
9345
|
chunks.push(value);
|
|
8145
9346
|
}
|
|
@@ -8180,7 +9381,7 @@ function machineIndexScopePath(source, documents) {
|
|
|
8180
9381
|
if (!document) continue;
|
|
8181
9382
|
const references = [...headerLinks(document)];
|
|
8182
9383
|
if (/html/i.test(document.contentType)) {
|
|
8183
|
-
const $ =
|
|
9384
|
+
const $ = load4(document.body);
|
|
8184
9385
|
references.push(...$("link[href], a[href]").map((_index, element) => $(element).attr("href") ?? "").get().filter((href) => /\/(?:llms(?:-full)?\.txt|sitemap\.xml)(?:[?#]|$)/i.test(href)));
|
|
8185
9386
|
}
|
|
8186
9387
|
for (const reference of references) {
|
|
@@ -8291,7 +9492,7 @@ function jsonObjectAfterKey(value, key) {
|
|
|
8291
9492
|
return null;
|
|
8292
9493
|
}
|
|
8293
9494
|
function embeddedMintlifyConfig(body) {
|
|
8294
|
-
const $ =
|
|
9495
|
+
const $ = load4(body);
|
|
8295
9496
|
const flightPayloads = [];
|
|
8296
9497
|
$("script").each((_index, element) => {
|
|
8297
9498
|
const script = $(element).text();
|
|
@@ -8389,7 +9590,7 @@ function isSafePortableUrl(value) {
|
|
|
8389
9590
|
}
|
|
8390
9591
|
}
|
|
8391
9592
|
function decodeHtmlAttribute(value) {
|
|
8392
|
-
const document =
|
|
9593
|
+
const document = load4(`<i data-thally-value="${value.replace(/"/g, """)}"></i>`);
|
|
8393
9594
|
return document("i").attr("data-thally-value") ?? "";
|
|
8394
9595
|
}
|
|
8395
9596
|
function escapeMarkdownText(value, escapeTableSeparator = false) {
|
|
@@ -8475,7 +9676,7 @@ function replacePortableHtmlImages(value) {
|
|
|
8475
9676
|
if (start < cursor) continue;
|
|
8476
9677
|
const end = htmlOpeningTagEnd(value, start + match[0].length);
|
|
8477
9678
|
if (end === null) continue;
|
|
8478
|
-
const fragment =
|
|
9679
|
+
const fragment = load4(value.slice(start, end));
|
|
8479
9680
|
const image = fragment("img").first();
|
|
8480
9681
|
const source = image.attr("src");
|
|
8481
9682
|
const destination = source && isSafePortableUrl(source) ? markdownLinkDestination(source) : null;
|
|
@@ -8500,7 +9701,7 @@ function replacePortableHtmlAnchors(value) {
|
|
|
8500
9701
|
const closing = closingMatch.exec(value);
|
|
8501
9702
|
if (!closing) continue;
|
|
8502
9703
|
const end = closing.index + closing[0].length;
|
|
8503
|
-
const fragment =
|
|
9704
|
+
const fragment = load4(value.slice(start, end));
|
|
8504
9705
|
const anchor = fragment("a").first();
|
|
8505
9706
|
const href = anchor.attr("href");
|
|
8506
9707
|
const label = escapeMarkdownText(anchor.text().replace(/\s+/g, " ").trim());
|
|
@@ -8795,7 +9996,7 @@ function stripMintlifyDocumentationIndex(body) {
|
|
|
8795
9996
|
return lines.slice(index).join("\n");
|
|
8796
9997
|
}
|
|
8797
9998
|
function extractEmbeddedOpenApi(content) {
|
|
8798
|
-
if (Buffer.byteLength(content, "utf8") >
|
|
9999
|
+
if (Buffer.byteLength(content, "utf8") > MAX_EMBEDDED_SCHEMA_BYTES) return { content };
|
|
8799
10000
|
try {
|
|
8800
10001
|
const root = embeddedOpenApiParser.parse(content);
|
|
8801
10002
|
const candidates = (root.children ?? []).flatMap((node2) => {
|
|
@@ -8828,10 +10029,10 @@ function extractEmbeddedOpenApi(content) {
|
|
|
8828
10029
|
const serialized = JSON.stringify(document, (_key, value) => {
|
|
8829
10030
|
values += 1;
|
|
8830
10031
|
if (typeof value === "string") textLength += value.length;
|
|
8831
|
-
if (values > 1e5 || textLength >
|
|
10032
|
+
if (values > 1e5 || textLength > MAX_EMBEDDED_SCHEMA_BYTES || typeof value === "number" && !Number.isFinite(value)) throw new Error("OpenAPI document exceeds portable data limits.");
|
|
8832
10033
|
return value;
|
|
8833
10034
|
});
|
|
8834
|
-
if (Buffer.byteLength(serialized, "utf8") >
|
|
10035
|
+
if (Buffer.byteLength(serialized, "utf8") > MAX_EMBEDDED_SCHEMA_BYTES) return { content };
|
|
8835
10036
|
const before = content.slice(0, start).replace(/(?:^|\n)##\s+OpenAPI\s*\n\s*$/i, "\n");
|
|
8836
10037
|
const after = content.slice(end);
|
|
8837
10038
|
return {
|
|
@@ -8939,8 +10140,12 @@ function mergeEmbeddedOpenApi(fragments) {
|
|
|
8939
10140
|
return new TextEncoder().encode(stringifyYaml2(combined));
|
|
8940
10141
|
}
|
|
8941
10142
|
function migrationHtmlArticle(body) {
|
|
8942
|
-
const $ =
|
|
10143
|
+
const $ = load4(body);
|
|
8943
10144
|
const root = ["main article", "article", "main", '[role="main"]', "body"].map((selector) => $(selector).first()).find((candidate) => candidate.length);
|
|
10145
|
+
projectProtectedEmails($, root);
|
|
10146
|
+
recoverFlightArticleCode($, root);
|
|
10147
|
+
const assets = [];
|
|
10148
|
+
const svgProjections = new Map(root.find("svg").toArray().map((element) => [element, projectMigrationSvg($.html(element))]));
|
|
8944
10149
|
root.find([
|
|
8945
10150
|
"script",
|
|
8946
10151
|
"style",
|
|
@@ -9001,10 +10206,25 @@ function migrationHtmlArticle(body) {
|
|
|
9001
10206
|
projection.append(list2);
|
|
9002
10207
|
select.replaceWith(projection);
|
|
9003
10208
|
});
|
|
9004
|
-
|
|
10209
|
+
projectCapturedDisclosures($, root);
|
|
10210
|
+
root.find("svg").each((_index, element) => {
|
|
10211
|
+
const svg = $(element);
|
|
10212
|
+
if (svg.parents("svg,button,nav,footer,aside").length) return;
|
|
10213
|
+
const projection = svgProjections.get(element);
|
|
10214
|
+
if (!projection) return;
|
|
10215
|
+
const image = $("<img>").attr("src", `/${projection.asset.path}`).attr("alt", projection.alternative);
|
|
10216
|
+
for (const attribute of ["id", "width", "height"]) {
|
|
10217
|
+
const value = svg.attr(attribute);
|
|
10218
|
+
if (value !== void 0) image.attr(attribute, value);
|
|
10219
|
+
}
|
|
10220
|
+
assets.push(projection.asset);
|
|
10221
|
+
svg.replaceWith(image);
|
|
10222
|
+
});
|
|
10223
|
+
projectCapturedTabs($, root);
|
|
10224
|
+
return { $, root, assets };
|
|
9005
10225
|
}
|
|
9006
10226
|
function htmlPage(document, id, options = {}) {
|
|
9007
|
-
const { $, root } = migrationHtmlArticle(document.body);
|
|
10227
|
+
const { $, root, assets } = migrationHtmlArticle(document.body);
|
|
9008
10228
|
const links = root.find("a[href]").map((_index, element) => $(element).attr("href") ?? "").get().filter(Boolean);
|
|
9009
10229
|
const scopedTitle = options.omitDocumentHeading ? root.find("h1").first().text().trim() : "";
|
|
9010
10230
|
const title = scopedTitle || $("main h1, article h1, h1").first().text().trim() || $('meta[property="og:title"]').attr("content")?.trim() || $("title").text().split("|")[0].trim();
|
|
@@ -9043,6 +10263,7 @@ function htmlPage(document, id, options = {}) {
|
|
|
9043
10263
|
root.find("img[src]").each((_index, element) => {
|
|
9044
10264
|
const src = $(element).attr("src");
|
|
9045
10265
|
if (!src) return;
|
|
10266
|
+
if (assets.some((asset) => src === `/${asset.path}`)) return;
|
|
9046
10267
|
try {
|
|
9047
10268
|
const resolved = new URL(src, document.finalUrl);
|
|
9048
10269
|
if (["http:", "https:"].includes(resolved.protocol)) {
|
|
@@ -9054,7 +10275,15 @@ function htmlPage(document, id, options = {}) {
|
|
|
9054
10275
|
$(element).removeAttr("src");
|
|
9055
10276
|
}
|
|
9056
10277
|
});
|
|
9057
|
-
const turndown = new TurndownService({
|
|
10278
|
+
const turndown = new TurndownService({
|
|
10279
|
+
codeBlockStyle: "fenced",
|
|
10280
|
+
emDelimiter: "_",
|
|
10281
|
+
headingStyle: "atx",
|
|
10282
|
+
preformattedCode: true,
|
|
10283
|
+
// Turndown chooses its blank rule before custom rules. Empty source anchor
|
|
10284
|
+
// leaves still carry navigation identity, including captured tab controls.
|
|
10285
|
+
blankReplacement: (_content, node) => options.preserveAnchors ? anchor(node) : ""
|
|
10286
|
+
});
|
|
9058
10287
|
let isConvertingTableCell = false;
|
|
9059
10288
|
turndown.remove(["script", "style", "noscript"]);
|
|
9060
10289
|
turndown.addRule("migration-literal-table-code", {
|
|
@@ -9095,6 +10324,22 @@ ${content}
|
|
|
9095
10324
|
|
|
9096
10325
|
${anchor(element)}${heading ? `${"#".repeat(Number(heading[1]))} ${content.trim()}` : content}
|
|
9097
10326
|
|
|
10327
|
+
`;
|
|
10328
|
+
}
|
|
10329
|
+
});
|
|
10330
|
+
turndown.addRule("migration-flow-link", {
|
|
10331
|
+
filter: (node) => node.nodeName === "A" && node.hasAttribute("href") && Boolean(node.querySelector("div,p,picture,figure,blockquote,pre,table,ul,ol,h1,h2,h3,h4,h5,h6")),
|
|
10332
|
+
replacement: (content, node) => {
|
|
10333
|
+
const element = node;
|
|
10334
|
+
const href = migrationImageAttribute(element.getAttribute("href") ?? "");
|
|
10335
|
+
return `
|
|
10336
|
+
|
|
10337
|
+
${anchor(element)}<Card href="${href}">
|
|
10338
|
+
|
|
10339
|
+
${content.trim()}
|
|
10340
|
+
|
|
10341
|
+
</Card>
|
|
10342
|
+
|
|
9098
10343
|
`;
|
|
9099
10344
|
}
|
|
9100
10345
|
});
|
|
@@ -9145,7 +10390,7 @@ ${content.trim()}
|
|
|
9145
10390
|
const element = node;
|
|
9146
10391
|
const className = element.className;
|
|
9147
10392
|
const tag = /admonition-(?:danger)/.test(className) ? "Error" : /admonition-(?:caution|warning)/.test(className) ? "Warning" : /admonition-info/.test(className) ? "Info" : "Note";
|
|
9148
|
-
const fragment =
|
|
10393
|
+
const fragment = load4(element.outerHTML);
|
|
9149
10394
|
const clone = fragment(".theme-admonition").first();
|
|
9150
10395
|
const title2 = clone.find('[class*="admonitionHeading"],.admonition-heading').first();
|
|
9151
10396
|
const titleText = title2.text().trim();
|
|
@@ -9166,11 +10411,15 @@ ${titleText ? `**${escapeMarkdownText(titleText)}**
|
|
|
9166
10411
|
filter: (node) => node.nodeName === "DIV" && node.classList.contains("tabs-container"),
|
|
9167
10412
|
replacement: (_content, node) => {
|
|
9168
10413
|
const element = node;
|
|
9169
|
-
const fragment =
|
|
10414
|
+
const fragment = load4(element.outerHTML);
|
|
9170
10415
|
const container = fragment(".tabs-container").first();
|
|
9171
10416
|
const labels2 = container.children("ul.tabs").children("li").toArray().map((item) => fragment(item).text().trim() || "Tab");
|
|
9172
10417
|
const panels = container.find('[role="tabpanel"]').toArray().filter((panel) => fragment(panel).closest(".tabs-container")[0] === container[0]);
|
|
9173
10418
|
if (panels.length === 0) return _content;
|
|
10419
|
+
const residual = container.clone();
|
|
10420
|
+
residual.children("ul.tabs").remove();
|
|
10421
|
+
residual.find('[role="tabpanel"]').remove();
|
|
10422
|
+
if (residual.text().trim() || residual.find("a[href],pre,img,svg,table,video,iframe,input,select,textarea").length) return _content;
|
|
9174
10423
|
const tabs = panels.map((panel, index) => {
|
|
9175
10424
|
const panelId = fragment(panel).attr("id");
|
|
9176
10425
|
const tab = panelId ? container.find('[role="tab"]').toArray().find((item) => fragment(item).attr("aria-controls") === panelId) : void 0;
|
|
@@ -9188,13 +10437,40 @@ ${anchor(element)}<Tabs>
|
|
|
9188
10437
|
${tabs.join("\n\n")}
|
|
9189
10438
|
</Tabs>
|
|
9190
10439
|
|
|
10440
|
+
`;
|
|
10441
|
+
}
|
|
10442
|
+
});
|
|
10443
|
+
turndown.addRule("migration-complete-captured-tabs", {
|
|
10444
|
+
filter: (node) => node.hasAttribute("data-thally-static-tabs"),
|
|
10445
|
+
replacement: (_content, node) => {
|
|
10446
|
+
const element = node;
|
|
10447
|
+
const fragment = load4(element.outerHTML);
|
|
10448
|
+
const container = fragment("[data-thally-static-tabs]").first();
|
|
10449
|
+
const panels = container.find("[data-thally-static-tab]").toArray().filter((panel) => fragment(panel).closest("[data-thally-static-tabs]")[0] === container[0]);
|
|
10450
|
+
const tabs = panels.map((panel) => {
|
|
10451
|
+
const selection = fragment(panel);
|
|
10452
|
+
const title2 = migrationImageAttribute(selection.attr("data-thally-static-tab"));
|
|
10453
|
+
const id2 = selection.attr("id");
|
|
10454
|
+
const panelAnchor = options.preserveAnchors && id2 ? `<a id="${migrationImageAttribute(id2)}" />
|
|
10455
|
+
|
|
10456
|
+
` : "";
|
|
10457
|
+
return `<Tab title="${title2}">
|
|
10458
|
+
${panelAnchor}${turndown.turndown(selection.html() ?? "").trim()}
|
|
10459
|
+
</Tab>`;
|
|
10460
|
+
});
|
|
10461
|
+
return `
|
|
10462
|
+
|
|
10463
|
+
${anchor(element)}<Tabs>
|
|
10464
|
+
${tabs.join("\n\n")}
|
|
10465
|
+
</Tabs>
|
|
10466
|
+
|
|
9191
10467
|
`;
|
|
9192
10468
|
}
|
|
9193
10469
|
});
|
|
9194
10470
|
turndown.addRule("gfm-table", {
|
|
9195
10471
|
filter: "table",
|
|
9196
10472
|
replacement: (_content, node) => {
|
|
9197
|
-
const fragment =
|
|
10473
|
+
const fragment = load4(node.outerHTML);
|
|
9198
10474
|
const rows = fragment("tr").toArray().map((row) => fragment(row).children("th,td").toArray().map((cell) => {
|
|
9199
10475
|
const wasConvertingTableCell = isConvertingTableCell;
|
|
9200
10476
|
isConvertingTableCell = true;
|
|
@@ -9220,7 +10496,7 @@ ${normalized.slice(1).map((row) => `| ${row.join(" | ")} |`).join("\n")}
|
|
|
9220
10496
|
filter: (node) => node.nodeName === "PRE",
|
|
9221
10497
|
replacement: (_content, node) => {
|
|
9222
10498
|
const element = node;
|
|
9223
|
-
const fragment =
|
|
10499
|
+
const fragment = load4(element.outerHTML);
|
|
9224
10500
|
const tokenLines = fragment(".token-line").toArray();
|
|
9225
10501
|
const code = (tokenLines.length > 0 ? tokenLines.map((line) => fragment(line).text()).join("\n") : fragment("pre").text()).replace(/\n$/, "");
|
|
9226
10502
|
const language = ["code", "pre"].flatMap((selector) => {
|
|
@@ -9245,7 +10521,7 @@ ${fence}
|
|
|
9245
10521
|
const escape = turndown.escape.bind(turndown);
|
|
9246
10522
|
turndown.escape = (text3) => isConvertingTableCell ? escape(text3.replace(/[<>{}]/g, (character) => ({ "<": "<", ">": ">", "{": "{", "}": "}" })[character])) : escape(text3).replace(/[<{}]/g, (match) => `\\${match}`);
|
|
9247
10523
|
const body = `${documentHeadingAnchor}${turndown.turndown(root.html() ?? "").trim()}`;
|
|
9248
|
-
if (!title || body.length < 40 && $("article").length === 0) return { page: null, links };
|
|
10524
|
+
if (!title || body.length < 40 && $("article").length === 0) return { page: null, links, assets };
|
|
9249
10525
|
return {
|
|
9250
10526
|
page: {
|
|
9251
10527
|
id,
|
|
@@ -9256,11 +10532,12 @@ ${fence}
|
|
|
9256
10532
|
body,
|
|
9257
10533
|
source: document.finalUrl.toString()
|
|
9258
10534
|
},
|
|
9259
|
-
links
|
|
10535
|
+
links,
|
|
10536
|
+
assets
|
|
9260
10537
|
};
|
|
9261
10538
|
}
|
|
9262
10539
|
function htmlNavigationLinks(document) {
|
|
9263
|
-
const $ =
|
|
10540
|
+
const $ = load4(document.body);
|
|
9264
10541
|
return $('.nav-tabs a[href], nav a[href], aside a[href], [role="navigation"] a[href]').map((_index, element) => $(element).attr("href") ?? "").get().filter(Boolean);
|
|
9265
10542
|
}
|
|
9266
10543
|
function normalizedLinkLabel(value) {
|
|
@@ -9268,7 +10545,7 @@ function normalizedLinkLabel(value) {
|
|
|
9268
10545
|
}
|
|
9269
10546
|
function readDocusaurusSidebar(document) {
|
|
9270
10547
|
if (!/html/i.test(document.contentType)) return null;
|
|
9271
|
-
const $ =
|
|
10548
|
+
const $ = load4(document.body);
|
|
9272
10549
|
const sidebar = $("ul.theme-doc-sidebar-menu").first();
|
|
9273
10550
|
if (sidebar.length === 0) return null;
|
|
9274
10551
|
function readList(list2) {
|
|
@@ -9304,7 +10581,7 @@ function docusaurusSidebarHrefs(snapshot) {
|
|
|
9304
10581
|
return hrefs;
|
|
9305
10582
|
}
|
|
9306
10583
|
function deriveDocusaurusScope(source, document, submittedScopePath) {
|
|
9307
|
-
const $ =
|
|
10584
|
+
const $ = load4(document.body);
|
|
9308
10585
|
const sidebar = readDocusaurusSidebar(document);
|
|
9309
10586
|
const internalPaths = docusaurusSidebarHrefs(sidebar).flatMap((href) => {
|
|
9310
10587
|
try {
|
|
@@ -9434,7 +10711,7 @@ function docusaurusNavigationFromSnapshots(snapshots, pages, scopePath) {
|
|
|
9434
10711
|
return { tabs };
|
|
9435
10712
|
}
|
|
9436
10713
|
function htmlTopLevelNavigation(document, source, scopePath) {
|
|
9437
|
-
const $ =
|
|
10714
|
+
const $ = load4(document.body);
|
|
9438
10715
|
const collectCandidates = (selector) => {
|
|
9439
10716
|
const candidates2 = [];
|
|
9440
10717
|
$(selector).each((_containerIndex, container) => {
|
|
@@ -9495,7 +10772,7 @@ function markdownLinks(body) {
|
|
|
9495
10772
|
return [...body.matchAll(/\[[^\]]+\]\(([^)\s]+)(?:\s+['"][^'"]*['"])?\)/g)].map((match) => match[1]);
|
|
9496
10773
|
}
|
|
9497
10774
|
function sitemapLinks(body) {
|
|
9498
|
-
const $ =
|
|
10775
|
+
const $ = load4(body, { xmlMode: true });
|
|
9499
10776
|
return $("url > loc, sitemap > loc").map((_index, element) => $(element).text().trim()).get().filter(Boolean);
|
|
9500
10777
|
}
|
|
9501
10778
|
function robotsSitemaps(body) {
|
|
@@ -9534,7 +10811,7 @@ async function migrateUrl(options) {
|
|
|
9534
10811
|
const platform = options.platform ?? detectUrlPlatform(scopedHtmlProbe ?? initial);
|
|
9535
10812
|
let docusaurusHtmlProbe = platform === "docusaurus" ? scopedHtmlProbe : null;
|
|
9536
10813
|
if (docusaurusHtmlProbe && !readDocusaurusSidebar(docusaurusHtmlProbe)) {
|
|
9537
|
-
const $ =
|
|
10814
|
+
const $ = load4(docusaurusHtmlProbe.body);
|
|
9538
10815
|
const docsHref = $("nav a[href]").toArray().map((element) => ({
|
|
9539
10816
|
href: $(element).attr("href"),
|
|
9540
10817
|
label: normalizedLinkLabel($(element).text())
|
|
@@ -9566,6 +10843,7 @@ async function migrateUrl(options) {
|
|
|
9566
10843
|
const queue = [source];
|
|
9567
10844
|
const queued = /* @__PURE__ */ new Set([candidateIdentity(source)]);
|
|
9568
10845
|
const warnings = [];
|
|
10846
|
+
const importedAssets = /* @__PURE__ */ new Map();
|
|
9569
10847
|
const fetchedSitemaps = /* @__PURE__ */ new Set();
|
|
9570
10848
|
const docusaurusSidebars = docusaurusDiscovery?.sidebar ? [docusaurusDiscovery.sidebar] : [];
|
|
9571
10849
|
const docusaurusRedirects = [];
|
|
@@ -9733,7 +11011,7 @@ async function migrateUrl(options) {
|
|
|
9733
11011
|
const extracted = htmlPage(document, id);
|
|
9734
11012
|
if (extracted.page) extracted.page.navigationId = navigationId;
|
|
9735
11013
|
const sidebar = platform === "docusaurus" ? readDocusaurusSidebar(document) : null;
|
|
9736
|
-
return { candidate, page: extracted.page, links: extracted.links, base: document.finalUrl, sidebar, failure: false };
|
|
11014
|
+
return { candidate, page: extracted.page, links: extracted.links, assets: extracted.assets, base: document.finalUrl, sidebar, failure: false };
|
|
9737
11015
|
}));
|
|
9738
11016
|
for (const result of results) {
|
|
9739
11017
|
if (result.failure) {
|
|
@@ -9748,6 +11026,9 @@ async function migrateUrl(options) {
|
|
|
9748
11026
|
const sourceIdentity = result.page ? candidateIdentity(new URL(result.page.source)) : null;
|
|
9749
11027
|
if (result.page && sourceIdentity && !seenSources.has(sourceIdentity) && !seenIds.has(result.page.id) && pages.length < maxPages) {
|
|
9750
11028
|
pages.push(result.page);
|
|
11029
|
+
if ("assets" in result && result.assets) {
|
|
11030
|
+
for (const asset of result.assets) importedAssets.set(asset.path, asset);
|
|
11031
|
+
}
|
|
9751
11032
|
if ("pageWarnings" in result && result.pageWarnings) {
|
|
9752
11033
|
for (const message of result.pageWarnings) warnings.push({ code: "unsupported-config", message, source: result.page.source });
|
|
9753
11034
|
}
|
|
@@ -9841,7 +11122,7 @@ async function migrateUrl(options) {
|
|
|
9841
11122
|
sourceKind: "url",
|
|
9842
11123
|
platform,
|
|
9843
11124
|
pages,
|
|
9844
|
-
assets: openApiAsset ? [{ path: "openapi.yaml", content: openApiAsset }] : [],
|
|
11125
|
+
assets: [...importedAssets.values(), ...openApiAsset ? [{ path: "openapi.yaml", content: openApiAsset }] : []],
|
|
9845
11126
|
docsConfig,
|
|
9846
11127
|
...sourceMintlifyConfig ? {
|
|
9847
11128
|
site: {
|
|
@@ -9931,12 +11212,12 @@ async function sourceRefOversizeReason(repo, fetcher = defaultMigrationFetcher)
|
|
|
9931
11212
|
return null;
|
|
9932
11213
|
}
|
|
9933
11214
|
function findSourceRefDocsRoot(repositoryDir) {
|
|
9934
|
-
for (const
|
|
11215
|
+
for (const directory2 of [join(repositoryDir, "docs"), repositoryDir]) {
|
|
9935
11216
|
try {
|
|
9936
|
-
const config = join(
|
|
9937
|
-
if (lstatSync5(
|
|
11217
|
+
const config = join(directory2, "docs.json");
|
|
11218
|
+
if (lstatSync5(directory2).isSymbolicLink() || !lstatSync5(config).isFile() || lstatSync5(config).size > DOCS_JSON_MAX_BYTES) continue;
|
|
9938
11219
|
const parsed = JSON.parse(readFileSync5(config, "utf8"));
|
|
9939
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && "navigation" in parsed) return
|
|
11220
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && "navigation" in parsed) return directory2;
|
|
9940
11221
|
} catch {
|
|
9941
11222
|
}
|
|
9942
11223
|
}
|
|
@@ -9948,9 +11229,9 @@ function sanitizeAndMeasure(root) {
|
|
|
9948
11229
|
let removedLinks = 0;
|
|
9949
11230
|
const stack = [root];
|
|
9950
11231
|
while (stack.length > 0) {
|
|
9951
|
-
const
|
|
9952
|
-
for (const entry of readdirSync3(
|
|
9953
|
-
const path = join(
|
|
11232
|
+
const directory2 = stack.pop();
|
|
11233
|
+
for (const entry of readdirSync3(directory2, { withFileTypes: true })) {
|
|
11234
|
+
const path = join(directory2, entry.name);
|
|
9954
11235
|
if (entry.isSymbolicLink()) {
|
|
9955
11236
|
unlinkSync(path);
|
|
9956
11237
|
removedLinks++;
|
|
@@ -10150,15 +11431,15 @@ var DOCUSAURUS_CONFIG_FILENAMES = [
|
|
|
10150
11431
|
"docusaurus.config.ts",
|
|
10151
11432
|
"docusaurus.config.mjs"
|
|
10152
11433
|
];
|
|
10153
|
-
function hasDocusaurusConfig(
|
|
11434
|
+
function hasDocusaurusConfig(directory2) {
|
|
10154
11435
|
return DOCUSAURUS_CONFIG_FILENAMES.some((filename) => {
|
|
10155
|
-
const path = resolveWithin(
|
|
11436
|
+
const path = resolveWithin(directory2, filename);
|
|
10156
11437
|
return existsSync5(path) && lstatSync6(path).isFile();
|
|
10157
11438
|
});
|
|
10158
11439
|
}
|
|
10159
|
-
function hasMintlifyConfig(
|
|
11440
|
+
function hasMintlifyConfig(directory2) {
|
|
10160
11441
|
return ["docs.json", "mint.json"].some((filename) => {
|
|
10161
|
-
const path = resolveWithin(
|
|
11442
|
+
const path = resolveWithin(directory2, filename);
|
|
10162
11443
|
if (!existsSync5(path) || !lstatSync6(path).isFile()) return false;
|
|
10163
11444
|
if (filename === "mint.json") return true;
|
|
10164
11445
|
try {
|
|
@@ -10169,9 +11450,9 @@ function hasMintlifyConfig(directory) {
|
|
|
10169
11450
|
}
|
|
10170
11451
|
});
|
|
10171
11452
|
}
|
|
10172
|
-
function countMarkdownPages(
|
|
11453
|
+
function countMarkdownPages(directory2, limit = 2e4) {
|
|
10173
11454
|
let count = 0;
|
|
10174
|
-
const stack = [
|
|
11455
|
+
const stack = [directory2];
|
|
10175
11456
|
while (stack.length > 0 && count < limit) {
|
|
10176
11457
|
const current = stack.pop();
|
|
10177
11458
|
let entries;
|
|
@@ -10235,11 +11516,11 @@ function findMintlifyProjectRoot(repositoryDir, docsDir, warnings) {
|
|
|
10235
11516
|
}
|
|
10236
11517
|
}
|
|
10237
11518
|
if (candidates.length === 0) return null;
|
|
10238
|
-
return pickPreferredDocsRoot(candidates, repositoryDir, "Mintlify", warnings, (
|
|
11519
|
+
return pickPreferredDocsRoot(candidates, repositoryDir, "Mintlify", warnings, (directory2) => existsSync5(resolveWithin(directory2, "docs.json")) ? 1 : 0);
|
|
10239
11520
|
}
|
|
10240
|
-
function hasFernConfig(
|
|
11521
|
+
function hasFernConfig(directory2) {
|
|
10241
11522
|
return ["docs.yml", "fern.config.json"].every((filename) => {
|
|
10242
|
-
const path = resolveWithin(
|
|
11523
|
+
const path = resolveWithin(directory2, filename);
|
|
10243
11524
|
return existsSync5(path) && lstatSync6(path).isFile();
|
|
10244
11525
|
});
|
|
10245
11526
|
}
|
|
@@ -10394,8 +11675,8 @@ function primaryDocusaurusDocsDirectory(projectRoot) {
|
|
|
10394
11675
|
function docusaurusArchiveRoots(projectRoot, repositoryDir, warnings) {
|
|
10395
11676
|
const archives = [];
|
|
10396
11677
|
const relativeRoot = relative6(repositoryDir, projectRoot).replace(/\\/g, "/");
|
|
10397
|
-
const directoryNames = (
|
|
10398
|
-
const path = resolveWithin(projectRoot,
|
|
11678
|
+
const directoryNames = (directory2) => {
|
|
11679
|
+
const path = resolveWithin(projectRoot, directory2);
|
|
10399
11680
|
if (!existsSync5(path) || !lstatSync6(path).isDirectory()) return [];
|
|
10400
11681
|
return readdirSync4(path, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink()).map((entry) => entry.name).sort();
|
|
10401
11682
|
};
|
|
@@ -10419,8 +11700,8 @@ function docusaurusArchiveRoots(projectRoot, repositoryDir, warnings) {
|
|
|
10419
11700
|
return existsSync5(path) && lstatSync6(path).isFile();
|
|
10420
11701
|
});
|
|
10421
11702
|
};
|
|
10422
|
-
const add = (
|
|
10423
|
-
const docsDir = [relativeRoot,
|
|
11703
|
+
const add = (directory2, routePrefix, label, sidebar) => {
|
|
11704
|
+
const docsDir = [relativeRoot, directory2].filter(Boolean).join("/");
|
|
10424
11705
|
archives.push({ docsDir, routePrefix, label, ...sidebar ? { sidebarPath: sidebar } : {} });
|
|
10425
11706
|
};
|
|
10426
11707
|
for (const version of versions) add(`versioned_docs/${version}`, version.slice("version-".length), `Version ${version.slice("version-".length)}`, sidebarPath(version));
|
|
@@ -10710,11 +11991,11 @@ function detectRepositoryPlatform(repositoryDir, docsDir) {
|
|
|
10710
11991
|
if (["pages/_meta.json", "_meta.json"].some((name) => existsSync5(resolveWithin(repositoryDir, name)))) return "nextra";
|
|
10711
11992
|
return "unknown";
|
|
10712
11993
|
}
|
|
10713
|
-
function containsMarkdown(
|
|
11994
|
+
function containsMarkdown(directory2, depth = 0) {
|
|
10714
11995
|
if (depth > 4) return false;
|
|
10715
|
-
for (const entry of readdirSync4(
|
|
11996
|
+
for (const entry of readdirSync4(directory2, { withFileTypes: true })) {
|
|
10716
11997
|
if (isIgnoredDirectory(entry.name) || entry.isSymbolicLink()) continue;
|
|
10717
|
-
const path = resolveWithin(
|
|
11998
|
+
const path = resolveWithin(directory2, entry.name);
|
|
10718
11999
|
if (entry.isFile() && [".md", ".mdx"].includes(extname6(entry.name).toLowerCase())) return true;
|
|
10719
12000
|
if (entry.isDirectory() && containsMarkdown(path, depth + 1)) return true;
|
|
10720
12001
|
}
|
|
@@ -10738,11 +12019,11 @@ function scanFiles(root, confinementRoot = root, warnings, rank, budget = MAX_SO
|
|
|
10738
12019
|
confinementReal = confinementRoot;
|
|
10739
12020
|
}
|
|
10740
12021
|
const visitedRealPaths = /* @__PURE__ */ new Set();
|
|
10741
|
-
function visit(
|
|
12022
|
+
function visit(directory2, logicalDirectory = directory2) {
|
|
10742
12023
|
if (files.length >= walkCap) return;
|
|
10743
12024
|
let directoryReal;
|
|
10744
12025
|
try {
|
|
10745
|
-
directoryReal = realpathSync4(
|
|
12026
|
+
directoryReal = realpathSync4(directory2);
|
|
10746
12027
|
} catch {
|
|
10747
12028
|
return;
|
|
10748
12029
|
}
|
|
@@ -10750,23 +12031,23 @@ function scanFiles(root, confinementRoot = root, warnings, rank, budget = MAX_SO
|
|
|
10750
12031
|
visitedRealPaths.add(directoryReal);
|
|
10751
12032
|
let entries;
|
|
10752
12033
|
try {
|
|
10753
|
-
entries = readdirSync4(
|
|
12034
|
+
entries = readdirSync4(directory2, { withFileTypes: true });
|
|
10754
12035
|
} catch {
|
|
10755
12036
|
return;
|
|
10756
12037
|
}
|
|
10757
12038
|
for (const entry of entries) {
|
|
10758
12039
|
if (files.length >= walkCap) return;
|
|
10759
12040
|
if (isIgnoredContentDirectory(entry.name)) {
|
|
10760
|
-
if (warnings && entry.isDirectory() && !entry.isSymbolicLink() && containsMarkdown(resolveWithin(
|
|
12041
|
+
if (warnings && entry.isDirectory() && !entry.isSymbolicLink() && containsMarkdown(resolveWithin(directory2, entry.name))) {
|
|
10761
12042
|
warnings.push({
|
|
10762
12043
|
code: "unsupported-config",
|
|
10763
12044
|
message: `The "${entry.name}" directory was skipped during migration but contains Markdown/MDX files; if any are real pages, move them out or pass --docs-dir to include them.`,
|
|
10764
|
-
source: relative6(root, resolveWithin(
|
|
12045
|
+
source: relative6(root, resolveWithin(directory2, entry.name)).replace(/\\/g, "/")
|
|
10765
12046
|
});
|
|
10766
12047
|
}
|
|
10767
12048
|
continue;
|
|
10768
12049
|
}
|
|
10769
|
-
const path = resolveWithin(
|
|
12050
|
+
const path = resolveWithin(directory2, entry.name);
|
|
10770
12051
|
const logicalPath = resolveWithin(logicalDirectory, entry.name);
|
|
10771
12052
|
if (entry.isSymbolicLink()) {
|
|
10772
12053
|
let real;
|
|
@@ -11078,11 +12359,11 @@ function resolveMintlifyApiSpecs(mintlifyConfig, files, warnings, remoteSpecs, n
|
|
|
11078
12359
|
const seen = /* @__PURE__ */ new Set();
|
|
11079
12360
|
const remoteByKey = /* @__PURE__ */ new Map();
|
|
11080
12361
|
const mountDirectory = (remote, reference) => {
|
|
11081
|
-
const
|
|
11082
|
-
if (!remote || !
|
|
11083
|
-
const mount = remote.directories?.find((existing) => existing.directory ===
|
|
12362
|
+
const directory2 = reference.directory?.replace(/^\/+|\/+$/g, "");
|
|
12363
|
+
if (!remote || !directory2) return;
|
|
12364
|
+
const mount = remote.directories?.find((existing) => existing.directory === directory2);
|
|
11084
12365
|
if (!mount) {
|
|
11085
|
-
remote.directories = [...remote.directories ?? [], { directory, ...reference.operations ? { operations: reference.operations } : {} }];
|
|
12366
|
+
remote.directories = [...remote.directories ?? [], { directory: directory2, ...reference.operations ? { operations: reference.operations } : {} }];
|
|
11086
12367
|
} else if (mount.operations && reference.operations) {
|
|
11087
12368
|
mount.operations = [.../* @__PURE__ */ new Set([...mount.operations, ...reference.operations])];
|
|
11088
12369
|
} else {
|
|
@@ -11267,7 +12548,7 @@ function servedOperations(source, parsed) {
|
|
|
11267
12548
|
return operation ? [operation] : [];
|
|
11268
12549
|
});
|
|
11269
12550
|
}
|
|
11270
|
-
var mountPrefix = (
|
|
12551
|
+
var mountPrefix = (directory2) => directory2.replace(/^\/+|\/+$/g, "").toLowerCase();
|
|
11271
12552
|
function apiOperationLinkMap(sources, docsConfig, otherMounts = []) {
|
|
11272
12553
|
const map = /* @__PURE__ */ new Map();
|
|
11273
12554
|
const prefixLandings = /* @__PURE__ */ new Map();
|
|
@@ -13363,12 +14644,12 @@ ${warnings.map((warning) => `- ${warning.message}`).join("\n")}`);
|
|
|
13363
14644
|
}
|
|
13364
14645
|
}
|
|
13365
14646
|
}
|
|
13366
|
-
const repositoryAssets = platform === "docusaurus" && configuredDocsDir && !options.docusaurusSkipAssets ? ["static", "public"].flatMap((
|
|
13367
|
-
const root = resolveWithin(docusaurusAssetRoot,
|
|
14647
|
+
const repositoryAssets = platform === "docusaurus" && configuredDocsDir && !options.docusaurusSkipAssets ? ["static", "public"].flatMap((directory2) => {
|
|
14648
|
+
const root = resolveWithin(docusaurusAssetRoot, directory2);
|
|
13368
14649
|
if (!existsSync5(root) || !lstatSync6(root).isDirectory()) return [];
|
|
13369
14650
|
return scanFiles(root, repositoryDir).map((file) => ({
|
|
13370
14651
|
...file,
|
|
13371
|
-
relativePath: `${
|
|
14652
|
+
relativePath: `${directory2}/${file.relativePath}`
|
|
13372
14653
|
}));
|
|
13373
14654
|
}) : [];
|
|
13374
14655
|
const assetCandidates = [];
|
|
@@ -13560,7 +14841,7 @@ ${warnings.map((warning) => `- ${warning.message}`).join("\n")}`);
|
|
|
13560
14841
|
message: `Skipped ${rootStyleProjection.omittedSelectors} stylesheet selector${rootStyleProjection.omittedSelectors === 1 ? "" : "s"} that target platform-owned or unreferenced markup. Recreate any intentional shell customization with Thally configuration.`
|
|
13561
14842
|
});
|
|
13562
14843
|
if (rootStyleProjection.css.trim()) {
|
|
13563
|
-
const identity =
|
|
14844
|
+
const identity = createHash4("sha256").update(componentSourceIdentity(options.sourceUrl, repositoryDir, mintlifyProjectRoot)).digest("hex").slice(0, 12);
|
|
13564
14845
|
const assetPath = `migrated/${identity}/style.css`;
|
|
13565
14846
|
const content = Buffer.from(rootStyleProjection.css);
|
|
13566
14847
|
assets.push({ path: assetPath, content });
|
|
@@ -14426,367 +15707,62 @@ function mergeMigrationConfig(existing, incoming) {
|
|
|
14426
15707
|
...uniqueTab.pages ?? [],
|
|
14427
15708
|
...uniqueTab.groups ?? []
|
|
14428
15709
|
];
|
|
14429
|
-
if (uniqueTab.pages?.length) {
|
|
14430
|
-
target2.pages = [...target2.pages ?? target2.groups ?? [], ...incomingRootNodes];
|
|
14431
|
-
delete target2.groups;
|
|
14432
|
-
} else if (uniqueTab.groups?.length) {
|
|
14433
|
-
if (target2.pages) target2.pages = [...target2.pages, ...uniqueTab.groups];
|
|
14434
|
-
else target2.groups = [...target2.groups ?? [], ...uniqueTab.groups];
|
|
14435
|
-
}
|
|
14436
|
-
}
|
|
14437
|
-
const changelog = existing.tabs.find((tab) => tab.tab.toLowerCase() === "changelog") ?? incoming.tabs.find((tab) => tab.tab.toLowerCase() === "changelog");
|
|
14438
|
-
if (changelog) tabs.push(changelog);
|
|
14439
|
-
const i18n = existing.i18n || incoming.i18n ? {
|
|
14440
|
-
defaultLocale: existing.i18n?.defaultLocale ?? incoming.i18n?.defaultLocale ?? "en",
|
|
14441
|
-
locales: [...new Map(
|
|
14442
|
-
[...existing.i18n?.locales ?? [], ...incoming.i18n?.locales ?? []].map((locale) => [locale.code, locale])
|
|
14443
|
-
).values()]
|
|
14444
|
-
} : void 0;
|
|
14445
|
-
return {
|
|
14446
|
-
...incoming,
|
|
14447
|
-
...existing,
|
|
14448
|
-
tabs,
|
|
14449
|
-
// Collection presentation belongs to the imported information
|
|
14450
|
-
// architecture; starter defaults must not coerce source dropdowns to tabs.
|
|
14451
|
-
navigation: incoming.navigation ?? existing.navigation,
|
|
14452
|
-
...existing.stylesheets?.length || incoming.stylesheets?.length ? { stylesheets: [.../* @__PURE__ */ new Set([...existing.stylesheets ?? [], ...incoming.stylesheets ?? []])] } : {},
|
|
14453
|
-
...i18n ? { i18n } : {},
|
|
14454
|
-
// Existing providers win per provider; imported ones fill the gaps.
|
|
14455
|
-
// A malformed (string/array) existing value must not spread into index keys.
|
|
14456
|
-
...isIntegrationsObject(existing.integrations) || isIntegrationsObject(incoming.integrations) ? {
|
|
14457
|
-
integrations: {
|
|
14458
|
-
...isIntegrationsObject(incoming.integrations) ? incoming.integrations : {},
|
|
14459
|
-
...isIntegrationsObject(existing.integrations) ? existing.integrations : {}
|
|
14460
|
-
}
|
|
14461
|
-
} : {}
|
|
14462
|
-
};
|
|
14463
|
-
}
|
|
14464
|
-
function renderMigrationFiles(bundle, options = {}) {
|
|
14465
|
-
const config = options.existingConfig ? mergeMigrationConfig(options.existingConfig, bundle.docsConfig) : bundle.docsConfig;
|
|
14466
|
-
return [
|
|
14467
|
-
...bundle.pages.map((page) => ({
|
|
14468
|
-
path: `src/content/${page.id}.mdx`,
|
|
14469
|
-
content: renderPage(bundle, page)
|
|
14470
|
-
})),
|
|
14471
|
-
...bundle.assets.map((asset) => ({ path: asset.projectRelative ? asset.path : `public/${asset.path}`, content: asset.content })),
|
|
14472
|
-
...(bundle.componentFiles ?? []).flatMap((file) => file.path === "src/mdx/custom-components.tsx" && options.existingComponentRegistry !== void 0 && typeof file.content === "string" ? mergeComponentRegistry(options.existingComponentRegistry, file.content) : [file]),
|
|
14473
|
-
...bundle.quarantinedFiles ?? [],
|
|
14474
|
-
{ path: "docs.json", content: `${JSON.stringify(config, null, 2)}
|
|
14475
|
-
` }
|
|
14476
|
-
];
|
|
14477
|
-
}
|
|
14478
|
-
|
|
14479
|
-
// src/url-run.ts
|
|
14480
|
-
import { createHash as createHash3 } from "crypto";
|
|
14481
|
-
import { load as load6 } from "cheerio";
|
|
14482
|
-
import remarkParse4 from "remark-parse";
|
|
14483
|
-
import remarkMdx4 from "remark-mdx";
|
|
14484
|
-
import { unified as unified4 } from "unified";
|
|
14485
|
-
|
|
14486
|
-
// src/svg-policy.ts
|
|
14487
|
-
import { Parser } from "htmlparser2";
|
|
14488
|
-
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
14489
|
-
var XLINK_NAMESPACE = "http://www.w3.org/1999/xlink";
|
|
14490
|
-
var ALLOWED_ELEMENTS = /* @__PURE__ */ new Set([
|
|
14491
|
-
"svg",
|
|
14492
|
-
"g",
|
|
14493
|
-
"defs",
|
|
14494
|
-
"symbol",
|
|
14495
|
-
"use",
|
|
14496
|
-
"title",
|
|
14497
|
-
"desc",
|
|
14498
|
-
"path",
|
|
14499
|
-
"rect",
|
|
14500
|
-
"circle",
|
|
14501
|
-
"ellipse",
|
|
14502
|
-
"line",
|
|
14503
|
-
"polyline",
|
|
14504
|
-
"polygon",
|
|
14505
|
-
"text",
|
|
14506
|
-
"tspan",
|
|
14507
|
-
"textpath",
|
|
14508
|
-
"lineargradient",
|
|
14509
|
-
"radialgradient",
|
|
14510
|
-
"stop",
|
|
14511
|
-
"clippath",
|
|
14512
|
-
"mask",
|
|
14513
|
-
"pattern",
|
|
14514
|
-
"marker",
|
|
14515
|
-
"filter",
|
|
14516
|
-
"feblend",
|
|
14517
|
-
"fecolormatrix",
|
|
14518
|
-
"fecomponenttransfer",
|
|
14519
|
-
"fecomposite",
|
|
14520
|
-
"feconvolvematrix",
|
|
14521
|
-
"fediffuselighting",
|
|
14522
|
-
"fedisplacementmap",
|
|
14523
|
-
"fedistantlight",
|
|
14524
|
-
"fedropshadow",
|
|
14525
|
-
"feflood",
|
|
14526
|
-
"fefunca",
|
|
14527
|
-
"fefuncb",
|
|
14528
|
-
"fefuncg",
|
|
14529
|
-
"fefuncr",
|
|
14530
|
-
"fegaussianblur",
|
|
14531
|
-
"femerge",
|
|
14532
|
-
"femergenode",
|
|
14533
|
-
"femorphology",
|
|
14534
|
-
"feoffset",
|
|
14535
|
-
"fepointlight",
|
|
14536
|
-
"fespecularlighting",
|
|
14537
|
-
"fespotlight",
|
|
14538
|
-
"fetile",
|
|
14539
|
-
"feturbulence"
|
|
14540
|
-
]);
|
|
14541
|
-
var ALLOWED_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
14542
|
-
"xmlns",
|
|
14543
|
-
"xmlns:xlink",
|
|
14544
|
-
"xml:space",
|
|
14545
|
-
"version",
|
|
14546
|
-
"baseprofile",
|
|
14547
|
-
"id",
|
|
14548
|
-
"class",
|
|
14549
|
-
"viewbox",
|
|
14550
|
-
"preserveaspectratio",
|
|
14551
|
-
"width",
|
|
14552
|
-
"height",
|
|
14553
|
-
"x",
|
|
14554
|
-
"y",
|
|
14555
|
-
"x1",
|
|
14556
|
-
"y1",
|
|
14557
|
-
"x2",
|
|
14558
|
-
"y2",
|
|
14559
|
-
"cx",
|
|
14560
|
-
"cy",
|
|
14561
|
-
"r",
|
|
14562
|
-
"rx",
|
|
14563
|
-
"ry",
|
|
14564
|
-
"d",
|
|
14565
|
-
"points",
|
|
14566
|
-
"pathlength",
|
|
14567
|
-
"transform",
|
|
14568
|
-
"transform-origin",
|
|
14569
|
-
"fill",
|
|
14570
|
-
"fill-opacity",
|
|
14571
|
-
"fill-rule",
|
|
14572
|
-
"stroke",
|
|
14573
|
-
"stroke-width",
|
|
14574
|
-
"stroke-opacity",
|
|
14575
|
-
"stroke-linecap",
|
|
14576
|
-
"stroke-linejoin",
|
|
14577
|
-
"stroke-miterlimit",
|
|
14578
|
-
"stroke-dasharray",
|
|
14579
|
-
"stroke-dashoffset",
|
|
14580
|
-
"opacity",
|
|
14581
|
-
"color",
|
|
14582
|
-
"display",
|
|
14583
|
-
"visibility",
|
|
14584
|
-
"overflow",
|
|
14585
|
-
"clip-path",
|
|
14586
|
-
"clip-rule",
|
|
14587
|
-
"clippathunits",
|
|
14588
|
-
"mask",
|
|
14589
|
-
"maskunits",
|
|
14590
|
-
"maskcontentunits",
|
|
14591
|
-
"filter",
|
|
14592
|
-
"filterunits",
|
|
14593
|
-
"primitiveunits",
|
|
14594
|
-
"marker-start",
|
|
14595
|
-
"marker-mid",
|
|
14596
|
-
"marker-end",
|
|
14597
|
-
"markerwidth",
|
|
14598
|
-
"markerheight",
|
|
14599
|
-
"markerunits",
|
|
14600
|
-
"refx",
|
|
14601
|
-
"refy",
|
|
14602
|
-
"orient",
|
|
14603
|
-
"patternunits",
|
|
14604
|
-
"patterncontentunits",
|
|
14605
|
-
"patterntransform",
|
|
14606
|
-
"gradientunits",
|
|
14607
|
-
"gradienttransform",
|
|
14608
|
-
"spreadmethod",
|
|
14609
|
-
"fx",
|
|
14610
|
-
"fy",
|
|
14611
|
-
"fr",
|
|
14612
|
-
"offset",
|
|
14613
|
-
"stop-color",
|
|
14614
|
-
"stop-opacity",
|
|
14615
|
-
"font-family",
|
|
14616
|
-
"font-size",
|
|
14617
|
-
"font-weight",
|
|
14618
|
-
"font-style",
|
|
14619
|
-
"font-variant",
|
|
14620
|
-
"letter-spacing",
|
|
14621
|
-
"word-spacing",
|
|
14622
|
-
"text-anchor",
|
|
14623
|
-
"dominant-baseline",
|
|
14624
|
-
"alignment-baseline",
|
|
14625
|
-
"baseline-shift",
|
|
14626
|
-
"text-decoration",
|
|
14627
|
-
"dx",
|
|
14628
|
-
"dy",
|
|
14629
|
-
"rotate",
|
|
14630
|
-
"textlength",
|
|
14631
|
-
"lengthadjust",
|
|
14632
|
-
"startoffset",
|
|
14633
|
-
"writing-mode",
|
|
14634
|
-
"direction",
|
|
14635
|
-
"unicode-bidi",
|
|
14636
|
-
"shape-rendering",
|
|
14637
|
-
"text-rendering",
|
|
14638
|
-
"image-rendering",
|
|
14639
|
-
"color-interpolation",
|
|
14640
|
-
"color-interpolation-filters",
|
|
14641
|
-
"vector-effect",
|
|
14642
|
-
"paint-order",
|
|
14643
|
-
"mix-blend-mode",
|
|
14644
|
-
"isolation",
|
|
14645
|
-
"in",
|
|
14646
|
-
"in2",
|
|
14647
|
-
"result",
|
|
14648
|
-
"stddeviation",
|
|
14649
|
-
"mode",
|
|
14650
|
-
"type",
|
|
14651
|
-
"values",
|
|
14652
|
-
"tablevalues",
|
|
14653
|
-
"slope",
|
|
14654
|
-
"intercept",
|
|
14655
|
-
"amplitude",
|
|
14656
|
-
"exponent",
|
|
14657
|
-
"operator",
|
|
14658
|
-
"k1",
|
|
14659
|
-
"k2",
|
|
14660
|
-
"k3",
|
|
14661
|
-
"k4",
|
|
14662
|
-
"radius",
|
|
14663
|
-
"scale",
|
|
14664
|
-
"xchannelselector",
|
|
14665
|
-
"ychannelselector",
|
|
14666
|
-
"basefrequency",
|
|
14667
|
-
"numoctaves",
|
|
14668
|
-
"seed",
|
|
14669
|
-
"stitchtiles",
|
|
14670
|
-
"flood-color",
|
|
14671
|
-
"flood-opacity",
|
|
14672
|
-
"lighting-color",
|
|
14673
|
-
"surfacescale",
|
|
14674
|
-
"diffuseconstant",
|
|
14675
|
-
"specularconstant",
|
|
14676
|
-
"specularexponent",
|
|
14677
|
-
"kernelmatrix",
|
|
14678
|
-
"kernelunitlength",
|
|
14679
|
-
"order",
|
|
14680
|
-
"divisor",
|
|
14681
|
-
"bias",
|
|
14682
|
-
"targetx",
|
|
14683
|
-
"targety",
|
|
14684
|
-
"edgemode",
|
|
14685
|
-
"preservealpha",
|
|
14686
|
-
"azimuth",
|
|
14687
|
-
"elevation",
|
|
14688
|
-
"z",
|
|
14689
|
-
"pointsatx",
|
|
14690
|
-
"pointsaty",
|
|
14691
|
-
"pointsatz",
|
|
14692
|
-
"limitingconeangle",
|
|
14693
|
-
"aria-hidden",
|
|
14694
|
-
"aria-label",
|
|
14695
|
-
"role",
|
|
14696
|
-
"focusable",
|
|
14697
|
-
// Validated below: only in-document fragment references.
|
|
14698
|
-
"href",
|
|
14699
|
-
"xlink:href"
|
|
14700
|
-
]);
|
|
14701
|
-
function hasExternalReference(value) {
|
|
14702
|
-
if (value.includes("\\")) return true;
|
|
14703
|
-
const compact = value.replace(/[\u0000- ]/gu, "").toLowerCase();
|
|
14704
|
-
if (/(?:java|vb)script:|data:|expression\(|@import|<|>/u.test(compact)) {
|
|
14705
|
-
return true;
|
|
14706
|
-
}
|
|
14707
|
-
for (const match of compact.matchAll(/url\(([^)]*)\)/gu)) {
|
|
14708
|
-
if (!/^["']?#[a-z0-9_.:-]+["']?$/u.test(match[1])) return true;
|
|
14709
|
-
}
|
|
14710
|
-
return compact.replace(/url\(([^)]*)\)/gu, "").includes("url(");
|
|
14711
|
-
}
|
|
14712
|
-
function utf8SvgText(content) {
|
|
14713
|
-
const hasUtf8Bom = content[0] === 239 && content[1] === 187 && content[2] === 191;
|
|
14714
|
-
const body = hasUtf8Bom ? content.subarray(3) : content;
|
|
14715
|
-
if (body[0] === 254 && body[1] === 255 || body[0] === 255 && body[1] === 254 || body[0] === 0 && body[1] === 0 || body.includes(0)) {
|
|
14716
|
-
return null;
|
|
14717
|
-
}
|
|
14718
|
-
const text3 = body.toString("utf8");
|
|
14719
|
-
if (text3.includes("\uFFFD")) return null;
|
|
14720
|
-
const declaration = /^<\?xml\b[^>]*\?>/iu.exec(text3);
|
|
14721
|
-
if (declaration) {
|
|
14722
|
-
const encoding = /\bencoding\s*=\s*["']([^"']*)["']/iu.exec(declaration[0]);
|
|
14723
|
-
if (encoding && !/^utf-?8$/iu.test(encoding[1].trim())) return null;
|
|
14724
|
-
} else if (/<\?xml\b/iu.test(text3)) {
|
|
14725
|
-
return null;
|
|
15710
|
+
if (uniqueTab.pages?.length) {
|
|
15711
|
+
target2.pages = [...target2.pages ?? target2.groups ?? [], ...incomingRootNodes];
|
|
15712
|
+
delete target2.groups;
|
|
15713
|
+
} else if (uniqueTab.groups?.length) {
|
|
15714
|
+
if (target2.pages) target2.pages = [...target2.pages, ...uniqueTab.groups];
|
|
15715
|
+
else target2.groups = [...target2.groups ?? [], ...uniqueTab.groups];
|
|
15716
|
+
}
|
|
14726
15717
|
}
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
|
|
14731
|
-
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
|
|
14736
|
-
|
|
14737
|
-
|
|
15718
|
+
const changelog = existing.tabs.find((tab) => tab.tab.toLowerCase() === "changelog") ?? incoming.tabs.find((tab) => tab.tab.toLowerCase() === "changelog");
|
|
15719
|
+
if (changelog) tabs.push(changelog);
|
|
15720
|
+
const i18n = existing.i18n || incoming.i18n ? {
|
|
15721
|
+
defaultLocale: existing.i18n?.defaultLocale ?? incoming.i18n?.defaultLocale ?? "en",
|
|
15722
|
+
locales: [...new Map(
|
|
15723
|
+
[...existing.i18n?.locales ?? [], ...incoming.i18n?.locales ?? []].map((locale) => [locale.code, locale])
|
|
15724
|
+
).values()]
|
|
15725
|
+
} : void 0;
|
|
15726
|
+
return {
|
|
15727
|
+
...incoming,
|
|
15728
|
+
...existing,
|
|
15729
|
+
tabs,
|
|
15730
|
+
// Collection presentation belongs to the imported information
|
|
15731
|
+
// architecture; starter defaults must not coerce source dropdowns to tabs.
|
|
15732
|
+
navigation: incoming.navigation ?? existing.navigation,
|
|
15733
|
+
...existing.stylesheets?.length || incoming.stylesheets?.length ? { stylesheets: [.../* @__PURE__ */ new Set([...existing.stylesheets ?? [], ...incoming.stylesheets ?? []])] } : {},
|
|
15734
|
+
...i18n ? { i18n } : {},
|
|
15735
|
+
// Existing providers win per provider; imported ones fill the gaps.
|
|
15736
|
+
// A malformed (string/array) existing value must not spread into index keys.
|
|
15737
|
+
...isIntegrationsObject(existing.integrations) || isIntegrationsObject(incoming.integrations) ? {
|
|
15738
|
+
integrations: {
|
|
15739
|
+
...isIntegrationsObject(incoming.integrations) ? incoming.integrations : {},
|
|
15740
|
+
...isIntegrationsObject(existing.integrations) ? existing.integrations : {}
|
|
15741
|
+
}
|
|
15742
|
+
} : {}
|
|
14738
15743
|
};
|
|
14739
|
-
const parser3 = new Parser(
|
|
14740
|
-
{
|
|
14741
|
-
onopentag(name, attributes) {
|
|
14742
|
-
const element = name.toLowerCase();
|
|
14743
|
-
if (depth === 0) {
|
|
14744
|
-
if (sawRoot || element !== "svg") fail();
|
|
14745
|
-
sawRoot = true;
|
|
14746
|
-
}
|
|
14747
|
-
depth += 1;
|
|
14748
|
-
openStarts.push(parser3.startIndex);
|
|
14749
|
-
if (element.includes(":") || !ALLOWED_ELEMENTS.has(element)) fail();
|
|
14750
|
-
for (const [rawName, value] of Object.entries(attributes)) {
|
|
14751
|
-
const attribute = rawName.toLowerCase();
|
|
14752
|
-
if (!ALLOWED_ATTRIBUTES.has(attribute)) {
|
|
14753
|
-
fail();
|
|
14754
|
-
continue;
|
|
14755
|
-
}
|
|
14756
|
-
if (attribute === "xmlns" && value !== SVG_NAMESPACE) fail();
|
|
14757
|
-
if (attribute === "xmlns:xlink" && value !== XLINK_NAMESPACE) fail();
|
|
14758
|
-
if ((attribute === "href" || attribute === "xlink:href") && !/^#[A-Za-z0-9_.:-]+$/u.test(value.trim())) {
|
|
14759
|
-
fail();
|
|
14760
|
-
}
|
|
14761
|
-
if (hasExternalReference(value)) fail();
|
|
14762
|
-
}
|
|
14763
|
-
},
|
|
14764
|
-
onclosetag(_name, isImplied) {
|
|
14765
|
-
depth -= 1;
|
|
14766
|
-
const start = openStarts.pop();
|
|
14767
|
-
if (isImplied && start !== parser3.startIndex) fail();
|
|
14768
|
-
},
|
|
14769
|
-
// DOCTYPE (and with it custom entities) or any other declaration other
|
|
14770
|
-
// than the XML prolog.
|
|
14771
|
-
onprocessinginstruction(name) {
|
|
14772
|
-
if (name.toLowerCase() !== "?xml") fail();
|
|
14773
|
-
},
|
|
14774
|
-
oncdatastart: fail,
|
|
14775
|
-
ontext(value) {
|
|
14776
|
-
if (depth === 0 && value.trim()) fail();
|
|
14777
|
-
},
|
|
14778
|
-
onerror: fail
|
|
14779
|
-
},
|
|
14780
|
-
{ xmlMode: true, decodeEntities: true, recognizeSelfClosing: true }
|
|
14781
|
-
);
|
|
14782
|
-
try {
|
|
14783
|
-
parser3.write(text3);
|
|
14784
|
-
parser3.end();
|
|
14785
|
-
} catch {
|
|
14786
|
-
return false;
|
|
14787
|
-
}
|
|
14788
|
-
return isPassive && sawRoot && depth === 0;
|
|
14789
15744
|
}
|
|
15745
|
+
function renderMigrationFiles(bundle, options = {}) {
|
|
15746
|
+
const config = options.existingConfig ? mergeMigrationConfig(options.existingConfig, bundle.docsConfig) : bundle.docsConfig;
|
|
15747
|
+
return [
|
|
15748
|
+
...bundle.pages.map((page) => ({
|
|
15749
|
+
path: `src/content/${page.id}.mdx`,
|
|
15750
|
+
content: renderPage(bundle, page)
|
|
15751
|
+
})),
|
|
15752
|
+
...bundle.assets.map((asset) => ({ path: asset.projectRelative ? asset.path : `public/${asset.path}`, content: asset.content })),
|
|
15753
|
+
...(bundle.componentFiles ?? []).flatMap((file) => file.path === "src/mdx/custom-components.tsx" && options.existingComponentRegistry !== void 0 && typeof file.content === "string" ? mergeComponentRegistry(options.existingComponentRegistry, file.content) : [file]),
|
|
15754
|
+
...bundle.quarantinedFiles ?? [],
|
|
15755
|
+
{ path: "docs.json", content: `${JSON.stringify(config, null, 2)}
|
|
15756
|
+
` }
|
|
15757
|
+
];
|
|
15758
|
+
}
|
|
15759
|
+
|
|
15760
|
+
// src/url-run.ts
|
|
15761
|
+
import { createHash as createHash6 } from "crypto";
|
|
15762
|
+
import { load as load8 } from "cheerio";
|
|
15763
|
+
import remarkParse5 from "remark-parse";
|
|
15764
|
+
import remarkMdx5 from "remark-mdx";
|
|
15765
|
+
import { unified as unified5 } from "unified";
|
|
14790
15766
|
|
|
14791
15767
|
// src/url-asset-cache.ts
|
|
14792
15768
|
function createMigrationAssetCache() {
|
|
@@ -14856,17 +15832,17 @@ function cloneUrlMigrationCheckpoint(checkpoint) {
|
|
|
14856
15832
|
}
|
|
14857
15833
|
|
|
14858
15834
|
// src/url-navigation.ts
|
|
14859
|
-
import { load as
|
|
15835
|
+
import { load as load6 } from "cheerio";
|
|
14860
15836
|
|
|
14861
15837
|
// src/url-scope.ts
|
|
14862
|
-
import { load as
|
|
15838
|
+
import { load as load5 } from "cheerio";
|
|
14863
15839
|
function inferUrlMigrationScope(capture) {
|
|
14864
15840
|
const source = capture.finalUrl;
|
|
14865
15841
|
let end = source.pathname.length;
|
|
14866
15842
|
while (end > 0 && source.pathname.charCodeAt(end - 1) === 47) end--;
|
|
14867
15843
|
const parent = end < source.pathname.length ? source.pathname.slice(0, end) || "/" : source.pathname.slice(0, source.pathname.lastIndexOf("/")) || "/";
|
|
14868
15844
|
if (!/html/i.test(capture.contentType) || Buffer.byteLength(capture.body) > 8e6) return { scopePath: parent, evidence: "source-parent" };
|
|
14869
|
-
const $ =
|
|
15845
|
+
const $ = load5(capture.body);
|
|
14870
15846
|
const ancestor = (path) => path === "/" || source.pathname === path || source.pathname.startsWith(`${path}/`);
|
|
14871
15847
|
const observed = (reference) => {
|
|
14872
15848
|
if (!reference || reference.length > 8192) return void 0;
|
|
@@ -14970,7 +15946,7 @@ function flightRecords(stream) {
|
|
|
14970
15946
|
return records;
|
|
14971
15947
|
}
|
|
14972
15948
|
function mintlifyNavigation(body, base, locale, selectedScope) {
|
|
14973
|
-
const $ =
|
|
15949
|
+
const $ = load6(body);
|
|
14974
15950
|
const scope = inferUrlMigrationScope({ body, contentType: "text/html", finalUrl: base });
|
|
14975
15951
|
const mount = scope.evidence === "source-parent" ? selectedScope ?? "/" : scope.scopePath;
|
|
14976
15952
|
const configTarget = (value) => {
|
|
@@ -15100,41 +16076,176 @@ function resolveNavigation(nodes, base) {
|
|
|
15100
16076
|
};
|
|
15101
16077
|
return walk2(nodes);
|
|
15102
16078
|
}
|
|
16079
|
+
function sidebarCollectionMenus($, root, base, existing) {
|
|
16080
|
+
const document = readMigrationFlightDocument($);
|
|
16081
|
+
if (!document) return [];
|
|
16082
|
+
const resolve5 = (input) => {
|
|
16083
|
+
let value = input;
|
|
16084
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16085
|
+
for (let depth = 0; depth < 32 && typeof value === "string"; depth++) {
|
|
16086
|
+
if (value === "$undefined") return void 0;
|
|
16087
|
+
if (value.startsWith("$$")) return value.slice(1);
|
|
16088
|
+
const reference = /^\$L?([a-f\d]+)(?::(.+))?$/i.exec(value);
|
|
16089
|
+
if (!reference) return value;
|
|
16090
|
+
if (seen.has(value) || !document.records.has(reference[1])) return void 0;
|
|
16091
|
+
seen.add(value);
|
|
16092
|
+
value = document.records.get(reference[1]);
|
|
16093
|
+
for (const key of reference[2]?.split(":") ?? []) {
|
|
16094
|
+
if (key === "props" && Array.isArray(value) && value[0] === "$") {
|
|
16095
|
+
value = value[3];
|
|
16096
|
+
continue;
|
|
16097
|
+
}
|
|
16098
|
+
if (!value || typeof value !== "object" || !Object.hasOwn(value, key)) return void 0;
|
|
16099
|
+
value = value[key];
|
|
16100
|
+
}
|
|
16101
|
+
}
|
|
16102
|
+
return typeof value === "string" && /^\$L?[a-f\d]+(?::|$)/i.test(value) ? void 0 : value;
|
|
16103
|
+
};
|
|
16104
|
+
const known = /* @__PURE__ */ new Set();
|
|
16105
|
+
const remember = (nodes) => {
|
|
16106
|
+
for (const node of nodes) {
|
|
16107
|
+
if (node.url) known.add(node.url);
|
|
16108
|
+
remember(node.children ?? []);
|
|
16109
|
+
}
|
|
16110
|
+
};
|
|
16111
|
+
remember(existing);
|
|
16112
|
+
const result = [];
|
|
16113
|
+
let visited = 0;
|
|
16114
|
+
const active = /* @__PURE__ */ new Set();
|
|
16115
|
+
const visit = (input, inSidebar, inHeader, inArticle, depth) => {
|
|
16116
|
+
if (++visited > 1e5 || depth > 96 || active.has(input)) return;
|
|
16117
|
+
const value = resolve5(input);
|
|
16118
|
+
if (!value || typeof value !== "object") return;
|
|
16119
|
+
active.add(input);
|
|
16120
|
+
if (Array.isArray(value)) {
|
|
16121
|
+
if (value[0] === "$" && object(value[3])) {
|
|
16122
|
+
const componentId = typeof value[1] === "string" ? /^\$L([a-f\d]+)$/i.exec(value[1])?.[1] : void 0;
|
|
16123
|
+
const component = componentId ? document.modules.get(componentId) : value[1];
|
|
16124
|
+
const article = inArticle || ["PageArticle", "article", "pre", "code"].includes(String(component));
|
|
16125
|
+
const sidebar = !article && (inSidebar || component === "Sidebar");
|
|
16126
|
+
const header = sidebar && (inHeader || component === "SidebarHeader");
|
|
16127
|
+
if (header && component === "RootToggle") {
|
|
16128
|
+
const options = resolve5(value[3].options);
|
|
16129
|
+
if (Array.isArray(options) && options.length >= 2 && options.length <= 100) {
|
|
16130
|
+
const entries = options.map(resolve5).map((option) => object(option) ? { label: text2(resolve5(option.title)), url: target(resolve5(option.url), base) } : {});
|
|
16131
|
+
const hasVisibleChoice = entries.some((entry) => entry.label && root.find("button[aria-haspopup]").toArray().some((button) => [button, ...$(button).find("*").toArray()].some((node) => $(node).text().trim() === entry.label)));
|
|
16132
|
+
if (hasVisibleChoice && entries.every((entry) => entry.label && entry.url)) for (const entry of entries) {
|
|
16133
|
+
if (!known.has(entry.url)) {
|
|
16134
|
+
known.add(entry.url);
|
|
16135
|
+
result.push({ label: entry.label, url: entry.url });
|
|
16136
|
+
}
|
|
16137
|
+
}
|
|
16138
|
+
}
|
|
16139
|
+
}
|
|
16140
|
+
visit(value[3].children, sidebar, header, article, depth + 1);
|
|
16141
|
+
} else for (const child of value) visit(child, inSidebar, inHeader, inArticle, depth + 1);
|
|
16142
|
+
} else for (const child of Object.values(value)) visit(child, inSidebar, inHeader, inArticle, depth + 1);
|
|
16143
|
+
active.delete(input);
|
|
16144
|
+
};
|
|
16145
|
+
visit(document.records.get("0"), false, false, false, 0);
|
|
16146
|
+
return visited > 1e5 ? [] : result;
|
|
16147
|
+
}
|
|
15103
16148
|
function extractSourceNavigation(capture, selectedScope) {
|
|
15104
16149
|
if (capture.navigation) return resolveNavigation(capture.navigation, capture.finalUrl);
|
|
15105
16150
|
if (!/html/i.test(capture.contentType) || Buffer.byteLength(capture.body) > MAX_CAPTURE_BYTES) return [];
|
|
15106
16151
|
const mintlify = mintlifyNavigation(capture.body, capture.finalUrl, capture.locale, selectedScope);
|
|
15107
16152
|
if (mintlify.length) return mintlify;
|
|
15108
|
-
const $ =
|
|
16153
|
+
const $ = load6(capture.body);
|
|
15109
16154
|
const candidates = ['.theme-doc-sidebar-menu,[aria-label*="sidebar" i]', "aside", '[role="navigation"],nav'];
|
|
15110
|
-
const root = candidates.map((selector) => $(selector).filter((_index, node) =>
|
|
16155
|
+
const root = candidates.map((selector) => $(selector).filter((_index, node) => {
|
|
16156
|
+
const item = $(node);
|
|
16157
|
+
if (!item.find("a[href]").length || item.closest("header,article").length) return false;
|
|
16158
|
+
const current = new URL(capture.finalUrl);
|
|
16159
|
+
const internal = item.find("a[href]").toArray().flatMap((link) => {
|
|
16160
|
+
const reference = target($(link).attr("href"), capture.finalUrl);
|
|
16161
|
+
if (!reference) return [];
|
|
16162
|
+
const url = new URL(reference);
|
|
16163
|
+
return url.origin === current.origin ? [url] : [];
|
|
16164
|
+
});
|
|
16165
|
+
if (!internal.length) {
|
|
16166
|
+
if (item.is('nav,[role="navigation"]')) return true;
|
|
16167
|
+
const prose = item.clone();
|
|
16168
|
+
prose.find("a,svg,img,script,style").remove();
|
|
16169
|
+
return !prose.text().trim();
|
|
16170
|
+
}
|
|
16171
|
+
return internal.every((url) => !url.hash) || internal.some((url) => url.pathname !== current.pathname || !url.hash && url.search !== current.search);
|
|
16172
|
+
}).first()).find((candidate) => candidate.length);
|
|
15111
16173
|
if (!root) return [];
|
|
15112
16174
|
let count = 0;
|
|
16175
|
+
const labelOf = (item) => {
|
|
16176
|
+
const visible = item.text().replace(/\s+/g, " ").trim();
|
|
16177
|
+
if (visible) return visible;
|
|
16178
|
+
if (item.is("a[href]")) {
|
|
16179
|
+
const url = target(item.attr("href"), capture.finalUrl);
|
|
16180
|
+
if (url && root.find("a[href]").toArray().some((node) => node !== item[0] && $(node).text().trim() && target($(node).attr("href"), capture.finalUrl) === url)) return "";
|
|
16181
|
+
}
|
|
16182
|
+
return text2(item.attr("aria-label")) || text2(item.attr("title")) || text2(item.find("img[alt]").first().attr("alt")) || "";
|
|
16183
|
+
};
|
|
15113
16184
|
const walk2 = (element, excluded, depth = 0) => {
|
|
15114
16185
|
if (depth > MAX_DEPTH) throw new Error("Source navigation exceeds its safety bound.");
|
|
15115
16186
|
const result = [];
|
|
16187
|
+
const siblings = $(element).children().toArray().filter((node) => node !== excluded);
|
|
16188
|
+
if (siblings.length > MAX_NODES) throw new Error("Source navigation exceeds its safety bound.");
|
|
16189
|
+
const marker = (node) => {
|
|
16190
|
+
const item = $(node);
|
|
16191
|
+
return item.is("p,span") && Boolean(item.text().trim()) && item.text().length <= 512 && item.find("*").toArray().every((child) => $(child).is("span,strong,em,b,i,small,code,br")) && !item.find("a,button,input,textarea,select,form,div,p,section,article").length && !item.closest('form,[role="search"],[aria-hidden="true"]').length;
|
|
16192
|
+
};
|
|
16193
|
+
const markerPositions = siblings.flatMap((node, index) => marker(node) ? [index] : []);
|
|
16194
|
+
const markers = markerPositions.map((index) => siblings[index]);
|
|
16195
|
+
const isLinkContainer = (node) => {
|
|
16196
|
+
const item = $(node);
|
|
16197
|
+
if (item.is("a[href]")) return true;
|
|
16198
|
+
if (!item.is("div,li,ul,ol,details")) return false;
|
|
16199
|
+
if (!item.find("a[href]").length || item.find('form,input,textarea,select,[role="search"]').length) return false;
|
|
16200
|
+
const remainder = item.clone();
|
|
16201
|
+
remainder.find("a[href],svg,img").remove();
|
|
16202
|
+
return !remainder.text().trim() && !remainder.find("button,form,input,textarea,select,section,article").length;
|
|
16203
|
+
};
|
|
16204
|
+
const groupedMarkers = /* @__PURE__ */ new Set();
|
|
16205
|
+
if (markers.length >= 2 && markers.every((node) => node.tagName === markers[0].tagName)) {
|
|
16206
|
+
let isComplete = true;
|
|
16207
|
+
for (let index = 0; index < markers.length; index++) {
|
|
16208
|
+
const start = markerPositions[index] + 1;
|
|
16209
|
+
const end = index + 1 < markers.length ? markerPositions[index + 1] : siblings.length;
|
|
16210
|
+
const following = siblings.slice(start, end).filter((node) => $(node).text().trim() || $(node).find("a[href],button,input,textarea,select,form,img").length);
|
|
16211
|
+
if (!following.length || !following.every(isLinkContainer)) {
|
|
16212
|
+
isComplete = false;
|
|
16213
|
+
break;
|
|
16214
|
+
}
|
|
16215
|
+
}
|
|
16216
|
+
if (isComplete) markers.forEach((node) => groupedMarkers.add(node));
|
|
16217
|
+
}
|
|
16218
|
+
let currentGroup;
|
|
16219
|
+
const append = (nodes) => {
|
|
16220
|
+
if (currentGroup) currentGroup.children.push(...nodes);
|
|
16221
|
+
else result.push(...nodes);
|
|
16222
|
+
};
|
|
15116
16223
|
$(element).children().each((_index, node) => {
|
|
15117
16224
|
if (++count > MAX_NODES) throw new Error("Source navigation exceeds its safety bound.");
|
|
15118
16225
|
if (node === excluded) return;
|
|
15119
16226
|
const item = $(node);
|
|
15120
|
-
if (
|
|
15121
|
-
|
|
16227
|
+
if (groupedMarkers.has(node)) {
|
|
16228
|
+
currentGroup = { kind: "group", label: item.text().replace(/\s+/g, " ").trim(), children: [] };
|
|
16229
|
+
result.push(currentGroup);
|
|
16230
|
+
} else if (item.is("a[href]")) {
|
|
16231
|
+
const label = labelOf(item);
|
|
15122
16232
|
const url = target(item.attr("href"), capture.finalUrl);
|
|
15123
|
-
if (label && url)
|
|
16233
|
+
if (label && url) append([{ label, url }]);
|
|
15124
16234
|
} else if (item.is("li,details") || item.attr("data-migration-group") !== void 0 || item.children("h2,h3,h4,h5,h6").length > 0) {
|
|
15125
16235
|
const directLink = item.children("a[href]").first();
|
|
15126
16236
|
const direct = directLink.length ? directLink : item.children("div").children("a[href]").first();
|
|
15127
|
-
const label = direct
|
|
16237
|
+
const label = labelOf(direct) || labelOf(item.children("summary,button,span,h2,h3,h4,h5,h6").first());
|
|
15128
16238
|
const children = walk2(node, direct[0], depth + 1);
|
|
15129
16239
|
const url = target(direct.attr("href"), capture.finalUrl);
|
|
15130
|
-
if (label && (url || children.length))
|
|
15131
|
-
else
|
|
15132
|
-
} else
|
|
16240
|
+
if (label && (url || children.length)) append([{ label, ...url ? { url } : {}, ...children.length ? { children } : {} }]);
|
|
16241
|
+
else append(children);
|
|
16242
|
+
} else append(walk2(node, excluded, depth + 1));
|
|
15133
16243
|
});
|
|
15134
16244
|
return result;
|
|
15135
16245
|
};
|
|
15136
16246
|
try {
|
|
15137
|
-
|
|
16247
|
+
const nodes = walk2(root);
|
|
16248
|
+
return [...nodes, ...sidebarCollectionMenus($, root, capture.finalUrl, nodes)];
|
|
15138
16249
|
} catch {
|
|
15139
16250
|
return [];
|
|
15140
16251
|
}
|
|
@@ -15181,6 +16292,71 @@ function mergeSourceNavigation(existing, incoming) {
|
|
|
15181
16292
|
return merge(existing, incoming);
|
|
15182
16293
|
}
|
|
15183
16294
|
|
|
16295
|
+
// src/url-identity.ts
|
|
16296
|
+
import { createHash as createHash5 } from "crypto";
|
|
16297
|
+
import { load as load7 } from "cheerio";
|
|
16298
|
+
var directory = (path) => path.replace(/\/index\/?$/i, "").replace(/\/$/, "") || "/";
|
|
16299
|
+
function migrationSectionQueryCandidate(source, anchors) {
|
|
16300
|
+
const target2 = new URL(source);
|
|
16301
|
+
const sections = [...source.searchParams].filter(([, value]) => anchors.includes(value));
|
|
16302
|
+
const section = sections.length === 1 && source.searchParams.getAll(sections[0][0]).length === 1 ? sections[0] : void 0;
|
|
16303
|
+
if (section) target2.searchParams.delete(section[0]);
|
|
16304
|
+
target2.hash = "";
|
|
16305
|
+
target2.pathname = target2.pathname.replace(/\/+$/, "") || "/";
|
|
16306
|
+
return { canonicalUrl: target2.href, ...section ? { sectionAnchor: section[1] } : {} };
|
|
16307
|
+
}
|
|
16308
|
+
function isMigrationUtilityUrl(url) {
|
|
16309
|
+
return /^\/cdn-cgi\/l\/email-protection\/?$/i.test(url.pathname);
|
|
16310
|
+
}
|
|
16311
|
+
function declaredMigrationArticleUrl(document) {
|
|
16312
|
+
const target2 = declaredCanonical(document);
|
|
16313
|
+
return target2 && target2.search === document.finalUrl.search ? target2 : document.finalUrl;
|
|
16314
|
+
}
|
|
16315
|
+
function declaredCanonical(document) {
|
|
16316
|
+
if (!/html/i.test(document.contentType)) return void 0;
|
|
16317
|
+
const reference = load7(document.body)('link[rel="canonical"][href]').first().attr("href");
|
|
16318
|
+
if (!reference) return void 0;
|
|
16319
|
+
try {
|
|
16320
|
+
const target2 = new URL(reference, document.finalUrl);
|
|
16321
|
+
if (target2.origin !== document.finalUrl.origin || target2.username || target2.password || directory(target2.pathname) !== directory(document.finalUrl.pathname)) return void 0;
|
|
16322
|
+
target2.hash = "";
|
|
16323
|
+
target2.pathname = target2.pathname.replace(/\/+$/, "") || "/";
|
|
16324
|
+
return target2;
|
|
16325
|
+
} catch {
|
|
16326
|
+
return void 0;
|
|
16327
|
+
}
|
|
16328
|
+
}
|
|
16329
|
+
function observedMigrationArticleIdentity(document) {
|
|
16330
|
+
if (!/html/i.test(document.contentType)) return void 0;
|
|
16331
|
+
const { $, root } = migrationHtmlArticle(document.body);
|
|
16332
|
+
if (!root.length || !root.text().trim()) return void 0;
|
|
16333
|
+
const anchors = root.find("[id]").toArray().map((node) => $(node).attr("id"));
|
|
16334
|
+
root.find("nav,aside,footer,script,style").remove();
|
|
16335
|
+
const metadata = load7(document.body);
|
|
16336
|
+
const payload = JSON.stringify([
|
|
16337
|
+
$.html(root),
|
|
16338
|
+
metadata("title").text(),
|
|
16339
|
+
metadata('meta[name="description"]').attr("content"),
|
|
16340
|
+
metadata("html").attr("lang"),
|
|
16341
|
+
document.locale,
|
|
16342
|
+
document.version,
|
|
16343
|
+
// Deferred content can exist only in inert hydration data. Never erase its
|
|
16344
|
+
// differences merely because two collapsed DOM panels appear identical.
|
|
16345
|
+
metadata("script").toArray().map((node) => [metadata(node).attr("src"), metadata(node).text()]),
|
|
16346
|
+
(document.states ?? []).map((state) => [state.id, state.label, state.response.body])
|
|
16347
|
+
]);
|
|
16348
|
+
const source = document.finalUrl;
|
|
16349
|
+
const canonical2 = declaredCanonical(document) ?? new URL(source);
|
|
16350
|
+
if (canonical2.href === source.href) {
|
|
16351
|
+
canonical2.href = migrationSectionQueryCandidate(source, anchors).canonicalUrl;
|
|
16352
|
+
}
|
|
16353
|
+
canonical2.hash = "";
|
|
16354
|
+
canonical2.pathname = canonical2.pathname.replace(/\/+$/, "") || "/";
|
|
16355
|
+
const removed = [...source.searchParams].filter(([key, value]) => !canonical2.searchParams.getAll(key).includes(value));
|
|
16356
|
+
const sectionAnchor = removed.length === 1 && anchors.includes(removed[0][1]) ? removed[0][1] : void 0;
|
|
16357
|
+
return { canonicalUrl: canonical2.href, articleSha256: createHash5("sha256").update(payload).digest("hex"), ...sectionAnchor ? { sectionAnchor } : {} };
|
|
16358
|
+
}
|
|
16359
|
+
|
|
15184
16360
|
// src/url-api-schema-controls.ts
|
|
15185
16361
|
var MAX_CAPTURE_BYTES2 = 8e6;
|
|
15186
16362
|
var MAX_TAB_GROUPS = 256;
|
|
@@ -15299,17 +16475,378 @@ function apiSchemaTabGroups(body, document, operation) {
|
|
|
15299
16475
|
for (const proof of proofs) scopeCounts.set(proof.scope, (scopeCounts.get(proof.scope) ?? 0) + 1);
|
|
15300
16476
|
return proofs.filter((proof) => scopeCounts.get(proof.scope) === 1).map((proof) => proof.index);
|
|
15301
16477
|
}
|
|
16478
|
+
function apiSchemaDisclosureGroups(body, document, operation) {
|
|
16479
|
+
if (Buffer.byteLength(body) > MAX_CAPTURE_BYTES2 || !complete(document)) return [];
|
|
16480
|
+
if (!/^(?:get|post|put|patch|delete|head|options|trace)$/i.test(operation.method)) return [];
|
|
16481
|
+
const path = object2(object2(document.paths)?.[operation.path]);
|
|
16482
|
+
const selected = object2(path?.[operation.method.toLowerCase()]);
|
|
16483
|
+
if (!selected) return [];
|
|
16484
|
+
const { $, root } = migrationHtmlArticle(body);
|
|
16485
|
+
const operations = root.find('[id^="api-playground-"][id$="-operation-page"]').filter((_index, node) => {
|
|
16486
|
+
const item = $(node);
|
|
16487
|
+
const endpoint = item.find('[data-component-part="scroll-area-content"]').first().clone();
|
|
16488
|
+
endpoint.find("[data-thally-static-base-urls]").remove();
|
|
16489
|
+
return item.find(".method-pill").first().text().trim().toLowerCase() === operation.method.toLowerCase() && endpoint.text().trim() === operation.path;
|
|
16490
|
+
});
|
|
16491
|
+
if (operations.length !== 1) return [];
|
|
16492
|
+
const ids = /* @__PURE__ */ new Map();
|
|
16493
|
+
root.find("[id]").each((_index, node) => {
|
|
16494
|
+
const id = $(node).attr("id");
|
|
16495
|
+
ids.set(id, (ids.get(id) ?? 0) + 1);
|
|
16496
|
+
});
|
|
16497
|
+
if (ids.get(operations.attr("id")) !== 1) return [];
|
|
16498
|
+
let visits = 0;
|
|
16499
|
+
const property = (value, name, active = /* @__PURE__ */ new Set()) => {
|
|
16500
|
+
if (++visits > 1e5 || active.has(value)) return [];
|
|
16501
|
+
const schema = resolve4(document, value);
|
|
16502
|
+
if (!schema) return [];
|
|
16503
|
+
active.add(value);
|
|
16504
|
+
const direct = object2(schema.properties)?.[name];
|
|
16505
|
+
const result = direct ? [direct] : [
|
|
16506
|
+
...schema.items ? property(schema.items, name, active) : [],
|
|
16507
|
+
...["allOf", "oneOf", "anyOf"].flatMap((key) => Array.isArray(schema[key]) ? schema[key].flatMap((child) => property(child, name, active)) : [])
|
|
16508
|
+
];
|
|
16509
|
+
active.delete(value);
|
|
16510
|
+
return result;
|
|
16511
|
+
};
|
|
16512
|
+
const fieldSelector = ".object-param-field,.array-param-field";
|
|
16513
|
+
const proofs = [];
|
|
16514
|
+
if (root.find("details").length > MAX_TABS) return [];
|
|
16515
|
+
root.find("details").each((index, node) => {
|
|
16516
|
+
const details = $(node), control = details.children('summary[data-component-part="expandable-button"]');
|
|
16517
|
+
const panel = details.children('[data-component-part="expandable-content"]');
|
|
16518
|
+
const field = details.closest(fieldSelector), section = field.closest(".api-section");
|
|
16519
|
+
if (!details.is('.expandable[data-component-part="expandable"]') || control.length !== 1 || panel.length !== 1 || details.children().length !== 2 || !field.length || section.closest('[id^="api-playground-"][id$="-operation-page"]')[0] !== operations[0]) return;
|
|
16520
|
+
const target2 = control.attr("aria-controls"), controlId = control.attr("id");
|
|
16521
|
+
if (target2 && (panel.attr("id") !== target2 || ids.get(target2) !== 1) || controlId && ids.get(controlId) !== 1) return;
|
|
16522
|
+
const payload = panel.clone();
|
|
16523
|
+
payload.find("script,style").remove();
|
|
16524
|
+
if (payload.text().trim() || payload.children().length) return;
|
|
16525
|
+
const ancestors = field.parents(fieldSelector).toArray().reverse().filter((owner) => $(owner).is(".array-param-field") || $(owner).find('[data-component-part="expandable-content"]').toArray().some((region) => $(region).closest(fieldSelector)[0] === owner && field.parents().toArray().includes(region)));
|
|
16526
|
+
const chain = [...ancestors, field[0]];
|
|
16527
|
+
const names = chain.map((owner) => $(owner).find('[data-component-part="field-name"]').filter((_index, name) => $(name).closest(fieldSelector)[0] === owner));
|
|
16528
|
+
const hasNamedPath = names.every((name) => name.length === 1 && Boolean(name.text().trim()));
|
|
16529
|
+
const heading = section.children(".api-section-heading");
|
|
16530
|
+
if (heading.length !== 1) return;
|
|
16531
|
+
const leaves = heading.find("*").toArray().filter((element) => $(element).children().length === 0).map((element) => $(element).text().trim());
|
|
16532
|
+
const combined = leaves.flatMap((text3) => {
|
|
16533
|
+
const match = text3.match(/^([1-5]\d{2}|default) - ([a-z][a-z\d.+-]*\/[a-z\d.+-]+)$/i);
|
|
16534
|
+
return match ? [{ status: match[1], media: match[2] }] : [];
|
|
16535
|
+
});
|
|
16536
|
+
const media = heading.find("*").toArray().filter((element) => $(element).children().length === 0).map((element) => $(element).text().trim()).filter((text3) => /^[a-z][a-z\d.+-]*\/[a-z\d.+-]+$/i.test(text3));
|
|
16537
|
+
const statuses = heading.find('button[aria-haspopup="menu"]').toArray().map((button) => $(button).text().trim()).filter((text3) => /^(?:[1-5]\d{2}|default)$/.test(text3));
|
|
16538
|
+
if (combined.length === 1 && !media.length && !statuses.length) {
|
|
16539
|
+
media.push(combined[0].media);
|
|
16540
|
+
statuses.push(combined[0].status);
|
|
16541
|
+
}
|
|
16542
|
+
let schemas = [];
|
|
16543
|
+
let offset = 0;
|
|
16544
|
+
let prefix = "";
|
|
16545
|
+
if (media.length === 1 && statuses.length === 1) {
|
|
16546
|
+
const response = resolve4(document, object2(selected.responses)?.[statuses[0]]);
|
|
16547
|
+
schemas = [object2(object2(response?.content)?.[media[0]])?.schema];
|
|
16548
|
+
prefix = "response";
|
|
16549
|
+
} else if (media.length === 1 && !statuses.length) {
|
|
16550
|
+
const request2 = resolve4(document, selected.requestBody);
|
|
16551
|
+
schemas = [object2(object2(request2?.content)?.[media[0]])?.schema];
|
|
16552
|
+
prefix = "body";
|
|
16553
|
+
} else if (!media.length && !statuses.length) {
|
|
16554
|
+
const head = $(chain[0]).find(".param-head[id]").filter((_index, element) => $(element).closest(fieldSelector)[0] === chain[0]).first().attr("id") ?? "";
|
|
16555
|
+
const location = ["query", "path", "header", "cookie"].find((value) => head.startsWith(`${value}-`));
|
|
16556
|
+
if (names[0]?.length !== 1 || !location && !head.startsWith("parameter-")) return;
|
|
16557
|
+
const parameters = [...Array.isArray(path?.parameters) ? path.parameters : [], ...Array.isArray(selected.parameters) ? selected.parameters : []].map((value) => resolve4(document, value)).filter((parameter) => (!location || parameter?.in === location) && parameter?.name === names[0].text().trim());
|
|
16558
|
+
if (parameters.length !== 1) return;
|
|
16559
|
+
schemas = [parameters[0]?.schema];
|
|
16560
|
+
offset = 1;
|
|
16561
|
+
prefix = $(chain[0]).is(".array-param-field") ? "parameter" : `parameter-${names[0].text().trim()}`;
|
|
16562
|
+
}
|
|
16563
|
+
const expandable = (value) => {
|
|
16564
|
+
const schema = resolve4(document, value);
|
|
16565
|
+
return Boolean(schema && (object2(schema.properties) || object2(schema.items) || object2(schema.additionalProperties) || ["allOf", "oneOf", "anyOf"].some((key) => Array.isArray(schema[key]))));
|
|
16566
|
+
};
|
|
16567
|
+
const roots = schemas;
|
|
16568
|
+
if (hasNamedPath) {
|
|
16569
|
+
for (const name of names.slice(offset)) schemas = schemas.flatMap((schema) => property(schema, name.text().trim()));
|
|
16570
|
+
if (schemas.some(expandable)) {
|
|
16571
|
+
proofs.push(index);
|
|
16572
|
+
return;
|
|
16573
|
+
}
|
|
16574
|
+
}
|
|
16575
|
+
const marker = details.attr("data-testid");
|
|
16576
|
+
if (!prefix || !marker?.endsWith("-children")) return;
|
|
16577
|
+
const expected = marker.slice(0, -"-children".length);
|
|
16578
|
+
const visibleNames = chain.flatMap((owner) => {
|
|
16579
|
+
const labels2 = $(owner).find('[data-component-part="field-name"]').filter((_index, label) => $(label).closest(fieldSelector)[0] === owner);
|
|
16580
|
+
return labels2.length === 1 ? [labels2.text().trim()] : [];
|
|
16581
|
+
});
|
|
16582
|
+
const matches = /* @__PURE__ */ new Set();
|
|
16583
|
+
const walk2 = (value, key, pathNames, active = /* @__PURE__ */ new Set()) => {
|
|
16584
|
+
if (++visits > 1e5 || key.length > 2048 || active.has(value)) return;
|
|
16585
|
+
const schema = resolve4(document, value);
|
|
16586
|
+
if (!schema) return;
|
|
16587
|
+
if (key === expected && expandable(schema)) {
|
|
16588
|
+
let cursor = 0;
|
|
16589
|
+
const labelsAgree = visibleNames.every((name) => {
|
|
16590
|
+
const found = pathNames.indexOf(name, cursor);
|
|
16591
|
+
cursor = found + 1;
|
|
16592
|
+
return found >= 0;
|
|
16593
|
+
});
|
|
16594
|
+
if (labelsAgree) matches.add(schema);
|
|
16595
|
+
}
|
|
16596
|
+
if (!expected.startsWith(`${key}-`)) return;
|
|
16597
|
+
active.add(value);
|
|
16598
|
+
for (const [name, child] of Object.entries(object2(schema.properties) ?? {})) {
|
|
16599
|
+
const segments = /* @__PURE__ */ new Set([name, name.replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase()]);
|
|
16600
|
+
for (const segment of segments) walk2(child, `${key}-${segment}`, [...pathNames, name], active);
|
|
16601
|
+
}
|
|
16602
|
+
if (schema.items) walk2(schema.items, `${key}-items`, pathNames, active);
|
|
16603
|
+
if ((schema.nullable === true || Array.isArray(schema.type) && schema.type.includes("null")) && !schema.oneOf) walk2({ ...schema, nullable: false, type: Array.isArray(schema.type) ? schema.type.filter((value2) => value2 !== "null") : schema.type }, `${key}-one-of-0`, pathNames, active);
|
|
16604
|
+
if (Array.isArray(schema.allOf)) schema.allOf.forEach((child) => walk2(child, key, pathNames, active));
|
|
16605
|
+
for (const [keyword, segment] of [["allOf", "all-of"], ["oneOf", "one-of"], ["anyOf", "any-of"]]) {
|
|
16606
|
+
const children = schema[keyword];
|
|
16607
|
+
if (Array.isArray(children)) children.forEach((child, branch) => walk2(child, `${key}-${segment}-${branch}`, pathNames, active));
|
|
16608
|
+
}
|
|
16609
|
+
active.delete(value);
|
|
16610
|
+
};
|
|
16611
|
+
roots.forEach((schema) => walk2(schema, prefix, offset ? [names[0].text().trim()] : []));
|
|
16612
|
+
if (matches.size === 1) proofs.push(index);
|
|
16613
|
+
});
|
|
16614
|
+
return visits > 1e5 ? [] : proofs;
|
|
16615
|
+
}
|
|
16616
|
+
function apiOperationCodeControls(body, specification, operation) {
|
|
16617
|
+
if (Buffer.byteLength(body) > MAX_CAPTURE_BYTES2 || !complete(specification)) return [];
|
|
16618
|
+
const selected = object2(object2(object2(specification.paths)?.[operation.path])?.[operation.method.toLowerCase()]);
|
|
16619
|
+
if (!selected) return [];
|
|
16620
|
+
const { $, root } = migrationHtmlArticle(body);
|
|
16621
|
+
const flight = readMigrationFlightDocument($);
|
|
16622
|
+
if (!flight) return [];
|
|
16623
|
+
let visited = 0, textBytes = 0, exceeded = false;
|
|
16624
|
+
const resolveValue = (input) => {
|
|
16625
|
+
if (exceeded) return void 0;
|
|
16626
|
+
const result = resolveMigrationFlightValue(flight, input);
|
|
16627
|
+
if (!result.resolved) exceeded = true;
|
|
16628
|
+
return result.value;
|
|
16629
|
+
};
|
|
16630
|
+
const textOf = (input, depth = 0, label = false) => {
|
|
16631
|
+
if (exceeded || ++visited > 1e5 || depth > 96) {
|
|
16632
|
+
exceeded = true;
|
|
16633
|
+
return void 0;
|
|
16634
|
+
}
|
|
16635
|
+
const value = resolveValue(input);
|
|
16636
|
+
if (value === void 0 || value === null || typeof value === "boolean") return "";
|
|
16637
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
16638
|
+
const result = String(value);
|
|
16639
|
+
textBytes += Buffer.byteLength(result);
|
|
16640
|
+
if (textBytes > MAX_CAPTURE_BYTES2) {
|
|
16641
|
+
exceeded = true;
|
|
16642
|
+
return void 0;
|
|
16643
|
+
}
|
|
16644
|
+
return result;
|
|
16645
|
+
}
|
|
16646
|
+
if (!Array.isArray(value)) return void 0;
|
|
16647
|
+
if (value[0] === "$") {
|
|
16648
|
+
if (typeof value[1] !== "string" || !(label ? ["div", "p", "span", "code", "a", "br", "svg", "path", "polyline"] : ["span", "code", "a", "br"]).includes(value[1]) || !object2(value[3])) return void 0;
|
|
16649
|
+
return value[1] === "br" ? "\n" : textOf(value[3].children, depth + 1, label);
|
|
16650
|
+
}
|
|
16651
|
+
const children = value.map((child) => textOf(child, depth + 1, label));
|
|
16652
|
+
return children.some((child) => child === void 0) ? void 0 : children.join("");
|
|
16653
|
+
};
|
|
16654
|
+
const samplePairs = (value, transport = true) => {
|
|
16655
|
+
if (exceeded) return void 0;
|
|
16656
|
+
const samples = transport ? resolveValue(value) : value;
|
|
16657
|
+
if (!Array.isArray(samples) || samples.length > 64) return void 0;
|
|
16658
|
+
const pairs = [];
|
|
16659
|
+
for (const input of samples) {
|
|
16660
|
+
const sample = object2(transport ? resolveValue(input) : input);
|
|
16661
|
+
const language = transport ? resolveValue(sample?.lang) : sample?.lang;
|
|
16662
|
+
const source = transport ? resolveValue(sample?.source) : sample?.source;
|
|
16663
|
+
const label = transport ? resolveValue(sample?.label) : sample?.label;
|
|
16664
|
+
if (label !== void 0 && typeof label !== "string") return void 0;
|
|
16665
|
+
if (typeof language !== "string" || !language.trim() || typeof source !== "string" || !source.trim()) return void 0;
|
|
16666
|
+
textBytes += Buffer.byteLength(language) + Buffer.byteLength(source) + (typeof label === "string" ? Buffer.byteLength(label) : 0);
|
|
16667
|
+
if (textBytes > MAX_CAPTURE_BYTES2) {
|
|
16668
|
+
exceeded = true;
|
|
16669
|
+
return void 0;
|
|
16670
|
+
}
|
|
16671
|
+
pairs.push(JSON.stringify([language, source, label ?? null]));
|
|
16672
|
+
}
|
|
16673
|
+
return pairs;
|
|
16674
|
+
};
|
|
16675
|
+
const declared = selected["x-codeSamples"] === void 0 ? [] : samplePairs(selected["x-codeSamples"], false);
|
|
16676
|
+
if (!declared) return [];
|
|
16677
|
+
const groups = [];
|
|
16678
|
+
const providers = [];
|
|
16679
|
+
let providerCount = 0, generatedControllers = 0, providerMetadataMatches = false;
|
|
16680
|
+
const matchesOperation = (value) => {
|
|
16681
|
+
const metadata = object2(resolveValue(value));
|
|
16682
|
+
const declaration = resolveValue(metadata?.openapi);
|
|
16683
|
+
if (typeof declaration !== "string") return false;
|
|
16684
|
+
const tokens = declaration.trim().split(/\s+/);
|
|
16685
|
+
return tokens.at(-2)?.toLowerCase() === operation.method.toLowerCase() && tokens.at(-1) === operation.path;
|
|
16686
|
+
};
|
|
16687
|
+
const active = /* @__PURE__ */ new Set();
|
|
16688
|
+
const visit = (input, provider, group, depth, owners = []) => {
|
|
16689
|
+
if (exceeded || ++visited > 1e5 || depth > 96) {
|
|
16690
|
+
exceeded = true;
|
|
16691
|
+
return;
|
|
16692
|
+
}
|
|
16693
|
+
const value = resolveValue(input);
|
|
16694
|
+
if (!value || typeof value !== "object") return;
|
|
16695
|
+
if (active.has(value)) {
|
|
16696
|
+
exceeded = true;
|
|
16697
|
+
return;
|
|
16698
|
+
}
|
|
16699
|
+
active.add(value);
|
|
16700
|
+
if (Array.isArray(value)) {
|
|
16701
|
+
if (value[0] === "$" && object2(value[3])) {
|
|
16702
|
+
const props = value[3];
|
|
16703
|
+
const moduleId = typeof value[1] === "string" ? /^\$L([a-f\d]+)$/i.exec(value[1])?.[1] : void 0;
|
|
16704
|
+
const kind = moduleId ? flight.modules.get(moduleId) : value[1];
|
|
16705
|
+
const ownId = moduleId ? void 0 : resolveValue(props.id);
|
|
16706
|
+
const localOwners = typeof ownId === "string" ? [...owners, ownId] : owners;
|
|
16707
|
+
let owned = provider;
|
|
16708
|
+
if (kind === "OpenApiProvider") {
|
|
16709
|
+
providerCount += 1;
|
|
16710
|
+
const data = object2(resolveValue(props.openApiReferenceData));
|
|
16711
|
+
const source = object2(resolveValue(data?.operation));
|
|
16712
|
+
const samples = samplePairs(source?.codeSamples);
|
|
16713
|
+
const authored = source?.["x-codeSamples"] === void 0 ? [] : samplePairs(source["x-codeSamples"]);
|
|
16714
|
+
owned = Boolean(source && source.method === operation.method.toLowerCase() && source.path === operation.path && samples && authored && JSON.stringify(samples) === JSON.stringify(declared) && JSON.stringify(authored) === JSON.stringify(declared));
|
|
16715
|
+
if (owned) {
|
|
16716
|
+
providers.push(source);
|
|
16717
|
+
providerMetadataMatches = matchesOperation(props.pageMetadata);
|
|
16718
|
+
}
|
|
16719
|
+
}
|
|
16720
|
+
if (owned && kind === "MDXContentController" && matchesOperation(props.pageMetadata)) {
|
|
16721
|
+
const child = resolveValue(props.children);
|
|
16722
|
+
const childId = Array.isArray(child) && child[0] === "$" && typeof child[1] === "string" ? /^\$L([a-f\d]+)$/i.exec(child[1])?.[1] : void 0;
|
|
16723
|
+
const childProps = Array.isArray(child) ? object2(child[3]) : void 0;
|
|
16724
|
+
const source = object2(resolveValue(childProps?.mdxSource));
|
|
16725
|
+
const scope = object2(resolveValue(source?.scope));
|
|
16726
|
+
if (childId && flight.modules.get(childId) === "default" && typeof source?.compiledSource === "string" && (() => {
|
|
16727
|
+
if (matchesOperation(scope?.pageMetadata)) return true;
|
|
16728
|
+
const hint = object2(resolveValue(scope?.pageMetadata)), metadata = object2(resolveValue(props.pageMetadata));
|
|
16729
|
+
const declaration = resolveValue(hint?.openapi);
|
|
16730
|
+
if (typeof declaration !== "string" || typeof hint?.href !== "string" || !hint.href || hint.href !== metadata?.href) return false;
|
|
16731
|
+
const tokens = declaration.trim().split(/\s+/);
|
|
16732
|
+
const template = (path) => path.split("/").map((segment) => /^\{[^{}\/]+\}$/.test(segment) ? "{}" : segment).join("/");
|
|
16733
|
+
return tokens.at(-2)?.toLowerCase() === operation.method.toLowerCase() && template(tokens.at(-1) ?? "") === template(operation.path);
|
|
16734
|
+
})()) generatedControllers += 1;
|
|
16735
|
+
}
|
|
16736
|
+
let local = group;
|
|
16737
|
+
if (owned && typeof props.className === "string" && props.className.split(/\s+/).includes("code-group")) {
|
|
16738
|
+
local = { owners: localOwners, code: [], controls: [], toolbar: false, generated: false, invalid: false };
|
|
16739
|
+
groups.push(local);
|
|
16740
|
+
}
|
|
16741
|
+
if (local && owned) {
|
|
16742
|
+
if (props["data-component-part"] === "code-group-tab-bar") local.toolbar = true;
|
|
16743
|
+
if (String(props["data-index"]) === "-1") local.generated = true;
|
|
16744
|
+
if (props["aria-expanded"] !== void 0) {
|
|
16745
|
+
const text3 = textOf(props.children, 0, true);
|
|
16746
|
+
if (kind !== "button" || props["aria-haspopup"] !== "menu" || text3 === void 0) local.invalid = true;
|
|
16747
|
+
else local.controls.push(JSON.stringify([text3, props["aria-label"] ?? "", String(props["aria-expanded"]), props["aria-haspopup"]]));
|
|
16748
|
+
}
|
|
16749
|
+
if (kind === "pre") {
|
|
16750
|
+
const code = textOf(props.children);
|
|
16751
|
+
if (code === void 0 || !code.trim()) local.invalid = true;
|
|
16752
|
+
else local.code.push(code);
|
|
16753
|
+
}
|
|
16754
|
+
if (props["aria-busy"] === true || props["aria-busy"] === "true" || props.role === "progressbar") local.invalid = true;
|
|
16755
|
+
}
|
|
16756
|
+
visit(props.children, owned, local, depth + 1, localOwners);
|
|
16757
|
+
} else for (const child of value) visit(child, provider, group, depth + 1, owners);
|
|
16758
|
+
} else if (depth === 0 && Array.isArray(value.f)) {
|
|
16759
|
+
visit(value.f, provider, group, depth + 1, owners);
|
|
16760
|
+
} else if (Object.keys(value).every((key) => key === "children")) {
|
|
16761
|
+
const children = value.children;
|
|
16762
|
+
if (Array.isArray(children) && children.length >= 2) visit(children, provider, group, depth + 1, owners);
|
|
16763
|
+
}
|
|
16764
|
+
active.delete(value);
|
|
16765
|
+
};
|
|
16766
|
+
visit(flight.records.get("0"), false, void 0, 0);
|
|
16767
|
+
if (exceeded || providerCount !== 1 || providers.length !== 1 || groups.length > MAX_TAB_GROUPS) return [];
|
|
16768
|
+
const sources = declared.map((pair) => JSON.parse(pair)[1]);
|
|
16769
|
+
const sourceCounts = /* @__PURE__ */ new Map();
|
|
16770
|
+
for (const group of groups) if (group.toolbar && group.generated && !group.invalid && group.controls.length >= 1 && group.controls.length <= 2) {
|
|
16771
|
+
const signature = JSON.stringify([group.owners, group.code, group.controls]);
|
|
16772
|
+
sourceCounts.set(signature, (sourceCounts.get(signature) ?? 0) + 1);
|
|
16773
|
+
}
|
|
16774
|
+
const expanded = root.find("[aria-expanded]").toArray();
|
|
16775
|
+
if (expanded.length > MAX_TABS) return [];
|
|
16776
|
+
const controlIndices = new Map(expanded.map((node, index) => [node, index]));
|
|
16777
|
+
const domGroups = /* @__PURE__ */ new Map();
|
|
16778
|
+
$(expanded).each((_index, node) => {
|
|
16779
|
+
const control = $(node);
|
|
16780
|
+
const group = control.closest('.code-group,[data-testid="code-group-select"]');
|
|
16781
|
+
const legacy = group.is('[data-testid="code-group-select"]');
|
|
16782
|
+
if (!control.is('button[aria-haspopup="menu"]') || control.attr("aria-controls") || !legacy && !control.closest('[data-component-part="code-group-tab-bar"]').length || !group.length || group.find("[aria-expanded]").length < 1 || group.find("[aria-expanded]").length > 2) return;
|
|
16783
|
+
if (domGroups.has(group[0])) return;
|
|
16784
|
+
const menus = group.find("[aria-expanded]");
|
|
16785
|
+
if (menus.toArray().some((menu) => !$(menu).is('button[aria-haspopup="menu"]') || !$(menu).attr("aria-label")?.trim() && !$(menu).text().trim() || $(menu).attr("aria-controls") || !legacy && $(menu).closest('[data-component-part="code-group-tab-bar"]')[0] !== group.children('[data-component-part="code-group-tab-bar"]')[0] || legacy && !$(menu).parents().toArray().includes(group.children().first()[0]))) return;
|
|
16786
|
+
if (menus.length === 2) {
|
|
16787
|
+
const samples = declared.map((pair) => JSON.parse(pair));
|
|
16788
|
+
const labelledChoices = samples.filter((sample) => sample[2] && samples.filter((other) => other[0] === sample[0]).length >= 2);
|
|
16789
|
+
if (!labelledChoices.length || !menus.toArray().some((menu) => labelledChoices.some((sample) => sample[2] === $(menu).text().trim()))) return;
|
|
16790
|
+
}
|
|
16791
|
+
const panels = group.find("[data-index]");
|
|
16792
|
+
const code = group.find("pre").toArray().map((pre) => {
|
|
16793
|
+
const lines = $(pre).find(".token-line");
|
|
16794
|
+
return lines.length ? lines.toArray().map((line) => $(line).text()).join("\n") : $(pre).text();
|
|
16795
|
+
});
|
|
16796
|
+
if (group.find('[aria-busy="true"],[role="progressbar"]').length) return;
|
|
16797
|
+
if (legacy) {
|
|
16798
|
+
if (menus.length !== 2 || group.children().length !== 2 || group.children().first().find("pre").length || code.length !== 1 || !code[0].trim() || panels.length) return;
|
|
16799
|
+
const selectedSamples = declared.map((pair) => JSON.parse(pair)).filter((sample) => sample[2] && menus.toArray().some((menu) => $(menu).text().trim() === sample[2]) && menus.toArray().some((menu) => $(menu).text().trim().toLowerCase() === sample[0]?.toLowerCase()) && (code[0] === sample[1] || code[0] === sample[1]?.replace(/\n$/, "")));
|
|
16800
|
+
if (!selectedSamples.length) return;
|
|
16801
|
+
} else if (!panels.length || panels.length > MAX_TABS || code.length !== panels.length || !panels.toArray().some((panel) => $(panel).attr("data-index") === "-1") || panels.toArray().some((panel) => $(panel).find("pre").length !== 1 || !$(panel).text().trim()) || !sources.every((source) => code.some((captured) => captured === source || captured === source.replace(/\n$/, "")))) return;
|
|
16802
|
+
const controls = menus.toArray().map((menu) => JSON.stringify([$(menu).text(), $(menu).attr("aria-label") ?? "", $(menu).attr("aria-expanded"), $(menu).attr("aria-haspopup")]));
|
|
16803
|
+
const owners = group.parents("[id]").toArray().reverse().map((owner) => $(owner).attr("id"));
|
|
16804
|
+
if (group.attr("id")) owners.push(group.attr("id"));
|
|
16805
|
+
domGroups.set(group[0], { signature: JSON.stringify([owners, code, controls]), indices: menus.toArray().map((menu) => controlIndices.get(menu)), code, legacy, title: group.children('[data-component-part="code-group-tab-bar"]').find("span[title]").first().attr("title"), label: legacy || group.children('[data-component-part="code-group-tab-bar"]').length === 1 && group.children('[data-component-part="code-group-tab-bar"]').find("span[title]").toArray().some((title) => Boolean($(title).attr("title")?.trim()) && $(title).text().trim() === $(title).attr("title")) });
|
|
16806
|
+
});
|
|
16807
|
+
const domCounts = /* @__PURE__ */ new Map();
|
|
16808
|
+
for (const group of domGroups.values()) domCounts.set(group.signature, (domCounts.get(group.signature) ?? 0) + 1);
|
|
16809
|
+
const proofs = [];
|
|
16810
|
+
for (const group of domGroups.values()) if (sourceCounts.get(group.signature) === 1 && domCounts.get(group.signature) === 1) proofs.push(...group.indices);
|
|
16811
|
+
if (groups.length === 0 && providerMetadataMatches && generatedControllers === 1 && domGroups.size === 2) {
|
|
16812
|
+
const operations = root.find('[id^="api-playground-"][id$="-operation-page"]').filter((_index, node) => {
|
|
16813
|
+
const endpoint = $(node).find('[data-component-part="scroll-area-content"]').first().clone();
|
|
16814
|
+
endpoint.find("[data-thally-static-base-urls]").remove();
|
|
16815
|
+
return $(node).find(".method-pill").first().text().trim().toLowerCase() === operation.method.toLowerCase() && endpoint.text().trim() === operation.path;
|
|
16816
|
+
});
|
|
16817
|
+
const main = $("main#content-container"), side = $('[id="content-side-layout"]');
|
|
16818
|
+
const content = $('[id="content-area"]');
|
|
16819
|
+
const slots = /* @__PURE__ */ new Map();
|
|
16820
|
+
const titles = [resolveValue(providers[0].title), resolveValue(providers[0].summary), ...declared.flatMap((pair) => {
|
|
16821
|
+
const values = JSON.parse(pair);
|
|
16822
|
+
return [values[0], values[2]];
|
|
16823
|
+
})].filter((value) => typeof value === "string").map((value) => value.toLowerCase());
|
|
16824
|
+
let valid = operations.length === 1 && main.length === 1 && side.length === 1 && content.length === 1 && operations.closest("#content-area")[0] === content[0] && $("[id]").filter((_index, node) => $(node).attr("id") === operations.attr("id")).length === 1 && side.closest("main")[0] === main[0];
|
|
16825
|
+
for (const [node, entry] of domGroups) {
|
|
16826
|
+
const group = $(node);
|
|
16827
|
+
const control = group.find("button[aria-expanded]").first();
|
|
16828
|
+
const owner = group.closest('[id^="api-playground-"][id$="-operation-page"]');
|
|
16829
|
+
const slot = owner[0] === operations[0] ? "inline" : group.closest("#content-side-layout")[0] === side[0] ? "sidebar" : void 0;
|
|
16830
|
+
if (!slot || slots.has(slot) || !entry.label || !entry.legacy && (!entry.title || !titles.includes(entry.title.toLowerCase()) || !control.attr("aria-label")?.trim()) || group.closest("main")[0] !== main[0] || group.closest('.mdx-content,.api-section,.object-param-field,.array-param-field,[data-component-part="expandable-content"]').length) valid = false;
|
|
16831
|
+
else slots.set(slot, entry);
|
|
16832
|
+
}
|
|
16833
|
+
if (valid && slots.size === 2 && JSON.stringify(slots.get("inline")?.code) === JSON.stringify(slots.get("sidebar")?.code)) {
|
|
16834
|
+
proofs.push(...[...slots.values()].flatMap((slot) => slot.indices));
|
|
16835
|
+
}
|
|
16836
|
+
}
|
|
16837
|
+
return proofs;
|
|
16838
|
+
}
|
|
15302
16839
|
|
|
15303
16840
|
// src/url-run.ts
|
|
15304
|
-
var CONVERTER_VERSION = "url-evidence-
|
|
15305
|
-
var
|
|
16841
|
+
var CONVERTER_VERSION = "url-evidence-v6";
|
|
16842
|
+
var parser3 = unified5().use(remarkParse5).use(remarkMdx5);
|
|
15306
16843
|
var ACCEPT = "text/markdown,text/html,application/xhtml+xml;q=0.9";
|
|
15307
16844
|
var MAX_RESPONSE_BYTES = 8e6;
|
|
15308
16845
|
var MAX_ASSET_BYTES2 = 1e7;
|
|
15309
16846
|
var MAX_RECORDS = 1e5;
|
|
15310
16847
|
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"]);
|
|
15311
16848
|
function hash2(value) {
|
|
15312
|
-
return
|
|
16849
|
+
return createHash6("sha256").update(value).digest("hex");
|
|
15313
16850
|
}
|
|
15314
16851
|
function canonicalJson(value) {
|
|
15315
16852
|
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;
|
|
@@ -15345,14 +16882,14 @@ function markdownNodes(body) {
|
|
|
15345
16882
|
nodes.push(node);
|
|
15346
16883
|
for (const child of node.children ?? []) visit(child);
|
|
15347
16884
|
};
|
|
15348
|
-
visit(
|
|
16885
|
+
visit(parser3.parse(body));
|
|
15349
16886
|
return nodes;
|
|
15350
16887
|
}
|
|
15351
16888
|
function markdownCode(body) {
|
|
15352
16889
|
return markdownNodes(body).filter((node) => node.type === "code").map((node) => node.value ?? "");
|
|
15353
16890
|
}
|
|
15354
16891
|
function alternativeBlocks(body, baseline) {
|
|
15355
|
-
const blocks = (value) => (
|
|
16892
|
+
const blocks = (value) => (parser3.parse(value).children ?? []).map((node) => value.slice(node.position.start.offset, node.position.end.offset));
|
|
15356
16893
|
const originals = new Set(blocks(baseline));
|
|
15357
16894
|
return blocks(body).filter((block) => !originals.has(block)).join("\n\n");
|
|
15358
16895
|
}
|
|
@@ -15364,7 +16901,7 @@ function linksOf(document) {
|
|
|
15364
16901
|
return [...root.find("a[href]").toArray(), ...$('link[rel="sitemap"][href],link[rel="alternate"][href]').toArray()].map((node) => $(node).attr("href")).filter(Boolean);
|
|
15365
16902
|
}
|
|
15366
16903
|
if (/xml/i.test(document.contentType) || /<urlset|<sitemapindex/i.test(document.body)) {
|
|
15367
|
-
const $ =
|
|
16904
|
+
const $ = load8(document.body, { xmlMode: true });
|
|
15368
16905
|
return $("loc").toArray().map((node) => $(node).text().trim());
|
|
15369
16906
|
}
|
|
15370
16907
|
return [
|
|
@@ -15394,7 +16931,8 @@ function evidenceOf(capture) {
|
|
|
15394
16931
|
...capture.artifactRef ? { artifactRef: capture.artifactRef } : {},
|
|
15395
16932
|
states: (capture.states ?? []).map((state) => ({ id: state.id, label: state.label, sha256: hash2(state.response.body) })),
|
|
15396
16933
|
...technical,
|
|
15397
|
-
links: linksOf(capture)
|
|
16934
|
+
links: linksOf(capture),
|
|
16935
|
+
articleIdentity: observedMigrationArticleIdentity(capture)
|
|
15398
16936
|
};
|
|
15399
16937
|
}
|
|
15400
16938
|
function markdownHeadingAnchors(body) {
|
|
@@ -15415,20 +16953,6 @@ function idForUrl(url, scope) {
|
|
|
15415
16953
|
const id = pageIdFromReference(relative7 || "introduction", true);
|
|
15416
16954
|
return id && `${id}${url.search ? `--${hash2(url.search).slice(0, 12)}` : ""}`;
|
|
15417
16955
|
}
|
|
15418
|
-
function articleIdentity(document) {
|
|
15419
|
-
if (!/html/i.test(document.contentType)) return document.finalUrl;
|
|
15420
|
-
const $ = load6(document.body);
|
|
15421
|
-
const reference = $('link[rel="canonical"][href]').first().attr("href");
|
|
15422
|
-
if (!reference) return document.finalUrl;
|
|
15423
|
-
try {
|
|
15424
|
-
const target2 = new URL(reference, document.finalUrl);
|
|
15425
|
-
const source = document.finalUrl;
|
|
15426
|
-
const directory = (path) => path.replace(/\/index\/?$/i, "").replace(/\/$/, "");
|
|
15427
|
-
return target2.origin === source.origin && !target2.username && !target2.password && target2.search === source.search && directory(target2.pathname) === directory(source.pathname) ? target2 : source;
|
|
15428
|
-
} catch {
|
|
15429
|
-
return document.finalUrl;
|
|
15430
|
-
}
|
|
15431
|
-
}
|
|
15432
16956
|
function convert(document, id) {
|
|
15433
16957
|
if (/html/i.test(document.contentType)) {
|
|
15434
16958
|
const technical = htmlEvidence(document);
|
|
@@ -15477,24 +17001,52 @@ function assetReferences(capture) {
|
|
|
15477
17001
|
...root.find("[srcset]").toArray().flatMap((node) => migrationImageCandidates($(node).attr("srcset") ?? "", capture.finalUrl).map((candidate) => candidate.url))
|
|
15478
17002
|
].filter(Boolean);
|
|
15479
17003
|
}
|
|
15480
|
-
function unresolvedStaticControls(body,
|
|
17004
|
+
function unresolvedStaticControls(body, coveredSchemaGroups = [], coveredSchemaDisclosures = [], coveredCodeControls = []) {
|
|
15481
17005
|
const { $, root } = migrationHtmlArticle(body);
|
|
17006
|
+
root.find("[aria-expanded]").each((index, node) => {
|
|
17007
|
+
if (coveredCodeControls.includes(index)) $(node).removeAttr("aria-expanded");
|
|
17008
|
+
});
|
|
15482
17009
|
root.find('[role="tablist"],[data-component-part="tabs-list"]').each((index, node) => {
|
|
15483
17010
|
if (coveredSchemaGroups.includes(index)) $(node).remove();
|
|
15484
17011
|
});
|
|
17012
|
+
root.find("details").each((index, node) => {
|
|
17013
|
+
if (coveredSchemaDisclosures.includes(index)) $(node).remove();
|
|
17014
|
+
});
|
|
15485
17015
|
const tabs = root.find('[role="tab"]').toArray();
|
|
17016
|
+
const idCounts = /* @__PURE__ */ new Map();
|
|
17017
|
+
root.find("[id]").each((_index, node) => {
|
|
17018
|
+
const id = $(node).attr("id");
|
|
17019
|
+
idCounts.set(id, (idCounts.get(id) ?? 0) + 1);
|
|
17020
|
+
});
|
|
15486
17021
|
for (const tab of tabs) {
|
|
17022
|
+
const controlId = $(tab).attr("id");
|
|
17023
|
+
if (controlId && idCounts.get(controlId) !== 1) return true;
|
|
15487
17024
|
const controls = $(tab).attr("aria-controls");
|
|
15488
|
-
const group = $(tab).closest('[role="tablist"]');
|
|
17025
|
+
const group = $(tab).closest('[role="tablist"],ul.tabs');
|
|
15489
17026
|
const container = group.closest(".code-group,.tabs-container,.tabs.tab-container");
|
|
15490
|
-
const peers = group.find('[role="tab"]').toArray().filter((node) => $(node).closest('[role="tablist"]')[0] === group[0]);
|
|
17027
|
+
const peers = group.find('[role="tab"]').toArray().filter((node) => $(node).closest('[role="tablist"],ul.tabs')[0] === group[0]);
|
|
15491
17028
|
const localPanels = container.find('[role="tabpanel"]').toArray().filter((node) => $(node).closest(".code-group,.tabs-container,.tabs.tab-container")[0] === container[0]);
|
|
15492
|
-
const owners = container.find('[role="tablist"]').toArray().filter((node) => $(node).closest(".code-group,.tabs-container,.tabs.tab-container")[0] === container[0]);
|
|
17029
|
+
const owners = container.find('[role="tablist"],ul.tabs').toArray().filter((node) => $(node).closest(".code-group,.tabs-container,.tabs.tab-container")[0] === container[0]);
|
|
15493
17030
|
const panels = controls ? root.find("[id]").filter((_index, node) => $(node).attr("id") === controls) : owners.length === 1 && peers.length === localPanels.length ? $(localPanels).eq(peers.indexOf(tab)) : $([]);
|
|
15494
|
-
if (panels.length !== 1 || !panels.text().trim() && !panels.find("pre,img,table,svg").length || panels.find('[aria-busy="true"],[role="progressbar"]').length) return true;
|
|
15495
|
-
|
|
17031
|
+
if (panels.length !== 1 || !panels.text().trim() && !panels.find("pre,img,table,svg").length || panels.is('[aria-busy="true"],[role="progressbar"]') || panels.find('[aria-busy="true"],[role="progressbar"]').length) return true;
|
|
17032
|
+
const labels2 = panels.attr("aria-labelledby")?.trim().split(/\s+/);
|
|
17033
|
+
if (labels2 && (!controlId || !labels2.includes(controlId))) return true;
|
|
17034
|
+
if (controls && !labels2 && (container.length ? panels.closest(".code-group,.tabs-container,.tabs.tab-container")[0] !== container[0] : panels.parent()[0] !== group.parent()[0])) return true;
|
|
17035
|
+
}
|
|
17036
|
+
const isCapturedImageZoom = (node, depth = 0) => {
|
|
17037
|
+
if (depth > 8) return false;
|
|
17038
|
+
const control = $(node), image = control.prev("span.zoom-image-trigger[data-ramka-trigger]");
|
|
17039
|
+
return control.is('button[data-ramka-trigger][aria-haspopup="dialog"][aria-label]') && Boolean(control.attr("aria-label")?.trim()) && !control.attr("aria-controls") && !control.text().trim() && image.find("img[src]").length === 1 && !image.text().trim() && !image.find("form,iframe,object,embed,canvas").length && image.find("button").toArray().every((button) => isCapturedImageZoom(button, depth + 1));
|
|
17040
|
+
};
|
|
17041
|
+
if (root.find("[aria-expanded]").toArray().some((node) => {
|
|
17042
|
+
const control = $(node);
|
|
17043
|
+
if (control.attr("role") === "tab") return false;
|
|
17044
|
+
const actions = control.parent('[id="page-context-menu"]');
|
|
17045
|
+
if (control.is('button[aria-haspopup="menu"]') && !control.attr("aria-controls") && !control.text().trim() && actions.closest("header").length && actions.children("button#page-context-menu-button").length === 1) return false;
|
|
17046
|
+
if (isCapturedImageZoom(node)) return false;
|
|
17047
|
+
return true;
|
|
17048
|
+
})) return true;
|
|
15496
17049
|
return root.find("details:not([open])").toArray().some((node) => {
|
|
15497
|
-
if (hasApiSchema && $(node).is(".expandable") && $(node).children('summary[data-component-part="expandable-button"]').length) return false;
|
|
15498
17050
|
const clone = $(node).clone();
|
|
15499
17051
|
clone.children("summary").remove();
|
|
15500
17052
|
return !clone.text().trim() && !clone.find("pre,img,table,svg").length;
|
|
@@ -15532,7 +17084,7 @@ function acceptedAsset(asset) {
|
|
|
15532
17084
|
}
|
|
15533
17085
|
function validRecord(record) {
|
|
15534
17086
|
if (record.outcome !== "imported") return true;
|
|
15535
|
-
return Boolean(record.page && record.pageSha256 === pageHash(record.page) && record.evidence && pageIdFromReference(record.page.id, true) === record.page.id && pageIdFromReference(record.page.navigationId, true) === record.page.navigationId && sanitizeRemoteMarkdown(record.page.body.replace(/^<a id="[^"<]*" \/>$/gm, "")) !== null && /^[a-f0-9]{64}$/.test(record.evidence.sha256) && (!record.apiSpecification || hasCompleteLocalApiSchema(record.apiSpecification.document) && record.apiSpecification.path === `openapi/migration-${record.apiSpecification.sha256}.json` && hash2(canonicalJson(record.apiSpecification.document)) === record.apiSpecification.sha256) && record.assets?.every((asset) => /^migration-assets\/[a-f0-9]{64}\.[a-z0-9]+$/.test(asset.path) && hash2(Buffer.from(asset.base64, "base64")) === asset.sha256));
|
|
17087
|
+
return Boolean(record.page && record.pageSha256 === pageHash(record.page) && record.evidence && pageIdFromReference(record.page.id, true) === record.page.id && pageIdFromReference(record.page.navigationId, true) === record.page.navigationId && sanitizeRemoteMarkdown(record.page.body.replace(/^<a id="[^"<]*" \/>$/gm, "")) !== null && /^[a-f0-9]{64}$/.test(record.evidence.sha256) && (!record.apiSpecification || hasCompleteLocalApiSchema(record.apiSpecification.document) && record.apiSpecification.path === `openapi/migration-${record.apiSpecification.sha256}.json` && hash2(canonicalJson(record.apiSpecification.document)) === record.apiSpecification.sha256) && record.assets?.every((asset) => /^migration-assets\/[a-f0-9]{64}\.[a-z0-9]+$/.test(asset.path) && (!asset.derivedFromSha256 || /^[a-f0-9]{64}$/.test(asset.derivedFromSha256)) && hash2(Buffer.from(asset.base64, "base64")) === asset.sha256));
|
|
15536
17088
|
}
|
|
15537
17089
|
function hasCompleteLocalApiSchema(document) {
|
|
15538
17090
|
let visited = 0;
|
|
@@ -15638,7 +17190,7 @@ function observedLocale(document, id, scopePath) {
|
|
|
15638
17190
|
}
|
|
15639
17191
|
const urlLocale = [id.split("/", 1)[0], ...scopePath.split("/"), document.finalUrl.pathname.split("/").filter(Boolean)[0]].find((segment) => segment && LOCALES.has(segment.toLowerCase()));
|
|
15640
17192
|
if (urlLocale) candidates.push({ source: "URL", value: canonicalLanguage(urlLocale) });
|
|
15641
|
-
const declared = /html/i.test(document.contentType) ?
|
|
17193
|
+
const declared = /html/i.test(document.contentType) ? load8(document.body)("html").attr("lang")?.trim() : void 0;
|
|
15642
17194
|
if (declared) {
|
|
15643
17195
|
const locale = canonicalLanguage(declared);
|
|
15644
17196
|
if (locale) candidates.push({ source: "html lang", value: locale });
|
|
@@ -15742,14 +17294,14 @@ function validateUrlMigration(checkpoint, cancelled = false) {
|
|
|
15742
17294
|
continue;
|
|
15743
17295
|
}
|
|
15744
17296
|
if (!inScope(link, source, checkpoint.scopePath)) continue;
|
|
15745
|
-
if (isDiscoveryIndex(link, source)) continue;
|
|
17297
|
+
if (isDiscoveryIndex(link, source) || isMigrationUtilityUrl(link)) continue;
|
|
15746
17298
|
if (/\.(?:png|jpe?g|gif|svg|webp|avif|pdf|zip|mp4|webm|css|js|json|ya?ml)$/i.test(link.pathname)) continue;
|
|
15747
17299
|
const destination = resolve5(link.toString());
|
|
15748
17300
|
if (!destination || !["imported", "excluded"].includes(destination.outcome)) {
|
|
15749
17301
|
issues.push({ code: "missing-page", source: record.url, message: `Unresolved internal destination: ${link}` });
|
|
15750
|
-
} else if (link.hash && destination.outcome === "imported") {
|
|
15751
|
-
let anchor = link.hash.slice(1);
|
|
15752
|
-
try {
|
|
17302
|
+
} else if ((link.hash || records.get(canonical(link.href, checkpoint.sourceUrl) ?? "")?.aliasAnchor) && destination.outcome === "imported") {
|
|
17303
|
+
let anchor = link.hash.slice(1) || records.get(canonical(link.href, checkpoint.sourceUrl) ?? "").aliasAnchor;
|
|
17304
|
+
if (link.hash) try {
|
|
15753
17305
|
anchor = decodeURIComponent(anchor);
|
|
15754
17306
|
} catch {
|
|
15755
17307
|
}
|
|
@@ -15770,7 +17322,7 @@ function validateUrlMigration(checkpoint, cancelled = false) {
|
|
|
15770
17322
|
const locale = node.locale ? canonicalLanguage(node.locale) : parentLocale;
|
|
15771
17323
|
if (node.url) {
|
|
15772
17324
|
const url = new URL(node.url, source);
|
|
15773
|
-
if (inScope(url, source, checkpoint.scopePath)) {
|
|
17325
|
+
if (inScope(url, source, checkpoint.scopePath) && !isMigrationUtilityUrl(url)) {
|
|
15774
17326
|
const destination = resolve5(url.toString());
|
|
15775
17327
|
if (destination?.outcome === "excluded" && destination.redirectTo) continue;
|
|
15776
17328
|
const page = destination?.page;
|
|
@@ -15838,6 +17390,7 @@ async function runUrlMigration(options) {
|
|
|
15838
17390
|
delete record.redirectTo;
|
|
15839
17391
|
delete record.reason;
|
|
15840
17392
|
delete record.aliasOf;
|
|
17393
|
+
delete record.aliasAnchor;
|
|
15841
17394
|
}
|
|
15842
17395
|
if (record.page && pageIdFromReference(record.page.id, true) !== record.page.id) throw new Error("Checkpoint contains an unsafe page path.");
|
|
15843
17396
|
records.set(record.url, record);
|
|
@@ -15848,7 +17401,8 @@ async function runUrlMigration(options) {
|
|
|
15848
17401
|
const enqueue = (value, base, discoveredBy) => {
|
|
15849
17402
|
const url = canonical(value, base);
|
|
15850
17403
|
if (!url || !inScope(new URL(url), source, scopePath) && !isDiscoveryIndex(new URL(url), source)) return;
|
|
15851
|
-
const
|
|
17404
|
+
const isUtility = isMigrationUtilityUrl(new URL(url));
|
|
17405
|
+
const isAttachment = isUtility || discoveredBy !== "submitted" && /\.(?:json|ya?ml)$/i.test(new URL(url).pathname);
|
|
15852
17406
|
const existing = records.get(url);
|
|
15853
17407
|
if (existing) {
|
|
15854
17408
|
if (!existing.discoveredBy.includes(discoveredBy)) {
|
|
@@ -15862,7 +17416,7 @@ async function runUrlMigration(options) {
|
|
|
15862
17416
|
url,
|
|
15863
17417
|
discoveredBy: [discoveredBy],
|
|
15864
17418
|
outcome: isAttachment ? "excluded" : "pending",
|
|
15865
|
-
...isAttachment ? { reason: "Machine-readable attachment, not an authored article." } : {}
|
|
17419
|
+
...isAttachment ? { reason: isUtility ? "Recognized provider utility endpoint, not an authored article." : "Machine-readable attachment, not an authored article." } : {}
|
|
15866
17420
|
};
|
|
15867
17421
|
records.set(url, record);
|
|
15868
17422
|
checkpoint.records.push(record);
|
|
@@ -15905,12 +17459,27 @@ async function runUrlMigration(options) {
|
|
|
15905
17459
|
let imported = usedIds.size;
|
|
15906
17460
|
const assetPayloads = new Map(checkpoint.records.flatMap((record) => (record.assets ?? []).map((asset) => [asset.sha256, asset])));
|
|
15907
17461
|
const assetBytes = /* @__PURE__ */ new Map();
|
|
15908
|
-
const
|
|
17462
|
+
const rasterizedSvgs = /* @__PURE__ */ new Map();
|
|
17463
|
+
const retainAsset = async (original) => {
|
|
17464
|
+
let asset = { ...original };
|
|
17465
|
+
delete asset.derivedFromSha256;
|
|
15909
17466
|
if (asset.unavailable) {
|
|
15910
17467
|
if ([404, 410].includes(asset.unavailable.status) && asset.content.byteLength === 0) return asset;
|
|
15911
17468
|
throw new Error("Invalid source asset availability evidence.");
|
|
15912
17469
|
}
|
|
15913
|
-
if (!acceptedAsset(asset))
|
|
17470
|
+
if (!acceptedAsset(asset)) {
|
|
17471
|
+
if (asset.content.byteLength > MAX_ASSET_BYTES2 || asset.contentType.split(";", 1)[0].trim().toLowerCase() !== "image/svg+xml" || !options.rasterizeSvg) throw new Error("Asset MIME/signature is unsupported or unsafe to serve.");
|
|
17472
|
+
const sourceSha256 = hash2(asset.content);
|
|
17473
|
+
let rendering = rasterizedSvgs.get(sourceSha256);
|
|
17474
|
+
if (!rendering) {
|
|
17475
|
+
rendering = options.rasterizeSvg({ ...asset, content: Buffer.from(asset.content) }, options.signal).then((rendered) => {
|
|
17476
|
+
if (rendered.unavailable || rendered.contentType.split(";", 1)[0].trim().toLowerCase() !== "image/png" || acceptedAsset(rendered) !== "png") throw new Error("Trusted SVG renderer did not return a bounded PNG image.");
|
|
17477
|
+
return { ...rendered, derivedFromSha256: sourceSha256 };
|
|
17478
|
+
});
|
|
17479
|
+
rasterizedSvgs.set(sourceSha256, rendering);
|
|
17480
|
+
}
|
|
17481
|
+
asset = { ...await rendering, url: original.url };
|
|
17482
|
+
}
|
|
15914
17483
|
const sha256 = hash2(asset.content);
|
|
15915
17484
|
const content = assetBytes.get(sha256) ?? Buffer.from(asset.content);
|
|
15916
17485
|
assetBytes.set(sha256, content);
|
|
@@ -15926,6 +17495,26 @@ async function runUrlMigration(options) {
|
|
|
15926
17495
|
}
|
|
15927
17496
|
let totalBytes = checkpoint.records.reduce((sum, record) => sum + (record.evidence?.byteLength ?? 0), 0) + [...assetPayloads.values()].reduce((sum, asset) => sum + Buffer.byteLength(asset.base64, "base64"), 0);
|
|
15928
17497
|
let budgetExhausted = false;
|
|
17498
|
+
const exactCaptures = /* @__PURE__ */ new Map();
|
|
17499
|
+
const exactCaptureKey = (document) => {
|
|
17500
|
+
let body = document.body;
|
|
17501
|
+
if (body.includes("data-cfemail")) {
|
|
17502
|
+
const $ = load8(body);
|
|
17503
|
+
projectProtectedEmails($, $.root());
|
|
17504
|
+
body = $.html();
|
|
17505
|
+
}
|
|
17506
|
+
return hash2(canonicalJson([
|
|
17507
|
+
hash2(body),
|
|
17508
|
+
document.contentType,
|
|
17509
|
+
document.status,
|
|
17510
|
+
document.locale,
|
|
17511
|
+
document.version,
|
|
17512
|
+
document.headers?.["content-language"],
|
|
17513
|
+
document.navigation,
|
|
17514
|
+
(document.states ?? []).map((state) => [state.id, state.label, state.response.finalUrl.href, state.response.contentType, state.response.status, hash2(state.response.body)]),
|
|
17515
|
+
(document.assets ?? []).map((asset) => [asset.url, asset.contentType, asset.unavailable, hash2(asset.content)])
|
|
17516
|
+
]));
|
|
17517
|
+
};
|
|
15929
17518
|
let cursor = 0;
|
|
15930
17519
|
const flush = async () => {
|
|
15931
17520
|
const distinct = [...new Map(changed.map((record) => [record.url, record])).values()];
|
|
@@ -15940,6 +17529,7 @@ async function runUrlMigration(options) {
|
|
|
15940
17529
|
let claimedId;
|
|
15941
17530
|
let claimedFinal;
|
|
15942
17531
|
let markdownRepresentation;
|
|
17532
|
+
let exactKey;
|
|
15943
17533
|
try {
|
|
15944
17534
|
delete record.reason;
|
|
15945
17535
|
if (/\/llms-full\.txt$/i.test(new URL(record.url).pathname)) {
|
|
@@ -15967,7 +17557,43 @@ async function runUrlMigration(options) {
|
|
|
15967
17557
|
throw new Error("Capture returned an unresolved redirect.");
|
|
15968
17558
|
}
|
|
15969
17559
|
if (Buffer.byteLength(document.body) > MAX_RESPONSE_BYTES) throw new Error("Captured response exceeds the 8 MB safety bound.");
|
|
15970
|
-
|
|
17560
|
+
if ((document.states?.length ?? 0) > 64 || (document.assets?.length ?? 0) > 256) throw new Error("Capture contains too many alternative states or assets.");
|
|
17561
|
+
for (const state of document.states ?? []) if (Buffer.byteLength(state.response.body) > MAX_RESPONSE_BYTES) throw new Error("Alternative state exceeds the 8 MB safety bound.");
|
|
17562
|
+
if (/html/i.test(document.contentType) && (!document.status || document.status < 300) && inScope(document.finalUrl, source, scopePath)) {
|
|
17563
|
+
exactKey = exactCaptureKey(document);
|
|
17564
|
+
const peer = resolveMigrationRecord(records, records.get(exactCaptures.get(exactKey) ?? ""));
|
|
17565
|
+
const peerIdentity = peer?.evidence?.articleIdentity;
|
|
17566
|
+
if (peer?.outcome === "imported" && peer.evidence && peerIdentity) {
|
|
17567
|
+
const candidate = migrationSectionQueryCandidate(document.finalUrl, peer.evidence.anchors);
|
|
17568
|
+
if (candidate.sectionAnchor && candidate.canonicalUrl === peerIdentity.canonicalUrl) {
|
|
17569
|
+
const byteLength = Buffer.byteLength(document.body) + (document.states ?? []).reduce((sum, state) => sum + Buffer.byteLength(state.response.body), 0);
|
|
17570
|
+
totalBytes += byteLength;
|
|
17571
|
+
if (totalBytes > (options.maxTotalBytes ?? 5e8)) {
|
|
17572
|
+
budgetExhausted = true;
|
|
17573
|
+
throw new Error("Migration exceeded its content byte budget.");
|
|
17574
|
+
}
|
|
17575
|
+
record.outcome = "alias";
|
|
17576
|
+
record.aliasOf = peer.url;
|
|
17577
|
+
record.aliasAnchor = candidate.sectionAnchor;
|
|
17578
|
+
if (peerIdentity.sectionAnchor && peer.aliasAnchor !== peerIdentity.sectionAnchor) {
|
|
17579
|
+
peer.aliasAnchor = peerIdentity.sectionAnchor;
|
|
17580
|
+
changed.push(peer);
|
|
17581
|
+
}
|
|
17582
|
+
record.evidence = {
|
|
17583
|
+
...peer.evidence,
|
|
17584
|
+
sha256: hash2(document.body),
|
|
17585
|
+
byteLength,
|
|
17586
|
+
finalUrl: document.finalUrl.href,
|
|
17587
|
+
...document.artifactRef ? { artifactRef: document.artifactRef } : {},
|
|
17588
|
+
articleIdentity: { ...peerIdentity, sectionAnchor: candidate.sectionAnchor }
|
|
17589
|
+
};
|
|
17590
|
+
if (!document.artifactRef) delete record.evidence.artifactRef;
|
|
17591
|
+
enqueueArticleLinks(record.evidence.links, document.finalUrl.href, record.url);
|
|
17592
|
+
return;
|
|
17593
|
+
}
|
|
17594
|
+
}
|
|
17595
|
+
}
|
|
17596
|
+
const identity = declaredMigrationArticleUrl(document);
|
|
15971
17597
|
const final = canonical(identity.toString(), sourceUrl);
|
|
15972
17598
|
const role = classifyMigrationResponse(document);
|
|
15973
17599
|
if (!inScope(document.finalUrl, source, scopePath) && !(role === "index" && isDiscoveryIndex(document.finalUrl, source))) {
|
|
@@ -15991,13 +17617,13 @@ async function runUrlMigration(options) {
|
|
|
15991
17617
|
return;
|
|
15992
17618
|
}
|
|
15993
17619
|
if (/html/i.test(document.contentType)) {
|
|
15994
|
-
const $ =
|
|
17620
|
+
const $ = load8(document.body);
|
|
15995
17621
|
$('link[rel="alternate"][type="text/markdown"][href]').each((_index, node) => {
|
|
15996
17622
|
const alternate = canonical($(node).attr("href"), final);
|
|
15997
17623
|
if (!alternate) return;
|
|
15998
17624
|
const target2 = new URL(alternate), primary = new URL(final);
|
|
15999
|
-
const
|
|
16000
|
-
if (target2.origin !== primary.origin || target2.search !== primary.search ||
|
|
17625
|
+
const directory2 = (path) => path.replace(/\.mdx?$/i, "").replace(/\/index\/?$/i, "").replace(/\/$/, "");
|
|
17626
|
+
if (target2.origin !== primary.origin || target2.search !== primary.search || directory2(target2.pathname) !== directory2(primary.pathname) || !/\.mdx?$/i.test(target2.pathname)) return;
|
|
16001
17627
|
enqueue(alternate, final, "declared-markdown-representation");
|
|
16002
17628
|
const sibling = records.get(alternate);
|
|
16003
17629
|
sibling.representationOf = record.url;
|
|
@@ -16048,6 +17674,9 @@ async function runUrlMigration(options) {
|
|
|
16048
17674
|
return;
|
|
16049
17675
|
}
|
|
16050
17676
|
let coveredSchemaGroups = [];
|
|
17677
|
+
let coveredSchemaDisclosures = [];
|
|
17678
|
+
let coveredCodeControls = [];
|
|
17679
|
+
let schemaOperation;
|
|
16051
17680
|
const hasSchemaChoice = /html/i.test(document.contentType) && migrationHtmlArticle(document.body).root.find('select[aria-label="Select schema type"],select[aria-label="\u9009\u62E9\u67B6\u6784\u7C7B\u578B"]').length > 0;
|
|
16052
17681
|
if (/html/i.test(document.contentType) && markdownRepresentation && (unresolvedStaticControls(document.body) || hasSchemaChoice)) {
|
|
16053
17682
|
const schemaCapture = await capture({ url: new URL(markdownRepresentation), signal: options.signal });
|
|
@@ -16063,7 +17692,10 @@ async function runUrlMigration(options) {
|
|
|
16063
17692
|
const path = `openapi/migration-${sha256}.json`;
|
|
16064
17693
|
record.apiSpecification = { path, sha256, document: fragment.document };
|
|
16065
17694
|
page.openapi = `${path} ${fragment.method} ${fragment.path}`;
|
|
17695
|
+
schemaOperation = fragment;
|
|
16066
17696
|
coveredSchemaGroups = apiSchemaTabGroups(document.body, fragment.document, fragment);
|
|
17697
|
+
coveredSchemaDisclosures = apiSchemaDisclosureGroups(document.body, fragment.document, fragment);
|
|
17698
|
+
coveredCodeControls = apiOperationCodeControls(document.body, fragment.document, fragment);
|
|
16067
17699
|
}
|
|
16068
17700
|
}
|
|
16069
17701
|
const states = document.states ?? [];
|
|
@@ -16094,12 +17726,13 @@ ${difference}`;
|
|
|
16094
17726
|
record.assets = [];
|
|
16095
17727
|
record.issues = [];
|
|
16096
17728
|
record.warnings = [];
|
|
16097
|
-
|
|
16098
|
-
|
|
17729
|
+
for (const captured of [document, ...states.map((state) => state.response)]) {
|
|
17730
|
+
if (!/html/i.test(captured.contentType)) continue;
|
|
17731
|
+
const { $, root } = migrationHtmlArticle(captured.body);
|
|
16099
17732
|
root.find("nav,footer,aside,.theme-doc-breadcrumbs,.theme-doc-toc-mobile,.table-of-contents,.hash-link").remove();
|
|
16100
17733
|
root.find('button svg,a.hash-link svg,[aria-hidden="true"] svg,svg[aria-hidden="true"],svg[data-lucide],svg[data-icon]').remove();
|
|
16101
17734
|
root.find("video,iframe").each((_index, node) => {
|
|
16102
|
-
if (projectMigrationMedia($.html(node),
|
|
17735
|
+
if (projectMigrationMedia($.html(node), captured.finalUrl) !== null) {
|
|
16103
17736
|
record.warnings.push({ code: "source-asset-warning", source: record.url, message: "Embedded video is preserved at its original public media URL; playback depends on the original host." });
|
|
16104
17737
|
$(node).remove();
|
|
16105
17738
|
}
|
|
@@ -16110,9 +17743,17 @@ ${difference}`;
|
|
|
16110
17743
|
}
|
|
16111
17744
|
const unsupported = [...new Set(root.find("iframe,object,embed,canvas,svg,form,input,textarea,select,math,video,audio").toArray().map((node) => node.tagName))];
|
|
16112
17745
|
if (unsupported.length) record.issues.push({ code: "unsupported-component", source: record.url, message: `Rendered content requires explicit review for: ${unsupported.join(", ")}.` });
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
17746
|
+
const groups = captured === document ? coveredSchemaGroups : record.apiSpecification && schemaOperation ? apiSchemaTabGroups(captured.body, record.apiSpecification.document, schemaOperation) : [];
|
|
17747
|
+
const disclosures = captured === document ? coveredSchemaDisclosures : record.apiSpecification && schemaOperation ? apiSchemaDisclosureGroups(captured.body, record.apiSpecification.document, schemaOperation) : [];
|
|
17748
|
+
const codeControls = captured === document ? coveredCodeControls : record.apiSpecification && schemaOperation ? apiOperationCodeControls(captured.body, record.apiSpecification.document, schemaOperation) : [];
|
|
17749
|
+
if (unresolvedStaticControls(captured.body, groups, disclosures, codeControls)) record.issues.push({ code: "unsupported-component", source: record.url, message: "An interactive alternative has no complete captured panel or disclosure content." });
|
|
17750
|
+
}
|
|
17751
|
+
const inlineAssets = [document, ...states.map((state) => state.response)].flatMap((captured) => /html/i.test(captured.contentType) ? migrationHtmlArticle(captured.body).assets.map((asset) => ({
|
|
17752
|
+
url: new URL(`/${asset.path}`, captured.finalUrl).href,
|
|
17753
|
+
contentType: "image/svg+xml",
|
|
17754
|
+
content: typeof asset.content === "string" ? Buffer.from(asset.content) : asset.content
|
|
17755
|
+
})) : []);
|
|
17756
|
+
const suppliedAssets = new Map([...document.assets ?? [], ...inlineAssets].map((asset) => [canonical(asset.url, final), asset]));
|
|
16116
17757
|
const assetUrls = [...new Set([...assetReferences(document), ...states.flatMap((state) => assetReferences(state.response))].map((url) => canonical(url, final)).filter((url) => Boolean(url)))];
|
|
16117
17758
|
if (assetUrls.length > 256 || (document.assets?.length ?? 0) > 256) throw new Error("Capture exceeds the 256 assets per page safety bound.");
|
|
16118
17759
|
for (const url of assetUrls) {
|
|
@@ -16122,7 +17763,7 @@ ${difference}`;
|
|
|
16122
17763
|
assetRequest = assetRequests.load(url, () => assetFetcher(new URL(url), options.signal).then(retainAsset));
|
|
16123
17764
|
}
|
|
16124
17765
|
const supplied = suppliedAssets.get(url);
|
|
16125
|
-
const asset = supplied ? retainAsset(supplied) : assetRequest ? await assetRequest : null;
|
|
17766
|
+
const asset = supplied ? await retainAsset(supplied) : assetRequest ? await assetRequest : null;
|
|
16126
17767
|
if (!asset) throw new Error("Capture host did not supply asset bytes or a binary fetch boundary.");
|
|
16127
17768
|
if (asset.unavailable && [404, 410].includes(asset.unavailable.status) && asset.content.byteLength === 0) {
|
|
16128
17769
|
record.warnings.push({ code: "asset-failed", source: record.url, message: `The original source asset is unavailable (HTTP ${asset.unavailable.status}); its original URL was retained: ${url}` });
|
|
@@ -16141,7 +17782,7 @@ ${difference}`;
|
|
|
16141
17782
|
}
|
|
16142
17783
|
}
|
|
16143
17784
|
const path = `migration-assets/${sha256}.${extension}`;
|
|
16144
|
-
const receipt = { url, path, sha256, contentType: asset.contentType, base64: existing?.base64 ?? Buffer.from(asset.content).toString("base64") };
|
|
17785
|
+
const receipt = { url, path, sha256, contentType: asset.contentType, base64: existing?.base64 ?? Buffer.from(asset.content).toString("base64"), ...asset.derivedFromSha256 ? { derivedFromSha256: asset.derivedFromSha256 } : {} };
|
|
16145
17786
|
record.assets.push(receipt);
|
|
16146
17787
|
if (!existing) assetPayloads.set(sha256, receipt);
|
|
16147
17788
|
if (!assetRequests.has(url)) assetRequests.remember(url, asset);
|
|
@@ -16166,6 +17807,7 @@ ${difference}`;
|
|
|
16166
17807
|
record.pageSha256 = pageHash(page);
|
|
16167
17808
|
record.outcome = "imported";
|
|
16168
17809
|
imported++;
|
|
17810
|
+
if (exactKey) exactCaptures.set(exactKey, record.url);
|
|
16169
17811
|
enqueueArticleLinks(evidence.links, final, record.url);
|
|
16170
17812
|
} catch (error) {
|
|
16171
17813
|
if (options.signal?.aborted) return;
|
|
@@ -16191,6 +17833,43 @@ ${difference}`;
|
|
|
16191
17833
|
}
|
|
16192
17834
|
}
|
|
16193
17835
|
};
|
|
17836
|
+
const settleArticleIdentities = () => {
|
|
17837
|
+
const groups = /* @__PURE__ */ new Map();
|
|
17838
|
+
for (const record of records.values()) {
|
|
17839
|
+
const identity = record.evidence?.articleIdentity;
|
|
17840
|
+
if (record.outcome !== "imported" || !identity) continue;
|
|
17841
|
+
const key = JSON.stringify([identity.canonicalUrl, identity.articleSha256]);
|
|
17842
|
+
const group = groups.get(key) ?? [];
|
|
17843
|
+
group.push(record);
|
|
17844
|
+
groups.set(key, group);
|
|
17845
|
+
}
|
|
17846
|
+
for (const group of groups.values()) {
|
|
17847
|
+
if (group.length < 2) continue;
|
|
17848
|
+
const canonicalUrl = group[0].evidence.articleIdentity.canonicalUrl;
|
|
17849
|
+
const winner = group.find((record) => record.url === canonicalUrl) ?? group[0];
|
|
17850
|
+
const winnerAnchor = winner.evidence.articleIdentity.sectionAnchor;
|
|
17851
|
+
if (winnerAnchor && winner.aliasAnchor !== winnerAnchor) {
|
|
17852
|
+
winner.aliasAnchor = winnerAnchor;
|
|
17853
|
+
changed.push(winner);
|
|
17854
|
+
}
|
|
17855
|
+
for (const alternate of group) {
|
|
17856
|
+
if (alternate === winner) continue;
|
|
17857
|
+
imported--;
|
|
17858
|
+
if (alternate.page && usedIds.get(alternate.page.id) === alternate.url) usedIds.delete(alternate.page.id);
|
|
17859
|
+
alternate.outcome = "alias";
|
|
17860
|
+
alternate.aliasOf = winner.url;
|
|
17861
|
+
alternate.aliasAnchor = alternate.evidence.articleIdentity.sectionAnchor;
|
|
17862
|
+
delete alternate.page;
|
|
17863
|
+
delete alternate.pageSha256;
|
|
17864
|
+
delete alternate.assets;
|
|
17865
|
+
delete alternate.apiSpecification;
|
|
17866
|
+
delete alternate.issues;
|
|
17867
|
+
delete alternate.warnings;
|
|
17868
|
+
delete alternate.reason;
|
|
17869
|
+
changed.push(alternate);
|
|
17870
|
+
}
|
|
17871
|
+
}
|
|
17872
|
+
};
|
|
16194
17873
|
const settleRepresentations = () => {
|
|
16195
17874
|
for (const record of records.values()) {
|
|
16196
17875
|
if (!record.representationOf) continue;
|
|
@@ -16216,6 +17895,7 @@ ${difference}`;
|
|
|
16216
17895
|
}
|
|
16217
17896
|
};
|
|
16218
17897
|
settleRepresentations();
|
|
17898
|
+
settleArticleIdentities();
|
|
16219
17899
|
while (cursor < pending.length && !options.signal?.aborted && !budgetExhausted && cursor < (options.maxCaptures ?? Infinity)) {
|
|
16220
17900
|
if (imported >= maxPages) {
|
|
16221
17901
|
const index = pending.findIndex((record, position) => position >= cursor && isDiscoveryIndex(new URL(record.url), source));
|
|
@@ -16226,6 +17906,7 @@ ${difference}`;
|
|
|
16226
17906
|
cursor += batch.length;
|
|
16227
17907
|
await Promise.all(batch.map(process2));
|
|
16228
17908
|
settleRepresentations();
|
|
17909
|
+
settleArticleIdentities();
|
|
16229
17910
|
if (changed.length >= batchSize) await flush();
|
|
16230
17911
|
}
|
|
16231
17912
|
await flush();
|
|
@@ -16245,7 +17926,7 @@ ${difference}`;
|
|
|
16245
17926
|
for (const node of nodes) {
|
|
16246
17927
|
const entry = node.url ? records.get(canonical(node.url, sourceUrl) ?? "") : void 0;
|
|
16247
17928
|
const target2 = resolveMigrationRecord(records, entry);
|
|
16248
|
-
if (target2?.page && node.label && !node.children?.length) {
|
|
17929
|
+
if (target2?.page && node.label && !node.children?.length && !entry?.aliasAnchor) {
|
|
16249
17930
|
const previous = navigationLabels.get(target2.url);
|
|
16250
17931
|
if (previous && previous !== node.label) navigationIssues.push({ code: "unsupported-component", source: target2.url, message: `This page has multiple source navigation labels (${previous}, ${node.label}); review the shared sidebar title.` });
|
|
16251
17932
|
else navigationLabels.set(target2.url, node.label);
|
|
@@ -16270,8 +17951,9 @@ ${difference}`;
|
|
|
16270
17951
|
anchor = decodeURIComponent(anchor);
|
|
16271
17952
|
} catch {
|
|
16272
17953
|
}
|
|
17954
|
+
const effectiveHash = url.hash || (records.get(identity)?.aliasAnchor ? `#${encodeURIComponent(records.get(identity).aliasAnchor)}` : "");
|
|
16273
17955
|
const hasBrokenSourceAnchor = Boolean(url.hash && destination?.outcome === "imported" && destination.evidence && !destination.evidence.anchors.includes(anchor));
|
|
16274
|
-
return `${route}${hasBrokenSourceAnchor ? "" :
|
|
17956
|
+
return `${route}${hasBrokenSourceAnchor ? "" : effectiveHash}`;
|
|
16275
17957
|
}) }] : []);
|
|
16276
17958
|
const validation = validateUrlMigration(checkpoint, Boolean(options.signal?.aborted));
|
|
16277
17959
|
validation.issues.push(...navigationIssues);
|
|
@@ -16350,7 +18032,7 @@ function rewriteMarkdownDestinations(body, rewrite) {
|
|
|
16350
18032
|
}
|
|
16351
18033
|
|
|
16352
18034
|
// src/remote-api.ts
|
|
16353
|
-
import { createHash as
|
|
18035
|
+
import { createHash as createHash7 } from "crypto";
|
|
16354
18036
|
import { lookup } from "dns/promises";
|
|
16355
18037
|
import { request } from "https";
|
|
16356
18038
|
import { isIP } from "net";
|
|
@@ -16514,7 +18196,7 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
16514
18196
|
}
|
|
16515
18197
|
const { format: extension, document } = parseSpecDocument(body.toString("utf8"));
|
|
16516
18198
|
const operations = parseOpenApi(document);
|
|
16517
|
-
const filename = `openapi-${
|
|
18199
|
+
const filename = `openapi-${createHash7("sha256").update(reference.url).digest("hex").slice(0, 12)}.${extension}`;
|
|
16518
18200
|
if (!assets.some((asset) => asset.path === `openapi/${filename}`)) assets.push({ path: `openapi/${filename}`, content: body, projectRelative: true });
|
|
16519
18201
|
for (const page of pages) {
|
|
16520
18202
|
const ref = page.openapi ? splitOpenApiRef(page.openapi) : null;
|
|
@@ -16534,18 +18216,18 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
16534
18216
|
}
|
|
16535
18217
|
}
|
|
16536
18218
|
const directories = [
|
|
16537
|
-
...(bundle.localApiMounts ?? []).map(({ directory }) =>
|
|
16538
|
-
...bundle.remoteApiSpecs.flatMap((reference) => (reference.directories ?? []).map(({ directory }) =>
|
|
18219
|
+
...(bundle.localApiMounts ?? []).map(({ directory: directory2 }) => directory2),
|
|
18220
|
+
...bundle.remoteApiSpecs.flatMap((reference) => (reference.directories ?? []).map(({ directory: directory2 }) => directory2))
|
|
16539
18221
|
];
|
|
16540
18222
|
const endpointRedirects = linkApiMounts(
|
|
16541
18223
|
[
|
|
16542
|
-
...(bundle.localApiMounts ?? []).map(({ filename, directory, tab }) => ({
|
|
18224
|
+
...(bundle.localApiMounts ?? []).map(({ filename, directory: directory2, tab }) => ({
|
|
16543
18225
|
filename,
|
|
16544
18226
|
content: Buffer.from(assets.find((asset) => asset.path === `openapi/${filename}`)?.content ?? []),
|
|
16545
|
-
prefix:
|
|
18227
|
+
prefix: directory2,
|
|
16546
18228
|
...tab ? { tab } : {}
|
|
16547
18229
|
})),
|
|
16548
|
-
...bound.flatMap(({ reference, filename, content, tabName }) => (reference.directories ?? []).map(({ directory, operations: listed }) => ({ filename, content, prefix:
|
|
18230
|
+
...bound.flatMap(({ reference, filename, content, tabName }) => (reference.directories ?? []).map(({ directory: directory2, operations: listed }) => ({ filename, content, prefix: directory2, tab: tabName, ...listed ? { operations: listed } : {} })))
|
|
16549
18231
|
],
|
|
16550
18232
|
{ ...bundle.docsConfig, tabs, redirects },
|
|
16551
18233
|
pages,
|
|
@@ -16563,7 +18245,7 @@ async function hydrateRemoteApiSpecs(bundle, fetcher) {
|
|
|
16563
18245
|
const specIds = apiTabSpecIds(tabs);
|
|
16564
18246
|
for (const { reference, filename, operations, tabName } of bound) {
|
|
16565
18247
|
const specId = specIds.find(({ tab }) => tab.tab === tabName && tab.api?.source === `openapi/${filename}`)?.specId;
|
|
16566
|
-
const listed = reference.directories?.length && reference.directories.every((
|
|
18248
|
+
const listed = reference.directories?.length && reference.directories.every((directory2) => directory2.operations) ? new Set(reference.directories.flatMap((directory2) => directory2.operations ?? []).map((name) => name.trim().split(/\s+/)).map(([method, ...path]) => `${method.toLowerCase()} ${path.join(" ")}`)) : null;
|
|
16567
18249
|
for (const operation of operations) {
|
|
16568
18250
|
if (listed && !listed.has(`${operation.method} ${operation.path}`)) continue;
|
|
16569
18251
|
const key = `${slug(operation.tag)}/${slug(operation.summary)}`;
|