@@ -10,6 +10,7 @@ const PUBLIC_DIR = path.join(__dirname, '../public');
10
10
const fileCache = new Map ( ) ;
11
11
const anchorMap = new Map ( ) ; // Map<filepath, Set<anchorId>>
12
12
const contributorMap = new Map ( ) ; // Map<anchorId, URL>
13
+ const redirectMap = new Map ( ) ; // Map<source, destination>
13
14
let errorCodes = new Set ( ) ;
14
15
15
16
async function readFileWithCache ( filePath ) {
@@ -162,6 +163,22 @@ async function validateLink(link) {
162
163
return { valid : true } ;
163
164
}
164
165
166
+ // Check for redirects
167
+ if ( redirectMap . has ( urlWithoutAnchor ) ) {
168
+ const redirectDestination = redirectMap . get ( urlWithoutAnchor ) ;
169
+ if (
170
+ redirectDestination . startsWith ( 'http://' ) ||
171
+ redirectDestination . startsWith ( 'https://' )
172
+ ) {
173
+ return { valid : true } ;
174
+ }
175
+ const redirectedLink = {
176
+ ...link ,
177
+ url : redirectDestination + ( anchorMatch ? anchorMatch [ 0 ] : '' ) ,
178
+ } ;
179
+ return validateLink ( redirectedLink ) ;
180
+ }
181
+
165
182
// Check if it's an error code link
166
183
const errorCodeMatch = urlWithoutAnchor . match ( / ^ \/ e r r o r s \/ ( \d + ) $ / ) ;
167
184
if ( errorCodeMatch ) {
@@ -295,17 +312,42 @@ async function fetchErrorCodes() {
295
312
}
296
313
const codes = await response . json ( ) ;
297
314
errorCodes = new Set ( Object . keys ( codes ) ) ;
298
- console . log ( chalk . gray ( `Fetched ${ errorCodes . size } React error codes\n ` ) ) ;
315
+ console . log ( chalk . gray ( `Fetched ${ errorCodes . size } React error codes` ) ) ;
299
316
} catch ( error ) {
300
317
throw new Error ( `Failed to fetch error codes: ${ error . message } ` ) ;
301
318
}
302
319
}
303
320
321
+ async function buildRedirectsMap ( ) {
322
+ try {
323
+ const vercelConfigPath = path . join ( __dirname , '../vercel.json' ) ;
324
+ const vercelConfig = JSON . parse (
325
+ await fs . promises . readFile ( vercelConfigPath , 'utf8' )
326
+ ) ;
327
+
328
+ if ( vercelConfig . redirects ) {
329
+ for ( const redirect of vercelConfig . redirects ) {
330
+ redirectMap . set ( redirect . source , redirect . destination ) ;
331
+ }
332
+ console . log (
333
+ chalk . gray ( `Loaded ${ redirectMap . size } redirects from vercel.json` )
334
+ ) ;
335
+ }
336
+ } catch ( error ) {
337
+ console . log (
338
+ chalk . yellow (
339
+ `Warning: Could not load redirects from vercel.json: ${ error . message } \n`
340
+ )
341
+ ) ;
342
+ }
343
+ }
344
+
304
345
async function main ( ) {
305
346
const files = getMarkdownFiles ( ) ;
306
347
console . log ( chalk . gray ( `Checking ${ files . length } markdown files...` ) ) ;
307
348
308
349
await fetchErrorCodes ( ) ;
350
+ await buildRedirectsMap ( ) ;
309
351
await buildContributorMap ( ) ;
310
352
await buildAnchorMap ( files ) ;
311
353
@@ -315,6 +357,7 @@ async function main() {
315
357
const totalLinks = results . reduce ( ( sum , r ) => sum + r . totalLinks , 0 ) ;
316
358
317
359
if ( deadLinks . length > 0 ) {
360
+ console . log ( '\n' ) ;
318
361
for ( const link of deadLinks ) {
319
362
console . log ( chalk . yellow ( `${ link . file } :${ link . line } :${ link . column } ` ) ) ;
320
363
console . log ( chalk . reset ( ` Link text: ${ link . text } ` ) ) ;
0 commit comments