文字链接可点击

URL文本转a标签,代码全部来自DeepSeek,可能存在bug

目前為 2025-02-01 提交的版本,檢視 最新版本

// ==UserScript==
// @name         文字链接可点击
// @version      1.2
// @description  URL文本转a标签,代码全部来自DeepSeek,可能存在bug
// @author       cangming99
// @match        *://*/*
// @grant        none
// @run-at       document-idle
// @license MIT
// @namespace https://gf.qytechs.cn/users/826934
// ==/UserScript==

(function() {
    'use strict';

    // 配置中心(可根据需求调整)
    const CONFIG = {
        // 匹配规则
        URL_REGEX: /(?:\b(?:https?|ftp|file):\/\/[^\s<>{}[\]"']+|www\.[^\s<>{}[\]"']+)\b/gi,
        // 性能防护
        MAX_MATCHES: 20,         // 单次最大匹配次数
        CONTEXT_RANGE: 300,       // 上下文截取范围
        COOLDOWN: 50,             // 冷却时间(ms)
        // 样式配置
        STYLE_CLASS: 'uc-link',
        LINK_STYLE: {
            color: '#ff4500',
            'text-decoration': 'underline dashed',
            'cursor': 'pointer',
            'position': 'relative'
        }
    };

    // 状态控制器
    let isProcessing = false;
    let lastSelection = null;

    // 样式隔离系统
    const style = document.createElement('style');
    style.textContent = `
        .${CONFIG.STYLE_CLASS} {
            color: ${CONFIG.LINK_STYLE.color} !important;
            text-decoration: ${CONFIG.LINK_STYLE['text-decoration']} !important;
            cursor: ${CONFIG.LINK_STYLE.cursor} !important;
            position: ${CONFIG.LINK_STYLE.position};
        }
    `;
    document.head.appendChild(style);

    // 选区保护机制
    function saveSelection() {
        const sel = window.getSelection();
        if (sel.rangeCount > 0) {
            lastSelection = sel.getRangeAt(0);
        }
    }

    function restoreSelection() {
        if (lastSelection) {
            const sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(lastSelection.cloneRange());
            lastSelection = null;
        }
    }

    // 动态防护系统
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            if (!mutation.addedNodes) return;
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === Node.ELEMENT_NODE) {
                    node.querySelectorAll('a').forEach(a => {
                        a.dataset.ucProtected = 'true';
                    });
                }
            });
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // 智能转换核心
    function smartConvert(event) {
        if (isProcessing) return;
        if (event.target.closest('a, [data-uc-protected]')) return;
        if (window.getSelection().toString().length > 0) return;

        const range = document.caretRangeFromPoint(event.clientX, event.clientY);
        if (!range || range.startContainer.nodeType !== Node.TEXT_NODE) return;

        const textNode = range.startContainer;
        const fullText = textNode.nodeValue;
        const clickPos = range.startOffset;

        // 智能范围限制
        const startPos = Math.max(0, clickPos - CONFIG.CONTEXT_RANGE/2);
        const endPos = Math.min(fullText.length, clickPos + CONFIG.CONTEXT_RANGE/2);
        const contextText = fullText.slice(startPos, endPos);
        const localClickPos = clickPos - startPos;

        // 精准匹配
        let matchCount = 0;
        let targetMatch = null;
        const regex = new RegExp(CONFIG.URL_REGEX.source, 'gi');

        let match;
        while ((match = regex.exec(contextText)) !== null) {
            if (++matchCount > CONFIG.MAX_MATCHES) break;

            const globalStart = startPos + match.index;
            const globalEnd = globalStart + match[0].length;

            if (localClickPos >= match.index && localClickPos <= match.index + match[0].length) {
                targetMatch = {
                    url: match[0],
                    start: globalStart,
                    end: globalEnd
                };
                break; // 找到第一个匹配即退出
            }
        }

        if (!targetMatch) return;

        // 执行转换
        isProcessing = true;
        const { url, start, end } = targetMatch;

        requestAnimationFrame(() => {
            const a = document.createElement('a');
            a.className = CONFIG.STYLE_CLASS;
            a.href = url.startsWith('www.') ? `http://${url}` : url;
            a.textContent = url;

            const before = document.createTextNode(fullText.slice(0, start));
            const after = document.createTextNode(fullText.slice(end));

            const parent = textNode.parentNode;
            parent.insertBefore(before, textNode);
            parent.insertBefore(a, textNode);
            parent.insertBefore(after, textNode);
            parent.removeChild(textNode);

            // 恢复流程
            setTimeout(() => {
                restoreSelection();
                isProcessing = false;
            }, CONFIG.COOLDOWN);

            event.stopImmediatePropagation();
            event.preventDefault();
        });
    }

    // 事件监听优化
    document.addEventListener('mousedown', saveSelection);
    document.addEventListener('mouseup', saveSelection);
    document.addEventListener('click', smartConvert, {
        capture: true,
        passive: false
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址