Merge branch 'api' into v3
This commit is contained in:
commit
ff1411d6ed
315
4chan_x.user.js
315
4chan_x.user.js
@ -8,11 +8,16 @@
|
||||
// @match *://boards.4chan.org/*
|
||||
// @match *://images.4chan.org/*
|
||||
// @match *://sys.4chan.org/*
|
||||
// @match *://api.4chan.org/*
|
||||
// @match *://*.foolz.us/api/*
|
||||
// @grant GM_getValue
|
||||
// @grant GM_setValue
|
||||
// @grant GM_deleteValue
|
||||
// @grant GM_openInTab
|
||||
// @run-at document-start
|
||||
// @updateURL https://github.com/MayhemYDG/4chan-x/raw/stable/4chan_x.user.js
|
||||
// @downloadURL https://github.com/MayhemYDG/4chan-x/raw/stable/4chan_x.user.js
|
||||
// @icon http://mayhemydg.github.com/4chan-x/favicon.gif
|
||||
// @icon data:image/gif;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAIALAAAAAAQABAAAAIxlI+pq+D9DAgUoFkPDlbs7lGiI2bSVnKglnJMOL6omczxVZK3dH/41AG6Lh7i6qUoAAA7
|
||||
// ==/UserScript==
|
||||
|
||||
/* LICENSE
|
||||
@ -81,6 +86,7 @@
|
||||
Config = {
|
||||
main: {
|
||||
Enhancing: {
|
||||
'Disable 4chan\'s extension': [true, 'Avoid conflicts between 4chan X and 4chan\'s inline extension.'],
|
||||
'404 Redirect': [true, 'Redirect dead threads and images.'],
|
||||
'Keybinds': [true, 'Bind actions to keyboard shortcuts.'],
|
||||
'Time Formatting': [true, 'Localize and format timestamps arbitrarily.'],
|
||||
@ -937,6 +943,9 @@
|
||||
return (_ref2 = $.id('boardNavDesktopFoot')) != null ? _ref2.hidden = true : void 0;
|
||||
},
|
||||
initFeatures: function() {
|
||||
if (Conf['Disable 4chan\'s extension']) {
|
||||
localStorage.setItem('4chan-settings', '{"disableAll":true}');
|
||||
}
|
||||
if (Conf['Resurrect Quotes']) {
|
||||
try {
|
||||
Quotify.init();
|
||||
@ -1086,7 +1095,7 @@
|
||||
return $.on(d, 'DOMNodeInserted', Main.addStyle);
|
||||
}
|
||||
},
|
||||
css: "/* general */\n.dialog.reply {\n display: block;\n border: 1px solid rgba(0, 0, 0, .25);\n padding: 0;\n}\n.move {\n cursor: move;\n}\nlabel {\n cursor: pointer;\n}\na[href=\"javascript:;\"] {\n text-decoration: none;\n}\n.warning {\n color: red;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\n display: block !important;\n}\n.post {\n overflow: visible !important;\n}\n\n/* header */\nbody.fourchan_x {\n margin-top: 2.5em;\n}\n#boardNavDesktop.reply {\n border-width: 0 0 1px;\n padding: 4px;\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n transition: opacity .1s ease-in-out;\n -o-transition: opacity .1s ease-in-out;\n -moz-transition: opacity .1s ease-in-out;\n -webkit-transition: opacity .1s ease-in-out;\n z-index: 1;\n}\n#boardNavDesktop.reply:not(:hover) {\n opacity: .4;\n transition: opacity 1.5s .5s ease-in-out;\n -o-transition: opacity 1.5s .5s ease-in-out;\n -moz-transition: opacity 1.5s .5s ease-in-out;\n -webkit-transition: opacity 1.5s .5s ease-in-out;\n}\n#boardNavDesktop.reply a {\n margin: -1px;\n}\n#settings {\n float: right;\n}\n\n/* quote */\n.inlined {\n opacity: .5;\n}\n#qp input, .forwarded {\n display: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\n text-decoration: none;\n border-bottom: 1px dashed;\n}\n.inline {\n border: 1px solid rgba(128, 128, 128, .5);\n display: table;\n margin: 2px 0;\n}\n.inline .post {\n border: 0 !important;\n display: table !important;\n margin: 0 !important;\n padding: 1px 2px !important;\n}\n#qp {\n position: fixed;\n padding: 2px 2px 5px;\n}\n#qp .post {\n border: none;\n margin: 0;\n padding: 0;\n}\n#qp img {\n max-height: 300px;\n max-width: 500px;\n}\n.qphl {\n outline: 2px solid rgba(216, 94, 49, .7);\n}\n\n/* file */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull {\n display: none;\n}\n#ihover {\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n max-height: 100%;\n max-width: 75%;\n position: fixed;\n padding-bottom: 16px;\n}"
|
||||
css: "/* general */\n.dialog.reply {\n display: block;\n border: 1px solid rgba(0, 0, 0, .25);\n padding: 0;\n}\n.move {\n cursor: move;\n}\nlabel {\n cursor: pointer;\n}\na[href=\"javascript:;\"] {\n text-decoration: none;\n}\n.warning {\n color: red;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\n display: block !important;\n}\n.post {\n overflow: visible !important;\n}\n\n/* header */\nbody.fourchan_x {\n margin-top: 2.5em;\n}\n#boardNavDesktop.reply {\n border-width: 0 0 1px;\n padding: 4px;\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n transition: opacity .1s ease-in-out;\n -o-transition: opacity .1s ease-in-out;\n -moz-transition: opacity .1s ease-in-out;\n -webkit-transition: opacity .1s ease-in-out;\n z-index: 1;\n}\n#boardNavDesktop.reply:not(:hover) {\n opacity: .4;\n transition: opacity 1.5s .5s ease-in-out;\n -o-transition: opacity 1.5s .5s ease-in-out;\n -moz-transition: opacity 1.5s .5s ease-in-out;\n -webkit-transition: opacity 1.5s .5s ease-in-out;\n}\n#boardNavDesktop.reply a {\n margin: -1px;\n}\n#settings {\n float: right;\n}\n\n/* quote */\n.quotelink.deadlink {\n text-decoration: underline !important;\n}\n.inlined {\n opacity: .5;\n}\n#qp input, .forwarded {\n display: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\n text-decoration: none;\n border-bottom: 1px dashed;\n}\n.inline {\n border: 1px solid rgba(128, 128, 128, .5);\n display: table;\n margin: 2px 0;\n}\n.inline .post {\n border: 0 !important;\n display: table !important;\n margin: 0 !important;\n padding: 1px 2px !important;\n}\n#qp {\n position: fixed;\n padding: 2px 2px 5px;\n}\n#qp .post {\n border: none;\n margin: 0;\n padding: 0;\n}\n#qp img {\n max-height: 300px;\n max-width: 500px;\n}\n.qphl {\n outline: 2px solid rgba(216, 94, 49, .7);\n}\n\n/* file */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull {\n display: none;\n}\n#ihover {\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n max-height: 100%;\n max-width: 75%;\n position: fixed;\n padding-bottom: 16px;\n}"
|
||||
};
|
||||
|
||||
Redirect = {
|
||||
@ -1230,6 +1239,7 @@
|
||||
};
|
||||
|
||||
Build = {
|
||||
spoilerRange: {},
|
||||
shortFilename: function(filename, isReply) {
|
||||
var threshold;
|
||||
threshold = isReply ? 30 : 40;
|
||||
@ -1239,120 +1249,139 @@
|
||||
return filename;
|
||||
}
|
||||
},
|
||||
post: function(o) {
|
||||
var board, bq, capcode, comment, container, date, dateUTC, email, file, fl, flag, flagTitle, html, isOP, name, pi, post, postID, subject, threadID, tripcode, uniqueID;
|
||||
postID = o.postID, threadID = o.threadID, board = o.board, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flag = o.flag, flagTitle = o.flagTitle, date = o.date, dateUTC = o.dateUTC, comment = o.comment, file = o.file;
|
||||
postFromObject: function(data, board) {
|
||||
var o;
|
||||
o = {
|
||||
postID: data.no,
|
||||
threadID: data.resto || data.no,
|
||||
board: board,
|
||||
name: data.name,
|
||||
capcode: data.capcode,
|
||||
tripcode: data.trip,
|
||||
uniqueID: data.id,
|
||||
email: data.email ? encodeURIComponent(data.email) : '',
|
||||
subject: data.sub,
|
||||
flagCode: data.country,
|
||||
flagName: data.country_name,
|
||||
date: data.now,
|
||||
dateUTC: data.time,
|
||||
comment: data.com,
|
||||
isSticky: !!data.sticky,
|
||||
isClosed: !!data.closed
|
||||
};
|
||||
if (data.ext || data.filedeleted) {
|
||||
o.file = {
|
||||
name: data.filename + data.ext,
|
||||
timestamp: "" + data.tim + data.ext,
|
||||
url: "//images.4chan.org/" + board + "/src/" + data.tim + data.ext,
|
||||
height: data.h,
|
||||
width: data.w,
|
||||
MD5: data.md5,
|
||||
size: data.fsize,
|
||||
turl: "//thumbs.4chan.org/" + board + "/thumb/" + data.tim + "s.jpg",
|
||||
theight: data.tn_h,
|
||||
twidth: data.tn_w,
|
||||
isSpoiler: !!data.spoiler,
|
||||
isDeleted: !!data.filedeleted
|
||||
};
|
||||
}
|
||||
return Build.post(o);
|
||||
},
|
||||
post: function(o, isArchived) {
|
||||
/*
|
||||
This function contains code from 4chan-JS (https://github.com/4chan/4chan-JS).
|
||||
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
var a, board, 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;
|
||||
postID = o.postID, threadID = o.threadID, board = o.board, 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;
|
||||
isOP = postID === threadID;
|
||||
html = [];
|
||||
html.push("<input type=checkbox name=" + postID + " value=delete> ");
|
||||
html.push("<span class=subject>" + subject + "</span> ");
|
||||
html.push("<span class='nameBlock");
|
||||
html.push((function() {
|
||||
staticPath = '//static.4chan.org';
|
||||
if (email) {
|
||||
emailStart = '<a href="mailto:' + email + '" class="useremail">';
|
||||
emailEnd = '</a>';
|
||||
} else {
|
||||
emailStart = '';
|
||||
emailEnd = '';
|
||||
}
|
||||
subject = subject ? "<span class=subject>" + subject + "</span>" : '';
|
||||
userID = !capcode && uniqueID ? (" <span class='posteruid id_" + uniqueID + "'>(ID: ") + ("<span class=hand title='Highlight posts by this ID'>" + uniqueID + "</span>)</span> ") : '';
|
||||
switch (capcode) {
|
||||
case 'M':
|
||||
return ' capcodeMod';
|
||||
case 'A':
|
||||
return ' capcodeAdmin';
|
||||
case 'D':
|
||||
return ' capcodeDeveloper';
|
||||
case 'admin':
|
||||
case 'admin_highlight':
|
||||
capcodeClass = " capcodeAdmin";
|
||||
capcodeStart = " <strong class='capcode hand id_admin'" + "title='Highlight posts by the Administrator'>## Admin</strong>";
|
||||
capcode = (" <img src='" + staticPath + "/image/adminicon.gif' ") + "alt='This user is the 4chan Administrator.' " + "title='This user is the 4chan Administrator.' class=identityIcon>";
|
||||
break;
|
||||
case 'mod':
|
||||
capcodeClass = " capcodeMod";
|
||||
capcodeStart = " <strong class='capcode hand id_mod' " + "title='Highlight posts by Moderators'>## Moderator</strong>";
|
||||
capcode = (" <img src='" + staticPath + "/image/modicon.gif' ") + "alt='This user is a 4chan Moderator.' " + "title='This user is a 4chan Moderator.' class=identityIcon>";
|
||||
break;
|
||||
case 'developer':
|
||||
capcodeClass = " capcodeDeveloper";
|
||||
capcodeStart = " <strong class='capcode hand id_developer' " + "title='Highlight posts by Developers'>## Developer</strong>";
|
||||
capcode = (" <img src='" + staticPath + "/image/developericon.gif' ") + "alt='This user is a 4chan Developer.' " + "title='This user is a 4chan Developer.' class=identityIcon>";
|
||||
break;
|
||||
default:
|
||||
return '';
|
||||
capcodeClass = '';
|
||||
capcodeStart = '';
|
||||
capcode = '';
|
||||
}
|
||||
})());
|
||||
html.push("'>");
|
||||
if (email) {
|
||||
html.push("<a href=mailto:" + email + " class=useremail>");
|
||||
flag = flagCode ? (" <img src='" + staticPath + "/image/country/" + (board === 'pol' ? 'troll/' : '')) + flagCode.toLowerCase() + (".gif' alt=" + flagCode + " title='" + flagName + "' class=countryFlag>") : '';
|
||||
if (file != null ? file.isDeleted : void 0) {
|
||||
fileHTML = isOP ? ("<div class=file id=f" + postID + "><div class=fileInfo></div><span class=fileThumb>") + ("<img src='" + staticPath + "/image/filedeleted.gif' alt='File deleted.'>") + "</span></div>" : ("<div id=f" + postID + " class=file><span class=fileThumb>") + ("<img src='" + staticPath + "/image/filedeleted-res.gif' alt='File deleted.'>") + "</span></div>";
|
||||
} else if (file) {
|
||||
ext = file.name.slice(-3);
|
||||
if (!file.twidth && !file.theight && ext === 'gif') {
|
||||
file.twidth = file.width;
|
||||
file.theight = file.height;
|
||||
}
|
||||
html.push("<span class=name>" + name + "</span>");
|
||||
if (tripcode) {
|
||||
html.push(" <span class=postertrip>" + tripcode + "</span>");
|
||||
}
|
||||
if (uniqueID) {
|
||||
html.push(" <span class='posteruid id_" + uniqueID + "'>(ID: <span class=hand title='Highlight posts by this ID'>" + uniqueID + "</span>)</span>");
|
||||
}
|
||||
switch (capcode) {
|
||||
case 'M':
|
||||
html.push(' <strong class="capcode hand id_mod" title="Highlight posts by Moderators">## Mod</strong>');
|
||||
html.push(' <img src=//static.4chan.org/image/modicon.gif alt="This user is a 4chan Moderator." title="This user is a 4chan Moderator." class=identityIcon>');
|
||||
break;
|
||||
case 'A':
|
||||
html.push(' <strong class="capcode hand id_admin" title="Highlight posts by the Administrator">## Admin</strong>');
|
||||
html.push(' <img src=//static.4chan.org/image/adminicon.gif alt="This user is the 4chan Administrator." title="This user is the 4chan Administrator." class=identityIcon>');
|
||||
break;
|
||||
case 'D':
|
||||
html.push(' <strong class="capcode hand id_mod" title="Highlight posts by Moderators">## Mod</strong>');
|
||||
html.push(' <img src=//static.4chan.org/image/developericon.gif alt="This user is a 4chan Developer." title="This user is a 4chan Developer." class=identityIcon>');
|
||||
}
|
||||
if (email) {
|
||||
html.push('</a>');
|
||||
}
|
||||
if (flag) {
|
||||
html.push(" <img src=//static.4chan.org/image/country/" + (flag.toLowerCase()) + ".gif alt=" + flag + " title='" + flagTitle + "' class=countryFlag>");
|
||||
}
|
||||
html.push('</span> ');
|
||||
html.push("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ");
|
||||
html.push('<span class="postNum desktop">');
|
||||
html.push("<a href=/" + board + "/res/" + threadID + "#p" + postID + " title='Highlight this post'>No.</a>");
|
||||
html.push("<a href=\"" + (g.REPLY ? "javascript:quote('" + postID + "');" : "/" + board + "/res/" + threadID + "#q" + postID) + "\" title='Quote this post'>" + postID + "</a>");
|
||||
html.push('</span>');
|
||||
pi = $.el('div', {
|
||||
id: "pi" + postID,
|
||||
className: 'postInfo desktop',
|
||||
innerHTML: html.join('')
|
||||
});
|
||||
bq = $.el('blockquote', {
|
||||
id: "m" + postID,
|
||||
className: 'postMessage',
|
||||
innerHTML: comment
|
||||
});
|
||||
if (file.name) {
|
||||
html = [];
|
||||
html.push('<div class=fileInfo>');
|
||||
html.push("<span id=fT" + postID + " class=fileText" + (file.isSpoiler ? " title='file.name'" : '') + ">File: ");
|
||||
html.push("<a href=" + file.url + " target=_blank>" + file.origin + "</a>");
|
||||
html.push('-(');
|
||||
fileSize = $.bytesToString(file.size);
|
||||
fileThumb = file.turl;
|
||||
if (file.isSpoiler) {
|
||||
html.push('Spoiler Image, ');
|
||||
fileSize = "Spoiler Image, " + fileSize;
|
||||
if (!isArchived) {
|
||||
fileThumb = '//static.4chan.org/image/spoiler';
|
||||
if (spoilerRange = Build.spoilerRange[board]) {
|
||||
fileThumb += ("-" + board) + Math.floor(1 + spoilerRange * Math.random());
|
||||
}
|
||||
html.push("" + ($.bytesToString(file.size)) + ", ");
|
||||
html.push(/\.pdf$/i.test(file.name) ? "PDF" : "" + file.width + "x" + file.height);
|
||||
if (!file.isSpoiler) {
|
||||
html.push(", <span title='" + file.name + "'>" + (Build.shortFilename(file.name)) + "</span>");
|
||||
fileThumb += '.png';
|
||||
file.twidth = file.theight = 100;
|
||||
}
|
||||
html.push(")</span></div>");
|
||||
html.push("<a class='fileThumb" + (file.isSpoiler ? ' imgspoiler' : '') + "' href=" + file.url + " target=_blank>");
|
||||
html.push("<img src=" + file.turl + " alt='" + (file.isSpoiler ? 'Spoiler Image, ' : '') + ($.bytesToString(file.size)) + "' data-md5='" + file.MD5 + "' style='height:" + file.theight + "px;width:" + file.twidth + "px'>");
|
||||
html.push('</a>');
|
||||
fl = $.el('div', {
|
||||
id: "f" + postID,
|
||||
className: 'file',
|
||||
innerHTML: html.join('')
|
||||
}
|
||||
imgSrc = ("<a class='fileThumb" + (file.isSpoiler ? ' imgspoiler' : '') + "' href='" + file.url + "' target=_blank>") + ("<img src='" + fileThumb + "' alt='" + fileSize + "' data-md5=" + file.MD5 + " style='width:" + file.twidth + "px;height:" + file.theight + "px'></a>");
|
||||
a = $.el('a', {
|
||||
innerHTML: file.name
|
||||
});
|
||||
filename = a.textContent.replace(/%22/g, '"');
|
||||
a.textContent = Build.shortFilename(filename);
|
||||
shortFilename = a.innerHTML;
|
||||
a.textContent = filename;
|
||||
filename = a.innerHTML.replace(/'/g, ''');
|
||||
fileDims = ext === 'pdf' ? 'PDF' : "" + file.width + "x" + file.height;
|
||||
fileInfo = ("<span class=fileText id=fT" + postID + (file.isSpoiler ? " title='" + filename + "'" : '') + ">File: <a href='" + file.url + "' target=_blank>" + file.timestamp + "</a>") + ("-(" + fileSize + ", " + fileDims + (file.isSpoiler ? '' : ", <span title='" + filename + "'>" + shortFilename + "</span>")) + ")</span>";
|
||||
fileHTML = "<div id=f" + postID + " class=file><div class=fileInfo>" + fileInfo + "</div>" + imgSrc + "</div>";
|
||||
} else {
|
||||
fileHTML = '';
|
||||
}
|
||||
post = $.el('div', {
|
||||
id: "p" + postID,
|
||||
className: "post " + (isOP ? 'op' : 'reply')
|
||||
});
|
||||
if (fl && isOP) {
|
||||
$.add(post, fl);
|
||||
}
|
||||
$.add(post, pi);
|
||||
if (fl && !isOP) {
|
||||
$.add(post, fl);
|
||||
}
|
||||
$.add(post, bq);
|
||||
tripcode = tripcode ? " <span class=postertrip>" + tripcode + "</span>" : '';
|
||||
sticky = isSticky ? ' <img src=//static.4chan.org/image/sticky.gif alt=Sticky title=Sticky style="height:16px;width:16px">' : '';
|
||||
closed = isClosed ? ' <img src=//static.4chan.org/image/closed.gif alt=Closed title=Closed style="height:16px;width:16px">' : '';
|
||||
container = $.el('div', {
|
||||
id: "pc" + postID,
|
||||
className: "postContainer " + (isOP ? 'op' : 'reply') + "Container"
|
||||
className: "postContainer " + (isOP ? 'op' : 'reply') + "Container",
|
||||
innerHTML: (isOP ? '' : "<div class=sideArrows id=sa" + postID + ">>></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) + '<br><em>' + ("<a href=" + ("/" + board + "/res/" + threadID + "#p" + postID) + ">No.</a>") + ("<a href='" + (g.REPLY && g.THREAD_ID === threadID ? "javascript:quote(" + postID + ")" : "/" + board + "/res/" + threadID + "#q" + postID) + "'>" + postID + "</a>") + '</em></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=" + ("/" + board + "/res/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.REPLY && g.THREAD_ID === threadID ? "javascript:quote(" + postID + ")" : "/" + board + "/res/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage id=m" + postID + ">" + (comment || '') + "</blockquote> ") + '</div>'
|
||||
});
|
||||
if (!isOP) {
|
||||
$.add(container, $.el('div', {
|
||||
id: "sa" + postID,
|
||||
className: 'sideArrows',
|
||||
textContent: '>>'
|
||||
}));
|
||||
_ref = $$('.quotelink', container);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
quote = _ref[_i];
|
||||
href = quote.getAttribute('href');
|
||||
if (href[0] === '/') {
|
||||
continue;
|
||||
}
|
||||
quote.href = "/" + board + "/res/" + href;
|
||||
}
|
||||
$.add(container, post);
|
||||
return container;
|
||||
}
|
||||
};
|
||||
@ -1397,7 +1426,7 @@
|
||||
}
|
||||
root.textContent = "Loading post No." + postID + "...";
|
||||
if (threadID) {
|
||||
return $.cache("/" + board + "/res/" + threadID, function() {
|
||||
return $.cache("//api.4chan.org/" + board + "/res/" + threadID + ".json", function() {
|
||||
return Get.fetchedPost(this, board, threadID, postID, root, context);
|
||||
});
|
||||
} else if (url = Redirect.post(board, postID)) {
|
||||
@ -1420,7 +1449,7 @@
|
||||
return $.add(root, nodes.root);
|
||||
},
|
||||
fetchedPost: function(req, board, threadID, postID, root, context) {
|
||||
var doc, href, link, pc, post, quote, status, thread, url, _i, _len, _ref;
|
||||
var post, posts, spoilerRange, status, thread, url, _i, _len;
|
||||
if (post = g.posts["" + board + "." + postID]) {
|
||||
Get.insert(post, root, context);
|
||||
return;
|
||||
@ -1429,48 +1458,44 @@
|
||||
if (status !== 200) {
|
||||
if (url = Redirect.post(board, postID)) {
|
||||
$.cache(url, function() {
|
||||
return Get.archivedPost(this, board, postID, root);
|
||||
return Get.archivedPost(this, board, postID, root, context);
|
||||
});
|
||||
} else {
|
||||
$.addClass(root, 'warning');
|
||||
root.textContent = status === 404 ? "Thread No." + threadID + " has not been found." : "Error " + req.status + ": " + req.statusText + ".";
|
||||
root.textContent = status === 404 ? "Thread No." + threadID + " 404'd." : "Error " + req.status + ": " + req.statusText + ".";
|
||||
}
|
||||
return;
|
||||
}
|
||||
doc = d.implementation.createHTMLDocument('');
|
||||
doc.documentElement.innerHTML = req.response;
|
||||
if (!(pc = doc.getElementById("pc" + postID))) {
|
||||
posts = JSON.parse(req.response).posts;
|
||||
if (spoilerRange = posts[0].custom_spoiler) {
|
||||
Build.spoilerRange[board] = spoilerRange;
|
||||
}
|
||||
postID = +postID;
|
||||
for (_i = 0, _len = posts.length; _i < _len; _i++) {
|
||||
post = posts[_i];
|
||||
if (post.no === postID) {
|
||||
break;
|
||||
}
|
||||
if (post.no > postID) {
|
||||
if (url = Redirect.post(board, postID)) {
|
||||
$.cache(url, function() {
|
||||
return Get.archivedPost(this, board, postID, root);
|
||||
return Get.parseArchivedPost(this, board, postID, root, context);
|
||||
});
|
||||
} else {
|
||||
$.addClass(root, 'warning');
|
||||
root.textContent = "Post No." + postID + " has not been found.";
|
||||
root.textContent = "Post No." + postID + " was not found.";
|
||||
}
|
||||
return;
|
||||
}
|
||||
pc = d.importNode(pc, true);
|
||||
_ref = $$('.quotelink', pc);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
quote = _ref[_i];
|
||||
href = quote.getAttribute('href');
|
||||
if (href[0] === '/') {
|
||||
continue;
|
||||
}
|
||||
quote.href = "/" + board + "/res/" + href;
|
||||
}
|
||||
link = $('a[title="Highlight this post"]', pc);
|
||||
link.href = "/" + board + "/res/" + threadID + "#p" + postID;
|
||||
link.nextSibling.href = "/" + board + "/res/" + threadID + "#q" + postID;
|
||||
board = g.boards[board] || new Board(board);
|
||||
thread = g.threads["" + board + "." + threadID] || new Thread(threadID, board);
|
||||
post = new Post(pc, thread, board);
|
||||
post = new Post(Build.postFromObject(post, board), thread, board);
|
||||
Main.callbackNodes(Post, [post]);
|
||||
return Get.insert(post, root, context);
|
||||
},
|
||||
archivedPost: function(req, board, postID, root, context) {
|
||||
var bq, comment, data, post, postContainer, thread, threadID;
|
||||
var bq, comment, data, o, post, thread, threadID;
|
||||
if (post = g.posts["" + board + "." + postID]) {
|
||||
Get.insert(post, root, context);
|
||||
return;
|
||||
@ -1512,37 +1537,49 @@
|
||||
});
|
||||
comment = bq.innerHTML.replace(/(^|>)(>[^<$]+)(<|$)/g, '$1<span class=quote>$2</span>$3');
|
||||
threadID = data.thread_num;
|
||||
postContainer = Build.post({
|
||||
o = {
|
||||
postID: postID,
|
||||
threadID: threadID,
|
||||
board: board,
|
||||
name: data.name,
|
||||
capcode: data.capcode,
|
||||
name: data.name_processed,
|
||||
capcode: (function() {
|
||||
switch (data.capcode) {
|
||||
case 'M':
|
||||
return 'mod';
|
||||
case 'A':
|
||||
return 'admin';
|
||||
case 'D':
|
||||
return 'developer';
|
||||
}
|
||||
})(),
|
||||
tripcode: data.trip,
|
||||
uniqueID: data.poster_hash,
|
||||
email: data.email,
|
||||
subject: data.title,
|
||||
flag: data.poster_country,
|
||||
email: encodeURIComponent(data.email),
|
||||
subject: data.title_processed,
|
||||
flagCode: data.poster_country,
|
||||
flagName: data.poster_country_name_processed,
|
||||
date: data.fourchan_date,
|
||||
dateUTC: data.timestamp,
|
||||
comment: comment,
|
||||
file: {
|
||||
name: data.media_filename,
|
||||
origin: data.media_orig,
|
||||
comment: comment
|
||||
};
|
||||
if (data.media_filename) {
|
||||
o.file = {
|
||||
name: data.media_filename_processed,
|
||||
timestamp: data.media_orig,
|
||||
url: data.media_link || data.remote_media_link,
|
||||
height: data.media_h,
|
||||
width: data.media_w,
|
||||
isSpoiler: data.spoiler === '1',
|
||||
MD5: data.media_hash,
|
||||
size: data.media_size,
|
||||
turl: data.thumb_link || ("//thumbs.4chan.org/" + board + "/thumb/" + data.preview_orig),
|
||||
theight: data.preview_h,
|
||||
twidth: data.preview_w
|
||||
twidth: data.preview_w,
|
||||
isSpoiler: data.spoiler === '1'
|
||||
};
|
||||
}
|
||||
});
|
||||
board = g.boards[board] || new Board(board);
|
||||
thread = g.threads["" + board + "." + threadID] || new Thread(threadID, board);
|
||||
post = new Post(postContainer, thread, board, {
|
||||
post = new Post(Build.post(o, true), thread, board, {
|
||||
isArchived: true
|
||||
});
|
||||
Main.callbackNodes(Post, [post]);
|
||||
|
||||
7
Cakefile
7
Cakefile
@ -19,11 +19,16 @@ HEADER = """
|
||||
// @match *://boards.4chan.org/*
|
||||
// @match *://images.4chan.org/*
|
||||
// @match *://sys.4chan.org/*
|
||||
// @match *://api.4chan.org/*
|
||||
// @match *://*.foolz.us/api/*
|
||||
// @grant GM_getValue
|
||||
// @grant GM_setValue
|
||||
// @grant GM_deleteValue
|
||||
// @grant GM_openInTab
|
||||
// @run-at document-start
|
||||
// @updateURL https://github.com/MayhemYDG/4chan-x/raw/stable/4chan_x.user.js
|
||||
// @downloadURL https://github.com/MayhemYDG/4chan-x/raw/stable/4chan_x.user.js
|
||||
// @icon http://mayhemydg.github.com/4chan-x/favicon.gif
|
||||
// @icon data:image/gif;base64,R0lGODlhEAAQAKECAAAAAGbMM////////yH5BAEKAAIALAAAAAAQABAAAAIxlI+pq+D9DAgUoFkPDlbs7lGiI2bSVnKglnJMOL6omczxVZK3dH/41AG6Lh7i6qUoAAA7
|
||||
// ==/UserScript==
|
||||
|
||||
/* LICENSE
|
||||
|
||||
16
changelog
16
changelog
@ -4,6 +4,22 @@ alpha
|
||||
Fix Quote Backlinks not affecting inlined quotes.
|
||||
Fix Quote Highlighting not affecting inlined quotes.
|
||||
|
||||
master
|
||||
- Mayhem
|
||||
Use 4chan's API to fetch posts for:
|
||||
- Thread Updater.
|
||||
- Quote Inlining.
|
||||
- Quote Previewing.
|
||||
- Thread Expansion.
|
||||
- Comment Expansion.
|
||||
This will make fetching faster, and reduce bandwidth usage.
|
||||
Add an option to disable 4chan's inline extension. Enabled by default.
|
||||
Fix compatibility with Scriptish's auto-udpater.
|
||||
|
||||
2.34.10
|
||||
- Mayhem
|
||||
Fix 4chan X. Blame moot.
|
||||
|
||||
2.34.9
|
||||
- Mayhem
|
||||
Add /g/, /k/, /w/, /an/, /cgl/, /ck/, /lit/, /toy/ and /x/ archived image redirection.
|
||||
|
||||
@ -1 +1 @@
|
||||
postMessage({version:'2.34.9'},'*')
|
||||
postMessage({version:'2.34.10'},'*')
|
||||
392
script.coffee
392
script.coffee
@ -1,6 +1,7 @@
|
||||
Config =
|
||||
main:
|
||||
Enhancing:
|
||||
'Disable 4chan\'s extension': [true, 'Avoid conflicts between 4chan X and 4chan\'s inline extension.']
|
||||
'404 Redirect': [true, 'Redirect dead threads and images.']
|
||||
'Keybinds': [true, 'Bind actions to keyboard shortcuts.']
|
||||
'Time Formatting': [true, 'Localize and format timestamps arbitrarily.']
|
||||
@ -741,6 +742,9 @@ Main =
|
||||
$.id('boardNavDesktopFoot')?.hidden = true
|
||||
|
||||
initFeatures: ->
|
||||
if Conf['Disable 4chan\'s extension']
|
||||
localStorage.setItem '4chan-settings', '{"disableAll":true}'
|
||||
|
||||
if Conf['Resurrect Quotes']
|
||||
try
|
||||
Quotify.init()
|
||||
@ -935,6 +939,9 @@ body.fourchan_x {
|
||||
}
|
||||
|
||||
/* quote */
|
||||
.quotelink.deadlink {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
.inlined {
|
||||
opacity: .5;
|
||||
}
|
||||
@ -1060,6 +1067,7 @@ Redirect =
|
||||
url or ''
|
||||
|
||||
Build =
|
||||
spoilerRange: {}
|
||||
shortFilename: (filename, isReply) ->
|
||||
# FILENAME SHORTENING SCIENCE:
|
||||
# OPs have a +10 characters threshold.
|
||||
@ -1069,117 +1077,249 @@ Build =
|
||||
"#{filename[...threshold - 5]}(...).#{filename[-3..]}"
|
||||
else
|
||||
filename
|
||||
post: (o) ->
|
||||
postFromObject: (data, board) ->
|
||||
o =
|
||||
# id
|
||||
postID: data.no
|
||||
threadID: data.resto or data.no
|
||||
board: board
|
||||
# info
|
||||
name: data.name
|
||||
capcode: data.capcode
|
||||
tripcode: data.trip
|
||||
uniqueID: data.id
|
||||
email: if data.email then encodeURIComponent data.email else ''
|
||||
subject: data.sub
|
||||
flagCode: data.country
|
||||
flagName: data.country_name
|
||||
date: data.now
|
||||
dateUTC: data.time
|
||||
comment: data.com
|
||||
# thread status
|
||||
isSticky: !!data.sticky
|
||||
isClosed: !!data.closed
|
||||
# file
|
||||
if data.ext or data.filedeleted
|
||||
o.file =
|
||||
name: data.filename + data.ext
|
||||
timestamp: "#{data.tim}#{data.ext}"
|
||||
url: "//images.4chan.org/#{board}/src/#{data.tim}#{data.ext}"
|
||||
height: data.h
|
||||
width: data.w
|
||||
MD5: data.md5
|
||||
size: data.fsize
|
||||
turl: "//thumbs.4chan.org/#{board}/thumb/#{data.tim}s.jpg"
|
||||
theight: data.tn_h
|
||||
twidth: data.tn_w
|
||||
isSpoiler: !!data.spoiler
|
||||
isDeleted: !!data.filedeleted
|
||||
Build.post o
|
||||
post: (o, isArchived) ->
|
||||
###
|
||||
This function contains code from 4chan-JS (https://github.com/4chan/4chan-JS).
|
||||
@license: https://github.com/4chan/4chan-JS/blob/master/LICENSE
|
||||
###
|
||||
{
|
||||
postID, threadID, board
|
||||
name, capcode, tripcode, uniqueID, email, subject, flag, flagTitle, date, dateUTC, comment
|
||||
name, capcode, tripcode, uniqueID, email, subject, flagCode, flagName, date, dateUTC
|
||||
isSticky, isClosed
|
||||
comment
|
||||
file
|
||||
} = o
|
||||
isOP = postID is threadID
|
||||
|
||||
# post info
|
||||
html = []
|
||||
# input
|
||||
html.push "<input type=checkbox name=#{postID} value=delete> "
|
||||
# subject
|
||||
html.push "<span class=subject>#{subject}</span> "
|
||||
# name block
|
||||
html.push "<span class='nameBlock"
|
||||
html.push switch capcode
|
||||
when 'M' then ' capcodeMod'
|
||||
when 'A' then ' capcodeAdmin'
|
||||
when 'D' then ' capcodeDeveloper'
|
||||
else ''
|
||||
html.push "'>"
|
||||
# mail start
|
||||
html.push "<a href=mailto:#{email} class=useremail>" if email
|
||||
# name
|
||||
html.push "<span class=name>#{name}</span>"
|
||||
# tripcode
|
||||
html.push " <span class=postertrip>#{tripcode}</span>" if tripcode
|
||||
# user id
|
||||
html.push " <span class='posteruid id_#{uniqueID}'>(ID: <span class=hand title='Highlight posts by this ID'>#{uniqueID}</span>)</span>" if uniqueID
|
||||
# capcode
|
||||
staticPath = '//static.4chan.org'
|
||||
|
||||
if email
|
||||
emailStart = '<a href="mailto:' + email + '" class="useremail">'
|
||||
emailEnd = '</a>'
|
||||
else
|
||||
emailStart = ''
|
||||
emailEnd = ''
|
||||
|
||||
subject =
|
||||
if subject
|
||||
"<span class=subject>#{subject}</span>"
|
||||
else
|
||||
''
|
||||
|
||||
userID =
|
||||
if !capcode and uniqueID
|
||||
" <span class='posteruid id_#{uniqueID}'>(ID: " +
|
||||
"<span class=hand title='Highlight posts by this ID'>#{uniqueID}</span>)</span> "
|
||||
else
|
||||
''
|
||||
|
||||
switch capcode
|
||||
when 'M'
|
||||
html.push ' <strong class="capcode hand id_mod" title="Highlight posts by Moderators">## Mod</strong>'
|
||||
html.push ' <img src=//static.4chan.org/image/modicon.gif alt="This user is a 4chan Moderator." title="This user is a 4chan Moderator." class=identityIcon>'
|
||||
when 'A'
|
||||
html.push ' <strong class="capcode hand id_admin" title="Highlight posts by the Administrator">## Admin</strong>'
|
||||
html.push ' <img src=//static.4chan.org/image/adminicon.gif alt="This user is the 4chan Administrator." title="This user is the 4chan Administrator." class=identityIcon>'
|
||||
when 'D'
|
||||
html.push ' <strong class="capcode hand id_mod" title="Highlight posts by Moderators">## Mod</strong>'
|
||||
html.push ' <img src=//static.4chan.org/image/developericon.gif alt="This user is a 4chan Developer." title="This user is a 4chan Developer." class=identityIcon>'
|
||||
# mail end
|
||||
html.push '</a>' if email
|
||||
# flag
|
||||
# XXX what about troll flags in /pol/?
|
||||
html.push " <img src=//static.4chan.org/image/country/#{flag.toLowerCase()}.gif alt=#{flag} title='#{flagTitle}' class=countryFlag>" if flag
|
||||
# end name block
|
||||
html.push '</span> '
|
||||
# date
|
||||
html.push "<span class=dateTime data-utc=#{dateUTC}>#{date}</span> "
|
||||
# post num
|
||||
html.push '<span class="postNum desktop">'
|
||||
html.push "<a href=/#{board}/res/#{threadID}#p#{postID} title='Highlight this post'>No.</a>"
|
||||
html.push "<a href=\"#{
|
||||
if g.REPLY
|
||||
"javascript:quote('#{postID}');"
|
||||
when 'admin', 'admin_highlight'
|
||||
capcodeClass = " capcodeAdmin"
|
||||
capcodeStart = " <strong class='capcode hand id_admin'" +
|
||||
"title='Highlight posts by the Administrator'>## Admin</strong>"
|
||||
capcode = " <img src='#{staticPath}/image/adminicon.gif' " +
|
||||
"alt='This user is the 4chan Administrator.' " +
|
||||
"title='This user is the 4chan Administrator.' class=identityIcon>"
|
||||
when 'mod'
|
||||
capcodeClass = " capcodeMod"
|
||||
capcodeStart = " <strong class='capcode hand id_mod' " +
|
||||
"title='Highlight posts by Moderators'>## Moderator</strong>"
|
||||
capcode = " <img src='#{staticPath}/image/modicon.gif' " +
|
||||
"alt='This user is a 4chan Moderator.' " +
|
||||
"title='This user is a 4chan Moderator.' class=identityIcon>"
|
||||
when 'developer'
|
||||
capcodeClass = " capcodeDeveloper"
|
||||
capcodeStart = " <strong class='capcode hand id_developer' " +
|
||||
"title='Highlight posts by Developers'>## Developer</strong>"
|
||||
capcode = " <img src='#{staticPath}/image/developericon.gif' " +
|
||||
"alt='This user is a 4chan Developer.' " +
|
||||
"title='This user is a 4chan Developer.' class=identityIcon>"
|
||||
else
|
||||
"/#{board}/res/#{threadID}#q#{postID}"
|
||||
}\" title='Quote this post'>#{postID}</a>"
|
||||
# XXX closed/sticky?
|
||||
html.push '</span>'
|
||||
pi = $.el 'div',
|
||||
id: "pi#{postID}"
|
||||
className: 'postInfo desktop'
|
||||
innerHTML: html.join ''
|
||||
capcodeClass = ''
|
||||
capcodeStart = ''
|
||||
capcode = ''
|
||||
|
||||
bq = $.el 'blockquote',
|
||||
id: "m#{postID}"
|
||||
className: 'postMessage'
|
||||
innerHTML: comment
|
||||
|
||||
# file
|
||||
if file.name # XXX need to fix support of Flash
|
||||
html = []
|
||||
html.push '<div class=fileInfo>'
|
||||
html.push "<span id=fT#{postID} class=fileText#{if file.isSpoiler then " title='file.name'" else ''}>File: "
|
||||
html.push "<a href=#{file.url} target=_blank>#{file.origin}</a>"
|
||||
html.push '-('
|
||||
html.push 'Spoiler Image, ' if file.isSpoiler
|
||||
html.push "#{$.bytesToString file.size}, "
|
||||
html.push if /\.pdf$/i.test file.name
|
||||
"PDF"
|
||||
flag =
|
||||
if flagCode
|
||||
" <img src='#{staticPath}/image/country/#{if board is 'pol' then 'troll/' else ''}" +
|
||||
flagCode.toLowerCase() + ".gif' alt=#{flagCode} title='#{flagName}' class=countryFlag>"
|
||||
else
|
||||
"#{file.width}x#{file.height}"
|
||||
html.push ", <span title='#{file.name}'>#{Build.shortFilename file.name}</span>" unless file.isSpoiler
|
||||
html.push ")</span></div>"
|
||||
html.push "<a class='fileThumb#{if file.isSpoiler then ' imgspoiler' else ''}' href=#{file.url} target=_blank>"
|
||||
html.push "<img src=#{file.turl} alt='#{if file.isSpoiler then 'Spoiler Image, ' else ''}#{$.bytesToString file.size}' data-md5='#{file.MD5}' style='height:#{file.theight}px;width:#{file.twidth}px'>"
|
||||
html.push '</a>'
|
||||
fl = $.el 'div',
|
||||
id: "f#{postID}"
|
||||
className: 'file'
|
||||
innerHTML: html.join ''
|
||||
''
|
||||
|
||||
post = $.el 'div',
|
||||
id: "p#{postID}"
|
||||
className: "post #{if isOP then 'op' else 'reply'}"
|
||||
$.add post, fl if fl and isOP
|
||||
$.add post, pi
|
||||
$.add post, fl if fl and !isOP
|
||||
$.add post, bq
|
||||
if file?.isDeleted
|
||||
fileHTML =
|
||||
if isOP
|
||||
"<div class=file id=f#{postID}><div class=fileInfo></div><span class=fileThumb>" +
|
||||
"<img src='#{staticPath}/image/filedeleted.gif' alt='File deleted.'>" +
|
||||
"</span></div>"
|
||||
else
|
||||
"<div id=f#{postID} class=file><span class=fileThumb>" +
|
||||
"<img src='#{staticPath}/image/filedeleted-res.gif' alt='File deleted.'>" +
|
||||
"</span></div>"
|
||||
else if file
|
||||
ext = file.name[-3..]
|
||||
if !file.twidth and !file.theight and ext is 'gif' # wtf ?
|
||||
file.twidth = file.width
|
||||
file.theight = file.height
|
||||
|
||||
fileSize = $.bytesToString file.size
|
||||
|
||||
fileThumb = file.turl
|
||||
if file.isSpoiler
|
||||
fileSize = "Spoiler Image, #{fileSize}"
|
||||
unless isArchived
|
||||
fileThumb = '//static.4chan.org/image/spoiler'
|
||||
if spoilerRange = Build.spoilerRange[board]
|
||||
# Randomize the spoiler image.
|
||||
fileThumb += "-#{board}" + Math.floor 1 + spoilerRange * Math.random()
|
||||
fileThumb += '.png'
|
||||
file.twidth = file.theight = 100
|
||||
|
||||
imgSrc = "<a class='fileThumb#{if file.isSpoiler then ' imgspoiler' else ''}' href='#{file.url}' target=_blank>" +
|
||||
"<img src='#{fileThumb}' alt='#{fileSize}' data-md5=#{file.MD5} style='width:#{file.twidth}px;height:#{file.theight}px'></a>"
|
||||
|
||||
# Ha Ha filenames.
|
||||
# html -> text, translate WebKit's %22s into "s
|
||||
a = $.el 'a', innerHTML: file.name
|
||||
filename = a.textContent.replace /%22/g, '"'
|
||||
|
||||
# shorten filename, get html
|
||||
a.textContent = Build.shortFilename filename
|
||||
shortFilename = a.innerHTML
|
||||
|
||||
# get html
|
||||
a.textContent = filename
|
||||
filename = a.innerHTML.replace /'/g, '''
|
||||
|
||||
fileDims = if ext is 'pdf' then 'PDF' else "#{file.width}x#{file.height}"
|
||||
fileInfo = "<span class=fileText id=fT#{postID}#{if file.isSpoiler then " title='#{filename}'" else ''}>File: <a href='#{file.url}' target=_blank>#{file.timestamp}</a>" +
|
||||
"-(#{fileSize}, #{fileDims}#{
|
||||
if file.isSpoiler
|
||||
''
|
||||
else
|
||||
", <span title='#{filename}'>#{shortFilename}</span>"
|
||||
}" + ")</span>"
|
||||
|
||||
fileHTML = "<div id=f#{postID} class=file><div class=fileInfo>#{fileInfo}</div>#{imgSrc}</div>"
|
||||
else
|
||||
fileHTML = ''
|
||||
|
||||
tripcode =
|
||||
if tripcode
|
||||
" <span class=postertrip>#{tripcode}</span>"
|
||||
else
|
||||
''
|
||||
|
||||
sticky =
|
||||
if isSticky
|
||||
' <img src=//static.4chan.org/image/sticky.gif alt=Sticky title=Sticky style="height:16px;width:16px">'
|
||||
else
|
||||
''
|
||||
closed =
|
||||
if isClosed
|
||||
' <img src=//static.4chan.org/image/closed.gif alt=Closed title=Closed style="height:16px;width:16px">'
|
||||
else
|
||||
''
|
||||
|
||||
container = $.el 'div',
|
||||
id: "pc#{postID}"
|
||||
className: "postContainer #{if isOP then 'op' else 'reply'}Container"
|
||||
unless isOP
|
||||
$.add container, $.el 'div',
|
||||
id: "sa#{postID}"
|
||||
className: 'sideArrows'
|
||||
textContent: '>>'
|
||||
$.add container, post
|
||||
innerHTML: \
|
||||
(if isOP then '' else "<div class=sideArrows id=sa#{postID}>>></div>") +
|
||||
"<div id=p#{postID} class='post #{if isOP then 'op' else 'reply'}#{
|
||||
if capcode is 'admin_highlight'
|
||||
' highlightPost'
|
||||
else
|
||||
''
|
||||
}'>" +
|
||||
|
||||
"<div class='postInfoM mobile' id=pim#{postID}>" +
|
||||
"<span class='nameBlock#{capcodeClass}'>" +
|
||||
"<span class=name>#{name or ''}</span>" + tripcode +
|
||||
capcodeStart + capcode + userID + flag + sticky + closed +
|
||||
"<br>#{subject}" +
|
||||
"</span><span class='dateTime postNum' data-utc=#{dateUTC}>#{date}" +
|
||||
'<br><em>' +
|
||||
"<a href=#{"/#{board}/res/#{threadID}#p#{postID}"}>No.</a>" +
|
||||
"<a href='#{
|
||||
if g.REPLY and g.THREAD_ID is threadID
|
||||
"javascript:quote(#{postID})"
|
||||
else
|
||||
"/#{board}/res/#{threadID}#q#{postID}"
|
||||
}'>#{postID}</a>" +
|
||||
'</em></span>' +
|
||||
'</div>' +
|
||||
|
||||
(if isOP then fileHTML else '') +
|
||||
|
||||
"<div class='postInfo desktop' id=pi#{postID}>" +
|
||||
"<input type=checkbox name=#{postID} value=delete> " +
|
||||
"#{subject} " +
|
||||
"<span class='nameBlock#{capcodeClass}'>" +
|
||||
emailStart +
|
||||
"<span class=name>#{name or ''}</span>" + tripcode +
|
||||
capcodeStart + emailEnd + capcode + userID + flag + sticky + closed +
|
||||
' </span> ' +
|
||||
"<span class=dateTime data-utc=#{dateUTC}>#{date}</span> " +
|
||||
"<span class='postNum desktop'>" +
|
||||
"<a href=#{"/#{board}/res/#{threadID}#p#{postID}"} title='Highlight this post'>No.</a>" +
|
||||
"<a href='#{
|
||||
if g.REPLY and g.THREAD_ID is threadID
|
||||
"javascript:quote(#{postID})"
|
||||
else
|
||||
"/#{board}/res/#{threadID}#q#{postID}"
|
||||
}' title='Quote this post'>#{postID}</a>" +
|
||||
'</span>' +
|
||||
'</div>' +
|
||||
|
||||
(if isOP then '' else fileHTML) +
|
||||
|
||||
"<blockquote class=postMessage id=m#{postID}>#{comment or ''}</blockquote> " +
|
||||
|
||||
'</div>'
|
||||
|
||||
for quote in $$ '.quotelink', container
|
||||
href = quote.getAttribute 'href'
|
||||
continue if href[0] is '/' # Cross-board quote, or board link
|
||||
quote.href = "/#{board}/res/#{href}" # Fix pathnames
|
||||
|
||||
container
|
||||
|
||||
@ -1213,7 +1353,7 @@ Get =
|
||||
|
||||
root.textContent = "Loading post No.#{postID}..."
|
||||
if threadID
|
||||
$.cache "/#{board}/res/#{threadID}", ->
|
||||
$.cache "//api.4chan.org/#{board}/res/#{threadID}.json", ->
|
||||
Get.fetchedPost @, board, threadID, postID, root, context
|
||||
else if url = Redirect.post board, postID
|
||||
$.cache url, ->
|
||||
@ -1242,43 +1382,37 @@ Get =
|
||||
# The thread can die by the time we check a quote.
|
||||
if url = Redirect.post board, postID
|
||||
$.cache url, ->
|
||||
Get.archivedPost @, board, postID, root
|
||||
Get.archivedPost @, board, postID, root, context
|
||||
else
|
||||
$.addClass root, 'warning'
|
||||
root.textContent =
|
||||
if status is 404
|
||||
"Thread No.#{threadID} has not been found."
|
||||
"Thread No.#{threadID} 404'd."
|
||||
else
|
||||
"Error #{req.status}: #{req.statusText}."
|
||||
return
|
||||
|
||||
doc = d.implementation.createHTMLDocument ''
|
||||
doc.documentElement.innerHTML = req.response
|
||||
|
||||
unless pc = doc.getElementById "pc#{postID}"
|
||||
posts = JSON.parse(req.response).posts
|
||||
if spoilerRange = posts[0].custom_spoiler
|
||||
Build.spoilerRange[board] = spoilerRange
|
||||
postID = +postID
|
||||
for post in posts
|
||||
break if post.no is postID # we found it!
|
||||
if post.no > postID
|
||||
# The post can be deleted by the time we check a quote.
|
||||
if url = Redirect.post board, postID
|
||||
$.cache url, ->
|
||||
Get.archivedPost @, board, postID, root
|
||||
Get.parseArchivedPost @, board, postID, root, context
|
||||
else
|
||||
$.addClass root, 'warning'
|
||||
root.textContent = "Post No.#{postID} has not been found."
|
||||
root.textContent = "Post No.#{postID} was not found."
|
||||
return
|
||||
pc = d.importNode pc, true
|
||||
|
||||
for quote in $$ '.quotelink', pc
|
||||
href = quote.getAttribute 'href'
|
||||
continue if href[0] is '/' # Cross-board quote, or board link
|
||||
quote.href = "/#{board}/res/#{href}" # Fix pathnames
|
||||
link = $ 'a[title="Highlight this post"]', pc
|
||||
link.href = "/#{board}/res/#{threadID}#p#{postID}"
|
||||
link.nextSibling.href = "/#{board}/res/#{threadID}#q#{postID}"
|
||||
|
||||
board = g.boards[board] or
|
||||
new Board board
|
||||
thread = g.threads["#{board}.#{threadID}"] or
|
||||
new Thread threadID, board
|
||||
post = new Post pc, thread, board
|
||||
post = new Post Build.postFromObject(post, board), thread, board
|
||||
Main.callbackNodes Post, [post]
|
||||
Get.insert post, root, context
|
||||
archivedPost: (req, board, postID, root, context) ->
|
||||
@ -1332,42 +1466,46 @@ Get =
|
||||
comment = bq.innerHTML.replace /(^|>)(>[^<$]+)(<|$)/g, '$1<span class=quote>$2</span>$3'
|
||||
|
||||
threadID = data.thread_num
|
||||
postContainer = Build.post
|
||||
o =
|
||||
# id
|
||||
postID: postID
|
||||
threadID: threadID
|
||||
board: board
|
||||
# info
|
||||
name: data.name
|
||||
capcode: data.capcode
|
||||
name: data.name_processed
|
||||
capcode: switch data.capcode
|
||||
when 'M' then 'mod'
|
||||
when 'A' then 'admin'
|
||||
when 'D' then 'developer'
|
||||
tripcode: data.trip
|
||||
uniqueID: data.poster_hash
|
||||
email: data.email
|
||||
subject: data.title
|
||||
flag: data.poster_country
|
||||
# XXX flagTitle: data.???
|
||||
email: encodeURIComponent data.email
|
||||
subject: data.title_processed
|
||||
flagCode: data.poster_country
|
||||
flagName: data.poster_country_name_processed
|
||||
date: data.fourchan_date
|
||||
dateUTC: data.timestamp
|
||||
comment: comment
|
||||
# file
|
||||
file:
|
||||
name: data.media_filename
|
||||
origin: data.media_orig
|
||||
if data.media_filename
|
||||
o.file =
|
||||
name: data.media_filename_processed
|
||||
timestamp: data.media_orig
|
||||
url: data.media_link or data.remote_media_link
|
||||
height: data.media_h
|
||||
width: data.media_w
|
||||
isSpoiler: data.spoiler is '1'
|
||||
MD5: data.media_hash
|
||||
size: data.media_size
|
||||
turl: data.thumb_link or "//thumbs.4chan.org/#{board}/thumb/#{data.preview_orig}"
|
||||
theight: data.preview_h
|
||||
twidth: data.preview_w
|
||||
isSpoiler: data.spoiler is '1'
|
||||
|
||||
board = g.boards[board] or
|
||||
new Board board
|
||||
thread = g.threads["#{board}.#{threadID}"] or
|
||||
new Thread threadID, board
|
||||
post = new Post postContainer, thread, board,
|
||||
post = new Post Build.post(o, true), thread, board,
|
||||
isArchived: true
|
||||
Main.callbackNodes Post, [post]
|
||||
Get.insert post, root, context
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user