fail link show

标识无效的a标签

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         fail link show
// @namespace    [email protected]
// @description  标识无效的a标签
// @version      0.3
// @match        *://*.3d66.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(() => {
  "use strict";

  const STYLE_ID = "__query_only_mark_style__";
  const MARK_CLASS = "__query_only_mark";
  const BADGE_CLASS = "__query_only_badge";

  const ensureStyle = () => {
    if (document.getElementById(STYLE_ID)) return;
    const styleEl = document.createElement("style");
    styleEl.id = STYLE_ID;
    styleEl.textContent = `
      a.${MARK_CLASS}{
        outline:none !important;
      }
      a.${MARK_CLASS} .${BADGE_CLASS}{
        position:absolute !important;top:4px !important;right:4px !important;z-index:99999 !important;
        pointer-events:none !important;
        display:inline-flex !important;align-items:center !important;justify-content:center !important;
        width:16px !important;height:16px !important;
        font-size:10px !important;line-height:1 !important;border-radius:999px !important;
        font-weight:700 !important;
        color:#fff !important;
        background:linear-gradient(145deg,#ff6b6b,#d32f2f) !important;
        border:1px solid rgba(211,47,47,.9) !important;
        box-shadow:0 0 0 1px rgba(255,255,255,.9), 0 1px 4px rgba(211,47,47,.35) !important;
      }
    `;
    document.head.appendChild(styleEl);
  };

  const isEmptyHref = (href) => href == null || href.trim() === "";

  const isQueryOnlyHref = (href) => {
    if (isEmptyHref(href)) return false;
    const trimmed = href.trim();
    return trimmed.startsWith("?");
  };

  const applyBadges = () => {
    ensureStyle();
    document.querySelectorAll("a").forEach((a) => {
      const rawHref = a.getAttribute("href");
      const badge = a.querySelector(`.${BADGE_CLASS}`);
      const isBadLink = isEmptyHref(rawHref) || isQueryOnlyHref(rawHref);
      if (!isBadLink) {
        a.classList.remove(MARK_CLASS);
        badge?.remove();
        return;
      }

      const rect = a.getBoundingClientRect();
      const hasImg = a.querySelector("img") !== null;
      // 判断是否为卡片/块级元素:有图片,或尺寸较大,或绝对定位
      const computed = getComputedStyle(a);
      const isAbsolute = computed.position === "absolute" || computed.position === "fixed";
      const isCard = hasImg || (rect.height > 40 && rect.width > 40) || isAbsolute;

      // 基础样式
      const baseStyle =
        "z-index:99999;pointer-events:none;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;font-weight:700;color:#fff;background:linear-gradient(145deg,#ff6b6b,#d32f2f);border:1px solid rgba(211,47,47,.9);box-shadow:0 0 0 1px rgba(255,255,255,.9), 0 1px 4px rgba(211,47,47,.35);";

      let finalStyle = "";
      if (isCard) {
        // 卡片模式:右上角绝对定位
        if (computed.position === "static") {
          a.style.position = "relative";
        }
        finalStyle = `${baseStyle} position:absolute;top:4px;right:4px;width:16px;height:16px;font-size:10px;line-height:1;margin:0;transform:none;`;
      } else {
        // 文本模式:行内追加,不遮挡文字
        // 不需要设置 relative
        finalStyle = `${baseStyle} position:static;width:14px;height:14px;font-size:9px;line-height:1;margin-left:4px;vertical-align:middle;transform:translateY(-1px);`;
      }

      const ensureBadge = () => {
        if (!badge) {
          const nextBadge = document.createElement("span");
          nextBadge.className = BADGE_CLASS;
          nextBadge.textContent = "!";
          nextBadge.style.cssText = finalStyle;
          a.appendChild(nextBadge);
        } else {
          badge.style.cssText = finalStyle;
          // 确保在最后,防止位置不对
          if (a.lastElementChild !== badge) {
            a.appendChild(badge);
          }
        }
      };
      ensureBadge();
    });
  };

  let rafId = null;
  const scheduleApply = () => {
    if (rafId) return;
    rafId = requestAnimationFrame(() => {
      rafId = null;
      applyBadges();
    });
  };

  const observer = new MutationObserver(() => scheduleApply());
  observer.observe(document.documentElement, { subtree: true, childList: true, attributes: true });

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", () => applyBadges(), { once: true });
  } else {
    applyBadges();
  }
})();