Greasy Fork is available in English.
全站通用型页内增强脚本(精简版)
当前为
// ==UserScript==
// @name 当页开链
// @namespace
// @version 3.5
// @description 全站通用型页内增强脚本(精简版)
// @author none
// @match *://*/*
// @grant unsafeWindow
// @run-at document-body
// @namespace
// ==/UserScript==
(function() {
// 函数用于在当前标签页中打开链接
function openLinkInCurrentTab(url) {
window.location.href = url;
}
// 拦截所有点击事件
document.addEventListener('click', function(event) {
var target = event.target;
// 检查点击的元素以及其父元素是否是链接
while (target && target.tagName !== 'A') {
target = target.parentElement;
}
if (target && target.tagName === 'A') {
// 阻止默认行为,即在新标签页中打开链接
event.preventDefault();
// 获取链接的目标 URL
var url = target.href;
// 在当前标签页中打开链接
openLinkInCurrentTab(url);
}
});
'use strict';
// 协议安全名单
const SAFE_PROTOCOLS = new Set([
'http:', 'https:', 'ftp:',
'mailto:', 'tel:', 'sms:'
]);
// Shadow DOM处理器
const processShadowRoot = (root) => {
const stack = [root];
while (stack.length) {
const current = stack.pop();
current.querySelectorAll('a').forEach(processElement);
current.querySelectorAll('*').forEach(node => {
node.shadowRoot && stack.push(node.shadowRoot)
});
}
};
// 元素处理逻辑
const processElement = (element) => {
// 协议过滤
try {
const href = element.href?.toLowerCase() || '';
const protocol = new URL(href, location.href).protocol;
if (!SAFE_PROTOCOLS.has(protocol)) return;
} catch(e) {
return;
}
// 清理链接属性
['target', 'onclick', 'data-target'].forEach(attr => {
element.removeAttribute(attr);
});
};
// 智能观察器
const initObserver = () => {
const processed = new WeakSet();
let pending = new Set();
let isProcessing = false;
const batchProcess = () => {
const temp = new Set(pending);
pending.clear();
temp.forEach(node => {
if (node.nodeType === 1 && !processed.has(node)) {
processElement(node);
processed.add(node);
processShadowRoot(node);
}
});
isProcessing = false;
};
new MutationObserver(mutations => {
mutations.forEach(({ addedNodes }) => {
addedNodes.forEach(node => {
if (node.nodeType === 1) {
pending.add(node);
} else if (node.nodeType === 11) {
node.querySelectorAll('a').forEach(a => pending.add(a));
}
});
});
if (!isProcessing && pending.size) {
isProcessing = true;
batchProcess(); // 移除异步调度
}
}).observe(document, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['target', 'href']
});
};
// 核心初始化
const main = () => {
if (window.self !== window.top) return;
// 基础策略
if (!document.querySelector('base')) {
document.head.prepend(
Object.assign(document.createElement('base'), {
target: '_self'
})
);
}
// 初始处理
document.querySelectorAll('a').forEach(processElement);
processShadowRoot(document);
initObserver();
// 全局事件拦截
document.addEventListener('click', e => {
const target = e.composedPath()[0];
target.tagName === 'A' && processElement(target);
}, { capture: true });
// 处理window.open
unsafeWindow.open = function(url) {
window.location.href = url;
};
};
// 启动逻辑
document.readyState === 'complete' ? main() :
document.addEventListener('DOMContentLoaded', main);
})();