rBlock

移除一些网站用于数据统计的跳转功能,加快访问目标地址的速度。包括谷歌、知乎等,并添加少量定制化。| Removes redirects of some sites, such as google, zhihu..., add some customization.

As of 2016-07-03. See the latest version.

// ==UserScript==
// @name         rBlock
// @description  移除一些网站用于数据统计的跳转功能,加快访问目标地址的速度。包括谷歌、知乎等,并添加少量定制化。| Removes redirects of some sites, such as google, zhihu..., add some customization.
// @namespace    https://greasyfork.org/zh-CN/scripts/20568-rblock
// @homepageURL  https://github.com/nonoroazoro/rBlock
// @author       nonoroazoro
// @include      /^https?\:\/\/(www|encrypted|news)\.google\./
// @include      /^https?\:\/\/(www|zhuanlan)\.zhihu\./
// @version      1.2.4
// @run-at       document-end
// @grant        none
// ==/UserScript==

if (typeof unsafeWindow === "undefined")
{
    unsafeWindow = window;
}

const rBlock = {

    _blockers: [],

    start: function ()
    {
        this.reset();
        for (let blocker of this._blockers)
        {
            blocker.start();
        }
    },

    reset: function ()
    {
        this._blockers = [];

        // 1. google
        this._blockers.push(
            {
                start: function ()
                {
                    if (/^https?\:\/\/(www|encrypted|news)\.google\./.test(unsafeWindow.location.href))
                    {
                        const scope = this._getScope();
                        if (scope)
                        {
                            this._block(scope);
                            const observer = new unsafeWindow.MutationObserver((p_mutations) =>
                            {
                                this._block(scope);
                            });
                            observer.observe(document.body,
                                {
                                    childList: true,
                                    subtree: true
                                });
                        }
                    }
                },

                // block redirects of google
                _block: function (p_scope)
                {
                    let base;
                    let elem;
                    let elems;
                    if (["all", "videos", "news", "apps"].indexOf(p_scope) != -1)
                    {
                        // 1. all/videos/news/apps
                        base = document.querySelector("div#search");
                        elems = base.querySelectorAll(`a[onmousedown^="return rwt("]`);
                        for (let e of elems)
                        {
                            _removeAttributes(e, "onmousedown");
                        }
                    }
                    else if (["images"].indexOf(p_scope) != -1)
                    {
                        // 2. images
                        base = document.querySelector("div#search");
                        elems = base.querySelectorAll(`a[class^="irc_"], a[class*=" irc_"]`);
                        for (let e of elems)
                        {
                            _removeListeners(e, "mousedown");
                        }
                    }
                    else if (["books"].indexOf(p_scope) != -1)
                    {
                        // 3. books
                        base = document.querySelector("div#search");
                        elems = base.querySelectorAll(`a`);
                        for (let e of elems)
                        {
                        // open in new tab
                            if (!e.target)
                            {
                                e.target = "_blank";
                            }
                        }
                    }
                    else if (["news.google.com"].indexOf(p_scope) != -1)
                    {
                        // 4. news.google.com
                        elems = document.querySelectorAll(`.content-pane-container a.article`);
                        for (let e of elems)
                        {
                            _removeListeners(e, "click mousedown");
                        }
                    }

                    // 4. general
                    revealURL(
                        document.querySelectorAll(`a[href^="/url?"]`),
                        /^(?:\/url\?.*url=)(.*?)(?:&usg=|$)/i
                    );

                    // 5. cached links
                    let menuLink;
                    let cacheLink;
                    elems = document.querySelectorAll(`a[href^="http://webcache.googleusercontent."], a[href^="https://webcache.googleusercontent."]`);
                    for (let e of elems)
                    {
                        e.style.display = "inline";
                        menuLink = e.closest("div.action-menu.ab_ctl");

                        cacheLink = document.createElement("a");
                        cacheLink.setAttribute("href", e.getAttribute("href").replace(/^http\:/, "https:"));
                        cacheLink.target = "_blank";
                        cacheLink.innerText = " Cached ";

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

                _getScope: function ()
                {
                    const elem = document.querySelector("div.hdtb-msel");
                    const result = (elem ? elem.innerText : unsafeWindow.location.host).toLowerCase();
                    return result;
                }
            });

        // 2. zhihu
        this._blockers.push(
            {
                start: function ()
                {
                    if (/^https?\:\/\/(www|zhuanlan)\.zhihu\./.test(unsafeWindow.location.href))
                    {
                        this._block();
                        const observer = new unsafeWindow.MutationObserver((p_mutations) =>
                        {
                            this._block();
                        });
                        observer.observe(document.body,
                            {
                                childList: true,
                                subtree: true
                            });
                    }
                },

                _block: function ()
                {
                    // 1. general
                    revealURL(
                        document.querySelectorAll(
                            `a[href^="http://link.zhihu.com"], a[href^="https://link.zhihu.com"], a[href^="//link.zhihu.com"]`
                        ),
                        /(?:https?)?\:\/\/link\.zhihu\.com\/\?target=(.*)/i
                    );
                }
            });
    }
};

function _removeAttributes(p_element, p_attributes)
{
    if (p_element && typeof p_attributes === "string")
    {
        const attributes = p_attributes.split(/\W+/) || [];
        for (let attribute of attributes)
        {
            p_element.removeAttribute(attribute);
        }
    }
}

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

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

/**
 * reveal url
 */
function revealURL(p_elems, p_regex)
{
    if (p_elems && p_regex)
    {
        for (let e of p_elems)
        {
        // reveal url
            const m = e.getAttribute("href").match(p_regex);
            if (m && m[1])
            {
                e.setAttribute("href", decodeURIComponent(m[1]));
            }

        // open in new tab
            if (!e.target)
            {
                e.target = "_blank";
            }
        }
    }
}

rBlock.start();