Mirror of scripts from the defunct usercripts.org

August 3, 2019 ยท View on GitHub

// ==UserScript== // @name 4chan Linkify // @namespace csimi // @author csimi // @description Linkification of text links. // @homepage http://userscripts.org/users/156405/scripts // @version 2.0.5 // @updateURL http://userscripts.org/scripts/source/87750.meta.js // @icon http://i.imgur.com/JHVzK.png // @include http://boards.4chan.org/* // @include https://boards.4chan.org/* // @include http://boards.4channel.org/* // @include https://boards.4channel.org/* // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // ==/UserScript==

(function () { var self = { ready: function () { var MutationObserver; if (MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver) { observer = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { for (var i = 0; i < mutation.addedNodes.length; i++) { self.check(mutation.addedNodes[i]); } }); }); observer.observe(self.qs('body'), { childList: true, subtree: true }); } else { document.addEventListener('DOMNodeInserted', function (event) { self.check(event.target); }, false); }

		var func = function () {
			self.incrementalize(self.qsa('.board > .thread > .postContainer'));
		};
		if (document.readyState == 'loading') {
			document.addEventListener('DOMContentLoaded', func, false);
		}
		else func();
		
		if (typeof GM_registerMenuCommand == 'function' && typeof GM_getValue == 'function' && typeof GM_setValue == 'function' && typeof GM_deleteValue == 'function') {
			var menucommand = function () {
				if (!GM_getValue('blank')) {
					GM_setValue('blank', true);
					alert('Links now open in a blank window.');
				}
				else {
					GM_deleteValue('blank');
					alert('Links don\'t open in a blank window anymore.');
				}
			};
			GM_registerMenuCommand('4chan Linkify toggle blank window', menucommand, '');
		}
	},
	qs: function (a, b) {
		return (b || document).querySelector(a);
	},
	qsa: function (a, b) {
		return (b || document).querySelectorAll(a);
	},
	check: function (node) {
		if (node.nodeType && node.nodeType == 1 && node.classList.contains('postContainer')) {
			var bq = self.qs('blockquote', node);
			if (!bq || !bq.parentNode || !bq.childNodes || !bq.childNodes.length) return;
			for (var i = 0; i < bq.childNodes.length; i++) {
				self.process(bq.childNodes[i]);
			}
		}
		if (node.nodeType && node.nodeType == 1 && node.nodeName.toLowerCase() == 'blockquote') {
			for (var i = 0; i < node.childNodes.length; i++) {
				self.process(node.childNodes[i]);
			}
		}
	},
	create: function (s) {
		node = document.createElement('a');
		node.className = 'chanlinkify';
		node.href = s;
		node.appendChild(document.createTextNode(s));
		if (typeof GM_getValue == 'function' && GM_getValue('blank')) node.target = '_blank';
		return node;
	},
	next: function (node) {
		if (!node.nextSibling) return;
		if (node.nextSibling.nodeName.toLowerCase() == 'wbr') {
			node.appendChild(node.nextSibling);
		}
		var sib = node.nextSibling;
		if (sib && sib.nodeType == 3) {
			var m = sib.nodeValue.match(/^[^\s]+/);
			if (!m) return;
			var s = m[0];
			node.href = node.textContent+s;
			node.appendChild(document.createTextNode(s));
			if (sib.nodeValue.length == s.length) {
				node.parentNode.removeChild(sib);
			}
			else {
				sib.nodeValue = sib.nodeValue.substring(s.length);
			}
			self.next(node);
		}
	},
	process: function (node) {
		if (node.nodeType == 1 && node.childNodes.length && (node.classList.contains('quote') || node.nodeName.toLowerCase() == 's')) return self.process(node.childNodes[0]);
		if (node.nodeType != 3) return;
		var m;
		m = node.nodeValue.match(/[a-zA-Z][a-zA-Z0-9+-.]+:\/\/[^\s]+/);
		if (!m) m = node.nodeValue.match(/mailto:[^\s]+/);
		if (!m) m = node.nodeValue.match(/magnet:[^\s]+/);
		if (!m) m = node.nodeValue.match(/news:[^\s]+/);
		if (m && node.parentNode.nodeName.toLowerCase() != 'a') {
			var s = m[0];
			var a = self.create(s);
			if (node.nodeValue.length == s.length) {
				node.parentNode.replaceChild(a, node);
			}
			else {
				var pos = node.nodeValue.indexOf(s);
				if (pos != 0) node.parentNode.insertBefore(document.createTextNode(node.nodeValue.substring(0, pos)), node);
				node.parentNode.insertBefore(a, node);
				node.nodeValue = node.nodeValue.substring(pos+s.length);
				if (!node.nodeValue) node.parentNode.removeChild(node);
			}
			self.next(a);
		}
	},
	incrementalize: function (nodes) {
		var i = 0;
		var func = function () {
			for(var j = 0; i < nodes.length; i++, j++) {
				self.check(nodes[i]);
				if (j == 10) break;
			}
			if (i < nodes.length) window.setTimeout(func, 10);
		};
		func();
	},
};
self.ready();

})();