码桶
发现社区成员的开源项目
content.js2.5 KB
/*!
* 超链新标签页打开 (Open Links in New Tab)
* 强制所有超链接在新标签页中打开。
*
* 作者:白逸 | 官网:https://imxcy.cn
* Copyright (c) 白逸. All rights reserved.
*/
(function () {
"use strict";
var STORAGE_KEY = "enabled";
var enabled = true;
// 读取初始开关状态(默认开启)
chrome.storage.local.get({ enabled: true }, function (item) {
enabled = item.enabled;
});
// 开关状态变化时实时同步
chrome.storage.onChanged.addListener(function (changes, area) {
if (area === "local" && changes[STORAGE_KEY]) {
enabled = changes[STORAGE_KEY].newValue;
}
});
// 在事件路径中向上查找最近的 <a> 元素,兼容 Shadow DOM 与 <svg> 内的链接
function findAnchor(event) {
var path = typeof event.composedPath === "function" ? event.composedPath() : null;
if (path) {
for (var i = 0; i < path.length; i++) {
var node = path[i];
if (node && node.nodeType === 1) {
var tag = node.tagName;
if (tag === "A" || tag === "a") return node;
}
}
return null;
}
// 回退:无 composedPath 时使用 closest
var target = event.target;
return target && target.closest ? target.closest("a") : null;
}
// 判断链接是否应被跳过(保持浏览器默认行为)
function shouldSkip(link, href) {
if (!href) return true;
if (href.charAt(0) === "#") return true; // 页内锚点
if (/^\s*(javascript|mailto|tel|sms|blob|data):/i.test(href)) return true;
if (link.hasAttribute("download")) return true; // 下载链接
if (link.target === "_blank") return true; // 已是新标签页
return false;
}
document.addEventListener(
"click",
function (e) {
if (!enabled) return;
// 仅处理鼠标左键,且不干扰用户的组合键操作
if (e.button !== 0) return;
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return;
if (e.defaultPrevented) return; // 页面脚本已自行处理
var link = findAnchor(e);
if (!link) return;
var href = link.getAttribute("href");
if (shouldSkip(link, href)) return;
var url = link.href; // 使用解析后的绝对地址
if (!url) return;
e.preventDefault();
e.stopPropagation();
// noopener/noreferrer:避免新页面通过 window.opener 反向操作原页面
window.open(url, "_blank", "noopener,noreferrer");
},
true
);
})();