Skip to content

Instantly share code, notes, and snippets.

@TannerRogalsky
Created July 12, 2011 03:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TannerRogalsky/1077329 to your computer and use it in GitHub Desktop.
Save TannerRogalsky/1077329 to your computer and use it in GitHub Desktop.
A module for Reddit Enhancement Suite (RES) which finds any subreddit mentions that are not links and converts them into links.
modules['subredditLinker'] = {
moduleID: 'subredditLinker',
moduleName: 'Subreddit Linker',
options: { },
description: 'Finds any subreddit mentions that are not links and converts them into links.',
isEnabled: function() {
return RESConsole.getModulePrefs(this.moduleID);
},
include: Array(
/https?:\/\/([a-z]+).reddit.com\/user\/[-\w\.]+/i,
/https?:\/\/([a-z]+).reddit.com\/[-\w\.\/]+\/comments\/[-\w\.]+/i,
/https?:\/\/([a-z]+).reddit.com\/message\/[-\w\.\_\?=]*/i
),
exclude: Array(
/https?:\/\/([a-z]+).reddit.com\/ads\/[-\w\.\_\?=]*/i,
/https?:\/\/([a-z]+).reddit.com\/[-\w\.\/]*\/submit\/?$/i
),
isMatchURL: function() {
return RESUtils.isMatchURL(this.moduleID);
},
go: function() {
if ((this.isEnabled()) && (this.isMatchURL())) {
// DOMNodeInserted listener and findAllLinks code are based on / shamelessly copied from Show Images module.
document.body.addEventListener('DOMNodeInserted', function(event) {
if (
((event.target.tagName == 'DIV') && (event.target.getAttribute('id') == 'siteTable')) ||
((event.target.tagName == 'FORM') && (event.target.getAttribute('class') == 'usertext'))
)
{
var isSelfText = false;
if (event.target.tagName == 'FORM') {
isSelfText = true;
}
modules['subredditLinker'].findAllLinks(event.target, isSelfText);
if (!isSelfText) {
modules['subredditLinker'].waitForScan = setInterval(function() {
if (!(modules['subredditLinker'].scanningForLinks)) {
modules['subredditLinker'].subredditLinker(modules['subredditLinker'].gw, true);
clearInterval(modules['subredditLinker'].waitForScan);
}
}, 100);
}
}
}, true);
this.findAllLinks();
}
},
checkElementForLinks: function(index) {
ele = this.allElements[index];
var children = ele.childNodes;
for (var i = 0; i < children.length; i++) {
if (children[i].nodeType == 3) {
// Only search in Text Nodes to avoid modifying items that are already links.
var text = children[i].nodeValue;
var searchStart = 0;
var tag = children[i].parentNode.tagName;
var linkPattern = /(^|\b|\s)(https?:\/\/)*([a-z]*\.)*(reddit\.com\/)*\/?r\/([a-z0-9_]+)/gi;
var matches = text.substring(searchStart).match(linkPattern);
if (matches != null) {
for (var j=0; j < matches.length; j++) {
// Break content into 3 parts based on location of the match.
var match = matches[j];
var matchIndex = text.indexOf(match,searchStart);
var before = text.substring(0,matchIndex);
var after = text.substring(matchIndex + match.length);
//console.log('Match:' + match);
// If http(s) and/or the (sub)domain were included, preserve that info, otherwise build from scratch.
var subUrl;
if ( match.search(/^https?:\/\//i) > -1 ) {
subUrl = match;
} else if ( match.search(/^([a-z]*\.)*reddit.com/i) > -1 ) {
subUrl = "http://" + match;
} else {
var subName = match.substring(match.indexOf("r/"));
subUrl = "http://www.reddit.com/" + subName;
}
// Create link.
var subLink = "<a href=\"" + subUrl + "\">" + match + "</a>";
searchStart = matchIndex + subLink.length;
text = before + subLink + after;
}
var newNode = document.createElement(tag);
newNode.innerHTML = text;
children[i].parentNode.replaceChild(newNode, children[i]);
}
}
}
},
findAllLinks: function(ele, isSelfText) {
this.scanningForLinks = true;
if (ele == null) {
ele = document.body;
}
// get elements common across all pages first...
// if we're on a comments page, get those elements too...
var commentsre = new RegExp(/comments\/[-\w\.\/]/i);
var userre = new RegExp(/user\/[-\w\.\/]/i);
this.scanningSelfText = false;
if ((commentsre.test(location.href)) || (userre.test(location.href))) {
this.allElements = ele.querySelectorAll('.expando .usertext-body > div.md p, .expando .usertext-body > div.md li, .expando .usertext-body > div.md em, .expando .usertext-body > div.md strong, .content .usertext-body > div.md p, .content .usertext-body > div.md li, .content .usertext-body > div.md em, .content .usertext-body > div.md strong');
} else if (isSelfText) {
// We're scanning newly opened (from an expando) selftext...
this.allElements = ele.querySelectorAll('.usertext-body > div.md p, .usertext-body > div.md li, .usertext-body > div.md em, .usertext-body > div.md strong');
this.scanningSelfText = true;
}
if (this.allElements != null) {
// Make sure it doesn't die if there are no elements to work with, which happens in the message window if there are no messages.
this.allElementsCount=this.allElements.length;
this.allElementsi = 0;
if (RESUtils.pageType() == 'comments') {
(function(){
// we're on a comments page which is more intense, so just scan 15 comments at a time...
var chunkLength = Math.min((modules['subredditLinker'].allElementsCount - modules['subredditLinker'].allElementsi), 15);
for (var i=0;i<chunkLength;i++) {
modules['subredditLinker'].checkElementForLinks(modules['subredditLinker'].allElementsi);
modules['subredditLinker'].allElementsi++;
}
if (modules['subredditLinker'].allElementsi < modules['subredditLinker'].allElementsCount) {
setTimeout(arguments.callee, 1000);
} else {
modules['subredditLinker'].scanningSelfText = false;
modules['subredditLinker'].scanningForLinks = false;
}
})();
} else {
var chunkLength = modules['subredditLinker'].allElementsCount;
for (var i=0;i<chunkLength;i++) {
modules['subredditLinker'].checkElementForLinks(modules['subredditLinker'].allElementsi);
modules['subredditLinker'].allElementsi++;
}
modules['subredditLinker'].scanningSelfText = false;
modules['subredditLinker'].scanningForLinks = false;
}
}
}
}
@TannerRogalsky
Copy link
Author

Forked to remove trailing semicolon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment