rBlock

移除一些网站用于数据统计的链接跳转及部分其他功能,加快网站访问速度。

当前为 2016-11-30 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name            rBlock
// @author          nonoroazoro
// @description     移除一些网站用于数据统计的链接跳转及部分其他功能,加快网站访问速度。
// @description:en  Remove redirects and some features of web sites.
// @homepageURL     https://github.com/nonoroazoro/rBlock
// @namespace       https://greasyfork.org/zh-CN/scripts/20568-rblock
// @grant           none
// @version         1.2.9
// @run-at          document-end
// @include         /^https?:\/\/(.+\.)?github\./
// @include         /^https?:\/\/(.+\.)?google\./
// @include         /^https?:\/\/(.+\.)?zhihu\./
// ==/UserScript==

const rBlock = {

    _blockers: [],

    start: function ()
    {
        this.init();
        this._blockers.forEach(blocker => blocker.start());
    },

    init: function ()
    {
        this._blockers = [];
        const _host = window.location.host;

        // 1. google
        if (/^(.+\.)?google\./.test(_host))
        {
            this._blockers.push({
                start: function ()
                {
                    // 1. for static pages.
                    // when google instant predictions is disabled,
                    // this blocker will only be called once.
                    this._block();

                    // 2. for dynamic pages.
                    // when google instant predictions is enabled,
                    // this blocker will be call whenever the current page is updated.
                    _startMutationObserver(
                        {
                            "id":
                            [
                                "search", // all/videos/news/shopping/books/apps
                            ],
                            "class":
                            [
                                "irc_rit", // images
                                "pspo-popout pspo-lpop", // shopping
                            ]
                        },
                        this._block
                    );
                },

                // block redirects of google
                _block: function ()
                {
                    const base = document.querySelector("div#search");
                    if (base)
                    {
                        // 1. general
                        revealURL(
                            base.querySelectorAll(`a[href*="url="]`),
                            /.*url=(http[^&]+)/i
                        );

                        // 2. all/videos/news/apps
                        let elems = base.querySelectorAll(`a[onmousedown^="return rwt("]`);
                        _removeAttributes(elems, "onmousedown");

                        // 3. cached links
                        elems = document.querySelectorAll(`a[href^="http://webcache.googleusercontent."], a[href^="https://webcache.googleusercontent."]`);
                        const targets = document.querySelectorAll(`a.rblock-cached-link`);
                        if (elems.length !== targets.length * 2)
                        {
                            // prevent duplication
                            let menuLink;
                            let cacheLink;
                            elems.forEach((elem) =>
                            {
                                elem.style.display = "inline";
                                menuLink = elem.closest("div.action-menu.ab_ctl");

                                cacheLink = document.createElement("a");
                                cacheLink.setAttribute("href", elem.getAttribute("href").replace(/^http\:/, "https:"));
                                cacheLink.setAttribute("class", "rblock-cached-link");
                                cacheLink.target = "_blank";
                                cacheLink.innerText = " Cached ";

                                menuLink.parentNode.insertBefore(cacheLink, menuLink);
                            });
                        }
                    }
                }
            });
        }

        // 2. zhihu

        if (/^(.+\.)?zhihu\./.test(_host))
        {
            this._blockers.push({
                start: function ()
                {
                    this._block();

                    _startMutationObserver(
                        {
                            "id":
                            [
                                "js-home-feed-list", // 首页最新动态
                                "zh-question-answer-wrap", // 具体内容
                            ],
                            "class":
                            [
                                "zm-item-rich-text expandable js-collapse-body", // 首页、话题显示全部
                                "zh-general-list clearfix", // 话题
                                "entry", // 专栏
                            ],
                            "data-type":
                            [
                                "daily", // 发现
                            ]
                        },
                        this._block
                    );
                },

                _block: function ()
                {
                    // 1. general
                    revealURL(
                        document.querySelectorAll(`a[href*="?target="]`),
                        /.*target=(http[^&]+)/i
                    );

                    // 2. open in new tab
                    document.querySelectorAll(`a.internal`).forEach((elem) => _openInNewTab(elem));
                }
            });
        }

        // 3. github
        if (/^(.+\.)?github\./.test(_host))
        {
            this._blockers.push({
                start: function ()
                {
                    this._block();
                },

                _block: function ()
                {
                    // 1. disable keyboard shortcuts: "s" and "w"
                    document.addEventListener("keydown", (e) =>
                    {
                        if (e.key === "s" || e.key === "S" || e.key === "w" || e.key === "W")
                        {
                            e.stopPropagation();
                        }
                    }, true);
                }
            });
        }
    }
};

function _startMutationObserver(p_filter, p_handler)
{
    if (typeof p_handler === "function")
    {
        const filter = p_filter || {};
        const observer = new window.MutationObserver((p_mutations) =>
        {
            let needUpdate = false;
            for (let mutation of p_mutations)
            {
                for (let key in p_filter)
                {
                    if (p_filter[key].indexOf(mutation.target.getAttribute(key)) != -1)
                    {
                        needUpdate = true;
                        break;
                    }
                }

                if (needUpdate)
                {
                    break;
                }
            }

            if (needUpdate)
            {
                p_handler();
            }
        });
        observer.observe(document.body,
            {
                childList: true,
                subtree: true
            }
        );
    }
}

function _removeAttributes(p_elements, p_attributes)
{
    if (p_elements && typeof p_attributes === "string")
    {
        const attributes = p_attributes.split(/\W+/) || [];
        p_elements.forEach((elem) =>
        {
            attributes.forEach((attr) =>
            {
                elem.removeAttribute(attr);
            });
        });
    }
}

function _removeListeners(p_element, p_events)
{
    if (p_element && typeof p_events === "string")
    {
        const events = p_events.split(/\W+/) || [];
        events.forEach((event) =>
        {
            p_element.removeEventListener(event, _preventDefaultAction, true);
            p_element.addEventListener(event, _preventDefaultAction, true);
        });
    }
}

function _preventDefaultAction(e)
{
    e.stopPropagation();
}

function revealURL(p_elems, p_regex)
{
    if (p_elems && p_regex)
    {
        let groups;
        p_elems.forEach((elem) =>
        {
            // reveal url & open in new tab
            groups = decodeURIComponent(elem.getAttribute("href")).match(p_regex);
            if (groups && groups[1])
            {
                elem.setAttribute("href", groups[1]);
                _openInNewTab(elem);
            }
        });
    }
}

function _openInNewTab(p_elem)
{
    if (p_elem)
    {
        p_elem.target = "_blank";
    }
}

rBlock.start();