// ==UserScript==
// @name External Link Navigator
// @match *://*/*
// @grant GM_registerMenuCommand
// @grant GM_xmlhttpRequest
// @grant GM_openInTab
// ==/UserScript==
// TODO: * Treat subdomain urls as internal links
// * Create menu button to get all internal links
(function() {
"use strict";
const validProtocolRegex = /^(?:(?:f|ht)tps?):\/\//i;
// Function to get the title of a website
function getWebsiteTitle(url, callback, depth = 0) {
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(response) {
if (response.finalUrl !== url && depth < 5) {
getWebsiteTitle(response.finalUrl, callback, depth + 1);
} else {
const title = response.responseXML.title || response.finalUrl;
callback(title, response.finalUrl);
}
}
});
}
// Function to open a link in a new tab
function openLinkInNewTab(link) {
GM_registerMenuCommand(
`${link.name}`, () => GM_openInTab(link.href, { active: false, insert: true }), {
title: link.href,
id: link.id,
autoClose: false
}
);
}
// Function to get external links and open them in new tabs
function getExternalLinks() {
const externalLinks = Array.from(document.links)
.filter(link => link.host !== location.host && validProtocolRegex.test(link.href))
.reduce((acc, link, index) => {
if (!acc.some(l => l.href === link.href)) {
acc.push({
id: 'Z' + index,
name: (link.textContent || link.innerText || link.title)
.trim()
.replace(/\s+/g, " "),
href: link.href
});
}
return acc;
}, []);
if (externalLinks.length === 0) return [];
externalLinks.forEach(link => {
if (!link.name || link.name === link.href || validProtocolRegex.test(link.name)) {
getWebsiteTitle(link.href, (title, url) => {
[link.name, link.href] = [title, url]
openLinkInNewTab(link);
});
} else {
openLinkInNewTab(link);
}
});
return externalLinks;
}
// Register menu command to get external links
GM_registerMenuCommand("Get External Links", () => {
const startTime = new Date().getTime(); // Record start time
const links = getExternalLinks();
const endTime = new Date().getTime(); // Record end time
const timeDiff = endTime - startTime; // Calculate time difference
console.log(`Number of External Links: ${links.length} loaded in ${timeDiff}ms`);
}, {
id: 1,
autoClose: false
});
})();