-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest-links.js
More file actions
executable file
·104 lines (87 loc) · 2.69 KB
/
test-links.js
File metadata and controls
executable file
·104 lines (87 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const docsDir = path.join(__dirname, 'docs');
const brokenLinks = [];
const fixedLinks = [];
// Recursively find all markdown files
function findMarkdownFiles(dir) {
const files = [];
const items = fs.readdirSync(dir);
for (const item of items) {
const fullPath = path.join(dir, item);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
files.push(...findMarkdownFiles(fullPath));
} else if (item.endsWith('.md') || item.endsWith('.mdx')) {
files.push(fullPath);
}
}
return files;
}
// Check if a path exists (file or directory, with or without .md/.mdx extension)
function checkPath(targetPath) {
if (fs.existsSync(targetPath)) return true;
if (fs.existsSync(targetPath + '.md')) return true;
if (fs.existsSync(targetPath + '.mdx')) return true;
return false;
}
const mdFiles = findMarkdownFiles(docsDir);
console.log('Testing internal links in documentation...\n');
for (const mdFile of mdFiles) {
const content = fs.readFileSync(mdFile, 'utf8');
// Find markdown links: [text](path)
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
let match;
while ((match = linkRegex.exec(content)) !== null) {
const linkText = match[1];
const linkPath = match[2];
// Skip external URLs and anchors
if (linkPath.startsWith('http://') ||
linkPath.startsWith('https://') ||
linkPath.startsWith('#') ||
linkPath.startsWith('mailto:')) {
continue;
}
// Remove anchor from path
const cleanPath = linkPath.split('#')[0];
if (!cleanPath) continue;
// Resolve the path
let targetPath;
if (cleanPath.startsWith('/')) {
// Absolute path from docs root
targetPath = path.join(docsDir, cleanPath);
} else {
// Relative path
targetPath = path.resolve(path.dirname(mdFile), cleanPath);
}
// Check if target exists
if (!checkPath(targetPath)) {
brokenLinks.push({
file: path.relative(docsDir, mdFile),
link: linkPath,
text: linkText
});
} else {
fixedLinks.push({
file: path.relative(docsDir, mdFile),
link: linkPath
});
}
}
}
// Print results
if (brokenLinks.length > 0) {
console.log('❌ TEST FAILED: Found ' + brokenLinks.length + ' broken internal links:\n');
brokenLinks.forEach((link, i) => {
console.log((i + 1) + '. ' + link.file);
console.log(' Link: ' + link.link);
console.log(' Text: ' + link.text);
console.log();
});
process.exit(1);
} else {
console.log('✅ TEST PASSED: All internal links are valid!');
console.log(' Total links checked: ' + fixedLinks.length);
process.exit(0);
}