blob: f6a2f01d783074289f480fe4dd717e9aeaf7f6cc [file]
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const docsRoot = path.resolve(__dirname, '../docs');
function findFiles(dir) {
const results = [];
for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) results.push(...findFiles(full));
else if (entry.name.endsWith('.md') || entry.name.endsWith('.mdx')) results.push(full);
}
return results;
}
function fileExists(p) {
if (fs.existsSync(p)) return true;
if (fs.existsSync(p.replace(/\.md$/, '.mdx'))) return true;
if (fs.existsSync(p.replace(/\.mdx?$/, '') + '/index.md')) return true;
if (fs.existsSync(p.replace(/\.mdx?$/, '') + '/index.mdx')) return true;
return false;
}
function fixFile(filePath) {
let content = fs.readFileSync(filePath, 'utf-8');
const relFile = path.relative(docsRoot, filePath);
const fileDir = path.dirname(relFile);
let modified = false;
// Match all markdown links with relative paths
content = content.replace(/\]\((\.\.?\/[^\)]+)\)/g, (match, rawLink) => {
// Split anchor
let anchor = '';
let linkPath = rawLink;
const hashIdx = linkPath.indexOf('#');
if (hashIdx !== -1) {
anchor = linkPath.slice(hashIdx);
linkPath = linkPath.slice(0, hashIdx);
}
// Skip external/absolute links
if (linkPath.startsWith('http') || linkPath.startsWith('/docs/master/api')) return match;
// Resolve the link relative to current file dir
const resolved = path.resolve(path.join(docsRoot, fileDir), linkPath);
const resolvedRel = path.relative(docsRoot, resolved);
// Check if it actually exists
if (fileExists(resolved)) return match;
// It doesn't exist. Try to find it from docs root
// Extract the "intended" path (strip leading ../ and ./)
const strippedPath = linkPath.replace(/^(\.\.\/)+/, '').replace(/^\.\//, '');
// Try resolving from docs root
const fromRoot = path.join(docsRoot, strippedPath);
if (fileExists(fromRoot)) {
// Compute correct relative path from current file
const targetFile = fs.existsSync(fromRoot) ? fromRoot :
fs.existsSync(fromRoot.replace(/\.md$/, '.mdx')) ? fromRoot.replace(/\.md$/, '.mdx') :
fs.existsSync(fromRoot.replace(/\.mdx?$/, '') + '/index.md') ? fromRoot.replace(/\.mdx?$/, '') + '/index.md' :
fromRoot;
const correctRel = path.relative(path.join(docsRoot, fileDir), fromRoot);
const newLink = correctRel.startsWith('.') ? correctRel : './' + correctRel;
modified = true;
return `](${newLink}${anchor})`;
}
// Leave as-is
return match;
});
if (modified) {
fs.writeFileSync(filePath, content);
console.log(` Fixed: ${relFile}`);
}
}
const files = findFiles(docsRoot);
console.log(`Fixing links in ${files.length} files...`);
for (const file of files) {
fixFile(file);
}
console.log('Done!');