// ==UserScript== // @name 标记已点击链接(会话版) // @description 点击链接变暗并添加波浪线,标记会保存直到标签页关闭 // @version 2.9 // @author WJ // @match *://*/* // @license MIT // @grant none // @namespace https://greasyfork.org/users/914996 // @downloadURL none // ==/UserScript== (function() { // 加载存储的标记链接 const marked = JSON.parse(sessionStorage.xMarkedLinks || '{}'); // 标准化URL(核心简化版) const normalizeUrl = url => { try { const u = new URL(url); u.hash = ''; return u.href; } catch { return url; } }; // 标记链接样式 const markLink = a => { a.style.cssText = 'text-decoration:underline wavy #00CED1; opacity:0.5'; }; // 标记所有匹配链接 const markAll = url => { const normUrl = normalizeUrl(url); marked[normUrl] = true; sessionStorage.xMarkedLinks = JSON.stringify(marked); document.querySelectorAll('a[href]').forEach(a => { if (normalizeUrl(a.href) === normUrl) markLink(a); }); }; // 初始化标记 const init = () => { Object.keys(marked).forEach(url => { document.querySelectorAll('a[href]').forEach(a => { if (normalizeUrl(a.href) === url) markLink(a); }); }); }; // 动态内容检测 new MutationObserver(init).observe(document, { childList: true, subtree: true }); // 页面加载后初始化 document.addEventListener('DOMContentLoaded', init); // 点击处理 document.addEventListener('click', e => { const a = e.target.closest('a[href]'); if (!a || marked[normalizeUrl(a.href)]) return; if (!a.closest(` nav, .nav, .navbar, .navigation, .menu, .menubar, .breadcrumb, header, .header, footer, .footer, .pagination, .tabs, .tabbar, .sidebar, .aside, #sidebar, #aside, [role="navigation"], [role="menu"], [role="tablist"], [role="banner"] `)) { markAll(a.href); } }, true); })();