效果如图:
可以让文本内含有的链接变成可以点击的超链接。
在油猴里创建新的脚本,并粘贴下列内容:
// ==UserScript==
// @name 自动链接替换
// @namespace Violentmonkey Scripts
// @match https://marker.dotalk.cn/*
// @grant none
// @version 1.0
// @author Moy
// @description Automatically convert URLs to clickable links, including dynamically loaded content
// ==/UserScript==
(function() {
'use strict';
// 处理文本节点中的链接
function processTextNode(node) {
if (node.parentNode.tagName === 'SCRIPT' ||
node.parentNode.tagName === 'STYLE' ||
node.parentNode.tagName === 'NOSCRIPT' ||
node.parentNode.tagName === 'A' ||
node.parentNode.closest('a')) {
return;
}
const urlRegex = /(https?:\/\/[^\s]+)/g;
const text = node.textContent;
if (urlRegex.test(text)) {
const wrapper = document.createElement('span');
wrapper.innerHTML = text.replace(urlRegex, (url) => {
// 移除URL末尾的标点符号
const cleanUrl = url.replace(/[.,;!?]$/, '');
return `<a href="${cleanUrl}"
target="_blank"
rel="noopener noreferrer"
onclick="window.open('${cleanUrl}', '_blank'); return false;"
style="color: -webkit-link; text-decoration: underline; cursor: pointer;"
>${url}</a>`;
});
// 添加标记,避免重复处理
wrapper.setAttribute('data-processed', 'true');
node.parentNode.replaceChild(wrapper, node);
}
}
// 处理新添加或修改的节点
function processNode(node) {
// 如果节点已经处理过,跳过
if (node.nodeType === Node.ELEMENT_NODE &&
(node.getAttribute('data-processed') === 'true' || node.closest('[data-processed="true"]'))) {
return;
}
// 如果是文本节点,直接处理
if (node.nodeType === Node.TEXT_NODE) {
processTextNode(node);
return;
}
// 如果是元素节点,遍历其子节点
if (node.nodeType === Node.ELEMENT_NODE) {
// 使用TreeWalker遍历文本节点
const walker = document.createTreeWalker(
node,
NodeFilter.SHOW_TEXT,
{
acceptNode: function(node) {
if (node.parentNode.tagName === 'SCRIPT' ||
node.parentNode.tagName === 'STYLE' ||
node.parentNode.tagName === 'NOSCRIPT' ||
node.parentNode.tagName === 'A' ||
node.parentNode.closest('a') ||
node.parentNode.closest('[data-processed="true"]')) {
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
}
}
);
let textNode;
while (textNode = walker.nextNode()) {
processTextNode(textNode);
}
}
}
// 创建MutationObserver来监听DOM变化
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
// 处理新增的节点
mutation.addedNodes.forEach(node => {
processNode(node);
});
// 处理修改的节点
if (mutation.type === 'characterData') {
processNode(mutation.target);
}
});
});
// 配置观察选项
const config = {
childList: true, // 观察子节点的变化
subtree: true, // 观察所有后代节点
characterData: true // 观察文本内容的变化
};
// 开始观察整个文档
observer.observe(document.body, config);
// 初始处理页面上的现有内容
processNode(document.body);
})();