Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update deadlinks script to take into account redirects (#7882)
* Revert "Fix deadlinks (#7880)"

Original commit changeset: d52b3ec

Revert this so we can just fix the real deadlinks.

* Update deadlinks script to take into account redirects

Also check if a redirect exists before erroring.
  • Loading branch information
poteto authored Jul 21, 2025
commit 79eb0c5f7e4e970bb29a4145af02a87be54c255d
45 changes: 44 additions & 1 deletion scripts/deadLinkChecker.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const PUBLIC_DIR = path.join(__dirname, '../public');
const fileCache = new Map();
const anchorMap = new Map(); // Map<filepath, Set<anchorId>>
const contributorMap = new Map(); // Map<anchorId, URL>
const redirectMap = new Map(); // Map<source, destination>
let errorCodes = new Set();

async function readFileWithCache(filePath) {
Expand Down Expand Up @@ -162,6 +163,22 @@ async function validateLink(link) {
return {valid: true};
}

// Check for redirects
if (redirectMap.has(urlWithoutAnchor)) {
const redirectDestination = redirectMap.get(urlWithoutAnchor);
if (
redirectDestination.startsWith('http://') ||
redirectDestination.startsWith('https://')
) {
return {valid: true};
}
const redirectedLink = {
...link,
url: redirectDestination + (anchorMatch ? anchorMatch[0] : ''),
};
return validateLink(redirectedLink);
}

// Check if it's an error code link
const errorCodeMatch = urlWithoutAnchor.match(/^\/errors\/(\d+)$/);
if (errorCodeMatch) {
Expand Down Expand Up @@ -295,17 +312,42 @@ async function fetchErrorCodes() {
}
const codes = await response.json();
errorCodes = new Set(Object.keys(codes));
console.log(chalk.gray(`Fetched ${errorCodes.size} React error codes\n`));
console.log(chalk.gray(`Fetched ${errorCodes.size} React error codes`));
} catch (error) {
throw new Error(`Failed to fetch error codes: ${error.message}`);
}
}

async function buildRedirectsMap() {
try {
const vercelConfigPath = path.join(__dirname, '../vercel.json');
const vercelConfig = JSON.parse(
await fs.promises.readFile(vercelConfigPath, 'utf8')
);

if (vercelConfig.redirects) {
for (const redirect of vercelConfig.redirects) {
redirectMap.set(redirect.source, redirect.destination);
}
console.log(
chalk.gray(`Loaded ${redirectMap.size} redirects from vercel.json`)
);
}
} catch (error) {
console.log(
chalk.yellow(
`Warning: Could not load redirects from vercel.json: ${error.message}\n`
)
);
}
}

async function main() {
const files = getMarkdownFiles();
console.log(chalk.gray(`Checking ${files.length} markdown files...`));

await fetchErrorCodes();
await buildRedirectsMap();
await buildContributorMap();
await buildAnchorMap(files);

Expand All @@ -315,6 +357,7 @@ async function main() {
const totalLinks = results.reduce((sum, r) => sum + r.totalLinks, 0);

if (deadLinks.length > 0) {
console.log('\n');
for (const link of deadLinks) {
console.log(chalk.yellow(`${link.file}:${link.line}:${link.column}`));
console.log(chalk.reset(` Link text: ${link.text}`));
Expand Down