/** * @name Clean Links * @description Points t.co links in posts straight at the destination X already shows in the link text, strips common tracking parameters (utm_*, fbclid, gclid, ...) and shows the full URL on hover. No extra requests. * @version 1.0.1 * @author wayBetter * @permissions network:none */ const TRACKING = /^(utm_[a-z_]+|fbclid|gclid|dclid|gbraid|wbraid|msclkid|mc_cid|mc_eid|igshid|yclid|_hsenc|_hsmi|mkt_tok|ref_src|ref_url)$/i; module.exports = class CleanLinks { start() { const api = window.wayBetter.api; this.scope = api.scope(); this.scope.observe('[data-testid="tweetText"] a[href^="https://t.co/"], [data-testid="UserUrl"] a[href^="https://t.co/"], [data-testid="UserDescription"] a[href^="https://t.co/"]', link => this.clean(link)); } stop() { this.scope.dispose(); for (const link of document.querySelectorAll('a[data-bt-tco]')) { link.setAttribute('href', link.getAttribute('data-bt-tco')); link.removeAttribute('data-bt-tco'); if (link.hasAttribute('data-bt-title')) { link.removeAttribute('title'); link.removeAttribute('data-bt-title'); } } } /** X renders the expanded URL as the link text (partly hidden, "…" when shortened). */ destination(link) { const text = (link.textContent || '').replace(/…$/, '').trim(); if (!/^https?:\/\/\S+$/.test(text)) return null; try { const url = new URL(text); for (const key of [...url.searchParams.keys()]) if (TRACKING.test(key)) url.searchParams.delete(key); return url.href; } catch { return null; } } clean(link) { const target = this.destination(link); if (!target) return; link.setAttribute('data-bt-tco', link.getAttribute('href')); link.setAttribute('href', target); if (!link.hasAttribute('title')) { link.setAttribute('title', target); link.setAttribute('data-bt-title', ''); } } };