@mintlify/link-rot 3.0.1440 → 3.0.1441
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 +8 -2
- package/dist/graph.js +45 -24
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/graph.d.ts
CHANGED
|
@@ -33,10 +33,16 @@ export declare class MdxPath {
|
|
|
33
33
|
private constructParsedPath;
|
|
34
34
|
constructor(originalPath: string, relativeDir?: string, filename?: string, wrapper?: Wrapper | undefined);
|
|
35
35
|
toString(): string;
|
|
36
|
-
getResolvedFiles(
|
|
37
|
-
resolvesTo(node: Node,
|
|
36
|
+
getResolvedFiles(fileIndex: FileIndex, baseDir: string): string[];
|
|
37
|
+
resolvesTo(node: Node, fileIndex: FileIndex, baseDir: string): boolean;
|
|
38
38
|
static filterMapInternalPaths(paths: string[]): string[];
|
|
39
39
|
}
|
|
40
|
+
export declare class FileIndex {
|
|
41
|
+
private byDirAndName;
|
|
42
|
+
constructor(allFiles: string[]);
|
|
43
|
+
private static key;
|
|
44
|
+
lookup(dir: string, name: string, base: string): string[];
|
|
45
|
+
}
|
|
40
46
|
export declare class Node {
|
|
41
47
|
label: string;
|
|
42
48
|
paths: MdxPath[];
|
package/dist/graph.js
CHANGED
|
@@ -119,34 +119,25 @@ export class MdxPath {
|
|
|
119
119
|
}
|
|
120
120
|
return this.path.toString();
|
|
121
121
|
}
|
|
122
|
-
getResolvedFiles(
|
|
123
|
-
if (this.pathType !== PathType.INTERNAL)
|
|
122
|
+
getResolvedFiles(fileIndex, baseDir) {
|
|
123
|
+
if (this.pathType !== PathType.INTERNAL || this.path instanceof URL)
|
|
124
124
|
return [];
|
|
125
|
-
const
|
|
125
|
+
const { dir, name, base } = parse(this.toString());
|
|
126
126
|
const resolvedFiles = [];
|
|
127
127
|
if (existsSync(resolve(baseDir, this.toString()))) {
|
|
128
|
-
resolvedFiles.push(join(
|
|
128
|
+
resolvedFiles.push(join(dir, base));
|
|
129
129
|
}
|
|
130
130
|
// there may be multiple files/folders corresponding to the node
|
|
131
|
-
for
|
|
132
|
-
|
|
133
|
-
const parsedFilePath = parse(fileWithoutLeadingSlash);
|
|
134
|
-
if (parsedFilePath.dir === parsedPath.dir && parsedFilePath.name === parsedPath.name) {
|
|
135
|
-
resolvedFiles.push(fileWithoutLeadingSlash);
|
|
136
|
-
}
|
|
137
|
-
if (parsedFilePath.dir === parsedPath.dir && parsedPath.base === parsedFilePath.name) {
|
|
138
|
-
// account for edge case when there is another . in the filename
|
|
139
|
-
resolvedFiles.push(fileWithoutLeadingSlash);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
131
|
+
// account for edge case when there is another . in the filename
|
|
132
|
+
resolvedFiles.push(...fileIndex.lookup(dir, name, base));
|
|
142
133
|
return resolvedFiles;
|
|
143
134
|
}
|
|
144
|
-
resolvesTo(node,
|
|
135
|
+
resolvesTo(node, fileIndex, baseDir) {
|
|
145
136
|
if (this.pathType !== PathType.INTERNAL)
|
|
146
137
|
return false;
|
|
147
138
|
if (this.toString() === node.toString())
|
|
148
139
|
return true;
|
|
149
|
-
if (this.getResolvedFiles(
|
|
140
|
+
if (this.getResolvedFiles(fileIndex, baseDir).includes(node.toString()))
|
|
150
141
|
return true;
|
|
151
142
|
return false;
|
|
152
143
|
}
|
|
@@ -157,6 +148,31 @@ export class MdxPath {
|
|
|
157
148
|
.map((path) => path.toString());
|
|
158
149
|
}
|
|
159
150
|
}
|
|
151
|
+
export class FileIndex {
|
|
152
|
+
constructor(allFiles) {
|
|
153
|
+
this.byDirAndName = new Map();
|
|
154
|
+
allFiles.forEach((file, order) => {
|
|
155
|
+
const fileWithoutLeadingSlash = file.startsWith('/') ? file.slice(1) : file;
|
|
156
|
+
const { dir, name } = parse(fileWithoutLeadingSlash);
|
|
157
|
+
const key = FileIndex.key(dir, name);
|
|
158
|
+
const entry = [order, fileWithoutLeadingSlash];
|
|
159
|
+
const bucket = this.byDirAndName.get(key);
|
|
160
|
+
if (bucket)
|
|
161
|
+
bucket.push(entry);
|
|
162
|
+
else
|
|
163
|
+
this.byDirAndName.set(key, [entry]);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
static key(dir, name) {
|
|
167
|
+
return `${dir}\0${name}`;
|
|
168
|
+
}
|
|
169
|
+
lookup(dir, name, base) {
|
|
170
|
+
var _a, _b;
|
|
171
|
+
const byName = (_a = this.byDirAndName.get(FileIndex.key(dir, name))) !== null && _a !== void 0 ? _a : [];
|
|
172
|
+
const byBase = base === name ? [] : ((_b = this.byDirAndName.get(FileIndex.key(dir, base))) !== null && _b !== void 0 ? _b : []);
|
|
173
|
+
return [...byName, ...byBase].sort(([a], [b]) => a - b).map(([, file]) => file);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
160
176
|
/*
|
|
161
177
|
* A node is a representation of a page
|
|
162
178
|
* One node can contain multiple MdxPaths (corresponding to internal/external links in the page)
|
|
@@ -333,11 +349,11 @@ export class Graph {
|
|
|
333
349
|
return newEdge;
|
|
334
350
|
}
|
|
335
351
|
addEdgesBetweenNodes() {
|
|
336
|
-
const
|
|
352
|
+
const fileIndex = new FileIndex(getLinkPaths(this.baseDir, this.mintIgnoreGlobs));
|
|
337
353
|
for (const node of Object.values(this.nodes)) {
|
|
338
354
|
for (const path of node.paths) {
|
|
339
355
|
if (path.pathType === PathType.INTERNAL) {
|
|
340
|
-
const targetNode = Object.values(this.nodes).find((otherNode) => path.resolvesTo(otherNode,
|
|
356
|
+
const targetNode = Object.values(this.nodes).find((otherNode) => path.resolvesTo(otherNode, fileIndex, this.baseDir));
|
|
341
357
|
if (targetNode) {
|
|
342
358
|
const edge = this.addEdge(node, targetNode);
|
|
343
359
|
node.addOutgoingEdge(edge);
|
|
@@ -347,14 +363,18 @@ export class Graph {
|
|
|
347
363
|
}
|
|
348
364
|
}
|
|
349
365
|
precomputeFileResolutions() {
|
|
350
|
-
const
|
|
366
|
+
const fileIndex = new FileIndex(getLinkPaths(this.baseDir, this.mintIgnoreGlobs));
|
|
367
|
+
const resolvedKeys = new Set();
|
|
351
368
|
// Build resolution map for all internal paths
|
|
352
369
|
Object.values(this.nodes).forEach((node) => {
|
|
353
370
|
node.paths
|
|
354
371
|
.filter((path) => path.pathType === PathType.INTERNAL)
|
|
355
372
|
.forEach((path) => {
|
|
356
|
-
const resolvedFiles = path.getResolvedFiles(allFiles, this.baseDir);
|
|
357
373
|
const pathKey = path.toString();
|
|
374
|
+
if (resolvedKeys.has(pathKey))
|
|
375
|
+
return;
|
|
376
|
+
resolvedKeys.add(pathKey);
|
|
377
|
+
const resolvedFiles = path.getResolvedFiles(fileIndex, this.baseDir);
|
|
358
378
|
this.fileResolutionMap.set(pathKey, new Set(resolvedFiles));
|
|
359
379
|
});
|
|
360
380
|
});
|
|
@@ -385,6 +405,7 @@ export class Graph {
|
|
|
385
405
|
}
|
|
386
406
|
const brokenLinks = [];
|
|
387
407
|
const nodeSet = new Set(Object.values(this.nodes).map((node) => node.toString()));
|
|
408
|
+
const wildcardRedirects = [...this.redirectMap].filter(([source]) => /[:*]/.test(source));
|
|
388
409
|
for (const node of Object.values(this.nodes)) {
|
|
389
410
|
for (const path of node.paths) {
|
|
390
411
|
if (path.pathType === PathType.INTERNAL) {
|
|
@@ -392,11 +413,11 @@ export class Graph {
|
|
|
392
413
|
const resolvedFiles = this.fileResolutionMap.get(pathString);
|
|
393
414
|
const hasExistingFile = (resolvedFiles && [...resolvedFiles].some((file) => nodeSet.has(file))) ||
|
|
394
415
|
this.virtualNodes.has(pathString);
|
|
395
|
-
let redirectDestination = this.redirectMap.get(pathString);
|
|
416
|
+
let redirectDestination = hasExistingFile ? undefined : this.redirectMap.get(pathString);
|
|
396
417
|
let hasValidRedirect = redirectDestination &&
|
|
397
418
|
(nodeSet.has(`${redirectDestination}.mdx`) || nodeSet.has(redirectDestination));
|
|
398
|
-
if (!hasValidRedirect) {
|
|
399
|
-
for (const [sourcePattern, destinationPattern] of
|
|
419
|
+
if (!hasExistingFile && !hasValidRedirect) {
|
|
420
|
+
for (const [sourcePattern, destinationPattern] of wildcardRedirects) {
|
|
400
421
|
if (this.matchesWildcardPattern(pathString, sourcePattern)) {
|
|
401
422
|
redirectDestination = this.applyWildcardRedirect(pathString, sourcePattern, destinationPattern);
|
|
402
423
|
hasValidRedirect =
|