@mintlify/link-rot 3.0.819 → 3.0.821
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/dist/graph.d.ts +2 -0
- package/dist/graph.js +9 -1
- package/dist/static-checking/getBrokenInternalLinks.js +9 -0
- package/dist/static-checking/getOpenApiPagePaths.d.ts +8 -0
- package/dist/static-checking/getOpenApiPagePaths.js +68 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +6 -4
package/dist/graph.d.ts
CHANGED
|
@@ -67,9 +67,11 @@ export declare class Graph {
|
|
|
67
67
|
private fileResolutionMap;
|
|
68
68
|
private redirectMap;
|
|
69
69
|
private mintIgnoreGlobs;
|
|
70
|
+
private virtualNodes;
|
|
70
71
|
constructor(baseDir: string, mintIgnoreGlobs?: string[]);
|
|
71
72
|
addNode(label: string): Node;
|
|
72
73
|
addNodes(labels: string[]): void;
|
|
74
|
+
addVirtualNodes(labels: string[]): void;
|
|
73
75
|
setRedirects(redirects: {
|
|
74
76
|
source: string;
|
|
75
77
|
destination: string;
|
package/dist/graph.js
CHANGED
|
@@ -214,6 +214,7 @@ export class Graph {
|
|
|
214
214
|
this.fileResolutionMap = new Map();
|
|
215
215
|
this.redirectMap = new Map();
|
|
216
216
|
this.mintIgnoreGlobs = [];
|
|
217
|
+
this.virtualNodes = new Set();
|
|
217
218
|
this.baseDir = resolve(baseDir);
|
|
218
219
|
this.mintIgnoreGlobs = mintIgnoreGlobs;
|
|
219
220
|
}
|
|
@@ -228,6 +229,12 @@ export class Graph {
|
|
|
228
229
|
this.addNode(label);
|
|
229
230
|
}
|
|
230
231
|
}
|
|
232
|
+
addVirtualNodes(labels) {
|
|
233
|
+
for (const label of labels) {
|
|
234
|
+
this.addNode(label);
|
|
235
|
+
this.virtualNodes.add(new Node(label).toString());
|
|
236
|
+
}
|
|
237
|
+
}
|
|
231
238
|
setRedirects(redirects) {
|
|
232
239
|
for (const redirect of redirects) {
|
|
233
240
|
this.redirectMap.set(normalizePath(redirect.source), normalizePath(redirect.destination));
|
|
@@ -343,7 +350,8 @@ export class Graph {
|
|
|
343
350
|
if (path.pathType === PathType.INTERNAL) {
|
|
344
351
|
const pathString = path.toString();
|
|
345
352
|
const resolvedFiles = this.fileResolutionMap.get(pathString);
|
|
346
|
-
const hasExistingFile = resolvedFiles && [...resolvedFiles].some((file) => nodeSet.has(file))
|
|
353
|
+
const hasExistingFile = (resolvedFiles && [...resolvedFiles].some((file) => nodeSet.has(file))) ||
|
|
354
|
+
this.virtualNodes.has(pathString);
|
|
347
355
|
let redirectDestination = this.redirectMap.get(pathString);
|
|
348
356
|
let hasValidRedirect = redirectDestination &&
|
|
349
357
|
(nodeSet.has(`${redirectDestination}.mdx`) || nodeSet.has(redirectDestination));
|
|
@@ -14,6 +14,7 @@ import path from 'path';
|
|
|
14
14
|
import { visit } from 'unist-util-visit';
|
|
15
15
|
import { Graph, Wrapper } from '../graph.js';
|
|
16
16
|
import { getLinkPaths, getPagePaths } from '../prebuild.js';
|
|
17
|
+
import { getOpenApiPagePaths } from './getOpenApiPagePaths.js';
|
|
17
18
|
import { getRedirects } from './getRedirects.js';
|
|
18
19
|
export const decorateGraphNodeFromPageContent = (graphNode, content) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
20
|
const visitLinks = () => {
|
|
@@ -69,6 +70,14 @@ export const getBrokenInternalLinks = (repoPath) => __awaiter(void 0, void 0, vo
|
|
|
69
70
|
graph.setRedirects(redirectMappings);
|
|
70
71
|
// add nodes for every link alias in the project
|
|
71
72
|
graph.addAliasNodes();
|
|
73
|
+
// add virtual nodes for OpenAPI-generated pages
|
|
74
|
+
try {
|
|
75
|
+
const openApiPagePaths = yield getOpenApiPagePaths(baseDir);
|
|
76
|
+
graph.addVirtualNodes(openApiPagePaths);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
console.warn(`Warning: Failed to extract OpenAPI page paths: ${err}`);
|
|
80
|
+
}
|
|
72
81
|
const allSitePages = getPagePaths(baseDir);
|
|
73
82
|
const sitePages = allSitePages.filter((file) => !isMintIgnored(file, mintIgnoreGlobs));
|
|
74
83
|
yield Promise.all(sitePages.map((filePath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract virtual page paths that would be generated from OpenAPI specs.
|
|
3
|
+
* These pages don't exist as files but are valid link targets.
|
|
4
|
+
*
|
|
5
|
+
* Note: Uses api.openapi.directory from docs.json, or falls back to 'api-reference'.
|
|
6
|
+
* Per-navigation directory configs are not currently supported.
|
|
7
|
+
*/
|
|
8
|
+
export declare const getOpenApiPagePaths: (baseDir: string) => Promise<string[]>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { categorizeFilePaths } from '@mintlify/prebuild';
|
|
11
|
+
import { generateOpenApiPagesForDocsConfig } from '@mintlify/scraping';
|
|
12
|
+
import { validateDocsConfig } from '@mintlify/validation';
|
|
13
|
+
import fs from 'fs-extra';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
const DEFAULT_OUTPUT_DIR = 'api-reference';
|
|
16
|
+
const getOpenApiDirectory = (baseDir) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
var _a;
|
|
18
|
+
const docsJsonPath = path.join(baseDir, 'docs.json');
|
|
19
|
+
if (!fs.existsSync(docsJsonPath))
|
|
20
|
+
return DEFAULT_OUTPUT_DIR;
|
|
21
|
+
try {
|
|
22
|
+
const docsJson = yield fs.readJSON(docsJsonPath);
|
|
23
|
+
const result = validateDocsConfig(docsJson);
|
|
24
|
+
if (!result.success)
|
|
25
|
+
return DEFAULT_OUTPUT_DIR;
|
|
26
|
+
const openapi = (_a = result.data.api) === null || _a === void 0 ? void 0 : _a.openapi;
|
|
27
|
+
if (typeof openapi === 'object' && 'directory' in openapi && openapi.directory) {
|
|
28
|
+
return openapi.directory;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (_b) {
|
|
32
|
+
throw new Error('Unable to parse OpenAPI directory from docs.json');
|
|
33
|
+
}
|
|
34
|
+
return DEFAULT_OUTPUT_DIR;
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Extract virtual page paths that would be generated from OpenAPI specs.
|
|
38
|
+
* These pages don't exist as files but are valid link targets.
|
|
39
|
+
*
|
|
40
|
+
* Note: Uses api.openapi.directory from docs.json, or falls back to 'api-reference'.
|
|
41
|
+
* Per-navigation directory configs are not currently supported.
|
|
42
|
+
*/
|
|
43
|
+
export const getOpenApiPagePaths = (baseDir) => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
+
const pagePaths = [];
|
|
45
|
+
try {
|
|
46
|
+
const [{ openApiFiles }, outDir] = yield Promise.all([
|
|
47
|
+
categorizeFilePaths(baseDir),
|
|
48
|
+
getOpenApiDirectory(baseDir),
|
|
49
|
+
]);
|
|
50
|
+
for (const openApiFile of openApiFiles) {
|
|
51
|
+
try {
|
|
52
|
+
const { pagesAcc } = yield generateOpenApiPagesForDocsConfig(openApiFile.spec, {
|
|
53
|
+
openApiFilePath: openApiFile.originalFileLocation,
|
|
54
|
+
writeFiles: false,
|
|
55
|
+
outDir,
|
|
56
|
+
});
|
|
57
|
+
pagePaths.push(...Object.keys(pagesAcc));
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.warn(`Warning: Failed to extract pages from OpenAPI spec ${openApiFile.originalFileLocation}: ${err}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
console.warn(`Warning: Failed to categorize files for OpenAPI extraction: ${err}`);
|
|
66
|
+
}
|
|
67
|
+
return [...new Set(pagePaths)];
|
|
68
|
+
});
|