Merge branch 'v3'

Conflicts:
	builds/crx/script.js
	src/General/Settings.coffee
This commit is contained in:
Zixaphir 2013-08-05 14:38:52 -07:00
commit ae9b197d3f
9 changed files with 717 additions and 490 deletions

View File

@ -61,6 +61,7 @@ module.exports = (grunt) ->
files: files:
'builds/<%= pkg.name %>.meta.js': 'src/General/meta/metadata.js' 'builds/<%= pkg.name %>.meta.js': 'src/General/meta/metadata.js'
'builds/<%= pkg.name %>.user.js': [ 'builds/<%= pkg.name %>.user.js': [
'src/General/meta/botproc.js'
'src/General/meta/metadata.js' 'src/General/meta/metadata.js'
'src/General/meta/banner.js' 'src/General/meta/banner.js'
'src/General/meta/usestrict.js' 'src/General/meta/usestrict.js'

View File

@ -1,3 +1,4 @@
// Generated by CoffeeScript
// ==UserScript== // ==UserScript==
// @name 4chan X // @name 4chan X
// @version 1.2.25 // @version 1.2.25
@ -430,15 +431,14 @@
fd = new FormData(); fd = new FormData();
for (key in form) { for (key in form) {
val = form[key]; val = form[key];
if (!val) { if (val) {
continue;
}
if (val.size && val.name) { if (val.size && val.name) {
fd.append(key, val, val.name); fd.append(key, val, val.name);
} else { } else {
fd.append(key, val); fd.append(key, val);
} }
} }
}
return fd; return fd;
}; };
@ -1080,7 +1080,7 @@
_ref1 = Get.allQuotelinksLinkingTo(this); _ref1 = Get.allQuotelinksLinkingTo(this);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
quotelink = _ref1[_j]; quotelink = _ref1[_j];
if ($.hasClass(quotelink, 'deadlink')) { if (!(!$.hasClass(quotelink, 'deadlink'))) {
continue; continue;
} }
$.add(quotelink, $.tn('\u00A0(Dead)')); $.add(quotelink, $.tn('\u00A0(Dead)'));
@ -1844,6 +1844,7 @@
date: data.now, date: data.now,
dateUTC: data.time, dateUTC: data.time,
comment: data.com, comment: data.com,
capReps: data.capcode_replies,
isSticky: !!data.sticky, isSticky: !!data.sticky,
isClosed: !!data.closed isClosed: !!data.closed
}; };
@ -1871,9 +1872,9 @@
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE @license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
*/ */
var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref; var a, array, boardID, capReps, capcode, capcodeClass, capcodeReplies, capcodeStart, capcodeType, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, generateCapcodeReplies, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, file = o.file; postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, capReps = o.capReps, file = o.file;
isOP = postID === threadID; isOP = postID === threadID;
staticPath = '//static.4chan.org/image/'; staticPath = '//static.4chan.org/image/';
if (email) { if (email) {
@ -1947,10 +1948,32 @@
tripcode = tripcode ? " <span class=postertrip>" + tripcode + "</span>" : ''; tripcode = tripcode ? " <span class=postertrip>" + tripcode + "</span>" : '';
sticky = isSticky ? " <img src=" + staticPath + "sticky.gif alt=Sticky title=Sticky class=stickyIcon>" : ''; sticky = isSticky ? " <img src=" + staticPath + "sticky.gif alt=Sticky title=Sticky class=stickyIcon>" : '';
closed = isClosed ? " <img src=" + staticPath + "closed.gif alt=Closed title=Closed class=closedIcon>" : ''; closed = isClosed ? " <img src=" + staticPath + "closed.gif alt=Closed title=Closed class=closedIcon>" : '';
capcodeReplies = '';
if (capReps) {
generateCapcodeReplies = function(capcodeType, array) {
return "<span class=smaller><span class=bold>" + ((function() {
switch (capcodeType) {
case 'admin':
return 'Administrator';
case 'mod':
return 'Moderator';
case 'developer':
return 'Developer';
}
})()) + " Repl" + (array.length > 1 ? 'ies' : 'y') + ":</span> " + (array.map(function(ID) {
return "<a href='/" + boardID + "/res/" + threadID + "#p" + ID + "' class=quotelink>&gt;&gt;" + ID + "</a>";
}).join(' ')) + "</span><br>";
};
for (capcodeType in capReps) {
array = capReps[capcodeType];
capcodeReplies += generateCapcodeReplies(capcodeType, array);
}
capcodeReplies = "<br><br><span class=capcodeReplies>" + capcodeReplies + "</span>";
}
container = $.el('div', { container = $.el('div', {
id: "pc" + postID, id: "pc" + postID,
className: "postContainer " + (isOP ? 'op' : 'reply') + "Container", className: "postContainer " + (isOP ? 'op' : 'reply') + "Container",
innerHTML: (isOP ? '' : "<div class=sideArrows id=sa" + postID + ">&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + ("<div class='postInfoM mobile' id=pim" + postID + ">") + ("<span class='nameBlock" + capcodeClass + "'>") + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + capcode + userID + flag + sticky + closed + ("<br>" + subject) + ("</span><span class='dateTime postNum' data-utc=" + dateUTC + ">" + date) + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + ">No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? fileHTML : '') + ("<div class='postInfo desktop' id=pi" + postID + ">") + ("<input type=checkbox name=" + postID + " value=delete> ") + ("" + subject + " ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcode + userID + flag + sticky + closed + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum desktop'>" + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage id=m" + postID + ">" + (comment || '') + "</blockquote> ") + '</div>' innerHTML: (isOP ? '' : "<div class=sideArrows id=sa" + postID + ">&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + ("<div class='postInfoM mobile' id=pim" + postID + ">") + ("<span class='nameBlock" + capcodeClass + "'>") + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + capcode + userID + flag + sticky + closed + ("<br>" + subject) + ("</span><span class='dateTime postNum' data-utc=" + dateUTC + ">" + date) + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + ">No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? fileHTML : '') + ("<div class='postInfo desktop' id=pi" + postID + ">") + ("<input type=checkbox name=" + postID + " value=delete> ") + ("" + subject + " ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcode + userID + flag + sticky + closed + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum desktop'>" + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage id=m" + postID + ">" + (comment || '') + capcodeReplies + "</blockquote> ") + '</div>'
}); });
_ref = $$('.quotelink', container); _ref = $$('.quotelink', container);
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@ -4328,6 +4351,9 @@
len = snapshot.snapshotLength; len = snapshot.snapshotLength;
while (++i < len) { while (++i < len) {
node = snapshot.snapshotItem(i); node = snapshot.snapshotItem(i);
if (node.parentElement.nodeName === "A") {
continue;
}
data = node.data; data = node.data;
if (Linkify.regString.test(data)) { if (Linkify.regString.test(data)) {
Linkify.regString.lastIndex = 0; Linkify.regString.lastIndex = 0;
@ -4360,7 +4386,7 @@
index = match.index; index = match.index;
link = match[0]; link = match[0];
len2 = index + link.length; len2 = index + link.length;
if (len - len2 === 0) { if (len === len2) {
break; break;
} }
range = document.createRange(); range = document.createRange();
@ -4393,10 +4419,7 @@
} }
} }
if (range.collapsed) { if (range.collapsed) {
if (node.nodeName === 'WBR') { range.setEndAfter(node);
node = node.previousSibling;
}
range.setEnd(node, node.length);
} }
return Linkify.makeLink(range, post); return Linkify.makeLink(range, post);
}, },
@ -4428,21 +4451,28 @@
} }
}, },
embed: function(data) { embed: function(data) {
var embed, key, link, options, uid; var embed, href, key, link, name, options, uid, value, _ref;
key = data[0], uid = data[1], options = data[2], link = data[3]; key = data[0], uid = data[1], options = data[2], link = data[3];
href = link.href;
embed = $.el('a', { embed = $.el('a', {
name: uid,
option: options,
className: 'embedder', className: 'embedder',
href: 'javascript:;', href: 'javascript:;',
textContent: '(embed)' textContent: '(embed)'
}); });
embed.dataset.service = key; _ref = {
embed.dataset.originalurl = link.href; key: key,
$.addClass(link, "" + embed.dataset.service); href: href,
uid: uid,
options: options
};
for (name in _ref) {
value = _ref[name];
embed.dataset[name] = value;
}
$.addClass(link, "" + embed.dataset.key);
$.on(embed, 'click', Linkify.cb.toggle); $.on(embed, 'click', Linkify.cb.toggle);
return $.after(link, [$.tn(' '), embed]); $.after(link, [$.tn(' '), embed]);
}, },
title: function(data) { title: function(data) {
var err, key, link, options, service, title, titles, uid; var err, key, link, options, service, title, titles, uid;
@ -4488,23 +4518,24 @@
embed: function(a) { embed: function(a) {
var el, style, type; var el, style, type;
el = (type = Linkify.types[a.dataset.service]).el.call(a); el = (type = Linkify.types[a.dataset.key]).el.call(a);
el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px"; el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px";
a.textContent = '(unembed)'; a.textContent = '(unembed)';
return el; return el;
}, },
unembed: function(a) { unembed: function(a) {
var el, url; var el, href;
href = a.dataset.href;
el = $.el('a', { el = $.el('a', {
rel: 'nofollow noreferrer', rel: 'nofollow noreferrer',
target: 'blank', target: 'blank',
className: 'linkify', className: 'linkify',
href: url = a.dataset.originalurl, href: href,
textContent: a.dataset.title || url textContent: a.dataset.title || href
}); });
a.textContent = '(embed)'; a.textContent = '(embed)';
$.addClass(el, "" + a.dataset.service); $.addClass(el, "" + a.dataset.key);
return el; return el;
}, },
title: function(data) { title: function(data) {
@ -4532,108 +4563,13 @@
} }
}, },
types: { types: {
YouTube: {
regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/,
el: function() {
return $.el('iframe', {
src: "//www.youtube.com/embed/" + this.name + (this.option ? '#' + this.option : '') + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://gdata.youtube.com/feeds/api/videos/" + uid + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode";
},
text: function() {
return JSON.parse(this.responseText).entry.title.$t;
}
}
},
Vocaroo: {
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/,
style: 'border: 0; width: 150px; height: 45px;',
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://vocaroo.com/player.swf?playMediaID=" + (this.name.replace(/^i\//, '')) + "&autoplay=0' wmode='opaque' width='150' height='45' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
Vimeo: {
regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/,
el: function() {
return $.el('iframe', {
src: "//player.vimeo.com/video/" + this.name + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
LiveLeak: {
regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/,
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://www.liveleak.com/e/" + this.name + "?autostart=true' wmode='opaque' width='640' height='390' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
audio: { audio: {
regExp: /(.*\.(mp3|ogg|wav))$/, regExp: /(.*\.(mp3|ogg|wav))$/,
el: function() { el: function() {
return $.el('audio', { return $.el('audio', {
controls: 'controls', controls: 'controls',
preload: 'auto', preload: 'auto',
src: this.name src: this.dataset.uid
});
}
},
image: {
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/,
style: 'border: 0; width: auto; height: auto;',
el: function() {
return $.el('div', {
innerHTML: "<a target=_blank href='" + this.dataset.originalurl + "'><img src='" + this.dataset.originalurl + "'></a>"
});
}
},
SoundCloud: {
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/,
style: 'height: auto; width: 500px; display: inline-block;',
el: function() {
var div;
div = $.el('div', {
className: "soundcloud",
name: "soundcloud"
});
$.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + this.name, {
div: div,
onloadend: function() {
return this.div.innerHTML = JSON.parse(this.responseText).html;
}
}, false);
return div;
},
title: {
api: function(uid) {
return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
pastebin: {
regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/,
el: function() {
var div;
return div = $.el('iframe', {
src: "http://pastebin.com/embed_iframe.php?i=" + this.name
}); });
} }
}, },
@ -4643,7 +4579,7 @@
var div; var div;
return div = $.el('iframe', { return div = $.el('iframe', {
src: "http://www.purplegene.com/script?url=https://gist.github.com/" + this.name + ".js" src: "http://www.purplegene.com/script?url=https://gist.github.com/" + this.dataset.uid + ".js"
}); });
}, },
title: { title: {
@ -4662,13 +4598,138 @@
} }
} }
}, },
image: {
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/,
style: 'border: 0; width: auto; height: auto;',
el: function() {
return $.el('div', {
innerHTML: "<a target=_blank href='" + this.dataset.href + "'><img src='" + this.dataset.href + "'></a>"
});
}
},
InstallGentoo: { InstallGentoo: {
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/, regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/,
el: function() { el: function() {
return $.el('iframe', { return $.el('iframe', {
src: "http://paste.installgentoo.com/view/embed/" + this.name src: "http://paste.installgentoo.com/view/embed/" + this.dataset.uid
}); });
} }
},
LiveLeak: {
regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/,
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://www.liveleak.com/e/" + this.dataset.uid + "?autostart=true' wmode='opaque' width='640' height='390' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
pastebin: {
regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/,
el: function() {
var div;
return div = $.el('iframe', {
src: "http://pastebin.com/embed_iframe.php?i=" + this.dataset.uid
});
}
},
SoundCloud: {
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/,
style: 'height: auto; width: 500px; display: inline-block;',
el: function() {
var div;
div = $.el('div', {
className: "soundcloud",
name: "soundcloud"
});
$.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + this.dataset.uid, {
div: div,
onloadend: function() {
return this.div.innerHTML = JSON.parse(this.responseText).html;
}
}, false);
return div;
},
title: {
api: function(uid) {
return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
TwitchTV: {
regExp: /.*(?:twitch.tv\/)([^#\&\?]*).*/,
style: "border: none; width: 640px; height: 360px;",
el: function() {
var channel, chapter, result, _;
if (result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec(this.dataset.uid)) {
_ = result[0], channel = result[1], chapter = result[2];
return $.el('object', {
data: 'http://www.twitch.tv/widgets/archive_embed_player.swf',
innerHTML: "<param name='allowFullScreen' value='true' />\n<param name='flashvars' value='channel=" + channel + "&start_volume=25&auto_play=false" + (chapter ? "&chapter_id=" + chapter : "") + "' />"
});
} else {
channel = (/(\w+)/.exec(this.dataset.uid))[0];
return $.el('object', {
data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=" + channel,
innerHTML: "<param name=\"allowFullScreen\" value=\"true\" />\n<param name=\"movie\" value=\"http://www.twitch.tv/widgets/live_embed_player.swf\" />\n<param name=\"flashvars\" value=\"hostname=www.twitch.tv&channel=" + channel + "&auto_play=true&start_volume=25\" />"
});
}
}
},
Vocaroo: {
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/,
style: 'border: 0; width: 150px; height: 45px;',
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://vocaroo.com/player.swf?playMediaID=" + (this.dataset.uid.replace(/^i\//, '')) + "&autoplay=0' wmode='opaque' width='150' height='45' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
Vimeo: {
regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/,
el: function() {
return $.el('iframe', {
src: "//player.vimeo.com/video/" + this.dataset.uid + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
Vine: {
regExp: /.*(?:vine.co\/)([^#\&\?]*).*/,
style: 'border: none; width: 500px; height: 500px;',
el: function() {
return $.el('iframe', {
src: "https://vine.co/" + this.dataset.uid + "/card"
});
}
},
YouTube: {
regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/,
el: function() {
return $.el('iframe', {
src: "//www.youtube.com/embed/" + this.dataset.uid + (this.dataset.option ? '#' + this.dataset.option : '') + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://gdata.youtube.com/feeds/api/videos/" + uid + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode";
},
text: function() {
return JSON.parse(this.responseText).entry.title.$t;
}
}
} }
} }
}; };
@ -4958,13 +5019,12 @@
list = $("#list-" + type, QR.nodes.el); list = $("#list-" + type, QR.nodes.el);
for (_i = 0, _len = arr.length; _i < _len; _i++) { for (_i = 0, _len = arr.length; _i < _len; _i++) {
val = arr[_i]; val = arr[_i];
if (!val) { if (val) {
continue;
}
$.add(list, $.el('option', { $.add(list, $.el('option', {
textContent: val textContent: val
})); }));
} }
}
}, },
getPassword: function() { getPassword: function() {
var input, m; var input, m;
@ -9870,15 +9930,14 @@
_ref = Config.hotkeys; _ref = Config.hotkeys;
for (key in _ref) { for (key in _ref) {
val = _ref[key]; val = _ref[key];
if (!(key in data.Conf)) { if (key in data.Conf) {
continue;
}
data.Conf[key] = data.Conf[key].replace(/ctrl|alt|meta/g, function(s) { data.Conf[key] = data.Conf[key].replace(/ctrl|alt|meta/g, function(s) {
return "" + (s[0].toUpperCase()) + s.slice(1); return "" + (s[0].toUpperCase()) + s.slice(1);
}).replace(/(^|.+\+)[A-Z]$/g, function(s) { }).replace(/(^|.+\+)[A-Z]$/g, function(s) {
return "Shift+" + s.slice(0, -1) + (s.slice(-1).toLowerCase()); return "Shift+" + s.slice(0, -1) + (s.slice(-1).toLowerCase());
}); });
} }
}
data.Conf.WatchedThreads = data.WatchedThreads; data.Conf.WatchedThreads = data.WatchedThreads;
} else if (version[0] === '3') { } else if (version[0] === '3') {
data = Settings.convertSettings(data, { data = Settings.convertSettings(data, {

View File

@ -1,3 +1,4 @@
// Generated by CoffeeScript
// ==UserScript== // ==UserScript==
// @name appchan x // @name appchan x
// @version 2.2.2 // @version 2.2.2
@ -2787,15 +2788,14 @@
fd = new FormData(); fd = new FormData();
for (key in form) { for (key in form) {
val = form[key]; val = form[key];
if (!val) { if (val) {
continue;
}
if (val.size && val.name) { if (val.size && val.name) {
fd.append(key, val, val.name); fd.append(key, val, val.name);
} else { } else {
fd.append(key, val); fd.append(key, val);
} }
} }
}
return fd; return fd;
}; };
@ -3437,7 +3437,7 @@
_ref1 = Get.allQuotelinksLinkingTo(this); _ref1 = Get.allQuotelinksLinkingTo(this);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
quotelink = _ref1[_j]; quotelink = _ref1[_j];
if ($.hasClass(quotelink, 'deadlink')) { if (!(!$.hasClass(quotelink, 'deadlink'))) {
continue; continue;
} }
$.add(quotelink, $.tn('\u00A0(Dead)')); $.add(quotelink, $.tn('\u00A0(Dead)'));
@ -4140,6 +4140,7 @@
date: data.now, date: data.now,
dateUTC: data.time, dateUTC: data.time,
comment: data.com, comment: data.com,
capReps: data.capcode_replies,
isSticky: !!data.sticky, isSticky: !!data.sticky,
isClosed: !!data.closed isClosed: !!data.closed
}; };
@ -4167,9 +4168,9 @@
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE @license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
*/ */
var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref; var a, array, boardID, capReps, capcode, capcodeClass, capcodeReplies, capcodeStart, capcodeType, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, generateCapcodeReplies, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, file = o.file; postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, capReps = o.capReps, file = o.file;
isOP = postID === threadID; isOP = postID === threadID;
staticPath = '//static.4chan.org/image/'; staticPath = '//static.4chan.org/image/';
if (email) { if (email) {
@ -4243,10 +4244,32 @@
tripcode = tripcode ? " <span class=postertrip>" + tripcode + "</span>" : ''; tripcode = tripcode ? " <span class=postertrip>" + tripcode + "</span>" : '';
sticky = isSticky ? " <img src=" + staticPath + "sticky.gif alt=Sticky title=Sticky class=stickyIcon>" : ''; sticky = isSticky ? " <img src=" + staticPath + "sticky.gif alt=Sticky title=Sticky class=stickyIcon>" : '';
closed = isClosed ? " <img src=" + staticPath + "closed.gif alt=Closed title=Closed class=closedIcon>" : ''; closed = isClosed ? " <img src=" + staticPath + "closed.gif alt=Closed title=Closed class=closedIcon>" : '';
capcodeReplies = '';
if (capReps) {
generateCapcodeReplies = function(capcodeType, array) {
return "<span class=smaller><span class=bold>" + ((function() {
switch (capcodeType) {
case 'admin':
return 'Administrator';
case 'mod':
return 'Moderator';
case 'developer':
return 'Developer';
}
})()) + " Repl" + (array.length > 1 ? 'ies' : 'y') + ":</span> " + (array.map(function(ID) {
return "<a href='/" + boardID + "/res/" + threadID + "#p" + ID + "' class=quotelink>&gt;&gt;" + ID + "</a>";
}).join(' ')) + "</span><br>";
};
for (capcodeType in capReps) {
array = capReps[capcodeType];
capcodeReplies += generateCapcodeReplies(capcodeType, array);
}
capcodeReplies = "<br><br><span class=capcodeReplies>" + capcodeReplies + "</span>";
}
container = $.el('div', { container = $.el('div', {
id: "pc" + postID, id: "pc" + postID,
className: "postContainer " + (isOP ? 'op' : 'reply') + "Container", className: "postContainer " + (isOP ? 'op' : 'reply') + "Container",
innerHTML: (isOP ? '' : "<div class=sideArrows id=sa" + postID + ">&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + ("<div class='postInfoM mobile' id=pim" + postID + ">") + ("<span class='nameBlock" + capcodeClass + "'>") + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + capcode + userID + flag + sticky + closed + ("<br>" + subject) + ("</span><span class='dateTime postNum' data-utc=" + dateUTC + ">" + date) + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + ">No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? fileHTML : '') + ("<div class='postInfo desktop' id=pi" + postID + ">") + ("<input type=checkbox name=" + postID + " value=delete> ") + ("" + subject + " ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcode + userID + flag + sticky + closed + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum desktop'>" + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage id=m" + postID + ">" + (comment || '') + "</blockquote> ") + '</div>' innerHTML: (isOP ? '' : "<div class=sideArrows id=sa" + postID + ">&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + ("<div class='postInfoM mobile' id=pim" + postID + ">") + ("<span class='nameBlock" + capcodeClass + "'>") + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + capcode + userID + flag + sticky + closed + ("<br>" + subject) + ("</span><span class='dateTime postNum' data-utc=" + dateUTC + ">" + date) + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + ">No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? fileHTML : '') + ("<div class='postInfo desktop' id=pi" + postID + ">") + ("<input type=checkbox name=" + postID + " value=delete> ") + ("" + subject + " ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcode + userID + flag + sticky + closed + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum desktop'>" + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage id=m" + postID + ">" + (comment || '') + capcodeReplies + "</blockquote> ") + '</div>'
}); });
_ref = $$('.quotelink', container); _ref = $$('.quotelink', container);
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@ -6620,6 +6643,9 @@
len = snapshot.snapshotLength; len = snapshot.snapshotLength;
while (++i < len) { while (++i < len) {
node = snapshot.snapshotItem(i); node = snapshot.snapshotItem(i);
if (node.parentElement.nodeName === "A") {
continue;
}
data = node.data; data = node.data;
if (Linkify.regString.test(data)) { if (Linkify.regString.test(data)) {
Linkify.regString.lastIndex = 0; Linkify.regString.lastIndex = 0;
@ -6652,7 +6678,7 @@
index = match.index; index = match.index;
link = match[0]; link = match[0];
len2 = index + link.length; len2 = index + link.length;
if (len - len2 === 0) { if (len === len2) {
break; break;
} }
range = document.createRange(); range = document.createRange();
@ -6685,10 +6711,7 @@
} }
} }
if (range.collapsed) { if (range.collapsed) {
if (node.nodeName === 'WBR') { range.setEndAfter(node);
node = node.previousSibling;
}
range.setEnd(node, node.length);
} }
return Linkify.makeLink(range, post); return Linkify.makeLink(range, post);
}, },
@ -6720,21 +6743,28 @@
} }
}, },
embed: function(data) { embed: function(data) {
var embed, key, link, options, uid; var embed, href, key, link, name, options, uid, value, _ref;
key = data[0], uid = data[1], options = data[2], link = data[3]; key = data[0], uid = data[1], options = data[2], link = data[3];
href = link.href;
embed = $.el('a', { embed = $.el('a', {
name: uid,
option: options,
className: 'embedder', className: 'embedder',
href: 'javascript:;', href: 'javascript:;',
textContent: '(embed)' textContent: '(embed)'
}); });
embed.dataset.service = key; _ref = {
embed.dataset.originalurl = link.href; key: key,
$.addClass(link, "" + embed.dataset.service); href: href,
uid: uid,
options: options
};
for (name in _ref) {
value = _ref[name];
embed.dataset[name] = value;
}
$.addClass(link, "" + embed.dataset.key);
$.on(embed, 'click', Linkify.cb.toggle); $.on(embed, 'click', Linkify.cb.toggle);
return $.after(link, [$.tn(' '), embed]); $.after(link, [$.tn(' '), embed]);
}, },
title: function(data) { title: function(data) {
var err, key, link, options, service, title, titles, uid; var err, key, link, options, service, title, titles, uid;
@ -6780,23 +6810,24 @@
embed: function(a) { embed: function(a) {
var el, style, type; var el, style, type;
el = (type = Linkify.types[a.dataset.service]).el.call(a); el = (type = Linkify.types[a.dataset.key]).el.call(a);
el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px"; el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px";
a.textContent = '(unembed)'; a.textContent = '(unembed)';
return el; return el;
}, },
unembed: function(a) { unembed: function(a) {
var el, url; var el, href;
href = a.dataset.href;
el = $.el('a', { el = $.el('a', {
rel: 'nofollow noreferrer', rel: 'nofollow noreferrer',
target: 'blank', target: 'blank',
className: 'linkify', className: 'linkify',
href: url = a.dataset.originalurl, href: href,
textContent: a.dataset.title || url textContent: a.dataset.title || href
}); });
a.textContent = '(embed)'; a.textContent = '(embed)';
$.addClass(el, "" + a.dataset.service); $.addClass(el, "" + a.dataset.key);
return el; return el;
}, },
title: function(data) { title: function(data) {
@ -6824,108 +6855,13 @@
} }
}, },
types: { types: {
YouTube: {
regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/,
el: function() {
return $.el('iframe', {
src: "//www.youtube.com/embed/" + this.name + (this.option ? '#' + this.option : '') + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://gdata.youtube.com/feeds/api/videos/" + uid + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode";
},
text: function() {
return JSON.parse(this.responseText).entry.title.$t;
}
}
},
Vocaroo: {
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/,
style: 'border: 0; width: 150px; height: 45px;',
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://vocaroo.com/player.swf?playMediaID=" + (this.name.replace(/^i\//, '')) + "&autoplay=0' wmode='opaque' width='150' height='45' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
Vimeo: {
regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/,
el: function() {
return $.el('iframe', {
src: "//player.vimeo.com/video/" + this.name + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
LiveLeak: {
regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/,
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://www.liveleak.com/e/" + this.name + "?autostart=true' wmode='opaque' width='640' height='390' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
audio: { audio: {
regExp: /(.*\.(mp3|ogg|wav))$/, regExp: /(.*\.(mp3|ogg|wav))$/,
el: function() { el: function() {
return $.el('audio', { return $.el('audio', {
controls: 'controls', controls: 'controls',
preload: 'auto', preload: 'auto',
src: this.name src: this.dataset.uid
});
}
},
image: {
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/,
style: 'border: 0; width: auto; height: auto;',
el: function() {
return $.el('div', {
innerHTML: "<a target=_blank href='" + this.dataset.originalurl + "'><img src='" + this.dataset.originalurl + "'></a>"
});
}
},
SoundCloud: {
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/,
style: 'height: auto; width: 500px; display: inline-block;',
el: function() {
var div;
div = $.el('div', {
className: "soundcloud",
name: "soundcloud"
});
$.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + this.name, {
div: div,
onloadend: function() {
return this.div.innerHTML = JSON.parse(this.responseText).html;
}
}, false);
return div;
},
title: {
api: function(uid) {
return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
pastebin: {
regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/,
el: function() {
var div;
return div = $.el('iframe', {
src: "http://pastebin.com/embed_iframe.php?i=" + this.name
}); });
} }
}, },
@ -6935,7 +6871,7 @@
var div; var div;
return div = $.el('iframe', { return div = $.el('iframe', {
src: "http://www.purplegene.com/script?url=https://gist.github.com/" + this.name + ".js" src: "http://www.purplegene.com/script?url=https://gist.github.com/" + this.dataset.uid + ".js"
}); });
}, },
title: { title: {
@ -6954,13 +6890,138 @@
} }
} }
}, },
image: {
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/,
style: 'border: 0; width: auto; height: auto;',
el: function() {
return $.el('div', {
innerHTML: "<a target=_blank href='" + this.dataset.href + "'><img src='" + this.dataset.href + "'></a>"
});
}
},
InstallGentoo: { InstallGentoo: {
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/, regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/,
el: function() { el: function() {
return $.el('iframe', { return $.el('iframe', {
src: "http://paste.installgentoo.com/view/embed/" + this.name src: "http://paste.installgentoo.com/view/embed/" + this.dataset.uid
}); });
} }
},
LiveLeak: {
regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/,
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://www.liveleak.com/e/" + this.dataset.uid + "?autostart=true' wmode='opaque' width='640' height='390' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
pastebin: {
regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/,
el: function() {
var div;
return div = $.el('iframe', {
src: "http://pastebin.com/embed_iframe.php?i=" + this.dataset.uid
});
}
},
SoundCloud: {
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/,
style: 'height: auto; width: 500px; display: inline-block;',
el: function() {
var div;
div = $.el('div', {
className: "soundcloud",
name: "soundcloud"
});
$.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + this.dataset.uid, {
div: div,
onloadend: function() {
return this.div.innerHTML = JSON.parse(this.responseText).html;
}
}, false);
return div;
},
title: {
api: function(uid) {
return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
TwitchTV: {
regExp: /.*(?:twitch.tv\/)([^#\&\?]*).*/,
style: "border: none; width: 640px; height: 360px;",
el: function() {
var channel, chapter, result, _;
if (result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec(this.dataset.uid)) {
_ = result[0], channel = result[1], chapter = result[2];
return $.el('object', {
data: 'http://www.twitch.tv/widgets/archive_embed_player.swf',
innerHTML: "<param name='allowFullScreen' value='true' />\n<param name='flashvars' value='channel=" + channel + "&start_volume=25&auto_play=false" + (chapter ? "&chapter_id=" + chapter : "") + "' />"
});
} else {
channel = (/(\w+)/.exec(this.dataset.uid))[0];
return $.el('object', {
data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=" + channel,
innerHTML: "<param name=\"allowFullScreen\" value=\"true\" />\n<param name=\"movie\" value=\"http://www.twitch.tv/widgets/live_embed_player.swf\" />\n<param name=\"flashvars\" value=\"hostname=www.twitch.tv&channel=" + channel + "&auto_play=true&start_volume=25\" />"
});
}
}
},
Vocaroo: {
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/,
style: 'border: 0; width: 150px; height: 45px;',
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://vocaroo.com/player.swf?playMediaID=" + (this.dataset.uid.replace(/^i\//, '')) + "&autoplay=0' wmode='opaque' width='150' height='45' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
Vimeo: {
regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/,
el: function() {
return $.el('iframe', {
src: "//player.vimeo.com/video/" + this.dataset.uid + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
Vine: {
regExp: /.*(?:vine.co\/)([^#\&\?]*).*/,
style: 'border: none; width: 500px; height: 500px;',
el: function() {
return $.el('iframe', {
src: "https://vine.co/" + this.dataset.uid + "/card"
});
}
},
YouTube: {
regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/,
el: function() {
return $.el('iframe', {
src: "//www.youtube.com/embed/" + this.dataset.uid + (this.dataset.option ? '#' + this.dataset.option : '') + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://gdata.youtube.com/feeds/api/videos/" + uid + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode";
},
text: function() {
return JSON.parse(this.responseText).entry.title.$t;
}
}
} }
} }
}; };
@ -7242,13 +7303,12 @@
list = $("#list-" + type, QR.nodes.el); list = $("#list-" + type, QR.nodes.el);
for (_i = 0, _len = arr.length; _i < _len; _i++) { for (_i = 0, _len = arr.length; _i < _len; _i++) {
val = arr[_i]; val = arr[_i];
if (!val) { if (val) {
continue;
}
$.add(list, $.el('option', { $.add(list, $.el('option', {
textContent: val textContent: val
})); }));
} }
}
}, },
getPassword: function() { getPassword: function() {
var input, m; var input, m;

View File

@ -2770,15 +2770,14 @@
fd = new FormData(); fd = new FormData();
for (key in form) { for (key in form) {
val = form[key]; val = form[key];
if (!val) { if (val) {
continue;
}
if (val.size && val.name) { if (val.size && val.name) {
fd.append(key, val, val.name); fd.append(key, val, val.name);
} else { } else {
fd.append(key, val); fd.append(key, val);
} }
} }
}
return fd; return fd;
}; };
@ -3451,7 +3450,7 @@
_ref1 = Get.allQuotelinksLinkingTo(this); _ref1 = Get.allQuotelinksLinkingTo(this);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
quotelink = _ref1[_j]; quotelink = _ref1[_j];
if ($.hasClass(quotelink, 'deadlink')) { if (!(!$.hasClass(quotelink, 'deadlink'))) {
continue; continue;
} }
$.add(quotelink, $.tn('\u00A0(Dead)')); $.add(quotelink, $.tn('\u00A0(Dead)'));
@ -4154,6 +4153,7 @@
date: data.now, date: data.now,
dateUTC: data.time, dateUTC: data.time,
comment: data.com, comment: data.com,
capReps: data.capcode_replies,
isSticky: !!data.sticky, isSticky: !!data.sticky,
isClosed: !!data.closed isClosed: !!data.closed
}; };
@ -4181,9 +4181,9 @@
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE @license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
*/ */
var a, boardID, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref; var a, array, boardID, capReps, capcode, capcodeClass, capcodeReplies, capcodeStart, capcodeType, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, generateCapcodeReplies, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref;
postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, file = o.file; postID = o.postID, threadID = o.threadID, boardID = o.boardID, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, capReps = o.capReps, file = o.file;
isOP = postID === threadID; isOP = postID === threadID;
staticPath = '//static.4chan.org/image/'; staticPath = '//static.4chan.org/image/';
if (email) { if (email) {
@ -4257,10 +4257,32 @@
tripcode = tripcode ? " <span class=postertrip>" + tripcode + "</span>" : ''; tripcode = tripcode ? " <span class=postertrip>" + tripcode + "</span>" : '';
sticky = isSticky ? " <img src=" + staticPath + "sticky.gif alt=Sticky title=Sticky class=stickyIcon>" : ''; sticky = isSticky ? " <img src=" + staticPath + "sticky.gif alt=Sticky title=Sticky class=stickyIcon>" : '';
closed = isClosed ? " <img src=" + staticPath + "closed.gif alt=Closed title=Closed class=closedIcon>" : ''; closed = isClosed ? " <img src=" + staticPath + "closed.gif alt=Closed title=Closed class=closedIcon>" : '';
capcodeReplies = '';
if (capReps) {
generateCapcodeReplies = function(capcodeType, array) {
return "<span class=smaller><span class=bold>" + ((function() {
switch (capcodeType) {
case 'admin':
return 'Administrator';
case 'mod':
return 'Moderator';
case 'developer':
return 'Developer';
}
})()) + " Repl" + (array.length > 1 ? 'ies' : 'y') + ":</span> " + (array.map(function(ID) {
return "<a href='/" + boardID + "/res/" + threadID + "#p" + ID + "' class=quotelink>&gt;&gt;" + ID + "</a>";
}).join(' ')) + "</span><br>";
};
for (capcodeType in capReps) {
array = capReps[capcodeType];
capcodeReplies += generateCapcodeReplies(capcodeType, array);
}
capcodeReplies = "<br><br><span class=capcodeReplies>" + capcodeReplies + "</span>";
}
container = $.el('div', { container = $.el('div', {
id: "pc" + postID, id: "pc" + postID,
className: "postContainer " + (isOP ? 'op' : 'reply') + "Container", className: "postContainer " + (isOP ? 'op' : 'reply') + "Container",
innerHTML: (isOP ? '' : "<div class=sideArrows id=sa" + postID + ">&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + ("<div class='postInfoM mobile' id=pim" + postID + ">") + ("<span class='nameBlock" + capcodeClass + "'>") + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + capcode + userID + flag + sticky + closed + ("<br>" + subject) + ("</span><span class='dateTime postNum' data-utc=" + dateUTC + ">" + date) + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + ">No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? fileHTML : '') + ("<div class='postInfo desktop' id=pi" + postID + ">") + ("<input type=checkbox name=" + postID + " value=delete> ") + ("" + subject + " ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcode + userID + flag + sticky + closed + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum desktop'>" + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage id=m" + postID + ">" + (comment || '') + "</blockquote> ") + '</div>' innerHTML: (isOP ? '' : "<div class=sideArrows id=sa" + postID + ">&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + ("<div class='postInfoM mobile' id=pim" + postID + ">") + ("<span class='nameBlock" + capcodeClass + "'>") + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + capcode + userID + flag + sticky + closed + ("<br>" + subject) + ("</span><span class='dateTime postNum' data-utc=" + dateUTC + ">" + date) + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + ">No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? fileHTML : '') + ("<div class='postInfo desktop' id=pi" + postID + ">") + ("<input type=checkbox name=" + postID + " value=delete> ") + ("" + subject + " ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcode + userID + flag + sticky + closed + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum desktop'>" + ("<a href=" + ("/" + boardID + "/res/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === +threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/res/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage id=m" + postID + ">" + (comment || '') + capcodeReplies + "</blockquote> ") + '</div>'
}); });
_ref = $$('.quotelink', container); _ref = $$('.quotelink', container);
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@ -6627,6 +6649,9 @@
len = snapshot.snapshotLength; len = snapshot.snapshotLength;
while (++i < len) { while (++i < len) {
node = snapshot.snapshotItem(i); node = snapshot.snapshotItem(i);
if (node.parentElement.nodeName === "A") {
continue;
}
data = node.data; data = node.data;
if (Linkify.regString.test(data)) { if (Linkify.regString.test(data)) {
Linkify.regString.lastIndex = 0; Linkify.regString.lastIndex = 0;
@ -6659,7 +6684,7 @@
index = match.index; index = match.index;
link = match[0]; link = match[0];
len2 = index + link.length; len2 = index + link.length;
if (len - len2 === 0) { if (len === len2) {
break; break;
} }
range = document.createRange(); range = document.createRange();
@ -6692,10 +6717,7 @@
} }
} }
if (range.collapsed) { if (range.collapsed) {
if (node.nodeName === 'WBR') { range.setEndAfter(node);
node = node.previousSibling;
}
range.setEnd(node, node.length);
} }
return Linkify.makeLink(range, post); return Linkify.makeLink(range, post);
}, },
@ -6727,21 +6749,28 @@
} }
}, },
embed: function(data) { embed: function(data) {
var embed, key, link, options, uid; var embed, href, key, link, name, options, uid, value, _ref;
key = data[0], uid = data[1], options = data[2], link = data[3]; key = data[0], uid = data[1], options = data[2], link = data[3];
href = link.href;
embed = $.el('a', { embed = $.el('a', {
name: uid,
option: options,
className: 'embedder', className: 'embedder',
href: 'javascript:;', href: 'javascript:;',
textContent: '(embed)' textContent: '(embed)'
}); });
embed.dataset.service = key; _ref = {
embed.dataset.originalurl = link.href; key: key,
$.addClass(link, "" + embed.dataset.service); href: href,
uid: uid,
options: options
};
for (name in _ref) {
value = _ref[name];
embed.dataset[name] = value;
}
$.addClass(link, "" + embed.dataset.key);
$.on(embed, 'click', Linkify.cb.toggle); $.on(embed, 'click', Linkify.cb.toggle);
return $.after(link, [$.tn(' '), embed]); $.after(link, [$.tn(' '), embed]);
}, },
title: function(data) { title: function(data) {
var err, key, link, options, service, title, titles, uid; var err, key, link, options, service, title, titles, uid;
@ -6787,23 +6816,24 @@
embed: function(a) { embed: function(a) {
var el, style, type; var el, style, type;
el = (type = Linkify.types[a.dataset.service]).el.call(a); el = (type = Linkify.types[a.dataset.key]).el.call(a);
el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px"; el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px";
a.textContent = '(unembed)'; a.textContent = '(unembed)';
return el; return el;
}, },
unembed: function(a) { unembed: function(a) {
var el, url; var el, href;
href = a.dataset.href;
el = $.el('a', { el = $.el('a', {
rel: 'nofollow noreferrer', rel: 'nofollow noreferrer',
target: 'blank', target: 'blank',
className: 'linkify', className: 'linkify',
href: url = a.dataset.originalurl, href: href,
textContent: a.dataset.title || url textContent: a.dataset.title || href
}); });
a.textContent = '(embed)'; a.textContent = '(embed)';
$.addClass(el, "" + a.dataset.service); $.addClass(el, "" + a.dataset.key);
return el; return el;
}, },
title: function(data) { title: function(data) {
@ -6831,108 +6861,13 @@
} }
}, },
types: { types: {
YouTube: {
regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/,
el: function() {
return $.el('iframe', {
src: "//www.youtube.com/embed/" + this.name + (this.option ? '#' + this.option : '') + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://gdata.youtube.com/feeds/api/videos/" + uid + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode";
},
text: function() {
return JSON.parse(this.responseText).entry.title.$t;
}
}
},
Vocaroo: {
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/,
style: 'border: 0; width: 150px; height: 45px;',
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://vocaroo.com/player.swf?playMediaID=" + (this.name.replace(/^i\//, '')) + "&autoplay=0' wmode='opaque' width='150' height='45' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
Vimeo: {
regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/,
el: function() {
return $.el('iframe', {
src: "//player.vimeo.com/video/" + this.name + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
LiveLeak: {
regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/,
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://www.liveleak.com/e/" + this.name + "?autostart=true' wmode='opaque' width='640' height='390' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
audio: { audio: {
regExp: /(.*\.(mp3|ogg|wav))$/, regExp: /(.*\.(mp3|ogg|wav))$/,
el: function() { el: function() {
return $.el('audio', { return $.el('audio', {
controls: 'controls', controls: 'controls',
preload: 'auto', preload: 'auto',
src: this.name src: this.dataset.uid
});
}
},
image: {
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/,
style: 'border: 0; width: auto; height: auto;',
el: function() {
return $.el('div', {
innerHTML: "<a target=_blank href='" + this.dataset.originalurl + "'><img src='" + this.dataset.originalurl + "'></a>"
});
}
},
SoundCloud: {
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/,
style: 'height: auto; width: 500px; display: inline-block;',
el: function() {
var div;
div = $.el('div', {
className: "soundcloud",
name: "soundcloud"
});
$.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + this.name, {
div: div,
onloadend: function() {
return this.div.innerHTML = JSON.parse(this.responseText).html;
}
}, false);
return div;
},
title: {
api: function(uid) {
return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
pastebin: {
regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/,
el: function() {
var div;
return div = $.el('iframe', {
src: "http://pastebin.com/embed_iframe.php?i=" + this.name
}); });
} }
}, },
@ -6942,7 +6877,7 @@
var div; var div;
return div = $.el('iframe', { return div = $.el('iframe', {
src: "http://www.purplegene.com/script?url=https://gist.github.com/" + this.name + ".js" src: "http://www.purplegene.com/script?url=https://gist.github.com/" + this.dataset.uid + ".js"
}); });
}, },
title: { title: {
@ -6961,13 +6896,138 @@
} }
} }
}, },
image: {
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/,
style: 'border: 0; width: auto; height: auto;',
el: function() {
return $.el('div', {
innerHTML: "<a target=_blank href='" + this.dataset.href + "'><img src='" + this.dataset.href + "'></a>"
});
}
},
InstallGentoo: { InstallGentoo: {
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/, regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/,
el: function() { el: function() {
return $.el('iframe', { return $.el('iframe', {
src: "http://paste.installgentoo.com/view/embed/" + this.name src: "http://paste.installgentoo.com/view/embed/" + this.dataset.uid
}); });
} }
},
LiveLeak: {
regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/,
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://www.liveleak.com/e/" + this.dataset.uid + "?autostart=true' wmode='opaque' width='640' height='390' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
pastebin: {
regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/,
el: function() {
var div;
return div = $.el('iframe', {
src: "http://pastebin.com/embed_iframe.php?i=" + this.dataset.uid
});
}
},
SoundCloud: {
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/,
style: 'height: auto; width: 500px; display: inline-block;',
el: function() {
var div;
div = $.el('div', {
className: "soundcloud",
name: "soundcloud"
});
$.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + this.dataset.uid, {
div: div,
onloadend: function() {
return this.div.innerHTML = JSON.parse(this.responseText).html;
}
}, false);
return div;
},
title: {
api: function(uid) {
return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
TwitchTV: {
regExp: /.*(?:twitch.tv\/)([^#\&\?]*).*/,
style: "border: none; width: 640px; height: 360px;",
el: function() {
var channel, chapter, result, _;
if (result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec(this.dataset.uid)) {
_ = result[0], channel = result[1], chapter = result[2];
return $.el('object', {
data: 'http://www.twitch.tv/widgets/archive_embed_player.swf',
innerHTML: "<param name='allowFullScreen' value='true' />\n<param name='flashvars' value='channel=" + channel + "&start_volume=25&auto_play=false" + (chapter ? "&chapter_id=" + chapter : "") + "' />"
});
} else {
channel = (/(\w+)/.exec(this.dataset.uid))[0];
return $.el('object', {
data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=" + channel,
innerHTML: "<param name=\"allowFullScreen\" value=\"true\" />\n<param name=\"movie\" value=\"http://www.twitch.tv/widgets/live_embed_player.swf\" />\n<param name=\"flashvars\" value=\"hostname=www.twitch.tv&channel=" + channel + "&auto_play=true&start_volume=25\" />"
});
}
}
},
Vocaroo: {
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/,
style: 'border: 0; width: 150px; height: 45px;',
el: function() {
return $.el('object', {
innerHTML: "<embed src='http://vocaroo.com/player.swf?playMediaID=" + (this.dataset.uid.replace(/^i\//, '')) + "&autoplay=0' wmode='opaque' width='150' height='45' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
});
}
},
Vimeo: {
regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/,
el: function() {
return $.el('iframe', {
src: "//player.vimeo.com/video/" + this.dataset.uid + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid;
},
text: function() {
return JSON.parse(this.responseText).title;
}
}
},
Vine: {
regExp: /.*(?:vine.co\/)([^#\&\?]*).*/,
style: 'border: none; width: 500px; height: 500px;',
el: function() {
return $.el('iframe', {
src: "https://vine.co/" + this.dataset.uid + "/card"
});
}
},
YouTube: {
regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/,
el: function() {
return $.el('iframe', {
src: "//www.youtube.com/embed/" + this.dataset.uid + (this.dataset.option ? '#' + this.dataset.option : '') + "?wmode=opaque"
});
},
title: {
api: function(uid) {
return "https://gdata.youtube.com/feeds/api/videos/" + uid + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode";
},
text: function() {
return JSON.parse(this.responseText).entry.title.$t;
}
}
} }
} }
}; };
@ -7250,13 +7310,12 @@
list = $("#list-" + type, QR.nodes.el); list = $("#list-" + type, QR.nodes.el);
for (_i = 0, _len = arr.length; _i < _len; _i++) { for (_i = 0, _len = arr.length; _i < _len; _i++) {
val = arr[_i]; val = arr[_i];
if (!val) { if (val) {
continue;
}
$.add(list, $.el('option', { $.add(list, $.el('option', {
textContent: val textContent: val
})); }));
} }
}
}, },
getPassword: function() { getPassword: function() {
var input, m; var input, m;

View File

@ -27,6 +27,7 @@ Build =
date: data.now date: data.now
dateUTC: data.time dateUTC: data.time
comment: data.com comment: data.com
capReps: data.capcode_replies
# thread status # thread status
isSticky: !!data.sticky isSticky: !!data.sticky
isClosed: !!data.closed isClosed: !!data.closed
@ -58,7 +59,7 @@ Build =
postID, threadID, boardID postID, threadID, boardID
name, capcode, tripcode, uniqueID, email, subject, flagCode, flagName, date, dateUTC name, capcode, tripcode, uniqueID, email, subject, flagCode, flagName, date, dateUTC
isSticky, isClosed isSticky, isClosed
comment comment, capReps
file file
} = o } = o
isOP = postID is threadID isOP = postID is threadID
@ -176,23 +177,40 @@ Build =
else else
fileHTML = '' fileHTML = ''
tripcode = tripcode = if tripcode
if tripcode
" <span class=postertrip>#{tripcode}</span>" " <span class=postertrip>#{tripcode}</span>"
else else
'' ''
sticky = sticky = if isSticky
if isSticky
" <img src=#{staticPath}sticky.gif alt=Sticky title=Sticky class=stickyIcon>" " <img src=#{staticPath}sticky.gif alt=Sticky title=Sticky class=stickyIcon>"
else else
'' ''
closed = closed = if isClosed
if isClosed
" <img src=#{staticPath}closed.gif alt=Closed title=Closed class=closedIcon>" " <img src=#{staticPath}closed.gif alt=Closed title=Closed class=closedIcon>"
else else
'' ''
capcodeReplies = ''
if capReps
generateCapcodeReplies = (capcodeType, array) ->
"<span class=smaller><span class=bold>#{
switch capcodeType
when 'admin'
'Administrator'
when 'mod'
'Moderator'
when 'developer'
'Developer'
} Repl#{if array.length > 1 then 'ies' else 'y'}:</span> #{
array.map (ID) ->
"<a href='/#{boardID}/res/#{threadID}#p#{ID}' class=quotelink>&gt;&gt;#{ID}</a>"
.join ' '
}</span><br>"
for capcodeType, array of capReps
capcodeReplies += generateCapcodeReplies capcodeType, array
capcodeReplies = "<br><br><span class=capcodeReplies>#{capcodeReplies}</span>"
container = $.el 'div', container = $.el 'div',
id: "pc#{postID}" id: "pc#{postID}"
className: "postContainer #{if isOP then 'op' else 'reply'}Container" className: "postContainer #{if isOP then 'op' else 'reply'}Container"
@ -245,7 +263,7 @@ Build =
(if isOP then '' else fileHTML) + (if isOP then '' else fileHTML) +
"<blockquote class=postMessage id=m#{postID}>#{comment or ''}</blockquote> " + "<blockquote class=postMessage id=m#{postID}>#{comment or ''}#{capcodeReplies}</blockquote> " +
'</div>' '</div>'

View File

@ -61,8 +61,7 @@ $.formData = (form) ->
if form instanceof HTMLFormElement if form instanceof HTMLFormElement
return new FormData form return new FormData form
fd = new FormData() fd = new FormData()
for key, val of form for key, val of form when val
continue unless val
# XXX GM bug # XXX GM bug
# if val instanceof Blob # if val instanceof Blob
if val.size and val.name if val.size and val.name

View File

@ -174,8 +174,7 @@ class Post
return if file return if file
# Get quotelinks/backlinks to this post # Get quotelinks/backlinks to this post
# and paint them (Dead). # and paint them (Dead).
for quotelink in Get.allQuotelinksLinkingTo @ for quotelink in Get.allQuotelinksLinkingTo @ when not $.hasClass quotelink, 'deadlink'
continue if $.hasClass quotelink, 'deadlink'
$.add quotelink, $.tn '\u00A0(Dead)' $.add quotelink, $.tn '\u00A0(Dead)'
$.addClass quotelink, 'deadlink' $.addClass quotelink, 'deadlink'
return return

View File

@ -44,6 +44,9 @@ Linkify =
while ++i < len while ++i < len
node = snapshot.snapshotItem i node = snapshot.snapshotItem i
continue if node.parentElement.nodeName is "A"
data = node.data data = node.data
if Linkify.regString.test data if Linkify.regString.test data
@ -69,7 +72,7 @@ Linkify =
link = match[0] link = match[0]
len2 = index + link.length len2 = index + link.length
break if len - len2 is 0 break if len is len2
range = document.createRange(); range = document.createRange();
range.setStart node, index range.setStart node, index
@ -99,9 +102,7 @@ Linkify =
range.setEnd node, result.index range.setEnd node, result.index
if range.collapsed if range.collapsed
if node.nodeName is 'WBR' range.setEndAfter node
node = node.previousSibling
range.setEnd node, node.length
Linkify.makeLink range, post Linkify.makeLink range, post
@ -137,20 +138,20 @@ Linkify =
embed: (data) -> embed: (data) ->
[key, uid, options, link] = data [key, uid, options, link] = data
href = link.href
embed = $.el 'a', embed = $.el 'a',
name: uid
option: options
className: 'embedder' className: 'embedder'
href: 'javascript:;' href: 'javascript:;'
textContent: '(embed)' textContent: '(embed)'
embed.dataset.service = key for name, value of {key, href, uid, options}
embed.dataset.originalurl = link.href embed.dataset[name] = value
$.addClass link, "#{embed.dataset.service}" $.addClass link, "#{embed.dataset.key}"
$.on embed, 'click', Linkify.cb.toggle $.on embed, 'click', Linkify.cb.toggle
$.after link, [$.tn(' '), embed] $.after link, [$.tn(' '), embed]
return
title: (data) -> title: (data) ->
[key, uid, options, link] = data [key, uid, options, link] = data
@ -190,7 +191,7 @@ Linkify =
embed: (a) -> embed: (a) ->
# We create an element to embed # We create an element to embed
el = (type = Linkify.types[a.dataset.service]).el.call a el = (type = Linkify.types[a.dataset.key]).el.call a
# Set style values. # Set style values.
el.style.cssText = if style = type.style el.style.cssText = if style = type.style
@ -204,15 +205,16 @@ Linkify =
unembed: (a) -> unembed: (a) ->
# Recreate the original link. # Recreate the original link.
{href} = a.dataset
el = $.el 'a', el = $.el 'a',
rel: 'nofollow noreferrer' rel: 'nofollow noreferrer'
target: 'blank' target: 'blank'
className: 'linkify' className: 'linkify'
href: url = a.dataset.originalurl href: href
textContent: a.dataset.title or url textContent: a.dataset.title or href
a.textContent = '(embed)' a.textContent = '(embed)'
$.addClass el, "#{a.dataset.service}" $.addClass el, "#{a.dataset.key}"
return el return el
@ -233,51 +235,50 @@ Linkify =
"[#{key}] #{@status}'d" "[#{key}] #{@status}'d"
types: types:
YouTube:
regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/
el: ->
$.el 'iframe',
src: "//www.youtube.com/embed/#{@name}#{if @option then '#' + @option else ''}?wmode=opaque"
title:
api: (uid) -> "https://gdata.youtube.com/feeds/api/videos/#{uid}?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode"
text: -> JSON.parse(@responseText).entry.title.$t
Vocaroo:
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/
style: 'border: 0; width: 150px; height: 45px;'
el: ->
$.el 'object',
innerHTML: "<embed src='http://vocaroo.com/player.swf?playMediaID=#{@name.replace /^i\//, ''}&autoplay=0' wmode='opaque' width='150' height='45' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
Vimeo:
regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/
el: ->
$.el 'iframe',
src: "//player.vimeo.com/video/#{@name}?wmode=opaque"
title:
api: (uid) -> "https://vimeo.com/api/oembed.json?url=http://vimeo.com/#{uid}"
text: -> JSON.parse(@responseText).title
LiveLeak:
regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/
el: ->
$.el 'object',
innerHTML: "<embed src='http://www.liveleak.com/e/#{@name}?autostart=true' wmode='opaque' width='640' height='390' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
audio: audio:
regExp: /(.*\.(mp3|ogg|wav))$/ regExp: /(.*\.(mp3|ogg|wav))$/
el: -> el: ->
$.el 'audio', $.el 'audio',
controls: 'controls' controls: 'controls'
preload: 'auto' preload: 'auto'
src: @name src: @dataset.uid
gist:
regExp: /.*(?:gist.github.com.*\/)([^\/][^\/]*)$/
el: ->
div = $.el 'iframe',
# Github doesn't allow embedding straight from the site, so we use an external site to bypass that.
src: "http://www.purplegene.com/script?url=https://gist.github.com/#{@dataset.uid}.js"
title:
api: (uid) -> "https://api.github.com/gists/#{uid}"
text: ->
response = JSON.parse(@responseText).files
return file for file of response when response.hasOwnProperty file
image: image:
regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/ regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/
style: 'border: 0; width: auto; height: auto;' style: 'border: 0; width: auto; height: auto;'
el: -> el: ->
$.el 'div', $.el 'div',
innerHTML: "<a target=_blank href='#{@dataset.originalurl}'><img src='#{@dataset.originalurl}'></a>" innerHTML: "<a target=_blank href='#{@dataset.href}'><img src='#{@dataset.href}'></a>"
InstallGentoo:
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/
el: ->
$.el 'iframe',
src: "http://paste.installgentoo.com/view/embed/#{@dataset.uid}"
LiveLeak:
regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/
el: ->
$.el 'object',
innerHTML: "<embed src='http://www.liveleak.com/e/#{@dataset.uid}?autostart=true' wmode='opaque' width='640' height='390' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
pastebin:
regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/
el: ->
div = $.el 'iframe',
src: "http://pastebin.com/embed_iframe.php?i=#{@dataset.uid}"
SoundCloud: SoundCloud:
regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/ regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/
@ -287,7 +288,7 @@ Linkify =
className: "soundcloud" className: "soundcloud"
name: "soundcloud" name: "soundcloud"
$.ajax( $.ajax(
"//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/#{@name}" "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/#{@dataset.uid}"
div: div div: div
onloadend: -> onloadend: ->
@div.innerHTML = JSON.parse(@responseText).html @div.innerHTML = JSON.parse(@responseText).html
@ -297,26 +298,59 @@ Linkify =
api: (uid) -> "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/#{uid}" api: (uid) -> "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/#{uid}"
text: -> JSON.parse(@responseText).title text: -> JSON.parse(@responseText).title
pastebin: TwitchTV:
regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/ regExp: /.*(?:twitch.tv\/)([^#\&\?]*).*/
style: "border: none; width: 640px; height: 360px;"
el: -> el: ->
div = $.el 'iframe', if result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec @dataset.uid
src: "http://pastebin.com/embed_iframe.php?i=#{@name}" [_, channel, chapter] = result
gist: $.el 'object',
regExp: /.*(?:gist.github.com.*\/)([^\/][^\/]*)$/ data: 'http://www.twitch.tv/widgets/archive_embed_player.swf'
innerHTML: """
<param name='allowFullScreen' value='true' />
<param name='flashvars' value='channel=#{channel}&start_volume=25&auto_play=false#{if chapter then "&chapter_id=" + chapter else ""}' />
"""
else
channel = (/(\w+)/.exec @dataset.uid)[0]
$.el 'object',
data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=#{channel}"
innerHTML: """
<param name="allowFullScreen" value="true" />
<param name="movie" value="http://www.twitch.tv/widgets/live_embed_player.swf" />
<param name="flashvars" value="hostname=www.twitch.tv&channel=#{channel}&auto_play=true&start_volume=25" />
"""
Vocaroo:
regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/
style: 'border: 0; width: 150px; height: 45px;'
el: -> el: ->
div = $.el 'iframe', $.el 'object',
# Github doesn't allow embedding straight from the site, so we use an external site to bypass that. innerHTML: "<embed src='http://vocaroo.com/player.swf?playMediaID=#{@dataset.uid.replace /^i\//, ''}&autoplay=0' wmode='opaque' width='150' height='45' pluginspage='http://get.adobe.com/flashplayer/' type='application/x-shockwave-flash'></embed>"
src: "http://www.purplegene.com/script?url=https://gist.github.com/#{@name}.js"
title:
api: (uid) -> "https://api.github.com/gists/#{uid}"
text: ->
response = JSON.parse(@responseText).files
return file for file of response when response.hasOwnProperty file
InstallGentoo: Vimeo:
regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/ regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/
el: -> el: ->
$.el 'iframe', $.el 'iframe',
src: "http://paste.installgentoo.com/view/embed/#{@name}" src: "//player.vimeo.com/video/#{@dataset.uid}?wmode=opaque"
title:
api: (uid) -> "https://vimeo.com/api/oembed.json?url=http://vimeo.com/#{uid}"
text: -> JSON.parse(@responseText).title
Vine:
regExp: /.*(?:vine.co\/)([^#\&\?]*).*/
style: 'border: none; width: 500px; height: 500px;'
el: ->
$.el 'iframe',
src: "https://vine.co/#{@dataset.uid}/card"
YouTube:
regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/
el: ->
$.el 'iframe',
src: "//www.youtube.com/embed/#{@dataset.uid}#{if @dataset.option then '#' + @dataset.option else ''}?wmode=opaque"
title:
api: (uid) -> "https://gdata.youtube.com/feeds/api/videos/#{uid}?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode"
text: -> JSON.parse(@responseText).entry.title.$t

View File

@ -215,9 +215,7 @@ QR =
loadPersonas: (type, arr) -> loadPersonas: (type, arr) ->
list = $ "#list-#{type}", QR.nodes.el list = $ "#list-#{type}", QR.nodes.el
for val in arr for val in arr when val
# XXX Firefox displays empty <option>s in the completion list.
continue unless val
$.add list, $.el 'option', $.add list, $.el 'option',
textContent: val textContent: val
return return