merge mayhem master

This commit is contained in:
James Campos 2012-03-22 11:42:10 -07:00
commit 0cce896b1a
3 changed files with 85 additions and 84 deletions

View File

@ -502,26 +502,23 @@
}, },
set: function(name, value) { set: function(name, value) {
name = Main.namespace + name; name = Main.namespace + name;
localStorage[name] = JSON.stringify(value); localStorage.setItem(name, JSON.stringify(value));
return GM_setValue(name, JSON.stringify(value)); return GM_setValue(name, JSON.stringify(value));
} }
} : { } : {
"delete": function(name) { "delete": function(name) {
name = Main.namespace + name; return localStorage.removeItem(Main.namespace + name);
return delete localStorage[name];
}, },
get: function(name, defaultValue) { get: function(name, defaultValue) {
var value; var value;
name = Main.namespace + name; if (value = localStorage.getItem(Main.namespace + name)) {
if (value = localStorage[name]) {
return JSON.parse(value); return JSON.parse(value);
} else { } else {
return defaultValue; return defaultValue;
} }
}, },
set: function(name, value) { set: function(name, value) {
name = Main.namespace + name; return localStorage.setItem(Main.namespace + name, JSON.stringify(value));
return localStorage[name] = JSON.stringify(value);
} }
}); });
@ -585,6 +582,7 @@
node: function(post) { node: function(post) {
var el, filter, firstThread, isOP, key, result, thisThread, value, _i, _len, _ref; var el, filter, firstThread, isOP, key, result, thisThread, value, _i, _len, _ref;
if (post.isInlined) return; if (post.isInlined) return;
post.isOP = post["class"] === 'op';
isOP = post.isOP, el = post.el; isOP = post.isOP, el = post.el;
for (key in Filter.filters) { for (key in Filter.filters) {
value = Filter[key](post); value = Filter[key](post);
@ -727,7 +725,7 @@
})); }));
}, },
parse: function(req, a, threadID, replyID) { parse: function(req, a, threadID, replyID) {
var doc, node, post, quote, quotes, _i, _len; var doc, href, node, post, quote, quotes, _i, _len;
if (req.status !== 200) { if (req.status !== 200) {
a.textContent = "" + req.status + " " + req.statusText; a.textContent = "" + req.status + " " + req.statusText;
return; return;
@ -739,8 +737,10 @@
quotes = node.getElementsByClassName('quotelink'); quotes = node.getElementsByClassName('quotelink');
for (_i = 0, _len = quotes.length; _i < _len; _i++) { for (_i = 0, _len = quotes.length; _i < _len; _i++) {
quote = quotes[_i]; quote = quotes[_i];
if (quote.hash === quote.getAttribute('href')) { if (quote.hash === (href = quote.getAttribute('href'))) {
quote.pathname = "/" + g.BOARD + "/res/" + threadID; quote.pathname = "/" + g.BOARD + "/res/" + threadID;
} else if (href !== quote.href) {
quote.href = "res/" + href;
} }
} }
post = { post = {
@ -845,7 +845,7 @@
_ref2 = $$('.quotelink', table); _ref2 = $$('.quotelink', table);
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
quote = _ref2[_j]; quote = _ref2[_j];
if ((href = quote.getAttribute('href')) === quote.hash) { if (quote.hash === (href = quote.getAttribute('href'))) {
quote.pathname = pathname; quote.pathname = pathname;
} else if (href !== quote.href) { } else if (href !== quote.href) {
quote.href = "res/" + href; quote.href = "res/" + href;
@ -897,7 +897,7 @@
table.hidden = false; table.hidden = false;
$.rm(parent); $.rm(parent);
id = table.firstChild.firstChild.lastChild.id; id = table.firstChild.firstChild.lastChild.id;
_ref2 = $$(".quotelink[href='#" + id + "'], .backlink[href='#" + id + "']"); _ref2 = $$(".quotelink[href$='#" + id + "'], .backlink[href='#" + id + "']");
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
quote = _ref2[_j]; quote = _ref2[_j];
$.removeClass(quote, 'filtered'); $.removeClass(quote, 'filtered');
@ -2069,6 +2069,13 @@
req: 'response', req: 'response',
html: this.response html: this.response
}); });
},
onerror: function() {
return QR.message.send({
req: 'status',
ready: true,
banned: true
});
} }
}; };
opts = { opts = {
@ -2094,17 +2101,7 @@
'Content-Type': 'multipart/form-data;boundary=' + boundary 'Content-Type': 'multipart/form-data;boundary=' + boundary
}; };
} }
try { return QR.ajax = $.ajax(url, callbacks, opts);
return QR.ajax = $.ajax(url, callbacks, opts);
} catch (e) {
if (e.name === 'NETWORK_ERR') {
return QR.message.send({
req: 'status',
ready: true,
banned: true
});
}
}
} }
} }
}; };
@ -2416,7 +2413,7 @@
_ref = $$('.thread'); _ref = $$('.thread');
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
thread = _ref[_i]; thread = _ref[_i];
op = thread.firstChild; op = $('.op', thread);
a = $.el('a', { a = $.el('a', {
textContent: '[ - ]', textContent: '[ - ]',
href: 'javascript:;' href: 'javascript:;'
@ -2837,7 +2834,7 @@
var day, hour, min, month, year, _, _ref; var day, hour, min, month, year, _, _ref;
_ref = node.textContent.match(/(\d+)\/(\d+)\/(\d+)\(\w+\)(\d+):(\d+)/), _ = _ref[0], month = _ref[1], day = _ref[2], year = _ref[3], hour = _ref[4], min = _ref[5]; _ref = node.textContent.match(/(\d+)\/(\d+)\/(\d+)\(\w+\)(\d+):(\d+)/), _ = _ref[0], month = _ref[1], day = _ref[2], year = _ref[3], hour = _ref[4], min = _ref[5];
year = "20" + year; year = "20" + year;
month -= 1; month--;
hour = chanOffset + Number(hour); hour = chanOffset + Number(hour);
return new Date(year, month, day, hour, min); return new Date(year, month, day, hour, min);
}; };
@ -2851,6 +2848,7 @@
time = $.el('time', { time = $.el('time', {
textContent: ' ' + Time.funk(Time) + ' ' textContent: ' ' + Time.funk(Time) + ' '
}); });
time.setAttribute('datetime', Time.date.toISOString());
return $.replace(node, time); return $.replace(node, time);
}, },
foo: function() { foo: function() {
@ -2937,21 +2935,23 @@
return Main.callbacks.push(this.node); return Main.callbacks.push(this.node);
}, },
node: function(post) { node: function(post) {
var fullname, link, node, regexp, resolution, shortname, size, type, unit, _, _ref; var data, link, node, regexp, resolution, size, span, unit, _, _ref;
if (post["class"] === 'inline' || !(node = post.filesize)) return; if (post["class"] === 'inline' || !(node = post.filesize)) return;
type = node.childElementCount === 2 ? 0 : 1; regexp = /^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF)/;
regexp = type ? /^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF)/ : /^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF), <span title="(.+)">([^<]+)/; _ref = node.innerHTML.match(regexp), _ = _ref[0], link = _ref[1], size = _ref[2], unit = _ref[3], resolution = _ref[4];
_ref = node.innerHTML.match(regexp), _ = _ref[0], link = _ref[1], size = _ref[2], unit = _ref[3], resolution = _ref[4], fullname = _ref[5], shortname = _ref[6]; data = {
FileInfo.data = {
link: link, link: link,
size: size, size: size,
unit: unit, unit: unit,
resolution: resolution, resolution: resolution
fullname: fullname,
shortname: shortname,
type: type
}; };
return node.innerHTML = FileInfo.funks[type](FileInfo); if (span = $('span', node)) {
data.fullname = span.title;
data.shortname = span.textContent;
}
data.type = +(!span);
FileInfo.data = data;
return node.innerHTML = FileInfo.funks[data.type](FileInfo);
}, },
setFormats: function() { setFormats: function() {
var code, format, funks, i, param; var code, format, funks, i, param;
@ -3999,7 +3999,6 @@
"class": klass, "class": klass,
id: node.getElementsByTagName('input')[0].name, id: node.getElementsByTagName('input')[0].name,
threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).firstChild.id, threadId: g.THREAD_ID || $.x('ancestor::div[@class="thread"]', node).firstChild.id,
isOP: klass === 'op',
isInlined: /\binline\b/.test(klass), isInlined: /\binline\b/.test(klass),
filesize: node.getElementsByClassName('filesize')[0] || false, filesize: node.getElementsByClassName('filesize')[0] || false,
quotes: node.getElementsByClassName('quotelink'), quotes: node.getElementsByClassName('quotelink'),
@ -4061,10 +4060,7 @@ a[href="javascript:;"] {\
text-decoration: none;\ text-decoration: none;\
}\ }\
\ \
.block ~ .op,\ .block ~ *,\
.block ~ .omittedposts,\
.block ~ table,\
.block ~ br,\
#content > [name=tab]:not(:checked) + div,\ #content > [name=tab]:not(:checked) + div,\
#updater:not(:hover) > :not(.move),\ #updater:not(:hover) > :not(.move),\
#qp > input, #qp .inline, .forwarded {\ #qp > input, #qp .inline, .forwarded {\
@ -4290,12 +4286,12 @@ img[md5], img[md5] + img {\
/* revealed spoilers do not have height/width,\ /* revealed spoilers do not have height/width,\
this fixes "expanded" auto-gifs */\ this fixes "expanded" auto-gifs */\
img[md5] {\ img[md5] {\
max-height: 251px;\ max-height: 252px;\
max-width: 251px;\ max-width: 252px;\
}\ }\
input ~ a > img[md5] {\ input ~ a > img[md5] {\
max-height: 126px;\ max-height: 127px;\
max-width: 126px;\ max-width: 127px;\
}\ }\
\ \
#qr, #qp, #updater, #stats, #ihover, #overlay, #navlinks {\ #qr, #qp, #updater, #stats, #ihover, #overlay, #navlinks {\

View File

@ -7,4 +7,16 @@
- Clone 4chan X. - Clone 4chan X.
- `cd` into it and build with `cake build`. - `cd` into it and build with `cake build`.
- For development (continuous builds), run `cake dev &`. Kill the process with `killall node`. - For development (continuous builds), run `cake dev &`. Kill the process with `killall node`.
- Upgrade version with `cake -v VERSION upgrade`.
# Releasing
- Upgrade version with `cake -v VERSION upgrade`. Note that this is only used to
release new 4chan x versions, and is not needed or wanted in pull requests.
# Contributing
- Edit the CoffeeScript source
- Build the JavaScript
- If the edits affect regular users, edit the changelog
- Fork the repo
- Send a pull request

View File

@ -431,21 +431,18 @@ $.extend $,
set: (name, value) -> set: (name, value) ->
name = Main.namespace + name name = Main.namespace + name
# for `storage` events # for `storage` events
localStorage[name] = JSON.stringify value localStorage.setItem name, JSON.stringify value
GM_setValue name, JSON.stringify value GM_setValue name, JSON.stringify value
else else
delete: (name) -> delete: (name) ->
name = Main.namespace + name localStorage.removeItem Main.namespace + name
delete localStorage[name]
get: (name, defaultValue) -> get: (name, defaultValue) ->
name = Main.namespace + name if value = localStorage.getItem Main.namespace + name
if value = localStorage[name]
JSON.parse value JSON.parse value
else else
defaultValue defaultValue
set: (name, value) -> set: (name, value) ->
name = Main.namespace + name localStorage.setItem Main.namespace + name, JSON.stringify value
localStorage[name] = JSON.stringify value
$$ = (selector, root=d.body) -> $$ = (selector, root=d.body) ->
Array::slice.call root.querySelectorAll selector Array::slice.call root.querySelectorAll selector
@ -524,6 +521,7 @@ Filter =
node: (post) -> node: (post) ->
return if post.isInlined return if post.isInlined
post.isOP = post.class is 'op'
{isOP, el} = post {isOP, el} = post
for key of Filter.filters for key of Filter.filters
value = Filter[key] post value = Filter[key] post
@ -645,8 +643,10 @@ ExpandComment =
quotes = node.getElementsByClassName 'quotelink' quotes = node.getElementsByClassName 'quotelink'
for quote in quotes for quote in quotes
if quote.hash is quote.getAttribute 'href' if quote.hash is href = quote.getAttribute 'href' # Add pathname to in-thread quotes
quote.pathname = "/#{g.BOARD}/res/#{threadID}" quote.pathname = "/#{g.BOARD}/res/#{threadID}"
else if href isnt quote.href # Fix cross-thread links, not cross-board ones
quote.href = "res/#{href}"
post = post =
el: node el: node
threadId: threadID threadId: threadID
@ -725,9 +725,9 @@ ExpandThread =
for reply in $$ '.reply', doc for reply in $$ '.reply', doc
table = d.importNode reply.parentNode.parentNode.parentNode table = d.importNode reply.parentNode.parentNode.parentNode
for quote in $$ '.quotelink', table for quote in $$ '.quotelink', table
if (href = quote.getAttribute 'href') is quote.hash #add pathname to normal quotes if quote.hash is href = quote.getAttribute 'href' # Add pathname to in-thread quotes
quote.pathname = pathname quote.pathname = pathname
else if href isnt quote.href #fix x-thread links, not x-board ones else if href isnt quote.href # Fix cross-thread links, not cross-board ones
quote.href = "res/#{href}" quote.href = "res/#{href}"
link = $ '.quotejs', table link = $ '.quotejs', table
link.href = "res/#{thread.firstChild.id}##{reply.id}" link.href = "res/#{thread.firstChild.id}##{reply.id}"
@ -768,7 +768,7 @@ ReplyHiding =
table.hidden = false table.hidden = false
$.rm parent $.rm parent
id = table.firstChild.firstChild.lastChild.id id = table.firstChild.firstChild.lastChild.id
for quote in $$ ".quotelink[href='##{id}'], .backlink[href='##{id}']" for quote in $$ ".quotelink[href$='##{id}'], .backlink[href='##{id}']"
$.removeClass quote, 'filtered' $.removeClass quote, 'filtered'
delete g.hiddenReplies[id] delete g.hiddenReplies[id]
$.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies $.set "hiddenReplies/#{g.BOARD}/", g.hiddenReplies
@ -1744,6 +1744,9 @@ QR =
QR.message.send QR.message.send
req: 'response' req: 'response'
html: @response html: @response
onerror: ->
# CORS disabled error: redirecting to banned page ;_;
QR.message.send req: 'status', ready: true, banned: true
opts = opts =
form: form form: form
type: 'post' type: 'post'
@ -1760,12 +1763,7 @@ QR =
opts.headers = opts.headers =
'Content-Type': 'multipart/form-data;boundary=' + boundary 'Content-Type': 'multipart/form-data;boundary=' + boundary
try QR.ajax = $.ajax url, callbacks, opts
QR.ajax = $.ajax url, callbacks, opts
catch e
# CORS disabled error: redirecting to banned page ;_;
if e.name is 'NETWORK_ERR'
QR.message.send req: 'status', ready: true, banned: true
Options = Options =
init: -> init: ->
@ -2040,7 +2038,7 @@ ThreadHiding =
init: -> init: ->
hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {} hiddenThreads = $.get "hiddenThreads/#{g.BOARD}/", {}
for thread in $$ '.thread' for thread in $$ '.thread'
op = thread.firstChild op = $ '.op', thread
a = $.el 'a', a = $.el 'a',
textContent: '[ - ]' textContent: '[ - ]'
href: 'javascript:;' href: 'javascript:;'
@ -2405,7 +2403,7 @@ Time =
[_, month, day, year, hour, min] = [_, month, day, year, hour, min] =
node.textContent.match /(\d+)\/(\d+)\/(\d+)\(\w+\)(\d+):(\d+)/ node.textContent.match /(\d+)\/(\d+)\/(\d+)\(\w+\)(\d+):(\d+)/
year = "20#{year}" year = "20#{year}"
month -= 1 #months start at 0 month-- # Months start at 0
hour = chanOffset + Number hour hour = chanOffset + Number hour
new Date year, month, day, hour, min new Date year, month, day, hour, min
@ -2417,6 +2415,8 @@ Time =
Time.date = Time.parse node Time.date = Time.parse node
time = $.el 'time', time = $.el 'time',
textContent: ' ' + Time.funk(Time) + ' ' textContent: ' ' + Time.funk(Time) + ' '
# Set the datetime attribute, ISO'd.
time.setAttribute 'datetime', Time.date.toISOString()
$.replace node, time $.replace node, time
foo: -> foo: ->
code = Conf['time'].replace /%([A-Za-z])/g, (s, c) -> code = Conf['time'].replace /%([A-Za-z])/g, (s, c) ->
@ -2473,23 +2473,20 @@ FileInfo =
Main.callbacks.push @node Main.callbacks.push @node
node: (post) -> node: (post) ->
return if post.class is 'inline' or not node = post.filesize return if post.class is 'inline' or not node = post.filesize
type = if node.childElementCount is 2 then 0 else 1 regexp = /^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF)/
regexp = [_, link, size, unit, resolution] =
if type
/^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF)/
else
/^File: (<.+>)-\((?:Spoiler Image, )?([\d\.]+) (\w+), (\d+x\d+|PDF), <span title="(.+)">([^<]+)/
[_, link, size, unit, resolution, fullname, shortname] =
node.innerHTML.match regexp node.innerHTML.match regexp
FileInfo.data = data =
link: link link: link
size: size size: size
unit: unit unit: unit
resolution: resolution resolution: resolution
fullname: fullname if span = $ 'span', node
shortname: shortname data.fullname = span.title
type: type data.shortname = span.textContent
node.innerHTML = FileInfo.funks[type] FileInfo data.type = +!span
FileInfo.data = data
node.innerHTML = FileInfo.funks[data.type] FileInfo
setFormats: -> setFormats: ->
funks = [] funks = []
for i in [0..1] for i in [0..1]
@ -3363,7 +3360,6 @@ Main =
class: klass class: klass
id: node.getElementsByTagName('input')[0].name id: node.getElementsByTagName('input')[0].name
threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).firstChild.id threadId: g.THREAD_ID or $.x('ancestor::div[@class="thread"]', node).firstChild.id
isOP: klass is 'op'
isInlined: /\binline\b/.test klass isInlined: /\binline\b/.test klass
filesize: node.getElementsByClassName('filesize')[0] or false filesize: node.getElementsByClassName('filesize')[0] or false
quotes: node.getElementsByClassName 'quotelink' quotes: node.getElementsByClassName 'quotelink'
@ -3405,10 +3401,7 @@ a[href="javascript:;"] {
text-decoration: none; text-decoration: none;
} }
.block ~ .op, .block ~ *,
.block ~ .omittedposts,
.block ~ table,
.block ~ br,
#content > [name=tab]:not(:checked) + div, #content > [name=tab]:not(:checked) + div,
#updater:not(:hover) > :not(.move), #updater:not(:hover) > :not(.move),
#qp > input, #qp .inline, .forwarded { #qp > input, #qp .inline, .forwarded {
@ -3634,12 +3627,12 @@ img[md5], img[md5] + img {
/* revealed spoilers do not have height/width, /* revealed spoilers do not have height/width,
this fixes "expanded" auto-gifs */ this fixes "expanded" auto-gifs */
img[md5] { img[md5] {
max-height: 251px; max-height: 252px;
max-width: 251px; max-width: 252px;
} }
input ~ a > img[md5] { input ~ a > img[md5] {
max-height: 126px; max-height: 127px;
max-width: 126px; max-width: 127px;
} }
#qr, #qp, #updater, #stats, #ihover, #overlay, #navlinks { #qr, #qp, #updater, #stats, #ihover, #overlay, #navlinks {