Greasy Fork

文本链接自动识别为超链接

通过正则表达式识别文本中的链接,并转换为超链接

目前为 2022-09-30 提交的版本。查看 最新版本

// ==UserScript==
// @name               Textlink to Hyperlink
// @name:zh-CN         文本链接自动识别为超链接
// @version            0.1.1
// @description        Recognize links in text by regular expression, and convert to hyperlinks
// @description:zh-CN  通过正则表达式识别文本中的链接,并转换为超链接
// @author             DreamNya
// @match              *://*/*
// @grant              none
// @run-at             document-start
// @license            MIT
// @namespace https://greasyfork.org/users/809466
// ==/UserScript==

//文本链接识别正则
const reg = /https?:\/\/[\w\.-]+\.\w+(:\d{1,5})?(\/[#%\w?&.=\-@]+)*/g;
//忽略标签类型
const ignore = ['SCRIPT', 'STYLE', 'A'];

//脚本运行时遍历所有节点
queryElement(document)

//后续通过观察器监视
let obs = new MutationObserver(m => {
    m.forEach(mm => {
        formatHref(mm.target, mm.addedNodes)
        mm.addedNodes.forEach(i => queryElement(i))
    })
});
obs.observe(document, { subtree: true, childList: true });

function queryElement(element) {
    //用了点语法糖
    [...(element.querySelectorAll?.("*") ?? [])].forEach(i => formatHref(i, i.childNodes))
}

function formatHref(target, childNodes) {
    //忽略标签
    if (ignore.find(n => n == target.nodeName)) return

    let mark = false;

    //文本链接构造为a标签
    [...childNodes].forEach(c => {
        if (c.nodeName == '#text' && c.textContent.match(reg)) {
            c.textContent = c.textContent.replace(reg, (m) => { return `<a href='${m}' target='_blank'>${m}</a>` })
            mark = true
        }
    })

    //格式化标签
    if (mark) {
        target.innerHTML = target.innerHTML.replace(/&lt;a /g, "<a ").replace(/&lt;\/a&gt;/g, "</a>").replace(/' target='_blank'&gt;/g, "' target='_blank'>")
    }
}