@thallylabs/migrate 0.2.43 → 0.2.45
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 +215 -26
- package/dist/index.d.ts +32 -7
- package/dist/index.js +2624 -1068
- package/dist/index.js.map +1 -1
- package/dist/url-migration.d.ts +2 -2
- package/dist/url-migration.js +213 -54
- package/dist/url-migration.js.map +1 -1
- package/dist/{url-run-CPzQfjRW.d.ts → url-run-D-E4dr2h.d.ts} +9 -1
- package/package.json +2 -1
package/dist/url-migration.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { h as MigrationCapture } from './url-run-
|
|
2
|
-
export { a as MigrationAsset, f as MigrationBundle, i as MigrationCaptureProvider, j as MigrationCaptureState, k as MigrationCapturedAsset, g as MigrationDocsConfig, l as MigrationEvidence, m as MigrationFetchRequest, n as MigrationFetchResponse, d as MigrationFetcher, o as MigrationJournalAsset, b as MigrationNavigationGroup, p as MigrationNavigationOccurrence, q as MigrationNavigationTab, M as MigrationPage, e as MigrationPlatform, c as MigrationWarning, R as RenderedMigrationFile, U as UrlMigrationCheckpoint, r as UrlMigrationCheckpointDelta, s as UrlMigrationIssue, t as UrlMigrationRecord, u as UrlMigrationRun, v as UrlMigrationRunOptions, w as UrlMigrationValidation, x as classifyMigrationResponse, z as renderMigrationFiles, A as runUrlMigration, B as validateUrlMigration } from './url-run-
|
|
1
|
+
import { h as MigrationCapture } from './url-run-D-E4dr2h.js';
|
|
2
|
+
export { a as MigrationAsset, f as MigrationBundle, i as MigrationCaptureProvider, j as MigrationCaptureState, k as MigrationCapturedAsset, g as MigrationDocsConfig, l as MigrationEvidence, m as MigrationFetchRequest, n as MigrationFetchResponse, d as MigrationFetcher, o as MigrationJournalAsset, b as MigrationNavigationGroup, p as MigrationNavigationOccurrence, q as MigrationNavigationTab, M as MigrationPage, e as MigrationPlatform, c as MigrationWarning, R as RenderedMigrationFile, U as UrlMigrationCheckpoint, r as UrlMigrationCheckpointDelta, s as UrlMigrationIssue, t as UrlMigrationRecord, u as UrlMigrationRun, v as UrlMigrationRunOptions, w as UrlMigrationValidation, x as classifyMigrationResponse, z as renderMigrationFiles, A as runUrlMigration, B as validateUrlMigration } from './url-run-D-E4dr2h.js';
|
|
3
3
|
|
|
4
4
|
interface UrlMigrationScope {
|
|
5
5
|
scopePath: string;
|
package/dist/url-migration.js
CHANGED
|
@@ -56,6 +56,32 @@ function playgroundDisplay(value, where, warn) {
|
|
|
56
56
|
return void 0;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
// src/redirects.ts
|
|
60
|
+
function trimTrailingSlashes(route) {
|
|
61
|
+
let end = route.length;
|
|
62
|
+
while (end > 0 && route[end - 1] === "/") end--;
|
|
63
|
+
return route.slice(0, end);
|
|
64
|
+
}
|
|
65
|
+
function exactRoute(route) {
|
|
66
|
+
return route.startsWith("/") && !/[?:*#()[\]{}]/.test(route) ? trimTrailingSlashes(route) || "/" : null;
|
|
67
|
+
}
|
|
68
|
+
function literalRoute(route) {
|
|
69
|
+
return exactRoute(route)?.toLowerCase() ?? null;
|
|
70
|
+
}
|
|
71
|
+
function resolveDotSegments(route) {
|
|
72
|
+
const segments = [];
|
|
73
|
+
for (const segment of route.split("/").slice(1)) {
|
|
74
|
+
const dots = segment.replace(/%2e/gi, ".");
|
|
75
|
+
if (dots === "..") segments.pop();
|
|
76
|
+
else if (dots !== ".") segments.push(segment);
|
|
77
|
+
}
|
|
78
|
+
return `/${segments.join("/")}`;
|
|
79
|
+
}
|
|
80
|
+
function destinationRoute(destination) {
|
|
81
|
+
const route = destination.startsWith("//") ? null : exactRoute(destination.split(/[?#]/, 1)[0]);
|
|
82
|
+
return route === null ? null : resolveDotSegments(route);
|
|
83
|
+
}
|
|
84
|
+
|
|
59
85
|
// src/navigation.ts
|
|
60
86
|
function titleCase(value) {
|
|
61
87
|
return value.split(/[-_]/).map((word) => ["api", "cli", "sdk", "ui"].includes(word.toLowerCase()) ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
@@ -1270,9 +1296,9 @@ function recoverFlightArticleCode($, root) {
|
|
|
1270
1296
|
const projectionBudget = expansionBudget();
|
|
1271
1297
|
recoverFlightTreeTabs($, root, projectionBudget);
|
|
1272
1298
|
const renderedHeadings = root.find("h1,h2,h3,h4,h5,h6").toArray().filter((node) => $(node).attr("data-thally-static-disclosure-heading") === void 0);
|
|
1273
|
-
const
|
|
1299
|
+
const headingText2 = renderedHeadings.map((node) => labelText($(node).text()));
|
|
1274
1300
|
const existingCode = root.find("pre").toArray().map((node) => renderedCode($, node));
|
|
1275
|
-
if (!
|
|
1301
|
+
if (!headingText2.length || !existingCode.length) return;
|
|
1276
1302
|
const prose = root.clone();
|
|
1277
1303
|
prose.find("pre,button,script,style,nav,footer,aside").remove();
|
|
1278
1304
|
const renderedProse = labelText(prose.text());
|
|
@@ -1285,7 +1311,7 @@ function recoverFlightArticleCode($, root) {
|
|
|
1285
1311
|
const anchor = /\s+\[#([A-Za-z\d_.:-]+)\]$/.exec(text2);
|
|
1286
1312
|
return anchor && $(renderedHeadings[index]).attr("id") === anchor[1] ? text2.slice(0, anchor.index) : text2;
|
|
1287
1313
|
});
|
|
1288
|
-
if (JSON.stringify(headings) !== JSON.stringify(
|
|
1314
|
+
if (JSON.stringify(headings) !== JSON.stringify(headingText2)) continue;
|
|
1289
1315
|
let proseCursor = 0;
|
|
1290
1316
|
let hasMatchingProse = true;
|
|
1291
1317
|
for (const paragraph of nodes.filter((node) => node.type === "paragraph" || node.type === "tableCell")) {
|
|
@@ -1902,6 +1928,7 @@ import { createHash as createHash2 } from "crypto";
|
|
|
1902
1928
|
import { lookup } from "dns/promises";
|
|
1903
1929
|
import { request } from "https";
|
|
1904
1930
|
import { isIP } from "net";
|
|
1931
|
+
import { createGunzip } from "zlib";
|
|
1905
1932
|
|
|
1906
1933
|
// src/spec-exclude.ts
|
|
1907
1934
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
@@ -1911,6 +1938,7 @@ var HOSTNAME_LABEL = "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?";
|
|
|
1911
1938
|
var HOSTNAME = new RegExp(`^${HOSTNAME_LABEL}(?:\\.${HOSTNAME_LABEL})*$`);
|
|
1912
1939
|
|
|
1913
1940
|
// src/mdx.ts
|
|
1941
|
+
import { analyze } from "eslint-scope";
|
|
1914
1942
|
import { posix } from "path";
|
|
1915
1943
|
import { compileSync } from "@mdx-js/mdx";
|
|
1916
1944
|
import { nameToEmoji } from "gemoji";
|
|
@@ -2398,6 +2426,14 @@ function parseFrontmatter(raw) {
|
|
|
2398
2426
|
}
|
|
2399
2427
|
}
|
|
2400
2428
|
|
|
2429
|
+
// src/source-styles.ts
|
|
2430
|
+
import postcss from "postcss";
|
|
2431
|
+
import selectorParser from "postcss-selector-parser";
|
|
2432
|
+
import ts2 from "typescript";
|
|
2433
|
+
var CONTENT_CONTAINER = ".thally-docs-prose";
|
|
2434
|
+
var SOURCE_PAGE_ATTRIBUTE = "data-thally-source-page";
|
|
2435
|
+
var SCOPE = `:where(${CONTENT_CONTAINER}, [${SOURCE_PAGE_ATTRIBUTE}])`;
|
|
2436
|
+
|
|
2401
2437
|
// src/fence-meta.ts
|
|
2402
2438
|
import remarkParse2 from "remark-parse";
|
|
2403
2439
|
import { unified as unified2 } from "unified";
|
|
@@ -2495,11 +2531,31 @@ function titleFromId(id) {
|
|
|
2495
2531
|
return value.split(/[-_]/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
2496
2532
|
}
|
|
2497
2533
|
var descriptionParser = unified3().use(remarkParse3).use(remarkGfm2).use(remarkMdx2);
|
|
2498
|
-
function plainText(node) {
|
|
2534
|
+
function plainText(node, elements) {
|
|
2535
|
+
if (elements && (node.type === "mdxJsxTextElement" || node.type === "mdxJsxFlowElement")) {
|
|
2536
|
+
elements.found = true;
|
|
2537
|
+
return "";
|
|
2538
|
+
}
|
|
2499
2539
|
if (node.type === "text" || node.type === "inlineCode") return node.value ?? "";
|
|
2500
2540
|
if (node.type === "image") return node.alt ?? "";
|
|
2501
2541
|
if (node.type === "break") return " ";
|
|
2502
|
-
return (node.children ?? []).map(plainText).join("");
|
|
2542
|
+
return (node.children ?? []).map((child) => plainText(child, elements)).join("");
|
|
2543
|
+
}
|
|
2544
|
+
function headingText(content, definitions, elements) {
|
|
2545
|
+
const references = [...content.matchAll(/\[([^\]\n]+)\]/g)].map((match) => definitions?.get(match[1].trim().replace(/\s+/g, " ").toLowerCase()) ?? "").join("\n");
|
|
2546
|
+
try {
|
|
2547
|
+
return plainText(descriptionParser.parse(`# ${content}
|
|
2548
|
+
|
|
2549
|
+
${references}`), elements).trim();
|
|
2550
|
+
} catch {
|
|
2551
|
+
return content;
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
function mdxTextWithoutInlineElements(content, definitions) {
|
|
2555
|
+
if (!/<[A-Za-z]/.test(content)) return void 0;
|
|
2556
|
+
const elements = { found: false };
|
|
2557
|
+
const text2 = headingText(content, definitions, elements);
|
|
2558
|
+
return elements.found && /[\p{L}\p{M}\p{N}]/u.test(text2) ? text2 : void 0;
|
|
2503
2559
|
}
|
|
2504
2560
|
function firstParagraph(content) {
|
|
2505
2561
|
function findParagraph(node) {
|
|
@@ -2519,6 +2575,23 @@ function firstParagraph(content) {
|
|
|
2519
2575
|
return "";
|
|
2520
2576
|
}
|
|
2521
2577
|
}
|
|
2578
|
+
var linkParser = unified3().use(remarkParse3);
|
|
2579
|
+
function withoutMarkdownLinks(text2) {
|
|
2580
|
+
const links = [];
|
|
2581
|
+
const collect = (node) => {
|
|
2582
|
+
if (node.type === "link") {
|
|
2583
|
+
const first = node.children?.[0]?.position?.start.offset;
|
|
2584
|
+
const last = node.children?.at(-1)?.position?.end.offset;
|
|
2585
|
+
const start = node.position?.start.offset;
|
|
2586
|
+
const end = node.position?.end.offset;
|
|
2587
|
+
if (start !== void 0 && end !== void 0) links.push({ start, end, textStart: first ?? start, textEnd: last ?? start });
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
for (const child of node.children ?? []) collect(child);
|
|
2591
|
+
};
|
|
2592
|
+
collect(linkParser.parse(text2));
|
|
2593
|
+
return links.reduceRight((result, link) => result.slice(0, link.start) + result.slice(link.textStart, link.textEnd) + result.slice(link.end), text2);
|
|
2594
|
+
}
|
|
2522
2595
|
function docusaurusAdmonitionTag(kind) {
|
|
2523
2596
|
if (kind === "danger") return "Error";
|
|
2524
2597
|
if (kind === "info") return "Info";
|
|
@@ -2723,9 +2796,9 @@ ${trimmed.slice(0, marker).trimEnd()}`;
|
|
|
2723
2796
|
function headingIdMarker(id) {
|
|
2724
2797
|
return `{/* #${id} */}`;
|
|
2725
2798
|
}
|
|
2726
|
-
var HEADING_ID_WORD = /[\p{L}\p{M}\p{N}_
|
|
2799
|
+
var HEADING_ID_WORD = /[\p{L}\p{M}\p{N}_+&/@%=<>|\u2019\u201c\u201d\u2014\u2013\u2192\u2026]/u;
|
|
2727
2800
|
function mintlifyHeadingSlug(text2) {
|
|
2728
|
-
const chars = [...text2.replace(/[\u200b*]/g, "").normalize("NFC").trim().toLowerCase()];
|
|
2801
|
+
const chars = [...text2.replace(/[\u200b*]/g, "").replace(/(?<=[\p{L}\p{M}\p{N}_])\(s\)(?![\p{L}\p{M}\p{N}_])/gu, "s").normalize("NFC").trim().toLowerCase()];
|
|
2729
2802
|
const isWord = (char) => char !== void 0 && HEADING_ID_WORD.test(char);
|
|
2730
2803
|
let id = "";
|
|
2731
2804
|
let afterDash = false;
|
|
@@ -2737,11 +2810,11 @@ function mintlifyHeadingSlug(text2) {
|
|
|
2737
2810
|
if (isWord(char)) {
|
|
2738
2811
|
id += char;
|
|
2739
2812
|
afterDash = false;
|
|
2740
|
-
} else if (/[\s-]/.test(char) || char === "." && isWord(after) || char === "(" && isWord(before) && (isWord(after) || after === "{") || char === ")" && after !== void 0 && !/\s/.test(after)) {
|
|
2813
|
+
} else if (/[\s-]/.test(char) || char === "." && (isWord(after) || after === ",") || char === "(" && isWord(before) && (isWord(after) || after === "{") || char === ")" && after !== void 0 && !/\s/.test(after)) {
|
|
2741
2814
|
if (id && !afterDash) id += "-";
|
|
2742
2815
|
afterDash = true;
|
|
2743
2816
|
endsWithDash = true;
|
|
2744
|
-
} else if (char === "{" || char === ":" || char === '"') {
|
|
2817
|
+
} else if (char === "{" || char === ":" || char === '"' || char === ",") {
|
|
2745
2818
|
afterDash = false;
|
|
2746
2819
|
}
|
|
2747
2820
|
});
|
|
@@ -2751,17 +2824,77 @@ function thallyHeadingSlug(text2) {
|
|
|
2751
2824
|
return text2.normalize("NFC").toLowerCase().replace(/[^\p{L}\p{M}\p{N}]+/gu, "-").replace(/(^-|-$)/g, "");
|
|
2752
2825
|
}
|
|
2753
2826
|
function typesetQuotes(text2) {
|
|
2827
|
+
const opensClosed = text2.startsWith('"') && !text2.trimEnd().endsWith('"');
|
|
2754
2828
|
return text2.split(/(`[^`]*`|<[^>]*>|\]\([^)]*\))/).map((part, index) => {
|
|
2755
2829
|
if (index % 2) return part;
|
|
2756
|
-
return part.replace(/(^|[\s([{\u2014\u2013])"/g, "
|
|
2830
|
+
return part.replace(/(^|[\s([{\u2014\u2013])"/g, (match, before) => opensClosed && index === 0 && before === "" ? match : `${before}\u201C`).replace(/"/g, "\u201D").replace(/(^|[\s([{\u2014\u2013\u201c])'(?=\S)(?!<|<)/g, "$1\u2018").replace(/'/g, "\u2019");
|
|
2757
2831
|
}).join("");
|
|
2758
2832
|
}
|
|
2833
|
+
function typesetEllipses(text2) {
|
|
2834
|
+
return text2.split(/(`[^`]*`|<[^>]*>|\]\([^)]*\))/).map((part, index) => index % 2 ? part : part.replace(/\.{3}/g, "\u2026")).join("");
|
|
2835
|
+
}
|
|
2759
2836
|
function plainHeadingText(source) {
|
|
2760
|
-
|
|
2837
|
+
const unlinked = !source.includes("`") ? source : source.replace(/(`[^`]*`)|!?\[((?:`[^`]*`|[^\]`])*)\]\([^)]*\)/g, (_match, code, text2 = "") => code ?? text2);
|
|
2838
|
+
return unlinked.split(/(`[^`]*`)/).map((part, index) => index % 2 ? part.slice(1, -1) : part.replace(/\{\/\*[\s\S]*?\*\/\}/g, " ").replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/<\/?[A-Za-z][^>]*>/g, "").replace(/(?<!\\)(\*\*|__|~~|\*)/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/\\([\\`*_{}[\]()#+.!&<>|~-])/g, "$1")).join("");
|
|
2839
|
+
}
|
|
2840
|
+
function staticAttributeString(value) {
|
|
2841
|
+
if (typeof value === "string") return value;
|
|
2842
|
+
const expression = value?.value;
|
|
2843
|
+
if (typeof expression !== "string") return void 0;
|
|
2844
|
+
return expression.match(/^\s*(?:"([^"\\]*)"|'([^'\\]*)'|`((?:[^`\\$]|\$(?!\{))*)`)\s*$/)?.slice(1).find((part) => part !== void 0);
|
|
2845
|
+
}
|
|
2846
|
+
function pageIdClaims(body) {
|
|
2847
|
+
let tree;
|
|
2848
|
+
try {
|
|
2849
|
+
tree = descriptionParser.parse(body);
|
|
2850
|
+
} catch {
|
|
2851
|
+
return { free: () => false };
|
|
2852
|
+
}
|
|
2853
|
+
const owners = /* @__PURE__ */ new Map();
|
|
2854
|
+
const headingLines = /* @__PURE__ */ new Set();
|
|
2855
|
+
let claims = 0;
|
|
2856
|
+
const root = (id) => id.toLowerCase().replace(/-\d+$/, "");
|
|
2857
|
+
const claim = (owner, ...ids) => {
|
|
2858
|
+
for (const id of ids) {
|
|
2859
|
+
const key = root(id);
|
|
2860
|
+
const held = owners.get(key);
|
|
2861
|
+
if (!key) continue;
|
|
2862
|
+
if (!held) owners.set(key, { owner, shared: false });
|
|
2863
|
+
else if (held.owner !== owner) held.shared = true;
|
|
2864
|
+
}
|
|
2865
|
+
};
|
|
2866
|
+
const visit = (node) => {
|
|
2867
|
+
const line = node.position?.start.line ?? 0;
|
|
2868
|
+
if (node.type === "heading" && (node.depth ?? 0) >= 2) {
|
|
2869
|
+
headingLines.add(line);
|
|
2870
|
+
const text2 = typesetQuotes(plainText(node));
|
|
2871
|
+
claim(`heading ${line}`, mintlifyHeadingSlug(text2), thallyHeadingSlug(text2), thallyHeadingSlug(plainText(node, { found: false })));
|
|
2872
|
+
for (const child of node.children ?? []) {
|
|
2873
|
+
const authored = child.type === "mdxTextExpression" ? child.value?.match(/^\s*\/\*\s*#(\S+?)\s*\*\/\s*$/)?.[1] : void 0;
|
|
2874
|
+
if (authored) claim(`claim ${claims++}`, authored);
|
|
2875
|
+
}
|
|
2876
|
+
} else if (node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") {
|
|
2877
|
+
for (const { type, name, value } of node.attributes ?? []) {
|
|
2878
|
+
const text2 = type === "mdxJsxAttribute" ? staticAttributeString(value) : void 0;
|
|
2879
|
+
if (text2 === void 0) continue;
|
|
2880
|
+
if (name === "id") claim(`claim ${claims++}`, text2);
|
|
2881
|
+
else if (name === "title") claim(`claim ${claims++}`, mintlifyHeadingSlug(text2), thallyHeadingSlug(text2));
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
for (const child of node.children ?? []) visit(child);
|
|
2885
|
+
};
|
|
2886
|
+
visit(tree);
|
|
2887
|
+
return {
|
|
2888
|
+
free: (id, line) => {
|
|
2889
|
+
const held = owners.get(root(id));
|
|
2890
|
+
return headingLines.has(line) && (!held || held.owner === `heading ${line}` && !held.shared);
|
|
2891
|
+
}
|
|
2892
|
+
};
|
|
2761
2893
|
}
|
|
2762
2894
|
function markMintlifyHeadings(body) {
|
|
2763
2895
|
let fence;
|
|
2764
|
-
|
|
2896
|
+
let claims;
|
|
2897
|
+
return body.split("\n").map((line, index) => {
|
|
2765
2898
|
const marker = line.match(/^ {0,3}(`{3,}|~{3,})/);
|
|
2766
2899
|
if (marker) {
|
|
2767
2900
|
if (!fence) fence = marker[1];
|
|
@@ -2775,8 +2908,13 @@ function markMintlifyHeadings(body) {
|
|
|
2775
2908
|
const source = typesetQuotes(explicit ? explicit[1] : heading[2]);
|
|
2776
2909
|
if (explicit) return `${heading[1]}${source}${explicit[2]}`;
|
|
2777
2910
|
const text2 = plainHeadingText(source);
|
|
2778
|
-
const id = mintlifyHeadingSlug(
|
|
2779
|
-
|
|
2911
|
+
const id = mintlifyHeadingSlug(plainHeadingText(typesetEllipses(source)));
|
|
2912
|
+
let marked = id !== thallyHeadingSlug(text2);
|
|
2913
|
+
if (id && !marked) {
|
|
2914
|
+
const visible = mdxTextWithoutInlineElements(source);
|
|
2915
|
+
if (visible !== void 0 && id !== thallyHeadingSlug(visible)) marked = (claims ??= pageIdClaims(body)).free(id, index + 1);
|
|
2916
|
+
}
|
|
2917
|
+
return `${heading[1]}${source}${id && marked ? ` ${headingIdMarker(id)}` : ""}`;
|
|
2780
2918
|
}).join("\n");
|
|
2781
2919
|
}
|
|
2782
2920
|
var GLOBAL_DOCUSARUS_COMPONENTS = /* @__PURE__ */ new Set([
|
|
@@ -2792,6 +2930,7 @@ function removeGlobalDocusaurusImports(body) {
|
|
|
2792
2930
|
(statement, component) => GLOBAL_DOCUSARUS_COMPONENTS.has(component) ? "" : statement
|
|
2793
2931
|
));
|
|
2794
2932
|
}
|
|
2933
|
+
var PLAIN_TEXT = new RegExp("^\\p{L}(?:[\\p{L}\\p{N} ,.;'?%$=+-]*[\\p{L}\\p{N}.])?$", "u");
|
|
2795
2934
|
function leadingPageHeading(body) {
|
|
2796
2935
|
if (!/^ {0,3}(?:#(?:[ \t]|$)|=+[ \t\r]*$)/m.test(body)) return void 0;
|
|
2797
2936
|
try {
|
|
@@ -2904,6 +3043,27 @@ function normalizeFernFileTrees(body) {
|
|
|
2904
3043
|
}
|
|
2905
3044
|
));
|
|
2906
3045
|
}
|
|
3046
|
+
function unwrapHtmlCommentInMdxComment(body) {
|
|
3047
|
+
return replaceOutsideCode(body, (text2) => {
|
|
3048
|
+
const opener = /\{\s*\/\*\s*<!--/g;
|
|
3049
|
+
const closer = /\s*\*\/\s*\}/y;
|
|
3050
|
+
let out = "";
|
|
3051
|
+
let copied = 0;
|
|
3052
|
+
let dash = -2;
|
|
3053
|
+
let star = -2;
|
|
3054
|
+
for (let found = opener.exec(text2); found; found = opener.exec(text2)) {
|
|
3055
|
+
const inner = opener.lastIndex;
|
|
3056
|
+
if (dash !== -1 && dash < inner) dash = text2.indexOf("-->", inner);
|
|
3057
|
+
if (dash === -1) break;
|
|
3058
|
+
if (star !== -1 && star < inner) star = text2.indexOf("*/", inner);
|
|
3059
|
+
closer.lastIndex = dash + 3;
|
|
3060
|
+
if (star !== -1 && star < dash || !closer.test(text2)) continue;
|
|
3061
|
+
out += `${text2.slice(copied, found.index)}{/*${text2.slice(inner, dash)}*/}`;
|
|
3062
|
+
copied = opener.lastIndex = closer.lastIndex;
|
|
3063
|
+
}
|
|
3064
|
+
return out + text2.slice(copied);
|
|
3065
|
+
});
|
|
3066
|
+
}
|
|
2907
3067
|
function normalizeFernCallouts(body) {
|
|
2908
3068
|
return replaceOutsideCode(body, (whole) => {
|
|
2909
3069
|
const openTags = [];
|
|
@@ -3468,6 +3628,7 @@ function normalizeMdx(body, platform, unwrapMdxCodeBlocks = true) {
|
|
|
3468
3628
|
rewritten = rewritten.replace(/^\n{2,}/, "\n");
|
|
3469
3629
|
}
|
|
3470
3630
|
if (runMintlify) rewritten = normalizeMintlifyParameterAnchors(rewritten);
|
|
3631
|
+
rewritten = unwrapHtmlCommentInMdxComment(rewritten);
|
|
3471
3632
|
rewritten = replaceOutsideCode(rewritten, (segment) => {
|
|
3472
3633
|
let result = convertHtmlStyleAttributes(segment).replace(/<!--([\s\S]*?)-->/g, (_match, content) => mdxComment(content)).replace(/<Danger(\s[^>]*)?>/g, "<Error$1>").replace(/<\/Danger>/g, "</Error>").replace(/<Warn(\s[^>]*)?>/g, "<Warning$1>").replace(/<\/Warn>/g, "</Warning>").replace(/<Tree\.Folder/g, "<Folder").replace(/<\/Tree\.Folder>/g, "</Folder>").replace(/<Tree\.File/g, "<File").replace(/<\/Tree\.File>/g, "</File>");
|
|
3473
3634
|
if (runDocusaurus) {
|
|
@@ -3497,8 +3658,15 @@ function normalizeMdx(body, platform, unwrapMdxCodeBlocks = true) {
|
|
|
3497
3658
|
}
|
|
3498
3659
|
return normalizeFlowParagraphContainers(normalized);
|
|
3499
3660
|
}
|
|
3661
|
+
var SITE_PATH_LINK = /^\/(?:[A-Za-z0-9._~-]+(?:\/[A-Za-z0-9._~-]+)*\/?)?(?:\?(?:[A-Za-z0-9._~=&-]|%[0-9A-Fa-f]{2})*)?(?:#[A-Za-z0-9._~-]+)?$/;
|
|
3662
|
+
var MAX_SITE_PATH_LINK_LENGTH = 2e3;
|
|
3663
|
+
function sitePathLink(url) {
|
|
3664
|
+
if (url.length > MAX_SITE_PATH_LINK_LENGTH || url.includes("__ESC_") || !SITE_PATH_LINK.test(url)) return void 0;
|
|
3665
|
+
return url.split(/[?#]/, 1)[0].split("/").some((segment) => segment === "." || segment === "..") ? void 0 : url;
|
|
3666
|
+
}
|
|
3500
3667
|
function externalPageUrl(value) {
|
|
3501
3668
|
const url = typeof value === "string" ? value.trim() : "";
|
|
3669
|
+
if (url.startsWith("/")) return sitePathLink(url);
|
|
3502
3670
|
if (!/^https?:\/\/[^\s]+$/i.test(url)) return void 0;
|
|
3503
3671
|
try {
|
|
3504
3672
|
new URL(url);
|
|
@@ -3546,7 +3714,9 @@ function parseMarkdownPage(input) {
|
|
|
3546
3714
|
const body = removeUndefinedExpressions(injectReactHookImports(input.platform === "mintlify" ? normalizeMintlifyCodeFences(normalized, input.warn) : normalized), input.warn).trim();
|
|
3547
3715
|
const keywords = Array.isArray(parsed.data.keywords) ? parsed.data.keywords.filter((value) => typeof value === "string") : [];
|
|
3548
3716
|
const heading = leadingPageHeading(body);
|
|
3549
|
-
const
|
|
3717
|
+
const authoredTitle = typeof parsed.data.title === "string" && parsed.data.title.trim() ? parsed.data.title.trim() : heading?.title;
|
|
3718
|
+
const title = authoredTitle ?? titleFromId(identity.navigationId);
|
|
3719
|
+
const namesOperation = typeof parsed.data.openapi === "string" && Boolean(parsed.data.openapi.trim());
|
|
3550
3720
|
const sidebarTitle = input.platform === "docusaurus" ? parsed.data.sidebar_label : parsed.data.sidebarTitle;
|
|
3551
3721
|
const navTitle = typeof sidebarTitle === "string" && sidebarTitle.trim() ? sidebarTitle.trim() : typeof parsed.data.navTitle === "string" && parsed.data.navTitle.trim() ? parsed.data.navTitle.trim() : void 0;
|
|
3552
3722
|
const icon = typeof parsed.data.icon === "string" && parsed.data.icon.trim() ? parsed.data.icon.trim() : void 0;
|
|
@@ -3559,18 +3729,25 @@ function parseMarkdownPage(input) {
|
|
|
3559
3729
|
const badge = typeof parsed.data.tag === "string" && parsed.data.tag.trim() ? parsed.data.tag.trim() : typeof parsed.data.badge === "string" && parsed.data.badge.trim() ? parsed.data.badge.trim() : void 0;
|
|
3560
3730
|
const sourceMode = typeof parsed.data.mode === "string" ? parsed.data.mode : void 0;
|
|
3561
3731
|
const mode = sourceMode === "frame" ? "wide" : ["default", "wide", "custom", "center", "home"].includes(sourceMode ?? "") ? sourceMode : void 0;
|
|
3732
|
+
if (input.platform === "mintlify" && typeof parsed.data.url === "string" && parsed.data.url.trim().startsWith("/") && !externalPageUrl(parsed.data.url)) {
|
|
3733
|
+
const shown = parsed.data.url.trim();
|
|
3734
|
+
input.warn?.(`Page "${identity.id}": its "url" frontmatter ${JSON.stringify(shown.length > 80 ? `${shown.slice(0, 80)}...` : shown)} was not turned into a link, so the page was kept with its own content. Only a site path made of letters, digits and . _ ~ - segments, with an optional ?key=value query and #id fragment, can become a link.`);
|
|
3735
|
+
}
|
|
3562
3736
|
const externalUrl = input.platform === "mintlify" ? externalPageUrl(parsed.data.url) : void 0;
|
|
3563
|
-
const
|
|
3737
|
+
const authoredDescription = typeof parsed.data.description === "string" && parsed.data.description.trim() ? parsed.data.description.trim() : void 0;
|
|
3738
|
+
const description = authoredDescription ?? (namesOperation ? "" : firstParagraph(body));
|
|
3564
3739
|
const page = {
|
|
3565
3740
|
id: identity.id,
|
|
3566
3741
|
navigationId: identity.navigationId,
|
|
3567
3742
|
locale: identity.locale,
|
|
3568
3743
|
title,
|
|
3744
|
+
...authoredTitle === void 0 && namesOperation ? { titleFromFileName: true } : {},
|
|
3569
3745
|
navTitle,
|
|
3570
3746
|
icon,
|
|
3571
3747
|
iconType,
|
|
3572
3748
|
description,
|
|
3573
|
-
|
|
3749
|
+
// A description taken from the body is the paragraph the body already shows, so it must not also appear under the title.
|
|
3750
|
+
...input.platform === "docusaurus" || input.platform === "fern" || authoredDescription === void 0 && description !== "" ? { descriptionPlacement: "body" } : {},
|
|
3574
3751
|
badge,
|
|
3575
3752
|
keywords,
|
|
3576
3753
|
mode,
|
|
@@ -3585,6 +3762,12 @@ function parseMarkdownPage(input) {
|
|
|
3585
3762
|
source: input.source,
|
|
3586
3763
|
...parsed.error ? { frontmatterError: parsed.error } : {}
|
|
3587
3764
|
};
|
|
3765
|
+
const writtenDescription = typeof parsed.data.description === "string" ? parsed.data.description.trim() : "";
|
|
3766
|
+
const plainDescription2 = withoutMarkdownLinks(writtenDescription);
|
|
3767
|
+
if (plainDescription2 !== writtenDescription) {
|
|
3768
|
+
page.description = plainDescription2;
|
|
3769
|
+
input.warn?.(`Page "${identity.id}": its description had links, which Thally shows as plain text; the link text was kept.`);
|
|
3770
|
+
}
|
|
3588
3771
|
resolvePageDisplayHeading(page, input.platform);
|
|
3589
3772
|
return page;
|
|
3590
3773
|
}
|
|
@@ -3738,32 +3921,6 @@ function projectCapturedTabs($, root) {
|
|
|
3738
3921
|
}
|
|
3739
3922
|
}
|
|
3740
3923
|
|
|
3741
|
-
// src/redirects.ts
|
|
3742
|
-
function trimTrailingSlashes(route) {
|
|
3743
|
-
let end = route.length;
|
|
3744
|
-
while (end > 0 && route[end - 1] === "/") end--;
|
|
3745
|
-
return route.slice(0, end);
|
|
3746
|
-
}
|
|
3747
|
-
function exactRoute(route) {
|
|
3748
|
-
return route.startsWith("/") && !/[?:*#()[\]{}]/.test(route) ? trimTrailingSlashes(route) || "/" : null;
|
|
3749
|
-
}
|
|
3750
|
-
function literalRoute(route) {
|
|
3751
|
-
return exactRoute(route)?.toLowerCase() ?? null;
|
|
3752
|
-
}
|
|
3753
|
-
function resolveDotSegments(route) {
|
|
3754
|
-
const segments = [];
|
|
3755
|
-
for (const segment of route.split("/").slice(1)) {
|
|
3756
|
-
const dots = segment.replace(/%2e/gi, ".");
|
|
3757
|
-
if (dots === "..") segments.pop();
|
|
3758
|
-
else if (dots !== ".") segments.push(segment);
|
|
3759
|
-
}
|
|
3760
|
-
return `/${segments.join("/")}`;
|
|
3761
|
-
}
|
|
3762
|
-
function destinationRoute(destination) {
|
|
3763
|
-
const route = destination.startsWith("//") ? null : exactRoute(destination.split(/[?#]/, 1)[0]);
|
|
3764
|
-
return route === null ? null : resolveDotSegments(route);
|
|
3765
|
-
}
|
|
3766
|
-
|
|
3767
3924
|
// src/url.ts
|
|
3768
3925
|
var MAX_LOCAL_RESPONSE_BYTES = 8e6;
|
|
3769
3926
|
var MAX_EMBEDDED_SCHEMA_BYTES = 2e6;
|
|
@@ -4822,6 +4979,8 @@ ${fence}
|
|
|
4822
4979
|
navigationId: id,
|
|
4823
4980
|
title,
|
|
4824
4981
|
description: description || plainDescription(body) || `Documentation imported from ${document.finalUrl.hostname}.`,
|
|
4982
|
+
// A description taken from the page text is already in the body; only one the site published is shown under the title.
|
|
4983
|
+
...description ? {} : { descriptionPlacement: "body" },
|
|
4825
4984
|
keywords: [],
|
|
4826
4985
|
body,
|
|
4827
4986
|
source: document.finalUrl.toString()
|
|
@@ -6651,11 +6810,11 @@ function rewriteMarkdownDestinations(body, rewrite) {
|
|
|
6651
6810
|
import { createHash as createHash6 } from "crypto";
|
|
6652
6811
|
import { existsSync as existsSync2, lstatSync as lstatSync2, readFileSync as readFileSync2 } from "fs";
|
|
6653
6812
|
import { basename, dirname as dirname2, extname as extname3, posix as posix2, relative as relative3, resolve as resolve3 } from "path";
|
|
6654
|
-
import
|
|
6655
|
-
import
|
|
6813
|
+
import postcss2 from "postcss";
|
|
6814
|
+
import selectorParser2 from "postcss-selector-parser";
|
|
6656
6815
|
import remarkMdx5 from "remark-mdx";
|
|
6657
6816
|
import remarkParse6 from "remark-parse";
|
|
6658
|
-
import
|
|
6817
|
+
import ts3 from "typescript";
|
|
6659
6818
|
import { unified as unified6 } from "unified";
|
|
6660
6819
|
var parser3 = unified6().use(remarkParse6).use(remarkMdx5);
|
|
6661
6820
|
var DOCUSAURUS_THEME_SHIMS = {
|
|
@@ -6700,29 +6859,29 @@ function hash2(value) {
|
|
|
6700
6859
|
return createHash6("sha256").update(value).digest("hex").slice(0, 12);
|
|
6701
6860
|
}
|
|
6702
6861
|
function sourceFile(source, filename) {
|
|
6703
|
-
return
|
|
6862
|
+
return ts3.createSourceFile(filename, source, ts3.ScriptTarget.Latest, true, scriptKindFor(filename));
|
|
6704
6863
|
}
|
|
6705
6864
|
function mergeComponentRegistry(existing, incoming) {
|
|
6706
6865
|
const fingerprint = hash2(incoming);
|
|
6707
6866
|
const name = `MigratedRegistry${fingerprint}`;
|
|
6708
6867
|
const registryPath = `./migrated-components-${fingerprint}`;
|
|
6709
6868
|
const source = sourceFile(existing, "custom-components.tsx");
|
|
6710
|
-
const alreadyImported = source.statements.some((statement) =>
|
|
6869
|
+
const alreadyImported = source.statements.some((statement) => ts3.isImportDeclaration(statement) && ts3.isStringLiteral(statement.moduleSpecifier) && statement.moduleSpecifier.text === registryPath);
|
|
6711
6870
|
let initializer;
|
|
6712
6871
|
for (const statement of source.statements) {
|
|
6713
|
-
if (!
|
|
6872
|
+
if (!ts3.isVariableStatement(statement) || !statement.modifiers?.some((modifier) => modifier.kind === ts3.SyntaxKind.ExportKeyword)) continue;
|
|
6714
6873
|
for (const declaration of statement.declarationList.declarations) {
|
|
6715
|
-
if (
|
|
6874
|
+
if (ts3.isIdentifier(declaration.name) && declaration.name.text === "customComponents") initializer = declaration.initializer;
|
|
6716
6875
|
}
|
|
6717
6876
|
}
|
|
6718
|
-
while (initializer && (
|
|
6719
|
-
if (!initializer || !
|
|
6877
|
+
while (initializer && (ts3.isAsExpression(initializer) || ts3.isSatisfiesExpression(initializer) || ts3.isParenthesizedExpression(initializer))) initializer = initializer.expression;
|
|
6878
|
+
if (!initializer || !ts3.isObjectLiteralExpression(initializer)) {
|
|
6720
6879
|
throw new Error("Cannot safely merge src/mdx/custom-components.tsx: export customComponents as an object literal before importing components. The existing registry was preserved.");
|
|
6721
6880
|
}
|
|
6722
6881
|
const content = alreadyImported ? existing : applyReplacements(existing, [
|
|
6723
6882
|
{
|
|
6724
|
-
start: source.statements.filter((statement) =>
|
|
6725
|
-
end: source.statements.filter((statement) =>
|
|
6883
|
+
start: source.statements.filter((statement) => ts3.isExpressionStatement(statement) && ts3.isStringLiteral(statement.expression)).at(-1)?.end ?? 0,
|
|
6884
|
+
end: source.statements.filter((statement) => ts3.isExpressionStatement(statement) && ts3.isStringLiteral(statement.expression)).at(-1)?.end ?? 0,
|
|
6726
6885
|
value: `
|
|
6727
6886
|
import { customComponents as ${name} } from ${JSON.stringify(registryPath)}
|
|
6728
6887
|
`
|