Merge branch 'master' into filter

This commit is contained in:
ccd0 2015-04-24 18:41:25 -07:00
commit a2725a16de
29 changed files with 1074 additions and 611 deletions

View File

@ -2,8 +2,63 @@ Sometimes the changelog has notes (not comprehensive) acknowledging people's wor
The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x).
### v1.10.11
**v1.10.11.1** *(2015-04-24)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.11.1/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.11.1/builds/4chan-X-noupdate.crx "Chromium version")]
- Merge v1.10.10.3: Fix original post form not showing when JS is disabled.
**v1.10.11.0** *(2015-04-24)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.11.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.11.0/builds/4chan-X-noupdate.crx "Chromium version")]
- Based on v1.10.10.2.
- Fix whitespace being stripped from the comment before filtering. This makes it possible to filter whitespace spam.
### v1.10.10
**v1.10.10.3** *(2015-04-24)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.10.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.10.3/builds/4chan-X-noupdate.crx "Chromium version")]
- Fix original post form not showing when JS is disabled.
**v1.10.10.2** *(2015-04-21)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.10.2/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.10.2/builds/4chan-X-noupdate.crx "Chromium version")]
- Add focus indication to verify button in captcha popup.
**v1.10.10.1** *(2015-04-19)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.10.1/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.10.1/builds/4chan-X-noupdate.crx "Chromium version")]
- Merge v1.10.9.5: (thebladeee) Archive list: Transferred /w/ and /wg/ back to Nyafuu.
**v1.10.10.0** *(2015-04-18)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.10.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.10.0/builds/4chan-X-noupdate.crx "Chromium version")]
- Based on v1.10.9.4.
- Make images in image captcha selectable with arrow keys.
- Add `Captcha Fixes` option (on by default) to control whether 4chan X runs inside the Javascript-based captcha.
### v1.10.9
**v1.10.9.5** *(2015-04-19)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.5/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.5/builds/4chan-X-noupdate.crx "Chromium version")]
- (thebladeee) Archive list: Transferred /w/ and /wg/ back to Nyafuu.
**v1.10.9.4** *(2015-04-17)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.4/builds/4chan-X-noupdate.crx "Chromium version")]
- (Hasumi) Update archive.moe: Add /gif/.
**v1.10.9.3** *(2015-04-17)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.3/builds/4chan-X-noupdate.crx "Chromium version")]
- Resize report window as needed instead of opening it huge at beginning.
**v1.10.9.2** *(2015-04-16)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.2/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.2/builds/4chan-X-noupdate.crx "Chromium version")]
- (aCarbon) Normal report size box if pass is logged in.
- Clean up leftover Recaptcha iframes to prevent memory leak.
**v1.10.9.1** *(2015-04-15)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.1/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.1/builds/4chan-X-noupdate.crx "Chromium version")]
- Merge v1.10.8.11: Increase report window size to accomodate increasingly common image captchas.
- Fix report window closing before redirect.
**v1.10.9.0** *(2015-04-15)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.9.0/builds/4chan-X-noupdate.crx "Chromium version")]
- Based on v1.10.8.10.
- Support reporting posts to fgts archive.
- Add capcode to archive search menu.
### v1.10.8
**v1.10.8.11** *(2015-04-15)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.8.11/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.8.11/builds/4chan-X-noupdate.crx "Chromium version")]
- Increase report window size to accomodate increasingly common image captchas.
**v1.10.8.10** *(2015-04-13)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.8.10/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.8.10/builds/4chan-X-noupdate.crx "Chromium version")]
- Fix unwanted focusing on the submit button if you focus on the comment field too soon after entering the captcha.
**v1.10.8.9** *(2015-04-13)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.8.9/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.8.9/builds/4chan-X-noupdate.crx "Chromium version")]
- (fgts) Remove /fit/ from fgts archive.

View File

@ -1,4 +1,6 @@
path = require 'path'
crx = require 'crx'
JSZip = require 'jszip'
module.exports = (grunt) ->
grunt.util.linefeed = '\n'
@ -234,25 +236,6 @@ module.exports = (grunt) ->
]
tasks: 'build'
crx:
prod:
src: 'testbuilds/crx<%= pkg.meta.suffix[pkg.channel] %>/'
dest: 'testbuilds/<%= pkg.name %><%= pkg.meta.suffix[pkg.channel] %>.crx'
privateKey: '../<%= pkg.name %>-keys/<%= pkg.name %>.pem'
compress:
crx:
options:
archive: 'testbuilds/<%= pkg.name %><%= pkg.meta.suffix[pkg.channel] %>.crx.zip'
level: 9
pretty: true
expand: true
flatten: true
src: 'testbuilds/crx<%= pkg.meta.suffix[pkg.channel] %>/*'
dest: '/'
date: '<%= pkg.meta.date %>'
mode: parseInt('644', 8)
clean:
builds: 'builds'
testbuilds: 'testbuilds'
@ -335,7 +318,7 @@ module.exports = (grunt) ->
grunt.registerTask 'build-crx-channel', [
'concat:crx'
'copy:crx'
'compress:crx'
'zip-crx'
]
grunt.registerTask 'build-crx', [
@ -354,6 +337,17 @@ module.exports = (grunt) ->
'clean:tmpcrx'
]
grunt.registerTask 'zip-crx', 'Pack CRX contents in ZIP file', ->
pkg = grunt.config 'pkg'
zip = new JSZip()
for file in grunt.file.expand "testbuilds/crx#{pkg.meta.suffix[pkg.channel]}/*"
zip.file path.basename(file), grunt.file.read(file, {encoding: null}), {date: new Date(pkg.meta.date)}
output = zip.generate
type: 'nodebuffer'
compression: 'DEFLATE'
compressionOptions: {level: 9}
grunt.file.write "testbuilds/#{pkg.name}#{pkg.meta.suffix[pkg.channel]}.crx.zip", output
grunt.registerTask 'sign-channel', 'Sign CRX package', (channel) ->
done = @async()
pkg = grunt.config 'pkg'

Binary file not shown.

View File

@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X beta
// @version 1.10.8.9
// @version 1.10.11.1
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@ -11,6 +11,7 @@
// @match *://a.4cdn.org/*
// @match *://i.4cdn.org/*
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
// @grant GM_getValue
// @grant GM_setValue

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X beta
// @version 1.10.8.9
// @version 1.10.11.1
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@ -12,6 +12,7 @@
// @match *://a.4cdn.org/*
// @match *://i.4cdn.org/*
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
// @grant GM_getValue
// @grant GM_setValue
@ -109,7 +110,7 @@
'use strict';
(function() {
var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, Callbacks, Captcha, CatalogLinks, CatalogThread, Clone, Conf, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, E, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume, c, d, doc, g,
var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, Callbacks, Captcha, CatalogLinks, CatalogThread, Clone, Conf, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, E, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume, c, d, doc, g,
slice = [].slice,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@ -127,6 +128,7 @@
'Announcement Hiding': [true, 'Add button to hide 4chan announcements.'],
'Desktop Notifications': [true, 'Enables desktop notifications across various 4chan X features.'],
'404 Redirect': [true, 'Redirect dead threads and images to the archives.'],
'Archive Report': [true, 'Enable reporting posts to supported archives.'],
'Except Archives from Encryption': [false, 'Permit loading content from, and warningless redirects to, HTTP-only archives from HTTPS pages.'],
'Keybinds': [true, 'Bind actions to keyboard shortcuts.'],
'Time Formatting': [true, 'Localize and format timestamps.'],
@ -235,7 +237,8 @@
'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1],
'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1],
'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1],
'Bottom QR Link': [true, 'Places a link on the bottom of threads to open the QR.', 1]
'Bottom QR Link': [true, 'Places a link on the bottom of threads to open the QR.', 1],
'Captcha Fixes': [true, 'Make captcha more keyboard-navigable.']
},
'Quote Links': {
'Quote Backlinks': [true, 'Add quote backlinks.'],
@ -396,7 +399,7 @@
doc = d.documentElement;
g = {
VERSION: '1.10.8.9',
VERSION: '1.10.11.1',
NAMESPACE: '4chan X.',
boards: {}
};
@ -627,9 +630,11 @@
$.addStyle = function(css, id, test) {
var style;
style = $.el('style', {
id: id,
textContent: css
});
if (id != null) {
style.id = id;
}
$.asap((function() {
return d.head && ((test == null) || test());
}), function() {
@ -1291,28 +1296,33 @@
}
Post.prototype.parseComment = function() {
var bq, k, len1, node, ref, spoilers;
var abbr, bq, commentDisplay, k, len1, len2, node, q, ref, spoilers;
this.nodes.comment.normalize();
bq = this.nodes.comment.cloneNode(true);
ref = $$('.abbr, .exif, b, marquee', bq);
ref = $$('.abbr + br, .exif, b, .fortune', bq);
for (k = 0, len1 = ref.length; k < len1; k++) {
node = ref[k];
$.rm(node);
}
if (abbr = $('.abbr', bq)) {
$.rm(abbr);
}
this.info.comment = this.nodesToText(bq);
spoilers = $$('s', bq);
return this.info.commentSpoilered = (function() {
var len2, q;
if (abbr) {
this.info.comment = this.info.comment.replace(/\n\n$/, '');
}
commentDisplay = this.info.comment;
if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) {
spoilers = $$('s', bq);
if (spoilers.length) {
for (q = 0, len2 = spoilers.length; q < len2; q++) {
node = spoilers[q];
$.replace(node, $.tn('[spoiler]'));
}
return this.nodesToText(bq);
} else {
return this.info.comment;
commentDisplay = this.nodesToText(bq);
}
}).call(this);
}
return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, '');
};
Post.prototype.nodesToText = function(bq) {
@ -1323,7 +1333,7 @@
while (node = nodes.snapshotItem(i++)) {
text += node.data || '\n';
}
return text.trim().replace(/\s+$/gm, '');
return text;
};
Post.prototype.parseQuotes = function() {
@ -4298,7 +4308,7 @@
threadExcerpt: function(thread) {
var OP, excerpt, ref;
OP = thread.OP;
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.info.comment.replace(/\n+/g, ' // ') || OP.info.nameBlock);
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.info.commentDisplay.replace(/\n+/g, ' // ') || OP.info.nameBlock);
if (excerpt.length > 73) {
return excerpt.slice(0, 70) + "...";
}
@ -5070,18 +5080,18 @@
},
node: function() {
var filter, k, key, len1, ref, ref1, result, value;
if (this.isClone || this.isFetchedQuote) {
if (this.isClone) {
return;
}
for (key in Filter.filters) {
if ((value = Filter[key](this)) !== false) {
if ((value = Filter[key](this)) != null) {
ref = Filter.filters[key];
for (k = 0, len1 = ref.length; k < len1; k++) {
filter = ref[k];
if (!(result = filter(value, this.isReply))) {
continue;
}
if (result.hide) {
if (result.hide && !this.isFetchedQuote) {
if (this.isReply) {
PostHiding.hide(this, result.stub);
} else if (g.VIEW === 'index') {
@ -5103,73 +5113,41 @@
}
},
name: function(post) {
if ('name' in post.info) {
return post.info.name;
}
return false;
return post.info.name;
},
uniqueID: function(post) {
if ('uniqueID' in post.info) {
return post.info.uniqueID;
}
return false;
return post.info.uniqueID;
},
tripcode: function(post) {
if ('tripcode' in post.info) {
return post.info.tripcode;
}
return false;
return post.info.tripcode;
},
capcode: function(post) {
if ('capcode' in post.info) {
return post.info.capcode;
}
return false;
return post.info.capcode;
},
subject: function(post) {
if ('subject' in post.info) {
return post.info.subject || false;
}
return false;
return post.info.subject || void 0;
},
comment: function(post) {
if ('comment' in post.info) {
return post.info.comment;
}
return false;
return post.info.comment;
},
flag: function(post) {
if ('flag' in post.info) {
return post.info.flag;
}
return false;
return post.info.flag;
},
filename: function(post) {
if (post.file) {
return post.file.name;
}
return false;
var ref;
return (ref = post.file) != null ? ref.name : void 0;
},
dimensions: function(post) {
var file;
file = post.file;
if (file != null ? file.dimensions : void 0) {
return file.dimensions;
}
return false;
var ref;
return (ref = post.file) != null ? ref.dimensions : void 0;
},
filesize: function(post) {
if (post.file) {
return post.file.size;
}
return false;
var ref;
return (ref = post.file) != null ? ref.size : void 0;
},
MD5: function(post) {
var ref;
if ((ref = post.file) != null ? ref.MD5 : void 0) {
return post.file.MD5;
}
return false;
return (ref = post.file) != null ? ref.MD5 : void 0;
},
menu: {
init: function() {
@ -5209,7 +5187,7 @@
open: function(post) {
var value;
value = Filter[type](post);
return value !== false;
return value != null;
}
};
},
@ -6696,8 +6674,8 @@
if (g.VIEW === 'archive') {
return;
}
$.globalEval('document.documentElement.dataset.jsEnabled = true;');
noscript = Conf['Force Noscript Captcha'] || !doc.dataset.jsEnabled;
$.globalEval('document.documentElement.classList.add("js-enabled");');
noscript = Conf['Force Noscript Captcha'] || !$.hasClass(doc, 'js-enabled');
this.captcha = Captcha[noscript ? 'noscript' : 'v2'];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
@ -6726,7 +6704,7 @@
}
if (Conf['Hide Original Post Form']) {
$.addClass(doc, 'hide-original-post-form');
if (!doc.dataset.jsEnabled) {
if (!$.hasClass(doc, 'js-enabled')) {
return $.onExists(doc, '#postForm noscript', true, $.rm);
}
}
@ -7630,6 +7608,104 @@
Captcha = {};
Captcha.fixes = {
css: '.rc-imageselect-target > .rc-imageselect-tile > img:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}',
init: function() {
switch (location.pathname.split('/')[3]) {
case 'anchor':
return this.initMain();
case 'frame':
return this.initPopup();
}
},
initMain: function() {
return $.onExists(d.body, '#recaptcha-anchor', true, function(checkbox) {
var focus;
focus = function() {
if (d.hasFocus() && d.activeElement !== checkbox) {
return checkbox.focus();
}
};
focus();
return $.on(window, 'focus', function() {
return $.queueTask(focus);
});
});
},
initPopup: function() {
$.addStyle(this.css);
this.fixImages();
new MutationObserver((function(_this) {
return function() {
return _this.fixImages();
};
})(this)).observe(d.body, {
childList: true,
subtree: true
});
return $.on(d, 'keydown', this.keybinds.bind(this));
},
fixImages: function() {
var focus, img, k, len1, ref;
if (!(this.images = $$('.rc-imageselect-target > .rc-imageselect-tile > img')).length) {
return;
}
focus = this.images[0].tabIndex !== 0;
ref = this.images;
for (k = 0, len1 = ref.length; k < len1; k++) {
img = ref[k];
img.tabIndex = 0;
}
if (focus) {
return this.focusImage();
}
},
focusImage: function() {
var img;
img = this.images[0];
return $.asap(function() {
if (!doc.contains(img)) {
return true;
}
img.focus();
return d.activeElement === img;
}, function() {});
},
keybinds: function(e) {
var dx, reload, verify, x;
if (!(this.images && doc.contains(this.images[0]) && d.activeElement)) {
return;
}
reload = $.id('recaptcha-reload-button');
verify = $.id('recaptcha-verify-button');
x = this.images.indexOf(d.activeElement);
if (x < 0) {
if (!$('.rc-controls').contains(d.activeElement)) {
return;
}
x = d.activeElement === verify ? 11 : 9;
}
if (!(dx = {
38: 9,
40: 3,
37: 11,
39: 1
}[e.keyCode])) {
return;
}
x = (x + dx) % 12;
if (x === 10) {
x = dx === 11 ? 9 : 11;
}
(this.images[x] || {
9: reload,
11: verify
}[x]).focus();
e.preventDefault();
return e.stopPropagation();
}
};
Captcha.noscript = {
lifetime: 2 * $.MINUTE,
iframeURL: '//www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc',
@ -7989,20 +8065,6 @@
};
})(this));
},
initFrame: function() {
$.globalEval('window.focus = function() {};');
return $.on(window, 'focus', function() {
return $.queueTask(function() {
var checkbox;
if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
return;
}
if (d.activeElement !== checkbox) {
return checkbox.focus();
}
});
});
},
shouldFocus: false,
timeouts: {},
postsCount: 0,
@ -8102,6 +8164,7 @@
})(this));
},
destroy: function() {
var garbage, ins, k, len1, ref;
if (!this.isEnabled) {
return;
}
@ -8110,7 +8173,15 @@
if (this.nodes.container) {
$.rm(this.nodes.container);
}
return delete this.nodes.container;
delete this.nodes.container;
ref = $$('div > .gc-bubbleDefault');
for (k = 0, len1 = ref.length; k < len1; k++) {
garbage = ref[k];
if ((ins = garbage.parentNode.nextSibling) && ins.nodeName === 'INS') {
$.rm(ins);
}
$.rm(garbage.parentNode);
}
},
sync: function(captchas) {
if (captchas == null) {
@ -8132,7 +8203,7 @@
}
},
save: function(pasted) {
var base1;
var base1, focus, ref, ref1;
$.forceSync('captchas');
this.captchas.push({
response: $('textarea', this.nodes.container).value,
@ -8148,6 +8219,7 @@
}
this.reload();
} else {
focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && ((ref1 = d.activeElement.src) != null ? ref1.slice(0, 38) : void 0) === 'https://www.google.com/recaptcha/api2/';
if (pasted) {
this.destroy();
} else {
@ -8155,7 +8227,9 @@
base1.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND);
}
}
QR.nodes.status.focus();
if (focus) {
QR.nodes.status.focus();
}
}
if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) {
return QR.submit();
@ -11441,7 +11515,7 @@
},
subEntries: []
};
ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']];
ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']];
for (k = 0, len1 = ref1.length; k < len1; k++) {
type = ref1[k];
entry.subEntries.push(this.createSubEntry(type[0], type[1]));
@ -11708,17 +11782,19 @@
el: a,
order: 10,
open: function(post) {
ReportLink.post = post;
return !post.isDead;
ReportLink.url = !post.isDead ? "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post : Conf['Archive Report'] ? Redirect.to('report', {
boardID: post.board.ID,
postID: post.ID
}) : void 0;
return !!ReportLink.url;
}
});
},
report: function() {
var id, post, set, url;
post = ReportLink.post;
url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post;
var id, set, url;
url = ReportLink.url;
id = Date.now();
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=285";
set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1,width=685,height=200";
return window.open(url, id, set);
}
};
@ -13271,7 +13347,7 @@
return;
}
notif = new Notification(post.info.nameBlock + " replied to you", {
body: post.info[Conf['Remove Spoilers'] || Conf['Reveal Spoilers'] ? 'comment' : 'commentSpoilered'],
body: post.info.commentDisplay,
icon: Favicon.logo
});
notif.onclick = function() {
@ -13411,7 +13487,8 @@
o = {
thread: {},
post: {},
file: {}
file: {},
report: {}
};
archives = {};
ref = Redirect.archives;
@ -13421,17 +13498,19 @@
archives[name] = data;
for (q = 0, len2 = boards.length; q < len2; q++) {
boardID = boards[q];
if (!(!withCredentials)) {
continue;
if (!withCredentials) {
if (!(boardID in o.thread)) {
o.thread[boardID] = data;
}
if (!(boardID in o.post || software !== 'foolfuuka')) {
o.post[boardID] = data;
}
if (!(boardID in o.file || indexOf.call(files, boardID) < 0)) {
o.file[boardID] = data;
}
}
if (!(boardID in o.thread)) {
o.thread[boardID] = data;
}
if (!(boardID in o.post || software !== 'foolfuuka')) {
o.post[boardID] = data;
}
if (!(boardID in o.file || indexOf.call(files, boardID) < 0)) {
o.file[boardID] = data;
if (name === 'fgts') {
o.report[boardID] = data;
}
}
}
@ -13452,7 +13531,7 @@
}
return Redirect.data = o;
},
archives: [{"uid":0,"name":"Moe","domain":"archive.moe","http":false,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","fit","gd","h","i","int","jp","k","m","mlp","out","po","qa","r9k","s4s","sci","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","fit","gd","h","i","jp","k","m","mlp","po","qa","r9k","s4s","sci","tg","u","v","vg","vp","vr","wsg"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","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":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u","w","wg"],"files":["c","d","e","i","lgbt","t","u","w","wg"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","qa","w"],"files":["cgl","g","mu","qa","w"]},{"uid":10,"name":"warosu","domain":"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","g","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"],"files":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"]},{"uid":22,"name":"not4plebs","domain":"totally.not4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["sp"],"files":["sp"]},{"uid":23,"name":"DesuStorage","domain":"archive.desustorage.org","http":false,"https":true,"software":"foolfuuka","boards":["mlp","qa"],"files":["mlp","qa"]}],
archives: [{"uid":0,"name":"Moe","domain":"archive.moe","http":false,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","fit","gd","gif","h","i","int","jp","k","m","mlp","out","po","qa","r9k","s4s","sci","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","fit","gd","h","i","jp","k","m","mlp","po","qa","r9k","s4s","sci","tg","u","v","vg","vp","vr","wsg"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","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":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u"],"files":["c","d","e","i","lgbt","t","u"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","qa","w"],"files":["cgl","g","mu","qa","w"]},{"uid":10,"name":"warosu","domain":"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","g","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"],"files":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"]},{"uid":22,"name":"not4plebs","domain":"totally.not4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["sp"],"files":["sp"]},{"uid":23,"name":"DesuStorage","domain":"archive.desustorage.org","http":false,"https":true,"software":"foolfuuka","boards":["mlp","qa"],"files":["mlp","qa"]}],
to: function(dest, data) {
var archive;
archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID];
@ -13506,10 +13585,20 @@
var boardID, path, type, value;
boardID = arg.boardID, type = arg.type, value = arg.value;
type = type === 'name' ? 'username' : type === 'MD5' ? 'image' : type;
if (type === 'capcode') {
value = {
'Developer': 'dev'
}[value] || value.toLowerCase();
}
value = encodeURIComponent(value);
path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value : boardID + "/?task=search2&search_" + (type === 'image' ? 'media_hash' : type) + "=" + value;
return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path;
},
report: function(archive, arg) {
var boardID, postID;
boardID = arg.boardID, postID = arg.postID;
return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID;
},
securityCheck: function(URL) {
return /^https:\/\//.test(URL) || location.protocol === 'http:' || Conf['Except Archives from Encryption'];
},
@ -15229,6 +15318,63 @@
}
};
Report = {
init: function() {
var match;
if (!(/\bmode=report\b/.test(location.search) && (match = location.search.match(/\bno=(\d+)/)))) {
return;
}
this.postID = +match[1];
return $.ready(this.ready);
},
ready: function() {
new MutationObserver(Report.resize).observe(d.body, {
childList: true,
attributes: true,
subtree: true
});
if (Conf['Archive Report']) {
return Report.archive();
}
},
resize: function() {
var bubble, dy;
if (!(bubble = $('.gc-bubbleDefault'))) {
return;
}
dy = bubble.getBoundingClientRect().bottom - doc.clientHeight;
if (dy > 0) {
return window.resizeBy(0, dy);
}
},
archive: function() {
var link, message, url;
Redirect.init();
if (!(url = Redirect.to('report', {
boardID: g.BOARD.ID,
postID: Report.postID
}))) {
return;
}
if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) {
$.globalEval('self.close = function(){};');
window.resizeTo(685, 320);
location.replace(url);
return;
}
link = $.el('a', {
href: url,
textContent: 'Report to fgts'
});
$.on(link, 'click', function(e) {
if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) {
return window.resizeTo(685, 320);
}
});
return $.add(d.body, [$.tn(' ['), link, $.tn(']')]);
}
};
Time = {
init: function() {
var ref;
@ -16018,12 +16164,24 @@
Main = {
init: function() {
var db, flatten, k, len1, pathname, ref, ref1, ref2, type;
var db, flatten, k, len1, pathname, ref, ref1, ref2;
if (location.hostname === 'www.google.com') {
type = location.pathname === '/recaptcha/api/fallback' ? 'noscript' : 'v2';
return $.ready(function() {
return Captcha[type].initFrame();
});
if (location.pathname === '/recaptcha/api/fallback') {
$.ready(function() {
return Captcha.noscript.initFrame();
});
} else {
$.get('Captcha Fixes', true, function(arg) {
var enabled;
enabled = arg['Captcha Fixes'];
if (enabled) {
return $.ready(function() {
return Captcha.fixes.init();
});
}
});
}
return;
}
g.threads = new SimpleDict();
g.posts = new SimpleDict();
@ -16097,6 +16255,7 @@
case 'a.4cdn.org':
return;
case 'sys.4chan.org':
Report.init();
if (g.VIEW === 'post') {
PostSuccessful.init();
}
@ -17096,10 +17255,8 @@
" /* party hats */\n" +
" pointer-events: none;\n" +
"}\n" +
"marquee,\n" +
".postMessage marquee + br,\n" +
".postMessage marquee + br + br {\n" +
" display: none;\n" +
":root:not(.js-enabled) #postForm {\n" +
" display: table;\n" +
"}\n" +
"/* Anti-autoplay */\n" +
"audio.controls-added {\n" +

Binary file not shown.

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
// @version 1.10.8.9
// @version 1.10.11.1
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@ -12,6 +12,7 @@
// @match *://a.4cdn.org/*
// @match *://i.4cdn.org/*
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
// @grant GM_getValue
// @grant GM_setValue
@ -108,7 +109,7 @@
'use strict';
(function() {
var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, Callbacks, Captcha, CatalogLinks, CatalogThread, Clone, Conf, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, E, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume, c, d, doc, g,
var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, Callbacks, Captcha, CatalogLinks, CatalogThread, Clone, Conf, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, E, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume, c, d, doc, g,
slice = [].slice,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@ -126,6 +127,7 @@
'Announcement Hiding': [true, 'Add button to hide 4chan announcements.'],
'Desktop Notifications': [true, 'Enables desktop notifications across various 4chan X features.'],
'404 Redirect': [true, 'Redirect dead threads and images to the archives.'],
'Archive Report': [true, 'Enable reporting posts to supported archives.'],
'Except Archives from Encryption': [false, 'Permit loading content from, and warningless redirects to, HTTP-only archives from HTTPS pages.'],
'Keybinds': [true, 'Bind actions to keyboard shortcuts.'],
'Time Formatting': [true, 'Localize and format timestamps.'],
@ -234,7 +236,8 @@
'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1],
'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1],
'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1],
'Bottom QR Link': [true, 'Places a link on the bottom of threads to open the QR.', 1]
'Bottom QR Link': [true, 'Places a link on the bottom of threads to open the QR.', 1],
'Captcha Fixes': [true, 'Make captcha more keyboard-navigable.']
},
'Quote Links': {
'Quote Backlinks': [true, 'Add quote backlinks.'],
@ -395,7 +398,7 @@
doc = d.documentElement;
g = {
VERSION: '1.10.8.9',
VERSION: '1.10.11.1',
NAMESPACE: '4chan X.',
boards: {}
};
@ -626,9 +629,11 @@
$.addStyle = function(css, id, test) {
var style;
style = $.el('style', {
id: id,
textContent: css
});
if (id != null) {
style.id = id;
}
$.asap((function() {
return d.head && ((test == null) || test());
}), function() {
@ -1290,28 +1295,33 @@
}
Post.prototype.parseComment = function() {
var bq, k, len1, node, ref, spoilers;
var abbr, bq, commentDisplay, k, len1, len2, node, q, ref, spoilers;
this.nodes.comment.normalize();
bq = this.nodes.comment.cloneNode(true);
ref = $$('.abbr, .exif, b, marquee', bq);
ref = $$('.abbr + br, .exif, b, .fortune', bq);
for (k = 0, len1 = ref.length; k < len1; k++) {
node = ref[k];
$.rm(node);
}
if (abbr = $('.abbr', bq)) {
$.rm(abbr);
}
this.info.comment = this.nodesToText(bq);
spoilers = $$('s', bq);
return this.info.commentSpoilered = (function() {
var len2, q;
if (abbr) {
this.info.comment = this.info.comment.replace(/\n\n$/, '');
}
commentDisplay = this.info.comment;
if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) {
spoilers = $$('s', bq);
if (spoilers.length) {
for (q = 0, len2 = spoilers.length; q < len2; q++) {
node = spoilers[q];
$.replace(node, $.tn('[spoiler]'));
}
return this.nodesToText(bq);
} else {
return this.info.comment;
commentDisplay = this.nodesToText(bq);
}
}).call(this);
}
return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, '');
};
Post.prototype.nodesToText = function(bq) {
@ -1322,7 +1332,7 @@
while (node = nodes.snapshotItem(i++)) {
text += node.data || '\n';
}
return text.trim().replace(/\s+$/gm, '');
return text;
};
Post.prototype.parseQuotes = function() {
@ -4297,7 +4307,7 @@
threadExcerpt: function(thread) {
var OP, excerpt, ref;
OP = thread.OP;
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.info.comment.replace(/\n+/g, ' // ') || OP.info.nameBlock);
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.info.commentDisplay.replace(/\n+/g, ' // ') || OP.info.nameBlock);
if (excerpt.length > 73) {
return excerpt.slice(0, 70) + "...";
}
@ -5069,18 +5079,18 @@
},
node: function() {
var filter, k, key, len1, ref, ref1, result, value;
if (this.isClone || this.isFetchedQuote) {
if (this.isClone) {
return;
}
for (key in Filter.filters) {
if ((value = Filter[key](this)) !== false) {
if ((value = Filter[key](this)) != null) {
ref = Filter.filters[key];
for (k = 0, len1 = ref.length; k < len1; k++) {
filter = ref[k];
if (!(result = filter(value, this.isReply))) {
continue;
}
if (result.hide) {
if (result.hide && !this.isFetchedQuote) {
if (this.isReply) {
PostHiding.hide(this, result.stub);
} else if (g.VIEW === 'index') {
@ -5102,73 +5112,41 @@
}
},
name: function(post) {
if ('name' in post.info) {
return post.info.name;
}
return false;
return post.info.name;
},
uniqueID: function(post) {
if ('uniqueID' in post.info) {
return post.info.uniqueID;
}
return false;
return post.info.uniqueID;
},
tripcode: function(post) {
if ('tripcode' in post.info) {
return post.info.tripcode;
}
return false;
return post.info.tripcode;
},
capcode: function(post) {
if ('capcode' in post.info) {
return post.info.capcode;
}
return false;
return post.info.capcode;
},
subject: function(post) {
if ('subject' in post.info) {
return post.info.subject || false;
}
return false;
return post.info.subject || void 0;
},
comment: function(post) {
if ('comment' in post.info) {
return post.info.comment;
}
return false;
return post.info.comment;
},
flag: function(post) {
if ('flag' in post.info) {
return post.info.flag;
}
return false;
return post.info.flag;
},
filename: function(post) {
if (post.file) {
return post.file.name;
}
return false;
var ref;
return (ref = post.file) != null ? ref.name : void 0;
},
dimensions: function(post) {
var file;
file = post.file;
if (file != null ? file.dimensions : void 0) {
return file.dimensions;
}
return false;
var ref;
return (ref = post.file) != null ? ref.dimensions : void 0;
},
filesize: function(post) {
if (post.file) {
return post.file.size;
}
return false;
var ref;
return (ref = post.file) != null ? ref.size : void 0;
},
MD5: function(post) {
var ref;
if ((ref = post.file) != null ? ref.MD5 : void 0) {
return post.file.MD5;
}
return false;
return (ref = post.file) != null ? ref.MD5 : void 0;
},
menu: {
init: function() {
@ -5208,7 +5186,7 @@
open: function(post) {
var value;
value = Filter[type](post);
return value !== false;
return value != null;
}
};
},
@ -6695,8 +6673,8 @@
if (g.VIEW === 'archive') {
return;
}
$.globalEval('document.documentElement.dataset.jsEnabled = true;');
noscript = Conf['Force Noscript Captcha'] || !doc.dataset.jsEnabled;
$.globalEval('document.documentElement.classList.add("js-enabled");');
noscript = Conf['Force Noscript Captcha'] || !$.hasClass(doc, 'js-enabled');
this.captcha = Captcha[noscript ? 'noscript' : 'v2'];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
@ -6725,7 +6703,7 @@
}
if (Conf['Hide Original Post Form']) {
$.addClass(doc, 'hide-original-post-form');
if (!doc.dataset.jsEnabled) {
if (!$.hasClass(doc, 'js-enabled')) {
return $.onExists(doc, '#postForm noscript', true, $.rm);
}
}
@ -7629,6 +7607,104 @@
Captcha = {};
Captcha.fixes = {
css: '.rc-imageselect-target > .rc-imageselect-tile > img:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}',
init: function() {
switch (location.pathname.split('/')[3]) {
case 'anchor':
return this.initMain();
case 'frame':
return this.initPopup();
}
},
initMain: function() {
return $.onExists(d.body, '#recaptcha-anchor', true, function(checkbox) {
var focus;
focus = function() {
if (d.hasFocus() && d.activeElement !== checkbox) {
return checkbox.focus();
}
};
focus();
return $.on(window, 'focus', function() {
return $.queueTask(focus);
});
});
},
initPopup: function() {
$.addStyle(this.css);
this.fixImages();
new MutationObserver((function(_this) {
return function() {
return _this.fixImages();
};
})(this)).observe(d.body, {
childList: true,
subtree: true
});
return $.on(d, 'keydown', this.keybinds.bind(this));
},
fixImages: function() {
var focus, img, k, len1, ref;
if (!(this.images = $$('.rc-imageselect-target > .rc-imageselect-tile > img')).length) {
return;
}
focus = this.images[0].tabIndex !== 0;
ref = this.images;
for (k = 0, len1 = ref.length; k < len1; k++) {
img = ref[k];
img.tabIndex = 0;
}
if (focus) {
return this.focusImage();
}
},
focusImage: function() {
var img;
img = this.images[0];
return $.asap(function() {
if (!doc.contains(img)) {
return true;
}
img.focus();
return d.activeElement === img;
}, function() {});
},
keybinds: function(e) {
var dx, reload, verify, x;
if (!(this.images && doc.contains(this.images[0]) && d.activeElement)) {
return;
}
reload = $.id('recaptcha-reload-button');
verify = $.id('recaptcha-verify-button');
x = this.images.indexOf(d.activeElement);
if (x < 0) {
if (!$('.rc-controls').contains(d.activeElement)) {
return;
}
x = d.activeElement === verify ? 11 : 9;
}
if (!(dx = {
38: 9,
40: 3,
37: 11,
39: 1
}[e.keyCode])) {
return;
}
x = (x + dx) % 12;
if (x === 10) {
x = dx === 11 ? 9 : 11;
}
(this.images[x] || {
9: reload,
11: verify
}[x]).focus();
e.preventDefault();
return e.stopPropagation();
}
};
Captcha.noscript = {
lifetime: 2 * $.MINUTE,
iframeURL: '//www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc',
@ -7988,20 +8064,6 @@
};
})(this));
},
initFrame: function() {
$.globalEval('window.focus = function() {};');
return $.on(window, 'focus', function() {
return $.queueTask(function() {
var checkbox;
if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
return;
}
if (d.activeElement !== checkbox) {
return checkbox.focus();
}
});
});
},
shouldFocus: false,
timeouts: {},
postsCount: 0,
@ -8101,6 +8163,7 @@
})(this));
},
destroy: function() {
var garbage, ins, k, len1, ref;
if (!this.isEnabled) {
return;
}
@ -8109,7 +8172,15 @@
if (this.nodes.container) {
$.rm(this.nodes.container);
}
return delete this.nodes.container;
delete this.nodes.container;
ref = $$('div > .gc-bubbleDefault');
for (k = 0, len1 = ref.length; k < len1; k++) {
garbage = ref[k];
if ((ins = garbage.parentNode.nextSibling) && ins.nodeName === 'INS') {
$.rm(ins);
}
$.rm(garbage.parentNode);
}
},
sync: function(captchas) {
if (captchas == null) {
@ -8131,7 +8202,7 @@
}
},
save: function(pasted) {
var base1;
var base1, focus, ref, ref1;
$.forceSync('captchas');
this.captchas.push({
response: $('textarea', this.nodes.container).value,
@ -8147,6 +8218,7 @@
}
this.reload();
} else {
focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && ((ref1 = d.activeElement.src) != null ? ref1.slice(0, 38) : void 0) === 'https://www.google.com/recaptcha/api2/';
if (pasted) {
this.destroy();
} else {
@ -8154,7 +8226,9 @@
base1.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND);
}
}
QR.nodes.status.focus();
if (focus) {
QR.nodes.status.focus();
}
}
if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) {
return QR.submit();
@ -11440,7 +11514,7 @@
},
subEntries: []
};
ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']];
ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']];
for (k = 0, len1 = ref1.length; k < len1; k++) {
type = ref1[k];
entry.subEntries.push(this.createSubEntry(type[0], type[1]));
@ -11707,17 +11781,19 @@
el: a,
order: 10,
open: function(post) {
ReportLink.post = post;
return !post.isDead;
ReportLink.url = !post.isDead ? "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post : Conf['Archive Report'] ? Redirect.to('report', {
boardID: post.board.ID,
postID: post.ID
}) : void 0;
return !!ReportLink.url;
}
});
},
report: function() {
var id, post, set, url;
post = ReportLink.post;
url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post;
var id, set, url;
url = ReportLink.url;
id = Date.now();
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=285";
set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1,width=685,height=200";
return window.open(url, id, set);
}
};
@ -13270,7 +13346,7 @@
return;
}
notif = new Notification(post.info.nameBlock + " replied to you", {
body: post.info[Conf['Remove Spoilers'] || Conf['Reveal Spoilers'] ? 'comment' : 'commentSpoilered'],
body: post.info.commentDisplay,
icon: Favicon.logo
});
notif.onclick = function() {
@ -13410,7 +13486,8 @@
o = {
thread: {},
post: {},
file: {}
file: {},
report: {}
};
archives = {};
ref = Redirect.archives;
@ -13420,17 +13497,19 @@
archives[name] = data;
for (q = 0, len2 = boards.length; q < len2; q++) {
boardID = boards[q];
if (!(!withCredentials)) {
continue;
if (!withCredentials) {
if (!(boardID in o.thread)) {
o.thread[boardID] = data;
}
if (!(boardID in o.post || software !== 'foolfuuka')) {
o.post[boardID] = data;
}
if (!(boardID in o.file || indexOf.call(files, boardID) < 0)) {
o.file[boardID] = data;
}
}
if (!(boardID in o.thread)) {
o.thread[boardID] = data;
}
if (!(boardID in o.post || software !== 'foolfuuka')) {
o.post[boardID] = data;
}
if (!(boardID in o.file || indexOf.call(files, boardID) < 0)) {
o.file[boardID] = data;
if (name === 'fgts') {
o.report[boardID] = data;
}
}
}
@ -13451,7 +13530,7 @@
}
return Redirect.data = o;
},
archives: [{"uid":0,"name":"Moe","domain":"archive.moe","http":false,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","fit","gd","h","i","int","jp","k","m","mlp","out","po","qa","r9k","s4s","sci","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","fit","gd","h","i","jp","k","m","mlp","po","qa","r9k","s4s","sci","tg","u","v","vg","vp","vr","wsg"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","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":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u","w","wg"],"files":["c","d","e","i","lgbt","t","u","w","wg"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","qa","w"],"files":["cgl","g","mu","qa","w"]},{"uid":10,"name":"warosu","domain":"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","g","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"],"files":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"]},{"uid":22,"name":"not4plebs","domain":"totally.not4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["sp"],"files":["sp"]},{"uid":23,"name":"DesuStorage","domain":"archive.desustorage.org","http":false,"https":true,"software":"foolfuuka","boards":["mlp","qa"],"files":["mlp","qa"]}],
archives: [{"uid":0,"name":"Moe","domain":"archive.moe","http":false,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","fit","gd","gif","h","i","int","jp","k","m","mlp","out","po","qa","r9k","s4s","sci","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","fit","gd","h","i","jp","k","m","mlp","po","qa","r9k","s4s","sci","tg","u","v","vg","vp","vr","wsg"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","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":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u"],"files":["c","d","e","i","lgbt","t","u"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","qa","w"],"files":["cgl","g","mu","qa","w"]},{"uid":10,"name":"warosu","domain":"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","g","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"],"files":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"]},{"uid":22,"name":"not4plebs","domain":"totally.not4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["sp"],"files":["sp"]},{"uid":23,"name":"DesuStorage","domain":"archive.desustorage.org","http":false,"https":true,"software":"foolfuuka","boards":["mlp","qa"],"files":["mlp","qa"]}],
to: function(dest, data) {
var archive;
archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID];
@ -13505,10 +13584,20 @@
var boardID, path, type, value;
boardID = arg.boardID, type = arg.type, value = arg.value;
type = type === 'name' ? 'username' : type === 'MD5' ? 'image' : type;
if (type === 'capcode') {
value = {
'Developer': 'dev'
}[value] || value.toLowerCase();
}
value = encodeURIComponent(value);
path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value : boardID + "/?task=search2&search_" + (type === 'image' ? 'media_hash' : type) + "=" + value;
return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path;
},
report: function(archive, arg) {
var boardID, postID;
boardID = arg.boardID, postID = arg.postID;
return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID;
},
securityCheck: function(URL) {
return /^https:\/\//.test(URL) || location.protocol === 'http:' || Conf['Except Archives from Encryption'];
},
@ -15228,6 +15317,63 @@
}
};
Report = {
init: function() {
var match;
if (!(/\bmode=report\b/.test(location.search) && (match = location.search.match(/\bno=(\d+)/)))) {
return;
}
this.postID = +match[1];
return $.ready(this.ready);
},
ready: function() {
new MutationObserver(Report.resize).observe(d.body, {
childList: true,
attributes: true,
subtree: true
});
if (Conf['Archive Report']) {
return Report.archive();
}
},
resize: function() {
var bubble, dy;
if (!(bubble = $('.gc-bubbleDefault'))) {
return;
}
dy = bubble.getBoundingClientRect().bottom - doc.clientHeight;
if (dy > 0) {
return window.resizeBy(0, dy);
}
},
archive: function() {
var link, message, url;
Redirect.init();
if (!(url = Redirect.to('report', {
boardID: g.BOARD.ID,
postID: Report.postID
}))) {
return;
}
if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) {
$.globalEval('self.close = function(){};');
window.resizeTo(685, 320);
location.replace(url);
return;
}
link = $.el('a', {
href: url,
textContent: 'Report to fgts'
});
$.on(link, 'click', function(e) {
if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) {
return window.resizeTo(685, 320);
}
});
return $.add(d.body, [$.tn(' ['), link, $.tn(']')]);
}
};
Time = {
init: function() {
var ref;
@ -16017,12 +16163,24 @@
Main = {
init: function() {
var db, flatten, k, len1, pathname, ref, ref1, ref2, type;
var db, flatten, k, len1, pathname, ref, ref1, ref2;
if (location.hostname === 'www.google.com') {
type = location.pathname === '/recaptcha/api/fallback' ? 'noscript' : 'v2';
return $.ready(function() {
return Captcha[type].initFrame();
});
if (location.pathname === '/recaptcha/api/fallback') {
$.ready(function() {
return Captcha.noscript.initFrame();
});
} else {
$.get('Captcha Fixes', true, function(arg) {
var enabled;
enabled = arg['Captcha Fixes'];
if (enabled) {
return $.ready(function() {
return Captcha.fixes.init();
});
}
});
}
return;
}
g.threads = new SimpleDict();
g.posts = new SimpleDict();
@ -16096,6 +16254,7 @@
case 'a.4cdn.org':
return;
case 'sys.4chan.org':
Report.init();
if (g.VIEW === 'post') {
PostSuccessful.init();
}
@ -17095,10 +17254,8 @@
" /* party hats */\n" +
" pointer-events: none;\n" +
"}\n" +
"marquee,\n" +
".postMessage marquee + br,\n" +
".postMessage marquee + br + br {\n" +
" display: none;\n" +
":root:not(.js-enabled) #postForm {\n" +
" display: table;\n" +
"}\n" +
"/* Anti-autoplay */\n" +
"audio.controls-added {\n" +

Binary file not shown.

View File

@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X
// @version 1.10.8.9
// @version 1.10.11.1
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@ -11,6 +11,7 @@
// @match *://a.4cdn.org/*
// @match *://i.4cdn.org/*
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
// @grant GM_getValue
// @grant GM_setValue

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
// @version 1.10.8.9
// @version 1.10.11.1
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@ -12,6 +12,7 @@
// @match *://a.4cdn.org/*
// @match *://i.4cdn.org/*
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
// @grant GM_getValue
// @grant GM_setValue
@ -109,7 +110,7 @@
'use strict';
(function() {
var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, Callbacks, Captcha, CatalogLinks, CatalogThread, Clone, Conf, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, E, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume, c, d, doc, g,
var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, Build, Callbacks, Captcha, CatalogLinks, CatalogThread, Clone, Conf, Config, Connection, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, E, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, ImageCommon, ImageExpand, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, ShimSet, SimpleDict, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, Volume, c, d, doc, g,
slice = [].slice,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@ -127,6 +128,7 @@
'Announcement Hiding': [true, 'Add button to hide 4chan announcements.'],
'Desktop Notifications': [true, 'Enables desktop notifications across various 4chan X features.'],
'404 Redirect': [true, 'Redirect dead threads and images to the archives.'],
'Archive Report': [true, 'Enable reporting posts to supported archives.'],
'Except Archives from Encryption': [false, 'Permit loading content from, and warningless redirects to, HTTP-only archives from HTTPS pages.'],
'Keybinds': [true, 'Bind actions to keyboard shortcuts.'],
'Time Formatting': [true, 'Localize and format timestamps.'],
@ -235,7 +237,8 @@
'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1],
'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1],
'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1],
'Bottom QR Link': [true, 'Places a link on the bottom of threads to open the QR.', 1]
'Bottom QR Link': [true, 'Places a link on the bottom of threads to open the QR.', 1],
'Captcha Fixes': [true, 'Make captcha more keyboard-navigable.']
},
'Quote Links': {
'Quote Backlinks': [true, 'Add quote backlinks.'],
@ -396,7 +399,7 @@
doc = d.documentElement;
g = {
VERSION: '1.10.8.9',
VERSION: '1.10.11.1',
NAMESPACE: '4chan X.',
boards: {}
};
@ -627,9 +630,11 @@
$.addStyle = function(css, id, test) {
var style;
style = $.el('style', {
id: id,
textContent: css
});
if (id != null) {
style.id = id;
}
$.asap((function() {
return d.head && ((test == null) || test());
}), function() {
@ -1291,28 +1296,33 @@
}
Post.prototype.parseComment = function() {
var bq, k, len1, node, ref, spoilers;
var abbr, bq, commentDisplay, k, len1, len2, node, q, ref, spoilers;
this.nodes.comment.normalize();
bq = this.nodes.comment.cloneNode(true);
ref = $$('.abbr, .exif, b, marquee', bq);
ref = $$('.abbr + br, .exif, b, .fortune', bq);
for (k = 0, len1 = ref.length; k < len1; k++) {
node = ref[k];
$.rm(node);
}
if (abbr = $('.abbr', bq)) {
$.rm(abbr);
}
this.info.comment = this.nodesToText(bq);
spoilers = $$('s', bq);
return this.info.commentSpoilered = (function() {
var len2, q;
if (abbr) {
this.info.comment = this.info.comment.replace(/\n\n$/, '');
}
commentDisplay = this.info.comment;
if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) {
spoilers = $$('s', bq);
if (spoilers.length) {
for (q = 0, len2 = spoilers.length; q < len2; q++) {
node = spoilers[q];
$.replace(node, $.tn('[spoiler]'));
}
return this.nodesToText(bq);
} else {
return this.info.comment;
commentDisplay = this.nodesToText(bq);
}
}).call(this);
}
return this.info.commentDisplay = commentDisplay.trim().replace(/\s+$/gm, '');
};
Post.prototype.nodesToText = function(bq) {
@ -1323,7 +1333,7 @@
while (node = nodes.snapshotItem(i++)) {
text += node.data || '\n';
}
return text.trim().replace(/\s+$/gm, '');
return text;
};
Post.prototype.parseQuotes = function() {
@ -4298,7 +4308,7 @@
threadExcerpt: function(thread) {
var OP, excerpt, ref;
OP = thread.OP;
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.info.comment.replace(/\n+/g, ' // ') || OP.info.nameBlock);
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.info.commentDisplay.replace(/\n+/g, ' // ') || OP.info.nameBlock);
if (excerpt.length > 73) {
return excerpt.slice(0, 70) + "...";
}
@ -5070,18 +5080,18 @@
},
node: function() {
var filter, k, key, len1, ref, ref1, result, value;
if (this.isClone || this.isFetchedQuote) {
if (this.isClone) {
return;
}
for (key in Filter.filters) {
if ((value = Filter[key](this)) !== false) {
if ((value = Filter[key](this)) != null) {
ref = Filter.filters[key];
for (k = 0, len1 = ref.length; k < len1; k++) {
filter = ref[k];
if (!(result = filter(value, this.isReply))) {
continue;
}
if (result.hide) {
if (result.hide && !this.isFetchedQuote) {
if (this.isReply) {
PostHiding.hide(this, result.stub);
} else if (g.VIEW === 'index') {
@ -5103,73 +5113,41 @@
}
},
name: function(post) {
if ('name' in post.info) {
return post.info.name;
}
return false;
return post.info.name;
},
uniqueID: function(post) {
if ('uniqueID' in post.info) {
return post.info.uniqueID;
}
return false;
return post.info.uniqueID;
},
tripcode: function(post) {
if ('tripcode' in post.info) {
return post.info.tripcode;
}
return false;
return post.info.tripcode;
},
capcode: function(post) {
if ('capcode' in post.info) {
return post.info.capcode;
}
return false;
return post.info.capcode;
},
subject: function(post) {
if ('subject' in post.info) {
return post.info.subject || false;
}
return false;
return post.info.subject || void 0;
},
comment: function(post) {
if ('comment' in post.info) {
return post.info.comment;
}
return false;
return post.info.comment;
},
flag: function(post) {
if ('flag' in post.info) {
return post.info.flag;
}
return false;
return post.info.flag;
},
filename: function(post) {
if (post.file) {
return post.file.name;
}
return false;
var ref;
return (ref = post.file) != null ? ref.name : void 0;
},
dimensions: function(post) {
var file;
file = post.file;
if (file != null ? file.dimensions : void 0) {
return file.dimensions;
}
return false;
var ref;
return (ref = post.file) != null ? ref.dimensions : void 0;
},
filesize: function(post) {
if (post.file) {
return post.file.size;
}
return false;
var ref;
return (ref = post.file) != null ? ref.size : void 0;
},
MD5: function(post) {
var ref;
if ((ref = post.file) != null ? ref.MD5 : void 0) {
return post.file.MD5;
}
return false;
return (ref = post.file) != null ? ref.MD5 : void 0;
},
menu: {
init: function() {
@ -5209,7 +5187,7 @@
open: function(post) {
var value;
value = Filter[type](post);
return value !== false;
return value != null;
}
};
},
@ -6696,8 +6674,8 @@
if (g.VIEW === 'archive') {
return;
}
$.globalEval('document.documentElement.dataset.jsEnabled = true;');
noscript = Conf['Force Noscript Captcha'] || !doc.dataset.jsEnabled;
$.globalEval('document.documentElement.classList.add("js-enabled");');
noscript = Conf['Force Noscript Captcha'] || !$.hasClass(doc, 'js-enabled');
this.captcha = Captcha[noscript ? 'noscript' : 'v2'];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
@ -6726,7 +6704,7 @@
}
if (Conf['Hide Original Post Form']) {
$.addClass(doc, 'hide-original-post-form');
if (!doc.dataset.jsEnabled) {
if (!$.hasClass(doc, 'js-enabled')) {
return $.onExists(doc, '#postForm noscript', true, $.rm);
}
}
@ -7630,6 +7608,104 @@
Captcha = {};
Captcha.fixes = {
css: '.rc-imageselect-target > .rc-imageselect-tile > img:focus {\n outline: 2px solid #4a90e2;\n}\n.rc-button-default:focus {\n box-shadow: inset 0 0 0 2px #0063d6;\n}',
init: function() {
switch (location.pathname.split('/')[3]) {
case 'anchor':
return this.initMain();
case 'frame':
return this.initPopup();
}
},
initMain: function() {
return $.onExists(d.body, '#recaptcha-anchor', true, function(checkbox) {
var focus;
focus = function() {
if (d.hasFocus() && d.activeElement !== checkbox) {
return checkbox.focus();
}
};
focus();
return $.on(window, 'focus', function() {
return $.queueTask(focus);
});
});
},
initPopup: function() {
$.addStyle(this.css);
this.fixImages();
new MutationObserver((function(_this) {
return function() {
return _this.fixImages();
};
})(this)).observe(d.body, {
childList: true,
subtree: true
});
return $.on(d, 'keydown', this.keybinds.bind(this));
},
fixImages: function() {
var focus, img, k, len1, ref;
if (!(this.images = $$('.rc-imageselect-target > .rc-imageselect-tile > img')).length) {
return;
}
focus = this.images[0].tabIndex !== 0;
ref = this.images;
for (k = 0, len1 = ref.length; k < len1; k++) {
img = ref[k];
img.tabIndex = 0;
}
if (focus) {
return this.focusImage();
}
},
focusImage: function() {
var img;
img = this.images[0];
return $.asap(function() {
if (!doc.contains(img)) {
return true;
}
img.focus();
return d.activeElement === img;
}, function() {});
},
keybinds: function(e) {
var dx, reload, verify, x;
if (!(this.images && doc.contains(this.images[0]) && d.activeElement)) {
return;
}
reload = $.id('recaptcha-reload-button');
verify = $.id('recaptcha-verify-button');
x = this.images.indexOf(d.activeElement);
if (x < 0) {
if (!$('.rc-controls').contains(d.activeElement)) {
return;
}
x = d.activeElement === verify ? 11 : 9;
}
if (!(dx = {
38: 9,
40: 3,
37: 11,
39: 1
}[e.keyCode])) {
return;
}
x = (x + dx) % 12;
if (x === 10) {
x = dx === 11 ? 9 : 11;
}
(this.images[x] || {
9: reload,
11: verify
}[x]).focus();
e.preventDefault();
return e.stopPropagation();
}
};
Captcha.noscript = {
lifetime: 2 * $.MINUTE,
iframeURL: '//www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc',
@ -7989,20 +8065,6 @@
};
})(this));
},
initFrame: function() {
$.globalEval('window.focus = function() {};');
return $.on(window, 'focus', function() {
return $.queueTask(function() {
var checkbox;
if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
return;
}
if (d.activeElement !== checkbox) {
return checkbox.focus();
}
});
});
},
shouldFocus: false,
timeouts: {},
postsCount: 0,
@ -8102,6 +8164,7 @@
})(this));
},
destroy: function() {
var garbage, ins, k, len1, ref;
if (!this.isEnabled) {
return;
}
@ -8110,7 +8173,15 @@
if (this.nodes.container) {
$.rm(this.nodes.container);
}
return delete this.nodes.container;
delete this.nodes.container;
ref = $$('div > .gc-bubbleDefault');
for (k = 0, len1 = ref.length; k < len1; k++) {
garbage = ref[k];
if ((ins = garbage.parentNode.nextSibling) && ins.nodeName === 'INS') {
$.rm(ins);
}
$.rm(garbage.parentNode);
}
},
sync: function(captchas) {
if (captchas == null) {
@ -8132,7 +8203,7 @@
}
},
save: function(pasted) {
var base1;
var base1, focus, ref, ref1;
$.forceSync('captchas');
this.captchas.push({
response: $('textarea', this.nodes.container).value,
@ -8148,6 +8219,7 @@
}
this.reload();
} else {
focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && ((ref1 = d.activeElement.src) != null ? ref1.slice(0, 38) : void 0) === 'https://www.google.com/recaptcha/api2/';
if (pasted) {
this.destroy();
} else {
@ -8155,7 +8227,9 @@
base1.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND);
}
}
QR.nodes.status.focus();
if (focus) {
QR.nodes.status.focus();
}
}
if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) {
return QR.submit();
@ -11441,7 +11515,7 @@
},
subEntries: []
};
ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']];
ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Filename', 'filename'], ['Image MD5', 'MD5']];
for (k = 0, len1 = ref1.length; k < len1; k++) {
type = ref1[k];
entry.subEntries.push(this.createSubEntry(type[0], type[1]));
@ -11708,17 +11782,19 @@
el: a,
order: 10,
open: function(post) {
ReportLink.post = post;
return !post.isDead;
ReportLink.url = !post.isDead ? "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post : Conf['Archive Report'] ? Redirect.to('report', {
boardID: post.board.ID,
postID: post.ID
}) : void 0;
return !!ReportLink.url;
}
});
},
report: function() {
var id, post, set, url;
post = ReportLink.post;
url = "//sys.4chan.org/" + post.board + "/imgboard.php?mode=report&no=" + post;
var id, set, url;
url = ReportLink.url;
id = Date.now();
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=285";
set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1,width=685,height=200";
return window.open(url, id, set);
}
};
@ -13271,7 +13347,7 @@
return;
}
notif = new Notification(post.info.nameBlock + " replied to you", {
body: post.info[Conf['Remove Spoilers'] || Conf['Reveal Spoilers'] ? 'comment' : 'commentSpoilered'],
body: post.info.commentDisplay,
icon: Favicon.logo
});
notif.onclick = function() {
@ -13411,7 +13487,8 @@
o = {
thread: {},
post: {},
file: {}
file: {},
report: {}
};
archives = {};
ref = Redirect.archives;
@ -13421,17 +13498,19 @@
archives[name] = data;
for (q = 0, len2 = boards.length; q < len2; q++) {
boardID = boards[q];
if (!(!withCredentials)) {
continue;
if (!withCredentials) {
if (!(boardID in o.thread)) {
o.thread[boardID] = data;
}
if (!(boardID in o.post || software !== 'foolfuuka')) {
o.post[boardID] = data;
}
if (!(boardID in o.file || indexOf.call(files, boardID) < 0)) {
o.file[boardID] = data;
}
}
if (!(boardID in o.thread)) {
o.thread[boardID] = data;
}
if (!(boardID in o.post || software !== 'foolfuuka')) {
o.post[boardID] = data;
}
if (!(boardID in o.file || indexOf.call(files, boardID) < 0)) {
o.file[boardID] = data;
if (name === 'fgts') {
o.report[boardID] = data;
}
}
}
@ -13452,7 +13531,7 @@
}
return Redirect.data = o;
},
archives: [{"uid":0,"name":"Moe","domain":"archive.moe","http":false,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","fit","gd","h","i","int","jp","k","m","mlp","out","po","qa","r9k","s4s","sci","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","fit","gd","h","i","jp","k","m","mlp","po","qa","r9k","s4s","sci","tg","u","v","vg","vp","vr","wsg"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","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":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u","w","wg"],"files":["c","d","e","i","lgbt","t","u","w","wg"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","qa","w"],"files":["cgl","g","mu","qa","w"]},{"uid":10,"name":"warosu","domain":"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","g","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"],"files":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"]},{"uid":22,"name":"not4plebs","domain":"totally.not4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["sp"],"files":["sp"]},{"uid":23,"name":"DesuStorage","domain":"archive.desustorage.org","http":false,"https":true,"software":"foolfuuka","boards":["mlp","qa"],"files":["mlp","qa"]}],
archives: [{"uid":0,"name":"Moe","domain":"archive.moe","http":false,"https":true,"software":"foolfuuka","boards":["a","biz","c","co","diy","fit","gd","gif","h","i","int","jp","k","m","mlp","out","po","qa","r9k","s4s","sci","tg","tv","u","v","vg","vp","vr","wsg"],"files":["a","biz","c","co","diy","fit","gd","h","i","jp","k","m","mlp","po","qa","r9k","s4s","sci","tg","u","v","vg","vp","vr","wsg"]},{"uid":3,"name":"4plebs Archive","domain":"archive.4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"],"files":["adv","f","hr","o","pol","s4s","tg","trv","tv","x"]},{"uid":4,"name":"Nyafuu Archive","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":"archive.loveisover.me","http":true,"https":true,"software":"foolfuuka","boards":["c","d","e","i","lgbt","t","u"],"files":["c","d","e","i","lgbt","t","u"]},{"uid":8,"name":"Rebecca Black Tech","domain":"rbt.asia","http":false,"https":true,"software":"fuuka","boards":["cgl","g","mu","qa","w"],"files":["cgl","g","mu","qa","w"]},{"uid":10,"name":"warosu","domain":"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","g","ic","jp","lit","sci","tg","vr"]},{"uid":15,"name":"fgts","domain":"fgts.jp","http":true,"https":true,"software":"foolfuuka","boards":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"],"files":["asp","b","cm","h","hc","hm","n","p","qa","r","s","soc","toy","y"]},{"uid":22,"name":"not4plebs","domain":"totally.not4plebs.org","http":true,"https":true,"software":"foolfuuka","boards":["sp"],"files":["sp"]},{"uid":23,"name":"DesuStorage","domain":"archive.desustorage.org","http":false,"https":true,"software":"foolfuuka","boards":["mlp","qa"],"files":["mlp","qa"]}],
to: function(dest, data) {
var archive;
archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID];
@ -13506,10 +13585,20 @@
var boardID, path, type, value;
boardID = arg.boardID, type = arg.type, value = arg.value;
type = type === 'name' ? 'username' : type === 'MD5' ? 'image' : type;
if (type === 'capcode') {
value = {
'Developer': 'dev'
}[value] || value.toLowerCase();
}
value = encodeURIComponent(value);
path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value : boardID + "/?task=search2&search_" + (type === 'image' ? 'media_hash' : type) + "=" + value;
return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path;
},
report: function(archive, arg) {
var boardID, postID;
boardID = arg.boardID, postID = arg.postID;
return "https://so.fgts.jp/report/?board=" + boardID + "&no=" + postID;
},
securityCheck: function(URL) {
return /^https:\/\//.test(URL) || location.protocol === 'http:' || Conf['Except Archives from Encryption'];
},
@ -15229,6 +15318,63 @@
}
};
Report = {
init: function() {
var match;
if (!(/\bmode=report\b/.test(location.search) && (match = location.search.match(/\bno=(\d+)/)))) {
return;
}
this.postID = +match[1];
return $.ready(this.ready);
},
ready: function() {
new MutationObserver(Report.resize).observe(d.body, {
childList: true,
attributes: true,
subtree: true
});
if (Conf['Archive Report']) {
return Report.archive();
}
},
resize: function() {
var bubble, dy;
if (!(bubble = $('.gc-bubbleDefault'))) {
return;
}
dy = bubble.getBoundingClientRect().bottom - doc.clientHeight;
if (dy > 0) {
return window.resizeBy(0, dy);
}
},
archive: function() {
var link, message, url;
Redirect.init();
if (!(url = Redirect.to('report', {
boardID: g.BOARD.ID,
postID: Report.postID
}))) {
return;
}
if ((message = $('h3')) && /Report submitted!/.test(message.textContent)) {
$.globalEval('self.close = function(){};');
window.resizeTo(685, 320);
location.replace(url);
return;
}
link = $.el('a', {
href: url,
textContent: 'Report to fgts'
});
$.on(link, 'click', function(e) {
if (!(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0)) {
return window.resizeTo(685, 320);
}
});
return $.add(d.body, [$.tn(' ['), link, $.tn(']')]);
}
};
Time = {
init: function() {
var ref;
@ -16018,12 +16164,24 @@
Main = {
init: function() {
var db, flatten, k, len1, pathname, ref, ref1, ref2, type;
var db, flatten, k, len1, pathname, ref, ref1, ref2;
if (location.hostname === 'www.google.com') {
type = location.pathname === '/recaptcha/api/fallback' ? 'noscript' : 'v2';
return $.ready(function() {
return Captcha[type].initFrame();
});
if (location.pathname === '/recaptcha/api/fallback') {
$.ready(function() {
return Captcha.noscript.initFrame();
});
} else {
$.get('Captcha Fixes', true, function(arg) {
var enabled;
enabled = arg['Captcha Fixes'];
if (enabled) {
return $.ready(function() {
return Captcha.fixes.init();
});
}
});
}
return;
}
g.threads = new SimpleDict();
g.posts = new SimpleDict();
@ -16097,6 +16255,7 @@
case 'a.4cdn.org':
return;
case 'sys.4chan.org':
Report.init();
if (g.VIEW === 'post') {
PostSuccessful.init();
}
@ -17096,10 +17255,8 @@
" /* party hats */\n" +
" pointer-events: none;\n" +
"}\n" +
"marquee,\n" +
".postMessage marquee + br,\n" +
".postMessage marquee + br + br {\n" +
" display: none;\n" +
":root:not(.js-enabled) #postForm {\n" +
" display: table;\n" +
"}\n" +
"/* Anti-autoplay */\n" +
"audio.controls-added {\n" +

Binary file not shown.

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.10.8.9' />
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.10.11.1' />
</app>
</gupdate>

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.10.8.9' />
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.10.11.1' />
</app>
</gupdate>

202
npm-shrinkwrap.json generated
View File

@ -465,198 +465,6 @@
}
}
},
"grunt-contrib-compress": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-0.13.0.tgz",
"dependencies": {
"archiver": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-0.13.1.tgz",
"dependencies": {
"async": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz"
},
"buffer-crc32": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.5.tgz"
},
"glob": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz",
"dependencies": {
"inflight": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
}
}
},
"inherits": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"minimatch": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz",
"dependencies": {
"brace-expansion": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz",
"dependencies": {
"balanced-match": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz"
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
}
}
}
}
},
"once": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
}
}
}
}
},
"lazystream": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz"
},
"lodash": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz"
},
"readable-stream": {
"version": "1.0.33",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz",
"dependencies": {
"core-util-is": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz"
},
"inherits": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
}
}
},
"tar-stream": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.1.2.tgz",
"dependencies": {
"bl": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/bl/-/bl-0.9.3.tgz"
},
"end-of-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz",
"dependencies": {
"once": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz"
}
}
}
}
},
"xtend": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz"
}
}
},
"zip-stream": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.5.0.tgz",
"dependencies": {
"compress-commons": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-0.2.0.tgz",
"dependencies": {
"crc32-stream": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-0.3.1.tgz"
},
"node-int64": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.3.3.tgz"
}
}
}
}
}
}
},
"chalk": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
"dependencies": {
"ansi-styles": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz"
},
"escape-string-regexp": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz"
},
"has-ansi": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
"dependencies": {
"ansi-regex": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz"
}
}
},
"strip-ansi": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
"dependencies": {
"ansi-regex": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz"
}
}
},
"supports-color": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz"
}
}
},
"prettysize": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/prettysize/-/prettysize-0.0.3.tgz"
}
}
},
"grunt-contrib-concat": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-0.5.1.tgz",
@ -1081,6 +889,16 @@
}
}
},
"jszip": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-2.5.0.tgz",
"dependencies": {
"pako": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.6.tgz"
}
}
},
"load-grunt-tasks": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.1.0.tgz",

View File

@ -3,8 +3,8 @@
"description": "Cross-browser userscript for maximum lurking on 4chan.",
"meta": {
"name": "4chan X",
"version": "1.10.8.9",
"date": "2015-04-13T15:07:30.185Z",
"version": "1.10.11.1",
"date": "2015-04-24T14:48:43.242Z",
"repo": "https://github.com/ccd0/4chan-x/",
"page": "https://github.com/ccd0/4chan-x",
"downloads": "https://ccd0.github.io/4chan-x/builds/",
@ -22,6 +22,7 @@
"*://a.4cdn.org/*",
"*://i.4cdn.org/*",
"https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*",
"https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*",
"*://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc"
],
"suffix": {
@ -49,7 +50,6 @@
"grunt-concurrent": "^1.0.0",
"grunt-contrib-clean": "^0.6.0",
"grunt-contrib-coffee": "^0.13.0",
"grunt-contrib-compress": "^0.13.0",
"grunt-contrib-concat": "^0.5.1",
"grunt-contrib-copy": "^0.8.0",
"grunt-contrib-jshint": "^0.11.1",
@ -57,6 +57,7 @@
"grunt-markdown": "^0.7.0",
"grunt-shell": "^1.1.2",
"grunt-webstore-upload": "^0.8.2",
"jszip": "^2.5.0",
"load-grunt-tasks": "^3.1.0",
"npm-shrinkwrap": "^5.3.0"
},

View File

@ -4,15 +4,18 @@ Redirect =
thread: {}
post: {}
file: {}
report: {}
archives = {}
for data in Redirect.archives
{name, boards, files, software, withCredentials} = data
archives[name] = data
for boardID in boards when !withCredentials
o.thread[boardID] = data unless boardID of o.thread
o.post[boardID] = data unless boardID of o.post or software isnt 'foolfuuka'
o.file[boardID] = data unless boardID of o.file or boardID not in files
for boardID in boards
unless withCredentials
o.thread[boardID] = data unless boardID of o.thread
o.post[boardID] = data unless boardID of o.post or software isnt 'foolfuuka'
o.file[boardID] = data unless boardID of o.file or boardID not in files
o.report[boardID] = data if name is 'fgts'
for boardID, record of Conf['selectedArchives']
for type, id of record
@ -84,6 +87,9 @@ Redirect =
"#{boardID}/?task=search2&search_#{if type is 'image' then 'media_hash' else type}=#{value}"
"#{Redirect.protocol archive}#{archive.domain}/#{path}"
report: (archive, {boardID, postID}) ->
"https://so.fgts.jp/report/?board=#{boardID}&no=#{postID}"
securityCheck: (URL) ->
/^https:\/\//.test(URL) or
location.protocol is 'http:' or

View File

@ -5,7 +5,7 @@
"http": false,
"https": true,
"software": "foolfuuka",
"boards": ["a", "biz", "c", "co", "diy", "fit", "gd", "h", "i", "int", "jp", "k", "m", "mlp", "out", "po", "qa", "r9k", "s4s", "sci", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
"boards": ["a", "biz", "c", "co", "diy", "fit", "gd", "gif", "h", "i", "int", "jp", "k", "m", "mlp", "out", "po", "qa", "r9k", "s4s", "sci", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
"files": ["a", "biz", "c", "co", "diy", "fit", "gd", "h", "i", "jp", "k", "m", "mlp", "po", "qa", "r9k", "s4s", "sci", "tg", "u", "v", "vg", "vp", "vr", "wsg"]
}, {
"uid": 3,
@ -32,8 +32,8 @@
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["c", "d", "e", "i", "lgbt", "t", "u", "w", "wg"],
"files": ["c", "d", "e", "i", "lgbt", "t", "u", "w", "wg"]
"boards": ["c", "d", "e", "i", "lgbt", "t", "u"],
"files": ["c", "d", "e", "i", "lgbt", "t", "u"]
}, {
"uid": 8,
"name": "Rebecca Black Tech",

View File

@ -35,6 +35,10 @@ Config =
true
'Redirect dead threads and images to the archives.'
]
'Archive Report': [
true
'Enable reporting posts to supported archives.'
]
'Except Archives from Encryption': [
false
'Permit loading content from, and warningless redirects to, HTTP-only archives from HTTPS pages.'
@ -474,6 +478,10 @@ Config =
'Places a link on the bottom of threads to open the QR.'
1
]
'Captcha Fixes': [
true
'Make captcha more keyboard-navigable.'
]
'Quote Links':
'Quote Backlinks': [

View File

@ -3,7 +3,7 @@ Get =
{OP} = thread
excerpt = "/#{thread.board}/ - " + (
OP.info.subject?.trim() or
OP.info.comment.replace(/\n+/g, ' // ') or
OP.info.commentDisplay.replace(/\n+/g, ' // ') or
OP.info.nameBlock)
return "#{excerpt[...70]}..." if excerpt.length > 73
excerpt

View File

@ -1,8 +1,13 @@
Main =
init: ->
if location.hostname is 'www.google.com'
type = if location.pathname is '/recaptcha/api/fallback' then 'noscript' else 'v2'
return $.ready -> Captcha[type].initFrame()
if location.pathname is '/recaptcha/api/fallback'
$.ready -> Captcha.noscript.initFrame()
else
$.get 'Captcha Fixes', true, ({'Captcha Fixes': enabled}) ->
if enabled
$.ready -> Captcha.fixes.init()
return
g.threads = new SimpleDict()
g.posts = new SimpleDict()
@ -56,6 +61,7 @@ Main =
when 'a.4cdn.org'
return
when 'sys.4chan.org'
Report.init()
PostSuccessful.init() if g.VIEW is 'post'
return
when 'i.4cdn.org'

View File

@ -105,10 +105,8 @@ hr + div.center:not(.ad-cnt):not(.topad):not(.middlead):not(.bottomad) {
/* party hats */
pointer-events: none;
}
marquee,
.postMessage marquee + br,
.postMessage marquee + br + br {
display: none;
:root:not(.js-enabled) #postForm {
display: table;
}
/* Anti-autoplay */
@ -1282,6 +1280,7 @@ input.field.tripped:not(:hover):not(:focus) {
background: linear-gradient(to bottom, #F8F8F8, #DCDCDC) no-repeat;
border: 1px solid #BBB;
border-radius: 2px;
height: 100%;
}
#qr-file-button {
width: 15%;

View File

@ -125,8 +125,8 @@ $.onExists = (root, selector, subtree, cb) ->
$.addStyle = (css, id, test) ->
style = $.el 'style',
id: id
textContent: css
style.id = id if id?
$.asap (-> d.head and (!test? or test())), ->
$.add d.head, style
style

View File

@ -106,22 +106,28 @@ class Post
# 'Comment too long'...
# EXIF data. (/p/)
# Rolls. (/tg/)
# Marquees. (/pol/)
# Fortunes. (/s4s/)
bq = @nodes.comment.cloneNode true
for node in $$ '.abbr + br, .exif, b, .fortune', bq
$.rm node
if abbr = $ '.abbr', bq
$.rm abbr
@info.comment = @nodesToText bq
if abbr
@info.comment = @info.comment.replace /\n\n$/, ''
# Hide spoilers.
# Remove:
# Preceding and following new lines.
# Trailing spaces.
bq = @nodes.comment.cloneNode true
for node in $$ '.abbr, .exif, b, marquee', bq
$.rm node
@info.comment = @nodesToText bq
# Get the comment's text with spoilers hidden.
spoilers = $$ 's', bq
@info.commentSpoilered = if spoilers.length
for node in spoilers
$.replace node, $.tn '[spoiler]'
@nodesToText bq
else
@info.comment
commentDisplay = @info.comment
unless Conf['Remove Spoilers'] or Conf['Reveal Spoilers']
spoilers = $$ 's', bq
if spoilers.length
for node in spoilers
$.replace node, $.tn '[spoiler]'
commentDisplay = @nodesToText bq
@info.commentDisplay = commentDisplay.trim().replace /\s+$/gm, ''
nodesToText: (bq) ->
text = ""
@ -129,7 +135,7 @@ class Post
i = 0
while node = nodes.snapshotItem i++
text += node.data or '\n'
text.trim().replace /\s+$/gm, ''
text
parseQuotes: ->
@quotes = []

View File

@ -11,11 +11,14 @@ ReportLink =
el: a
order: 10
open: (post) ->
ReportLink.post = post
!post.isDead
ReportLink.url = unless post.isDead
"//sys.4chan.org/#{post.board}/imgboard.php?mode=report&no=#{post}"
else if Conf['Archive Report']
Redirect.to 'report', {boardID: post.board.ID, postID: post.ID}
!!ReportLink.url
report: ->
{post} = ReportLink
url = "//sys.4chan.org/#{post.board}/imgboard.php?mode=report&no=#{post}"
{url} = ReportLink
id = Date.now()
set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=285"
set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1,width=685,height=200"
window.open url, id, set

34
src/Miscellaneous/Report.coffee Executable file
View File

@ -0,0 +1,34 @@
Report =
init: ->
return unless /\bmode=report\b/.test(location.search) and match = location.search.match /\bno=(\d+)/
@postID = +match[1]
$.ready @ready
ready: ->
new MutationObserver(Report.resize).observe d.body,
childList: true
attributes: true
subtree: true
Report.archive() if Conf['Archive Report']
resize: ->
return unless bubble = $ '.gc-bubbleDefault'
dy = bubble.getBoundingClientRect().bottom - doc.clientHeight
window.resizeBy 0, dy if dy > 0
archive: ->
Redirect.init()
return unless url = Redirect.to 'report', {boardID: g.BOARD.ID, postID: Report.postID}
if (message = $ 'h3') and /Report submitted!/.test(message.textContent)
$.globalEval 'self.close = function(){};'
window.resizeTo 685, 320
location.replace url
return
link = $.el 'a',
href: url
textContent: 'Report to fgts'
$.on link, 'click', (e) ->
unless e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
window.resizeTo 685, 320
$.add d.body, [$.tn(' ['), link, $.tn(']')]

View File

@ -128,7 +128,7 @@ Unread =
openNotification: (post) ->
return unless Header.areNotificationsEnabled
notif = new Notification "#{post.info.nameBlock} replied to you",
body: post.info[if Conf['Remove Spoilers'] or Conf['Reveal Spoilers'] then 'comment' else 'commentSpoilered']
body: post.info.commentDisplay
icon: Favicon.logo
notif.onclick = ->
Header.scrollToIfNeeded post.nodes.root, true

View File

@ -0,0 +1,61 @@
Captcha.fixes =
css: '''
.rc-imageselect-target > .rc-imageselect-tile > img:focus {
outline: 2px solid #4a90e2;
}
.rc-button-default:focus {
box-shadow: inset 0 0 0 2px #0063d6;
}
'''
init: ->
switch location.pathname.split('/')[3]
when 'anchor' then @initMain()
when 'frame' then @initPopup()
initMain: ->
$.onExists d.body, '#recaptcha-anchor', true, (checkbox) ->
focus = ->
if d.hasFocus() and d.activeElement isnt checkbox
checkbox.focus()
focus()
$.on window, 'focus', ->
$.queueTask focus
initPopup: ->
$.addStyle @css
@fixImages()
new MutationObserver(=> @fixImages()).observe d.body, {childList: true, subtree: true}
$.on d, 'keydown', @keybinds.bind(@)
fixImages: ->
return unless (@images = $$ '.rc-imageselect-target > .rc-imageselect-tile > img').length
focus = @images[0].tabIndex isnt 0
for img in @images
img.tabIndex = 0
@focusImage() if focus
focusImage: ->
# XXX Image is not focusable at first in Firefox; to be refactored when I figure out why.
img = @images[0]
$.asap ->
return true unless doc.contains img
img.focus()
d.activeElement is img
, ->
keybinds: (e) ->
return unless @images and doc.contains(@images[0]) and d.activeElement
reload = $.id 'recaptcha-reload-button'
verify = $.id 'recaptcha-verify-button'
x = @images.indexOf d.activeElement
if x < 0
return unless $('.rc-controls').contains d.activeElement
x = if d.activeElement is verify then 11 else 9
return unless dx = {38: 9, 40: 3, 37: 11, 39: 1}[e.keyCode] # Up, Down, Left, Right
x = (x + dx) % 12
if x is 10
x = if dx is 11 then 9 else 11
(@images[x] or {9: reload, 11: verify}[x]).focus()
e.preventDefault()
e.stopPropagation()

View File

@ -25,13 +25,6 @@ Captcha.v2 =
# XXX Greasemonkey 1.x workaround to gain access to GM_* functions.
$.queueTask => @save false
initFrame: ->
$.globalEval 'window.focus = function() {};'
$.on window, 'focus', ->
$.queueTask ->
return unless d.hasFocus() and (checkbox = $.id 'recaptcha-anchor')
checkbox.focus() unless d.activeElement is checkbox
shouldFocus: false
timeouts: {}
postsCount: 0
@ -125,6 +118,11 @@ Captcha.v2 =
$.rmClass QR.nodes.el, 'captcha-open'
$.rm @nodes.container if @nodes.container
delete @nodes.container
# Clean up abandoned iframes.
for garbage in $$ 'div > .gc-bubbleDefault'
$.rm ins if (ins = garbage.parentNode.nextSibling) and ins.nodeName is 'INS'
$.rm garbage.parentNode
return
sync: (captchas=[]) ->
@captchas = captchas
@ -155,11 +153,12 @@ Captcha.v2 =
QR.nodes.status.focus()
@reload()
else
focus = d.activeElement?.nodeName is 'IFRAME' and d.activeElement.src?[...38] is 'https://www.google.com/recaptcha/api2/'
if pasted
@destroy()
else
@timeouts.destroy ?= setTimeout @destroy.bind(@), 3 * $.SECOND
QR.nodes.status.focus()
QR.nodes.status.focus() if focus
QR.submit() if Conf['Post on Captcha Completion'] and !QR.cooldown.auto

View File

@ -9,8 +9,8 @@ QR =
return if g.VIEW is 'archive'
$.globalEval 'document.documentElement.dataset.jsEnabled = true;'
noscript = Conf['Force Noscript Captcha'] or !doc.dataset.jsEnabled
$.globalEval 'document.documentElement.classList.add("js-enabled");'
noscript = Conf['Force Noscript Captcha'] or not $.hasClass doc, 'js-enabled'
@captcha = Captcha[if noscript then 'noscript' else 'v2']
$.on d, '4chanXInitFinished', @initReady
@ -37,7 +37,7 @@ QR =
if Conf['Hide Original Post Form']
$.addClass doc, 'hide-original-post-form'
if !doc.dataset.jsEnabled
unless $.hasClass doc, 'js-enabled'
# Prevent unnecessary loading of fallback iframe.
$.onExists doc, '#postForm noscript', true, $.rm