-
Notifications
You must be signed in to change notification settings - Fork 265
Automate Internal Link Updates Using Redirects File #1119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
d12dbb2
Created a script that checks for borken links
krofax 3f525de
updated the link checker
krofax 7e72b2b
Documented the steps involved to automate the redirect
krofax de92cb6
revert changes made in lychee
krofax d69fb35
revert previous changes to lychee file
krofax 1d4dea4
Update notes/fix-redirects.md
krofax 10ecb2b
fix lint issues
krofax 83db102
update the command
krofax 2da87a6
revert changes
krofax File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# Redirect links management guide | ||
|
||
## Scripts overview | ||
Two scripts help maintain internal links when pages are redirected: | ||
|
||
* `check-redirects`: Identifies links that need updating based on the `_redirects` file. | ||
* `fix-redirects`: Automatically updates links to match `_redirects` entries. | ||
|
||
## Checking for broken links | ||
|
||
Run the check script: | ||
|
||
```bash | ||
pnpm lint //OR | ||
pnpm check-redirects | ||
``` | ||
## What it does | ||
|
||
* Scans all `.mdx` files in the docs | ||
* Compares internal links against `_redirects` file | ||
* Reports any outdated links that need updating | ||
* Provides a summary of total, broken, and valid links | ||
|
||
## Example output | ||
|
||
```bash | ||
File "builders/overview.mdx" contains outdated link "/chain/overview" - should be updated to "/stack/overview" | ||
|
||
Summary: | ||
Total pages 🔍 - 50 | ||
Pages broken 🚫 - 2 | ||
Pages OK ✅ - 48 | ||
|
||
``` | ||
|
||
## Fixing broken links | ||
|
||
Fix links automatically: | ||
|
||
```bash | ||
pnpm fix //OR | ||
pnpm fix-redirects | ||
``` | ||
|
||
## What it does | ||
|
||
* Updates all internal links to match `_redirects` entries | ||
* Preserves other content and formatting | ||
* Shows which files and links were updated | ||
* Provides a summary of changes made | ||
|
||
## Example output | ||
|
||
```bash | ||
Fixed in "builders/overview.mdx": /chain/overview → /stack/overview | ||
|
||
Summary: | ||
Total files 🔍 - 50 | ||
Files fixed ✅ - 2 | ||
Files skipped ⏭️ - 48 | ||
``` | ||
|
||
## Best practices | ||
|
||
1. Before running | ||
|
||
* Commit current changes | ||
* Review `_redirects` file is up-to-date | ||
* Run `check-redirects` first to preview changes | ||
|
||
|
||
2. After running | ||
|
||
* Review git diff of updated files | ||
* Test updated links locally | ||
* Commit changes with descriptive message | ||
krofax marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
|
||
## Common issues | ||
|
||
* Script fails: Ensure `_redirects` file exists in public folder, it should always be there! | ||
* No broken links found: Verify `_redirects` entries are correct. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import * as fs from 'fs/promises'; | ||
import * as path from 'path'; | ||
|
||
const rootDir = path.join(process.cwd(), 'pages'); | ||
const redirectsPath = path.join(process.cwd(), 'public', '_redirects'); | ||
const updates: string[] = []; | ||
|
||
// ANSI color codes | ||
const WHITE = '\x1b[37m'; | ||
const GREEN = '\x1b[32m'; | ||
const YELLOW = '\x1b[33m'; | ||
const RESET = '\x1b[0m'; | ||
const BOLD = '\x1b[1m'; | ||
|
||
interface Redirect { | ||
from: string; | ||
to: string; | ||
} | ||
|
||
interface Summary { | ||
total: number; | ||
fixed: number; | ||
skipped: number; | ||
} | ||
|
||
async function getRedirects(): Promise<Redirect[]> { | ||
const content = await fs.readFile(redirectsPath, 'utf-8'); | ||
return content.split('\n') | ||
.filter(line => line.trim() && !line.startsWith('#')) | ||
.map(line => { | ||
const [from, to] = line.split(/\s+/); | ||
return { from, to }; | ||
}); | ||
} | ||
krofax marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
async function findMdxFiles(dir: string): Promise<string[]> { | ||
const files: string[] = []; | ||
const entries = await fs.readdir(dir, { withFileTypes: true }); | ||
|
||
for (const entry of entries) { | ||
const fullPath = path.join(dir, entry.name); | ||
if (entry.isDirectory() && !entry.name.startsWith('_')) { | ||
files.push(...await findMdxFiles(fullPath)); | ||
} else if (entry.isFile() && /\.(md|mdx)$/.test(entry.name)) { | ||
files.push(fullPath); | ||
} | ||
} | ||
return files; | ||
} | ||
|
||
async function fixFile(filePath: string, redirects: Redirect[]): Promise<boolean> { | ||
let content = await fs.readFile(filePath, 'utf-8'); | ||
let hasChanges = false; | ||
const relativeFilePath = path.relative(rootDir, filePath); | ||
|
||
redirects.forEach(redirect => { | ||
const markdownRegex = new RegExp(`\\[([^\\]]+)\\]\\(${redirect.from}\\)`, 'g'); | ||
const hrefRegex = new RegExp(`href="${redirect.from}"`, 'g'); | ||
|
||
if (content.match(markdownRegex) || content.match(hrefRegex)) { | ||
content = content | ||
.replace(markdownRegex, `[$1](${redirect.to})`) | ||
.replace(hrefRegex, `href="${redirect.to}"`); | ||
|
||
updates.push(`${WHITE}Fixed in "${relativeFilePath}": ${YELLOW}${redirect.from}${WHITE} → ${GREEN}${redirect.to}${RESET}`); | ||
hasChanges = true; | ||
} | ||
}); | ||
krofax marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (hasChanges) { | ||
await fs.writeFile(filePath, content); | ||
} | ||
|
||
return hasChanges; | ||
} | ||
|
||
function printSummary(summary: Summary) { | ||
console.log('\nSummary:'); | ||
console.log(`${WHITE}Total files 🔍 - ${summary.total}`); | ||
console.log(`${GREEN}Files fixed ✅ - ${summary.fixed}`); | ||
console.log(`${WHITE}Files skipped ⏭️ - ${summary.skipped}${RESET}`); | ||
} | ||
|
||
async function main() { | ||
const summary: Summary = { | ||
total: 0, | ||
fixed: 0, | ||
skipped: 0 | ||
}; | ||
|
||
console.log('Starting to fix redirect links...'); | ||
console.log('Root directory:', rootDir); | ||
|
||
try { | ||
const redirects = await getRedirects(); | ||
const files = await findMdxFiles(rootDir); | ||
|
||
summary.total = files.length; | ||
|
||
for (const file of files) { | ||
const wasFixed = await fixFile(file, redirects); | ||
if (wasFixed) { | ||
summary.fixed++; | ||
} else { | ||
summary.skipped++; | ||
} | ||
} | ||
|
||
if (updates.length > 0) { | ||
console.log(`${GREEN}${BOLD}Fixed links:${RESET}`); | ||
updates.forEach(update => console.log(update)); | ||
printSummary(summary); | ||
} else { | ||
console.log(`${GREEN}No broken links found. Everything is up to date.${RESET}`); | ||
printSummary(summary); | ||
} | ||
} catch (error) { | ||
console.error(`${YELLOW}${BOLD}Error fixing redirects:${RESET}`, error); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
main().catch(error => { | ||
console.error(`${YELLOW}${BOLD}Error in main process:${RESET}`, error); | ||
process.exit(1); | ||
}); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.