Created
January 31, 2025 04:39
-
-
Save hargup/0c1b0d761c44a9f069ea67fea040f424 to your computer and use it in GitHub Desktop.
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
// Function to check if a URL is broken and replace with Wayback Machine version | |
async function getWaybackUrl(url) { | |
const waybackUrl = `https://archive.org/wayback/available?url=${encodeURIComponent(url)}`; | |
try { | |
const waybackResponse = await fetch(waybackUrl); | |
const data = await waybackResponse.json(); | |
// Check if there's an archived version available | |
if (data.archived_snapshots?.closest?.url) { | |
return data.archived_snapshots.closest.url; | |
} | |
return null; | |
} catch (error) { | |
console.error('Error checking Wayback Machine:', error); | |
return null; | |
} | |
} | |
// Function to check if a URL is accessible | |
async function isUrlAccessible(url) { | |
try { | |
const response = await fetch(url, { method: 'HEAD' }); | |
return response.ok; | |
} catch (error) { | |
return false; | |
} | |
} | |
// Function to replace broken links | |
async function replaceWithWaybackLink(url) { | |
if (await isUrlAccessible(url)) { | |
return url; | |
} | |
const waybackUrl = await getWaybackUrl(url); | |
return waybackUrl || url; | |
} | |
// Function to handle broken images | |
function handleBrokenImage(img) { | |
// Only process if not already being handled | |
if (!img.dataset.beingProcessed) { | |
img.dataset.beingProcessed = 'true'; | |
const originalSrc = img.src; | |
getWaybackUrl(originalSrc).then(waybackUrl => { | |
if (waybackUrl) { | |
img.src = waybackUrl; | |
img.setAttribute('data-original-src', originalSrc); | |
img.classList.add('wayback-replaced'); | |
} | |
}).finally(() => { | |
delete img.dataset.beingProcessed; | |
}); | |
} | |
} | |
// Function to replace all broken links and images in a webpage | |
async function replaceAllBrokenContent() { | |
// Handle links | |
const links = document.getElementsByTagName('a'); | |
for (const link of links) { | |
const originalUrl = link.href; | |
if (originalUrl && !originalUrl.startsWith('javascript:')) { | |
const newUrl = await replaceWithWaybackLink(originalUrl); | |
if (newUrl !== originalUrl) { | |
link.href = newUrl; | |
link.setAttribute('data-original-url', originalUrl); | |
link.classList.add('wayback-replaced'); | |
} | |
} | |
} | |
// Handle images | |
const images = document.getElementsByTagName('img'); | |
for (const img of images) { | |
// Set up error handler for images | |
img.onerror = () => handleBrokenImage(img); | |
// Also check current images | |
if (!img.complete || img.naturalHeight === 0) { | |
handleBrokenImage(img); | |
} | |
} | |
} | |
// Function to observe DOM changes and handle new content | |
function observeContentChanges() { | |
const observer = new MutationObserver((mutations) => { | |
mutations.forEach((mutation) => { | |
mutation.addedNodes.forEach((node) => { | |
if (node.nodeType === Node.ELEMENT_NODE) { | |
// Handle new links | |
if (node.tagName === 'A') { | |
replaceWithWaybackLink(node.href).then(newUrl => { | |
if (newUrl !== node.href) { | |
node.href = newUrl; | |
node.setAttribute('data-original-url', node.href); | |
node.classList.add('wayback-replaced'); | |
} | |
}); | |
} | |
// Handle new images | |
if (node.tagName === 'IMG') { | |
node.onerror = () => handleBrokenImage(node); | |
if (!node.complete || node.naturalHeight === 0) { | |
handleBrokenImage(node); | |
} | |
} | |
// Check for nested elements | |
const links = node.getElementsByTagName('a'); | |
const images = node.getElementsByTagName('img'); | |
Array.from(links).forEach(link => replaceAllBrokenContent()); | |
Array.from(images).forEach(img => { | |
img.onerror = () => handleBrokenImage(img); | |
if (!img.complete || img.naturalHeight === 0) { | |
handleBrokenImage(img); | |
} | |
}); | |
} | |
}); | |
}); | |
}); | |
observer.observe(document.body, { | |
childList: true, | |
subtree: true | |
}); | |
} | |
// CSS to style replaced content | |
const style = document.createElement('style'); | |
style.textContent = ` | |
.wayback-replaced { | |
border: 2px dotted #666; | |
position: relative; | |
} | |
.wayback-replaced:hover::after { | |
content: 'Archived version from Wayback Machine'; | |
position: absolute; | |
bottom: 100%; | |
left: 50%; | |
transform: translateX(-50%); | |
background: #333; | |
color: white; | |
padding: 5px; | |
border-radius: 3px; | |
font-size: 12px; | |
white-space: nowrap; | |
z-index: 1000; | |
} | |
img.wayback-replaced { | |
padding: 2px; | |
} | |
`; | |
document.head.appendChild(style); | |
// Initialize when the page loads | |
document.addEventListener('DOMContentLoaded', () => { | |
replaceAllBrokenContent(); | |
observeContentChanges(); | |
}); | |
// Usage example: | |
// Run the replacement manually | |
// replaceAllBrokenContent(); | |
// Check individual URLs | |
// const newUrl = await replaceWithWaybackLink('https://example.com/broken-link'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment