// ==UserScript==
// @name 4chan Linkify
// @namespace csimi
// @author csimi
// @description Linkification of text links.
// @homepage http://userscripts.org/users/156405/scripts
// @version 1.4.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/*
// ==/UserScript==
(function () {
///////////////////////////////////
var config = {
'multiLineLinks': true,
'targetBlank': false
}
///////////////////////////////////
function $ (a, b) { if (a && document.querySelector) return (b || document).querySelector(a); }
function $$ (a, b) { if (a && document.querySelectorAll) return (b || document).querySelectorAll(a); }
function foreach (a, f) { if (typeof(a) == 'object' && a.length && typeof(f) == 'function') { for (var i = 0; i < a.length; i++) { a[i] = f(a[i], i) || a[i]; } } }
function ce (a, b) { if (typeof(a) != 'string') return; var c = document.createElement(a); foreach(b, function (d) { if (d.nodeType == 1) { c.appendChild(d); } else if (typeof(d) == 'object' && !d.length) { for (var k in d) { c.setAttribute(k, d[k]); } } else if (typeof(d) == 'string') { c.appendChild(document.createTextNode(d)); } }); return c; }
function checkLinks (a) {
if (!a) return;
if (a.nodeType == 3) {
var b = a.nodeValue.match(/[a-zA-Z][a-zA-Z0-9+-.]+:\/\/[^\s]+/);
if (!b) var b = a.nodeValue.match(/mailto:[^\s]+/);
if (!b) var b = a.nodeValue.match(/magnet:[^\s]+/);
if (!b) var b = a.nodeValue.match(/news:[^\s]+/);
if (b && (a.parentNode.nodeName.toLowerCase() != 'a')) {
var m = b[0];
if (a.nodeValue.length == m.length) {
var el = ce('a', [
{'href': a.nodeValue,
'class': 'chanlinkify'},
a.nodeValue
]);
if (config.targetBlank) el.setAttribute('target', 'blank');
a.parentNode.replaceChild(el, a);
}
else {
var c = a.nodeValue.indexOf(m);
if (a.nodeValue.substring(c-1, c) == '(') {
if (/(.*)\x29$/.test(m)) {
m = m.match(/(.*)\x29$/)[1];
c = a.nodeValue.indexOf(m);
}
}
if (a.nodeValue.substring(c-2, c) == '("') {
if (/(.*)\x22\x29$/.test(m)) {
m = m.match(/(.*)\x22\x29$/)[1];
c = a.nodeValue.indexOf(m);
}
}
if (a.nodeValue.substring(c-2, c) == '(\'') {
if (/(.*)\x27\x29$/.test(m)) {
m = m.match(/(.*)\x27\x29$/)[1];
c = a.nodeValue.indexOf(m);
}
}
var d = c+m.length;
if (c != 0) a.parentNode.insertBefore(document.createTextNode(a.nodeValue.substring(0, c)), a);
var el = ce('a', [
{'href': m,
'class': 'chanlinkify'},
m
]);
if (config.targetBlank) el.setAttribute('target', 'blank');
a.parentNode.insertBefore(el, a);
if (d == a.nodeValue.length) a.parentNode.removeChild(a);
else {
a.nodeValue = a.nodeValue.substring(d);
checkLinks(a);
}
}
}
}else if (a.className == 'quote') {
checkLinks(a.childNodes[0])
}else if (a.className == 'spoiler'){
if(a.childNodes.length != 0) {
checkLinks(a.childNodes[0]);
}else {
removeSpoiler(a)
}
}
}
foreach($$('blockquote'), function (a) {
foreach(a.childNodes, function (b) {
checkLinks(b);
});
});
foreach($$('span.subject'), function (b) {
checkLinks(b.childNodes[0]);
});
document.addEventListener('DOMNodeInserted', function (e) {
var t = e.target;
if (t.nodeType === 1 && t.nodeName.toLowerCase() === 'div') {
if (t.className.split(' ').filter(function (cls) { return cls === 'postContainer'; }).length) {
foreach($('blockquote', t).childNodes, function (a) {
checkLinks(a);
});
}
}
if (t.nodeType === 3 && t.parentNode.nodeName.toLowerCase() === 'blockquote') {
checkLinks(t);
}
if (t.nodeName.toLowerCase() == 'blockquote') {
foreach(t.childNodes, function (a) {
checkLinks(a);
});
}
}, false);
function appendNextTextNode (a) {
var r = (a.parentNode.className == 'quote') ? a.parentNode : a;
if (r.nextSibling && (r.nextSibling.nodeName.toLowerCase() == 'br')) {
if (r.nextSibling.nextSibling && (r.nextSibling.nextSibling.nodeType == 3)) {
var b = r.nextSibling.nextSibling;
var c = b.nodeValue.match(/^[^\s]+/);
if (!c) return;
a.href += c[0];
a.childNodes[0].nodeValue += c[0];
if (b.nodeValue.length == c[0].length) {
r.parentNode.removeChild(r.nextSibling);
r.parentNode.removeChild(b);
}
else {
r.parentNode.removeChild(r.nextSibling);
b.nodeValue = b.nodeValue.substring(c[0].length);
}
}
}
}
function removeSpoiler(a) {
b = a.previousSibling
c = a.nextSibling
if(c.nodeType == 3) {
a.parentNode.removeChild(a)
var d = c.nodeValue.match(/^[^\s]+/);
if (!d) return;
b.href = b.childNodes[0].nodeValue + d[0];
b.childNodes[0].nodeValue = b.href;
if (c.nodeValue.length == d[0].length) {
c.parentNode.removeChild(c);
}
else {
c.nodeValue = c.nodeValue.substring(d[0].length);
}
}
}
if (config.multiLineLinks) document.addEventListener('click', function (e) {
var t = e.target;
if ((t.className == 'chanlinkify') && e.shiftKey && e.ctrlKey) {
e.preventDefault();
e.stopPropagation();
appendNextTextNode(t);
}
}, false);
})();