Hier ist die vollständige Version meines LinkCleaner-Add-ons. Dieses ist komplett modular aufgebaut, SK-minimalistisch und zeichnet sich durch eine saubere und überflüssige Implementierung aus. Der bereitgestellte Code enthält ausschließlich die benötigten Funktionalitäten. Alles ist sauber und separat gehalten, sodass Sie die Komponenten umgehend in Ihren Add-on-Ordner integrieren können.
Dies ist die vollständige Dokumentation für das Firefox‑Add-on LinkCleaner SK inklusive Struktur, Icons, Manifest, Hintergrundskript, Popup und Funktionen.
📁 Add-on Struktur
🖤 SK‑Style Icons (schwarz, minimal)
Einfaches, klares Icon‑Set:
📄 manifest.json
{
"manifest_version": 3,
"name": "LinkCleaner SK",
"version": "2.0",
"description": "Bereinigt Tracking-Parameter aus URLs. Popup, Kontextmenü, Auto-Clean, Whitelist.",
"permissions": [
"tabs",
"contextMenus",
"clipboardWrite",
"webRequest",
"webRequestBlocking"
],
"host_permissions": ["<all_urls>"],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"32": "icons/icon32.png",
"48": "icons/icon48.png"
}
},
"background": {
"scripts": ["background.js"]
}
}
📄 background.js
// -----------------------------
// Whitelist-Domains
// -----------------------------
const WHITELIST = [
"sparkasse.de",
"paypal.com",
"banking.example.com"
];
// -----------------------------
// Tracking-Parameter
// -----------------------------
const BLOCKED_PARAMS = [
"fbclid", "gclid", "dclid", "yclid",
"mc_cid", "mc_eid",
"ref", "ref_src", "ref_url",
"igshid", "si", "mkt_tok"
];
// -----------------------------
// URL-Bereinigung
// -----------------------------
function cleanUrl(urlString) {
try {
const url = new URL(urlString);
if (WHITELIST.some(domain => url.hostname.includes(domain))) {
return urlString;
}
for (const [key] of url.searchParams.entries()) {
if (key.toLowerCase().startsWith("utm_")) {
url.searchParams.delete(key);
}
}
BLOCKED_PARAMS.forEach(param => {
if (url.searchParams.has(param)) {
url.searchParams.delete(param);
}
});
return url.toString();
} catch (e) {
return urlString;
}
}
// -----------------------------
// Kontextmenü
// -----------------------------
browser.contextMenus.create({
id: "clean-copy",
title: "Link bereinigen & kopieren",
contexts: ["link"]
});
browser.contextMenus.create({
id: "clean-open",
title: "Link bereinigen & öffnen",
contexts: ["link"]
});
browser.contextMenus.create({
id: "clean-open-new",
title: "Link bereinigen & in neuem Tab öffnen",
contexts: ["link"]
});
// -----------------------------
// Kontextmenü-Handler
// -----------------------------
browser.contextMenus.onClicked.addListener(async (info, tab) => {
const cleaned = cleanUrl(info.linkUrl);
switch (info.menuItemId) {
case "clean-copy":
await navigator.clipboard.writeText(cleaned);
break;
case "clean-open":
browser.tabs.update(tab.id, { url: cleaned });
break;
case "clean-open-new":
browser.tabs.create({ url: cleaned });
break;
}
});
// -----------------------------
// Auto-Clean beim Öffnen neuer Tabs
// -----------------------------
browser.webRequest.onBeforeRequest.addListener(
details => {
const cleaned = cleanUrl(details.url);
if (cleaned !== details.url) {
return { redirectUrl: cleaned };
}
},
{ urls: ["<all_urls>"] },
["blocking"]
);
// -----------------------------
// Auto-Clean beim Kopieren (Copy-Interceptor)
// -----------------------------
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.url) {
const cleaned = cleanUrl(changeInfo.url);
if (cleaned !== changeInfo.url) {
browser.tabs.update(tabId, { url: cleaned });
}
}
});
📄 popup.html
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>LinkCleaner SK</title>
<style>
body { font-family: system-ui; margin: 10px; min-width: 320px; }
textarea { width: 100%; min-height: 70px; font-family: monospace; }
button { margin-top: 6px; margin-right: 6px; }
</style>
</head>
<body>
<textarea id="inputUrl"></textarea>
<button id="cleanBtn">Bereinigen</button>
<button id="applyBtn">Im Tab öffnen</button>
<textarea id="outputUrl" readonly></textarea>
<script src="/popup.js"></script>
</body>
</html>
📄 popup.js
function cleanUrl(urlString) {
try {
const url = new URL(urlString);
for (const [key] of url.searchParams.entries()) {
if (key.startsWith("utm_")) url.searchParams.delete(key);
}
return url.toString();
} catch {
return "";
}
}
document.getElementById("cleanBtn").onclick = () => {
const input = document.getElementById("inputUrl").value;
document.getElementById("outputUrl").value = cleanUrl(input);
};
document.getElementById("applyBtn").onclick = async () => {
const cleaned = document.getElementById("outputUrl").value;
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
browser.tabs.update(tab.id, { url: cleaned });
};
🎯 Fertig
Hier liegt eine umfassende Dokumentation für mein Add-on für Firefox vor, die sich gleichermaßen für die Entwicklung, das Release als auch das Hosting eignet.