O'Reilly Hacks
oreilly.comO'Reilly NetworkSafari BookshelfConferences Sign In/My Account | View Cart   
Book List Learning Lab PDFs O'Reilly Gear Newsletters Press Room Jobs  


 
Buy the book!
Greasemonkey Hacks
By Mark Pilgrim
November 2005
More Info

HACK
#13
Turn Naked URLs into Hyperlinks
Make every URL clickable
The Code
[Discuss (0) | Link to this hack]

The Code

This user script runs on all pages. To ensure that it does not affect URLs that are already linked, it uses an XPath query that includes not(ancestor::a). To ensure that it does affect URLs in uppercase, the XPath query also includes "contains(translate(., 'HTTP', 'http'), 'http')]".

Once we find a text node that definitely contains an unlinked URL, there could be more than one URL within it, so we need to convert all the URLs while keeping the surrounding text intact. We replace the text with an empty <span> element as a placeholder and then incrementally reinsert each non-URL text snippet and each constructed URL link.

Save the following user script as linkify.user.js:

	// ==UserScript==
	// @name		  Linkify
	// @namespace	  http://youngpup.net/userscripts
	// @description   Turn plain-text URLs into hyperlinks
	// @include *
	// ==/UserScript==

	// based on code by Aaron Boodman
	// and included here with his gracious permission

	var urlRegex = /\b(https?:\/\/[^\s+\"\<\>]+)/ig;
	var snapTextElements = document.evaluate("//text()[not(ancestor::a) " + 
		"and not(ancestor::script) and not(ancestor::style) and " + 
		"contains(translate(., 'HTTP', 'http'), 'http')]", 
		document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	for (var i = snapTextElements.snapshotLength - 1; i >= 0; i--) {
		var elmText = snapTextElements.snapshotItem(i);
		if (urlRegex.test(elmText.nodeValue)) {
			var elmSpan = document.createElement("span");
			var sURLText = elmText.nodeValue;
			elmText.parentNode.replaceChild(elmSpan, elmText);
			urlRegex.lastIndex = 0;
			for (var match = null, lastLastIndex = 0;
				 (match = urlRegex.exec(sURLText)); ) { 
				elmSpan.appendChild(document.createTextNode(
				sURLText.substring(lastLastIndex, match.index))); 
				var elmLink = document.createElement("a"); 
				elmLink.setAttribute("href", match[0]); 
				elmLink.appendChild(document.createTextNode(match[0])); 
				elmSpan.appendChild(elmLink); 
				lastLastIndex = urlRegex.lastIndex;
			}
			elmSpan.appendChild(document.createTextNode(
				sURLText.substring(lastLastIndex)));
			elmSpan.normalize();
		}
	}


O'Reilly Home | Privacy Policy

© 2007 O'Reilly Media, Inc.
Website: | Customer Service: | Book issues:

All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.