去除bilibili链接中不需要的参数,如spm_id_from/from_sourse/from/等,还地址栏以清白干净
// ==UserScript== // @name Bilibili 干净链接 // @namespace Motoori Kashin // @version 2.1.5 // @description 去除bilibili链接中不需要的参数,如spm_id_from/from_sourse/from/等,还地址栏以清白干净 // @author Motoori Kashin // @match *://*.bilibili.com/* // @grant none // @run-at document-start // ==/UserScript== (function () { function isURL(url,base) { try { if (typeof url === "string" && /^[\W\w]+\.[\W\w]+/.test(url) && !/^[a-z]+:/.test(url)) { // 处理省略协议头情况 const str = url.startsWith("//") ? "" : "//"; url = location.protocol + str + url; } return new URL(url, base); } catch (e) { return false; } } /** 垃圾参数 */ const paramsSet = new Set([ 'spm_id_from', 'from_source', 'msource', 'bsource', 'seid', 'source', 'session_id', 'visit_id', 'sourceFrom', 'from_spmid', 'share_source', 'share_medium', 'share_plat', 'share_session_id', 'share_tag', 'unique_k', "csource", "vd_source", "tab", "is_story_h5", "share_from", "plat_id", "-Arouter", "spmid", ]); /** 节点监听暂存 */ const nodelist = []; /** * 清理url * @param str 原url * @returns 新url */ function clean(str) { if(/.*:\/\/.*.bilibili.com\/.*/.test(str) && !str.includes('passport.bilibili.com')){ const url = isURL(str); if(url){ paramsSet.forEach(d => { url.searchParams.delete(d); }); return url.toJSON(); } } return str; } /** 地址备份 */ let locationBackup; /** 处理地址栏 */ function cleanLocation() { const { href } = location; if (href === locationBackup) return; replaceUrl(locationBackup = clean(href)); } /** 处理href属性 */ function anchor(list) { list.forEach(d => { if (!d.href) return; d.href.includes("bilibili.tv") && (d.href = d.href.replace("bilibili.tv", "bilibili.com")); // tv域名失效 d.href = clean(d.href); }); } /** 检查a标签 */ function click(e) { // 代码copy自B站spm.js var f = e.target; for (; f && "A" !== f.tagName;) { f = f.parentNode } if ("A" !== (null == f ? void 0 : f.tagName)) { return } anchor([f]); } /** * 修改当前URL而不出发重定向 * **无法跨域操作!** * @param url 新URL */ function replaceUrl(url) { window.history.replaceState(window.history.state, "", url); } cleanLocation(); // 及时处理地址栏 // 处理注入的节点 let timer = 0; observerAddedNodes((node) => { clearTimeout(timer); timer = setTimeout(() => { cleanLocation(); anchor(document.querySelectorAll("a")); }); }); // 处理点击事件 window.addEventListener("click", click, !1); // 处理右键菜单 window.addEventListener("contextmenu", click, !1); // 页面载入完成 document.addEventListener("load", ()=>anchor(document.querySelectorAll("a")), !1); /** * 注册节点添加监听 * **监听节点变动开销极大,如非必要请改用其他方法并且用后立即销毁!** * @param callback 添加节点后执行的回调函数 * @returns 注册编号,用于使用`removeObserver`销毁监听 */ function observerAddedNodes(callback) { try { if (typeof callback === "function") nodelist.push(callback); return nodelist.length - 1; } catch (e) { console.error(e) } } const observe = new MutationObserver(d => d.forEach(d => { d.addedNodes[0] && nodelist.forEach(async f => { try { f(d.addedNodes[0]) } catch (e) { console.error(d) } }) })); observe.observe(document, { childList: true, subtree: true }); window.open = ((__open__) => { return (url, name, params) => { return __open__(clean(url), name, params) } })(window.open) window.navigation && window.navigation.addEventListener('navigate', e => { const newURL = clean(e.destination.url) if(e.destination.url!=newURL) { e.preventDefault(); // 返回前还是先阻止原事件吧 if(newURL == window.location.href) return // 如果清理后和原来一样就直接返回 // 否则就处理清理后的链接 window.history.replaceState(window.history.state, "", newURL) return } }); })();