Merge branch 'mayhem' into v3

Conflicts:
	CHANGELOG.md
	package.json
	src/General/Build.coffee
	src/General/Index.coffee
	src/General/Main.coffee
	src/General/lib/post.class
	src/Monitoring/ThreadStats.coffee
This commit is contained in:
Zixaphir 2014-05-03 02:45:58 -07:00
commit a1601d8825
15 changed files with 116 additions and 92 deletions

View File

@ -95,10 +95,6 @@ module.exports = (grunt) ->
push: false
shell:
options:
stdout: true
stderr: true
failOnError: true
checkout:
command: 'git checkout <%= pkg.meta.mainBranch %>'
commit:

View File

@ -1175,7 +1175,7 @@
Post.prototype.parseQuote = function(quotelink) {
var fullID, match;
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/(?:res|thread)\/\d+#p(\d+)$/))) {
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/(res|thread)\/\d+(.*)?\#p(\d+)$/))) {
return;
}
this.nodes.quotelinks.push(quotelink);
@ -1189,7 +1189,7 @@
};
Post.prototype.parseFile = function(that) {
var anchor, fileEl, fileText, nameNode, size, thumb, unit, _ref;
var anchor, fileEl, fileText, nameNode, size, thumb, unit;
if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) {
return;
}
@ -1213,7 +1213,7 @@
this.file.isImage = /(jpg|png|gif)$/i.test(this.file.URL);
this.file.isVideo = /webm$/i.test(this.file.URL);
if (this.file.isImage || this.file.isVideo) {
this.file.dimensions = (_ref = fileText.childNodes[2].textContent.match(/\d+x\d+/)) != null ? _ref[0] : void 0;
this.file.dimensions = fileText.childNodes[2].data.match(/\d+x\d+/)[0];
}
return this.file.name = !this.file.isSpoiler && (nameNode = $('a', fileText)) ? nameNode.title || nameNode.textContent : fileText.title;
};
@ -1225,7 +1225,7 @@
node = _ref[_i];
$.rm(node);
}
_ref1 = $$('[id]', post);
_ref1 = $$('[id]:not(.exif)', post);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
node = _ref1[_j];
node.removeAttribute('id');
@ -2926,8 +2926,8 @@
toggleHiddenThreads: function() {
$('#hidden-toggle a', Index.navLinks).textContent = (Index.showHiddenThreads = !Index.showHiddenThreads) ? 'Hide' : 'Show';
Index.sort();
if (Conf['Index Mode'] === 'paged' && Index.getCurrentPage() > 0) {
return Index.pageNav(0);
if (Conf['Index Mode'] === 'paged' && Index.getCurrentPage() > 1) {
return Index.pageNav(1);
} else {
return Index.buildIndex();
}
@ -3010,7 +3010,7 @@
if (Index.cb.indexNav(a, true)) {
return;
}
return Index.userPageNav(+a.pathname.split('/')[2]);
return Index.userPageNav(+a.pathname.split('/')[2] || 1);
},
headerNav: function(e) {
var a, needChange, onSameIndex;
@ -3077,7 +3077,7 @@
if (Index.currentPage === pageNum && !Index.root.parentElement) {
return;
}
Navigate.pushState(pageNum === 0 ? './' : pageNum);
Navigate.pushState(pageNum === 1 ? './' : pageNum);
return Index.pageLoad(pageNum);
},
pageLoad: function(pageNum) {
@ -3322,7 +3322,7 @@
var err, thread, threadRoot;
threadRoot = Build.thread(g.BOARD, threadData);
if (thread = g.BOARD.threads[threadData.no]) {
thread.setPage(Math.floor(i / Index.threadsNumPerPage));
thread.setPage(Math.floor(i / Index.threadsNumPerPage) + 1);
thread.setCount('post', threadData.replies + 1, threadData.bumplimit);
thread.setCount('file', threadData.images + !!threadData.ext, threadData.imagelimit);
thread.setStatus('Sticky', !!threadData.sticky);
@ -3517,7 +3517,7 @@
switch (Conf['Index Mode']) {
case 'paged':
case 'infinite':
pageNum = Index.getCurrentPage();
pageNum = Index.getCurrentPage() - 1;
threadsPerPage = Index.getThreadsNumPerPage();
threads = [];
i = threadsPerPage * pageNum;
@ -3645,6 +3645,17 @@
return n = (n + 1) % 3;
};
})(),
path: function(boardID, threadID, postID, fragment) {
var path;
path = "/" + boardID + "/thread/" + threadID;
if ((g.SLUG != null) && threadID === g.THREADID) {
path += "/" + g.SLUG;
}
if (postID) {
path += "#" + (fragment || 'p') + postID;
}
return path;
},
postFromObject: function(data, boardID) {
var o;
o = {
@ -3759,9 +3770,9 @@
sticky = isSticky ? " <img src=" + staticPath + "sticky" + gifIcon + " title=Sticky class=stickyIcon>" : '';
closed = isClosed ? " <img src=" + staticPath + "closed" + gifIcon + " title=Closed class=closedIcon>" : '';
if (isOP && g.VIEW === 'index') {
pageNum = Math.floor(Index.liveThreadData.keys.indexOf("" + postID) / Index.threadsNumPerPage);
pageNum = Math.floor(Index.liveThreadData.keys.indexOf("" + postID) / Index.threadsNumPerPage) + 1;
pageIcon = " <span class=page-num title='This thread is on page " + pageNum + " in the original index.'>Page " + pageNum + "</span>";
replyLink = " &nbsp; <span>[<a href='/" + boardID + "/thread/" + threadID + "' class=replylink>Reply</a>]</span>";
replyLink = " &nbsp; <span>[<a href='" + (Build.path(boardID, threadID)) + "' class=replylink>Reply</a>]</span>";
} else {
pageIcon = '';
replyLink = '';
@ -3769,19 +3780,16 @@
container = $.el('div', {
id: "pc" + postID,
className: "postContainer " + (isOP ? 'op' : 'reply') + "Container",
innerHTML: (isOP ? '' : "<div class=sideArrows>&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + (isOP ? fileHTML : '') + "<div class=postInfo>" + ("<input type=checkbox name=" + postID + " value=delete> ") + ("<span class=subject>" + (subject || '') + "</span> ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcodeIcon + userID + flag + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum'>" + ("<a href=" + ("/" + boardID + "/thread/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/thread/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + pageIcon + sticky + closed + replyLink + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage>" + (comment || '') + "</blockquote> ") + '</div>'
innerHTML: (isOP ? '' : "<div class=sideArrows>&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + (isOP ? fileHTML : '') + "<div class=postInfo>" + ("<input type=checkbox name=" + postID + " value=delete> ") + ("<span class=subject>" + (subject || '') + "</span> ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcodeIcon + userID + flag + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum'>" + ("<a href=" + (Build.path(boardID, threadID, postID)) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === threadID ? "javascript:quote(" + postID + ")" : Build.path(boardID, threadID, postID, 'q')) + "' title='Quote this post'>" + postID + "</a>") + pageIcon + sticky + closed + replyLink + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage>" + (comment || '') + "</blockquote> ") + '</div>'
});
_ref = $$('.quotelink', container);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
quote = _ref[_i];
href = quote.getAttribute('href');
if (href[0] === '/') {
if (href[0] !== '#') {
continue;
}
if (href[0] === '#') {
href = "" + threadID + href;
}
quote.href = "/" + boardID + "/thread/" + href;
quote.href = Build.path(boardID, threadID, href.slice(2));
}
return container;
},
@ -3796,7 +3804,7 @@
return $.el('a', {
className: 'summary',
textContent: text.join(' '),
href: "/" + boardID + "/thread/" + threadID
href: Build.path(boardID, threadID)
});
},
thread: function(board, data, full) {
@ -3832,12 +3840,12 @@
data = Index.liveThreadData[thread.ID];
postCount = data.replies + 1;
fileCount = data.images + !!data.ext;
pageCount = Math.floor(Index.liveThreadData.keys.indexOf("" + thread.ID) / Index.threadsNumPerPage);
pageCount = Math.floor(Index.liveThreadData.keys.indexOf("" + thread.ID) / Index.threadsNumPerPage) + 1;
subject = thread.OP.info.subject ? "<div class='subject'>" + thread.OP.info.subject + "</div>" : '';
comment = thread.OP.nodes.comment.innerHTML.replace(/(<br>\s*){2,}/g, '<br>');
root = $.el('div', {
className: 'catalog-thread',
innerHTML: "<a href=\"/" + thread.board + "/thread/" + thread.ID + "\" class=\"thumb\"></a><div class=\"thread-stats\" title=\"Post count / File count / Page count\"><span class=\"post-count\">" + postCount + "</span> / <span class=\"file-count\">" + fileCount + "</span> / <span class=\"page-count\">" + pageCount + "</span><span class=\"thread-icons\"></span></div>" + subject + "<div class=\"comment\">" + comment + "</div>"
innerHTML: "<a href=\"" + (Build.path(thread.board.ID, thread.ID)) + "\" class=\"thumb\"></a><div class=\"thread-stats\" title=\"Post count / File count / Page count\"><span class=\"post-count\">" + postCount + "</span> / <span class=\"file-count\">" + fileCount + "</span> / <span class=\"page-count\">" + pageCount + "</span><span class=\"thread-icons\"></span></div>" + subject + "<div class=\"comment\">" + comment + "</div>"
});
root.dataset.fullID = thread.fullID;
if (thread.isPinned) {
@ -5316,7 +5324,7 @@
var a, frag, hash, text;
frag = QuoteBacklink.frag.cloneNode(true);
a = frag.lastElementChild;
a.href = "/" + quoter.board + "/thread/" + quoter.thread + "#p" + quoter;
a.href = Build.path(quoter.board.ID, quoter.thread.ID, quoter.ID);
a.textContent = text = QuoteBacklink.funk(quoter.ID);
if (quoter.isDead) {
$.addClass(a, 'deadlink');
@ -5888,7 +5896,7 @@
quoteID = "" + boardID + "." + postID;
if (post = g.posts[quoteID]) {
a = $.el('a', {
href: "/" + boardID + "/thread/" + post.thread + "#p" + postID,
href: Build.path(boardID, post.thread.ID, postID),
className: post.isDead ? 'quotelink deadlink' : 'quotelink',
textContent: quote
});
@ -6222,7 +6230,7 @@
_ref = $$('br', frag);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
if (node !== frag.lastElementChild) {
if (node !== frag.lastChild) {
$.replace(node, $.tn('\n>'));
}
}
@ -6910,7 +6918,7 @@
isReply: isReply,
threadID: threadID
});
URL = threadID === postID ? "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0;
URL = threadID === postID ? Build.path(g.BOARD.ID, threadID) : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? Build.path(g.BOARD.ID, threadID, postID) : void 0;
if (URL) {
if (Conf['Open Post in New Tab']) {
$.open(URL);
@ -11120,7 +11128,7 @@
}
return Redirect.data = o;
},
archives: [{"uid":0,"name":"Foolz","domain":"archive.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["a","biz","co","diy","gd","jp","m","sci","sp","tg","tv","vg","vp","vr","wsg"],"files":["a","biz","gd","diy","jp","m","sci","tg","vg","vp","vr","wsg"]},{"uid":1,"name":"NSFW Foolz","domain":"nsfw.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["u"],"files":["u"]},{"uid":2,"name":"The Dark Cave","domain":"archive.thedarkcave.org","http":true,"https":true,"software":"foolfuuka","boards":["c","int","out","po"],"files":["c","po"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":18,"name":"4plebs Flash Archive","domain":"flash.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["f"],"files":["f"]},{"uid":4,"name":"Nyafuu","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","w","wg"],"files":["c","e","w","wg"]},{"uid":5,"name":"Love is Over","domain":"loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["d","i"],"files":["d","i"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":true,"https":true,"software":"fuuka","boards":["cgl","g","mu","w"],"files":["cgl","g","mu","w"]},{"uid":9,"name":"Heinessen","domain":"archive.heinessen.com","http":true,"https":false,"software":"fuuka","boards":["an","fit","k","mlp","r9k","toy"],"files":["an","fit","k","r9k","toy"]},{"uid":10,"name":"warosu","domain":"fuuka.warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.eu","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","r","s","soc","y"]},{"uid":16,"name":"maware","domain":"archive.mawa.re","http":true,"https":false,"software":"foolfuuka","boards":["t"],"files":["t"]},{"uid":17,"name":"installgentoo.com","domain":"chan.installgentoo.com","http":true,"https":false,"software":"foolfuuka","boards":["g","t"],"files":["g","t"]},{"uid":13,"name":"Foolz Beta","domain":"beta.foolz.us","http":true,"https":true,"withCredentials":true,"software":"foolfuuka","boards":["a","biz","co","d","diy","gd","jp","m","s4s","sci","sp","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","d","diy","gd","jp","m","s4s","sci","tg","u","vg","vp","vr","wsg"]}],
archives: [{"uid":0,"name":"Foolz","domain":"archive.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["a","biz","co","diy","gd","jp","m","sci","sp","tg","tv","vg","vp","vr","wsg"],"files":["a","biz","gd","diy","jp","m","sci","tg","vg","vp","vr","wsg"]},{"uid":1,"name":"NSFW Foolz","domain":"nsfw.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["u"],"files":["u"]},{"uid":2,"name":"The Dark Cave","domain":"archive.thedarkcave.org","http":true,"https":true,"software":"foolfuuka","boards":["c","int","out","po"],"files":["c","po"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":18,"name":"4plebs Flash Archive","domain":"flash.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["f"],"files":["f"]},{"uid":4,"name":"Nyafuu","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","w","wg"],"files":["c","e","w","wg"]},{"uid":5,"name":"Love is Over","domain":"loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["d","i"],"files":["d","i"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":true,"https":true,"software":"fuuka","boards":["cgl","g","mu","w"],"files":["cgl","g","mu","w"]},{"uid":9,"name":"Heinessen","domain":"archive.heinessen.com","http":true,"https":false,"software":"fuuka","boards":["an","fit","k","mlp","r9k","toy"],"files":["an","fit","k","r9k","toy"]},{"uid":10,"name":"warosu","domain":"fuuka.warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.eu","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","r","s","soc","y"]},{"uid":16,"name":"maware","domain":"archive.mawa.re","http":true,"https":false,"software":"foolfuuka","boards":["t"],"files":["t"]},{"uid":17,"name":"installgentoo.com","domain":"chan.installgentoo.com","http":true,"https":false,"software":"foolfuuka","boards":["g","t"],"files":["g","t"]},{"uid":13,"name":"Foolz Beta","domain":"beta.foolz.us","http":true,"https":true,"withCredentials":true,"software":"foolfuuka","boards":["a","biz","co","d","diy","gd","jp","m","s4s","sci","sp","tg","tv","u","vg","vp","vr","wsg"],"files":["a","biz","d","diy","gd","jp","m","s4s","sci","tg","u","vg","vp","vr","wsg"]}],
to: function(dest, data) {
var archive;
archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID];
@ -12419,7 +12427,7 @@
if (g.VIEW !== 'index') {
return;
}
url = "/" + thread.board + "/thread/" + thread;
url = Build.path(thread.board.ID, thread.ID);
if (tab) {
return $.open(url);
} else {
@ -13825,7 +13833,10 @@
}
if (g.VIEW === 'thread') {
g.THREADID = +pathname[3];
if (pathname[2] !== 'thread' || pathname.length > 4) {
if (pathname[4] != null) {
g.SLUG = pathname[4];
}
if (pathname[2] !== 'thread') {
pathname[2] = 'thread';
history.replaceState(null, '', pathname.slice(0, 4).join('/') + location.hash);
}

View File

@ -1231,7 +1231,7 @@
Post.prototype.parseQuote = function(quotelink) {
var fullID, match;
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/(?:res|thread)\/\d+#p(\d+)$/))) {
if (!(match = quotelink.href.match(/boards\.4chan\.org\/([^\/]+)\/(res|thread)\/\d+(.*)?\#p(\d+)$/))) {
return;
}
this.nodes.quotelinks.push(quotelink);
@ -1245,7 +1245,7 @@
};
Post.prototype.parseFile = function(that) {
var anchor, fileEl, fileText, nameNode, size, thumb, unit, _ref, _ref1;
var anchor, fileEl, fileText, nameNode, size, thumb, unit, _ref;
if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) {
return;
}
@ -1269,10 +1269,10 @@
this.file.isImage = /(jpg|png|gif)$/i.test(this.file.URL);
this.file.isVideo = /webm$/i.test(this.file.URL);
if (this.file.isImage || this.file.isVideo) {
this.file.dimensions = (_ref = fileText.childNodes[2].textContent.match(/\d+x\d+/)) != null ? _ref[0] : void 0;
this.file.dimensions = fileText.childNodes[2].data.match(/\d+x\d+/)[0];
}
this.file.name = !this.file.isSpoiler && (nameNode = $('a', fileText)) ? nameNode.title || nameNode.textContent : fileText.title;
return this.file.name = (_ref1 = this.file.name) != null ? _ref1.replace(/%22/g, '"') : void 0;
return this.file.name = (_ref = this.file.name) != null ? _ref.replace(/%22/g, '"') : void 0;
};
Post.prototype.cleanup = function(root, post) {
@ -1282,7 +1282,7 @@
node = _ref[_i];
$.rm(node);
}
_ref1 = $$('[id]', post);
_ref1 = $$('[id]:not(.exif)', post);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
node = _ref1[_j];
node.removeAttribute('id');
@ -2985,8 +2985,8 @@
toggleHiddenThreads: function() {
$('#hidden-toggle a', Index.navLinks).textContent = (Index.showHiddenThreads = !Index.showHiddenThreads) ? 'Hide' : 'Show';
Index.sort();
if (Conf['Index Mode'] === 'paged' && Index.getCurrentPage() > 0) {
return Index.pageNav(0);
if (Conf['Index Mode'] === 'paged' && Index.getCurrentPage() > 1) {
return Index.pageNav(1);
} else {
return Index.buildIndex();
}
@ -3069,7 +3069,7 @@
if (Index.cb.indexNav(a, true)) {
return;
}
return Index.userPageNav(+a.pathname.split('/')[2]);
return Index.userPageNav(+a.pathname.split('/')[2] || 1);
},
headerNav: function(e) {
var a, needChange, onSameIndex;
@ -3136,7 +3136,7 @@
if (Index.currentPage === pageNum && !Index.root.parentElement) {
return;
}
Navigate.pushState(pageNum === 0 ? './' : pageNum);
Navigate.pushState(pageNum === 1 ? './' : pageNum);
return Index.pageLoad(pageNum);
},
pageLoad: function(pageNum) {
@ -3381,7 +3381,7 @@
var err, thread, threadRoot;
threadRoot = Build.thread(g.BOARD, threadData);
if (thread = g.BOARD.threads[threadData.no]) {
thread.setPage(Math.floor(i / Index.threadsNumPerPage));
thread.setPage(Math.floor(i / Index.threadsNumPerPage) + 1);
thread.setCount('post', threadData.replies + 1, threadData.bumplimit);
thread.setCount('file', threadData.images + !!threadData.ext, threadData.imagelimit);
thread.setStatus('Sticky', !!threadData.sticky);
@ -3576,7 +3576,7 @@
switch (Conf['Index Mode']) {
case 'paged':
case 'infinite':
pageNum = Index.getCurrentPage();
pageNum = Index.getCurrentPage() - 1;
threadsPerPage = Index.getThreadsNumPerPage();
threads = [];
i = threadsPerPage * pageNum;
@ -3704,6 +3704,17 @@
return n = (n + 1) % 3;
};
})(),
path: function(boardID, threadID, postID, fragment) {
var path;
path = "/" + boardID + "/thread/" + threadID;
if ((g.SLUG != null) && threadID === g.THREADID) {
path += "/" + g.SLUG;
}
if (postID) {
path += "#" + (fragment || 'p') + postID;
}
return path;
},
postFromObject: function(data, boardID) {
var o;
o = {
@ -3818,9 +3829,9 @@
sticky = isSticky ? " <img src=" + staticPath + "sticky" + gifIcon + " title=Sticky class=stickyIcon>" : '';
closed = isClosed ? " <img src=" + staticPath + "closed" + gifIcon + " title=Closed class=closedIcon>" : '';
if (isOP && g.VIEW === 'index') {
pageNum = Math.floor(Index.liveThreadData.keys.indexOf("" + postID) / Index.threadsNumPerPage);
pageNum = Math.floor(Index.liveThreadData.keys.indexOf("" + postID) / Index.threadsNumPerPage) + 1;
pageIcon = " <span class=page-num title='This thread is on page " + pageNum + " in the original index.'>Page " + pageNum + "</span>";
replyLink = " &nbsp; <span>[<a href='/" + boardID + "/thread/" + threadID + "' class=replylink>Reply</a>]</span>";
replyLink = " &nbsp; <span>[<a href='" + (Build.path(boardID, threadID)) + "' class=replylink>Reply</a>]</span>";
} else {
pageIcon = '';
replyLink = '';
@ -3828,19 +3839,16 @@
container = $.el('div', {
id: "pc" + postID,
className: "postContainer " + (isOP ? 'op' : 'reply') + "Container",
innerHTML: (isOP ? '' : "<div class=sideArrows>&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + (isOP ? fileHTML : '') + "<div class=postInfo>" + ("<input type=checkbox name=" + postID + " value=delete> ") + ("<span class=subject>" + (subject || '') + "</span> ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcodeIcon + userID + flag + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum'>" + ("<a href=" + ("/" + boardID + "/thread/" + threadID + "#p" + postID) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === threadID ? "javascript:quote(" + postID + ")" : "/" + boardID + "/thread/" + threadID + "#q" + postID) + "' title='Quote this post'>" + postID + "</a>") + pageIcon + sticky + closed + replyLink + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage>" + (comment || '') + "</blockquote> ") + '</div>'
innerHTML: (isOP ? '' : "<div class=sideArrows>&gt;&gt;</div>") + ("<div id=p" + postID + " class='post " + (isOP ? 'op' : 'reply') + (capcode === 'admin_highlight' ? ' highlightPost' : '') + "'>") + (isOP ? fileHTML : '') + "<div class=postInfo>" + ("<input type=checkbox name=" + postID + " value=delete> ") + ("<span class=subject>" + (subject || '') + "</span> ") + ("<span class='nameBlock" + capcodeClass + "'>") + emailStart + ("<span class=name>" + (name || '') + "</span>") + tripcode + capcodeStart + emailEnd + capcodeIcon + userID + flag + ' </span> ' + ("<span class=dateTime data-utc=" + dateUTC + ">" + date + "</span> ") + "<span class='postNum'>" + ("<a href=" + (Build.path(boardID, threadID, postID)) + " title='Highlight this post'>No.</a>") + ("<a href='" + (g.VIEW === 'thread' && g.THREADID === threadID ? "javascript:quote(" + postID + ")" : Build.path(boardID, threadID, postID, 'q')) + "' title='Quote this post'>" + postID + "</a>") + pageIcon + sticky + closed + replyLink + '</span>' + '</div>' + (isOP ? '' : fileHTML) + ("<blockquote class=postMessage>" + (comment || '') + "</blockquote> ") + '</div>'
});
_ref = $$('.quotelink', container);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
quote = _ref[_i];
href = quote.getAttribute('href');
if (href[0] === '/') {
if (href[0] !== '#') {
continue;
}
if (href[0] === '#') {
href = "" + threadID + href;
}
quote.href = "/" + boardID + "/thread/" + href;
quote.href = Build.path(boardID, threadID, href.slice(2));
}
return container;
},
@ -3855,7 +3863,7 @@
return $.el('a', {
className: 'summary',
textContent: text.join(' '),
href: "/" + boardID + "/thread/" + threadID
href: Build.path(boardID, threadID)
});
},
thread: function(board, data, full) {
@ -3891,12 +3899,12 @@
data = Index.liveThreadData[thread.ID];
postCount = data.replies + 1;
fileCount = data.images + !!data.ext;
pageCount = Math.floor(Index.liveThreadData.keys.indexOf("" + thread.ID) / Index.threadsNumPerPage);
pageCount = Math.floor(Index.liveThreadData.keys.indexOf("" + thread.ID) / Index.threadsNumPerPage) + 1;
subject = thread.OP.info.subject ? "<div class='subject'>" + thread.OP.info.subject + "</div>" : '';
comment = thread.OP.nodes.comment.innerHTML.replace(/(<br>\s*){2,}/g, '<br>');
root = $.el('div', {
className: 'catalog-thread',
innerHTML: "<a href=\"/" + thread.board + "/thread/" + thread.ID + "\" class=\"thumb\"></a><div class=\"thread-stats\" title=\"Post count / File count / Page count\"><span class=\"post-count\">" + postCount + "</span> / <span class=\"file-count\">" + fileCount + "</span> / <span class=\"page-count\">" + pageCount + "</span><span class=\"thread-icons\"></span></div>" + subject + "<div class=\"comment\">" + comment + "</div>"
innerHTML: "<a href=\"" + (Build.path(thread.board.ID, thread.ID)) + "\" class=\"thumb\"></a><div class=\"thread-stats\" title=\"Post count / File count / Page count\"><span class=\"post-count\">" + postCount + "</span> / <span class=\"file-count\">" + fileCount + "</span> / <span class=\"page-count\">" + pageCount + "</span><span class=\"thread-icons\"></span></div>" + subject + "<div class=\"comment\">" + comment + "</div>"
});
root.dataset.fullID = thread.fullID;
if (thread.isPinned) {
@ -5368,7 +5376,7 @@
var a, frag, hash, text;
frag = QuoteBacklink.frag.cloneNode(true);
a = frag.lastElementChild;
a.href = "/" + quoter.board + "/thread/" + quoter.thread + "#p" + quoter;
a.href = Build.path(quoter.board.ID, quoter.thread.ID, quoter.ID);
a.textContent = text = QuoteBacklink.funk(quoter.ID);
if (quoter.isDead) {
$.addClass(a, 'deadlink');
@ -5940,7 +5948,7 @@
quoteID = "" + boardID + "." + postID;
if (post = g.posts[quoteID]) {
a = $.el('a', {
href: "/" + boardID + "/thread/" + post.thread + "#p" + postID,
href: Build.path(boardID, post.thread.ID, postID),
className: post.isDead ? 'quotelink deadlink' : 'quotelink',
textContent: quote
});
@ -6284,7 +6292,7 @@
_ref = $$('br', frag);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
if (node !== frag.lastElementChild) {
if (node !== frag.lastChild) {
$.replace(node, $.tn('\n>'));
}
}
@ -6953,7 +6961,7 @@
isReply: isReply,
threadID: threadID
});
URL = threadID === postID ? "/" + g.BOARD + "/thread/" + threadID : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0;
URL = threadID === postID ? Build.path(g.BOARD.ID, threadID) : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? Build.path(g.BOARD.ID, threadID, postID) : void 0;
if (URL) {
if (Conf['Open Post in New Tab']) {
$.open(URL);
@ -11134,7 +11142,7 @@
}
return Redirect.data = o;
},
archives: [{"uid":0,"name":"Foolz","domain":"archive.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["a","biz","co","diy","gd","jp","m","sci","sp","tg","tv","vg","vp","vr","wsg"],"files":["a","biz","gd","diy","jp","m","sci","tg","vg","vp","vr","wsg"]},{"uid":1,"name":"NSFW Foolz","domain":"nsfw.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["u"],"files":["u"]},{"uid":2,"name":"The Dark Cave","domain":"archive.thedarkcave.org","http":true,"https":true,"software":"foolfuuka","boards":["c","int","out","po"],"files":["c","po"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":18,"name":"4plebs Flash Archive","domain":"flash.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["f"],"files":["f"]},{"uid":4,"name":"Nyafuu","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","w","wg"],"files":["c","e","w","wg"]},{"uid":5,"name":"Love is Over","domain":"loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["d","i"],"files":["d","i"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":true,"https":true,"software":"fuuka","boards":["cgl","g","mu","w"],"files":["cgl","g","mu","w"]},{"uid":9,"name":"Heinessen","domain":"archive.heinessen.com","http":true,"https":false,"software":"fuuka","boards":["an","fit","k","mlp","r9k","toy"],"files":["an","fit","k","r9k","toy"]},{"uid":10,"name":"warosu","domain":"fuuka.warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.eu","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","r","s","soc","y"]},{"uid":16,"name":"maware","domain":"archive.mawa.re","http":true,"https":false,"software":"foolfuuka","boards":["t"],"files":["t"]},{"uid":17,"name":"installgentoo.com","domain":"chan.installgentoo.com","http":true,"https":false,"software":"foolfuuka","boards":["g","t"],"files":["g","t"]},{"uid":13,"name":"Foolz Beta","domain":"beta.foolz.us","http":true,"https":true,"withCredentials":true,"software":"foolfuuka","boards":["a","biz","co","d","diy","gd","jp","m","s4s","sci","sp","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","d","diy","gd","jp","m","s4s","sci","tg","u","vg","vp","vr","wsg"]}],
archives: [{"uid":0,"name":"Foolz","domain":"archive.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["a","biz","co","diy","gd","jp","m","sci","sp","tg","tv","vg","vp","vr","wsg"],"files":["a","biz","gd","diy","jp","m","sci","tg","vg","vp","vr","wsg"]},{"uid":1,"name":"NSFW Foolz","domain":"nsfw.foolz.us","http":true,"https":true,"software":"foolfuuka","boards":["u"],"files":["u"]},{"uid":2,"name":"The Dark Cave","domain":"archive.thedarkcave.org","http":true,"https":true,"software":"foolfuuka","boards":["c","int","out","po"],"files":["c","po"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":18,"name":"4plebs Flash Archive","domain":"flash.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["f"],"files":["f"]},{"uid":4,"name":"Nyafuu","domain":"archive.nyafuu.org","http":true,"https":true,"software":"foolfuuka","boards":["c","e","w","wg"],"files":["c","e","w","wg"]},{"uid":5,"name":"Love is Over","domain":"loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["d","i"],"files":["d","i"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":true,"https":true,"software":"fuuka","boards":["cgl","g","mu","w"],"files":["cgl","g","mu","w"]},{"uid":9,"name":"Heinessen","domain":"archive.heinessen.com","http":true,"https":false,"software":"fuuka","boards":["an","fit","k","mlp","r9k","toy"],"files":["an","fit","k","r9k","toy"]},{"uid":10,"name":"warosu","domain":"fuuka.warosu.org","http":false,"https":true,"software":"fuuka","boards":["3","biz","cgl","ck","diy","fa","g","ic","jp","lit","sci","tg","vr"],"files":["3","biz","cgl","ck","diy","fa","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.eu","http":true,"https":true,"software":"foolfuuka","boards":["asp","cm","h","hc","hm","n","p","r","s","soc","y"],"files":["asp","cm","h","hc","hm","n","p","r","s","soc","y"]},{"uid":16,"name":"maware","domain":"archive.mawa.re","http":true,"https":false,"software":"foolfuuka","boards":["t"],"files":["t"]},{"uid":17,"name":"installgentoo.com","domain":"chan.installgentoo.com","http":true,"https":false,"software":"foolfuuka","boards":["g","t"],"files":["g","t"]},{"uid":13,"name":"Foolz Beta","domain":"beta.foolz.us","http":true,"https":true,"withCredentials":true,"software":"foolfuuka","boards":["a","biz","co","d","diy","gd","jp","m","s4s","sci","sp","tg","tv","u","vg","vp","vr","wsg"],"files":["a","biz","d","diy","gd","jp","m","s4s","sci","tg","u","vg","vp","vr","wsg"]}],
to: function(dest, data) {
var archive;
archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID];
@ -12433,7 +12441,7 @@
if (g.VIEW !== 'index') {
return;
}
url = "/" + thread.board + "/thread/" + thread;
url = Build.path(thread.board.ID, thread.ID);
if (tab) {
return $.open(url);
} else {
@ -13842,7 +13850,10 @@
}
if (g.VIEW === 'thread') {
g.THREADID = +pathname[3];
if (pathname[2] !== 'thread' || pathname.length > 4) {
if (pathname[4] != null) {
g.SLUG = pathname[4];
}
if (pathname[2] !== 'thread') {
pathname[2] = 'thread';
history.replaceState(null, '', pathname.slice(0, 4).join('/') + location.hash);
}

View File

@ -105,7 +105,7 @@ a[href="javascript:;"] {
:root.bottom-header body {
margin-bottom: 2em;
}
body > .desktop:not(#boardNavDesktop):not(#boardNavDesktopFoot),
body > .desktop:not(hr):not(.navLinks):not(#boardNavDesktop):not(#boardNavDesktopFoot),
:root.fourchan-x #navtopright,
:root.fourchan-x #navbotright,
:root.fourchan-x:not(.show-original-top-board-list) #boardNavDesktop,

View File

@ -37,7 +37,7 @@
"grunt-contrib-concat": "~0.4.0",
"grunt-contrib-copy": "~0.5.0",
"grunt-contrib-watch": "~0.6.1",
"grunt-shell": "~0.6.4",
"grunt-shell": "~0.7.0",
"load-grunt-tasks": "~0.4.0"
},
"repository": {

View File

@ -123,6 +123,6 @@
"https": true,
"withCredentials": true,
"software": "foolfuuka",
"boards": ["a", "biz", "co", "d", "diy", "gd", "jp", "m", "s4s", "sci", "sp", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
"boards": ["a", "biz", "co", "d", "diy", "gd", "jp", "m", "s4s", "sci", "sp", "tg", "tv", "u", "vg", "vp", "vr", "wsg"],
"files": ["a", "biz", "d", "diy", "gd", "jp", "m", "s4s", "sci", "tg", "u", "vg", "vp", "vr", "wsg"]
}]

View File

@ -15,6 +15,11 @@ Build =
thumbRotate: do ->
n = 0
-> n = (n + 1) % 3
path: (boardID, threadID, postID, fragment) ->
path = "/#{boardID}/thread/#{threadID}"
path += "/#{g.SLUG}" if g.SLUG? and threadID is g.THREADID
path += "##{fragment or 'p'}#{postID}" if postID
path
postFromObject: (data, boardID) ->
o =
# id
@ -178,9 +183,9 @@ Build =
''
if isOP and g.VIEW is 'index'
pageNum = Index.liveThreadData.keys.indexOf("#{postID}") // Index.threadsNumPerPage
pageNum = Index.liveThreadData.keys.indexOf("#{postID}") // Index.threadsNumPerPage + 1
pageIcon = " <span class=page-num title='This thread is on page #{pageNum} in the original index.'>Page #{pageNum}</span>"
replyLink = " &nbsp; <span>[<a href='/#{boardID}/thread/#{threadID}' class=replylink>Reply</a>]</span>"
replyLink = " &nbsp; <span>[<a href='#{Build.path boardID, threadID}' class=replylink>Reply</a>]</span>"
else
pageIcon = ''
replyLink = ''
@ -209,12 +214,12 @@ Build =
' </span> ' +
"<span class=dateTime data-utc=#{dateUTC}>#{date}</span> " +
"<span class='postNum'>" +
"<a href=#{"/#{boardID}/thread/#{threadID}#p#{postID}"} title='Highlight this post'>No.</a>" +
"<a href=#{Build.path boardID, threadID, postID} title='Highlight this post'>No.</a>" +
"<a href='#{
if g.VIEW is 'thread' and g.THREADID is threadID
"javascript:quote(#{postID})"
else
"/#{boardID}/thread/#{threadID}#q#{postID}"
Build.path boardID, threadID, postID, 'q'
}' title='Quote this post'>#{postID}</a>" +
pageIcon + sticky + closed + replyLink +
'</span>' +
@ -226,12 +231,11 @@ Build =
'</div>'
# Fix pathnames
# Fix quote pathnames in index or cross-{board,thread} posts
for quote in $$ '.quotelink', container
href = quote.getAttribute 'href'
continue if href[0] is '/' # Cross-board quote, or board link
href = "#{threadID}#{href}" if href[0] is '#'
quote.href = "/#{boardID}/thread/#{href}" # Fix pathnames
continue unless href[0] is '#'
quote.href = Build.path boardID, threadID, href[2..]
container
@ -243,7 +247,7 @@ Build =
$.el 'a',
className: 'summary'
textContent: text.join ' '
href: "/#{boardID}/thread/#{threadID}"
href: Build.path boardID, threadID
thread: (board, data, full) ->
Build.spoilerRange[board] = data.custom_spoiler
@ -277,7 +281,7 @@ Build =
postCount = data.replies + 1
fileCount = data.images + !!data.ext
pageCount = Index.liveThreadData.keys.indexOf("#{thread.ID}") // Index.threadsNumPerPage
pageCount = Index.liveThreadData.keys.indexOf("#{thread.ID}") // Index.threadsNumPerPage + 1
subject = if thread.OP.info.subject
"<div class='subject'>#{thread.OP.info.subject}</div>"

View File

@ -301,8 +301,8 @@ Index =
else
'Show'
Index.sort()
if Conf['Index Mode'] is 'paged' and Index.getCurrentPage() > 0
Index.pageNav 0
if Conf['Index Mode'] is 'paged' and Index.getCurrentPage() > 1
Index.pageNav 1
else
Index.buildIndex()
@ -360,7 +360,7 @@ Index =
return
e.preventDefault()
return if Index.cb.indexNav a, true
Index.userPageNav +a.pathname.split('/')[2]
Index.userPageNav +a.pathname.split('/')[2] or 1
headerNav: (e) ->
a = e.target
@ -411,7 +411,7 @@ Index =
pageNav: (pageNum) ->
return if Index.currentPage is pageNum and not Index.root.parentElement
Navigate.pushState if pageNum is 0 then './' else pageNum
Navigate.pushState if pageNum is 1 then './' else pageNum
Index.pageLoad pageNum
pageLoad: (pageNum) ->
@ -603,7 +603,7 @@ Index =
Index.liveThreadData.forEach (threadData) ->
threadRoot = Build.thread g.BOARD, threadData
if thread = g.BOARD.threads[threadData.no]
thread.setPage i // Index.threadsNumPerPage
thread.setPage i // Index.threadsNumPerPage + 1
thread.setCount 'post', threadData.replies + 1, threadData.bumplimit
thread.setCount 'file', threadData.images + !!threadData.ext, threadData.imagelimit
thread.setStatus 'Sticky', !!threadData.sticky
@ -741,7 +741,7 @@ Index =
nodes = []
switch Conf['Index Mode']
when 'paged', 'infinite'
pageNum = Index.getCurrentPage()
pageNum = Index.getCurrentPage() - 1
threadsPerPage = Index.getThreadsNumPerPage()
threads = []

View File

@ -18,7 +18,8 @@ Main =
return Index.catalogSwitch()
if g.VIEW is 'thread'
g.THREADID = +pathname[3]
if pathname[2] isnt 'thread' or pathname.length > 4
g.SLUG = pathname[4] if pathname[4]?
if pathname[2] isnt 'thread'
pathname[2] = 'thread'
history.replaceState null, '', pathname.slice(0,4).join('/') + location.hash

View File

@ -1,4 +1,4 @@
<a href="/#{thread.board}/thread/#{thread.ID}" class="thumb"></a>
<a href="#{Build.path thread.board.ID, thread.ID}" class="thumb"></a>
<div class="thread-stats" title="Post count / File count / Page count">
<span class="post-count">#{postCount}</span> / <span class="file-count">#{fileCount}</span> / <span class="page-count">#{pageCount}</span>
<span class="thread-icons"></span>

View File

@ -101,8 +101,9 @@ class Post
return unless match = quotelink.href.match ///
boards\.4chan\.org/
([^/]+) # boardID
/(?:res|thread)/\d+#p
(\d+) # postID
/(res|thread)/\d+
(.*)? # thread slug
\#p(\d+) # postID
$
///
@ -138,7 +139,7 @@ class Post
@file.isImage = /(jpg|png|gif)$/i.test @file.URL
@file.isVideo = /webm$/i.test @file.URL
if @file.isImage or @file.isVideo
@file.dimensions = fileText.childNodes[2].textContent.match(/\d+x\d+/)?[0]
@file.dimensions = fileText.childNodes[2].data.match(/\d+x\d+/)[0]
@file.name = if !@file.isSpoiler and nameNode = $ 'a', fileText
nameNode.title or nameNode.textContent
else
@ -155,7 +156,7 @@ class Post
cleanup: (root, post) ->
for node in $$ '.mobile', root
$.rm node
for node in $$ '[id]', post
for node in $$ '[id]:not(.exif)', post
node.removeAttribute 'id'
for node in $$ '.desktop', root
$.rmClass node, 'desktop'

View File

@ -247,7 +247,7 @@ Keybinds =
open: (thread, tab) ->
return if g.VIEW isnt 'index'
url = "/#{thread.board}/thread/#{thread}"
url = Build.path thread.board.ID, thread.ID
if tab
$.open url
else

View File

@ -228,7 +228,7 @@ QR =
$.prepend frag, $.tn '[code]'
$.add frag, $.tn '[/code]'
for node in $$ 'br', frag
$.replace node, $.tn '\n>' unless node is frag.lastElementChild
$.replace node, $.tn '\n>' unless node is frag.lastChild
for node in $$ 's', frag
$.replace node, [$.tn('[spoiler]'), node.childNodes..., $.tn '[/spoiler]']
for node in $$ '.prettyprint', frag
@ -871,9 +871,9 @@ QR =
QR.cooldown.set {req, post, isReply, threadID}
URL = if threadID is postID # new thread
"/#{g.BOARD}/thread/#{threadID}"
Build.path g.BOARD.ID, threadID
else if g.VIEW is 'index' and !QR.cooldown.auto and Conf['Open Post in New Tab'] # replying from the index
"/#{g.BOARD}/thread/#{threadID}#p#{postID}"
Build.path g.BOARD.ID, threadID, postID
if URL
if Conf['Open Post in New Tab']
$.open URL

View File

@ -55,7 +55,7 @@ QuoteBacklink =
buildBacklink: (quoted, quoter) ->
frag = QuoteBacklink.frag.cloneNode true
a = frag.lastElementChild
a.href = "/#{quoter.board}/thread/#{quoter.thread}#p#{quoter}"
a.href = Build.path quoter.board.ID, quoter.thread.ID, quoter.ID
a.textContent = text = QuoteBacklink.funk quoter.ID
if quoter.isDead
$.addClass a, 'deadlink'

View File

@ -44,7 +44,7 @@ Quotify =
# Don't add 'deadlink' when quotifying in an archived post,
# and we don't know if the post died yet.
a = $.el 'a',
href: "/#{boardID}/thread/#{post.thread}#p#{postID}"
href: Build.path boardID, post.thread.ID, postID
className: if post.isDead then 'quotelink deadlink' else 'quotelink'
textContent: quote
$.extend a.dataset, {boardID, threadID: post.thread.ID, postID}