// ==UserScript== // @name 网页文本转链接 // @description 网页中文本转为可点击链接 添加颜色下划线 // @version 2.1 // @author WJ // @match *://*/* // @license MIT // @grant none // @namespace https://greasyfork.org/users/914996 // @downloadURL none // ==/UserScript== (function() { 'use strict'; const ZZ = /\b([\w.?:/=%&#-]{3,}\.(?:app|aero|aer|art|asia|beer|biz|cat|cc|chat|ci|cloud|club|cn|com|cool|coop|co|dev|edu|email|fit|fun|gov|govt|group|hk|host|icu|info|ink|int|io|jobs|kim|love|ltd|luxe|me|mil|mobi|moe|museum|name|net|nl|network|one|online|org|plus|post|press|pro|red|ren|run|ru|shop|site|si|space|store|tech|tel|top|travel|tv|tw|uk|us|video|vip|wang|website|wiki|wml|work|ws|xin|xyz|yoga|zone)(?!\w)[\w.?:/=%&#-]*)/gi; // 添加样式 document.head.insertAdjacentHTML('beforeend', '' ); // 一次性收集所有文本节点 const treeWalker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, { acceptNode: (node) => { const parent = node.parentNode; // 预过滤:跳过不需要处理的节点 if (parent.tagName === 'SCRIPT' || parent.tagName === 'STYLE' || parent.tagName === 'TEXTAREA' || parent.tagName === 'A' || parent.isContentEditable) { return NodeFilter.FILTER_REJECT; } return NodeFilter.FILTER_ACCEPT; } } ); // 批量处理节点 const nodes = []; while (treeWalker.nextNode()) nodes.push(treeWalker.currentNode); // 高效处理循环 for (let i = 0, len = nodes.length; i < len; i++) { const node = nodes[i]; const text = node.textContent; // 快速跳过不含域名的文本 if (!ZZ.test(text)) continue; ZZ.lastIndex = 0; // 重置正则 // 创建替换内容 let newHtml = text.replace(ZZ, match => { return `${match}`; }); // 执行DOM替换 if (newHtml !== text) { const span = document.createElement('span'); span.innerHTML = newHtml; node.replaceWith(span); } } })();