标记已点击链接

点击链接变暗并加波浪线,标记持续到标签页关闭

// ==UserScript==
// @name         标记已点击链接
// @description  点击链接变暗并加波浪线,标记持续到标签页关闭
// @version      1.0
// @author       WJ
// @match        *://*/*
// @license      MIT
// @grant        none
// @namespace https://greasyfork.org/users/914996
// ==/UserScript==

(() => {
  'use strict';

  /* ---------- 0. 样式:一条 CSS 搞定 ---------- */
  const sheet = new CSSStyleSheet();
  sheet.replaceSync('a.x-marked{opacity:.5!important;text-decoration:underline wavy #0ce!important}');
  document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

  /* ---------- 1. 数据:用 Set,省 JSON 往返 ---------- */
  const marked = new Set(JSON.parse(sessionStorage.xMarked || '[]'));

  /* ---------- 2. 标记/恢复 ---------- */
  const mark = a => a.classList.toggle('x-marked', marked.has(a.href));
  document.querySelectorAll('a[href]').forEach(mark);

  /* ---------- 3. 动态节点 ---------- */
  new MutationObserver(muts => muts.forEach(m => m.addedNodes.forEach(n =>
    n.nodeType === 1 && (n.tagName === 'A' ? mark(n)
      : n.querySelectorAll?.('a[href]').forEach(mark))
  ))).observe(document.body, {childList: true, subtree: true});

  /* ---------- 4. 点击事件:CSS 过滤导航区 ---------- */
  document.addEventListener('click', e => {
    const a = e.target.closest(`a[href]:not(
      nav a, header a, footer a, aside a,
      .nav a, .navbar a, .navigation a, .menu a, .menubar a,
      .breadcrumb a, .pagination a, .tabs a, .tabbar a, .sidebar a, .header a, .footer a,
      [role="navigation"] a, [role="menu"] a, [role="tablist"] a, [role="banner"] a)`
    );
    if (a) {
      marked.add(a.href);
      sessionStorage.xMarked = JSON.stringify([...marked]);
      a.classList.add('x-marked');
  }}, true);
})();