【求助】网页中的文本链接转化为超链接

自己搓一个,凑合用吧,对b站有效
(2025 7/30更新,欢迎提bug)

// ==UserScript==
// @name         !✅双击文本打开链接
// @namespace    http://tampermonkey.net/
// @version      3.3
// @description  双击文本时,打开鼠标所在位置最近的链接,支持 Shadow DOM 和多个链接判断
// @author       psycho
// @match        *://*/*
// @run-at       document-idle
// ==/UserScript==

(function () {
    'use strict';

    const urlRegexGlobal = /\b((?:https?:\/\/|www\.)[-\w@:%_+.~#?&//=]+|[\w.-]+\.(?:com|net|org|cn|io|me|tv|cc|xyz|info)(?:\/[\w@:%_+.~#?&//=]*)?)\b/gi;

    function getTextNodesIn(el) {
        const nodes = [];
        const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, {
            acceptNode: node => node.nodeValue.trim() ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
        });
        while (walker.nextNode()) nodes.push(walker.currentNode);
        return nodes;
    }

    document.addEventListener('dblclick', (event) => {
        const target = event.composedPath()[0];
        if (!target || !(target instanceof Element)) return;

        const textNodes = getTextNodesIn(target);
        const mouseX = event.clientX;
        const mouseY = event.clientY;

        let closestUrl = null;
        let minDistance = Infinity;

        for (const textNode of textNodes) {
            const fullText = textNode.nodeValue;
            urlRegexGlobal.lastIndex = 0;
            let match;

            while ((match = urlRegexGlobal.exec(fullText)) !== null) {
                const startOffset = match.index;
                const endOffset = startOffset + match[0].length;

                const range = document.createRange();
                range.setStart(textNode, startOffset);
                range.setEnd(textNode, endOffset);

                const rects = range.getClientRects();
                for (const rect of rects) {
                    const dx = mouseX - (rect.left + rect.right) / 2;
                    const dy = mouseY - (rect.top + rect.bottom) / 2;
                    const distance = Math.sqrt(dx * dx + dy * dy);

                    if (
                        mouseX >= rect.left && mouseX <= rect.right &&
                        mouseY >= rect.top && mouseY <= rect.bottom &&
                        distance < minDistance
                    ) {
                        minDistance = distance;
                        closestUrl = match[0];
                    }
                }
            }
        }

        if (closestUrl) {
            const fullUrl = /^https?:\/\//i.test(closestUrl) ? closestUrl : 'http://' + closestUrl;
            console.log('[双击] 最近链接:', fullUrl);
            window.open(fullUrl, '_blank');
        } else {
            console.warn('[双击] 没有找到匹配链接');
        }
    }, { capture: true, passive: true });
})();