// ==UserScript==
// @name rBlock
// @description 移除一些网站用于数据统计的跳转功能,加快访问目标地址的速度。包括 Google、GitHub、知乎等,并添加少量定制化。| Removes redirects of some sites, such as Google, GitHub, 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\./
// @include /^https?\:\/\/(gist\.)?github\.com/
// @version 1.2.6
// @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))
{
// 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 host = unsafeWindow.location.host;
if (host === "news.google.com")
{
// 1. news.google.com
const elems = document.querySelectorAll(`.content-pane-container a.article`);
for (let e of elems)
{
_removeListeners(e, "click mousedown");
}
}
else
{
const base = document.querySelector("div#search");
if (base)
{
// 1. all/videos/news/apps
let elems = base.querySelectorAll(`a[onmousedown^="return rwt("]`);
for (let e of elems)
{
_removeAttributes(e, "onmousedown");
}
// 2. images
elems = base.querySelectorAll(`a[class^="irc_"], a[class*=" irc_"]`);
for (let e of elems)
{
_removeListeners(e, "mousedown");
}
// 3. books
revealURL(
base.querySelectorAll(`a[href^="/aclk?"]`),
/\/aclk?.*url=(.*)/i
);
// 4. general
revealURL(
document.querySelectorAll(`a[href*="/url?"]`),
/(?:\/url\?.*url=)(.*?)(?:&usg=|$)/i
);
// 5. cached links
elems = document.querySelectorAll(`a[href^="http://webcache.googleusercontent."], a[href^="https://webcache.googleusercontent."]`);
let targets = document.querySelectorAll(`a.rblock-cached-link`);
if (elems.length != targets.length * 2)
{
// prevent duplication
let menuLink;
let cacheLink;
for (let elem of elems)
{
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
this._blockers.push(
{
start: function ()
{
if (/^https?\:\/\/(www|zhuanlan)\.zhihu\./.test(unsafeWindow.location.href))
{
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", // 话题
],
"data-type":
[
"daily", // 发现
]
},
this._block
);
}
},
_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
);
// 2. open in new tab
const elems = document.querySelectorAll(`a.internal`);
for (let elem of elems)
{
_openInNewTab(elem);
}
}
}
);
// 3. github
this._blockers.push(
{
start: function ()
{
if (/^https?\:\/\/(gist\.)?github\.com/.test(unsafeWindow.location.href))
{
this._block();
}
},
_block: function ()
{
// 1. general
document.addEventListener("keydown", (e) =>
{
if (e.key === "s" || e.key === "S")
{
e.stopPropagation();
}
}, true);
}
}
);
}
};
function _startMutationObserver(p_filter, p_handler)
{
if (typeof p_handler === "function")
{
const filter = p_filter || {};
const observer = new unsafeWindow.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_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
_openInNewTab(e);
}
}
}
function _openInNewTab(p_elem)
{
if (p_elem && !p_elem.target)
{
p_elem.target = "_blank";
}
}
rBlock.start();