Greasy Fork

来自缓存

Greasy Fork is available in English.

Bilibili 禁止新标签页打开链接

让哔哩哔哩所有链接在当前标签页打开

当前为 2025-02-16 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Bilibili 禁止新标签页打开链接
// @name:en      Bilibili No New Tab
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  让哔哩哔哩所有链接在当前标签页打开
// @description:en Force all Bilibili links to open in the current tab instead of a new tab
// @author       ChingyuanCheng
// @license      MIT
// @match        *://*.bilibili.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // 判断是否为B站域名
    function isBilibiliDomain(url) {
        try {
            const u = new URL(url, location.href);
            return u.hostname.endsWith('.bilibili.com') ||
                   u.hostname === 'bilibili.com';
        } catch {
            return false;
        }
    }

    // 判断是否为赛事页面
    function isMatchPage() {
        return location.pathname.startsWith('/match/');
    }

    /**
     * 核心拦截:处理所有可能的跳转方式
     */
    function interceptAllNavigations() {
        // 拦截 window.open
        const originalOpen = window.open;
        window.open = function(url, target, features) {
            if (typeof url === 'string' && isBilibiliDomain(url)) {
                console.log(`[全局拦截] window.open: ${url}`);
                location.href = url;
                return null;
            }
            return originalOpen(...arguments);
        };

        // 拦截所有链接点击(包括动态生成和事件委托)
        document.addEventListener('click', function(event) {
            let target = event.target;
            while (target && target.tagName !== 'A') {
                target = target.parentElement;
            }

            if (target?.tagName === 'A') {
                const href = target.getAttribute('href');
                if (href && isBilibiliDomain(href)) {
                    // 特殊处理赛事页面主站按钮
                    if (isMatchPage() && href === 'https://www.bilibili.com') {
                        console.log(`[赛事页面拦截] 主站跳转: ${href}`);
                        event.preventDefault();
                        event.stopImmediatePropagation();
                        location.href = href;
                    }
                    // 处理常规链接
                    else if (target.target === '_blank' || event.ctrlKey) {
                        console.log(`[全局拦截] <a> 跳转: ${href}`);
                        event.preventDefault();
                        event.stopImmediatePropagation();
                        location.href = href;
                    }
                }
            }
        }, true); // 捕获阶段处理
    }

    /**
     * 动态链接处理
     */
    function handleDynamicLinks() {
        // 初始处理
        modifyLinks();

        // 观察动态内容
        new MutationObserver(mutations => {
            mutations.forEach(() => modifyLinks());
        }).observe(document.body, {
            childList: true,
            subtree: true
        });

        function modifyLinks() {
            document.querySelectorAll('a').forEach(a => {
                if (isBilibiliDomain(a.href)) {
                    // 移除所有新标签页属性
                    a.removeAttribute('target');
                    a.removeAttribute('data-target-new');

                    // 特殊处理赛事页面主站按钮
                    if (isMatchPage() && a.href === 'https://www.bilibili.com') {
                        a.href = a.href.replace(/(\?|&)spm_id_from=[^&]*/, '');
                    }
                }
            });
        }
    }

    // 初始化
    function init() {
        interceptAllNavigations();
        handleDynamicLinks();
    }

    // 启动
    init();
})();