Skip to content

Instantly share code, notes, and snippets.

@slashedzer0
Created February 25, 2025 11:54
Show Gist options
  • Save slashedzer0/f55dcdf8b17c2b87ce5fc9610552f65a to your computer and use it in GitHub Desktop.
Save slashedzer0/f55dcdf8b17c2b87ce5fc9610552f65a to your computer and use it in GitHub Desktop.
High-performance Reddit to RedLib frontend redirector
// ==UserScript==
// @name Reddit to RedLib Redirector
// @namespace https://github.com/slashedzer0
// @version 1.1.0
// @description High-performance Reddit to RedLib frontend redirector
// @author slashedzer0
// @match *://*.reddit.com/*
// @match *://reddit.com/*
// @match *://*/*
// @grant none
// @run-at document-start
// @noframes true
// ==/UserScript==
(function() {
'use strict';
const REDLIB_BASE = 'https://redlib.perennialte.ch';
const REDDIT_PATTERN = /^(?:(?:https?:)?\/\/)?(?:(?:www|old|new)\.)?reddit\.com(\/[^?#]*)?(\?[^#]*)?(#.*)?$/i;
const redditHostRegex = /\breddit\.com$/i;
const processedLinks = new Set();
const convertToRedLib = (() => {
const a = document.createElement('a');
return (url) => {
if (!url || url.includes(REDLIB_BASE)) return url;
try {
a.href = url;
if (!REDDIT_PATTERN.test(url)) return url;
return REDLIB_BASE + (a.pathname || '/') + a.search + a.hash;
} catch {
return url;
}
};
})();
const debounce = (fn, delay) => {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(null, args), delay);
};
};
const processLink = (link) => {
if (!link || !link.href || processedLinks.has(link)) return;
if (link.href.indexOf('reddit.com') !== -1) {
const newHref = convertToRedLib(link.href);
if (newHref !== link.href) {
link.href = newHref;
processedLinks.add(link);
}
}
};
const processLinks = debounce((links) => {
const len = links.length;
for (let i = 0; i < len; i++) {
processLink(links[i]);
}
}, 50);
const observerCallback = (mutations) => {
const links = [];
mutations.forEach(mutation => {
if (mutation.type === 'childList') {
const addedNodes = mutation.addedNodes;
const addedNodesLen = addedNodes.length;
for (let i = 0; i < addedNodesLen; i++) {
const node = addedNodes[i];
if (node.nodeType === 1) {
if (node.tagName === 'A') {
links.push(node);
} else if (node.getElementsByTagName) {
const nodeLinks = node.getElementsByTagName('a');
if (nodeLinks.length) {
links.push(...nodeLinks);
}
}
}
}
}
});
if (links.length) {
processLinks(links);
}
};
if (redditHostRegex.test(window.location.hostname)) {
const redirectUrl = convertToRedLib(window.location.href);
if (redirectUrl !== window.location.href) {
window.stop();
window.location.replace(redirectUrl);
}
}
document.addEventListener('click', (e) => {
const link = e.target.closest('a');
if (!link || !link.href) return;
if (link.href.indexOf('reddit.com') !== -1) {
const newHref = convertToRedLib(link.href);
if (newHref !== link.href) {
e.preventDefault();
window.location.href = newHref;
}
}
}, { capture: true, passive: false });
const observer = new MutationObserver(observerCallback);
observer.observe(document.documentElement, {
childList: true,
subtree: true,
attributes: false,
characterData: false
});
processLinks(document.getElementsByTagName('a'));
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment