Remove redirection for URL shortened by twitter.com, identi.ca, and microca.st. Use HTTPS for other shorteners. Block referrers. Improve privacy.
当前为
// ==UserScript==
// @name Canonical links
// @author Guillaume
// @description Remove redirection for URL shortened by twitter.com, identi.ca, and microca.st. Use HTTPS for other shorteners. Block referrers. Improve privacy.
// @namespace https://greasyfork.org/fr/users/11386-guillaume
// @include https://twitter.com/*
// @include https://identi.ca/*
// @include https://microca.st/*
// @version 1.4
// @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['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,
'identi.ca': 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 textNode = 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(textNode);
el.parentNode.replaceChild(newLink, el);
};
var makeLinkFromTitle = function(el)
{
var url = el.title;
var text = el.textContentVisible;
if ( text.indexOf('http:') === 0 || text.indexOf('https:') )
text = url;
var textNode = document.createTextNode(text);
var newLink = document.createElement('a');
newLink.href = url;
newLink.title = el.title;
newLink.className = el.className;
newLink.dir = el.dir;
newLink.appendChild(textNode);
el.parentNode.replaceChild(newLink, el);
};
var onLink = function(el)
{
var updateText = false;
if ( el.childNodes.length == 1
&& el.childNodes[0].nodeType === 3
&& el.childNodes[0].textContent == el.href )
updateText = true;
makeLinkCanonical(el);
makeLinkPrivate(el);
if ( updateText )
{
var textNode = document.createTextNode(el.href);
el.replaceChild(textNode, el.childNodes[0]);
}
}
var onTwitterLink = function(el)
{
makeLinkExpanded(el);
}
var onPumpIOLink = function(el)
{
makeLinkFromTitle(el);
}
https://microca.st/dbd
window.addEventListener("load", function(ev) {
// unshadow for better debugging
delete console.log;
// initial pass
if ( window.Pump )
[].slice.call(document.querySelectorAll('a[title^=http]')).forEach(onPumpIOLink);
[].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);