您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Replace twitter short URLs (t.co) by real URLs. Enable HTTPS for other shorterners. Block referers. Improve privacy.
当前为
// ==UserScript== // @name Canonical links // @author Guillaume // @description Replace twitter short URLs (t.co) by real URLs. Enable HTTPS for other shorterners. Block referers. Improve privacy. // @namespace https://greasyfork.org/fr/users/11386-guillaume // @include https://twitter.com/* // @version 1.2 // @grant none // @run-at document-start // @license CC by-sa http://creativecommons.org/licenses/by-sa/3.0/ // ==/UserScript== // Credits: // // - getVisibleText, textContentVisible: // This is derived from a work by Ethan Brown. // Original license: cc-by sa // Source: http://stackoverflow.com/questions/19985306/get-the-innertext-of-an-element-but-exclude-hidden-children function getVisibleText( node ) { if ( node.nodeType === 1 ) // Element { var rect = node.getBoundingClientRect(); if ( rect.width === 0 || rect.height === 0 ) return ''; } else if ( node.nodeType === 3 ) // Text { return node.textContent; } var text = ''; for( var i = 0; i < node.childNodes.length; i++ ) text += getVisibleText( node.childNodes[i] ); return text; } if ( ! Node.prototype.hasOwnProperty('textContentVisible') ) { Object.defineProperty(Node.prototype, 'textContentVisible', { get: function() { return getVisibleText( this ); }, enumerable: true }); } var hostRules = {}; hostRules['ln.is'] = function(pathn) { return 'https://www.youtube.com/watch?v=' + pathn.substr(1); }; hostRules['youtu.be'] = function(pathn) { return 'https://www.youtube.com/watch?v=' + pathn.substr(1); }; var hostsWithHttps = { 'bit.ly': true, 'bc.vc': true, 'db.tt': true, 'goo.gl': true, 'grnpc.org': true, 'is.gd': true, 'j.mp': true, 'lnkd.in': true, 't.co': true, 'tinyurl.com': true, 'v.gd': true, 'vur.me': true, 'x.co': true }; var makeLinkCanonical = function(el) { var i = 0; var limit = 3; while ( hostRules[el.hostname] && i < limit ) { var urlFactory = hostRules[el.hostname]; el.href = urlFactory(el.pathname, el.search, el.hash); } // normalize host el.host = el.host; } var makeLinkPrivate = function(el) { // use https if ( el.protocol === 'http:' && hostsWithHttps[el.host] ) { el.protocol = 'https:'; } // disable referers el.rel = 'noreferrer'; } var makeLinkExpanded = function(el) { var text = document.createTextNode(el.textContentVisible); var url = el.dataset.expandedUrl; var newLink = document.createElement('a'); newLink.href = url; newLink.title = el.title; newLink.className = el.className; newLink.dir = el.dir; newLink.appendChild(text); el.parentNode.replaceChild(newLink, el); }; var onLink = function(el) { makeLinkCanonical(el); makeLinkPrivate(el); } var onTwitterLink = function(el) { makeLinkExpanded(el); } window.addEventListener("load", function(ev) { // unshadow for better debugging delete console.log; // initial pass [].slice.call(document.querySelectorAll('a[data-expanded-url]')).forEach(onTwitterLink); [].slice.call(document.querySelectorAll('a[href]')).forEach(onLink); // watch changes var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { for ( var i = 0; i < mutation.addedNodes.length; i++ ) { var node = mutation.addedNodes[i]; if ( node.querySelectorAll ) { [].slice.call(node.querySelectorAll('a[data-expanded-url]')).forEach(onTwitterLink); [].slice.call(node.querySelectorAll('a[href]')).forEach(onLink); } } }); }); var config = { childList: true, subtree: true }; observer.observe(document, config); }, true);