// ==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\./ // @downloadURL none // ==/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();