Greasy Fork

rBlock

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

目前为 2016-11-30 提交的版本。查看 最新版本

// ==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();