Greasy Fork

Greasy Fork is available in English.

强制后台新建标签页打开所有链接

所有链接强制后台新建标签页打开,兼容Firefox和Chrome

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         强制后台新建标签页打开所有链接
// @namespace    http://greasyfork.icu/
// @version      1.4
// @license      MIT
// @author       pugfly
// @match        *://*/*
// @grant        GM_openInTab
// @grant        GM_addStyle
// @grant        unsafeWindow
// @run-at       document-start
// @description 所有链接强制后台新建标签页打开,兼容Firefox和Chrome
// ==/UserScript==

(function() {
    'use strict';

    // ===== 全局配置 =====
    const CONFIG = {
        XUEQIU: {
            WHITELIST: [
                /\/u\/[\w-]+$/,          // 用户主页
                /\/S\/[A-Z0-9_.]+$/,     // 股票代码
                /\/\d+\/status\/\d+/     // 帖子详情
            ],
            BLACKLIST_KEYWORDS: /(展开|收起|评论|回复|讨论|更多|分享|收藏|点赞|举报|关闭)/,
            FIX_CSS: `
                [class*='modal-close'], [class*='ad-close'] {
                    z-index: 9999 !important;
                    pointer-events: auto !important;
                }
            `
        }
    };

    // ===== 雪球网专用模块 =====
    if (window.location.hostname.includes('xueqiu.com')) {
        // 1. 样式修复
        GM_addStyle(CONFIG.XUEQIU.FIX_CSS);

        // 2. 智能链接处理
        document.addEventListener('click', function(e) {
            const link = e.target.closest('a');
            if (!link || !link.href) return;

            // 排除功能链接
            const isFunctional = 
                CONFIG.XUEQIU.BLACKLIST_KEYWORDS.test(link.textContent) ||
                link.href.startsWith('javascript:') ||
                link.hasAttribute('onclick');

            // 匹配白名单链接
            const shouldOpen = CONFIG.XUEQIU.WHITELIST.some(re => re.test(link.href));

            if (!isFunctional && shouldOpen) {
                e.preventDefault();
                e.stopImmediatePropagation();
                GM_openInTab(link.href, { active: false });
            }
        }, true);

        // 3. 拦截SPA路由
        const nativePushState = history.pushState;
        history.pushState = function(state, title, url) {
            if (url && CONFIG.XUEQIU.WHITELIST.some(re => re.test(url))) {
                GM_openInTab(url, { active: false });
                return;
            }
            nativePushState.apply(this, arguments);
        };

        return; // 阻断后续通用逻辑
    }

    // ===== 通用网站模块 =====
    let isProcessing = false;
    
    // 1. 链接点击处理
    document.addEventListener('click', function(e) {
        if (isProcessing) return;
        isProcessing = true;

        let target = e.target;
        while (target && target.tagName !== 'A') target = target.parentElement;
        if (!target?.href) return;

        // 排除功能链接
        if (target.href.startsWith('javascript:') || target.hasAttribute('onclick')) return;

        e.preventDefault();
        e.stopImmediatePropagation();
        GM_openInTab(target.href, { active: false });

        setTimeout(() => isProcessing = false, 50);
    }, true);

    // 2. 表单提交处理
    document.addEventListener('submit', function(e) {
        const form = e.target;
        if (form.tagName !== 'FORM') return;

        e.preventDefault();
        const url = new URL(form.action || window.location.href);
        new FormData(form).forEach((v,k) => url.searchParams.append(k,v));
        GM_openInTab(url.href, { active: false });
    }, true);

    // 3. 回车键处理
    document.addEventListener('keydown', function(e) {
        if (e.key === 'Enter' && e.target.tagName === 'INPUT') {
            const input = e.target;
            const form = input.closest('form');
            if (form) return; // 由表单提交处理

            const url = new URL(window.location.href);
            url.searchParams.set(input.name || 'q', input.value);
            GM_openInTab(url.href, { active: false });
            e.preventDefault();
        }
    }, true);

    // 4. 动态内容监控
    new MutationObserver(mutations => {
        mutations.forEach(({ addedNodes }) => {
            addedNodes.forEach(node => {
                if (node.nodeType === 1) {
                    node.querySelectorAll('a').forEach(link => {
                        link.setAttribute('target', '_blank');
                    });
                }
            });
        });
    }).observe(document, { subtree: true, childList: true });
})();