Created
January 6, 2011 13:02
-
-
Save nmaier/767855 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Linkify Plus | |
// @version 2.0.2 | |
// @namespace http://arantius.com/misc/greasemonkey/ | |
// @description Turn plain text URLs into links. Supports http, https, ftp, email addresses. | |
// @include http* | |
// @exclude http://www.google.tld/search* | |
// @exclude https://encrypted.google.tld/search* | |
// ==/UserScript== | |
/******************************************************************************* | |
Loosely based on the Linkify script located at: | |
http://downloads.mozdev.org/greasemonkey/linkify.user.js | |
Originally written by Anthony Lieuallen of http://arantius.com/ | |
Licensed for unlimited modification and redistribution as long as | |
this notice is kept intact. | |
If possible, please contact me regarding new features, bugfixes | |
or changes that I could integrate into the existing code instead of | |
creating a different script. Thank you. | |
Version history: | |
Version 2.0.3: | |
- Fix infinite recursion on X(HT)ML pages. | |
Version 2.0.2: | |
- Limit @include, for greater site/plugin compatibility. | |
Version 2.0.1: | |
- Fix aberrant 'mailto:' where it does not belong. | |
Version 2.0: | |
- Apply incrementally, so the browser does not hang on large pages. | |
- Continually apply to new content added to the page (i.e. AJAX). | |
Version 1.1.4: | |
- Basic "don't screw up xml pretty printing" exception case | |
Version 1.1.3: | |
- Include "+" in the username of email addresses. | |
Version 1.1.2: | |
- Include "." in the username of email addresses. | |
Version 1.1: | |
- Fixed a big that caused the first link in a piece of text to | |
be skipped (i.e. not linkified). | |
*******************************************************************************/ | |
var notInTags=[ | |
'a', 'head', 'noscript', 'option', 'script', 'style', 'title', 'textarea' | |
]; | |
var textNodeXpath= | |
".//text()[not(ancestor::ns:"+notInTags.join(') and not(ancestor::ns:')+")]"; | |
var urlRE=/((?:https?|ftp):\/\/[^\s'"'<>()]+|www\.[^\s'"'<>()]+|[-\w.+]+@(?:[-\w]+\.)+[\w]{2,6})/gi; | |
var queue=[]; | |
/******************************************************************************/ | |
linkifyContainer(document.body); | |
document.body.addEventListener('DOMNodeInserted', function(event) { | |
linkifyContainer(event.target); | |
}, false); | |
/******************************************************************************/ | |
function linkifyContainer(container) { | |
var xpathResult=document.evaluate( | |
textNodeXpath, | |
container, | |
container.namespaceURI | |
? { lookupNamespaceURI: function(prefix) { return container.namespaceURI; } } | |
: null, | |
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, | |
null | |
); | |
var i=0; | |
function continuation() { | |
var node, counter=0; | |
while (node=xpathResult.snapshotItem(i++)) { | |
linkifyTextNode(node); | |
if (++counter>50) { | |
return setTimeout(continuation, 0); | |
} | |
} | |
} | |
setTimeout(continuation, 0); | |
} | |
function linkifyTextNode(node) { | |
var i, l, m; | |
var txt=node.textContent; | |
var span=null; | |
var p=0; | |
while (m=urlRE.exec(txt)) { | |
if (null==span) { | |
//create a span to hold the new text with links in it | |
span=document.createElement('span'); | |
} | |
//get the link without trailing dots | |
l=m[0].replace(/\.*$/, ''); | |
//put in text up to the link | |
span.appendChild(document.createTextNode(txt.substring(p, m.index))); | |
//create a link and put it in the span | |
a=document.createElement('a'); | |
a.appendChild(document.createTextNode(l)); | |
if (l.match(/^www/i)) { | |
l='http://'+l; | |
} else if (-1==l.indexOf('://')) { | |
l='mailto:'+l; | |
} | |
a.setAttribute('href', l); | |
span.appendChild(a); | |
//track insertion point | |
p=m.index+m[0].length; | |
} | |
if (span) { | |
//take the text after the last link | |
span.appendChild(document.createTextNode(txt.substring(p, txt.length))); | |
//replace the original text with the new span | |
try { | |
node.parentNode.replaceChild(span, node); | |
} catch (e) { | |
console.error(e); | |
console.log(node); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment