diff --git a/4chan_x.meta.js b/4chan_x.meta.js deleted file mode 100644 index 0f81bc89f..000000000 --- a/4chan_x.meta.js +++ /dev/null @@ -1,20 +0,0 @@ -// ==UserScript== -// @name 4chan x -// @namespace aeosynth -// @version 1.0.11 -// @description Cross-browser userscript for maximum lurking on 4chan. -// @copyright 2013-2013 Zixaphir -// @copyright 2013-2013 Jordan Bates -// @copyright 2009-2011 James Campos -// @copyright 2012-2013 Nicolas Stepien -// @license MIT; http://en.wikipedia.org/wiki/Mit_license -// @match *://*.4chan.org/* -// @grant GM_getValue -// @grant GM_setValue -// @grant GM_deleteValue -// @grant GM_openInTab -// @run-at document-start -// @updateURL https://github.com/seaweedchan/4chan-x/raw/stable/4chan_x.meta.js -// @downloadURL https://github.com/seaweedchan/4chan-x/raw/stable/4chan_x.user.js -// @icon data:image/gif;base64,R0lGODlhYAAQAJEAAGbMM////wAAAP///yH5BAEAAAMALAAAAABgABAAAAL8nI+py+0Po5y02ruEFmh7PnxbJ3KecR4pqoWr2iajIgR2AIb3bu43WPPhdENiLmg7Jn25EODZFDwBTSIPJRwir1tuElvshrNf1RR4lv2QPZzmG9zA16c4uO3+WeVl55Qq9RdVZlc4p3VYdcfXBpSo0ufyJ1gVx2j0huhmWKSW1Xhpd0czSZVBhucl1Hj6acVkBNnZIcggdgh7y0qTFIoaOypTqoiZCTpjiRwp66jp8RhsVmrq2bzbsbz3AcxpDfztBxUIVT0qij0LtsoN3c1MSx5eSQiNTqzL7mzed+4khfZPBrIRL1jEoFHCRYw6A1usKGiiQwgMFCtalFAAADs= -// ==/UserScript== diff --git a/4chan_x.user.js b/4chan_x.user.js deleted file mode 100644 index b969a3b44..000000000 --- a/4chan_x.user.js +++ /dev/null @@ -1,7876 +0,0 @@ -// ==UserScript== -// @name 4chan x -// @namespace aeosynth -// @version 1.0.11 -// @description Old v2 version to point to new 4chan X. -// @copyright 2013-2013 Zixaphir -// @copyright 2013-2013 Jordan Bates -// @copyright 2009-2011 James Campos -// @copyright 2012-2013 Nicolas Stepien -// @license MIT; http://en.wikipedia.org/wiki/Mit_license -// @match *://*.4chan.org/* -// @grant GM_getValue -// @grant GM_setValue -// @grant GM_deleteValue -// @grant GM_openInTab -// @run-at document-start -// @updateURL https://github.com/seaweedchan/4chan-x/raw/stable/4chan_x.meta.js -// @downloadURL https://github.com/seaweedchan/4chan-x/raw/stable/4chan_x.user.js -// @icon data:image/gif;base64,R0lGODlhYAAQAJEAAGbMM////wAAAP///yH5BAEAAAMALAAAAABgABAAAAL8nI+py+0Po5y02ruEFmh7PnxbJ3KecR4pqoWr2iajIgR2AIb3bu43WPPhdENiLmg7Jn25EODZFDwBTSIPJRwir1tuElvshrNf1RR4lv2QPZzmG9zA16c4uO3+WeVl55Qq9RdVZlc4p3VYdcfXBpSo0ufyJ1gVx2j0huhmWKSW1Xhpd0czSZVBhucl1Hj6acVkBNnZIcggdgh7y0qTFIoaOypTqoiZCTpjiRwp66jp8RhsVmrq2bzbsbz3AcxpDfztBxUIVT0qij0LtsoN3c1MSx5eSQiNTqzL7mzed+4khfZPBrIRL1jEoFHCRYw6A1usKGiiQwgMFCtalFAAADs= -// ==/UserScript== - -/* - * 4chan x - Version 1.0.11 - 2013-04-25 - * - * Licensed under the MIT license. - * https://github.com/seaweedchan/4chan-x/blob/4chanX/LICENSE - * - * Appchan X Copyright © 2013-2013 Zixaphir - * http://zixaphir.github.io/appchan-x/ - * 4chan x Copyright © 2009-2011 James Campos - * https://github.com/aeosynth/4chan-x - * 4chan x Copyright © 2012-2013 Nicolas Stepien - * https://4chan-x.just-believe.in/ - * 4chan x Copyright © 2013-2013 Jordan Bates - * http://seaweedchan.github.io/4chan-x/ - * 4chan x Copyright © 2012-2013 ihavenoface - * http://ihavenoface.github.io/4chan-x/ - * OneeChan Copyright © 2011-2013 Jordan Bates - * http://seaweedchan.github.io/oneechan/ - * 4chan SS Copyright © 2011-2013 Ahodesuka - * https://github.com/ahodesuka/4chan-Style-Script/ - * Raphael Icons Copyright © 2013 Dmitry Baranovskiy - * http://raphaeljs.com/icons/ - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Contributors: - * aeosynth - * mayhemydg - * noface - * !K.WeEabo0o - * blaise - * that4chanwolf - * desuwa - * seaweed - * e000 - * ahodesuka - * Shou - * ferongr - * xat - * Ongpot - * thisisanon - * Anonymous - * Seiba - * herpaderpderp - * WakiMiko - * btmcsweeney - * AppleBloom - * - * All the people who've taken the time to write bug reports. - * - * Thank you. - */ - -/* - * Linkify based on: - * http://downloads.mozdev.org/greasemonkey/linkify.user.js - * https://github.com/MayhemYDG/LinkifyPlusFork - * - * Originally written by Anthony Lieuallen of http://arantius.com/ - * Licensed for unlimited modification and redistribution as long as - * this notice is kept intact. - */ - -/* - * JSColor, JavaScript Color Picker - * - * @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html - * @author Jan Odvarko, http://odvarko.cz - * @link http://JSColor.com - */ - -(function() { - var $, $$, AnnouncementHiding, Anonymize, ArchiveLink, BanChecker, Build, CatalogLinks, Conf, Config, CustomNavigation, DeleteLink, DownloadLink, EmbedLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Get, IDColor, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, MarkOwn, Markdown, Menu, MutationObserver, Nav, Navigation, Options, Prefetch, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, Quotify, Redirect, RelativeDates, RemoveSpoilers, ReplyHideLink, ReplyHiding, ReportLink, RevealSpoilers, Sauce, StrikethroughQuotes, Style, ThreadHideLink, ThreadHiding, ThreadStats, Time, TitlePost, UI, Unread, UpdateAlert, Updater, Watcher, d, g, userNavigation, _base, - __slice = [].slice; - - Config = { - main: { - Enhancing: { - 'Catalog Links': [true, 'Turn Navigation links into links to each board\'s catalog.'], - 'External Catalog': [false, 'Link to external catalog instead of the internal one.'], - '404 Redirect': [true, 'Redirect dead threads and images'], - 'Keybinds': [true, 'Binds actions to keys'], - 'Time Formatting': [true, 'Arbitrarily formatted timestamps, using your local time'], - 'Relative Post Dates': [false, 'Display dates as "3 minutes ago" f.e., tooltip shows the timestamp'], - 'File Info Formatting': [true, 'Reformats the file information'], - 'Comment Expansion': [true, 'Expand too long comments'], - 'Thread Expansion': [true, 'View all replies'], - 'Index Navigation': [false, 'Navigate to previous / next thread'], - 'Reply Navigation': [false, 'Navigate to top / bottom of thread'], - 'Custom Navigation': [false, 'Customize your Navigation bar.'], - 'Append Delimiters': [false, 'Adds delimiters before and after custom navigation.'], - 'Check for Updates': [true, 'Check for updated versions of 4chan X'], - 'Check for Bans': [false, 'Check ban status and prepend it to the top of the page.'], - 'Check for Bans constantly': [false, 'Optain ban status on every refresh. Note that this will cause delay on getting the result.'], - 'Custom CSS': [false, 'Add your own CSS to 4chan.'], - 'Emoji': [false, 'Adds icons next to names for different emails'] - }, - Linkification: { - 'Linkify': [true, 'Convert text into links where applicable.'], - 'Embedding': [true, 'Embed supported services.'], - 'Link Title': [true, 'Replace the link of a supported site with its actual title. Currently Supported: YouTube, Vimeo, SoundCloud'] - }, - Filtering: { - 'Announcement Hiding': [false, 'Allow toggling of announcement. New announcements will unhide automatically.'], - 'Anonymize': [false, 'Make everybody anonymous'], - 'Filter': [true, 'Self-moderation placebo'], - 'Recursive Filtering': [true, 'Filter replies of filtered posts, recursively'], - 'Reply Hiding': [false, 'Hide single replies'], - 'Thread Hiding': [false, 'Hide entire threads'], - 'Show Stubs': [true, 'Of hidden threads / replies'] - }, - Imaging: { - 'Image Expansion': [true, 'Expand images'], - 'Image Hover': [false, 'Show full image on mouseover'], - 'Sauce': [true, 'Add sauce to images'], - 'Reveal Spoilers': [false, 'Replace spoiler thumbnails by the original thumbnail'], - 'Don\'t Expand Spoilers': [true, 'Don\'t expand spoilers when using ImageExpand.'], - 'Expand From Current': [false, 'Expand images from current position to thread end.'], - 'Fappe Tyme': [false, 'Toggle display of posts without images.'], - 'Prefetch': [false, 'Prefetch images.'], - 'Replace GIF': [false, 'Replace thumbnail of gifs with its actual image.'], - 'Replace PNG': [false, 'Replace pngs.'], - 'Replace JPG': [false, 'Replace jpgs.'] - }, - Menu: { - 'Menu': [true, 'Add a drop-down menu in posts.'], - 'Report Link': [true, 'Add a report link to the menu.'], - 'Delete Link': [true, 'Add post and image deletion links to the menu.'], - 'Download Link': [false, 'Add a download with original filename link to the menu. Chrome-only currently.'], - 'Archive Link': [true, 'Add an archive link to the menu.'], - 'Embed Link': [true, 'Add an embed link to the menu to embed all supported formats in a post.'], - 'Thread Hiding Link': [true, 'Add a link to hide entire threads.'], - 'Reply Hiding Link': [true, 'Add a link to hide single replies.'] - }, - Monitoring: { - 'Thread Updater': [true, 'Update threads. Has more options in its own dialog.'], - 'Optional Increase': [false, 'Increase value of Updater over time.'], - 'Interval per board': [false, 'Change the intervals of updates on a board-by-board basis.'], - 'Unread Count': [true, 'Show unread post count in tab title'], - 'Unread Favicon': [true, 'Show a different favicon when there are unread posts'], - 'Post in Title': [true, 'Show the op\'s post in the tab title'], - 'Thread Stats': [true, 'Display reply and image count'], - 'Merged Updater and Stats': [false, 'Merges the updater and thread stats into one container.'], - 'Thread Watcher': [false, 'Bookmark threads'], - 'Auto Watch': [true, 'Automatically watch threads that you start'], - 'Auto Watch Reply': [false, 'Automatically watch threads that you reply to'], - 'Color user IDs': [false, 'Assign unique colors to user IDs on boards that use them'], - 'Remove Spoilers': [false, 'Remove all spoilers in text.'], - 'Indicate Spoilers': [false, 'Indicate spoilers if Remove Spoilers is enabled.'] - }, - Posting: { - 'Quick Reply': [true, 'Reply without leaving the page'], - 'Cooldown': [true, 'Prevent "flood detected" errors.'], - 'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.'], - 'Auto Hide QR': [false, 'Automatically hide the quick reply when posting.'], - 'Open Reply in New Tab': [false, 'Open replies in a new tab that are made from the main board.'], - 'Per Board Persona': [false, 'Remember Name, Email, Subject, etc per board instead of globally.'], - 'Remember QR size': [false, 'Remember the size of the Quick reply (Firefox only).'], - 'Remember Subject': [false, 'Remember the subject field, instead of resetting after posting.'], - 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.'], - 'Remember Sage': [false, 'Remember email even if it contains sage.'], - 'Hide Original Post Form': [true, 'Replace the normal post form with a shortcut to open the QR'], - 'Markdown': [false, 'Code, italic, bold, italic bold, double struck - `, *, **, ***, ||, respectively. _ can be used instead of *.'] - }, - Quoting: { - 'Quote Backlinks': [true, 'Add quote backlinks'], - 'OP Backlinks': [false, 'Add backlinks to the OP'], - 'Quote Highlighting': [true, 'Highlight the previewed post'], - 'Quote Inline': [true, 'Show quoted post inline on quote click'], - 'Quote Hash Navigation': [false, 'Show a "#" to jump around the thread as if Quote Inline were disabled.'], - 'Quote Preview': [true, 'Show quote content on hover'], - 'Resurrect Quotes': [true, 'Linkify dead quotes to archives'], - 'Indicate OP quote': [true, 'Add \'(OP)\' to OP quotes'], - 'Indicate Cross-thread Quotes': [true, 'Add \'(Cross-thread)\' to cross-threads quotes'], - 'Indicate Own Posts': [true, 'Add (you) to posts you\'ve authored.'], - 'Forward Hiding': [true, 'Hide original posts of inlined backlinks'] - } - }, - filter: { - name: "# Filter any namefags:\n#/^(?!Anonymous$)/", - uniqueid: "# Filter a specific ID:\n#/Txhvk1Tl/", - tripcode: "# Filter any tripfags\n#/^!/", - mod: "# Set a custom class for mods:\n#/Mod$/;highlight:mod;op:yes\n# Set a custom class for moot:\n#/Admin$/;highlight:moot;op:yes", - email: "# Filter any e-mails that are not `sage` on /a/ and /jp/:\n#/^(?!sage$)/;boards:a,jp", - subject: "# Filter Generals on /v/:\n#/general/i;boards:v;op:only'", - comment: "# Filter Stallman copypasta on /g/:\n#/what you\'re refer+ing to as linux/i;boards:g", - country: '', - filename: '', - dimensions: "# Highlight potential wallpapers:\n#/1920x1080/;op:yes;highlight;top:no;boards:w,wg", - filesize: '', - md5: '' - }, - sauces: "http://iqdb.org/?url=$1\nhttp://www.google.com/searchbyimage?image_url=$1\n#http://tineye.com/search?url=$1\n#http://saucenao.com/search.php?db=999&url=$1\n#http://3d.iqdb.org/?url=$1\n#http://regex.info/exif.cgi?imgurl=$2\n# uploaders:\n#http://imgur.com/upload?url=$2;text:Upload to imgur\n#http://omploader.org/upload?url1=$2;text:Upload to omploader\n# \"View Same\" in archives:\n#http://archive.foolz.us/_/search/image/$3/;text:View same on foolz\n#http://archive.foolz.us/$4/search/image/$3/;text:View same on foolz /$4/\n#https://archive.installgentoo.net/$4/image/$3;text:View same on installgentoo /$4/", - time: '%m/%d/%y(%a)%H:%M', - backlink: '>>%id', - fileInfo: '%L (%p%s, %r)', - favicon: 'ferongr', - sageEmoji: 'appchan', - emojiPos: 'before', - updateIncrease: '5,10,15,20,30,60,90,120,240,300', - updateIncreaseB: '5,10,15,20,30,60,90,120,240,300', - customCSS: "/* Block Ads */\n/*\ndiv.center {\n display: none;\n}\n*/\n/* Tripcode Italics: */\n/*\nspan.postertrip {\n font-style: italic;\n}\n*/\n\n/* Add a rounded border to thumbnails (but not expanded images): */\n/*\n.fileThumb > img:first-child {\n border: solid 2px rgba(0,0,100,0.5);\n border-radius: 10px;\n}\n*/\n\n/* Make highlighted posts look inset on the page: */\n/*\ndiv.post:target,\ndiv.post.highlight {\n box-shadow: inset 2px 2px 2px rgba(0,0,0,0.2);\n}\n*/", - hotkeys: { - openQR: ['I', 'Open QR with post number inserted'], - openEmptyQR: ['i', 'Open QR without post number inserted'], - openOptions: ['ctrl+o', 'Open Options'], - close: ['Esc', 'Close Options or QR'], - spoiler: ['ctrl+s', 'Quick spoiler tags'], - math: ['ctrl+m', 'Quick math tags'], - eqn: ['ctrl+e', 'Quick eqn tags'], - code: ['alt+c', 'Quick code tags'], - sageru: ['alt+n', 'Sage keybind'], - submit: ['alt+s', 'Submit post'], - hideQR: ['h', 'Toggle hide status of QR'], - toggleCatalog: ['alt+t', 'Toggle links in nav bar'], - watch: ['w', 'Watch thread'], - update: ['u', 'Update now'], - unreadCountTo0: ['z', 'Mark thread as read'], - expandImage: ['m', 'Expand selected image'], - expandAllImages: ['M', 'Expand all images'], - fappeTyme: ['F', 'Toggle Fappe Tyme'], - zero: ['0', 'Jump to page 0'], - nextPage: ['L', 'Jump to the next page'], - previousPage: ['H', 'Jump to the previous page'], - nextThread: ['n', 'See next thread'], - previousThread: ['p', 'See previous thread'], - expandThread: ['e', 'Expand thread'], - openThreadTab: ['o', 'Open thread in new tab'], - openThread: ['O', 'Open thread in current tab'], - nextReply: ['J', 'Select next reply'], - previousReply: ['K', 'Select previous reply'], - hide: ['x', 'Hide thread'] - }, - updater: { - checkbox: { - 'Beep': [false, 'Beep on new post to completely read thread'], - 'Scrolling': [false, 'Scroll updated posts into view. Only enabled at bottom of page.'], - 'Scroll BG': [false, 'Scroll background tabs'], - 'Verbose': [true, 'Show countdown timer, new post count'], - 'Auto Update': [true, 'Automatically fetch new posts'] - }, - Interval: 30, - BGInterval: 60 - }, - embedWidth: 640, - embedHeight: 390 - }; - - if (!/^[a-z]+\.4chan\.org$/.test(location.hostname)) { - return; - } - - Conf = {}; - - g = {}; - - d = document; - - g.TYPE = 'sfw'; - - userNavigation = {}; - - MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.OMutationObserver; - - /* - loosely follows the jquery api: - http://api.jquery.com/ - not chainable - */ - - - $ = function(selector, root) { - var result; - - root || (root = d.body); - if (result = root.querySelector(selector)) { - return result; - } - }; - - $.extend = function(object, properties) { - var key, val; - - for (key in properties) { - val = properties[key]; - object[key] = val; - } - }; - - $.extend(Array.prototype, { - add: function(object, position) { - var keep; - - keep = this.slice(position); - this.length = position; - this.push(object); - return this.pushArrays(keep); - }, - contains: function(object) { - return this.indexOf(object) > -1; - }, - indexOf: function(object) { - var i; - - i = this.length; - while (i--) { - if (this[i] === object) { - break; - } - } - return i; - }, - pushArrays: function() { - var arg, args, _i, _len; - - args = arguments; - for (_i = 0, _len = args.length; _i < _len; _i++) { - arg = args[_i]; - this.push.apply(this, arg); - } - return this; - }, - remove: function(object) { - var index; - - if ((index = this.indexOf(object)) > -1) { - return this.splice(index, 1); - } else { - return false; - } - } - }); - - $.extend(String.prototype, { - capitalize: function() { - return this.charAt(0).toUpperCase() + this.slice(1); - }, - contains: function(string) { - return this.indexOf(string) > -1; - } - }); - - $.DAY = 24 * ($.HOUR = 60 * ($.MINUTE = 60 * ($.SECOND = 1000))); - - $.extend($, { - NBSP: '\u00A0', - minmax: function(value, min, max) { - return (value < min ? min : value > max ? max : value); - }, - log: typeof (_base = console.log).bind === "function" ? _base.bind(console) : void 0, - engine: /WebKit|Presto|Gecko/.exec(navigator.userAgent)[0].toLowerCase(), - ready: function(fc) { - var cb; - - if (['interactive', 'complete'].contains(d.readyState)) { - return setTimeout(fc); - } - if (!$.callbacks) { - $.callbacks = []; - cb = function() { - var callback, _i, _len, _ref; - - _ref = $.callbacks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - callback = _ref[_i]; - callback(); - } - return $.off(d, 'DOMContentLoaded', cb); - }; - $.on(d, 'DOMContentLoaded', cb); - } - $.callbacks.push(fc); - return $.on(d, 'DOMContentLoaded', cb); - }, - sync: function(key, cb) { - var parse; - - key = Main.namespace + key; - parse = JSON.parse; - return $.on(window, 'storage', function(e) { - if (e.key === key) { - return cb(parse(e.newValue)); - } - }); - }, - id: function(id) { - return d.getElementById(id); - }, - formData: function(arg) { - var fd, key, val; - - if (arg instanceof HTMLFormElement) { - fd = new FormData(arg); - } else { - fd = new FormData(); - for (key in arg) { - val = arg[key]; - if (val) { - fd.append(key, val); - } - } - } - return fd; - }, - ajax: function(url, callbacks, opts) { - var form, headers, key, r, type, upCallbacks, val; - - if (!opts) { - opts = {}; - } - type = opts.type, headers = opts.headers, upCallbacks = opts.upCallbacks, form = opts.form; - r = new XMLHttpRequest(); - r.overrideMimeType('text/html'); - type || (type = form && 'post' || 'get'); - r.open(type, url, true); - for (key in headers) { - val = headers[key]; - r.setRequestHeader(key, val); - } - $.extend(r, callbacks); - $.extend(r.upload, upCallbacks); - if (type === 'post') { - r.withCredentials = true; - } - r.send(form); - return r; - }, - cache: function(url, cb) { - var req; - - if (req = $.cache.requests[url]) { - if (req.readyState === 4) { - return cb.call(req); - } else { - return req.callbacks.push(cb); - } - } else { - req = $.ajax(url, { - onload: function() { - var _i, _len, _ref; - - _ref = this.callbacks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - cb = _ref[_i]; - cb.call(this); - } - }, - onabort: function() { - return delete $.cache.requests[url]; - }, - onerror: function() { - return delete $.cache.requests[url]; - } - }); - req.callbacks = [cb]; - return $.cache.requests[url] = req; - } - }, - cb: { - checked: function() { - $.set(this.name, this.checked); - return Conf[this.name] = this.checked; - }, - value: function() { - $.set(this.name, this.value.trim()); - return Conf[this.name] = this.value; - } - }, - addStyle: function(css, identifier) { - var style; - - style = $.el('style', { - innerHTML: css, - id: identifier - }); - $.add(d.head, style); - return style; - }, - x: function(path, root) { - root || (root = d.body); - return d.evaluate(path, root, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue; - }, - X: function(path, root) { - root || (root = d.body); - return d.evaluate(path, root, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); - }, - addClass: function(el, className) { - return el.classList.add(className); - }, - rmClass: function(el, className) { - return el.classList.remove(className); - }, - toggleClass: function(el, className) { - return el.classList.toggle(className); - }, - hasClass: function(el, className) { - return el.classList.contains(className); - }, - rm: function(el) { - return el.parentNode.removeChild(el); - }, - rmAll: function(root) { - var node; - - while (node = root.firstChild) { - $.rm(node); - } - }, - tn: function(string) { - return d.createTextNode(string); - }, - nodes: function(nodes) { - var frag, node, _i, _len; - - if (!(nodes instanceof Array)) { - return nodes; - } - frag = $.frag(); - for (_i = 0, _len = nodes.length; _i < _len; _i++) { - node = nodes[_i]; - $.add(frag, node); - } - return frag; - }, - frag: function() { - return d.createDocumentFragment(); - }, - add: function(parent, children) { - return parent.appendChild($.nodes(children)); - }, - prepend: function(parent, children) { - return parent.insertBefore($.nodes(children), parent.firstChild); - }, - after: function(root, el) { - return root.parentNode.insertBefore($.nodes(el), root.nextSibling); - }, - before: function(root, el) { - return root.parentNode.insertBefore($.nodes(el), root); - }, - replace: function(root, el) { - return root.parentNode.replaceChild($.nodes(el), root); - }, - el: function(tag, properties) { - var el; - - el = d.createElement(tag); - if (properties) { - $.extend(el, properties); - } - return el; - }, - on: function(el, events, handler) { - var event, _i, _len, _ref; - - _ref = events.split(' '); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - event = _ref[_i]; - el.addEventListener(event, handler, false); - } - }, - off: function(el, events, handler) { - var event, _i, _len, _ref; - - _ref = events.split(' '); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - event = _ref[_i]; - el.removeEventListener(event, handler, false); - } - }, - event: function(el, e) { - return el.dispatchEvent(e); - }, - globalEval: function(code) { - var script; - - script = $.el('script', { - textContent: "(" + code + ")()" - }); - $.add(d.head, script); - return $.rm(script); - }, - shortenFilename: function(filename, isOP) { - var threshold; - - threshold = 30 + 10 * isOP; - if (filename.replace(/\.\w+$/, '').length > threshold) { - return "" + filename.slice(0, threshold - 5) + "(...)" + (filename.match(/\.\w+$/)); - } else { - return filename; - } - }, - bytesToString: function(size) { - var unit; - - unit = 0; - while (size >= 1024) { - size /= 1024; - unit++; - } - size = unit > 1 ? Math.round(size * 100) / 100 : Math.round(size); - return "" + size + " " + ['B', 'KB', 'MB', 'GB'][unit]; - }, - debounce: function(wait, fn) { - var timeout; - - timeout = null; - return function() { - if (timeout) { - clearTimeout(timeout); - } else { - fn.apply(this, arguments); - } - return timeout = setTimeout((function() { - return timeout = null; - }), wait); - }; - } - }); - - $.cache.requests = {}; - - $.extend($, typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null ? { - "delete": function(name) { - name = Main.namespace + name; - return GM_deleteValue(name); - }, - get: function(name, defaultValue) { - var value; - - name = Main.namespace + name; - if ((value = GM_getValue(name)) && value !== 'undefined') { - return JSON.parse(value); - } else { - return defaultValue; - } - }, - set: function(name, value) { - name = Main.namespace + name; - localStorage.setItem(name, JSON.stringify(value)); - return GM_setValue(name, JSON.stringify(value)); - }, - open: function(url) { - return GM_openInTab(location.protocol + url, true); - } - } : { - "delete": function(name) { - return localStorage.removeItem(Main.namespace + name); - }, - get: function(name, defaultValue) { - var value; - - if (value = localStorage.getItem(Main.namespace + name)) { - return JSON.parse(value); - } else { - return defaultValue; - } - }, - set: function(name, value) { - return localStorage.setItem(Main.namespace + name, JSON.stringify(value)); - }, - open: function(url) { - return window.open(location.protocol + url, '_blank'); - } - }); - - $$ = function(selector, root) { - var result; - - root || (root = d.body); - if (result = __slice.call(root.querySelectorAll(selector))) { - return result; - } - return null; - }; - - UI = { - dialog: function(id, position, html) { - var el, move; - - el = $.el('div', { - className: 'reply dialog', - innerHTML: html, - id: id - }); - el.style.cssText = $.get("" + id + ".coords", position); - if (move = $('.move', el)) { - move.addEventListener('mousedown', UI.dragstart, false); - } - return el; - }, - dragstart: function(e) { - var el, rect; - - e.preventDefault(); - UI.el = el = this.parentNode; - d.addEventListener('mousemove', UI.drag, false); - d.addEventListener('mouseup', UI.dragend, false); - rect = el.getBoundingClientRect(); - UI.dx = e.clientX - rect.left; - UI.dy = e.clientY - rect.top; - UI.width = d.documentElement.clientWidth - rect.width; - return UI.height = d.documentElement.clientHeight - rect.height; - }, - drag: function(e) { - var left, style, top; - - left = e.clientX - UI.dx; - top = e.clientY - UI.dy; - left = left < 10 ? '0px' : UI.width - left < 10 ? null : left + 'px'; - top = top < 10 ? '0px' : UI.height - top < 10 ? null : top + 'px'; - style = UI.el.style; - style.left = left; - style.top = top; - style.right = left === null ? '0px' : null; - return style.bottom = top === null ? '0px' : null; - }, - dragend: function() { - $.set("" + UI.el.id + ".coords", UI.el.style.cssText); - d.removeEventListener('mousemove', UI.drag, false); - d.removeEventListener('mouseup', UI.dragend, false); - return delete UI.el; - }, - hover: function(e, mode) { - var clientHeight, clientWidth, clientX, clientY, height, style, top, _ref; - - clientX = e.clientX, clientY = e.clientY; - style = UI.el.style; - _ref = d.documentElement, clientHeight = _ref.clientHeight, clientWidth = _ref.clientWidth; - height = UI.el.offsetHeight; - if ((mode || 'default') === 'default') { - top = clientY - 120; - style.top = "" + (clientHeight <= height || top <= 0 ? 0 : top + height >= clientHeight ? clientHeight - height : top) + "px"; - if (clientX <= clientWidth - 400) { - style.left = clientX + 45 + 'px'; - return style.right = null; - } else { - style.left = null; - style.right = clientWidth - clientX + 20 + 'px'; - return top = clientY - 120; - } - } else { - if (clientX <= clientWidth - 400) { - style.left = clientX + 20 + 'px'; - style.right = null; - top = clientY; - } else { - style.left = null; - style.right = clientWidth - clientX + 20 + 'px'; - top = clientY - 120; - } - return style.top = "" + (clientHeight <= height || top <= 0 ? 0 : top + height >= clientHeight ? clientHeight - height : top) + "px"; - } - }, - hoverend: function() { - $.rm(UI.el); - return delete UI.el; - } - }; - - Options = { - init: function() { - var a, setting, settings, _i, _len, _ref, _results; - - if (!$.get('firstrun')) { - $.set('firstrun', true); - if (!Favicon.el) { - Favicon.init(); - } - Options.dialog(); - } - _ref = ['navtopright', 'navbotright']; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - settings = _ref[_i]; - a = $.el('a', { - className: 'settingsWindowLink', - textContent: '4chan X Settings', - href: 'javascript:;' - }); - $.on(a, 'click', function() { - return Options.dialog(); - }); - setting = $.id(settings); - if (Conf['Disable 4chan\'s extension']) { - $.replace(setting.childNodes[1], a); - continue; - } - _results.push($.prepend(setting, [$.tn('['), a, $.tn('] ')])); - } - return _results; - }, - dialog: function() { - var archiver, arr, back, checked, customCSS, description, dialog, div, emojiPos, favicon, fieldset, fileInfo, filter, height, hiddenNum, hiddenThreads, input, key, label, legend, name, obj, overlay, sageEmoji, sauce, time, toSelect, tr, updateIncrease, updateIncreaseB, value, width, _i, _j, _len, _len1, _ref, _ref1, _ref2; - - dialog = Options.el = $.el('div', { - id: 'options', - className: 'reply dialog', - innerHTML: '
\ -
\ - \ - | Export\ - | Import\ - | 4chan X\ - | ' + Main.version + '\ -
\ -\ -
\ -
\ - \ -

\ -
\ -\ -
\ - \ - | \ - | \ - | \ - | \ -
\ -
\ -
\ - \ -
\ -
\ - \ -
\ -
Sauce is disabled.
\ - Lines starting with a # will be ignored.
\ - You can specify a certain display text by appending ;text:[text] to the url.\ -
    These parameters will be replaced by their corresponding values:\ -
  • $1: Thumbnail url.
  • \ -
  • $2: Full image url.
  • \ -
  • $3: MD5 hash.
  • \ -
  • $4: Current board.
  • \ -
\ - \ -
\ - \ -
\ -
Filter is disabled.
\ - \ -
\ - \ -
\ -
\ - Icons\ -
Emoji is disabled.
\ -
\ - Emoji Position
\ - \ - \ -
\ -
\ - Sage Emoji
\ - \ - \ -
\ -
\ -
Unread Favicon is disabled.
\ - Unread favicons
\ - \ - \ -
\ -
\ - \ -
\ - Archiver\ -
\ - Select an Archiver for this board:\ - \ -
\ -
\ -
\ - Updater\'s Dynamic Increase\ -
Visible tab
\ -
\ -
Background tab
\ -
\ -
\ -
\ - Backlink formatting\ -
Quote Backlinks are disabled.
\ -
:
\ -
\ -
\ - Time Formatting\ -
Time Formatting is disabled.
\ - :
\ - Supported format specifiers:
\ - Day: %a, %A, %d, %e
\ - Month: %m, %b, %B
\ - Year: %y
\ - Hour: %k, %H, %l (lowercase L), %I (uppercase i), %p, %P
\ - Minutes: %M
\ - Seconds: %S
\ -
\ -
\ -
File Info Formatting is disabled.
\ - File Info Formatting\ - :
\ - Link: %l (lowercase L, truncated), %L (untruncated), %t (Unix timestamp)
\ - Original file name: %n (truncated), %N (untruncated), %T (Unix timestamp)
\ - Spoiler indicator: %p
\ - Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
\ - Resolution: %r (Displays PDF on /po/, for PDFs)
\ -
\ -
\ -
Per Board Persona is disabled.
\ - Per Board Persona\ - \ -

\ -
\ - Name:\ -
\ -
\ - \ -
\ -
\ - Email:\ -
\ -
\ - \ -
\ -
\ - Subject:\ -
\ -
\ - \ -
\ -
\ - \ -
\ -
\ - Embedding\ - Specify size of video embeds
\ - Height: px\ - |\ - Width: px\ - \ -
\ -
\ - Custom Navigation\ -
Custom Navigation is disabled.
\ -
\ -
\ -
\ -
\ - Custom CSS\ -
Custom CSS is disabled.

\ - Remove Comment blocks to use! ( "/*" and "*/" around CSS blocks )\ - \ -
\ - \ -
\ -
Keybinds are disabled.
\ -
Allowed keys: Ctrl, Alt, Meta, a-z, A-Z, 0-9, Up, Down, Right, Left.
\ - \ - \ -
ActionsKeybinds
\ -
\ - \ -
Reloading page with new settings.
\ -
' - }); - _ref = $$('label[for]', dialog); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - label = _ref[_i]; - $.on(label, 'click', function() { - var previous; - - if (previous = $.id('selected_tab')) { - previous.id = ''; - } - return this.id = 'selected_tab'; - }); - } - $.on($('#credits .export', dialog), 'click', Options["export"]); - $.on($('#credits .import', dialog), 'click', Options["import"]); - $.on($('.imp-exp>input', dialog), 'change', Options.onImport); - _ref1 = Config.main; - for (key in _ref1) { - obj = _ref1[key]; - fieldset = $.el('fieldset'); - legend = $.el('legend', { - textContent: key - }); - for (key in obj) { - arr = obj[key]; - checked = $.get(key, Conf[key]) ? 'checked' : ''; - description = arr[1]; - div = $.el('div', { - innerHTML: ": " + description + "" - }); - $.on($('input', div), 'click', $.cb.checked); - $.add(fieldset, legend); - $.add(fieldset, div); - } - $.add($('#main_tab + div', dialog), fieldset); - } - hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); - hiddenNum = Object.keys(g.hiddenReplies).length + Object.keys(hiddenThreads).length; - div = $.el('div', { - innerHTML: "
Forget all hidden posts. Useful if you accidentally hide a post and have \"Show Stubs\" disabled.
" - }); - $.on($('button', div), 'click', Options.clearHidden); - $.on($('.optionlabel', div), 'mouseover', Options.mouseover); - $.add($('fieldset:nth-child(3)', dialog), div); - filter = $('select[name=filter]', dialog); - $.on(filter, 'change', Options.filter); - archiver = $('select[name=archiver]', dialog); - toSelect = Redirect.select(g.BOARD); - if (!toSelect[0]) { - toSelect = ['No Archive Available']; - } - for (_j = 0, _len1 = toSelect.length; _j < _len1; _j++) { - name = toSelect[_j]; - $.add(archiver, $.el('option', { - textContent: name - })); - } - if (toSelect[1]) { - archiver.value = $.get(value = "archiver/" + g.BOARD + "/", toSelect[0]); - $.on(archiver, 'change', function() { - return $.set(value, this.value); - }); - } - sauce = $('#sauces', dialog); - sauce.value = $.get(sauce.name, Conf[sauce.name]); - $.on(sauce, 'change', $.cb.value); - (back = $('[name=backlink]', dialog)).value = $.get('backlink', Conf['backlink']); - (time = $('[name=time]', dialog)).value = $.get('time', Conf['time']); - (fileInfo = $('[name=fileInfo]', dialog)).value = $.get('fileInfo', Conf['fileInfo']); - $.on(back, 'input', $.cb.value); - $.on(back, 'input', Options.backlink); - $.on(time, 'input', $.cb.value); - $.on(time, 'input', Options.time); - $.on(fileInfo, 'input', $.cb.value); - $.on(fileInfo, 'input', Options.fileInfo); - this.persona.select = $('[name=personaboards]', dialog); - this.persona.button = $('#persona button', dialog); - this.persona.data = $.get('persona', { - global: {} - }); - if (!this.persona.data[g.BOARD]) { - this.persona.data[g.BOARD] = JSON.parse(JSON.stringify(this.persona.data.global)); - } - for (name in this.persona.data) { - this.persona.select.innerHTML += ""; - } - this.persona.select.value = Conf['Per Board Persona'] ? g.BOARD : 'global'; - this.persona.init(); - $.on(this.persona.select, 'change', Options.persona.change); - customCSS = $('#customCSS', dialog); - customCSS.value = $.get(customCSS.name, Conf[customCSS.name]); - $.on(customCSS, 'change', function() { - $.cb.value.call(this); - return Style.addStyle(); - }); - (width = $('[name=embedWidth]', dialog)).value = $.get('embedWidth', Conf['embedWidth']); - (height = $('[name=embedHeight]', dialog)).value = $.get('embedHeight', Conf['embedHeight']); - $.on(width, 'input', $.cb.value); - $.on(height, 'input', $.cb.value); - $.on($('[name=resetSize]', dialog), 'click', function() { - $.set('embedWidth', width.value = Config.embedWidth); - return $.set('embedHeight', height.value = Config.embedHeight); - }); - favicon = $('select[name=favicon]', dialog); - favicon.value = $.get('favicon', Conf['favicon']); - $.on(favicon, 'change', $.cb.value); - $.on(favicon, 'change', Options.favicon); - sageEmoji = $('select[name=sageEmoji]', dialog); - sageEmoji.value = $.get('sageEmoji', Conf['sageEmoji']); - $.on(sageEmoji, 'change', $.cb.value); - $.on(sageEmoji, 'change', Options.sageEmoji); - emojiPos = $('select[name=emojiPos]', dialog); - emojiPos.value = $.get('emojiPos', Conf['emojiPos']); - $.on(emojiPos, 'change', $.cb.value); - $.on(emojiPos, 'change', Options.emojiPos); - (updateIncrease = $('[name=updateIncrease]', dialog)).value = $.get('updateIncrease', Conf['updateIncrease']); - (updateIncreaseB = $('[name=updateIncreaseB]', dialog)).value = $.get('updateIncreaseB', Conf['updateIncreaseB']); - $.on(updateIncrease, 'input', $.cb.value); - $.on(updateIncreaseB, 'input', $.cb.value); - this.customNavigation.dialog(dialog); - _ref2 = Config.hotkeys; - for (key in _ref2) { - arr = _ref2[key]; - tr = $.el('tr', { - innerHTML: "" + arr[1] + "" - }); - input = $('input', tr); - input.value = $.get(key, Conf[key]); - $.on(input, 'keydown', Options.keybind); - $.add($('#keybinds_tab + div tbody', dialog), tr); - } - overlay = $.el('div', { - id: 'overlay' - }); - $.on(dialog, 'click', function(e) { - return e.stopPropagation(); - }); - $.on(overlay, 'click', Options.close); - $.on(dialog, 'click', function(e) { - return e.stopPropagation(); - }); - $.add(overlay, dialog); - $.add(d.body, overlay); - d.body.style.setProperty('width', "" + d.body.clientWidth + "px", null); - $.addClass(d.body, 'unscroll'); - this.indicators(dialog); - Options.filter.call(filter); - Options.backlink.call(back); - Options.time.call(time); - Options.fileInfo.call(fileInfo); - Options.favicon.call(favicon); - return Options.sageEmoji.call(sageEmoji); - }, - indicators: function(dialog) { - var indicator, indicators, key, _i, _j, _len, _len1, _ref, _ref1; - - indicators = {}; - _ref = $$('.warning', dialog); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - indicator = _ref[_i]; - key = indicator.firstChild.textContent; - indicator.hidden = $.get(key, Conf[key]); - indicators[key] = indicator; - $.on($("[name='" + key + "']", dialog), 'click', function() { - return indicators[this.name].hidden = this.checked; - }); - } - _ref1 = $$('.disabledwarning', dialog); - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - indicator = _ref1[_j]; - key = indicator.firstChild.textContent; - indicator.hidden = !$.get(key, Conf[key]); - indicators[key] = indicator; - $.on($("[name='" + key + "']", dialog), 'click', function() { - return Options.indicators(dialog); - }); - } - }, - customNavigation: { - dialog: function(dialog) { - var addLink, div, index, input, item, itemIndex, li, link, navOptions, removeLink, ul, _ref; - - div = $("#customNavigation", dialog); - ul = $.el("div"); - li = $.el("div", { - className: "delimiter", - textContent: "Delimiter: " - }); - input = $.el("input", { - className: "field", - name: "delimiter" - }); - input.setAttribute("value", userNavigation.delimiter); - input.setAttribute("placeholder", "delimiter"); - input.setAttribute("type", "text"); - $.on(input, "change", function() { - if (this.value === "") { - alert("Custom Navigation options cannot be blank."); - return; - } - userNavigation.delimiter = this.value; - return $.set("userNavigation", userNavigation); - }); - $.add(li, input); - $.add(ul, li); - li = $.el("div", { - innerHTML: "Navigation Syntax:
Display Name | Title / Alternate Text | URL" - }); - $.add(ul, li); - navOptions = ["Display Name", "Title / Alt Text", "URL"]; - _ref = userNavigation.links; - for (index in _ref) { - link = _ref[index]; - if (typeof link !== 'object') { - continue; - } - li = $.el("div"); - input = $.el("input", { - className: "hidden", - value: index, - type: "hidden", - hidden: "hidden" - }); - $.add(li, input); - for (itemIndex in link) { - item = link[itemIndex]; - if (typeof item !== 'string') { - continue; - } - input = $.el("input", { - className: "field", - name: itemIndex, - value: item, - placeholder: navOptions[itemIndex], - type: "text" - }); - $.on(input, "change", function() { - if (this.value === "") { - alert("Custom Navigation options cannot be blank."); - return; - } - userNavigation.links[this.parentElement.firstChild.value][this.name] = this.value; - return $.set("userNavigation", userNavigation); - }); - $.add(li, [input, $.tn(' ')]); - } - addLink = $.el("a", { - textContent: " + ", - href: "javascript:;" - }); - $.on(addLink, "click", function() { - var blankLink; - - blankLink = ["ex", "example", "http://www.example.com/"]; - userNavigation.links.add(blankLink, this.parentElement.firstChild.value); - return Options.customNavigation.cleanup(); - }); - removeLink = $.el("a", { - textContent: " x ", - href: "javascript:;" - }); - $.on(removeLink, "click", function() { - userNavigation.links.remove(userNavigation.links[this.parentElement.firstChild.value]); - return Options.customNavigation.cleanup(); - }); - $.add(li, addLink); - $.add(li, removeLink); - $.add(ul, li); - } - li = $.el("div", { - innerHTML: "+ | Reset" - }); - $.on($('a[name=add]', li), "click", function() { - var blankLink; - - blankLink = ["ex", "example", "http://www.example.com/"]; - userNavigation.links.push(blankLink); - return Options.customNavigation.cleanup(); - }); - $.on($('a[name=reset]', li), "click", function() { - userNavigation = JSON.parse(JSON.stringify(Navigation)); - return Options.customNavigation.cleanup(); - }); - $.add(ul, li); - return $.add(div, ul); - }, - cleanup: function() { - $.set("userNavigation", userNavigation); - $.rm($("#customNavigation > div", d.body)); - return Options.customNavigation.dialog($("#options", d.body)); - } - }, - persona: { - init: function() { - var input, item, key, _i, _len, _ref; - - key = Conf['Per Board Persona'] ? g.BOARD : 'global'; - Options.persona.newButton(); - _ref = Options.persona.array; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - item = _ref[_i]; - input = $("input[name=" + item + "]", Options.el); - input.value = this.data[key][item] || ""; - $.on(input, 'blur', function() { - var pers; - - pers = Options.persona; - pers.data[pers.select.value][this.name] = this.value; - return $.set('persona', pers.data); - }); - } - return $.on(Options.persona.button, 'click', Options.persona.copy); - }, - array: ['name', 'email', 'sub'], - change: function() { - var input, item, key, _i, _len, _ref; - - key = this.value; - Options.persona.newButton(); - _ref = Options.persona.array; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - item = _ref[_i]; - input = $("input[name=" + item + "]", Options.el); - input.value = Options.persona.data[key][item]; - } - }, - copy: function() { - var change, data, select, _ref; - - _ref = Options.persona, select = _ref.select, data = _ref.data, change = _ref.change; - if (select.value === 'global') { - data.global = JSON.parse(JSON.stringify(data[select.value])); - } else { - data[select.value] = JSON.parse(JSON.stringify(data.global)); - } - $.set('persona', Options.persona.data = data); - return change.call(select); - }, - newButton: function() { - return Options.persona.button.textContent = "Copy from " + (Options.persona.select.value === 'global' ? 'current board' : 'global'); - } - }, - close: function() { - $.rm(this); - d.body.style.removeProperty('width'); - return $.rmClass(d.body, 'unscroll'); - }, - clearHidden: function() { - $["delete"]("hiddenReplies/" + g.BOARD + "/"); - $["delete"]("hiddenThreads/" + g.BOARD + "/"); - this.textContent = "hidden: 0"; - return g.hiddenReplies = {}; - }, - keybind: function(e) { - var key; - - if (e.keyCode === 9) { - return; - } - e.preventDefault(); - e.stopPropagation(); - if ((key = Keybinds.keyCode(e)) == null) { - return; - } - this.value = key; - return $.cb.value.call(this); - }, - filter: function() { - var article, el, name, ta; - - el = this.nextSibling; - if ((name = this.value) !== 'guide') { - ta = $.el('textarea', { - name: name, - className: 'field', - value: $.get(name, Conf[name]) - }); - $.on(ta, 'change', $.cb.value); - $.replace(el, ta); - return; - } - article = $.el('article', { - innerHTML: "

Use regular expressions, one per line.
\n Lines starting with a # will be ignored.
\n For example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.

\n
    You can use these settings with each regular expression, separate them with semicolons:\n
  • \n Per boards, separate them with commas. It is global if not specified.
    \n For example: boards:a,jp;.\n
  • \n
  • \n Filter OPs only along with their threads (`only`), replies only (`no`, this is default), or both (`yes`).
    \n For example: op:only;, op:no; or op:yes;.\n
  • \n
  • \n Overrule the `Show Stubs` setting if specified: create a stub (`yes`) or not (`no`).
    \n For example: stub:yes; or stub:no;.\n
  • \n
  • \n Highlight instead of hiding. You can specify a class name to use with a userstyle.
    \n For example: highlight; or highlight:wallpaper;.\n
  • \n
  • \n Highlighted OPs will have their threads put on top of board pages by default.
    \n For example: top:yes; or top:no;.\n
  • \n
" - }); - if (el) { - return $.replace(el, article); - } else { - return $.after(this, article); - } - }, - time: function() { - Time.foo(); - Time.date = new Date(); - return $.id('timePreview').textContent = Time.funk(Time); - }, - backlink: function() { - return $.id('backlinkPreview').textContent = Conf['backlink'].replace(/%id/, '123456789'); - }, - fileInfo: function() { - FileInfo.data = { - link: '//images.4chan.org/g/src/1334437723720.jpg', - spoiler: true, - size: '276', - unit: 'KB', - resolution: '1280x720', - fullname: 'd9bb2efc98dd0df141a94399ff5880b7.jpg', - shortname: 'd9bb2efc98dd0df141a94399ff5880(...).jpg' - }; - FileInfo.setFormats(); - return $.id('fileInfoPreview').innerHTML = FileInfo.funk(FileInfo); - }, - favicon: function() { - Favicon["switch"](); - Unread.update(true); - return this.previousElementSibling.innerHTML = " "; - }, - sageEmoji: function() { - Conf['sageEmoji'] = this.value; - return this.previousElementSibling.innerHTML = ""; - }, - "export": function() { - var a, data, now, output; - - now = Date.now(); - data = { - version: Main.version, - date: now, - Conf: Conf, - WatchedThreads: $.get('watched', {}) - }; - a = $.el('a', { - className: 'warning', - textContent: 'Save me!', - download: "4chan X v" + Main.version + "-" + now + ".json", - href: "data:application/json;base64," + (btoa(unescape(encodeURIComponent(JSON.stringify(data))))), - target: '_blank' - }); - if ($.engine !== 'gecko') { - a.click(); - return; - } - output = $('.imp-exp>.placeholder'); - $.rmAll(output); - $.rmAll($('.imp-exp-result')); - return $.add(output, a); - }, - "import": function() { - $('.imp-exp>input').click(); - return $.rmAll($('.imp-exp>.placeholder')); - }, - onImport: function() { - var file, output, reader; - - if (!(file = this.files[0])) { - return; - } - output = $('.imp-exp-result'); - if (!confirm('Your current settings will be entirely overwritten, are you sure?')) { - output.textContent = 'Import aborted.'; - return; - } - reader = new FileReader(); - reader.onload = function(e) { - var data, err; - - try { - data = JSON.parse(e.target.result); - Options.loadSettings(data); - if (confirm('Import successful. Refresh now?')) { - return window.location.reload(); - } - } catch (_error) { - err = _error; - return output.textContent = 'Import failed due to an error.'; - } - }; - return reader.readAsText(file); - }, - loadSettings: function(data) { - var key, val, _ref; - - _ref = data.Conf; - for (key in _ref) { - val = _ref[key]; - $.set(key, val); - } - return $.set('watched', data.WatchedThreads); - } - }; - - BanChecker = { - init: function() { - var reason; - - this.now = Date.now(); - if (!Conf['Check for Bans constantly'] && (reason = $.get('isBanned'))) { - return BanChecker.prepend(reason); - } else if (Conf['Check for Bans constantly'] || $.get('lastBanCheck', 0) < this.now - 6 * $.HOUR) { - return BanChecker.load(); - } - }, - load: function() { - this.url = 'https://www.4chan.org/banned'; - return $.ajax(this.url, { - onloadend: function() { - var doc, msg, reason; - - if (this.status === 200 || 304) { - if (!Conf['Check for Bans constantly']) { - $.set('lastBanCheck', BanChecker.now); - } - doc = d.implementation.createHTMLDocument(''); - doc.documentElement.innerHTML = this.response; - if (/no entry in our database/i.test((msg = $('.boxcontent', doc).textContent.trim()))) { - if ($.get('isBanned', false)) { - $["delete"]('isBanned'); - $.rm(BanChecker.el); - delete BanChecker.el; - } - return; - } - $.set('isBanned', reason = /This ban will not expire/i.test(msg) ? 'You are permabanned.' : 'You are banned.'); - return BanChecker.prepend(reason); - } - } - }); - }, - prepend: function(reason) { - var el; - - if (!BanChecker.el) { - Banchecker.el = el = $.el('h2', { - id: 'banmessage', - "class": 'warning', - innerHTML: " " + reason + " Click to find out why.", - title: 'Click to recheck.' - }, $.on(el.lastChild, 'click', function() { - if (!Conf['Check for Bans constantly']) { - $["delete"]('lastBanCheck'); - } - $["delete"]('isBanned'); - this.parentNode.style.opacity = '.5'; - return BanChecker.load(); - })); - return $.before($.id('delform'), el); - } else { - return Banchecker.el.firstChild.textContent = reason; - } - } - }; - - CatalogLinks = { - init: function() { - var a, el; - - el = $.el('span', { - className: 'toggleCatalog', - innerHTML: '[]' - }); - $.on((a = el.firstElementChild), 'click', this.toggle); - $.add($.id('boardNavDesktop'), [$.tn(' '), el]); - return this.toggle.call(a, true); - }, - toggle: function(onLoad) { - var a, board, useCatalog, _i, _len, _ref; - - if (onLoad === true) { - useCatalog = $.get('CatalogIsToggled', g.CATALOG); - } else { - $.set('CatalogIsToggled', useCatalog = this.textContent === 'Catalog Off'); - } - _ref = $$('a', $.id('boardNavDesktop')); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - a = _ref[_i]; - board = a.pathname.split('/')[1]; - if (['f', 'status', '4chan'].contains(board) || !board) { - if (board === 'f') { - a.pathname = '/f/'; - } - continue; - } - if (Conf['External Catalog']) { - a.href = useCatalog ? CatalogLinks.external(board) : "//boards.4chan.org/" + board + "/"; - } else { - a.pathname = "/" + board + "/" + (useCatalog ? 'catalog' : ''); - } - a.title = useCatalog ? "" + a.title + " - Catalog" : a.title.replace(/\ -\ Catalog$/, ''); - } - this.textContent = "Catalog " + (useCatalog ? 'On' : 'Off'); - return this.title = "Turn catalog links " + (useCatalog ? 'off' : 'on') + "."; - }, - external: function(board) { - return (['a', 'c', 'g', 'co', 'k', 'm', 'o', 'p', 'v', 'vg', 'w', 'cm', '3', 'adv', 'an', 'cgl', 'ck', 'diy', 'fa', 'fit', 'int', 'jp', 'mlp', 'lit', 'mu', 'n', 'po', 'sci', 'toy', 'trv', 'tv', 'vp', 'x', 'q'].contains(board) ? "http://catalog.neet.tv/" + board : ['d', 'e', 'gif', 'h', 'hr', 'hc', 'r9k', 's', 'pol', 'soc', 'u', 'i', 'ic', 'hm', 'r', 'w', 'wg', 'wsg', 't', 'y'].contains(board) ? "http://4index.gropes.us/" + board : "//boards.4chan.org/" + board + "/catalog"); - } - }; - - CustomNavigation = { - init: function() { - var a, i, len, link, navNodes, navigation, node, nodes; - - navigation = $("#boardNavDesktop", d.body); - navNodes = navigation.childNodes; - i = navNodes.length; - nodes = Conf['Append Delimiters'] ? [$.tn("" + userNavigation.delimiter + " ")] : []; - while (i--) { - if ((node = navNodes[i]).id) { - continue; - } - $.rm(node); - } - len = userNavigation.links.length - 1; - while (i++ < len) { - link = userNavigation.links[i]; - a = $.el('a', { - textContent: link[0], - title: link[1], - href: link[2] - }); - if (a.href.contains("/" + g.BOARD + "/")) { - $.addClass(a, 'current'); - } - nodes[nodes.length] = a; - if (Conf['Append Delimiters'] || i !== len) { - nodes[nodes.length] = $.tn(" " + userNavigation.delimiter + " "); - } - } - $.prepend(navigation, nodes); - } - }; - - Navigation = { - delimiter: "/", - links: [["a", "Anime & Manga", "//boards.4chan.org/a/"], ["b", "Random", "//boards.4chan.org/b/"], ["c", "Cute/Anime", "//boards.4chan.org/c/"], ["d", "Hentai/Alternative", "//boards.4chan.org/d/"], ["e", "Ecchi", "//boards.4chan.org/e/"], ["f", "Flash", "//boards.4chan.org/f/"], ["g", "Technology", "//boards.4chan.org/g/"], ["gif", "Animated Gifs", "//boards.4chan.org/gif/"], ["h", "Hentai", "//boards.4chan.org/h/"], ["hr", "High Resolution", "//boards.4chan.org/hr/"], ["k", "Weapons", "//boards.4chan.org/k/"], ["l", "Lolicon", "http://7chan.org/cake/"], ["m", "Mecha", "//boards.4chan.org/m/"], ["o", "Auto", "//boards.4chan.org/o/"], ["p", "Pictures", "//boards.4chan.org/p/"], ["r", "Requests", "//boards.4chan.org/r/"], ["s", "Sexy Beautiful Women", "//boards.4chan.org/s/"], ["t", "Torrents", "//boards.4chan.org/t/"], ["u", "Yuri", "//boards.4chan.org/u/"], ["v", "Video Games", "//boards.4chan.org/v/"], ["vg", "Video Game Generals", "//boards.4chan.org/vg/"], ["vr", "Retro Games", "//boards.4chan.org/vr/"], ["w", "Anime/Wallpapers", "//boards.4chan.org/w/"], ["wg", "Wallpapers/General", "//boards.4chan.org/wg/"], ["i", "Oekaki", "//boards.4chan.org/i/"], ["ic", "Artwork/Critique", "//boards.4chan.org/ic/"], ["r9k", "ROBOT9001", "//boards.4chan.org/r9k/"], ["s4s", "Shit 4chan Says", "//boards.4chan.org/s4s/"], ["cm", "Cute/Male", "//boards.4chan.org/cm/"], ["hm", "Handsome Men", "//boards.4chan.org/hm/"], ["lgbt", "LGBT", "//boards.4chan.org/lgbt/"], ["y", "Yaoi", "//boards.4chan.org/y/"], ["3", "3DCG", "//boards.4chan.org/3/"], ["adv", "Advice", "//boards.4chan.org/adv/"], ["an", "Animals", "//boards.4chan.org/an/"], ["asp", "Alternative Sports", "//boards.4chan.org/asp/"], ["cgl", "Cosplay & EGL", "//boards.4chan.org/cgl/"], ["ck", "Food & Cooking", "//boards.4chan.org/ck/"], ["co", "Comics & Cartoons", "//boards.4chan.org/co/"], ["diy", "Do It Yourself", "//boards.4chan.org/diy/"], ["fa", "Fashion", "//boards.4chan.org/fa/"], ["fit", "Health & Fitness", "//boards.4chan.org/fit/"], ["gd", "Graphic Design", "//boards.4chan.org/gd/"], ["hc", "Hardcore", "//boards.4chan.org/hc/"], ["int", "International", "//boards.4chan.org/int/"], ["jp", "Otaku Culture", "//boards.4chan.org/jp/"], ["lit", "Literature", "//boards.4chan.org/lit/"], ["mlp", "My Little Pony", "//boards.4chan.org/mlp/"], ["mu", "Music", "//boards.4chan.org/mu/"], ["n", "Transportation", "//boards.4chan.org/n/"], ["out", "Outdoors", "//boards.4chan.org/out/"], ["po", "Papercraft & Origami", "//boards.4chan.org/po/"], ["pol", "Politically Incorrect", "//boards.4chan.org/pol/"], ["sci", "Science & Math", "//boards.4chan.org/sci/"], ["soc", "Social", "//boards.4chan.org/soc/"], ["sp", "Sports", "//boards.4chan.org/sp/"], ["tg", "Traditional Games", "//boards.4chan.org/tg/"], ["toy", "Toys", "//boards.4chan.org/toys/"], ["trv", "Travel", "//boards.4chan.org/trv/"], ["tv", "Television & Film", "//boards.4chan.org/tv/"], ["vp", "Pokémon", "//boards.4chan.org/vp/"], ["wsg", "Worksafe GIF", "//boards.4chan.org/wsg/"], ["x", "Paranormal", "//boards.4chan.org/x/"], ["rs", "Rapidshares", "http://rs.4chan.org/"], ["status", "4chan Status", "http://status.4chan.org/"], ["q", "4chan Discussion", "//boards.4chan.org/q/"], ["@", "4chan Twitter", "http://www.twitter.com/4chan"]] - }; - - Emoji = { - init: function() { - this.icons.push(['PlanNine', Emoji.icons[0][1]]); - return this.icons.push(['sage', this.sageValue(Conf['sageEmoji'])]); - }, - sageValue: function(check) { - return (check === 'appchan' ? 'A4AAAAOCAMAAAAolt3jAAABa1BMVEUAAACqrKiCgYIAAAAAAAAAAACHmX5pgl5NUEx/hnx4hXRSUVMiIyKwrbFzn19SbkZ1d3OvtqtpaWhcX1ooMyRsd2aWkZddkEV8vWGcpZl+kHd7jHNdYFuRmI4bHRthaV5WhUFsfGZReUBFZjdJazpGVUBnamYfHB9TeUMzSSpHgS1cY1k1NDUyOC8yWiFywVBoh1lDSEAZHBpucW0ICQgUHhBjfFhCRUA+QTtEQUUBAQFyo1praWspKigWFRZHU0F6j3E9Oz5VWFN0j2hncWONk4sAAABASDxJWkJKTUgAAAAvNC0fJR0DAwMAAAA9QzoWGhQAAAA8YytvrFOJsnlqyT9oqExqtkdrsExpsUsqQx9rpVJDbzBBbi5utk9jiFRuk11iqUR64k5Wf0JIZTpadk5om1BkyjmF1GRNY0FheFdXpjVXhz86XSp2yFJwslR3w1NbxitbtDWW5nNnilhFXTtYqDRwp1dSijiJ7H99AAAAUnRSTlMAJTgNGQml71ypu3cPEN/RDh8HBbOwQN7wVg4CAQZ28vs9EDluXjo58Ge8xwMy0P3+rV8cT73sawEdTv63NAa3rQwo4cUdAl3hWQSWvS8qqYsjEDiCzAAAAIVJREFUeNpFx7GKAQAYAOD/A7GbZVAWZTBZFGQw6LyCF/MIkiTdcOmWSzYbJVE2u1KX0J1v+8QDv/EkyS0yXF/NgeEILiHfyc74mICTQltqYXBeAWU9HGxU09YqqEvAElGjyZYjPyLqitjzHSEiGkrsfMWr0VLe+oy/djGP//YwfbeP8bN3Or0bkqEVblAAAAAASUVORK5CYII=' : 'A4AAAANCAYAAACZ3F9/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAa9JREFUKFOdkt0rg2EUwM95b2zlL0CRRLngksznXrJsNtYW1tjYhM3mY6+IXZAbikhTKJp8XZAp81UmWYhIRHHhUi60e7s6ntdCa2449es8PfU7z+k5B6AbyuE/wQlc4BcO2d06unAUBCgFE0hianOd3NHIcy8NPwrUf9NBPZcOEi7ayXZiea/1V7+ljaXeYAfOgg2So2TOwQWGnwQafOgi962TnMFmatozUeNu4yetASspVvgXiUvii5K5Nm6z56ol3Hdtpy+cwSYy+HRUt1nLsoEato0kXyh6wTac+24brThWv6MNOYNW9prlG/uxmbRrFaT0VrCspZoNPSUNJNyCBcoiLZuhLH0o9U6UrAfGKCz7RlLM81Q8XUwqr4oKPLIQmnA8IupBigacVy7yrya/2JouhryJHJJNykg+UxLGOtz6+SQNpEiMcduls4Wvoli9WklVKz+ol5SU4U6ngql8Qj2eRI+GyajBhSRH4r3cUxhSeRVhsYBmWUWiyM+UMDmDUI2nsfuSC1I27nLgYZJlP8jhjJ3PY8iE+L8tWx4kQC6MQA5b1D9HNiRCFhx8AF/e2qh92VnKAAAAAElFTkSuQmCC'); - }, - icons: [['Plan9', 'AwAAAAPCAYAAAGn5h7fAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAzE15J1s7QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAACAElEQVQoz3WSz4sSARTHvzMjygpqYg3+KIhkE83DKtKlf0C9SrTRuZNEx0VowU6CuSeJNlwwpEO2kJ6SQBiIUAzFjRDF4wrjKosnGx3HmdehFDfpe/2+z/s++D5gU7IsEwRByICIiAEAIiIAYAFAXsjYVr/fLxMRNVvN+prJ5/OA3+/XERFNf02JyeVyDx0OxyvLNQsnimLKfcf9KRQKXQAAnE6nlf5qMpnQycnbP/kAoKoqsSwLAJhOp+AAwOv1otvtpqxWq73dbt/r9XqvEQ6HUalUEvF4XLd5IpvNZqlerzd5nlf6/f6tTCZjBACk0+nb+XxeW4UrikLJZPImAGA0Gq0NIqJyuSyyANDr9Q5Wu1utFvR6/SULAI1G4+vK8Pv90DTtGwsAJpPpaGUYDAZ0Op3PHAAEg8H3tVqtbrtu21sqyxuRSOQJk0ql9IvF4r7b7f7pcrlejkaj57IsH58Pzp8dvjhc/lsBk0gkbLFYrFqtVvd27+4qOk733ePxPDCbzVBVFfP5fCiK4rvhxfDN/qP9wSasGwwGMv1HiqJQsVg8ZlfTHMepkiR1t05gGJBGmM/nMBqNj9nN9kql0lNN064ARISzH2cQBAGz2ewLu2na7XYLwzBbvxYIBBCNRrFj3BmsAZ/PZ+J5/kOhUIAkSVeA8XiMZqt5efrx9OA3GfcgvyVno9cAAAAASUVORK5CYII='], ['Neko', 'BMAAAARCAMAAAAIRmf1AAACoFBMVEUAAABnUFZoUVddU1T6+PvFwLzn4eFXVlT/+vZpZGCgm5dKU1Cfnpz//flbWljr5uLp5OCalpNZWFb//f3r6+n28ff9+PRaVVH59Pr//vr38vj57/Dp7eyjn5zq8O5aVVJbYV9nVFhjUFRiWFlZVlFgZGOboJzm5uZhamfz9/bt8fDw6+drb26bl5j/8/lkX1z06uldWFS5r61UT0tfWlbDwr3Ew76moqNRTU7Mx8P75OpeY19pWl1XW1qzr6x5eHaLiojv7+1UT0xIU0uzqadVS0nV0MxkZGT5+PPk497///ra29Xq5eFtY2H28e2hnJignJlUUE1dXV2vrqxkY2FkYF/m3d5vZmfDuruhl5aZlJHx8O75+PZWVVP29vT/9fTj3trv6ubh5eRdXFqTkpBOTUtqZmX88/RMQ0T78vPEvr7HwcHDwsDq6ef///3Gx8H++fXEv7tZWVedmZZXXVudnJp0c3FZU1f79fnb1dlXUVVjXWFrZmy8t7359/qLj455e3q4s69vamZjX1zy4+avpaReWFz/+f1NR0vu6Ozp4+f48/lnYmi8ur3Iw7/69fHz7+xbV1SZmJZVUk1ZV1zq5ez++f/c196uqbDn4uj9+P7z7vRVVVXt6ORiXl/OycXHw8CPi4ihoJ5aWF3/+v/k3+axrLOsp67LzMZYU1m2sq9dWF5WUU1WUk/Au7eYlJGqpqObmphYVV749f7p5Or38fPu6OpiXFz38fH79vLz7urv6+hhYF5cWWKal6D//f/Z09Xg29exraqbl5RqaW6kpKTq5uPv7Of/+PDj29D//vP18Ozs5+OloJymoZ1ZVVJZWVlkYF2hnpmblIyspJmVjYKQi4enop5STUlRTUpcWUhqY1BgWT9ZUjhcV1NiXVkkhke3AAAABHRSTlMA5vjapJ+a9wAAAP9JREFUGBk9wA1EAwEAhuHv3dTQAkLiUlJFJWF0QDLFYDRXIMkomBgxNIYxhOk4wwCqQhQjxgxSGIsALFA5BiYbMZHajz1oJlx51sBJpf6Gd3zONcrqm/r1W8ByK0r+XV1LXyOLLnjW6hMGpu0u1IzPSdO17DgrGC6AadrVodGcDQYbhguP6wAvAaC0BRZQalkUQ8UQDz5tAof0XbejOFcV5xiUoCfjj3O/nf0ZbqAMPYmzU18KSDaRQ08qnfw+B2JNdAEQt2O5vctUGjhoIBU4ygPsj2Vh5zYopDK73hsirdkPTwGCbSHpiYFwYVVC/17pCFSBeUmoqwYQuZtWxx+BVEz0LeVKIQAAAABJRU5ErkJggg=='], ['Madotsuki', 'BQAAAAPCAMAAADTRh9nAAAALVBMVEUAAAC3iopWLTtWPkHnvqUcBxx5GCZyAAARERGbdXJrRUyGRUyYbY23coZFGDRFGEYfAAAAAXRSTlMAQObYZgAAAGhJREFUeF5Vy1kOQyEMQ1Fshzd12P9y61AixLX4yJFo1cvVUfT23GaflF0HPLln6bhnZVKCcrIWGqpCUcKYSP3JSIRySKTtULPNwMaD8/NC8tsyqsd1hR+6qeqIDHc3LD0B3KdtV1f2A+LJBBIHSgcEAAAAAElFTkSuQmCC'], ['Sega', 'CwAAAALBAMAAAD2A3K8AAAAMFBMVEUAAACMjpOChImytLmdnqMrKzDIyM55dnkODQ94foQ7PkXm5Olsb3VUUVVhZmw8Sl6klHLxAAAAAXRSTlMAQObYZgAAANFJREFUGJVjYIACRiUlJUUGDHBk4syTkxQwhO3/rQ/4ZYsuymi3YEFUqAhC4LCJZJGIi1uimKKjk3KysbOxsaMnAwNLyqoopaXhttf2it1anrJqke1pr1DlBAZhicLnM5YXZ4RWlIYoezx0zrjYqG6czCDsYRzxIko6Q/qFaKy0690Ij0MxN8K2MIhJXF+hsfxJxuwdpYGVaUU3Mm5bqgKFOZOFit3Vp23J3pgsqLxFUXpLtlD5bgcGBs45794dn6mkOVFQUOjNmXPPz8ysOcAAANw6SHLtrqolAAAAAElFTkSuQmCC'], ['Sakamoto', 'BEAAAAQCAYAAADwMZRfAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAxVJREFUOE+Nk19IU1EYwK+GQQTVQ39egh6ibKlzw91z7rn3bvfOmddNszl1bjKXc5rJJGmBUr7Yg9qTD0IalFgRBEYg6EDQQB+GovQyQgiaUZsoLcgHMcr069w7MgcGXfi453zn+37fv3MYZt/n99e76tzVj4JN/hP79fvXnV3hnNabwUBjoOHcgTYOu/JQspgTzsqKgn9BfD4vkWTzur287PqLVy+zM+yePB7KsRXLywTjnSpnZctBkPCdW8ccDuU55vBO8RXbkC/oP5ph19V5+7LIky0OY1BKbZEbLcFSt7u6pN7jLmltCVrr3DV5jY3+KovFEsccB1KJNVpefe10BqS2tqqO4/AuphBB4L/LkrRqNgtJs1lMypLls1kU38mytMLz/E8VIlutqVqX6/weZG52OttRXjbE0cP/FYLRlpVjDXuQ/r77x2XZPKkCHA4HBAIBkCQpAygIAvh8Pu2MZgO0Lz+QSa/sQfwN9RfpVN66XC6Ynp6GhYUFGBwczAC1t7fD0tISxONx6O7upgHILmsqvLcHodOggfiV/v5+SCaT4HQ6IRaLgdfr1bIRRREmJyfBZrNBNBqF+fl5sNsdgE2GiAbp6bmbdbXC7qWQbxMTE7C2tgY6nQ5SqRSEw2ENopaoZpCXlwdTU1NaoECgCbgiU6y8QH+ECYWaTymK7TWdys7MzIwGaWtrg42NDejo6AB1WjU1NZo+FArB2NgYrK6uQrAlCASxn2z6wkuMp87VIAhkE2MEAwMDkEgkYHx8HBYXF0HtkQpRy1BLiEQisLy8rPVNKSsFjEzrXH4+z1hlS4xDhKadNu7t7YPR0VHweDzAEVWfHru6HxkZgeHhYVAURYNjkylVWKArZjjMzqmdVi+QCsLUkQiEjvDvncEkvU7/qQ0Vgukeo48Go87IiCJnZNmipxiz7wXEbVDnbUxQOgM12h9n6qTq6NvapRdtkwaP0XK8RmPuYSbxYfaQ/sJJhjfknuFRURUi7AMOozcCwl94hLZp5F+EioDQVwqYI6jomZU1NFtM+rOSxZjVazcyvwHr/p/Kws1jegAAAABJRU5ErkJggg=='], ['Baka', 'BAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA0pJREFUOE91k3tI01EUx39JOpA0H4jNx0pbD3XTalISWf8YFlEgldqDsBLLyqjEKBCiLLWiggh6/KEV1WZ7OaelLZvDdDafNW1JFraWe/32+01FrUZ9uy4ylLpw4Z5z7/nc77n3HIqaMRIjZJyEcNX+uFCFeGmI/GZciEIsCFJUTvoAzDz+1y7K76MSwhX5hXl6z+WSbrzU2KB8YEGDwgrTaxZ3b7xHcaHhR3xw7Z5/UviB1ReP5XSg3+TAqYJOxMzWISFIC0GQDomhTVA9skCnsaAwp/vnMq66dBokNuBR9uFd7T9Z1zCunjci0qcRJUVdoJ3DYOhRnC/qBZ+jQbfeCc+37yjY2UEg0iwvJE0k9l8Z+8xqHmTgot0QLdQgTaQFQ2AsOzlHvOu1S5pwOLsHHo8HjHMCq2MazNvTlByKHyrJLDvdR25jMWRxYx5HjeMH2r1BDOOeguRua4OI14jx8a8YH5tA+al3EHKlW6mYOapb2oZBOOwMbEMseAE12L+jjUh3w+VipyAZ65oxn1NP/GMYGR6Ftn4Qsf7qa9S82Y/l/X122G0uL2TbxmZEz1WhXW8mUol8moXu+SCi/OoQ6VsDh3UUwyQ1k9GOaI5MTkX4yWTGHutvgI1F28sviAlRgxeoRm62HvsyW8En9pZ1TYgi6TntoyQtFm86rVgUoJZRvDnKMmXVAGxWmkAYOBwudBqGcHCvHulrGpGT2Uy+z4yT+QYsCXtCUpp8GxbKhx8gDK0ro+KjJGvzdjfDZnN6VdisLD5/JjArQ2zW66PJOj2lEZtStaBphkwah7K6kMJ/GEulp1bMWhAmMbTozOQRaWRtfoZVgjo4iRra4SYgGi26TwjxVeDKhR7Y7U606ixICq9tr7hd7+OthRWL7yUnJ1WPmXotqLhpRICPHCePtuFV6xdUPTAhcWEtRHEqfHpPyto4hPXLXnzflSEJnFaN3OCKDcsFsrEntR9RUmxARLAUgT5iBPuJsXWDBj0dZjRU9yNV+PTbpjTp9OA/pOSk24nRkXf1J462oPxcJ65f6ULlHSMulepRerYDgvj7A0cKpNz/tyTZqbzXO4t0ZZGQJ34RH11lFHIlA8LIqreCCMUZRY3cd2bwL/5/RmjNSXqtAAAAAElFTkSuQmCC'], ['Ponyo', 'BAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAuNJREFUOE+Nk3tI01EUx39BTytConQTt1am07m5abi5KT5S8z2dj1yOEMUC7aUgIoimlmUEWX9kBZGWaamEmE6U1BI1XNPNGTrnHs33IwuSXrL4NgcJ0mNdOHDh3PPhnPP9XoKwcroJYvMQiRSicHCQKCgUyZC9/T5rNet5KUFs0zCZbZMsFmZ9fTEjEEBDp4/KSSSb/4JoGIyWaTYbiykpWEhOxhSHAzWD0aqkUGhWAcVkW58xlvuPhfh4zItEmOHxYDR3MhcdDaNAsKJydAz5IySKRNjEUmy88vjOVaU8F0iPCqCNjEBHkC/UYaGYFwqxmJoKLYOhkxPElg0QsbNtTlmox9yjRD9UCbnoOR+J/lwRWtOCcdXfDc2BPpg0d7CQlIQZPh9KKlVkAQjJ2x2zmOSsQu7hpzUJfBhLjsNQmADjxcT10Bcl4rE4EHc5LjBEhEPn7f1WTqXSLQB/s1Tp7vslsoIkyPPiMJAbi86McBguiaHKjoEqR4jJy2K0nAxApzMN5iUGrclrKVaz2fUvuF4tRbxDKA90w5VjTFyLZKHpTBSq4/1QnxGB2qxoVIZx0JopRCPHFSNOThfWZzfrXDcZEowH4iA05ATg68hDtBaL0HAuCm3lJ9Bfcx2fFNUoi/DCjRgfNHHd1wCZA2TyXjNkE6F0cBDpPFiojeNi8EkJdFoN3vXch0nbBJOhDd907dANv8JITxNqziag3ZsJbUDAwLin50Q9QWwl1qSYoNOVvUcOoqOqAAa9Fu9H2/F9+B5WZLcwOyxFX18flLI+VASyMGVeoJHD+Tzq5BS1PoaKRrNT8127P74swsq4FCa9FKvqBqwaOiz3hdEuLKueYSyECT2LNW0eIfo3E/WmEbvnG1MUJnWdpWhDGDvxQXZHo+RR0uW2tnv+auPX+TvtJm7zKpaen/4y2yjBUlcxlvtvmvT16ZWDpQeoVv3/60F/NrHjTf4ugazIXtJ8ivjnz/sJ+yGQRjcqUdIAAAAASUVORK5CYII='], ['Rabite', 'BIAAAAQCAYAAAAbBi9cAAAD/0lEQVR4Xl2MXUxbdQDFz/9+9Lb3tkBLCxTKhzgoOOZAsokbJmZxDFHnd+LL4hKVzBgfNCY++ODbjDEaZowvErOM6HRu6hKZY2rIAOkCY4OSDTpFaAsrlJa2t5+39+NvjT7tnJzknIfzI98Nf/C6TuXdguWBd1q9rcb8/CwsZiu2Ywm4nDVo3VWLZCKDaDwJq9mCg31PgjAMKKUwmcyYvTbek9iJRDm6M/XswEDjwNz6plWW6wdZhjUAintFCEEhn0N04zYskljaDLaj8ar49oUrsYR6mrFJNj322w46H8y+mitM/ZJKZmyE4XAvjJSsazpyuSzslVZIkgWKOvvRgQ6Xrdlhqmds7o7bFZoLkctreKxf7GtuCE7IyUQjBQcQ8j/lvxCGQJZz0IoCVpamTtzfIh9nwiaIrCQyjNg8mq11oDLUhNXRJfT1Ozr3tS/PqpnQ80qRgjAmKIqBfK4ItbSLKoOZqR/6neLkENlSUAIhlktvEf+sD2rkm8nWTHtvZCGMVON1ePuaoBER31/MXGly1wSqq9Uug6FluYyWXJiPqFXmjd4Dh9oF9ZKKimYXRtYCx8lmMIDIxlIPGz591av0mtanF7FcCEN6iMXeox2wOJ0QJAmUAoRQaIqCnWAQY1/ewKNGNeQuYXkm0d2NC2e+wvmRr/Hx+6+8PHayrbDyyQBNDb9As3PHKDWG6MTM23RoeJAWsqeoWvyUUv0UHf7pBB0fe4OeeXe3/vmHbx3+8dwIGJ4IsFpMMFe0fbtAn+nwZePr1u4MBK8XIALG/Rt479wYrs2vgeNNAMNgMbiNzybuoKVvn+Gs9kbr6qpBfJfGYHFIkJUCoGwfqcoMX/b27EGhwgOjoCADDlP+CA51ugFFRzoB8FYNaQ1oqKD44+eNL+wNj7zJGQSIhe8+jgQ9thk+27v/KRY6L4FSCkVOwtlQj6P73Qgt/o1ERoKt4iUkE7+jrZMHyzIoK9cOBFfT4LbWAk+0a7ZLnvqHcTNdACgFScfAcjxEdy00VQclHGo7dqGeYxHbvIo6hwhSghCehb3G5p6eW7VxXC5/xGWToMgrKKoaCnIalI9CIARasQAqloMI/x4BWrLLYwE1AEPTwCGHaGjz7pw/leZUNV8wNm9BLy6CxsvxZ1kMbaY4TKIIXlNBsynoVjvAC4CuAoYOVi+CMfLYCUfg95tPHuzZB0YtKzsb58RMucWE/fZmhCbdOP9rNnLnxko6GVoB8lFwyVVw8b/AyeulHoJyN4Rb19dTFyeqBlu6njvfsWcvOJvLs7DMmw/7bvpeE4pU2OIcgcqmp4fGAgt2Txwvqr7lTp5V7LquZxXC6+BqEvGcY5pyjaM1tffJbk89NE3FP5VQ6y7a+paZAAAAAElFTkSuQmCC'], ['Arch', 'BAAAAAQCAMAAAAoLQ9TAAABCFBMVEUAAAAA//8rqtVAqtUQj88tpdIYks46otwVldUbktEaldMjldM2qNcXk9IWktQZkdIYlc8mnNUXlNEZktEZlNIYktIWlNMXktE7o9klmdMXktFHqdkXk9EWk9EYk9IlmtQXlNEXktAWk9AWlNEYlNFDptkZldMYk9E4otg/p9kXktEXk9AXlNA4otclmdQXk9IYktEXlNEwn9YXk9IXk9FFp9o3otgXk9FPrdwXk9E2otdCptkXk9E/ptkcldIXk9Edl9IXk9EjmdUXk9EXk9EXk9EbldIcldIjmdMmmtQsndUvntYyn9YyoNYzoNc0odc1odc2odc6pNg7pNg9pdlDp9pJqttOrdzlYlFbAAAARXRSTlMAAQYMEBEVFhgcHR0mLS8zNTY3PT4/RU1kdXp6e3+Cg4WIiYqMjZGXl5mbnqSnrbS3zMzV3OPk7Ozv8fT29vf4+fz8/f7SyXIjAAAAmUlEQVR4XlXI1WLCUBQF0YM3SHB3a1B3l7Bx1///E6ANkDtva0jKbCW2XIH1z2hiZEZ4uUgxo7JedTQye/KN/Sb5tbJ+7V9OXd1n+O+38257TL+tah3mADAwSMM7wzQWF4Hff6ubQIZIAIb6vxEF4CZyATXhZa4HwEnEA+2QgoiyQDnIEWkjVSBBZBqXbCRlKYo8+Rwkyx54AOYfFe7HhFa7AAAAAElFTkSuQmCC'], ['CentOS', 'BAAAAAQCAMAAAAoLQ9TAAAB5lBMVEUAAADy8tng4Ovs9tnk5O3c7bX44LLduNO1tdDh7r/eutj43q2kocX23az07N+qqsvUqcmXl7331ZXJj7r40o/Pn8T42qP63KjNw9n21p3Y387Ml7732JzR55z05MSxtMLGn8TC4Hx8eqt8e62Af6/B4HnG4oPC4HzH44fBf7LCgbOkoMTcsrmtn8PWqcfFtKrj4Jvs2ZOz2FnMqLXT3KfY5p60Z6NUU5XRuqHzwWSywqDn3JaiiLWahrWhkry5zJjRmqm1Z6P1wmb1y319fK632mK5cKi5nH+73Gu73Gy73W283W+9eK17e6y1yZS3aqRZWJdcW5ldXJplXZppaKBwb6VwcKV5eKswL306OYNPTpGkfK+m0kGpUJWq1EnEqIuXK3+Xh7ahP4qhkryMfK6BgK+CdpGMaKKMa6O9ea2+eq6+oYW/eq+NbqWVlL2Wlr7AjanA4HnA4HrBkqbBlafB33rCgbLCmKjCxIzC1mSs1UytV5mtxIWt1lCuz2evWpuvXJywxYzHjrvH4oXIjrrN2HXO5pTO5pXUlYnUlYvVl5Hb0G7e0XTg03rhr5fpzHPpzXTp0Hvtz3/wrDHytknyt0zyuE3yuVHzvVr0wGP1x3T1yHf1yXe0ZaL2zYP30o730pD31ZeRIcF5AAAAQ3RSTlMAFBkbHEhJS0xMTk5UWWBsd4SEiIiPkJCVlZaam6CjpK29wMPDxMTFxcnK193e3+Dg4uTn5+fo6e/v8/P4+fn7/P7+J4XBAAAAAOBJREFUeF5Vj1OvAwEYBb/yGlu717atLW0b17Zt2/6nze42TTpvMw8nOZCAmwUpiIY6c5IiLi9tPX64GairqszHQ4X2VB64v1Cs6PxMPJSdHM777s6/jyaMRGiRLyyrb88OpjZ3CzAXrm1sqzSNNeN7kVBPNgB7cG51abE5l9cXDces7emQ1uadHhutFUg6gpPKkSIqQGavwz7r7O/+/3t/rSdjI9XDM3qz4fr3B/3iA0aJTG9x71+9oR/PLDwUe2wm19bly+fTIxHyEETatbPewGEw6Mk/tKZCEqSQQUlIHB/QNBEjjVN1AAAAAElFTkSuQmCC'], ['Debian', 'A0AAAAQCAYAAADNo/U5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAZ5JREFUOE+Nkk0oBHEYxv8fu5GQj3JwcaDkIAc5IpR87M7MKnIVJVKclaIQ5Sy5OLkgR7n5OigcSNpmd2c2Vyfl4KT8/muWiVU79TTv+7zv837NCBF6PG1X+NpZyEYSD9mIc+tHnBPe23B9xKrCuTmbQA/JKfABrhBswa1hH4A38IwfOxPdX1qcjiCQxO5NyrjKV70TnSbeRPwJvGN3i4yyqnEucPY8ZZX9GSEgGK+RvFfyjk2VKZxzBNG8wJWWgh/xtDOeUXZ7Slr6TrSLYL9N4SMgYTTcwdc2ArvJcElhSVcM6mCNSV8n9hA59yTU5UWMG6HIbLhIWlglgWiC2L4Z79qTdo40D6ISuOWwKCWHyk9Fv8ldpUHOuGTuynwSBUynddPdlbEosVpP9Eu4FnOsRzUYNTsdmZN/d5LDiqM0w+2CMdAFFsFGWgfXxZnheqe/z+0puwEM0HHYV3Z9Sgz8TEz7GkQvpuJ/36ggj2AaHLrSlkULWV5x+h2E8xkZL16YVjGNaAUscfZ/f6c/k9ywLKI2MMcRWl0RLy007idmRbQJ7RIfDAAAAABJRU5ErkJggg=='], ['Fedora', 'BAAAAAQCAMAAAAoLQ9TAAABPlBMVEUAAAApQXIpQXIpQXIqQ3UpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIpQXIqQ3QpQXIpQXIqRHYpQXIpQXIqQ3QqRHYpQXI8brT///8uTYMpQnM5Zqg5ZqnS1+I4ZaY4ZactSn8uRnYrQ3MrRXgsRHUsR3s8bbM8brMtSX4wUosxVI01XZw2X50vUIguToQvR3c6X5o6aKs6aq08Un8qQnM9VIFDWINJXohKcKlXapEqQ3UvUIc2X55bhcBdcJVgcpdhfapmd5tuk8dxgqJ1hKR5jbB6iah/m8Shudq3v9C4wNG/x9bFy9nFzNnFzNrIz9zK0NzK0t/O2+3P1eA2YaDU2eTb3+jb4Oje4urj6fHm6e/s7/Tz9fj3+fz7/P38/f3+/v83YaEa/NNxAAAAHnRSTlMABAoVGyY1SVlpeIuQsLfDzdHW4+3y8/b39/n6+vr4+ns8AAAAyklEQVR4XiWN5XrDMAxF75KOknYdZJS0klNmHjMzMzO9/wvMcH7I37mSJShsJ+5NjMT6umDoHyXDcI/2qJadh++P3cle1de+9yPe3/bTY92wzfzr7wGtP3JrAI72BZGVtcAdQlwHy+JS1pDbBE9qamZF3BYrjQxPEXwKc6dC8bXFm0QIpmt8kn0Rn093q82UCtK8oXZckwFJzuulV8bHkajPyXdbnJnARfDHs0trz+JQ+5AFvzp/L0+cL2qPAINUPrq5OC6p/64F/AMnrST+Dq/r7QAAAABJRU5ErkJggg=='], ['FreeBSD', 'BAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAABIAAAASABGyWs+AAAABmJLR0QA/wD/AP+gvaeTAAADXklEQVQYGQXBS2wUZQDA8f83j33M9rF9d7u4loaWklaDpkSo9KDGaIKUaGxshD2YSPRiuDVeTDyhBxosJCoa40ktpAkPDcUqAYVIpUSUPrAulEdD2bbb7e7ObGcfM/P5+4kwKDvq6yJ1FYYcvb+YAkqAHo/HQ7FYrFIoCiurq9ZXJ06YSOkA+kBzfX06bys3zHxS9EL0tXDVyZfefacqV+X/ZSJx5+qLbx98LhaL9RiGEZWlEsWC/Thd9q6Pf3vs2u6Orc83rFsvTwwfLf5obgywT1Vjh2Hh+rbNsnTssJdNLedK5aIrpSuldKVXKsnH4+Pyn6FDXn5tMef9O+3NvdkvP1V4+EYw2AoQ+KSx8dRYS6NXXnwovaItXduSrrkinWxGOmZWJi9OyOK9m1LmsjIz9IH8QUMOd3WfAQwNKCy2tJwbHB5+XasPaxIHmc4g7WWEZ1MquBiRFlJTf1E7+Tl/H/8asavPzTY1nWd2ZkMDRPeBeHPz5ojwsilEQCBvTSKunCF3M8FSNkBGVTHDYYrLj8jVNhDZ2SMa2zo3MTamaIC/u6Ojr3DtrOrvP0BpdATnyBeIhTxpR5ABUlKSUlXS1dWstbVxdz6hPL0l1quGqkLaKwNvVcjEXNRd/4mit4Z19DjefBEPyCKxgQJQcF28dBrHNDGTSZSezsjeff0hraa2Vs2vrvit81O4vj9xLJcC4ADrQA7YAGqBGsAql/EtLdFQE/L7dF1XZmdnSrbPMJfXoLDmolQK8gJyQBowgQhQDRQBD+hsraVhd4e5MH+/oExfvWLJ9q3/3S7qMpNH2hsS40kFS4EUUAMA2IANRIBXv4uzuO67c2PykqkA5YmZ6bN18YPi0Yoknxc4AsJPCMLVAk2BLKDosCWqs/PZaulkuxk9fekcUBAAQGDks5FT0W++3NuYuC0DVUL4DIEdlIQDAj0IRkigaMjArkFx0tf523sffrQHyKsAgHPhwoXLL+yP9/kePNhk5ExUTyKFkJVAUAiCFZrQup4Rv9ftuLV/6ONBYBVABQAArMvJ5MXW7duD6P62sD8UrPAFRU1TpeCpCnGvPZr7WW///v0jpw+VC9ZdAAABAAAAAMLo7drWrmQyPWG/r8tnaGIjaM05ujr16x/ZBFh5AACA/wGZnIuw4Z4A3AAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxMi0wNy0wNFQxMDowOTo0OS0wNDowMOPVpFwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTItMDctMDRUMTA6MDk6NDktMDQ6MDCSiBzgAAAAAElFTkSuQmCC'], ['Gentoo', 'BAAAAAQCAMAAAAoLQ9TAAAB9VBMVEUAAAD///+AgICqqv+AgIC/v9+Ojqqii9GAgKptYZKQkOmPj/ddUYBgW4eVjeCTgfiWjO5wbJaZkvPBvepkXomYkNldV4Bzbpl6dJ+Uj7ynoO6Vi+1qZI63se2mnudjXYjOy+GCfaqZjvWlm/Pc2e+Oh7NeWIOWjfeXjeW1sd+gl+diXIfp5/KHgKnn5/F2cZx6c6ZgWoXc2e6dltrAvNu0scrX1eTOyujCvup4c5qpovVpY43///+6uPPJyPXq6fvm5vrz8/z8/P7+/v/d3PixqvmxrPSyrfe0sPO0sfS3tMve2/3r6vy6ufPz8/3d3fi3tM63tPO4tsu5tsu5tvO6tfe6t/Vva5KRjKy7tvW7t/W9vPO/vM+/vvPCwfPEw/TFwvTFxOfGxfTGxvTHxvTIx/TJx/aTiOrNzPXNzfXQzfnRzuHS0fbS0vbT0uHU0e/U0uTU0/bW0+zW1ffX1vfY1/jZ2Pjb2/jc2uSTiemVkLSlnvbe3PTe3vng3fzg3f3g4Pnh4Pnh4fri4enj4/nk5Prl5Prm4/ymn/bn5vro5/rp6O/p6funoPWsqs3t7Pvt7fXv7vzv7v3w7/nx7/3y8f3y8v3z8vytqPWuqPX09P319P319P719f339v739/34+P35+f37+/+uqev9/f6vqvSwrPQAR0dcAAAAPHRSTlMAAQIDBAgJCwwVFyAsNUFHSVBneH+Bh4mVmZmanKCxsrK2tr3ExtDW19rb4ODl5u3t7u/w8/T6+/z9/f4MkNJ1AAAA8ElEQVR4XjXNw5aDURSE0YrRtm3b54+dtm3btm3bz9k3Wek9+2pSYFwT8ibzE93hwAtdJqK3nZo4J9hFXbP+vFHOthV6gnGzstZq94wdCs4UCCDymQ2v7X0LdYoSQ0MIENRYzJbRlPTTHu73ZNAL8vivmVui98PpzuqffX0mIPHJGtOQenukteJ+aS3b9htNpDnT9TeZH1bHAwBRMhGpd6e6uNrLoRgxBKmsX47nBlp678ojpEA40fejcmW4e/No0V8IIPfj6eKgbEJ3ZUnzgE1OqWp9Q3VeWRAsg51f1dZ8c31RmAsc+N5JGbG+zvj3BzDCPrzMDC9SAAAAAElFTkSuQmCC'], ['Mint', 'BAAAAAQCAMAAAAoLQ9TAAACVVBMVEUAAADh4eEAAAAAAAAAAAAAAAAAAAAsLCyXl5dgYGCnp6eTk5N3d3fBwcGqqqq8vLzNzc3Ozs7Ozs7Pz8/Pz9DQ0NHR0dLS0tLS0tPT09Pf3t/Pz8/i4eLb29vZ2drZ2tna2dra2trf3t/u7O/u7e/u7O/r6+vt7O/w7/Lw8PDy8fTz8fXz8fbx8fHz8/P19fb49/j49/n6+vuPxlmWyGOx437h9NDr9eD6/fj////+/v75/vTA5Jv6/fb7/fnL5bDL5q+AxjeDxUCEzTyGxUaGzjyHxkiHzz6J0D+Kxk6K0kCLyE2M00WNy06P00mSz1OUyF+W2FGX1FiY0F6Z02CZ21ac0Wiez2yfz2+f2mOh4GCi4GOi4WKi4mOk12+k3Wul32um1Hin0nun4G6n5Gin5Wmo23Op2Huq1n+q43Cr526s4Hit23+v6XSw34Cw34Gw6nWx4IKy4IOy44Cy63ez146z34az4IWz4YW03Y217nu38H2625e645G74pK83pu98Iq984W+4ZjA4px0tzDA5ZrB8ZDC5p7D55/E947F6KHF+JHH4qvH6qTI46/K5LLL5LN1tzLL5bN1uTDL57DM5bPM6qzM66/N5rTP6LbP6bTR6rfS573T67vT7LrV7r3X68XX7MHX773Y77/Y9rvZ8cHa7cjd88bi88/j8tTk8djk9tHm8trn89vo89zo9N3p9N3p9d7p9tvq9d/s+93s/dzy+erz+O73+vT4/PX5/fT5/fX5/vN1uzB3vTD6/ff6/fh5uTj8/fv9/vr9/vx8wjV/xDmrMRH0AAAAOXRSTlMAAAECAwQJDzk/RUlNU3F0kpSVlpeYmpucnaKjpKWqqqqtu8LExMTEzdTU1NXY4evy8vP+/v7+/v6LaR1mAAABD0lEQVR4XiXI03bEABAA0KltW9kaW3eSZW3btm3btm3b/q4mp/fxgqKOtpamhrqaqoqykrQYABh+PVMU9fjE5Xp8o54kgPHN0EBHU2N5YXZykiua0HHd2759VF2Sk5IYE5GGsmCEWLV1kVWwt5O+3x/qpgsy8k4ja+cJl2/v5C22tlgCAHtw9TQSa4s+AzfPSm0BRNl9SydhWJzLC567KrNhgrNwHIJ5qTz/2f9w7Jw/DNqIjVr04exW0AEOXcN3Ab7enr9eDW2VTJgehONyc2Z8XP5YdD0Tcuhcc4/r45OjGX51TEjYPbh8THRPvbz+CHusgSZlT7rP8PkCwfQKaQUi9Igr6JsRBMFiWZgb/AHKElRzKopZJQAAAABJRU5ErkJggg=='], ['Osx', 'BAAAAAQCAMAAAAoLQ9TAAABrVBMVEUAAAD///////+qqqr///+ZmZn///+qqqqAgID///////+tra339/eAgICoqKjx8fGMjIzm5ubh4eGPj4/g4ODIyMiAgICSkpKLi4vS1tbPz8+Xl5eMjIypqanIyMjW1tZ2dnbR0dGamprFxcV3d3d+fn60tbV3d3dcXFx3d3epqal7fHxxcXF+foCnp6hYWFhyc3Ojo6SMjI5fX196enp+fn6Li4xERERqamqgoKFpaWmFhoeen6A/Pz9QUFCWlpeSk5SUlZWUlZaOjo+Tk5RHR0cuLi5YWFgwMDAeHh40NDQ3Nzc6OjpcXF1rbG0XFxdSU1NVVVVXV1dZWVlbW1tnZ2lwcHABAQEEBAQXFxchISI+P0BISUpaW1xHR0kNDg4qKyszNDU1NTY9Pj8NDQ1cXF4XFxhSU1QSEhIDAwMrKywtLS4uLi4wMDFHSElISEggISE0NDVJSktNTU1FRUVWVlhGRkYEBAVBQUE0NTZQUVJQUVMFBQUqKitWV1lXV1daWlpaWlw+Pj8bGxtcXV9dXV1fX19fYGFgYGBkZGRlZmhpaWlsbGxwcHB2dna844Y9AAAAV3RSTlMAAQIDAwUFBggMDhkeICMkKCgqMDIzPj9ERFBib4CCg4iMjZCcnp+jqamrw83W1tvb3ePl6Ojp6+vs7u7v8PHy9PT09PT3+vr7/f39/f39/v7+/v7+/v50ou7NAAAA30lEQVR4XkXIY3vDYABG4SepMdq2bRSz/capzdm2fvOuDO397Rw0Ly4tz2QAQPbcxuZ2E/STJwfxPhWgG355fRrVAIVb1zeP9UDLfiSwkAcADe8fn7tFxWuEXFRDoer/OgoMTRBCumj8yJwPBo8Zhpk14U856/HI8n0ZUtpZ1udrSzfVneA4roNKjdrwpcMRilb8d8G60+lKnrpWcn9bO+B23w2O8Tzfq4aiNSZJqzn5O4Kw16h06fPZ+VUlUHfo97+VAEb7rSh2UgDd4/U+TBlQY7FMj5gBIGvcarVVfQPVPTG94D0j9QAAAABJRU5ErkJggg=='], ['Rhel', 'BAAAAAQCAMAAAAoLQ9TAAABj1BMVEUAAAD///////8AAAD///////8AAAD///8AAAD///////8AAAD///8AAAD+/v4AAAAAAAAAAAArKysAAAD///////8AAAAAAAAAAAAAAAD///8AAAAAAAAAAAD///8AAAD///8AAAAAAAAAAAAAAAB5eXn+/v5JSUnKysrS0tJ5eXmqqqqxsrL+/v4ZCgknJyeHh4eIiIjo6OgZCAdOTk7t7e3///8GCwwPAAArKyv19fX29vb9/f0EAAD////+/v4AAAAGBgYHAAAJAAAMAAANAQAPAQAVAQFyCQV9fX2pIRzmEQjn5+cBAAAFAAAAAADnEQjvEgn////uEQjyEgnsEQjzEgnxEgljBwPaEAj9EwnwEglHBQJHBQNNBQIBAAB3CQR5CQSHCgWLCgWRCgWTCwadDAWmDAapDAa/DgfKDwjWEAgGAADh4eHiEQjmEQjmEQkKAADoEQgLAQDtEQgMAQDuEQnvEQjvEQkPAQAfAgEuAwEvAwE8BAL1Egn3Egn4Egn6Egk+BAL+/v5CBQJrB0muAAAAT3RSTlMAAAMEBAkYGhsbMTRLUmpvcHeIjLe6vcHCxM3P0NbW3Ojp6u/w9ff5+fn6+vr6+/v7+/v8/Pz9/f39/f39/f7+/v7+/v7+/v7+/v7+/v7+Q8UoNAAAAO5JREFUeF4tiwVPA0EYRL9SXIsWl+LuxfcOd2Z3764quLu788NZNrxkksmbDP2R7vH6GioLs+iffEzNXd4+TqPErUUpVqMOvwgdzMPn1rv5vPsVeufBTaBK/bH2FPvkEUuIG5jIIc+sHYn/HJ3dC/Hxuo4y8s44dzwBbFkisHN8bVIdXs6jb+H97aCwbHEIqgcml64CD7YllNkAVQC940MLYe5YzvIeQAXNrd19Roc5MdzfdQLUUKaUYyuG9I8y1g4gj6hIak4X5cBIT2MquZJrJdOqpY11ZpAiqVwbY/C7KY1cRCrZxX4pWXVuiuq/hs49kg4OyP4AAAAASUVORK5CYII='], ['Sabayon', 'BAAAAAQCAMAAAAoLQ9TAAABvFBMVEUAAAAcUaYdVKwAAAAAAAUABAwWRY4YSZYhZtIhaNYHDx0KCgoFDBcKCgoRMmYSNm0fXL0fXb8AAAAYS5gaTp8fXLwgXsEGBgYFBQUZSpgZTZ4JFSgODg4IEiIOJkwOKVIkW7EnXbQLGzUTExMKGC8LHjwMIkITExMiIiIPEBEPJ00QEhMXOXAaPncOJEgoXbApXbEcHBwwMDAEAgAfHRgQDgo3NC8AAAAHBwcKCgoLCwsJCQkaGhofHx8lJSUwMDA0NDQ4ODiRkZEICQocHBweHh4GBgYHCg8mJiYnJycpKSkrKystLS0uLi4ICAgODg43NzcRERF1dXUUFBSjo6O1tbUbGxsEBAMLGS8MDA0iIiIjIyMkJCQNDQ0NHTYKCQkoKCgPDw8QEBArMDkKCgkRERIREhMxMTEyMjISIz00Njk1NTU2NjYCAgIVFRU5OTo5P0c8PD0+Pj4/QURAQEBHR0dKSkpMTExSUlJiYmJlZWVnZ2cWFhZ2dnZ4eHh8fHx9fX2FhYUXFxeVlZWXl5eYmJiZmZmcnJwZGRmlpaWrq6usrKyvr68KFiq/v7/FxcXY2Nji4uLn5+ft7e0yif9uAAAAN3RSTlMAAAApKSkqKioqg4OEhISEhoa1tra3t7y9vr7S09PT09TU+Pj5+fn5+/v7+/v7+/v7/v7+/v7+70RY/wAAAPpJREFUeF4dyWNjw2AUBeC7dfYyorM6rx1exKltzLZt2/rDa/J8OgBVVlFDX39jcTZoUqCse251a2dvu6ccUtWlanLQ4Vpel+ThlWq1l3wEz58tx4dOt1dMlAJk9A5gMjG75LHwo46hzkwosGOMbejumoRvubC9EOrMviT0E0Us9fvN9dA6zxJCNv6+ECGsb6oNWsgmpZT9/UTUZo3Em6AW34guTL4jiAudiCM1kLcw8/SmHERfT1/eueBiDqR1GK1n9w+K8nglxYxd6QAML4ztXoQuj8YFgWcgqdJp8qzty26vaboCNIxBCshyQDKov0aXr29v1ufq1PwPx5Q7bCoh6eoAAAAASUVORK5CYII='], ['Slackware', 'BAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AcEDi0qZWWDgAAAAx1JREFUOMt9kktoXHUchb/ffc1M7rySSdJMOknFPMRitLgoNKKI8ZHGKkgrjU8SitidimSh2UkXoQmoO1dGQSxJjdvOtqSaqlR0USEGSjVJGxuSmWR6M3fu4/93YX0g4rc9HA6cc4Q7DI+fpzz7PA8++2mxvZAeBZ4xhHtFcJRmXWsWvb36/OLcyxf5B/KHeYHy7DmGx1+YSDjmWTdlobTGMAStQGkNoLXS4tXDq7u7tUcWz49tA8jR8QUuzB5n5NTCV13F9JEo1JJwTLKuzU61QiOMcd0UDb+BncwQK3Rl15eNja3ui/Njq8aF2eMcO/XlBz0H8oO2ZUkum6A13WB99TtyzXlaCi24SaFa+ZFCzsG2DNnfkdbFjsI1APPhk+d6ujqznycdCxFozadYWvyMpx47wa+bPkGksKwUNnsk3TaCGASRXDZh5LpHXPPg4Rcni+3uYBxrtBbQghlscOVKmYHeEm0ZIZ9xyLffw41ND6VAa43SmjiMByzHYtjzwr9arfshxf5jOKlvKZfn8es77N2uks24PPfSFD/9Uvt7AtPKWmEU9d645eHYJo5tcKi/FX/zG+zmQxQH+rANk862DOW5N/hhaY64cJSa5xNFCgDDILZACMKYWAmh73HmzFsMlBQJ06LeiMinE1S3KzRCm5rXIIoUIoKIYCVM36urZFbEoiBLNMIhAE6/NsSB7h6SKZdL8xsUOnpx9j1KbTdARACIowArYe1ergfNT2i0mIbJys0GI6PT3N1/hJvrPxOFdRJNBQIy/FapI4Bpgohgcjuw+jq8jy8tV55MNBWI4ohS802CpizKv8q+FgALZAfYgSyAZtNro1oLaU1VvxCA029Oraxs7u/tKnXiNjn8HyKwur6lI++6vPK4V7IA7u+1Dyu1tr183ddNbkHuXP8/zEIYeFqiLRl6YO/p0bHJdflT/PD9qZa1W+ry99fcvlAlcZwUpuUAglIRYVgnDEIOlna4q0M/NPnuO1/PzMwg/045O/XeibUt5/Xangx6viSVFpK2jtMpvdyWCz+5ryf10clX3/amp6eZmJjgd441URWWJY8BAAAAAElFTkSuQmCC'], ['Trisquel', 'BAAAAAQCAMAAAAoLQ9TAAABjFBMVEX///8AAAAAAAAAAAAAADMAAGYAAAAAHFUAGWYAF10AImYAIGAAHloAHGMAKGsAGmYAJmYAJGEAKnUAJ1gAMXYAJnEAJGQAI2EAK28AK3cAGTEAMHgALXEALXgALG0AFUAAI2oAK3EAMngANoYALXMANIAAM4IANIIAL3gANIcANokANoQANYQAOY0ANIYANooAN4kAN40AOY0APZMANIUAOY0AO5AAPZUAPJAAP5MAPpQAQJUAOYsAPpYANoUAPpoAPpUAM4AAQJkAPZIAPJEAQpgAN4cAPpQAPZUAPJEAO4oAOosAOo8AQJoAOYsAO44AQpsAO48AQp0AP5UAQpoARJwAQ58ARaAAQZgAQ54AQ50AQpgARaIARqMARaMARaIAR6QARaIARaEASakARKEAR6MASqsARKEASKcAR6MARqYAR6UATbEATa8ARqUARKAAR6oARqMASKgATK8AR6QATbIATbAASq0AR6cASKgASqwAR6UASKcATa8ASqoASqwAS6wASKoAS60ATbHn4CTpAAAAhHRSTlMAAQIFBQUGCQoLDxAREhMUFBUYGhobHB0eHh8gIiIjJCQkJCYoLC0xMTE0NDo6Oz1BQUNHSUxOVFVVVldaWl5iY2RkZWZoamtsb3FycnR1ent9f4KDhIiJioyNkJGYm5+foqOkpqamqKmqrKytsLKzs7e4uLy8v8TFxcXGx8rO0NXY2eZc4XYcAAAA00lEQVR4XkWN1VoCUQAG/3NWtwh7CTsQJOyk7BaDxuxA6bbrxf32gt25m7kZqDRYxziooDV7+1AalMUavQh2AsEZoWvzigLun+T17/c8QiJZ7qu2QKiNmyZthdcR1/as353jIeU1GxMHo5XHdqPFeX8IaDMdHPYN6dRN7LR4qQewdTa35HWkyh+fbxERAMjwlAWJv3CPSKDQ+H7XvHdkV4Pua3Gtm4sPKIF/WV8dop4VKBw/NU33B3x1JbTt+XwhkJQoqRfWvHOy28uqH8JIdomR/R+s9yR3Cso77AAAAABJRU5ErkJggg=='], ['Ubuntu', 'BAAAAAQCAMAAAAoLQ9TAAABKVBMVEX////ojFzplGf1zbnqnHLvs5P10b3yuZv1xKrytZXvtJXys5LysI32waT0n3HxiVHwg0jxhk31kFn0h0zxf0P0hUrveTv2iU3yfkD1hEfyejv5eDLybSX0aR7zZxvyayH6ZxnxZBj4YhH7XAb5WALlUQLeTwHgUAHeTgHfTwD65NzdTQDdTQHdTgD31MfcTgLcTADcTQD////xt5/31Mf54dfmfE/dUAbeVQ/jcUDcTgHeWBnnflHohFvpjGbqkGztnX342Mz53dLgXiP65d399PHdUgrtoYLyu6Xzvaf76eLfXB/rkm/fWhvupojwrpTeVhTgYSfgYynzwa30xbL1ybnngFT31snngljhZS3539XhZzDiajbibDn77OX88Ovrl3X99vTjbz1fisGCAAAAMHRSTlMABgYGBwcHJiorMDA1NXGHjY2Nl5mZmZyfn6O5u8XHzc3X193j9fj4+vr6/f39/f08OUojAAAAx0lEQVR4Xi3HZVbDYBhGwQctWqzFPXiQ+36pu+LubvtfBKcN82/UEhld2vWXxyL6F92gbTPabse8hU/uHMx1SZoyyJWPTwq1Rs7GpYE9+Cg+OJcs1MHvU9y4fnrN31yUm18vMCIPjtw3QMndw4rs8ieVzAAcBlewpe1KM3uaBuD3Dda1BhWXAsi6AFY1a2SqifxZ+rnxWYcJDRkUS3fO1R5vwe+XZgw4D4L3RAJiknoXCVX3WeiUpJ5pIxTvVmg45pl5k4Ot/AGV2iqZBWgJJAAAAABJRU5ErkJggg=='], ['Windows', 'BIAAAAQCAYAAAAbBi9cAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAA+pJREFUOE+F0n84FHYcB3CWSsL9ojo/6ik64c6PnTjmSS0limmrpBm2G002y++xzXRz6zE0R4nbw+RnTj/WD4sbanLkkAe55ccYlyNme4SrO9u9d13PI3/saZ+/vs/3831ez+f9eb5aWsuqy2mjRYeNUa7YmtjfTico7jNJ8z0eG24NB9vvnDrvufzpq89Npnr8VjMddNmuRh9rDfp36mFg91oM7qPIc5JdbDJq3An/JfCu7Hl53W2lpS220pP2OuniN299jAYbYizSENIoAgbCTdrTKtxOJVdvGo8psUwKy7Vxe4ez1YEVudGP8YEZzyveInFJ6mZRHHqYazDspw/pJwTIuERM5JIwmUdGdyo9K7/BszGzzg6fXzZHGJ8KvzQqXKOpoIeZLjofWR++BPWyCEnPY4xFGEKWQcLjMjKmr1MwfcMYwmz/Y4KOgNki0V5k1dkjUWCK93Kp2PMFFawos8cm1gZ2GqjLXktL4mbQPHLQ4B9ZDFE5+S356fQlyuJMqzH++HnTo6ui2OO1ko9Ul+4fxfd3d4F7k4YTReqpuFS88bGZUE2QNNDobuIq8Q5CduHb7lFJaTnvnym9ergjMWD/FG8zf+aKS3G9JO5C01Asah6wUXrvALKEDoitMMHhDKrKJdg8RU2s0EB2EWWur8dd7PDPFv6dUC0Gv3kAN36VPRGP/5k5NS6lljWxG0TDiSr1VKhoPwhevRMSqkwRxDObc/DavGtpP6zoi8XOyZfhnyNEvKANBU0P8VPfI/wyNCGXSn7wlEmyA9KrgmOKGth3eDVvPfyywq2dnUEv2R9qG2rLsH7xJXziKnWcI8tlTvEC7Mu8hROlImTU9aKqcwQ1vWOihWFu+sJknmph5CvxQh87c7bNh/NXo03hrMCosyvLmMNgMF7TQL6J1dsZIUVwjKqEO+cajp5vxPN439U/gKBt8PTcYHzL/BgHCyOf4unAISj6mFC2bYC82kB5Ls460NHRUVsDeYSXpGw7UgC7sAtwShDgzdM38W7BbURXtqpqhfmB8sEQuXwoCM/6faGQuGCxyxyKWhIm+PrSD495WL3cT0hhi8Whc3NbAs9KaOyCTvrJ8qkdX19XBeTUDU00+55USFzVU2yHstcaix0mUAjJkJeuRU868Ucmk0lcguiBnMAVxjbbdHV1yeq8+u4Hgo22huSG+iQXp83ftaxW3lsPZcs6KG5T8OwaAfJiPcxlrVRVRhvF02i0F/t5VbHZ7JWDfErKTLnhE3mFPuRFepg/uxqz6TqLv6euGj3ut87t/4ylvre3t3ZehOWWO1zjSFEqMVP4GfGb/DBykJcjmaZOoLsc+hcVY/LaAgcTQAAAAABJRU5ErkJggg=='], ['OpenBSD', 'BAAAAAQCAYAAAFo9M/3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAykIPu64pQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAADTklEQVQ4y32RXUxTdxjGn3N6eujoKT3SUkuk3VoBGfVjgFXAsZ7WkipyYXQbuu3CzUXZmGRbssnFEseFkWzgcGzGXky9MWL8TsC4IeFgtK4oAqOnG5vMVl1pCMVWQD7b/y5M6jLdflfvxfPked/nBQA0NDSChqnGVrLuGkES742NhJAdhAKAuk9yyUs5Gry7RQMZAARCWgivpQiPe71P5DUfH0xaqTL7m/iiLkJmphawa+e4SM2PvUyC4yUIBu8CnAQKAK53rCA5OUtQtStVpJ4Gw/FOBddZVKhCfq4MP4n6+at+DUsJm/e0G9JZzYEvI2tHwlEYjDxomkZ+3nG8WroRtHihZVOhVlorDQzh0okhcByDP4ZGcf+X9XAsvY5/RsBa7Kq5H/CqLctKyl/g08S2i6fq8W/MS3P34T9wNDVYSeDX1eTD9xhiLXbtB/Akwmmv6Kr+ICFkLpGhtNSM3qsSstS3oX8lSsmsxS6ZVn3j6PvVVqhUcvC8AtPxVPxwygVKvngN89WOjgVprggGA4eenjB4nsXsTASpC63I0wVTZYPR11FoKRB8Ax54PCFk6BhMTk5CPR3GSbHouGzknr/bYFq9EAvfc9Tu1sLjHcXNKxLuTOTgzOlOe7IHBc/beAXWpWmXlz8a84nhcLQ+ecVzsAEQrMWuMX+f9HZF2YPZ28FVSNfoPWqOzMUmqYMAJm7+/OOzXQFwHGpyEV+vi+yvtxBC9pDmpgJC4tvI3mo9GTitIxvW24nT7ug67HY/3eDs2bbyrVsrY2day70rV6kRfDAHk5lDLJqAmmeRiD9GJDKHvwb74R8G0mkTPjrQTTG122xkTTbwaV2b1H4u16JQKXGr7yG2b8/H1MQ09IsTSEmRwzf4CCwzD+dmE1re8CI7wwi5XNlFf9vaTXX4dWJg4LLl7h05fpNGwNAMWpp9CIVYNO/tRCzGwpDFQaVMQTS2CKY0BWr3GVGWNSXKACDDaA4Mh976pq9f5Sy09GgKlmeAMIBKzUKpU+BFoxJecRhUfAbMxDi4eADfHVmE79v7q575gvvYeVvjZ58LD5mwsKUyX0hnf0feslnQCWD4zxnc6reKisxsfH2oscqcmTmK/+Ow252cna7K52r+Bky6PqmoT5HBAAAAAElFTkSuQmCC'], ['Gnu', 'BAAAAAQCAYAAAFo9M/3AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AoYAywUV5gQrwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAADcElEQVQ4y43Tb0jjBRzH8c9v+7nNMebcUW21Cc78g/wcuhByIScoMRwoTBmFlZCmIJ14axqkgoYIkXIqKIVBEuJNUBEUPRlpqDC3Q2Ex0nTezun2YOaPLXNIv7Vvj7zgiOj1+PPk/eADjuNEuHN6ekqMw+H4IzMz8xChUCjV1NT0JbO7uxtfXFy8NZvNr21tbd0AAEQikY6I0m1tbQbx2NjYZiqV+vn29jY+PDw8xhYWFj45PDzcb25uhlQqfSTief6X0dFRpqKigvF4PPPipaWlY7lcXhCLxXJnZmY+ZTY2NnzX19ePGxsbHw0MDLivrq5mc3Jy2pPJZLVWq/2cdbvdDSzLholoNJ1OMy6Xq0Ymk5HNZktOTU29qMgA8HYqlaKDgwNKp9M0PT09BgAM/iGuqqoimUx2yPP8U5/P9wEAMB0dHRUKheJHiUTyeGhoqAUAnE7nR0qlsjcQCLwjlsvlz+bm5mQWi0VSWlr6bXV1tU6hUMj6+/vfN5lMN0xxcfG1zWZ7SETTSqWSGhoamPHxcajV6s+8Xu9Xou7u7t9VKtW00+mkSCTC6PV6aDQa8Dw/Wl9fP8UAQCgUosvLSyovL2eWl5dRUFBw7Ha7v9vc3By5K3g1EAg8FQSBiIguLi4IgBwA2LtEjuPuJxKJ62AwKFpdXf0eQBIvYVmW/cLlchEAWK1WAADT09NzX6PR/OTz+eKVlZUzKpVqTyqVvsnzfLCkpGSrtrb2t97eXnFeXl5ZKpWyZ2RkPPP7/UUnJyefGI3GU+zt7aU4jotOTk7mAUBfX1+b1Wq9kcvlBIAcDgctLCyQxWKhoqIi6uzs/BoAVlZW3qqpqbllZmdnf1hfX//Q4/HEzWbzX+3t7fcMBgMFg0EYjUYmEolAEAREo1Hk5+fT+fk5Mzg4GD86OpJ0dXXJGQBoaWl5Ra/XP6yrq3tQVlam2N7ehslkAsuySCaTUKvVSCQS2NnZSXAcJxYEQTEyMvKeIAhLDADY7fZ7BoPhm6ysLFpbWzuan5//WKvVvsHzPEWjUSYSiSA3N5d0Oh0TjUaf+/1+S2Nj46/4FwYAr7e2tnbF4/E/iYjC4TCFw+F0LBaj/f19mpiYeID/IAagAyABYLXb7cLZ2Rml02nyer3POY6rwv8hEr34u0IkEk1mZ2cTgGMA7768/RtL5JKsGzrLIgAAAABJRU5ErkJggg=='], ['CrunchBang', 'BYAAAAQCAQAAAC45EetAAAA8ElEQVR4XnWOsUpCYQBGz1TIHYu2Qix6g0DEtSeQu/UIISJtUS8gJq61F1wcdMohcBDxKUR8hsz1xA/y44/cs3znbB+RJ0Skl3pSkeFQbUs79VAPzrwPFRmN1Ja0Ug/16I93+1oi4lKte+zMXv32WuoAm43lXMrqzbFncgWw21lORf4+/PREKpAhYqZuPXZ+T/3yXbZEajV1JavUQ104sRcq0myqc5mnHurWqc/7yhExVwuPncl+C4Bu13L60ueAwcByOtLhgAIRCzU38fRGTmSxUBvSSD3Ui1NvQkXWa7Uq1dRD9R17HiqyRUSy1NP6B7e1Yu2GtlUKAAAAAElFTkSuQmCC'], ['Yuno', 'BgAAAAPCAYAAAD+pA/bAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAABDtJREFUOE+FlHtMm1UYxrtsi8aEgCb+oTFmZur+WNS5RaPERU10C2qGaBgb6hgwLwMmHTIKlIKlQIHSQrmU24BSSmnpBVooUmihtEC5yKWDjVu5uOkcEca4lG5E93j6EQmELX7Jky/fOed9fu973vMdGu0xT3Cgz57yXMZLDdXcy821PFWLKmuA6HqLMqtLX5POl4iYb2ukWW8IOOFe/qfe3/M4n0eOjwyZD8//bldODOk37N1yDJgl+LVdjEGLFKO9KkzZm8hbje7mIrTXZ7sMtTydrJh15H8hHW11XvN/jGS7VudcD5w34ZZzeQYb67fwYO03LN4exo1+LWzNxbA05O5QuzbHqRYn+++CHDx4YK9WLfaedfQzV5em54g5Zbi8OIml+VFMDLWQ7GXoaSmFWZsDZVGCO2u0EbkhHTrhFqi9PmelSsQ8tAtSVch60dpUeGe4kxgZxegzVkBzlQ2NKBG2+iJIMqMok9r8OLRIMqApToSqmAWTmk9B2+o2YW79oshU7ABcuvAFrVGWXkVKpBYoSaBSxIS2mINpiwbjZiUMZRloVfJQyaXDKObBpimBScpHFe8KmmXpaKhK3arGrBVuVBclHN2CiPNin1OVs1tVJYlQlyZBxA6DviQVo6ZaOKd7sTplw53BVugruBBzfsRslw7rZPxaczWutSpQV/gzJPxo1JexyfaxKBBpuiEx+tw+CpKdEvGWTprGlhcwqbIzL5/DYKMYndpK3L1hxf3ZfkrzwybUZjPhnOqmvlcmutFF1jis9QSShOrcWNSXJ1MA0ou/NZWc8Ddfe4VGO3bk0JON1dyMMlK+gmxNrZCFhZF2Kng7YNO0awt4b7wLNp2EqtAsF6ImP56SG0B6siovTYpIjg15gapCVhAfJRUyIBFEo6k8AyuTtkcC/qvG/XbDexulWJvqgYH0o0nKhVHFJ40XwFQnWM5OCX+XMg86c3KvVMSMapCmPpSTIygTxGKZZOcOXhrr3Mp4uzkFuG6B3ajE3TELDDU8qEmsmvRATxquKkxAnSTFjwKEfv3JU9JC5unG6rQ1bTkbQ4Yq/DVgxOqwBWt2K9Yne3ZCZvrgHO2k5paHzOhSiVCZSkdNTgzy40JRlPgDhDHBCxUZdCs91G8fLeK87zOl6XSOICZYXMGNhDqX9fDP/mbK2DXVi/szm03eLpejl5pzOfqwOt4JBT8OeYwQt/4R/BR0OzXiLCM5LOCji/4nXt46rpywgG+zor5RxgSdupBzJdglSY+5ZZbl3XNY6mbn7W0Lcx06zBg1WBjtcC6OmG+OmRTrFrnIUZESZeVeCpwh8TpiPsQ47/tloM97T+/6m8mg55mT3tStyL54mhlwwtszNvjzD8/6HH8i7PvvPPRioZdRWuDBZUR6pEWG7I8P9Xs1Jsj36MfvvO5J/+rTw58dP7afJPfBgeef3XGz/gskFVpJc4HwGwAAAABJRU5ErkJggg==']] - }; - - ExpandComment = { - init: function() { - var a, _i, _len, _ref; - - _ref = $$('.abbr'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - a = _ref[_i]; - $.on(a.firstElementChild, 'click', ExpandComment.expand); - } - }, - callbacks: [], - node: function(node) { - var callback, _i, _len, _ref; - - _ref = ExpandComment.callbacks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - callback = _ref[_i]; - callback(node); - } - }, - expand: function(e) { - var a, replyID, threadID, _, _ref; - - e.preventDefault(); - _ref = this.href.match(/(\d+)#p(\d+)/), _ = _ref[0], threadID = _ref[1], replyID = _ref[2]; - this.textContent = "Loading No." + replyID + "..."; - a = this; - return $.cache("//api.4chan.org" + this.pathname + ".json", function() { - return ExpandComment.parse(this, a, threadID, replyID); - }); - }, - parse: function(req, a, threadID, replyID) { - var bq, clone, href, post, posts, quote, quotes, spoilerRange, _conf, _i, _j, _len, _len1, _ref; - - _conf = Conf; - if (req.status !== 200) { - a.textContent = "" + req.status + " " + req.statusText; - return; - } - posts = JSON.parse(req.response).posts; - if (spoilerRange = posts[0].custom_spoiler) { - Build.spoilerRange[g.BOARD] = spoilerRange; - } - replyID = +replyID; - for (_i = 0, _len = posts.length; _i < _len; _i++) { - post = posts[_i]; - if (post.no === replyID) { - break; - } - } - if (post.no !== replyID) { - a.textContent = 'No.#{replyID} not found.'; - return; - } - bq = $.id("m" + replyID); - clone = bq.cloneNode(false); - clone.innerHTML = post.com; - _ref = quotes = clone.getElementsByClassName('quotelink'); - for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { - quote = _ref[_j]; - href = quote.getAttribute('href'); - if (href[0] === '/') { - continue; - } - quote.href = "res/" + href; - } - post = { - blockquote: clone, - threadID: threadID, - quotes: quotes, - backlinks: [] - }; - ExpandComment.node(post); - $.replace(bq, clone); - return Main.prettify(clone); - } - }; - - ExpandThread = { - init: function() { - var a, span, _i, _len, _ref; - - _ref = $$('.summary'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - span = _ref[_i]; - a = $.el('a', { - textContent: "+ " + span.textContent, - className: 'summary desktop', - href: 'javascript:;' - }); - $.on(a, 'click', function() { - return ExpandThread.toggle(this.parentNode); - }); - $.replace(span, a); - } - }, - toggle: function(thread) { - var a, num, replies, reply, url, _i, _len; - - url = "//api.4chan.org/" + g.BOARD + "/res/" + thread.id.slice(1) + ".json"; - a = $('.summary', thread); - switch (a.textContent[0]) { - case '+': - a.textContent = a.textContent.replace('+', '× Loading...'); - $.cache(url, function() { - return ExpandThread.parse(this, thread, a); - }); - break; - case 'X': - a.textContent = a.textContent.replace('× Loading...', '+'); - $.cache.requests[url].abort(); - break; - case '-': - a.textContent = a.textContent.replace('-', '+'); - num = (function() { - switch (g.BOARD) { - case 'b': - case 'vg': - case 'q': - return 3; - case 't': - return 1; - default: - return 5; - } - })(); - replies = $$('.replyContainer', thread); - replies.splice(replies.length - num, num); - for (_i = 0, _len = replies.length; _i < _len; _i++) { - reply = replies[_i]; - $.rm(reply); - } - } - }, - parse: function(req, thread, a) { - var backlink, frag, id, link, node, nodes, post, posts, replies, reply, spoilerRange, status, threadID, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _results; - - if ((status = req.status) !== 200) { - a.textContent = "" + status + " " + req.statusText; - $.off(a, 'click', ExpandThread.cb.toggle); - return; - } - a.textContent = a.textContent.replace('× Loading...', '-'); - posts = JSON.parse(req.response).posts; - if (spoilerRange = posts[0].custom_spoiler) { - Build.spoilerRange[g.BOARD] = spoilerRange; - } - replies = posts.slice(1); - threadID = thread.id.slice(1); - nodes = []; - for (_i = 0, _len = replies.length; _i < _len; _i++) { - reply = replies[_i]; - post = Build.postFromObject(reply, g.BOARD); - id = reply.no; - link = $('a[title="Highlight this post"]', post); - link.href = "res/" + threadID + "#p" + id; - link.nextSibling.href = "res/" + threadID + "#q" + id; - nodes.push(post); - } - _ref = $$('.summary ~ .replyContainer', a.parentNode); - for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { - post = _ref[_j]; - $.rm(post); - } - _ref1 = $$('.backlink', a.previousElementSibling); - for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { - backlink = _ref1[_k]; - if (!$.id(backlink.hash.slice(1))) { - $.rm(backlink); - } - } - _results = []; - for (_l = 0, _len3 = nodes.length; _l < _len3; _l++) { - node = nodes[_l]; - frag = $.frag(); - $.add(frag, node); - post = Main.preParse(node); - post.threadID = threadID; - Main.node(post); - _results.push($.add(thread, frag)); - } - return _results; - } - }; - - FileInfo = { - init: function() { - if (g.BOARD === 'f') { - return; - } - this.setFormats(); - QuotePreview.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var alt, filename, node, _ref; - - if (!post.fileInfo) { - return; - } - node = post.fileInfo.firstElementChild; - alt = post.img.alt; - filename = ((_ref = $('span', node)) != null ? _ref.title : void 0) || node.title; - FileInfo.data = { - link: post.img.parentNode.href, - spoiler: /^Spoiler/.test(alt), - size: alt.match(/\d+\.?\d*/)[0], - unit: alt.match(/\w+$/)[0], - resolution: node.textContent.match(/\d+x\d+|PDF/)[0], - fullname: filename, - shortname: Build.shortFilename(filename, post.ID === post.threadID) - }; - node.setAttribute('data-filename', filename); - return node.innerHTML = FileInfo.funk(FileInfo); - }, - setFormats: function() { - var code; - - code = Conf['fileInfo'].replace(/%(.)/g, function(s, c) { - if (c in FileInfo.formatters) { - return "' + f.formatters." + c + "() + '"; - } else { - return s; - } - }); - return this.funk = Function('f', "return '" + code + "'"); - }, - convertUnit: function(unitT) { - var i, size, unitF, units; - - size = this.data.size; - unitF = this.data.unit; - if (unitF !== unitT) { - units = ['B', 'KB', 'MB']; - i = units.indexOf(unitF) - units.indexOf(unitT); - if (unitT === 'B') { - unitT = 'Bytes'; - } - if (i > 0) { - while (i-- > 0) { - size *= 1024; - } - } else if (i < 0) { - while (i++ < 0) { - size /= 1024; - } - } - if (size < 1 && size.toString().length > size.toFixed(2).length) { - size = size.toFixed(2); - } - } - return "" + size + " " + unitT; - }, - formatters: { - t: function() { - return FileInfo.data.link.match(/\d+\..+$/)[0]; - }, - T: function() { - return "" + (this.t()) + ""; - }, - l: function() { - return "" + (this.n()) + ""; - }, - L: function() { - return "" + (this.N()) + ""; - }, - n: function() { - if (FileInfo.data.fullname === FileInfo.data.shortname) { - return FileInfo.data.fullname; - } else { - return "" + FileInfo.data.shortname + "" + FileInfo.data.fullname + ""; - } - }, - N: function() { - return FileInfo.data.fullname; - }, - p: function() { - if (FileInfo.data.spoiler) { - return 'Spoiler, '; - } else { - return ''; - } - }, - s: function() { - return "" + FileInfo.data.size + " " + FileInfo.data.unit; - }, - B: function() { - return FileInfo.convertUnit('B'); - }, - K: function() { - return FileInfo.convertUnit('KB'); - }, - M: function() { - return FileInfo.convertUnit('MB'); - }, - r: function() { - return FileInfo.data.resolution; - } - } - }; - - Keybinds = { - init: function() { - var node, _i, _len, _ref; - - this.bindings = this.bind(); - _ref = $$('[accesskey]'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - node = _ref[_i]; - node.removeAttribute('accesskey'); - } - return $.on(d, 'keydown', Keybinds.keydown); - }, - bind: function() { - var keys, _conf; - - _conf = Conf; - keys = {}; - keys[_conf.openQR] = function(thread, target, nodeName) { - return Keybinds.qr(thread, true); - }; - keys[_conf.openEmptyQR] = function(thread, target, nodeName) { - return Keybinds.qr(thread); - }; - keys[_conf.openOptions] = function() { - if (!$.id('overlay')) { - return Options.dialog(); - } - }; - keys[_conf.close] = function() { - var o; - - if (o = $.id('overlay')) { - return Options.close.call(o); - } else if (QR.el) { - return QR.close(); - } - }; - keys[_conf.submit] = function() { - if (QR.el && !QR.status()) { - return QR.submit(); - } - }; - keys[_conf.hideQR] = function(thread, target, nodeName) { - if (QR.el) { - if (QR.el.hidden) { - return QR.el.hidden = false; - } - return QR.autohide.click(); - } else { - return QR.open(); - } - }; - keys[_conf.toggleCatalog] = function() { - return CatalogLinks.toggle(); - }; - keys[_conf.spoiler] = function(thread, target, nodeName) { - if (!(($('[name=spoiler]')) && nodeName === 'textarea')) { - return; - } - return Keybinds.tags('spoiler', target); - }; - keys[_conf.math] = function(thread, target, nodeName) { - if (!(g.BOARD === (!!$('script[src^="//boards.4chan.org/jsMath/"]', d.head)) && nodeName === 'textarea')) { - return; - } - return Keybinds.tags('math', target); - }; - keys[_conf.eqn] = function(thread, target, nodeName) { - if (!(g.BOARD === (!!$('script[src^="//boards.4chan.org/jsMath/"]', d.head)) && nodeName === 'textarea')) { - return; - } - return Keybinds.tags('eqn', target); - }; - keys[_conf.code] = function(thread, target, nodeName) { - if (!(g.BOARD === 'g' && nodeName === 'textarea')) { - return; - } - return Keybinds.tags('code', target); - }; - keys[_conf.sageru] = function() { - $("[name=email]", QR.el).value = "sage"; - return QR.selected.email = "sage"; - }; - keys[_conf.watch] = function(thread, target, nodeName) { - return Watcher.toggle(thread); - }; - keys[_conf.update] = function() { - return Updater.update(); - }; - keys[_conf.unreadCountTo0] = function() { - Unread.replies = []; - return Unread.update(true); - }; - keys[_conf.expandImage] = function(thread, target, nodeName) { - return Keybinds.img(thread); - }; - keys[_conf.expandAllImages] = function(thread, target, nodeName) { - return Keybinds.img(thread, true); - }; - keys[_conf.fappeTyme] = function(thread, target, nodeName) { - return Keybinds.ft(thread); - }; - keys[_conf.zero] = function() { - return window.location = "/" + g.BOARD + "/0#delform"; - }; - keys[_conf.nextPage] = function() { - var form; - - if (form = $('.next form')) { - return window.location = form.action; - } - }; - keys[_conf.previousPage] = function() { - var form; - - if (form = $('.prev form')) { - return window.location = form.action; - } - }; - keys[_conf.nextThread] = function() { - if (g.REPLY) { - return; - } - return Nav.scroll(+1); - }; - keys[_conf.previousThread] = function() { - if (g.REPLY) { - return; - } - return Nav.scroll(-1); - }; - keys[_conf.expandThread] = function(thread, target, nodeName) { - return ExpandThread.toggle(thread); - }; - keys[_conf.openThread] = function(thread, target, nodeName) { - return Keybinds.open(thread); - }; - keys[_conf.openThreadTab] = function(thread, target, nodeName) { - return Keybinds.open(thread, true); - }; - keys[_conf.nextReply] = function(thread, target, nodeName) { - return Keybinds.hl(+1, thread); - }; - keys[_conf.previousReply] = function(thread, target, nodeName) { - return Keybinds.hl(-1, thread); - }; - keys[_conf.hide] = function(thread, target, nodeName) { - if (/\bthread\b/.test(thread.className)) { - return ThreadHiding.toggle(thread); - } - }; - return keys; - }, - keydown: function(e) { - var bind, key, nodeName, target, thread; - - if (!(key = Keybinds.keyCode(e))) { - return; - } - target = e.target; - if ((nodeName = target.nodeName.toLowerCase()) === 'textarea' || nodeName === 'input') { - if (!((key === 'Esc') || (/\+/.test(key)))) { - return; - } - } - thread = Nav.getThread(); - if (!(bind = Keybinds.bindings[key])) { - return; - } - bind(thread, target, nodeName); - return e.preventDefault(); - }, - keyCode: function(e) { - var c, kc, key; - - key = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90].contains(kc = e.keyCode) ? (c = String.fromCharCode(kc), e.shiftKey ? c : c.toLowerCase()) : ((function() { - switch (kc) { - case 8: - return ''; - case 13: - return 'Enter'; - case 27: - return 'Esc'; - case 37: - return 'Left'; - case 38: - return 'Up'; - case 39: - return 'Right'; - case 40: - return 'Down'; - default: - return null; - } - })()); - if (key) { - if (e.altKey) { - key = 'alt+' + key; - } - if (e.ctrlKey) { - key = 'ctrl+' + key; - } - if (e.metaKey) { - key = 'meta+' + key; - } - } - return key; - }, - tags: function(tag, ta) { - var range, selEnd, selStart, value; - - value = ta.value; - selStart = ta.selectionStart; - selEnd = ta.selectionEnd; - ta.value = value.slice(0, selStart) + ("[" + tag + "]") + value.slice(selStart, selEnd) + ("[/" + tag + "]") + value.slice(selEnd); - range = ("[" + tag + "]").length + selEnd; - ta.setSelectionRange(range, range); - return $.event(ta, new Event('input')); - }, - img: function(thread, all) { - var thumb; - - if (all) { - return $.id('imageExpand').click(); - } else { - thumb = $('img[data-md5]', $('.post.highlight', thread) || thread); - return ImageExpand.toggle(thumb.parentNode); - } - }, - ft: function(thread) { - return $('#fappeTyme>input').click(); - }, - qr: function(thread, quote) { - if (quote) { - QR.quote.call($('a[title="Quote this post"]', $('.post.highlight', thread) || thread)); - } else { - QR.open(); - } - return $('textarea', QR.el).focus(); - }, - open: function(thread, tab) { - var id, url; - - if (g.REPLY) { - return; - } - id = thread.id.slice(1); - url = "//boards.4chan.org/" + g.BOARD + "/res/" + id; - if (tab) { - return $.open(url); - } else { - return location.href = url; - } - }, - hl: function(delta, thread) { - var axis, next, post, rect, replies, reply, _i, _len; - - if (post = $('.reply.highlight', thread)) { - $.rmClass(post, 'highlight'); - rect = post.getBoundingClientRect(); - if (rect.bottom >= 0 && rect.top <= d.documentElement.clientHeight) { - axis = delta === +1 ? 'following' : 'preceding'; - next = $.x(axis + '::div[contains(@class,"post reply")][1]', post); - if (!next) { - return; - } - if (!(g.REPLY || $.x('ancestor::div[parent::div[@class="board"]]', next) === thread)) { - return; - } - rect = next.getBoundingClientRect(); - if (rect.top < 0 || rect.bottom > d.documentElement.clientHeight) { - next.scrollIntoView(delta === -1); - } - this.focus(next); - return; - } - } - replies = $$('.reply', thread); - if (delta === -1) { - replies.reverse(); - } - for (_i = 0, _len = replies.length; _i < _len; _i++) { - reply = replies[_i]; - rect = reply.getBoundingClientRect(); - if (delta === +1 && rect.top >= 0 || delta === -1 && rect.bottom <= d.documentElement.clientHeight) { - this.focus(reply); - return; - } - } - }, - focus: function(post) { - $.addClass(post, 'highlight'); - return post.focus(); - } - }; - - Navigation = { - delimiter: "/", - links: [["a", "Anime & Manga", "//boards.4chan.org/a/"], ["b", "Random", "//boards.4chan.org/b/"], ["c", "Cute/Anime", "//boards.4chan.org/c/"], ["d", "Hentai/Alternative", "//boards.4chan.org/d/"], ["e", "Ecchi", "//boards.4chan.org/e/"], ["f", "Flash", "//boards.4chan.org/f/"], ["g", "Technology", "//boards.4chan.org/g/"], ["gif", "Animated Gifs", "//boards.4chan.org/gif/"], ["h", "Hentai", "//boards.4chan.org/h/"], ["hr", "High Resolution", "//boards.4chan.org/hr/"], ["k", "Weapons", "//boards.4chan.org/k/"], ["l", "Lolicon", "http://7chan.org/cake/"], ["m", "Mecha", "//boards.4chan.org/m/"], ["o", "Auto", "//boards.4chan.org/o/"], ["p", "Pictures", "//boards.4chan.org/p/"], ["r", "Requests", "//boards.4chan.org/r/"], ["s", "Sexy Beautiful Women", "//boards.4chan.org/s/"], ["t", "Torrents", "//boards.4chan.org/t/"], ["u", "Yuri", "//boards.4chan.org/u/"], ["v", "Video Games", "//boards.4chan.org/v/"], ["vg", "Video Game Generals", "//boards.4chan.org/vg/"], ["w", "Anime/Wallpapers", "//boards.4chan.org/w/"], ["wg", "Wallpapers/General", "//boards.4chan.org/wg/"], ["i", "Oekaki", "//boards.4chan.org/i/"], ["ic", "Artwork/Critique", "//boards.4chan.org/ic/"], ["r9k", "Robot 9K", "//boards.4chan.org/r9k/"], ["cm", "Cute/Male", "//boards.4chan.org/cm/"], ["hm", "Handsome Men", "//boards.4chan.org/hm/"], ["y", "Yaoi", "//boards.4chan.org/y/"], ["3", "3DCG", "//boards.4chan.org/3/"], ["adv", "Advice", "//boards.4chan.org/adv/"], ["an", "Animals", "//boards.4chan.org/an/"], ["cgl", "Cosplay & EGL", "//boards.4chan.org/cgl/"], ["ck", "Food & Cooking", "//boards.4chan.org/ck/"], ["co", "Comics & Cartoons", "//boards.4chan.org/co/"], ["diy", "Do It Yourself", "//boards.4chan.org/diy/"], ["fa", "Fashion", "//boards.4chan.org/fa/"], ["fit", "Health & Fitness", "//boards.4chan.org/fit/"], ["hc", "Hardcore", "//boards.4chan.org/hc/"], ["int", "International", "//boards.4chan.org/int/"], ["jp", "Otaku Culture", "//boards.4chan.org/jp/"], ["lit", "Literature", "//boards.4chan.org/lit/"], ["mlp", "My Little Pony", "//boards.4chan.org/mlp/"], ["mu", "Music", "//boards.4chan.org/mu/"], ["n", "Transportation", "//boards.4chan.org/n/"], ["po", "Papercraft & Origami", "//boards.4chan.org/po/"], ["pol", "Politically Incorrect", "//boards.4chan.org/pol/"], ["sci", "Science & Math", "//boards.4chan.org/sci/"], ["soc", "Social", "//boards.4chan.org/soc/"], ["sp", "Sports", "//boards.4chan.org/sp/"], ["tg", "Traditional Games", "//boards.4chan.org/tg/"], ["toy", "Toys", "//boards.4chan.org/toys/"], ["trv", "Travel", "//boards.4chan.org/trv/"], ["tv", "Television & Film", "//boards.4chan.org/tv/"], ["vp", "Pokémon", "//boards.4chan.org/vp/"], ["wsg", "Worksafe GIF", "//boards.4chan.org/wsg/"], ["x", "Paranormal", "//boards.4chan.org/x/"], ["rs", "Rapidshares", "http://rs.4chan.org/"], ["status", "4chan Status", "http://status.4chan.org/"], ["q", "4chan Discussion", "//boards.4chan.org/q/"], ["@", "4chan Twitter", "http://www.twitter.com/4chan"]] - }; - - Nav = { - init: function() { - var next, prev, span; - - span = $.el('span', { - id: 'navlinks' - }); - prev = $.el('a', { - href: 'javascript:;' - }); - next = $.el('a', { - href: 'javascript:;' - }); - $.on(prev, 'click', this.prev); - $.on(next, 'click', this.next); - $.add(span, [prev, next]); - return $.add(d.body, span); - }, - prev: function() { - if (g.REPLY) { - return window.scrollTo(0, 0); - } else { - return Nav.scroll(-1); - } - }, - next: function() { - if (g.REPLY) { - return window.scrollTo(0, d.body.scrollHeight); - } else { - return Nav.scroll(+1); - } - }, - getThread: function(full) { - var bottom, i, rect, thread, _i, _len, _ref; - - Nav.threads = $$('.thread:not(.hidden)'); - _ref = Nav.threads; - for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { - thread = _ref[i]; - rect = thread.getBoundingClientRect(); - bottom = rect.bottom; - if (bottom > 0) { - if (full) { - return [thread, i, rect]; - } - return thread; - } - } - return $('.board'); - }, - scroll: function(delta) { - var i, rect, thread, top, _ref, _ref1; - - _ref = Nav.getThread(true), thread = _ref[0], i = _ref[1], rect = _ref[2]; - top = rect.top; - if (!((delta === -1 && Math.ceil(top) < 0) || (delta === +1 && top > 1))) { - i += delta; - } - top = (_ref1 = Nav.threads[i]) != null ? _ref1.getBoundingClientRect().top : void 0; - return window.scrollBy(0, top); - } - }; - - Redirect = { - image: function(board, filename) { - switch (board) { - case 'a': - case 'jp': - case 'm': - case 'q': - case 'sp': - case 'tg': - case 'vg': - case 'wsg': - return "//archive.foolz.us/" + board + "/full_image/" + filename; - case 'cgl': - case 'g': - case 'mu': - case 'w': - return "//rbt.asia/" + board + "/full_image/" + filename; - case 'an': - case 'k': - case 'toy': - case 'x': - return "http://archive.heinessen.com/" + board + "/full_image/" + filename; - case 'ck': - case 'lit': - return "//fuuka.warosu.org/" + board + "/full_image/" + filename; - case 'u': - return "//nsfw.foolz.us/" + board + "/full_image/" + filename; - case 'e': - return "//www.xn--clich-fsa.net/4chan/cgi-board.pl/" + board + "/img/" + filename; - case 'c': - return "//archive.nyafuu.org/" + board + "/full_image/" + filename; - } - }, - post: function(board, postID) { - var archive, name, _base1, _ref; - - if (Redirect.post[board] === void 0) { - _ref = this.archiver; - for (name in _ref) { - archive = _ref[name]; - if (archive.type === 'foolfuuka' && archive.boards.contains(board)) { - Redirect.post[board] = archive.base; - break; - } - } - (_base1 = Redirect.post)[board] || (_base1[board] = null); - } - if (Redirect.post[board]) { - return "" + Redirect.post[board] + "/_/api/chan/post/?board=" + board + "&num=" + postID; - } - return null; - }, - archiver: { - 'Foolz': { - base: '//archive.foolz.us', - boards: ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg', 'dev', 'foolz'], - type: 'foolfuuka' - }, - 'NSFWFoolz': { - base: '//nsfw.foolz.us', - boards: ['u', 'kuku'], - type: 'foolfuuka' - }, - 'TheDarkCave': { - base: 'http://archive.thedarkcave.org', - boards: ['c', 'int', 'out', 'po'], - type: 'foolfuuka' - }, - 'Warosu': { - base: '//fuuka.warosu.org', - boards: ['cgl', 'ck', 'fa', 'jp', 'lit', 'q', 's4s', 'tg', 'vr'], - type: 'fuuka' - }, - 'InstallGentoo': { - base: '//archive.installgentoo.net', - boards: ['diy', 'g', 'sci'], - type: 'fuuka' - }, - 'RebeccaBlackTech': { - base: '//rbt.asia', - boards: ['cgl', 'g', 'mu', 'w'], - type: 'fuuka_mail' - }, - 'Heinessen': { - base: 'http://archive.heinessen.com', - boards: ['an', 'fit', 'k', 'mlp', 'r9k', 'toy', 'x'], - type: 'fuuka' - }, - 'Cliche': { - base: '//www.xn--clich-fsa.net/4chan/cgi-board.pl', - boards: ['e'], - type: 'fuuka' - }, - 'NyaFuu': { - base: '//archive.nyafuu.org', - boards: ['c', 'w'], - type: 'fuuka' - } - }, - select: function(board) { - var archive, name; - - return (function() { - var _ref, _results; - - _ref = this.archiver; - _results = []; - for (name in _ref) { - archive = _ref[name]; - if (archive.boards.contains(board || g.BOARD)) { - _results.push(name); - } - } - return _results; - }).call(this); - }, - to: function(data) { - var archive, board, isSearch, threadID; - - board = data.board, threadID = data.threadID, isSearch = data.isSearch; - return ((archive = this.archiver[$.get("archiver/" + board + "/", this.select(board)[0])]) ? this.path(archive.base, archive.type, data) : threadID && !isSearch ? "//boards.4chan.org/" + board + "/" : null); - }, - path: function(base, archiver, data) { - var board, isSearch, postID, threadID, type, url, value; - - board = data.board, type = data.type, value = data.value, threadID = data.threadID, postID = data.postID, isSearch = data.isSearch; - if (isSearch) { - type = type === 'name' ? 'username' : type === 'md5' ? 'image' : type; - value = encodeURIComponent(value); - return ((url = archiver === 'foolfuuka' ? "search/" + type + "/" : type === 'image' ? "?task=search2&search_media_hash=" : type !== 'email' || archiver === 'fuuka_mail' ? "?task=search2&search_" + type + "=" : false) ? "" + base + "/" + board + "/" + url + value : url); - } - if (postID) { - postID = postID.match(/\d+/)[0]; - } - return base + "/" + board + "/" + (threadID ? "thread/" + threadID : "post/" + postID) + (threadID && postID ? "#" + (archiver === 'InstallGentoo' ? 'p' : '') + postID : ""); - } - }; - - RelativeDates = { - INTERVAL: $.MINUTE, - init: function() { - Main.callbacks.push(this.node); - return $.on(d, 'visibilitychange', this.flush); - }, - node: function(post) { - var dateEl, diff, utc; - - dateEl = $('.postInfo > .dateTime', post.el); - dateEl.title = dateEl.textContent; - utc = dateEl.dataset.utc * 1000; - diff = Date.now() - utc; - dateEl.textContent = RelativeDates.relative(diff); - RelativeDates.setUpdate(dateEl, utc, diff); - return RelativeDates.flush(); - }, - relative: function(diff) { - var number, rounded, unit; - - unit = (number = diff / $.DAY) > 1 ? 'day' : (number = diff / $.HOUR) > 1 ? 'hour' : (number = diff / $.MINUTE) > 1 ? 'minute' : (number = diff / $.SECOND, 'second'); - rounded = Math.round(number); - if (rounded !== 1) { - unit += 's'; - } - return "" + rounded + " " + unit + " ago"; - }, - stale: [], - flush: $.debounce($.SECOND, function() { - var now, update, _i, _len, _ref; - - if (d.hidden) { - return; - } - now = Date.now(); - _ref = RelativeDates.stale; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - update = _ref[_i]; - update(now); - } - RelativeDates.stale = []; - clearTimeout(RelativeDates.timeout); - return RelativeDates.timeout = setTimeout(RelativeDates.flush, RelativeDates.INTERVAL); - }), - setUpdate: function(dateEl, utc, diff) { - var markStale, setOwnTimeout, update; - - setOwnTimeout = function(diff) { - var delay; - - delay = diff < $.MINUTE ? $.SECOND - (diff + $.SECOND / 2) % $.SECOND : diff < $.HOUR ? $.MINUTE - (diff + $.MINUTE / 2) % $.MINUTE : $.HOUR - (diff + $.HOUR / 2) % $.HOUR; - return setTimeout(markStale, delay); - }; - update = function(now) { - if (d.contains(dateEl)) { - diff = now - utc; - dateEl.textContent = RelativeDates.relative(diff); - return setOwnTimeout(diff); - } - }; - markStale = function() { - return RelativeDates.stale.push(update); - }; - return setOwnTimeout(diff); - } - }; - - Time = { - init: function() { - Time.foo(); - QuotePreview.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var node; - - node = $('.postInfo > .dateTime', post.el); - Time.date = new Date(node.dataset.utc * 1000); - return node.textContent = Time.funk(Time); - }, - foo: function() { - var code; - - code = Conf['time'].replace(/%([A-Za-z])/g, function(s, c) { - if (c in Time.formatters) { - return "' + Time.formatters." + c + "() + '"; - } else { - return s; - } - }); - return Time.funk = Function('Time', "return '" + code + "'"); - }, - day: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], - zeroPad: function(n) { - if (n < 10) { - return '0' + n; - } else { - return n; - } - }, - formatters: { - a: function() { - return Time.day[Time.date.getDay()].slice(0, 3); - }, - A: function() { - return Time.day[Time.date.getDay()]; - }, - b: function() { - return Time.month[Time.date.getMonth()].slice(0, 3); - }, - B: function() { - return Time.month[Time.date.getMonth()]; - }, - d: function() { - return Time.zeroPad(Time.date.getDate()); - }, - e: function() { - return Time.date.getDate(); - }, - H: function() { - return Time.zeroPad(Time.date.getHours()); - }, - I: function() { - return Time.zeroPad(Time.date.getHours() % 12 || 12); - }, - k: function() { - return Time.date.getHours(); - }, - l: function() { - return Time.date.getHours() % 12 || 12; - }, - m: function() { - return Time.zeroPad(Time.date.getMonth() + 1); - }, - M: function() { - return Time.zeroPad(Time.date.getMinutes()); - }, - p: function() { - if (Time.date.getHours() < 12) { - return 'AM'; - } else { - return 'PM'; - } - }, - P: function() { - if (Time.date.getHours() < 12) { - return 'am'; - } else { - return 'pm'; - } - }, - S: function() { - return Time.zeroPad(Time.date.getSeconds()); - }, - y: function() { - return Time.date.getFullYear() - 2000; - } - } - }; - - UpdateAlert = { - init: function() { - var dialog, dismiss, overlay; - - if ($.get('updatealert')) { - return; - } - $.set('updatealert', true); - dialog = UpdateAlert.el = $.el('div', { - className: 'updateAlert reply dialog', - innerHTML: '\ - The new 4chan X is out now!
Get it here.
\ -
\ - Dismiss' - }); - overlay = $.el('div', { - id: 'overlay' - }); - dismiss = $('.dismiss', dialog); - $.on(overlay, 'click', function() { - $.rm(overlay); - d.body.style.removeProperty('width'); - return $.rmClass(d.body, 'unscroll'); - }); - $.on(dismiss, 'click', function() { - $.rm(overlay); - d.body.style.removeProperty('width'); - return $.rmClass(d.body, 'unscroll'); - }); - $.add(overlay, dialog); - $.add(d.body, overlay); - d.body.style.setProperty('width', "" + d.body.clientWidth + "px", null); - return $.addClass(d.body, 'unscroll'); - } - }; - - AnnouncementHiding = { - init: function() { - var gmsg, hideButton, hideState; - - if (!(gmsg = $.id('globalMessage'))) { - return; - } - hideState = $.get('hidegMessage', {}); - hideButton = $.el('a', { - id: 'toggleMsgButton', - className: "redButton", - textContent: "" + (hideState.hidden ? 'View Important Announcement' : 'Close Announcement'), - href: "javascript:;" - }); - $.before(gmsg, hideButton); - $.on(hideButton, 'click', function() { - $.toggleClass(gmsg, 'hidden'); - if (hideState.hidden) { - this.textContent = 'Close Announcement'; - hideState.hidden = false; - delete hideState.gmsg; - } else { - this.textContent = 'View Important Announcement'; - hideState.hidden = true; - hideState.gmsg = gmsg.textContent; - } - return $.set('hidegMessage', hideState); - }); - if (hideState.hidden) { - $.toggleClass(gmsg, 'hidden'); - if (gmsg.textContent !== hideState.gmsg) { - return hideButton.click(); - } - } - } - }; - - Anonymize = { - init: function() { - QuotePreview.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var name, parent, trip; - - name = $('.postInfo .name', post.el); - name.textContent = 'Anonymous'; - if ((trip = name.nextElementSibling) && trip.className === 'postertrip') { - $.rm(trip); - } - if ((parent = name.parentNode).className === 'useremail' && !/^mailto:sage$/i.test(parent.href)) { - return $.replace(parent, name); - } - } - }; - - Filter = { - filters: {}, - init: function() { - var boards, err, filter, hl, key, op, regexp, stub, top, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4; - - for (key in Config.filter) { - this.filters[key] = []; - _ref = Conf[key].split('\n'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - filter = _ref[_i]; - if (filter[0] === '#') { - continue; - } - if (!(regexp = filter.match(/\/(.+)\/(\w*)/))) { - continue; - } - filter = filter.replace(regexp[0], ''); - boards = ((_ref1 = filter.match(/boards:([^;]+)/)) != null ? _ref1[1].toLowerCase() : void 0) || 'global'; - if (!(boards === 'global' || boards.split(',').contains(g.BOARD))) { - continue; - } - if (key === 'md5') { - regexp = regexp[1]; - } else { - try { - regexp = RegExp(regexp[1], regexp[2]); - } catch (_error) { - err = _error; - alert(err.message); - continue; - } - } - op = ((_ref2 = filter.match(/[^t]op:(yes|no|only)/)) != null ? _ref2[1] : void 0) || 'no'; - stub = (function() { - var _ref3; - - switch ((_ref3 = filter.match(/stub:(yes|no)/)) != null ? _ref3[1] : void 0) { - case 'yes': - return true; - case 'no': - return false; - default: - return Conf['Show Stubs']; - } - })(); - if (hl = /highlight/.test(filter)) { - hl = ((_ref3 = filter.match(/highlight:(\w+)/)) != null ? _ref3[1] : void 0) || 'filter_highlight'; - top = ((_ref4 = filter.match(/top:(yes|no)/)) != null ? _ref4[1] : void 0) || 'yes'; - top = top === 'yes'; - } - this.filters[key].push(this.createFilter(regexp, op, stub, hl, top)); - } - if (!this.filters[key].length) { - delete this.filters[key]; - } - } - if (Object.keys(this.filters).length) { - return Main.callbacks.push(this.node); - } - }, - createFilter: function(regexp, op, stub, hl, top) { - var settings, test; - - test = typeof regexp === 'string' ? function(value) { - return regexp === value; - } : function(value) { - return regexp.test(value); - }; - settings = { - hide: !hl, - stub: stub, - "class": hl, - top: top - }; - return function(value, isOP) { - if (isOP && op === 'no' || !isOP && op === 'only') { - return false; - } - if (!test(value)) { - return false; - } - return settings; - }; - }, - node: function(post) { - var filter, isOP, key, result, root, value, _i, _len, _ref; - - if (post.isInlined) { - return; - } - isOP = post.ID === post.threadID; - root = post.root; - for (key in Filter.filters) { - value = Filter[key](post); - if (value === false) { - continue; - } - _ref = Filter.filters[key]; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - filter = _ref[_i]; - if (!(result = filter(value, isOP))) { - continue; - } - if (result.hide) { - if (isOP) { - if (!g.REPLY) { - ThreadHiding.hide(root.parentNode, result.stub); - } else { - continue; - } - } else { - ReplyHiding.hide(post.root, result.stub); - } - return; - } - $.addClass(root, result["class"]); - } - } - }, - name: function(post) { - return $('.name', post.el).textContent; - }, - uniqueid: function(post) { - var uid; - - if (uid = $('.posteruid', post.el)) { - return uid.textContent.slice(5, -1); - } - return false; - }, - tripcode: function(post) { - var trip; - - if (trip = $('.postertrip', post.el)) { - return trip.textContent; - } - return false; - }, - mod: function(post) { - var mod; - - if (mod = $('.capcode', post.el)) { - return mod.textContent; - } - return false; - }, - email: function(post) { - var mail; - - if (mail = $('.useremail', post.el)) { - return decodeURIComponent(mail.href.slice(7)); - } - return false; - }, - subject: function(post) { - var subject; - - if ((subject = $('.postInfo .subject', post.el)).textContent.length !== 0) { - return subject.textContent; - } - return false; - }, - comment: function(post) { - var content, data, i, nodes, text, _i, _ref; - - text = []; - nodes = d.evaluate('.//br|.//text()', post.blockquote, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - for (i = _i = 0, _ref = nodes.snapshotLength; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { - text.push((data = nodes.snapshotItem(i).data) ? data : '\n'); - } - if ((content = text.join('')).length !== 0) { - return content; - } - return false; - }, - country: function(post) { - var flag; - - if (flag = $('.countryFlag', post.el)) { - return flag.title; - } - return false; - }, - filename: function(post) { - var file, fileInfo; - - fileInfo = post.fileInfo; - if (fileInfo) { - if (file = $('.fileText > span', fileInfo)) { - return file.title; - } else { - return fileInfo.firstElementChild.dataset.filename; - } - } - return false; - }, - dimensions: function(post) { - var fileInfo, match; - - fileInfo = post.fileInfo; - if (fileInfo && (match = fileInfo.textContent.match(/\d+x\d+/))) { - return match[0]; - } - return false; - }, - filesize: function(post) { - var img; - - img = post.img; - if (img) { - return img.alt.replace('Spoiler Image, ', ''); - } - return false; - }, - md5: function(post) { - var img; - - img = post.img; - if (img) { - return img.dataset.md5; - } - return false; - }, - menuInit: function() { - var div, entry, type, _i, _len, _ref; - - div = $.el('div', { - textContent: 'Filter' - }); - entry = { - el: div, - open: function() { - return true; - }, - children: [] - }; - _ref = [['Name', 'name'], ['Unique ID', 'uniqueid'], ['Tripcode', 'tripcode'], ['Admin/Mod', 'mod'], ['E-mail', 'email'], ['Subject', 'subject'], ['Comment', 'comment'], ['Country', 'country'], ['Filename', 'filename'], ['Image dimensions', 'dimensions'], ['Filesize', 'filesize'], ['Image MD5', 'md5']]; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - type = _ref[_i]; - entry.children.push(this.createSubEntry(type[0], type[1])); - } - return Menu.addEntry(entry); - }, - createSubEntry: function(text, type) { - var el, onclick, open; - - el = $.el('a', { - href: 'javascript:;', - textContent: text - }); - onclick = null; - open = function(post) { - var value; - - value = Filter[type](post); - if (value === false) { - return false; - } - $.off(el, 'click', onclick); - onclick = function() { - var re, save, select, ta, tl; - - re = type === 'md5' ? value : value.replace(/\/|\\|\^|\$|\n|\.|\(|\)|\{|\}|\[|\]|\?|\*|\+|\|/g, function(c) { - if (c === '\n') { - return '\\n'; - } else if (c === '\\') { - return '\\\\'; - } else { - return "\\" + c; - } - }); - re = type === 'md5' ? "/" + value + "/" : "/^" + re + "$/"; - if (/\bop\b/.test(post["class"])) { - re += ';op:yes'; - } - save = (save = $.get(type, '')) ? "" + save + "\n" + re : re; - $.set(type, save); - Options.dialog(); - select = $('select[name=filter]', $.id('options')); - select.value = type; - $.event(select, new Event('change')); - $.id('filter_tab').checked = true; - ta = select.nextElementSibling; - tl = ta.textLength; - ta.setSelectionRange(tl, tl); - return ta.focus(); - }; - $.on(el, 'click', onclick); - return true; - }; - return { - el: el, - open: open - }; - } - }; - - ReplyHiding = { - init: function() { - return Main.callbacks.push(this.node); - }, - node: function(post) { - var side; - - if (post.isInlined || post.ID === post.threadID) { - return; - } - side = $('.sideArrows', post.root); - side.innerHTML = '[ - ]'; - $.on(side.firstChild, 'click', function() { - var button, id, root; - - return ReplyHiding.toggle(button = this.parentNode, root = button.parentNode, id = root.id.slice(2)); - }); - if (post.ID in g.hiddenReplies) { - return ReplyHiding.hide(post.root); - } - }, - toggle: function(button, root, id) { - var quote, quotes, _i, _j, _len, _len1; - - quotes = $$(".quotelink[href$='#p" + id + "'], .backlink[href$='#p" + id + "']"); - if (/\bstub\b/.test(button.className)) { - ReplyHiding.show(root); - for (_i = 0, _len = quotes.length; _i < _len; _i++) { - quote = quotes[_i]; - $.rmClass(quote, 'filtered'); - } - delete g.hiddenReplies[id]; - } else { - ReplyHiding.hide(root); - for (_j = 0, _len1 = quotes.length; _j < _len1; _j++) { - quote = quotes[_j]; - $.addClass(quote, 'filtered'); - } - g.hiddenReplies[id] = Date.now(); - } - return $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); - }, - hide: function(root) { - var a, id, menuButton, post, stub; - - post = $('.post', root); - if (post.hidden) { - return; - } - post.hidden = true; - $.addClass(root, 'hidden'); - if (!Conf['Show Stubs']) { - return; - } - stub = $.el('div', { - className: 'stub', - innerHTML: "[ + ] " + (Conf['Anonymize'] ? 'Anonymous' : $('.desktop > .nameBlock', root).textContent) + " " - }); - a = stub.firstChild; - $.on(a, 'click', function() { - var button; - - return ReplyHiding.toggle(button = this.parentNode, root = $.id("pc" + this.id.slice(4)), id); - }); - if (Conf['Menu']) { - menuButton = Menu.a.cloneNode(true); - $.on(menuButton, 'click', Menu.toggle); - $.add(stub, [$.tn(' '), menuButton]); - } - return $.prepend(root, stub); - }, - show: function(root) { - var post, stub; - - if ((stub = $('.stub', root))) { - $.rm(stub); - } - post = $('.post', root); - post.hidden = false; - return $.rmClass(root, 'hidden'); - }, - unhide: function(post) { - if (post.el.hidden) { - return ReplyHiding.show(post.root); - } - } - }; - - StrikethroughQuotes = { - init: function() { - return Main.callbacks.push(this.node); - }, - node: function(post) { - var el, quote, _i, _len, _ref; - - if (post.isInlined) { - return; - } - _ref = post.quotes; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - if (!(quote.hash && (el = $.id("p" + quote.hash.slice(2))) && quote.hostname === 'boards.4chan.org' && !/catalog$/.test(quote.pathname) && el.hidden)) { - continue; - } - $.addClass(quote, 'filtered'); - if (Conf['Recursive Filtering'] && post.ID !== post.threadID) { - ReplyHiding.hide(post.root); - } - } - } - }; - - ThreadHiding = { - init: function() { - var a, thread, _i, _len, _ref; - - this.hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); - ThreadHiding.sync(); - if (g.CATALOG) { - return; - } - _ref = $$('.thread'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - thread = _ref[_i]; - a = $.el('a', { - className: 'hide_thread_button', - innerHTML: '[ - ]', - href: 'javascript:;' - }); - $.on(a, 'click', function() { - return ThreadHiding.toggle($.x('ancestor::div[@class="thread"][1]', this)); - }); - $.add($('.op .postInfo', thread), a); - if (thread.id.slice(1) in this.hiddenThreads) { - ThreadHiding.hide(thread); - } - } - }, - sync: function() { - var hiddenThreadsCatalog, id; - - hiddenThreadsCatalog = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; - if (g.CATALOG) { - for (id in this.hiddenThreads) { - hiddenThreadsCatalog[id] = true; - } - return localStorage.setItem("4chan-hide-t-" + g.BOARD, JSON.stringify(hiddenThreadsCatalog)); - } else { - for (id in hiddenThreadsCatalog) { - if (!(id in this.hiddenThreads)) { - this.hiddenThreads[id] = Date.now(); - } - } - return $.set("hiddenThreads/" + g.BOARD + "/", this.hiddenThreads); - } - }, - toggle: function(thread) { - var id; - - id = thread.id.slice(1); - if (thread.hidden || /\bhidden_thread\b/.test(thread.firstChild.className)) { - ThreadHiding.show(thread); - delete ThreadHiding.hiddenThreads[id]; - } else { - ThreadHiding.hide(thread); - ThreadHiding.hiddenThreads[id] = Date.now(); - } - return $.set("hiddenThreads/" + g.BOARD + "/", ThreadHiding.hiddenThreads); - }, - hide: function(thread) { - var menuButton, num, opInfo, span, stub, text; - - if (!Conf['Show Stubs']) { - thread.hidden = true; - thread.nextElementSibling.hidden = true; - return; - } - if (/\bhidden_thread\b/.test(thread.firstChild.className)) { - return; - } - num = 0; - if (span = $('.summary', thread)) { - num = Number(span.textContent.match(/\d+/)); - } - num += $$('.opContainer ~ .replyContainer', thread).length; - text = num === 1 ? '1 reply' : "" + num + " replies"; - opInfo = $('.desktop > .nameBlock', thread).textContent; - stub = $.el('a', { - className: 'hidden_thread', - innerHTML: '[ + ]', - href: 'javascript:;' - }); - $.on(stub, 'click', function() { - return ThreadHiding.toggle(this.parentElement); - }); - $.add(stub, $.tn("" + opInfo + " (" + text + ")")); - if (Conf['Menu']) { - menuButton = Menu.a.cloneNode(true); - $.on(menuButton, 'click', Menu.toggle); - $.add(stub, [$.tn(' '), menuButton]); - } - return $.prepend(thread, stub); - }, - show: function(thread) { - var stub; - - if (stub = $('.hidden_thread', thread)) { - $.rm(stub); - } - thread.hidden = false; - return thread.nextElementSibling.hidden = false; - } - }; - - FappeTyme = { - init: function() { - var controls, el; - - if (g.CATALOG || g.BOARD === 'f') { - return; - } - if (!$.id('imgControls')) { - controls = $.el('div', { - id: 'imgControls', - innerHTML: "
" - }); - $.prepend($.id('delform'), controls); - } - el = $.el('label', { - href: 'javascript:;', - id: 'fappeTyme', - title: 'Fappe Tyme', - innerHTML: 'Fappe Tyme' - }); - $.add($.id('imgContainer'), el); - $.on($('input', el), 'click', FappeTyme.toggle); - return Main.callbacks.push(this.node); - }, - node: function(post) { - if (post.img) { - return; - } - return post.el.parentElement.classList.add("noFile"); - }, - toggle: function() { - return $.toggleClass(d.body, 'fappeTyme'); - } - }; - - ImageExpand = { - init: function() { - if (g.BOARD === 'f') { - return; - } - QuoteInline.callbacks.push(this.node); - Main.callbacks.push(this.node); - return this.dialog(); - }, - node: function(post) { - var a; - - if (!post.img || post.hasPDF) { - return; - } - a = post.img.parentNode; - $.on(a, 'click', ImageExpand.cb.toggle); - if (Conf['Don\'t Expand Spoilers'] && !Conf['Reveal Spoilers'] && /^spoiler\ image/i.test(a.firstChild.alt)) { - return; - } - if (ImageExpand.on && !post.el.hidden) { - return ImageExpand.expand(post.img); - } - }, - cb: { - toggle: function(e) { - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button) { - return; - } - e.preventDefault(); - return ImageExpand.toggle(this); - }, - all: function() { - var i, thumb, thumbs, _i, _j, _k, _len, _len1, _len2, _ref; - - ImageExpand.on = this.checked; - if (ImageExpand.on) { - thumbs = $$('img[data-md5]'); - if (Conf['Expand From Current']) { - for (i = _i = 0, _len = thumbs.length; _i < _len; i = ++_i) { - thumb = thumbs[i]; - if (thumb.getBoundingClientRect().top > 0) { - break; - } - } - thumbs = thumbs.slice(i); - } - for (_j = 0, _len1 = thumbs.length; _j < _len1; _j++) { - thumb = thumbs[_j]; - if (Conf['Don\'t Expand Spoilers'] && !Conf['Reveal Spoilers'] && /^spoiler\ image/i.test(thumb.alt)) { - continue; - } - ImageExpand.expand(thumb); - } - } else { - _ref = $$('img[data-md5][hidden]'); - for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) { - thumb = _ref[_k]; - ImageExpand.contract(thumb); - } - } - }, - typeChange: function() { - var klass; - - klass = (function() { - switch (this.value) { - case 'full': - return ''; - case 'fit width': - return 'fitwidth'; - case 'fit height': - return 'fitheight'; - case 'fit screen': - return 'fitwidth fitheight'; - } - }).call(this); - $.id('delform').className = klass; - if (/\bfitheight\b/.test(klass)) { - $.on(window, 'resize', ImageExpand.resize); - if (!ImageExpand.style) { - ImageExpand.style = $.addStyle(''); - } - return ImageExpand.resize(); - } else if (ImageExpand.style) { - return $.off(window, 'resize', ImageExpand.resize); - } - } - }, - toggle: function(a) { - var rect, thumb; - - thumb = a.firstChild; - if (thumb.hidden) { - rect = a.getBoundingClientRect(); - if (rect.bottom > 0) { - if ($.engine === 'webkit') { - if (rect.top < 0) { - d.body.scrollTop += rect.top - 42; - } - if (rect.left < 0) { - d.body.scrollLeft += rect.left; - } - } else { - if (rect.top < 0) { - d.documentElement.scrollTop += rect.top - 42; - } - if (rect.left < 0) { - d.documentElement.scrollLeft += rect.left; - } - } - } - return ImageExpand.contract(thumb); - } else { - return ImageExpand.expand(thumb); - } - }, - contract: function(thumb) { - thumb.hidden = false; - thumb.nextSibling.hidden = true; - return $.rmClass(thumb.parentNode.parentNode.parentNode.parentNode, 'image_expanded'); - }, - expand: function(thumb, src) { - var a, img; - - if ($.x('ancestor-or-self::*[@hidden]', thumb)) { - return; - } - a = thumb.parentNode; - src || (src = a.href); - if (/\.pdf$/.test(src)) { - return; - } - thumb.hidden = true; - $.addClass(thumb.parentNode.parentNode.parentNode.parentNode, 'image_expanded'); - if ((img = thumb.nextSibling) && img.tagName.toLowerCase() === 'img') { - img.hidden = false; - return; - } - img = $.el('img', { - src: src, - className: 'fullSize' - }); - $.on(img, 'error', ImageExpand.error); - return $.after(thumb, img); - }, - error: function() { - var src, thumb, timeoutID, url; - - thumb = this.previousSibling; - ImageExpand.contract(thumb); - $.rm(this); - src = this.src.split('/'); - if (!(src[2] === 'images.4chan.org' && (url = Redirect.image(src[3], src[5])))) { - if (g.dead) { - return; - } - url = "//images.4chan.org/" + src[3] + "/src/" + src[5]; - } - if ($.engine !== 'webkit' && url.split('/')[2] === 'images.4chan.org') { - return; - } - timeoutID = setTimeout(ImageExpand.expand, 10000, thumb, url); - if ($.engine !== 'webkit' || url.split('/')[2] !== 'images.4chan.org') { - return; - } - return $.ajax(url, { - onreadystatechange: (function() { - if (this.status === 404) { - return clearTimeout(timeoutID); - } - }) - }, { - type: 'head' - }); - }, - dialog: function() { - var controls, imageType, select; - - controls = $.el('div', { - id: 'imgControls', - innerHTML: "
" - }); - imageType = $.get('imageType', 'full'); - select = $('select', controls); - select.value = imageType; - ImageExpand.cb.typeChange.call(select); - $.on(select, 'change', $.cb.value); - $.on(select, 'change', ImageExpand.cb.typeChange); - $.on($('input', controls), 'click', ImageExpand.cb.all); - return $.prepend($.id('delform'), controls); - }, - resize: function() { - return ImageExpand.style.textContent = ".fitheight img[data-md5] + img {max-height:" + d.documentElement.clientHeight + "px;}"; - } - }; - - ImageHover = { - init: function() { - QuoteInline.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - if (!post.img || post.hasPDF) { - return; - } - return $.on(post.img, 'mouseover', ImageHover.mouseover); - }, - mouseover: function() { - var el; - - if (el = $.id('ihover')) { - if (el === UI.el) { - delete UI.el; - } - $.rm(el); - } - if (UI.el) { - return; - } - el = UI.el = $.el('img', { - id: 'ihover', - src: this.parentNode.href - }); - $.add(d.body, el); - $.on(el, 'load', ImageHover.load); - $.on(el, 'error', ImageHover.error); - $.on(this, 'mousemove', UI.hover); - return $.on(this, 'mouseout', ImageHover.mouseout); - }, - load: function() { - var style; - - if (!this.parentNode) { - return; - } - style = this.style; - return UI.hover({ - clientX: -45 + parseInt(style.left), - clientY: 120 + parseInt(style.top) - }); - }, - error: function() { - var src, timeoutID, url, - _this = this; - - src = this.src.split('/'); - if (!(src[2] === 'images.4chan.org' && (url = Redirect.image(src[3], src[5])))) { - if (g.dead) { - return; - } - url = "//images.4chan.org/" + src[3] + "/src/" + src[5]; - } - if ($.engine !== 'webkit' && url.split('/')[2] === 'images.4chan.org') { - return; - } - timeoutID = setTimeout((function() { - return _this.src = url; - }), 3000); - if ($.engine !== 'webkit' || url.split('/')[2] !== 'images.4chan.org') { - return; - } - return $.ajax(url, { - onreadystatechange: (function() { - if (this.status === 404) { - return clearTimeout(timeoutID); - } - }) - }, { - type: 'head' - }); - }, - mouseout: function() { - UI.hoverend(); - $.off(this, 'mousemove', UI.hover); - return $.off(this, 'mouseout', ImageHover.mouseout); - } - }; - - ImageReplace = { - init: function() { - if (g.BOARD === 'f') { - return; - } - QuoteInline.callbacks.push(this.node); - QuotePreview.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var el, href, img, type; - - img = post.img; - if (post.el.hidden || !img || /spoiler/.test(img.src)) { - return; - } - if (Conf["Replace " + ((type = ((href = img.parentNode.href).match(/\w{3}$/))[0].toUpperCase()) === 'PEG' ? 'JPG' : type)]) { - el = $.el('img'); - el.setAttribute('data-id', post.ID); - $.on(el, 'load', function() { - return img.src = el.src; - }); - return el.src = href; - } - } - }; - - Prefetch = { - init: function() { - if (g.BOARD === 'f') { - return; - } - return this.dialog(); - }, - dialog: function() { - var controls, first, input; - - controls = $.el('label', { - id: 'prefetch', - innerHTML: "Prefetch Images" - }); - input = $('input', controls); - $.on(input, 'change', Prefetch.change); - first = $.id('delform').firstElementChild; - if (first.id === 'imgControls') { - return $.after(first, controls); - } else { - return $.before(first, controls); - } - }, - change: function() { - var thumb, _i, _len, _ref; - - $.off(this, 'change', Prefetch.change); - _ref = $$('a.fileThumb'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - thumb = _ref[_i]; - $.el('img', { - src: thumb.href - }); - } - return Main.callbacks.push(Prefetch.node); - }, - node: function(post) { - var img; - - img = post.img; - if (post.el.hidden || !img) { - return; - } - return $.el('img', { - src: img.parentNode.href - }); - } - }; - - RevealSpoilers = { - init: function() { - QuotePreview.callbacks.push(this.node); - ExpandComment.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var img, s; - - img = post.img; - if (!(img && /^Spoiler/.test(img.alt)) || post.isArchived) { - return; - } - img.removeAttribute('style'); - s = img.style; - s.maxHeight = s.maxWidth = /\bop\b/.test(post["class"]) ? '250px' : '125px'; - return img.src = "//thumbs.4chan.org" + (img.parentNode.pathname.replace(/src(\/\d+).+$/, 'thumb$1s.jpg')); - } - }; - - Sauce = { - init: function() { - var link, _i, _len, _ref; - - if (g.BOARD === 'f') { - return; - } - this.links = []; - _ref = Conf['sauces'].split('\n'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link[0] === '#') { - continue; - } - this.links.push(this.createSauceLink(link.trim())); - } - if (!this.links.length) { - return; - } - return Main.callbacks.push(this.node); - }, - createSauceLink: function(link) { - var domain, el, href, m; - - link = link.replace(/(\$\d)/g, function(parameter) { - switch (parameter) { - case '$1': - return "' + (isArchived ? img.firstChild.src : 'http://thumbs.4chan.org' + img.pathname.replace(/src(\\/\\d+).+$/, 'thumb$1s.jpg')) + '"; - case '$2': - return "' + img.href + '"; - case '$3': - return "' + encodeURIComponent(img.firstChild.dataset.md5) + '"; - case '$4': - return g.BOARD; - default: - return parameter; - } - }); - domain = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; - href = link.replace(/;text:.+$/, ''); - href = Function('img', 'isArchived', "return '" + href + "'"); - el = $.el('a', { - target: '_blank', - textContent: domain - }); - return function(img, isArchived) { - var a; - - a = el.cloneNode(true); - a.href = href(img, isArchived); - return a; - }; - }, - node: function(post) { - var img, link, nodes, _i, _len, _ref; - - img = post.img; - if (!img) { - return; - } - img = img.parentNode; - nodes = []; - _ref = Sauce.links; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - nodes.push($.tn('\u00A0'), link(img, post.isArchived)); - } - return $.add(post.fileInfo, nodes); - } - }; - - Linkify = { - init: function() { - if (Conf['Embedding']) { - QuoteInline.callbacks.push(function(post) { - var embed, _i, _len, _ref; - - _ref = $$('.embed', post.blockquote); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - embed = _ref[_i]; - $.on(embed, 'click', Linkify.toggle); - } - }); - } - QuotePreview.callbacks.push(this.node); - ExpandComment.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - regString: /(\b([a-z]+:\/\/|[a-z]{3,}\.[-a-z0-9]+\.[a-z]+|[-a-z0-9]+\.[a-z]{2,4}|[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-z]{3,}:[a-z0-9?]|[a-z0-9._%+-:]+@[a-z0-9.-]+\.[a-z0-9])[^\s'"]+)/gi, - cypher: $.el('div'), - node: function(post) { - var a, child, cypher, cypherText, data, i, index, len, link, links, lookahead, name, next, node, nodes, snapshot, spoiler, text, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _results; - - snapshot = $.X('.//text()', post.blockquote); - cypher = Linkify.cypher; - i = -1; - len = snapshot.snapshotLength; - _results = []; - while (++i < len) { - nodes = $.frag(); - node = snapshot.snapshotItem(i); - data = node.data; - if (!(node.parentNode && Linkify.regString.test(data))) { - continue; - } - Linkify.regString.lastIndex = 0; - cypherText = []; - if (next = node.nextSibling) { - cypher.textContent = node.textContent; - cypherText[0] = cypher.innerHTML; - while ((next.nodeName.toLowerCase() === 'wbr' || next.nodeName.toLowerCase() === 's') && (lookahead = next.nextSibling) && ((name = lookahead.nodeName) === "#text" || name.toLowerCase() === 'br')) { - cypher.textContent = lookahead.textContent; - cypherText.push((spoiler = next.innerHTML) ? "" + (spoiler.replace(/" : ''); - cypherText.push(cypher.innerHTML); - $.rm(next); - next = lookahead.nextSibling; - if (lookahead.nodeName === "#text") { - $.rm(lookahead); - } - if (!next) { - break; - } - } - } - if (cypherText.length) { - data = cypherText.join(''); - } - links = data.match(Linkify.regString); - for (_i = 0, _len = links.length; _i < _len; _i++) { - link = links[_i]; - index = data.indexOf(link); - if (text = data.slice(0, index)) { - cypher.innerHTML = text; - _ref = __slice.call(cypher.childNodes); - for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { - child = _ref[_j]; - $.add(nodes, child); - } - } - cypher.innerHTML = (link.indexOf(':') < 0 ? (link.indexOf('@') > 0 ? 'mailto:' + link : 'http://' + link) : link).replace(/<(wbr|s|\/s)>/g, ''); - a = $.el('a', { - innerHTML: link, - className: 'linkify', - rel: 'nofollow noreferrer', - target: '_blank', - href: cypher.textContent - }); - $.add(nodes, Linkify.embedder(a)); - data = data.slice(index + link.length); - } - if (data) { - cypher.innerHTML = data; - _ref1 = __slice.call(cypher.childNodes); - for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { - child = _ref1[_k]; - $.add(nodes, child); - } - } - _results.push($.replace(node, nodes)); - } - return _results; - }, - toggle: function() { - var el, embed, style, type, url; - - embed = this.previousElementSibling; - if (this.className.contains("embedded")) { - el = $.el('a', { - rel: 'nofollow noreferrer', - target: 'blank', - className: 'linkify', - href: url = this.getAttribute("data-originalURL"), - textContent: this.getAttribute("data-title") || url - }); - this.textContent = '(embed)'; - } else { - el = (type = Linkify.types[this.getAttribute("data-service")]).el.call(this); - el.style.cssText = (style = type.style) ? style : "border: 0; width: " + ($.get('embedWidth', Config['embedWidth'])) + "px; height: " + ($.get('embedHeight', Config['embedHeight'])) + "px"; - this.textContent = '(unembed)'; - } - $.replace(embed, el); - return $.toggleClass(this, 'embedded'); - }, - types: { - YouTube: { - regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*).*/, - el: function() { - return $.el('iframe', { - src: "//www.youtube.com/embed/" + this.name - }); - }, - title: { - api: function() { - return "https://gdata.youtube.com/feeds/api/videos/" + this.name + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode"; - }, - text: function() { - return JSON.parse(this.responseText).entry.title.$t; - } - } - }, - Vocaroo: { - regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/, - style: 'border: 0; width: 150px; height: 45px;', - el: function() { - return $.el('object', { - innerHTML: "" - }); - } - }, - Vimeo: { - regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/, - el: function() { - return $.el('iframe', { - src: "//player.vimeo.com/video/" + this.name - }); - }, - title: { - api: function() { - return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + this.name; - }, - text: function() { - return JSON.parse(this.responseText).title; - } - } - }, - LiveLeak: { - regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/, - el: function() { - return $.el('iframe', { - src: "http://www.liveleak.com/e/" + this.name + "?autostart=true" - }); - } - }, - audio: { - regExp: /(.*\.(mp3|ogg|wav))$/, - el: function() { - return $.el('audio', { - controls: 'controls', - preload: 'auto', - src: this.name - }); - } - }, - SoundCloud: { - regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/, - style: 'height: auto; width: 500px; display: inline-block;', - el: function() { - var div; - - div = $.el('div', { - className: "soundcloud", - name: "soundcloud" - }); - $.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=" + (this.getAttribute('data-originalURL')) + "&color=" + (Style.colorToHex(Themes[Conf['theme']]['Background Color'])), { - div: div, - onloadend: function() { - return this.div.innerHTML = JSON.parse(this.responseText).html; - } - }, false); - return div; - } - }, - pastebin: { - regExp: /.*(?:pastebin.com\/)([^#\&\?]*).*/, - el: function() { - var div; - - return div = $.el('iframe', { - src: "http://pastebin.com/embed_iframe.php?i=" + this.name - }); - } - } - }, - embedder: function(a) { - var callbacks, embed, err, key, match, service, title, titles, type, _ref; - - if (!Conf['Embedding']) { - return [a]; - } - callbacks = function() { - var title; - - return a.textContent = (function() { - switch (this.status) { - case 200: - case 304: - title = "[" + (embed.getAttribute('data-service')) + "] " + (service.text.call(this)); - embed.setAttribute('data-title', title); - titles[embed.name] = [title, Date.now()]; - $.set('CachedTitles', titles); - return title; - case 404: - return "[" + key + "] Not Found"; - case 403: - return "[" + key + "] Forbidden or Private"; - default: - return "[" + key + "] " + this.status + "'d"; - } - }).call(this); - }; - _ref = Linkify.types; - for (key in _ref) { - type = _ref[key]; - if (!(match = a.href.match(type.regExp))) { - continue; - } - embed = $.el('a', { - name: (a.name = match[1]), - className: 'embedlink', - href: 'javascript:;', - textContent: '(embed)' - }); - embed.setAttribute('data-service', key); - embed.setAttribute('data-originalURL', a.href); - $.on(embed, 'click', Linkify.toggle); - if (Conf['Link Title'] && (service = type.title)) { - titles = $.get('CachedTitles', {}); - if (title = titles[match[1]]) { - a.textContent = title[0]; - embed.setAttribute('data-title', title[0]); - } else { - try { - $.cache(service.api.call(a), callbacks); - } catch (_error) { - err = _error; - a.innerHTML = "[" + key + "] Title Link Blocked (are you using NoScript?)"; - } - } - } - return [a, $.tn(' '), embed]; - } - return [a]; - } - }; - - ArchiveLink = { - init: function() { - var div, entry, key, type, _ref; - - div = $.el('div', { - textContent: 'Archive' - }); - entry = { - el: div, - open: function(post) { - var path; - - path = $('a[title="Highlight this post"]', post.el).pathname.split('/'); - if ((Redirect.to({ - board: path[1], - threadID: path[3], - postID: post.ID - })) === ("//boards.4chan.org/" + path[1] + "/")) { - return false; - } - post.info = [path[1], path[3]]; - return true; - }, - children: [] - }; - _ref = { - Post: 'apost', - Name: 'name', - Tripcode: 'tripcode', - 'E-mail': 'email', - Subject: 'subject', - Filename: 'filename', - 'Image MD5': 'md5' - }; - for (key in _ref) { - type = _ref[key]; - entry.children.push(this.createSubEntry(key, type)); - } - return Menu.addEntry(entry); - }, - createSubEntry: function(text, type) { - var el, open; - - el = $.el('a', { - textContent: text, - target: '_blank' - }); - open = function(post) { - var value; - - if (type === 'apost') { - el.href = Redirect.to({ - board: post.info[0], - threadID: post.info[1], - postID: post.ID - }); - return true; - } - value = Filter[type](post); - if (!value) { - return false; - } - return el.href = Redirect.to({ - board: post.info[0], - type: type, - value: value, - isSearch: true - }); - }; - return { - el: el, - open: open - }; - } - }; - - DeleteLink = { - init: function() { - var aImage, aPost, children, div; - - div = $.el('div', { - className: 'delete_link', - textContent: 'Delete' - }); - aPost = $.el('a', { - className: 'delete_post', - href: 'javascript:;' - }); - aImage = $.el('a', { - className: 'delete_image', - href: 'javascript:;' - }); - children = []; - children.push({ - el: aPost, - open: function() { - aPost.textContent = 'Post'; - $.on(aPost, 'click', DeleteLink["delete"]); - return true; - } - }); - children.push({ - el: aImage, - open: function(post) { - if (!post.img) { - return false; - } - aImage.textContent = 'Image'; - $.on(aImage, 'click', DeleteLink["delete"]); - return true; - } - }); - Menu.addEntry({ - el: div, - open: function(post) { - var node, seconds; - - if (post.isArchived) { - return false; - } - node = div.firstChild; - if (seconds = DeleteLink.cooldown[post.ID]) { - node.textContent = "Delete (" + seconds + ")"; - DeleteLink.cooldown.el = node; - } else { - node.textContent = 'Delete'; - delete DeleteLink.cooldown.el; - } - return true; - }, - children: children - }); - return $.on(d, 'QRPostSuccessful', this.cooldown.start); - }, - "delete": function() { - var board, form, id, m, menu, pwd, self; - - menu = $.id('menu'); - id = menu.dataset.id; - if (DeleteLink.cooldown[id]) { - return; - } - $.off(this, 'click', DeleteLink["delete"]); - this.textContent = 'Deleting...'; - pwd = (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : $.id('delPassword').value; - board = $('a[title="Highlight this post"]', $.id(menu.dataset.rootid)).pathname.split('/')[1]; - self = this; - form = { - mode: 'usrdel', - onlyimgdel: /\bdelete_image\b/.test(this.className), - pwd: pwd - }; - form[id] = 'delete'; - return $.ajax($.id('delform').action.replace("/" + g.BOARD + "/", "/" + board + "/"), { - onload: function() { - return DeleteLink.load(self, this.response); - }, - onerror: function() { - return DeleteLink.error(self); - } - }, { - form: $.formData(form) - }); - }, - load: function(self, html) { - var doc, msg, s; - - doc = d.implementation.createHTMLDocument(''); - doc.documentElement.innerHTML = html; - if (doc.title === '4chan - Banned') { - s = 'Banned!'; - } else if (msg = doc.getElementById('errmsg')) { - s = msg.textContent; - $.on(self, 'click', DeleteLink["delete"]); - } else { - s = 'Deleted'; - } - return self.textContent = s; - }, - error: function(self) { - self.textContent = 'Connection error, please retry.'; - return $.on(self, 'click', DeleteLink["delete"]); - }, - cooldown: { - start: function(e) { - var seconds; - - seconds = g.BOARD === 'q' ? 600 : 30; - return DeleteLink.cooldown.count(e.detail.postID, seconds, seconds); - }, - count: function(postID, seconds, length) { - var el; - - if (!((0 <= seconds && seconds <= length))) { - return; - } - setTimeout(DeleteLink.cooldown.count, 1000, postID, seconds - 1, length); - el = DeleteLink.cooldown.el; - if (seconds === 0) { - if (el != null) { - el.textContent = 'Delete'; - } - delete DeleteLink.cooldown[postID]; - delete DeleteLink.cooldown.el; - return; - } - if (el != null) { - el.textContent = "Delete (" + seconds + ")"; - } - return DeleteLink.cooldown[postID] = seconds; - } - } - }; - - DownloadLink = { - init: function() { - var a; - - if ($.el('a').download == null) { - return; - } - a = $.el('a', { - className: 'download_link', - textContent: 'Download file' - }); - return Menu.addEntry({ - el: a, - open: function(post) { - var fileText; - - if (!post.img) { - return false; - } - a.href = post.img.parentNode.href; - fileText = post.fileInfo.firstElementChild; - a.download = Conf['File Info Formatting'] ? fileText.dataset.filename : $('span', fileText).title; - return true; - } - }); - } - }; - - EmbedLink = { - init: function() { - var a; - - a = $.el('a', { - className: 'embed_link', - textContent: 'Embed all in post' - }); - $.on(a, 'click', EmbedLink.toggle); - return Menu.addEntry({ - el: a, - open: function(post) { - var quote; - - if ($('.embed', (quote = post.blockquote))) { - if ($('.embedded', quote)) { - this.el.textContent = 'Unembed all in post'; - EmbedLink[post.id] = true; - } - $.on(this.el, 'click', this.toggle); - return true; - } - return false; - } - }); - }, - toggle: function() { - var embed, id, menu, root, _i, _len, _ref; - - menu = $.id('menu'); - id = menu.dataset.id; - root = $.id("m" + id); - _ref = $$('.embed', root); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - embed = _ref[_i]; - if ((!EmbedLink[id] && embed.className.contains('embedded')) || (EmbedLink[id] && !embed.className.contains('embedded'))) { - continue; - } - embed.click(); - } - return EmbedLink[id] = !EmbedLink[id]; - } - }; - - Menu = { - entries: [], - init: function() { - this.a = $.el('a', { - className: 'menu_button', - href: 'javascript:;', - innerHTML: '[]' - }); - this.el = $.el('div', { - className: 'reply dialog', - id: 'menu', - tabIndex: 0 - }); - $.on(this.el, 'click', function(e) { - return e.stopPropagation(); - }); - $.on(this.el, 'keydown', this.keybinds); - $.on(d, 'AddMenuEntry', function(e) { - return Menu.addEntry(e.detail); - }); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var a; - - if (post.isInlined && !post.isCrosspost) { - a = $('.menu_button', post.el); - } else { - a = Menu.a.cloneNode(true); - $.add($('.postInfo', post.el), [$.tn('\u00A0'), a]); - } - return $.on(a, 'click', Menu.toggle); - }, - toggle: function(e) { - var lastOpener, post; - - e.preventDefault(); - e.stopPropagation(); - if (Menu.el.parentNode) { - lastOpener = Menu.lastOpener; - Menu.close(); - if (lastOpener === this) { - return; - } - } - Menu.lastOpener = this; - post = /\bhidden_thread\b/.test(this.parentNode.className) ? $.x('ancestor::div[parent::div[@class="board"]]/child::div[contains(@class,"opContainer")]', this) : $.x('ancestor::div[contains(@class,"postContainer")][1]', this); - return Menu.open(this, Main.preParse(post)); - }, - open: function(button, post) { - var bLeft, bRect, bTop, el, entry, funk, mRect, _i, _len, _ref; - - el = Menu.el; - el.setAttribute('data-id', post.ID); - el.setAttribute('data-rootid', post.root.id); - funk = function(entry, parent) { - var child, children, subMenu, _i, _len; - - children = entry.children; - if (!entry.open(post)) { - return; - } - $.add(parent, entry.el); - if (!children) { - return; - } - if (subMenu = $('.subMenu', entry.el)) { - $.rm(subMenu); - } - subMenu = $.el('div', { - className: 'reply dialog subMenu' - }); - $.add(entry.el, subMenu); - for (_i = 0, _len = children.length; _i < _len; _i++) { - child = children[_i]; - funk(child, subMenu); - } - }; - _ref = Menu.entries; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - entry = _ref[_i]; - funk(entry, el); - } - Menu.focus($('.entry', Menu.el)); - $.on(d, 'click', Menu.close); - $.add(d.body, el); - mRect = el.getBoundingClientRect(); - bRect = button.getBoundingClientRect(); - bTop = d.documentElement.scrollTop + d.body.scrollTop + bRect.top; - bLeft = d.documentElement.scrollLeft + d.body.scrollLeft + bRect.left; - el.style.top = bRect.top + bRect.height + mRect.height < d.documentElement.clientHeight ? bTop + bRect.height + 2 + 'px' : bTop - mRect.height - 2 + 'px'; - el.style.left = bRect.left + mRect.width < d.documentElement.clientWidth ? bLeft + 'px' : bLeft + bRect.width - mRect.width + 'px'; - return el.focus(); - }, - close: function() { - var el, focused, _i, _len, _ref; - - el = Menu.el; - $.rm(el); - _ref = $$('.focused.entry', el); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - focused = _ref[_i]; - $.rmClass(focused, 'focused'); - } - el.innerHTML = null; - el.removeAttribute('style'); - delete Menu.lastOpener; - delete Menu.focusedEntry; - return $.off(d, 'click', Menu.close); - }, - keybinds: function(e) { - var el, next, subMenu; - - el = Menu.focusedEntry; - switch (Keybinds.keyCode(e) || e.keyCode) { - case 'Esc': - Menu.lastOpener.focus(); - Menu.close(); - break; - case 13: - case 32: - el.click(); - break; - case 'Up': - if (next = el.previousElementSibling) { - Menu.focus(next); - } - break; - case 'Down': - if (next = el.nextElementSibling) { - Menu.focus(next); - } - break; - case 'Right': - if ((subMenu = $('.subMenu', el)) && (next = subMenu.firstElementChild)) { - Menu.focus(next); - } - break; - case 'Left': - if (next = $.x('parent::*[contains(@class,"subMenu")]/parent::*', el)) { - Menu.focus(next); - } - break; - default: - return; - } - e.preventDefault(); - return e.stopPropagation(); - }, - focus: function(el) { - var focused, _i, _len, _ref; - - if (focused = $.x('parent::*/child::*[contains(@class,"focused")]', el)) { - $.rmClass(focused, 'focused'); - } - _ref = $$('.focused', el); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - focused = _ref[_i]; - $.rmClass(focused, 'focused'); - } - Menu.focusedEntry = el; - return $.addClass(el, 'focused'); - }, - addEntry: function(entry) { - var funk; - - funk = function(entry) { - var child, children, el, _i, _len; - - el = entry.el, children = entry.children; - $.addClass(el, 'entry'); - $.on(el, 'focus mouseover', function(e) { - e.stopPropagation(); - return Menu.focus(this); - }); - if (!children) { - return; - } - $.addClass(el, 'hasSubMenu'); - for (_i = 0, _len = children.length; _i < _len; _i++) { - child = children[_i]; - funk(child); - } - }; - funk(entry); - return Menu.entries.push(entry); - } - }; - - ReplyHideLink = { - init: function() { - var a; - - if (!Conf['Reply Hiding']) { - Main.callbacks.push(this.node); - } - a = $.el('a', { - className: 'reply_hide_link', - href: 'javascript:;', - textContent: 'Hide / Restore Post' - }); - $.on(a, 'click', function() { - var button, id, menu, root; - - menu = Menu.el; - id = menu.dataset.id; - root = $.id("pc" + id); - button = root.firstChild; - ReplyHiding.toggle(button, root, id); - return Menu.close(); - }); - return Menu.addEntry({ - el: a, - open: function(post) { - if (post.isInlined || post.el.classList.contains('op')) { - return false; - } else { - return true; - } - } - }); - }, - node: function(post) { - if (post.isInlined || post.ID === post.threadID) { - return; - } - if (post.ID in g.hiddenReplies) { - return ReplyHiding.hide(post.root); - } - } - }; - - ReportLink = { - init: function() { - var a; - - a = $.el('a', { - className: 'report_link', - href: 'javascript:;', - textContent: 'Report this post' - }); - $.on(a, 'click', this.report); - return Menu.addEntry({ - el: a, - open: function(post) { - return post.isArchived === false; - } - }); - }, - report: function() { - var a, id, set, url; - - a = $('a[title="Highlight this post"]', $.id(this.parentNode.dataset.rootid)); - url = "//sys.4chan.org/" + (a.pathname.split('/')[1]) + "/imgboard.php?mode=report&no=" + this.parentNode.dataset.id; - id = Date.now(); - set = "toolbar=0,scrollbars=0,location=0,status=1,menubar=0,resizable=1,width=685,height=200"; - return window.open(url, id, set); - } - }; - - ThreadHideLink = { - init: function() { - var a; - - if (!Conf['Thread Hiding']) { - $.ready(this.iterate); - } - a = $.el('a', { - className: 'thread_hide_link', - href: 'javascript:;', - textContent: 'Hide / Restore Thread' - }); - $.on(a, 'click', function() { - var menu, thread; - - menu = Menu.el; - thread = $.id("t" + menu.dataset.id); - ThreadHiding.toggle(thread); - return Menu.close(); - }); - return Menu.addEntry({ - el: a, - open: function(post) { - if (post.el.classList.contains('op')) { - return true; - } else { - return false; - } - } - }); - }, - iterate: function() { - var thread, _i, _len, _ref; - - ThreadHiding.hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); - _ref = $$('.thread'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - thread = _ref[_i]; - if (thread.id.slice(1) in ThreadHiding.hiddenThreads) { - ThreadHiding.hide(thread); - } - } - } - }; - - Favicon = { - init: function() { - var href; - - if (this.el) { - return; - } - this.el = $('link[rel="shortcut icon"]', d.head); - this.el.type = 'image/x-icon'; - href = this.el.href; - this.SFW = /ws.ico$/.test(href); - this["default"] = href; - return this["switch"](); - }, - "switch": function() { - this.unreadDead = this.unreadSFW = this.unreadNSFW = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA'; - switch (Conf['favicon']) { - case 'ferongr': - this.unreadDead += 'BAAAAAQBAMAAADt3eJSAAAAD1BMVEWrVlbpCwJzBQD/jIzlCgLerRyUAAAAAXRSTlMAQObYZgAAAFhJREFUeF5Fi8ENw0AMw6gNZHcCXbJAkw2C7D9Tz68KJKAP+a8MKtAK9DJ9X9ZxB+WT/rbpt9L1Bq3lEapGgBqY3hvYfTagY6rLKHPa6DzTz2PothJAApsfXPUIxXEAtJ4AAAAASUVORK5CYII='; - this.unreadNSFW += 'BAAAAAQCAMAAAAoLQ9TAAAAFVBMVEWJq3ho/gooegBJ3ABU/QBW/wHV/8Hz/s/JAAAAAnRSTlMAscr1TiIAAABVSURBVBjTZY5LDgAxCEKNovc/8mgozq9d+CQRMPs/AC+Auz8BXlUfyGzoPZN7xNDoEVR0u2Zy3ziTsEV0oj5eTCn1KaVQGTpCHiH64wzegKZYV8M9Lia0Aj8l3NBcAAAAAElFTkSuQmCC'; - this.unreadSFW += 'BAAAAAQCAMAAAAoLQ9TAAAAFVBMVEUAS1QAnbAAsseF5vMA2fMA1/EAb37J/JegAAAAA3RSTlMAmPz35Xr7AAAAUUlEQVQY02WOCQ4AIQgDSUr5/5Pl9NjVhE6bYBX5H5IP0MxuoAH4gKqDe9XyZFDkPlirt+bjjyae2X2cWR7VgvkPpqWSoA60g7wtMsmWTIRHFpbuAyerdnAvAAAAAElFTkSuQmCC'; - break; - case 'xat-': - this.unreadDead += 'BAAAAAQBAMAAADt3eJSAAAAG1BMVEXzZmTzZGLzZGLzZGIAAAD/AAD/lJX4bWz/0tMaHcyBAAAABHRSTlMAm8l+71ABtwAAAFpJREFUeF5ty9EJgDAQA9B8dIGKC1gcoQNUm+ICvRWKAwjdwLklCAXBfD2SO/yE2ftIwFkNoVgCih2XVTWCGrI1EsDUz7svH2gSoo4zxruwry/KNlfBOSAljDwk8xZR3HxWZAAAAABJRU5ErkJggg=='; - this.unreadNSFW += 'BAAAAAQBAMAAADt3eJSAAAAIVBMVEVirGJdqF9dqF9dqF9dqF9082JmzDOq/5oAAACR/33Z/9JztnAYAAAABXRSTlMAyZ2Ses9C/CQAAABjSURBVHhebcsxDkBAFATQKbddGq1otJxij8AFJnsFqiVr8x1AuIFr8iMRhaleZv7HTyS2lRPA0FubGIDEpaPXhutBbUT2QQRA2Y/nln3R6JQDcHoc8b4rpuJBmmuvMAYIAW8utWkfv3LWVYEAAAAASUVORK5CYII='; - this.unreadSFW += 'BAAAAAQBAMAAADt3eJSAAAAHlBMVEUAAABde6Zde6Zde6Zde6aQz/8umMNquPcAAADQ6/+nHRY3AAAABXRSTlMAyZ16kvc074oAAABfSURBVHhebcuxCYAwFIThv0yrWNgKFo6QVnewcIFHNohlNBDfAu4rDyFYeNXHHcdPNC+jV3ASmqZIgiLXLsEagzWq66oKDHG7Y/vFbFMHeHtl6t1w9C/KOQWDc5ASNQ9glx6N+XFPbgAAAABJRU5ErkJggg=='; - break; - case 'Mayhem': - this.unreadDead += 'BAAAAAQBAMAAADt3eJSAAAAHlBMVEUAAAAAAAAAAAAAAAAAAAATExMBAQEAAAD/AAD///+gujywAAAACHRSTlMPJRcbLzEcM37+zgIAAAB9SURBVHheRcu9DoJAEATgcX0B+Wns7uAFRGgoCVhQ0phca8K77JXEI+6+rUujU32ZzOAXanLAFw5e91cdNEfPcVmF3+iEt8BxtOaANV51WdU2VE5FMw0O1B0YDaUOD30aZk6Bd4eT8Mfulz/OIinEeANd5yxLmwPqtqraO75dUSZT40SwmAAAAABJRU5ErkJggg=='; - this.unreadNSFW += 'BAAAAAQBAMAAADt3eJSAAAAHlBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9mzDPTSEsdAAAACHRSTlMaDCUeLg4zKeknoAsAAACHSURBVHheJcqxCsIwEMbxLw2CY27oLiSCYwioeyjS0Sp9Ah26d+koUtrkDXJv6xXhhj+/70B9R1T3BBN8V2urUKXV6ykdsOcSXeYPLpnXictLZAuRKqXokvzc3duGW9zBXBsbmlHBuG2KEi3PcgrPzMvA5YzHP44ieW6LiDkNNixfBYIHNOgHHmcn+8KfmKQAAAAASUVORK5CYII='; - this.unreadSFW += 'BAAAAAQBAMAAADt3eJSAAAAG1BMVEUAAAAAAAABAwMAAAAAAAAAAAAAAAAumMP///+/4sWwAAAAB3RSTlMVJxQdMSkcONaevAAAAIJJREFUeF4lirEKgzAURa9PcBai4PjI0NlA6y61kFXawVHq4h+8rEI0+ewmdLqHcw80SGtOw2Yg3hShiGdfLrHGLm5ug1y4Bzk6cc9kMiRTxDi3MTVVMykzjSv48VLm8yZwk6+RcFvEWzm/KEMG16P4Q51M8NYlw51Vxh8EXQ3AtuofzNIkEO8Bb0kAAAAASUVORK5CYII='; - break; - case '4chanJS': - this.unreadDead += 'BAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAD/AABnZ2f///8nFk05AAAAAXRSTlMAQObYZgAAAEFJREFUeNqNjgEKACAMAjvX/98cAkkxgmSgO8Bt/Ai4ApJ6KKhzF3OiEMDASrGB/QWgPEHsUpN+Ng9xAETMYhDrWmeHAMcmvycWAAAAAElFTkSuQmCC'; - this.unreadNSFW += 'BAAAAAQCAMAAAAoLQ9TAAAAElBMVEUBAAAAAABmzDNlyjJnZ2f///+6o7dfAAAAAXRSTlMAQObYZgAAAERJREFUeF6NjkEKADEIA51o///lJZfQxUsHITogWi8AvwZJuxmYa25xDooBLEwOWFTYAsYVhdorLZt9Ng9xCUTCUCQ2H3F4ANrZ2WNiAAAAAElFTkSuQmCC'; - this.unreadSFW += 'BAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAAul8NnZ2f////82iC9AAAAAXRSTlMAQObYZgAAAEFJREFUeNqNjgEKACAMAjvX/98cAkkxgmSgO8Bt/Ai4ApJ6KKhzF3OiEMDASrGB/QWgPEHsUpN+Ng9xAETMYhDrWmeHAMcmvycWAAAAAElFTkSuQmCC'; - break; - case 'Original': - this.unreadDead += 'BAAAAAQCAMAAAAoLQ9TAAAAD1BMVEWYmJiYmJj///8AAAD/AACKRYF4AAAAAnRSTlMAvLREMp8AAABFSURBVBjTbY7BDgAgCEIZ+P/f3MGgXHkR3wYCvENyCEq6BVVVPzFvg03sTZjT8w4GKWKL+8ih7jPffoEaKB52KJMKnrUA5kwBxesBDg0AAAAASUVORK5CYII='; - this.unreadNSFW += 'BAAAAAQCAMAAAAoLQ9TAAAADFBMVEWYmJj///9mzDMAAAADduU3AAAAAXRSTlMAQObYZgAAAERJREFUGNNtjkESACAIAkH+/+cOBuWUF3FnQIB3SA5BSbegquon5m2wib0Jc3rewSBFbHEfOdR95tsvUAPFww5lUsGzFpsgATH7KrmBAAAAAElFTkSuQmCC'; - this.unreadSFW += 'BAAAAAQCAMAAAAoLQ9TAAAADFBMVEWYmJj///8umMMAAACriBKaAAAAAXRSTlMAQObYZgAAAERJREFUGNNtjkESACAIAkH+/+cOBuWUF3FnQIB3SA5BSbegquon5m2wib0Jc3rewSBFbHEfOdR95tsvUAPFww5lUsGzFpsgATH7KrmBAAAAAElFTkSuQmCC'; - } - this.unread = this.SFW ? this.unreadSFW : this.unreadNSFW; - }, - empty: 'data:image/gif;base64,R0lGODlhEAAQAJEAAAAAAP///9vb2////yH5BAEAAAMALAAAAAAQABAAAAIvnI+pq+D9DBAUoFkPFnbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==', - dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==' - }; - - IDColor = { - init: function() { - QuotePreview.callbacks.push(this.node); - ExpandComment.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var str, uid; - - if (!(uid = $('.postInfo .hand', post.el))) { - return; - } - str = uid.textContent; - if (uid.nodeName === 'SPAN') { - uid.style.cssText = IDColor.apply.call(str); - } - if (!IDColor.highlight[str]) { - IDColor.highlight[str] = []; - } - if (str === $.get("highlightedID/" + g.BOARD + "/")) { - IDColor.highlight.current.push(post); - $.addClass(post.el, 'highlight'); - } - IDColor.highlight[str].push(post); - return $.on(uid, 'click', function() { - return IDColor.idClick(str); - }); - }, - ids: {}, - compute: function(str) { - var hash, rgb; - - hash = this.hash(str); - rgb = [(hash >> 24) & 0xFF, (hash >> 16) & 0xFF, (hash >> 8) & 0xFF]; - rgb[3] = ((rgb[0] * 0.299) + (rgb[1] * 0.587) + (rgb[2] * 0.114)) > 125; - this.ids[str] = rgb; - return rgb; - }, - apply: function() { - var rgb; - - rgb = IDColor.ids[this] || IDColor.compute(this); - return ("background-color: rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "); color: ") + (rgb[3] ? "black;" : "white;"); - }, - hash: function(str) { - var i, j, msg; - - msg = 0; - i = 0; - j = str.length; - while (i < j) { - msg = ((msg << 5) - msg) + str.charCodeAt(i); - ++i; - } - return msg; - }, - highlight: { - current: [] - }, - idClick: function(str) { - var last, post, value, _i, _j, _len, _len1, _ref, _ref1; - - _ref = this.highlight.current; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - post = _ref[_i]; - $.rmClass(post.el, 'highlight'); - } - last = $.get(value = "highlightedID/" + g.BOARD + "/", false); - if (str === last) { - this.highlight.current = []; - return $["delete"](value); - } - _ref1 = this.highlight[str]; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - post = _ref1[_j]; - if (post.isInlined) { - continue; - } - $.addClass(post.el, 'highlight'); - this.highlight.current.push(post); - } - return $.set(value, str); - } - }; - - MarkOwn = { - init: function() { - Main.callbacks.push(this.node); - return this.posts = $.get('ownedPosts', {}); - }, - node: function(post) { - var owned, posts, quote, _i, _len, _ref; - - posts = MarkOwn.posts; - _ref = post.quotes; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - if (!(quote.hash && posts[quote.hash.slice(2)])) { - continue; - } - owned = true; - $.addClass(quote, 'ownreply'); - quote.textContent += " (You)"; - } - if (owned) { - $.addClass(post.el, 'quotedYou'); - } - if (posts[post.ID]) { - $.addClass(post.el, 'yourPost'); - } - } - }; - - RemoveSpoilers = { - init: function() { - if (Conf['Indicate Spoilers']) { - this.wrapper = function(text) { - return "[spoiler]" + text + "[/spoiler]"; - }; - } - return Main.callbacks.push(this.node); - }, - wrapper: function(text) { - return text; - }, - node: function(post) { - var spoiler, spoilers, _i, _len; - - spoilers = $$('s', post.el); - for (_i = 0, _len = spoilers.length; _i < _len; _i++) { - spoiler = spoilers[_i]; - $.replace(spoiler, $.tn(RemoveSpoilers.wrapper(spoiler.textContent))); - } - } - }; - - ThreadStats = { - init: function() { - var container, dialog, move; - - ThreadStats.postcount = $.el('span', { - id: 'postcount', - textContent: '0' - }); - ThreadStats.imagecount = $.el('span', { - id: 'imagecount', - textContent: '0' - }); - if (Conf['Thread Updater'] && Conf['Merged Updater and Stats'] && (move = Updater.count.parentElement)) { - container = $.el('span'); - $.add(container, [$.tn('['), ThreadStats.postcount, $.tn(' / '), ThreadStats.imagecount, $.tn('] ')]); - $.prepend(move, container); - } else { - dialog = UI.dialog('stats', 'bottom: 0; left: 0;', '
'); - dialog.className = 'dialog'; - $.add($(".move", dialog), ThreadStats.postcount); - $.add($(".move", dialog), $.tn(" / ")); - $.add($(".move", dialog), ThreadStats.imagecount); - $.add(d.body, dialog); - } - this.posts = this.images = 0; - this.imgLimit = (function() { - switch (g.BOARD) { - case 'a': - case 'b': - case 'v': - case 'co': - case 'mlp': - return 251; - case 'vg': - return 376; - default: - return 151; - } - })(); - return Main.callbacks.push(this.node); - }, - node: function(post) { - if (post.isInlined) { - return; - } - ThreadStats.postcount.textContent = ++ThreadStats.posts; - if (!post.img) { - return; - } - ThreadStats.imagecount.textContent = ++ThreadStats.images; - if (ThreadStats.images > ThreadStats.imgLimit) { - return $.addClass(ThreadStats.imagecount, 'warning'); - } - } - }; - - TitlePost = { - init: function() { - return d.title = Get.title(); - } - }; - - Unread = { - init: function() { - this.title = d.title; - $.on(d, 'QRPostSuccessful', this.post); - this.update(); - $.on(window, 'scroll', Unread.scroll); - $.on(window, 'focus', Unread.focus); - return Main.callbacks.push(this.node); - }, - replies: [], - foresee: [], - post: function(e) { - return Unread.foresee.push(e.detail.postID); - }, - node: function(post) { - var count, el, index, root; - - if ((index = Unread.foresee.indexOf(post.ID)) !== -1) { - Unread.foresee.splice(index, 1); - return; - } - el = post.el, root = post.root; - if (el.hidden || /\bop\b/.test(post["class"]) || post.isInlined) { - return; - } - count = Unread.replies.push(el); - return Unread.update(count === 1); - }, - focus: function() { - if (Unread.replies !== 0) { - return Unread.count(); - } - }, - scroll: function() { - if (!(d.hidden || Unread.replies === 0)) { - return Unread.count(); - } - }, - count: function() { - var bottom, height, i, reply, _i, _len, _ref; - - height = d.documentElement.clientHeight; - _ref = Unread.replies; - for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { - reply = _ref[i]; - bottom = reply.getBoundingClientRect().bottom; - if (bottom > height) { - break; - } - } - if (i === 0) { - return; - } - Unread.replies = Unread.replies.slice(i); - return Unread.update(Unread.replies.length === 0); - }, - setTitle: function(count) { - if (this.scheduled) { - clearTimeout(this.scheduled); - delete Unread.scheduled; - this.setTitle(count); - return; - } - return this.scheduled = setTimeout((function() { - return d.title = "(" + count + ") " + Unread.title; - }), 5); - }, - update: function(updateFavicon) { - var count; - - if (!g.REPLY) { - return; - } - count = this.replies.length; - if (Conf['Unread Count']) { - this.setTitle(count); - } - if (!(Conf['Unread Favicon'] && updateFavicon)) { - return; - } - if ($.engine === 'presto') { - $.rm(Favicon.el); - } - Favicon.el.href = g.dead ? count ? Favicon.unreadDead : Favicon.dead : count ? Favicon.unread : Favicon["default"]; - if (g.dead) { - $.addClass(Favicon.el, 'dead'); - } else { - $.rmClass(Favicon.el, 'dead'); - } - if (count) { - $.addClass(Favicon.el, 'unread'); - } else { - $.rmClass(Favicon.el, 'unread'); - } - if ($.engine !== 'webkit') { - return $.add(d.head, Favicon.el); - } - } - }; - - Updater = { - init: function() { - var checkbox, checked, dialog, html, input, name, title, _i, _len, _ref; - - html = '
'; - checkbox = Config.updater.checkbox; - for (name in checkbox) { - title = checkbox[name][1]; - checked = Conf[name] ? 'checked' : ''; - html += "
"; - } - checked = Conf['Auto Update'] ? 'checked' : ''; - html += "
"; - dialog = UI.dialog('updater', 'bottom: 0; right: 0;', html); - this.count = $('#count', dialog); - this.timer = $('#timer', dialog); - this.thread = $.id("t" + g.THREAD_ID); - this.save = []; - this.checkPostCount = 0; - this.unsuccessfulFetchCount = 0; - this.lastModified = '0'; - _ref = $$('input', dialog); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - input = _ref[_i]; - if (input.type === 'checkbox') { - $.on(input, 'click', $.cb.checked); - } - switch (input.name) { - case 'Scroll BG': - $.on(input, 'click', this.cb.scrollBG); - this.cb.scrollBG.call(input); - break; - case 'Verbose': - $.on(input, 'click', this.cb.verbose); - this.cb.verbose.call(input); - break; - case 'Auto Update This': - $.on(input, 'click', this.cb.autoUpdate); - this.cb.autoUpdate.call(input); - break; - case 'Interval': - case 'BGInterval': - case "Interval_" + g.BOARD: - case "BGInterval_" + g.BOARD: - input.value = Conf[input.name]; - $.on(input, 'change', this.cb.interval); - this.cb.interval.call(input); - break; - case 'Update Now': - $.on(input, 'click', this.update); - } - } - $.add(d.body, dialog); - $.on(d, 'QRPostSuccessful', this.cb.post); - return $.on(d, 'visibilitychange', this.cb.visibility); - }, - /* - beep1.wav - http://freesound.org/people/pierrecartoons1979/sounds/90112 - - This work is licensed under the Attribution Noncommercial License. - http://creativecommons.org/licenses/by-nc/3.0/ - */ - - audio: $.el('audio', { - src: 'data:audio/wav;base64,UklGRjQDAABXQVZFZm10IBAAAAABAAEAgD4AAIA+AAABAAgAc21wbDwAAABBAAADAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkYXRhzAIAAGMms8em0tleMV4zIpLVo8nhfSlcPR102Ki+5JspVEkdVtKzs+K1NEhUIT7DwKrcy0g6WygsrM2k1NpiLl0zIY/WpMrjgCdbPhxw2Kq+5Z4qUkkdU9K1s+K5NkVTITzBwqnczko3WikrqM+l1NxlLF0zIIvXpsnjgydZPhxs2ay95aIrUEkdUdC3suK8N0NUIjq+xKrcz002WioppdGm091pK1w0IIjYp8jkhydXPxxq2K295aUrTkoeTs65suK+OUFUIzi7xqrb0VA0WSoootKm0t5tKlo1H4TYqMfkiydWQBxm16+85actTEseS8y7seHAPD9TIza5yKra01QyWSson9On0d5wKVk2H4DYqcfkjidUQB1j1rG75KsvSkseScu8seDCPz1TJDW2yara1FYxWSwnm9Sn0N9zKVg2H33ZqsXkkihSQR1g1bK65K0wSEsfR8i+seDEQTxUJTOzy6rY1VowWC0mmNWoz993KVc3H3rYq8TklSlRQh1d1LS647AyR0wgRMbAsN/GRDpTJTKwzKrX1l4vVy4lldWpzt97KVY4IXbUr8LZljVPRCxhw7W3z6ZISkw1VK+4sMWvXEhSPk6buay9sm5JVkZNiLWqtrJ+TldNTnquqbCwilZXU1BwpKirrpNgWFhTaZmnpquZbFlbVmWOpaOonHZcXlljhaGhpZ1+YWBdYn2cn6GdhmdhYGN3lp2enIttY2Jjco+bnJuOdGZlZXCImJqakHpoZ2Zug5WYmZJ/bGlobX6RlpeSg3BqaW16jZSVkoZ0bGtteImSk5KIeG5tbnaFkJKRinxxbm91gY2QkIt/c3BwdH6Kj4+LgnZxcXR8iI2OjIR5c3J0e4WLjYuFe3VzdHmCioyLhn52dHR5gIiKioeAeHV1eH+GiYqHgXp2dnh9hIiJh4J8eHd4fIKHiIeDfXl4eHyBhoeHhH96eHmA' - }), - cb: { - post: function() { - if (!Conf['Auto Update This']) { - return; - } - Updater.unsuccessfulFetchCount = 0; - return setTimeout(Updater.update, 500); - }, - checkpost: function(status) { - if (!(status === 404 || Updater.foundPost || Updater.checkPostCount >= 10)) { - return setTimeout(Updater.update, ++Updater.checkPostCount * 500); - } - Updater.checkPostCount = 0; - delete Updater.foundPost; - return delete Updater.postID; - }, - visibility: function() { - if (d.hidden) { - return; - } - Updater.unsuccessfulFetchCount = 0; - if (Updater.timer.textContent < (Conf['Interval per board'] ? -Conf['Interval_' + g.BOARD] : -Conf['Interval'])) { - return Updater.set('timer', -Updater.getInterval()); - } - }, - interval: function() { - var val; - - val = parseInt(this.value, 10); - this.value = val > 0 ? val : 30; - $.cb.value.call(this); - return Updater.set('timer', -Updater.getInterval()); - }, - verbose: function() { - if (Conf['Verbose']) { - Updater.set('count', '+0'); - return Updater.timer.hidden = false; - } else { - Updater.set('count', '+0'); - Updater.count.className = ''; - return Updater.timer.hidden = true; - } - }, - autoUpdate: function() { - if (Conf['Auto Update This'] = this.checked) { - return Updater.timeoutID = setTimeout(Updater.timeout, 1000); - } else { - return clearTimeout(Updater.timeoutID); - } - }, - scrollBG: function() { - return Updater.scrollBG = this.checked ? function() { - return true; - } : function() { - return !d.hidden; - }; - }, - load: function() { - switch (this.status) { - case 404: - Updater.set('timer', ''); - Updater.set('count', 404); - Updater.count.className = 'warning'; - clearTimeout(Updater.timeoutID); - g.dead = true; - if (Conf['Unread Count']) { - Unread.title = Unread.title.match(/^.+-/)[0] + ' 404'; - } else { - d.title = d.title.match(/^.+-/)[0] + ' 404'; - } - Unread.update(true); - QR.abort(); - break; - case 0: - case 304: - /* - Status Code 304: Not modified - By sending the `If-Modified-Since` header we get a proper status code, and no response. - This saves bandwidth for both the user and the servers and avoid unnecessary computation. - */ - - Updater.unsuccessfulFetchCount++; - Updater.set('timer', -Updater.getInterval()); - if (Conf['Verbose']) { - Updater.set('count', '+0'); - Updater.count.className = null; - } - break; - case 200: - Updater.lastModified = this.getResponseHeader('Last-Modified'); - Updater.cb.update(JSON.parse(this.response).posts); - Updater.set('timer', -Updater.getInterval()); - break; - default: - Updater.unsuccessfulFetchCount++; - Updater.set('timer', -Updater.getInterval()); - if (Conf['Verbose']) { - Updater.set('count', this.statusText); - Updater.count.className = 'warning'; - } - } - if (Updater.postID) { - Updater.cb.checkpost(this.status); - } - return delete Updater.request; - }, - update: function(posts) { - var count, frag, id, lastPost, node, nodes, post, scroll, spoilerRange, _i, _len, _ref; - - if (spoilerRange = posts[0].custom_spoiler) { - Build.spoilerRange[g.BOARD] = spoilerRange; - } - lastPost = Updater.thread.lastElementChild; - id = +lastPost.id.slice(2); - nodes = (function() { - var _i, _len, _ref, _results; - - _ref = posts.reverse(); - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - post = _ref[_i]; - if (post.no <= id) { - break; - } - if (Updater.postID) { - if (("" + post.no) === Updater.postID) { - Updater.foundPost = true; - } - } - _results.push(Build.postFromObject(post, g.BOARD)); - } - return _results; - })(); - count = nodes.length; - if (Conf['Verbose']) { - Updater.set('count', "+" + count); - Updater.count.className = count ? 'new' : null; - } - if (count) { - if (Conf['Beep'] && d.hidden && (Unread.replies.length === 0)) { - Updater.audio.play(); - } - Updater.unsuccessfulFetchCount = 0; - } else { - Updater.unsuccessfulFetchCount++; - return; - } - scroll = Conf['Scrolling'] && Updater.scrollBG() && lastPost.getBoundingClientRect().bottom - d.documentElement.clientHeight < 25; - _ref = nodes.reverse(); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - node = _ref[_i]; - frag = $.frag(); - $.add(frag, node); - Main.node(Main.preParse(node)); - $.add(Updater.thread, frag); - } - if (scroll && (nodes != null)) { - return nodes[0].scrollIntoView(); - } - } - }, - set: function(name, text) { - var el, node; - - el = Updater[name]; - if (node = el.firstChild) { - return node.data = text; - } else { - return el.textContent = text; - } - }, - getInput: function(input) { - var i, number, _i, _len, _results; - - while ((i = input.length) < 10) { - input[i] = input[i - 1]; - } - _results = []; - for (_i = 0, _len = input.length; _i < _len; _i++) { - number = input[_i]; - _results.push(parseInt(number, 10)); - } - return _results; - }, - getInterval: function() { - var count, i, increase, increaseString, j, string; - - string = "Interval" + (Conf['Interval per board'] ? "_" + g.BOARD : ""); - increaseString = "updateIncrease"; - if (d.hidden) { - string = "BG" + string; - increaseString += "B"; - } - i = +Conf[string]; - j = (count = this.unsuccessfulFetchCount) > 9 ? 9 : count; - return (Conf['Optional Increase'] ? (i > (increase = Updater.getInput(Conf[increaseString].split(','))[j]) ? i : increase) : i); - }, - timeout: function() { - var n; - - Updater.timeoutID = setTimeout(Updater.timeout, 1000); - n = 1 + parseInt(Updater.timer.firstChild.data, 10); - if (n === 0) { - return Updater.update(); - } else if (n >= Updater.getInterval()) { - Updater.unsuccessfulFetchCount++; - Updater.set('count', 'Retry'); - Updater.count.className = null; - return Updater.update(); - } else { - return Updater.set('timer', n); - } - }, - update: function() { - var request, url; - - Updater.set('timer', 0); - request = Updater.request; - if (request) { - request.onloadend = null; - request.abort(); - } - url = "//api.4chan.org/" + g.BOARD + "/res/" + g.THREAD_ID + ".json"; - return Updater.request = $.ajax(url, { - onloadend: Updater.cb.load - }, { - headers: { - 'If-Modified-Since': Updater.lastModified - } - }); - } - }; - - Watcher = { - init: function() { - var favicon, html, input, _i, _len, _ref; - - html = '
Thread Watcher
'; - this.dialog = UI.dialog('watcher', 'top: 50px; left: 0px;', html); - $.add(d.body, this.dialog); - _ref = $$('.op input'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - input = _ref[_i]; - favicon = $.el('img', { - className: 'favicon' - }); - $.on(favicon, 'click', this.cb.toggle); - $.before(input, favicon); - } - if (g.THREAD_ID === $.get('autoWatch', 0)) { - this.watch(g.THREAD_ID); - $["delete"]('autoWatch'); - } else { - this.refresh(); - } - $.on(d, 'QRPostSuccessful', this.cb.post); - return $.sync('watched', this.refresh); - }, - refresh: function(watched) { - var board, div, favicon, id, link, nodes, props, watchedBoard, x, _i, _j, _len, _len1, _ref, _ref1, _ref2; - - watched || (watched = $.get('watched', {})); - nodes = []; - for (board in watched) { - _ref = watched[board]; - for (id in _ref) { - props = _ref[id]; - x = $.el('a', { - textContent: '×', - href: 'javascript:;' - }); - $.on(x, 'click', Watcher.cb.x); - link = $.el('a', props); - link.title = link.textContent; - div = $.el('div'); - $.add(div, [x, $.tn(' '), link]); - nodes.push(div); - } - } - _ref1 = $$('div:not(.move)', Watcher.dialog); - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - div = _ref1[_i]; - $.rm(div); - } - $.add(Watcher.dialog, nodes); - watchedBoard = watched[g.BOARD] || {}; - _ref2 = $$('.favicon'); - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - favicon = _ref2[_j]; - id = favicon.nextSibling.name; - if (id in watchedBoard) { - favicon.src = Favicon["default"]; - } else { - favicon.src = Favicon.empty; - } - } - }, - cb: { - toggle: function() { - return Watcher.toggle(this.parentNode); - }, - x: function() { - var thread; - - thread = this.nextElementSibling.pathname.split('/'); - return Watcher.unwatch(thread[3], thread[1]); - }, - post: function(e) { - var postID, threadID, _ref; - - _ref = e.detail, postID = _ref.postID, threadID = _ref.threadID; - if (threadID === '0') { - if (Conf['Auto Watch']) { - return $.set('autoWatch', postID); - } - } else if (Conf['Auto Watch Reply']) { - return Watcher.watch(threadID); - } - } - }, - toggle: function(thread) { - var id; - - id = $('.favicon + input', thread).name; - return Watcher.watch(id) || Watcher.unwatch(id, g.BOARD); - }, - unwatch: function(id, board) { - var watched; - - watched = $.get('watched', {}); - delete watched[board][id]; - $.set('watched', watched); - return Watcher.refresh(); - }, - watch: function(id) { - var thread, watched, _name; - - thread = $.id("t" + id); - if ($('.favicon', thread).src === Favicon["default"]) { - return false; - } - watched = $.get('watched', {}); - watched[_name = g.BOARD] || (watched[_name] = {}); - watched[g.BOARD][id] = { - href: "/" + g.BOARD + "/res/" + id, - textContent: Get.title(thread) - }; - $.set('watched', watched); - Watcher.refresh(); - return true; - } - }; - - Markdown = { - format: function(text) { - var pattern, tag, tag_patterns; - - tag_patterns = { - bi: /(\*\*\*|___)(?=\S)([^\r\n]*?\S)\1/g, - b: /(\*\*|__)(?=\S)([^\r\n]*?\S)\1/g, - i: /(\*|_)(?=\S)([^\r\n]*?\S)\1/g, - code: /(`)(?=\S)([^\r\n]*?\S)\1/g, - ds: /(\|\||__)(?=\S)([^\r\n]*?\S)\1/g - }; - for (tag in tag_patterns) { - pattern = tag_patterns[tag]; - text = text ? text.replace(pattern, Markdown.unicode_convert) : '\u0020'; - } - return text; - }, - unicode_convert: function(str, tag, inner) { - var c, charcode, charcodes, codepoints, codes, fmt, i, unicode_text; - - fmt = (function() { - switch (tag) { - case '_': - case '*': - return 'i'; - case '__': - case '**': - return 'b'; - case '___': - case '***': - return 'bi'; - case '||': - return 'ds'; - case '`': - case '```': - return 'code'; - } - })(); - codepoints = { - b: [0x1D7CE, 0x1D400, 0x1D41A], - i: [0x1D7F6, 0x1D434, 0x1D44E], - bi: [0x1D7CE, 0x1D468, 0x1D482], - code: [0x1D7F6, 0x1D670, 0x1D68A], - ds: [0x1D7D8, 0x1D538, 0x1D552] - }; - charcodes = (function() { - var _i, _len, _results; - - _results = []; - for (i = _i = 0, _len = inner.length; _i < _len; i = ++_i) { - c = inner[i]; - _results.push(inner.charCodeAt(i)); - } - return _results; - })(); - codes = (function() { - var _i, _len, _results; - - _results = []; - for (_i = 0, _len = charcodes.length; _i < _len; _i++) { - charcode = charcodes[_i]; - if (charcode >= 48 && charcode <= 57) { - _results.push(charcode - 48 + codepoints[fmt][0]); - } else if (charcode >= 65 && charcode <= 90) { - _results.push(charcode - 65 + codepoints[fmt][1]); - } else if (charcode >= 97 && charcode <= 122) { - if (charcode === 104 && tag === 'i') { - _results.push(0x210E); - } else { - _results.push(charcode - 97 + codepoints[fmt][2]); - } - } else { - _results.push(charcode); - } - } - return _results; - })(); - unicode_text = codes.map(Markdown.ucs2_encode).join(''); - if (tag === 'code') { - unicode_text = unicode_text.replace(/\x20/g, '\xA0'); - } - return unicode_text; - }, - ucs2_encode: function(value) { - /* - From Punycode.js: https://github.com/bestiejs/punycode.js - - Copyright Mathias Bynens - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF` - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - var output; - - output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += String.fromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - return output += String.fromCharCode(value); - } - }; - - QR = { - init: function() { - if (!$.id('postForm')) { - return; - } - QuoteInline.callbacks.push(this.node); - Main.callbacks.push(this.node); - return setTimeout(this.asyncInit); - }, - asyncInit: function() { - var link, title; - - if (Conf['Hide Original Post Form']) { - link = $.el('h1', { - innerHTML: "" + (title = g.REPLY ? 'Reply to Thread' : 'Start a Thread') + "", - title: title - }); - $.on(link.firstChild, 'click', function() { - QR.open(); - if (!g.REPLY) { - QR.threadSelector.value = g.BOARD === 'f' ? '9999' : 'new'; - } - return $('textarea', QR.el).focus(); - }); - $.before($.id('postForm'), link); - if (Conf['Check for Bans']) { - BanChecker.init(); - } - } - if (Conf['Persistent QR']) { - QR.dialog(); - if (Conf['Auto Hide QR']) { - QR.hide(); - } - } - $.on(d, 'dragover', QR.dragOver); - $.on(d, 'drop', QR.dropFile); - return $.on(d, 'dragstart dragend', QR.drag); - }, - node: function(post) { - return $.on($('a[title="Quote this post"]', $('.postInfo', post.el)), 'click', QR.quote); - }, - open: function() { - if (QR.el) { - QR.el.hidden = false; - return QR.unhide(); - } else { - return QR.dialog(); - } - }, - close: function() { - var i, spoiler, _i, _len, _ref; - - QR.el.hidden = true; - QR.abort(); - d.activeElement.blur(); - $.rmClass(QR.el, 'dump'); - _ref = QR.replies; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - i = _ref[_i]; - QR.replies[0].rm(); - } - QR.cooldown.auto = false; - QR.status(); - QR.resetFileInput(); - if (!Conf['Remember Spoiler'] && (spoiler = $.id('spoiler')).checked) { - spoiler.click(); - } - return QR.cleanError(); - }, - hide: function() { - d.activeElement.blur(); - $.addClass(QR.el, 'autohide'); - return QR.autohide.checked = true; - }, - unhide: function() { - $.rmClass(QR.el, 'autohide'); - return QR.autohide.checked = false; - }, - toggleHide: function() { - return this.checked && QR.hide() || QR.unhide(); - }, - error: function(err) { - if (typeof err === 'string') { - QR.warning.textContent = err; - } else { - QR.warning.innerHTML = null; - $.add(QR.warning, err); - } - QR.open(); - if (QR.captcha.isEnabled && /captcha|verification/i.test(QR.warning.textContent)) { - $('[autocomplete]', QR.el).focus(); - } - if (d.hidden) { - return alert(QR.warning.textContent); - } - }, - cleanError: function() { - return QR.warning.textContent = null; - }, - status: function(data) { - var disabled, input, value; - - if (data == null) { - data = {}; - } - if (!QR.el) { - return; - } - if (g.dead) { - value = 404; - disabled = true; - QR.cooldown.auto = false; - } - value = data.progress || QR.cooldown.seconds || value; - input = QR.status.input; - input.value = QR.cooldown.auto && Conf['Cooldown'] ? value ? "Auto " + value : 'Auto' : value || 'Submit'; - return input.disabled = disabled || false; - }, - cooldown: { - init: function() { - if (!Conf['Cooldown']) { - return; - } - QR.cooldown.types = { - thread: (function() { - switch (g.BOARD) { - case 'q': - return 86400; - case 'b': - case 'soc': - case 'r9k': - return 600; - default: - return 300; - } - })(), - sage: 60, - file: g.BOARD === 'q' ? 300 : 30, - post: g.BOARD === 'q' ? 60 : 30 - }; - QR.cooldown.cooldowns = $.get("" + g.BOARD + ".cooldown", {}); - QR.cooldown.start(); - return $.sync("" + g.BOARD + ".cooldown", QR.cooldown.sync); - }, - start: function() { - if (QR.cooldown.isCounting) { - return; - } - QR.cooldown.isCounting = true; - return QR.cooldown.count(); - }, - sync: function(cooldowns) { - var id; - - for (id in cooldowns) { - QR.cooldown.cooldowns[id] = cooldowns[id]; - } - return QR.cooldown.start(); - }, - set: function(data) { - var cooldown, hasFile, isReply, isSage, start, type; - - if (!Conf['Cooldown']) { - return; - } - start = Date.now(); - if (data.delay) { - cooldown = { - delay: data.delay - }; - } else { - isSage = /sage/i.test(data.post.email); - hasFile = !!data.post.file; - isReply = data.isReply; - type = !isReply ? 'thread' : isSage ? 'sage' : hasFile ? 'file' : 'post'; - cooldown = { - isReply: isReply, - isSage: isSage, - hasFile: hasFile, - timeout: start + QR.cooldown.types[type] * $.SECOND - }; - } - QR.cooldown.cooldowns[start] = cooldown; - $.set("" + g.BOARD + ".cooldown", QR.cooldown.cooldowns); - return QR.cooldown.start(); - }, - unset: function(id) { - delete QR.cooldown.cooldowns[id]; - return $.set("" + g.BOARD + ".cooldown", QR.cooldown.cooldowns); - }, - count: function() { - var cooldown, cooldowns, elapsed, hasFile, isReply, isSage, now, post, seconds, start, type, types, update, _ref; - - if (Object.keys(QR.cooldown.cooldowns).length) { - setTimeout(QR.cooldown.count, 1000); - } else { - $["delete"]("" + g.BOARD + ".cooldown"); - delete QR.cooldown.isCounting; - delete QR.cooldown.seconds; - QR.status(); - return; - } - if ((isReply = g.REPLY ? true : QR.threadSelector.value !== 'new')) { - post = QR.replies[0]; - isSage = /sage/i.test(post.email); - hasFile = !!post.file; - } - now = Date.now(); - seconds = null; - _ref = QR.cooldown, types = _ref.types, cooldowns = _ref.cooldowns; - for (start in cooldowns) { - cooldown = cooldowns[start]; - if ('delay' in cooldown) { - if (cooldown.delay) { - seconds = Math.max(seconds, cooldown.delay--); - } else { - seconds = Math.max(seconds, 0); - QR.cooldown.unset(start); - } - continue; - } - if (isReply === cooldown.isReply) { - type = !isReply ? 'thread' : isSage && cooldown.isSage ? 'sage' : hasFile && cooldown.hasFile ? 'file' : 'post'; - elapsed = Math.floor((now - start) / 1000); - if (elapsed >= 0) { - seconds = Math.max(seconds, types[type] - elapsed); - } - } - if (!((start <= now && now <= cooldown.timeout))) { - QR.cooldown.unset(start); - } - } - update = seconds !== null || !!QR.cooldown.seconds; - QR.cooldown.seconds = seconds; - if (update) { - QR.status(); - } - if (seconds === 0 && QR.cooldown.auto) { - return QR.submit(); - } - } - }, - quote: function(e) { - var caretPos, id, range, s, sel, ta, text, _ref; - - if (e != null) { - e.preventDefault(); - } - QR.open(); - if (!g.REPLY) { - QR.threadSelector.value = $.x('ancestor::div[parent::div[@class="board"]]', this).id.slice(1); - } - id = this.previousSibling.hash.slice(2); - text = ">>" + id + "\n"; - sel = d.getSelection(); - if ((s = sel.toString().trim()) && id === ((_ref = $.x('ancestor-or-self::blockquote', sel.anchorNode)) != null ? _ref.id.match(/\d+$/)[0] : void 0)) { - s = s.replace(/\n/g, '\n>'); - text += ">" + s + "\n"; - } - ta = $('textarea', QR.el); - caretPos = ta.selectionStart; - ta.value = ta.value.slice(0, caretPos) + text + ta.value.slice(ta.selectionEnd); - range = caretPos + text.length; - ta.setSelectionRange(range, range); - ta.focus(); - return $.event(ta, new Event('input')); - }, - characterCount: function() { - var count, counter; - - counter = QR.charaCounter; - count = this.textLength; - counter.textContent = count; - counter.hidden = count < 1000; - return (count > 1500 ? $.addClass : $.rmClass)(counter, 'warning'); - }, - drag: function(e) { - var toggle; - - toggle = e.type === 'dragstart' ? $.off : $.on; - toggle(d, 'dragover', QR.dragOver); - return toggle(d, 'drop', QR.dropFile); - }, - dragOver: function(e) { - e.preventDefault(); - return e.dataTransfer.dropEffect = 'copy'; - }, - dropFile: function(e) { - if (!e.dataTransfer.files.length) { - return; - } - e.preventDefault(); - QR.open(); - QR.fileInput.call(e.dataTransfer); - return $.addClass(QR.el, 'dump'); - }, - fileInput: function() { - var file, _i, _len, _ref; - - QR.cleanError(); - if (this.files.length === 1) { - file = this.files[0]; - if (file.size > this.max) { - QR.error('File too large.'); - QR.resetFileInput(); - } else if (!QR.mimeTypes.contains(file.type)) { - QR.error('Unsupported file type.'); - QR.resetFileInput(); - } else { - QR.selected.setFile(file); - } - return; - } - _ref = this.files; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - file = _ref[_i]; - if (file.size > this.max) { - QR.error("File " + file.name + " is too large."); - break; - } else if (!QR.mimeTypes.contains(file.type)) { - QR.error("" + file.name + ": Unsupported file type."); - break; - } - if (!QR.replies[QR.replies.length - 1].file) { - QR.replies[QR.replies.length - 1].setFile(file); - } else { - new QR.reply().setFile(file); - } - } - $.addClass(QR.el, 'dump'); - return QR.resetFileInput(); - }, - resetFileInput: function() { - return QR.fileEl.value = null; - }, - replies: [], - reply: (function() { - function _Class() { - var key, persona, prev, - _this = this; - - prev = QR.replies[QR.replies.length - 1]; - persona = $.get('persona', { - global: {} - }); - if (!persona[key = Conf['Per Board Persona'] ? g.BOARD : 'global']) { - persona[key] = JSON.parse(JSON.stringify(persona.global)); - } - this.name = prev ? prev.name : persona[key].name || null; - this.email = prev && (Conf["Remember Sage"] || !/^sage$/.test(prev.email)) ? prev.email : persona[key].email || null; - this.sub = prev && Conf['Remember Subject'] ? prev.sub : Conf['Remember Subject'] ? persona[key].sub : null; - this.spoiler = prev && Conf['Remember Spoiler'] ? prev.spoiler : false; - this.com = null; - this.el = $.el('a', { - className: 'thumbnail', - draggable: true, - href: 'javascript:;', - innerHTML: '×' - }); - $('input', this.el).checked = this.spoiler; - $.on(this.el, 'click', function() { - return _this.select(); - }); - $.on($('.remove', this.el), 'click', function(e) { - e.stopPropagation(); - return _this.rm(); - }); - $.on($('label', this.el), 'click', function(e) { - return e.stopPropagation(); - }); - $.on($('input', this.el), 'change', function(e) { - _this.spoiler = e.target.checked; - if (_this.el.id === 'selected') { - return $.id('spoiler').checked = _this.spoiler; - } - }); - $.before($('#addReply', QR.el), this.el); - $.on(this.el, 'dragstart', this.dragStart); - $.on(this.el, 'dragenter', this.dragEnter); - $.on(this.el, 'dragleave', this.dragLeave); - $.on(this.el, 'dragover', this.dragOver); - $.on(this.el, 'dragend', this.dragEnd); - $.on(this.el, 'drop', this.drop); - QR.replies.push(this); - } - - _Class.prototype.setFile = function(file) { - var fileUrl, img, url, - _this = this; - - this.file = file; - this.el.title = "" + file.name + " (" + ($.bytesToString(file.size)) + ")"; - if (QR.spoiler) { - $('label', this.el).hidden = false; - } - if (!/^image/.test(file.type)) { - this.el.style.backgroundImage = null; - return; - } - if (!(url = window.URL || window.webkitURL)) { - return; - } - url.revokeObjectURL(this.url); - fileUrl = url.createObjectURL(file); - img = $.el('img'); - $.on(img, 'load', function() { - var c, data, i, l, s, ui8a, _i; - - s = 90 * 3; - if (img.height < s || img.width < s) { - _this.url = fileUrl; - _this.el.style.backgroundImage = "url(" + _this.url + ")"; - return; - } - if (img.height <= img.width) { - img.width = s / img.height * img.width; - img.height = s; - } else { - img.height = s / img.width * img.height; - img.width = s; - } - c = $.el('canvas', { - height: img.height, - width: img.width - }); - c.getContext('2d').drawImage(img, 0, 0, img.width, img.height); - data = atob(c.toDataURL().split(',')[1]); - l = data.length; - ui8a = new Uint8Array(l); - for (i = _i = 0; 0 <= l ? _i < l : _i > l; i = 0 <= l ? ++_i : --_i) { - ui8a[i] = data.charCodeAt(i); - } - _this.url = url.createObjectURL(new Blob([ui8a], { - type: 'image/png' - })); - _this.el.style.backgroundImage = "url(" + _this.url + ")"; - return typeof url.revokeObjectURL === "function" ? url.revokeObjectURL(fileUrl) : void 0; - }); - return img.src = fileUrl; - }; - - _Class.prototype.rmFile = function() { - var _base1; - - QR.resetFileInput(); - delete this.file; - this.el.title = null; - this.el.style.backgroundImage = null; - if (QR.spoiler) { - $('label', this.el).hidden = true; - } - return typeof (_base1 = window.URL || window.webkitURL).revokeObjectURL === "function" ? _base1.revokeObjectURL(this.url) : void 0; - }; - - _Class.prototype.select = function() { - var check, data, field, rectEl, rectList, _i, _len, _ref, _ref1; - - if (QR.selected === this) { - return; - } - if ((_ref = QR.selected) != null) { - _ref.el.removeAttribute('id'); - } - QR.selected = this; - this.el.id = 'selected'; - rectEl = this.el.getBoundingClientRect(); - rectList = this.el.parentNode.getBoundingClientRect(); - this.el.parentNode.scrollLeft += rectEl.left + rectEl.width / 2 - rectList.left - rectList.width / 2; - _ref1 = ['name', 'email', 'sub', 'com']; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - data = _ref1[_i]; - field = $("[name=" + data + "]", QR.el); - field.value = this[data]; - if (Conf['Tripcode Hider']) { - if (data === 'name') { - check = /^.*##?.+/.test(this[data]); - if (check) { - $.addClass(field, 'tripped'); - } - $.on(field, 'blur', function() { - check = /^.*##?.+/.test(this.value); - if (check && !this.className.match("\\btripped\\b")) { - return $.addClass(this, 'tripped'); - } else if (!check && this.className.match("\\btripped\\b")) { - return $.rmClass(this, 'tripped'); - } - }); - } - } - } - QR.characterCount.call($('textarea', QR.el)); - return $('#spoiler', QR.el).checked = this.spoiler; - }; - - _Class.prototype.dragStart = function() { - return $.addClass(this, 'drag'); - }; - - _Class.prototype.dragEnter = function() { - return $.addClass(this, 'over'); - }; - - _Class.prototype.dragLeave = function() { - return $.rmClass(this, 'over'); - }; - - _Class.prototype.dragOver = function(e) { - e.preventDefault(); - return e.dataTransfer.dropEffect = 'move'; - }; - - _Class.prototype.drop = function() { - var el, index, newIndex, oldIndex, reply; - - el = $('.drag', this.parentNode); - index = function(el) { - return __slice.call(el.parentNode.children).indexOf(el); - }; - oldIndex = index(el); - newIndex = index(this); - if (oldIndex < newIndex) { - $.after(this, el); - } else { - $.before(this, el); - } - reply = QR.replies.splice(oldIndex, 1)[0]; - return QR.replies.splice(newIndex, 0, reply); - }; - - _Class.prototype.dragEnd = function() { - var el; - - $.rmClass(this, 'drag'); - if (el = $('.over', this.parentNode)) { - return $.rmClass(el, 'over'); - } - }; - - _Class.prototype.rm = function() { - var index, _base1; - - QR.resetFileInput(); - $.rm(this.el); - index = QR.replies.indexOf(this); - if (QR.replies.length === 1) { - new QR.reply().select(); - $.rmClass(QR.el, 'dump'); - } else if (this.el.id === 'selected') { - (QR.replies[index - 1] || QR.replies[index + 1]).select(); - } - QR.replies.splice(index, 1); - return typeof (_base1 = window.URL || window.webkitURL).revokeObjectURL === "function" ? _base1.revokeObjectURL(this.url) : void 0; - }; - - return _Class; - - })(), - captcha: { - init: function() { - var observer, onMutationObserver, - _this = this; - - if (d.cookie.contains('pass_enabled=') || !(this.isEnabled = !!$.id('captchaFormPart'))) { - return; - } - if ($.id('recaptcha_challenge_field_holder')) { - return this.ready(); - } else { - if (MutationObserver) { - observer = new MutationObserver(onMutationObserver = function() { - if ($.id('recaptcha_challenge_field_holder')) { - _this.ready(); - return observer.disconnect(); - } - }); - return observer.observe($.id('recaptcha_widget_div'), { - childList: true, - subtree: true - }); - } else { - return $.on($.id('recaptcha_widget_div'), 'DOMNodeInserted', this.ready); - } - } - }, - ready: function() { - var observer, - _this = this; - - if (this.challenge = $.id('recaptcha_challenge_field_holder')) { - $.off($.id('recaptcha_widget_div'), 'DOMNodeInserted', this.onready); - delete this.onready; - } else { - return; - } - $.addClass(QR.el, 'captcha'); - $.after($('.textarea', QR.el), $.el('div', { - className: 'captchaimg', - title: 'Reload', - innerHTML: '' - })); - $.after($('.captchaimg', QR.el), $.el('div', { - className: 'captchainput', - innerHTML: '' - })); - this.img = $('.captchaimg > img', QR.el); - this.input = $('.captchainput > input', QR.el); - $.on(this.img.parentNode, 'click', this.reload); - $.on(this.input, 'keydown', this.keydown); - $.on(this.input, 'focus', function() { - return QR.el.classList.add('focus'); - }); - $.on(this.input, 'blur', function() { - return QR.el.classList.remove('focus'); - }); - if (MutationObserver) { - observer = new MutationObserver(function() { - return _this.load(); - }); - observer.observe(this.challenge, { - childList: true, - subtree: true - }); - } else { - $.on(this.challenge, 'DOMNodeInserted', function() { - return _this.load(); - }); - } - $.sync('captchas', function(arr) { - return _this.count(arr.length); - }); - this.count($.get('captchas', []).length); - return this.reload(); - }, - save: function() { - var captcha, captchas, response; - - if (!(response = this.input.value)) { - return; - } - captchas = $.get('captchas', []); - while ((captcha = captchas[0]) && captcha.time < Date.now()) { - captchas.shift(); - } - captchas.push({ - challenge: this.challenge.firstChild.value, - response: response, - time: this.timeout - }); - $.set('captchas', captchas); - this.count(captchas.length); - return this.reload(); - }, - load: function() { - var challenge; - - this.timeout = Date.now() + 4 * $.MINUTE; - challenge = this.challenge.firstChild.value; - this.img.alt = challenge; - this.img.src = "//www.google.com/recaptcha/api/image?c=" + challenge; - return this.input.value = null; - }, - count: function(count) { - this.input.placeholder = (function() { - switch (count) { - case 0: - return 'Verification (Shift + Enter to cache)'; - case 1: - return 'Verification (1 cached captcha)'; - default: - return "Verification (" + count + " cached captchas)"; - } - })(); - return this.input.alt = count; - }, - reload: function(focus) { - $.globalEval('Recaptcha.reload("t")'); - if (focus) { - return QR.captcha.input.focus(); - } - }, - keydown: function(e) { - var c; - - c = QR.captcha; - if (e.keyCode === 8 && !c.input.value) { - c.reload(); - } else if (e.keyCode === 13 && e.shiftKey) { - c.save(); - } else { - return; - } - return e.preventDefault(); - } - }, - dialog: function() { - var i, id, mimeTypes, name, size, spoiler, ta, thread, threads, _i, _j, _len, _len1, _ref, _ref1; - - QR.el = UI.dialog('qr', 'bottom: 0; right: 0;', '\ -
\ - \ - × \ -
\ -
\ -
\ -
\ -
+
\ -
\ -
\ - \ -
\ -
'); - if (Conf['Remember QR size']) { - $.on(ta = $('textarea', QR.el), 'mouseup', function() { - return $.set('QR.size', this.style.cssText); - }); - ta.style.cssText = $.get('QR.size', ''); - } - QR.autohide = $('#autohide', QR.el); - mimeTypes = $('ul.rules').firstElementChild.textContent.trim().match(/: (.+)/)[1].toLowerCase().replace(/\w+/g, function(type) { - switch (type) { - case 'jpg': - return 'image/jpeg'; - case 'pdf': - return 'application/pdf'; - case 'swf': - return 'application/x-shockwave-flash'; - default: - return "image/" + type; - } - }); - QR.mimeTypes = mimeTypes.split(', '); - QR.mimeTypes.push(''); - QR.fileEl = $('input[type=file]', QR.el); - QR.fileEl.max = $('input[name=MAX_FILE_SIZE]').value; - if ($.engine !== 'presto') { - QR.fileEl.accept = mimeTypes; - } - QR.warning = $('.warning', QR.el); - QR.spoiler = !!$('input[name=spoiler]'); - spoiler = $('#spoilerLabel', QR.el); - spoiler.hidden = !QR.spoiler; - QR.charaCounter = $('#charCount', QR.el); - ta = $('textarea', QR.el); - if (!g.REPLY) { - threads = ''; - _ref = $$('.thread'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - thread = _ref[_i]; - id = thread.id.slice(1); - threads += ""; - } - QR.threadSelector = g.BOARD === 'f' ? $('select[name=filetag]').cloneNode(true) : $.el('select', { - innerHTML: threads, - title: 'Create a new thread / Reply to a thread' - }); - QR.threadSelector.className = null; - $.prepend($('#threadselect', QR.el), QR.threadSelector); - $.on(QR.threadSelector, 'mousedown', function(e) { - return e.stopPropagation(); - }); - } - i = 0; - size = QR.fileEl.max; - while (i++ < 2) { - size /= 1024; - } - $.on(QR.fileEl, 'change', $.on(QR.fileEl, 'change', QR.fileInput)); - $.on(QR.fileEl, 'click', function(e) { - if (e.shiftKey) { - return QR.selected.rmFile() || e.preventDefault(); - } - }); - $.on(QR.autohide, 'change', QR.toggleHide); - $.on($('.close', QR.el), 'click', QR.close); - $.on($('#dump', QR.el), 'click', function() { - return $.toggleClass(QR.el, 'dump'); - }); - $.on($('#addReply', QR.el), 'click', function() { - return new QR.reply().select(); - }); - $.on($('form', QR.el), 'submit', QR.submit); - $.on(ta, 'input', function() { - return QR.selected.el.lastChild.textContent = this.value; - }); - $.on(ta, 'input', QR.characterCount); - $.on(spoiler.firstChild, 'change', function() { - return $('input', QR.selected.el).click(); - }); - $.on(QR.warning, 'click', QR.cleanError); - new QR.reply().select(); - _ref1 = ['name', 'email', 'sub', 'com']; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - name = _ref1[_j]; - $.on($("[name=" + name + "]", QR.el), 'focus', function() { - return QR.el.classList.add('focus'); - }); - $.on($("[name=" + name + "]", QR.el), 'blur', function() { - return QR.el.classList.remove('focus'); - }); - $.on($("[name=" + name + "]", QR.el), 'input', function() { - var _ref2; - - QR.selected[this.name] = this.value; - if (QR.cooldown.auto && QR.selected === QR.replies[0] && (0 < (_ref2 = QR.cooldown.seconds) && _ref2 <= 5)) { - return QR.cooldown.auto = false; - } - }); - $.on(QR.fileEl, 'focus', function() { - return QR.el.classList.add('focus'); - }); - $.on(QR.fileEl, 'blur', function() { - return QR.el.classList.remove('focus'); - }); - } - QR.status.input = $('input[type=submit]', QR.el); - QR.status(); - QR.cooldown.init(); - QR.captcha.init(); - $.add(d.body, QR.el); - return $.event(QR.el, new CustomEvent('QRDialogCreation', { - bubbles: true - })); - }, - submit: function(e) { - var callbacks, captcha, captchas, challenge, err, filetag, m, opts, post, reply, response, textOnly, threadID; - - if (e != null) { - e.preventDefault(); - } - if (QR.cooldown.seconds) { - QR.cooldown.auto = !QR.cooldown.auto; - QR.status(); - return; - } - QR.abort(); - reply = QR.replies[0]; - if (!g.REPLY && g.BOARD === 'f') { - filetag = QR.threadSelector.value; - threadID = 'new'; - } else { - threadID = g.THREAD_ID || QR.threadSelector.value; - } - if (threadID === 'new') { - threadID = null; - if (['vg', 'q'].contains(g.BOARD) && !reply.sub) { - err = 'New threads require a subject.'; - } else if (!(reply.file || (textOnly = !!$('input[name=textonly]', $.id('postForm'))))) { - err = 'No file selected.'; - } else if (g.BOARD === 'f' && filetag === '9999') { - err = 'Invalid tag specified.'; - } - } else if (!(reply.com || reply.file)) { - err = 'No file selected.'; - } - if (QR.captcha.isEnabled && !err) { - captchas = $.get('captchas', []); - while ((captcha = captchas[0]) && captcha.time < Date.now()) { - captchas.shift(); - } - if (captcha = captchas.shift()) { - challenge = captcha.challenge; - response = captcha.response; - } else { - challenge = QR.captcha.img.alt; - if (response = QR.captcha.input.value) { - QR.captcha.reload(); - } - } - $.set('captchas', captchas); - QR.captcha.count(captchas.length); - if (!response) { - err = 'No valid captcha.'; - } else { - response = response.trim(); - if (!/\s/.test(response)) { - response = "" + response + " " + response; - } - } - } - if (err) { - QR.cooldown.auto = false; - QR.status(); - QR.error(err); - return; - } - QR.cleanError(); - QR.cooldown.auto = QR.replies.length > 1; - if (Conf['Auto Hide QR'] && !QR.cooldown.auto && Conf['Post Form Style'] === "float") { - QR.hide(); - } - if (!QR.cooldown.auto && $.x('ancestor::div[@id="qr"]', d.activeElement)) { - d.activeElement.blur(); - } - QR.status({ - progress: '...' - }); - post = { - resto: threadID, - name: reply.name, - email: reply.email, - sub: reply.sub, - com: Conf['Markdown'] ? Markdown.format(reply.com) : reply.com, - upfile: reply.file, - filetag: filetag, - spoiler: reply.spoiler, - textonly: textOnly, - mode: 'regist', - pwd: (m = d.cookie.match(/4chan_pass=([^;]+)/)) ? decodeURIComponent(m[1]) : $('input[name=pwd]').value, - recaptcha_challenge_field: challenge, - recaptcha_response_field: response - }; - callbacks = { - onload: function() { - return QR.response(this.response); - }, - onerror: function() { - QR.cooldown.auto = false; - QR.status(); - QR.error($.el('a', { - href: '//www.4chan.org/banned', - target: '_blank', - textContent: 'Connection error, or you are banned.' - })); - if (Conf['Check for Bans']) { - $["delete"]('lastBanCheck'); - return BanChecker.init(); - } - } - }; - opts = { - form: $.formData(post), - upCallbacks: { - onload: function() { - return QR.status({ - progress: '...' - }); - }, - onprogress: function(e) { - return QR.status({ - progress: "" + (Math.round(e.loaded / e.total * 100)) + "%" - }); - } - } - }; - return QR.ajax = $.ajax($.id('postForm').parentNode.action, callbacks, opts); - }, - response: function(html) { - var ban, board, doc, el, err, key, persona, postID, reply, threadID, _, _ref; - - doc = d.implementation.createHTMLDocument(''); - doc.documentElement.innerHTML = html; - if (ban = $('.banType', doc)) { - board = $('.board', doc).innerHTML; - err = $.el('span', ban.textContent.toLowerCase() === 'banned' ? (Conf['Check for Bans'] ? ($["delete"]('lastBanCheck'), BanChecker.init()) : void 0, err.innerHTML = "You are banned on " + board + "! ;_;
\nClick here to see the reason.") : err.innerHTML = "You were issued a warning on " + board + " as " + ($('.nameBlock', doc).innerHTML) + ".
\nReason: " + ($('.reason', doc).innerHTML)); - } else if (err = doc.getElementById('errmsg')) { - if (el = $('a', err)) { - el.target = '_blank'; - } - } else if (doc.title !== 'Post successful!') { - err = 'Connection error with sys.4chan.org.'; - } - if (err) { - if (/captcha|verification/i.test(err.textContent) || err === 'Connection error with sys.4chan.org.') { - if (/mistyped/i.test(err.textContent)) { - err.textContent = 'You seem to have mistyped the CAPTCHA.'; - } - QR.cooldown.auto = QR.captcha.isEnabled ? !!$.get('captchas', []).length : err === 'Connection error with sys.4chan.org.' ? true : false; - QR.cooldown.set({ - delay: 2 - }); - } else { - QR.cooldown.auto = false; - } - QR.status(); - QR.error(err); - return; - } - reply = QR.replies[0]; - persona = $.get('persona', { - global: {} - }); - if (!persona[key = Conf['Per Board Persona'] ? g.BOARD : 'global']) { - persona[key] = JSON.parse(JSON.stringify(persona.global)); - } - persona[key] = { - name: reply.name, - email: !Conf["Remember Sage"] && /^sage$/.test(reply.email) ? /^sage$/.test(persona[key].email) ? null : persona[key].email : reply.email, - sub: Conf['Remember Subject'] ? reply.sub : null - }; - $.set('persona', persona); - _ref = doc.body.lastChild.textContent.match(/thread:(\d+),no:(\d+)/), _ = _ref[0], threadID = _ref[1], postID = _ref[2]; - Updater.postID = postID; - if (!MarkOwn.posts) { - MarkOwn.posts = $.get('ownedPosts', {}); - } - MarkOwn.posts[postID] = Date.now(); - $.set('ownedPosts', MarkOwn.posts); - $.event(QR.el, new CustomEvent('QRPostSuccessful', { - bubbles: true, - detail: { - threadID: threadID, - postID: postID - } - })); - if ($.get('isBanned')) { - if (BanChecker.el) { - $.rm(BanChecker.el); - delete BanChecker.el; - } - $["delete"]('isBanned'); - } - QR.cooldown.set({ - post: reply, - isReply: threadID !== '0' - }); - if (threadID === '0') { - location.pathname = "/" + g.BOARD + "/res/" + postID; - } else { - QR.cooldown.auto = QR.replies.length > 1; - if (Conf['Open Reply in New Tab'] && !g.REPLY && !QR.cooldown.auto) { - $.open("//boards.4chan.org/" + g.BOARD + "/res/" + threadID + "#p" + postID); - } - } - if (Conf['Persistent QR'] || QR.cooldown.auto) { - reply.rm(); - } else { - QR.close(); - } - QR.status(); - return QR.resetFileInput(); - }, - abort: function() { - var _ref; - - if ((_ref = QR.ajax) != null) { - _ref.abort(); - } - delete QR.ajax; - return QR.status(); - } - }; - - QuoteBacklink = { - init: function() { - var format; - - format = Conf['backlink'].replace(/%id/g, "' + id + '"); - this.funk = Function('id', "return '" + format + "'"); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var a, container, el, link, nodes, owned, qid, quote, quotes, _i, _len, _ref, _ref1; - - if (post.isInlined) { - return; - } - quotes = {}; - _ref = post.quotes; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - if (quote.parentNode.parentNode.className === 'capcodeReplies') { - break; - } - if (quote.hostname === 'boards.4chan.org' && !/catalog$/.test(quote.pathname) && (qid = (_ref1 = quote.hash) != null ? _ref1.slice(2) : void 0)) { - quotes[qid] = true; - } - } - a = $.el('a', { - href: "/" + g.BOARD + "/res/" + post.threadID + "#p" + post.ID, - className: post.el.hidden ? 'filtered backlink' : 'backlink', - textContent: QuoteBacklink.funk(post.ID) - }); - if (Conf['Mark Owned Posts']) { - if (MarkOwn.posts[post.ID]) { - $.addClass(a, 'ownreply'); - a.textContent += " (You)"; - owned = true; - } - } - for (qid in quotes) { - if (!(el = $.id("pi" + qid)) || !Conf['OP Backlinks'] && /\bop\b/.test(el.parentNode.className)) { - continue; - } - link = a.cloneNode(true); - nodes = $.nodes([$.tn(' '), link]); - if (Conf['Quote Preview']) { - $.on(link, 'mouseover', QuotePreview.mouseover); - } - if (Conf['Quote Inline']) { - $.on(link, 'click', QuoteInline.toggle); - if (Conf['Quote Hash Navigation']) { - QuoteInline.qiQuote(link); - } - } - if (!(container = $.id("blc" + qid))) { - $.addClass(el.parentNode, 'quoted'); - if (owned) { - $.addClass(el.parentNode, 'youQuoted'); - } - container = $.el('span', { - className: 'container', - id: "blc" + qid - }); - $.add(el, container); - } - $.add(container, nodes); - } - } - }; - - QuoteCT = { - init: function() { - ExpandComment.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var path, quote, _i, _len, _ref; - - if (post.isInlined && !post.isCrosspost) { - return; - } - _ref = post.quotes; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - if (!(quote.hash && quote.hostname === 'boards.4chan.org' && !/catalog$/.test(quote.pathname))) { - continue; - } - path = quote.pathname.split('/'); - if (path[1] === g.BOARD && path[3] !== post.threadID) { - $.add(quote, $.tn('\u00A0(Cross-thread)')); - } - } - } - }; - - QuoteInline = { - init: function() { - this.callbacks.push(this.node); - ExpandComment.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - callbacks: [], - cb: function(post, root) { - var callback, _i, _len, _ref; - - post.isCrosspost = post.isInlined = true; - post.threadID = $.x('ancestor::div[parent::div[@class="board"]]', root).id.match(/\d+$/)[0]; - _ref = Main.callbacks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - callback = _ref[_i]; - callback(post); - } - }, - cb2: function(post) { - var callback, _i, _len, _ref; - - post.isInlined = true; - _ref = QuoteInline.callbacks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - callback = _ref[_i]; - callback(post); - } - }, - node: function(post) { - var quote, _i, _j, _len, _len1, _ref, _ref1; - - _ref = post.quotes; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - if (!(quote.hash && quote.hostname === 'boards.4chan.org' && !/catalog$/.test(quote.pathname) || /\bdeadlink\b/.test(quote.className))) { - continue; - } - $.on(quote, 'click', QuoteInline.toggle); - if (Conf['Quote Hash Navigation'] && !post.isInlined) { - QuoteInline.qiQuote(quote); - } - } - _ref1 = post.backlinks; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - quote = _ref1[_j]; - $.on(quote, 'click', QuoteInline.toggle); - } - }, - qiQuote: function(quote) { - return $.after(quote, [ - $.tn(' '), $.el('a', { - className: 'qiQuote', - textContent: '#', - href: quote.href - }) - ]); - }, - toggle: function(e) { - var id; - - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) { - return; - } - e.preventDefault(); - id = this.dataset.id || this.hash.slice(2); - if (/\binlined\b/.test(this.className)) { - QuoteInline.rm(this, id); - } else { - if ($.x("ancestor::div[contains(@id,'p" + id + "')]", this)) { - return; - } - QuoteInline.add(this, id); - } - return $.toggleClass(this, 'inlined'); - }, - add: function(q, id) { - var board, el, i, inline, isBacklink, path, postID, root, threadID; - - if (q.host === 'boards.4chan.org') { - path = q.pathname.split('/'); - board = path[1]; - threadID = path[3]; - postID = id; - } else { - board = q.dataset.board; - threadID = 0; - postID = q.dataset.id; - } - el = board === g.BOARD ? $.id("p" + postID) : false; - inline = $.el('div', { - id: "i" + postID, - className: el ? 'inline' : 'inline crosspost' - }); - root = (isBacklink = /\bbacklink\b/.test(q.className)) ? q.parentNode : $.x('ancestor-or-self::*[parent::blockquote][1]', q); - if (Conf['Quote Hash Navigation'] && !isBacklink && root === q) { - $.after(root.nextElementSibling, inline); - } else { - $.after(root, inline); - } - Get.post(board, threadID, postID, inline, QuoteInline.cb, QuoteInline.cb2); - if (!el) { - return; - } - if (isBacklink && Conf['Forward Hiding']) { - $.addClass(el.parentNode, 'forwarded'); - ++el.dataset.forwarded || (el.dataset.forwarded = 1); - } - if ((i = Unread.replies.indexOf(el)) !== -1) { - Unread.replies.splice(i, 1); - Unread.update(true); - } - if (Conf['Color user IDs'] && ['b', 'q', 'soc'].contains(board)) { - return setTimeout(function() { - return $.rmClass($('.reply.highlight', inline), 'highlight'); - }); - } - }, - rm: function(q, id) { - var div, inlined, _i, _len, _ref; - - div = $.x("following::div[@id='i" + id + "']", q); - $.rm(div); - if (!Conf['Forward Hiding']) { - return; - } - _ref = $$('.backlink.inlined', div); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - inlined = _ref[_i]; - div = $.id(inlined.hash.slice(1)); - if (!--div.dataset.forwarded) { - $.rmClass(div.parentNode, 'forwarded'); - } - } - if (/\bbacklink\b/.test(q.className)) { - div = $.id("p" + id); - if (!--div.dataset.forwarded) { - return $.rmClass(div.parentNode, 'forwarded'); - } - } - } - }; - - QuoteOP = { - init: function() { - ExpandComment.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var quote, _i, _len, _ref; - - if (post.isInlined && !post.isCrosspost) { - return; - } - _ref = post.quotes; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - if (quote.hash.slice(2) === post.threadID) { - $.add(quote, $.tn('\u00A0(OP)')); - } - } - } - }; - - QuotePreview = { - init: function() { - QuoteInline.callbacks.push(this.node); - ExpandComment.callbacks.push(this.node); - Main.callbacks.push(this.node); - return $.ready(function() { - return $.add(d.body, QuotePreview.el = $.el('div', { - id: 'qp', - className: 'reply dialog' - })); - }); - }, - callbacks: [], - callback: function(node) { - var callback, _i, _len, _ref; - - _ref = QuotePreview.callbacks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - callback = _ref[_i]; - callback(node); - } - }, - node: function(post) { - var quote, _i, _j, _len, _len1, _ref, _ref1; - - _ref = post.quotes; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - if (!(quote.hostname === 'boards.4chan.org' && quote.hash && !/catalog$/.test(quote.pathname) || /\bdeadlink\b/.test(quote.className))) { - continue; - } - $.on(quote, 'mouseover', QuotePreview.mouseover); - } - _ref1 = post.backlinks; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - quote = _ref1[_j]; - $.on(quote, 'mouseover', QuotePreview.mouseover); - } - }, - mouseover: function(e) { - var board, child, children, el, path, postID, qp, quote, quoterID, threadID, _conf, _i, _j, _len, _len1, _ref; - - if (UI.el || /\binlined\b/.test(this.className)) { - return; - } - qp = QuotePreview.el; - if (children = qp.children) { - for (_i = 0, _len = children.length; _i < _len; _i++) { - child = children[_i]; - $.rm(child); - } - } - if (this.host === 'boards.4chan.org') { - path = this.pathname.split('/'); - board = path[1]; - threadID = path[3]; - postID = this.hash.slice(2); - } else { - board = this.dataset.board; - threadID = 0; - postID = this.dataset.id; - } - UI.el = qp; - UI.hover(e); - Get.post(board, threadID, postID, qp, function(post) { - Main.prettify(post.blockquote); - post.isArchived = qp.className.contains('archivedPost'); - return QuotePreview.callback(post); - }); - $.on(this, 'mousemove', UI.hover); - $.on(this, 'mouseout click', QuotePreview.mouseout); - _conf = Conf; - if (el = $.id("p" + postID)) { - _conf = Conf; - if (_conf['Quote Highlighting']) { - if (/\bop\b/.test(el.className)) { - $.addClass(el.parentNode, 'qphl'); - } else { - $.addClass(el, 'qphl'); - } - } - quoterID = $.x('ancestor::*[@id][1]', this).id.match(/\d+$/)[0]; - _ref = $$('.quotelink, .backlink', qp); - for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { - quote = _ref[_j]; - if (quote.hash.slice(2) === quoterID) { - $.addClass(quote, 'forwardlink'); - } - } - } - }, - mouseout: function(e) { - var el, hash; - - delete UI.el; - $.rm(QuotePreview.el.firstChild); - $.rmClass(QuotePreview.el, 'warning'); - if ((hash = this.hash) && (el = $.id(hash.slice(1)))) { - $.rmClass(el.parentNode, 'qphl'); - $.rmClass(el, 'qphl'); - } - $.off(this, 'mousemove', UI.hover); - return $.off(this, 'mouseout click', QuotePreview.mouseout); - } - }; - - Quotify = { - init: function() { - QuotePreview.callbacks.push(this.node); - ExpandComment.callbacks.push(this.node); - return Main.callbacks.push(this.node); - }, - node: function(post) { - var a, board, deadlink, id, m, postBoard, quote, _i, _len, _ref; - - if (post.isInlined && !post.isCrosspost) { - return; - } - _ref = $$('.deadlink', post.blockquote); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - deadlink = _ref[_i]; - quote = deadlink.textContent; - a = $.el('a', { - textContent: "" + quote + "\u00A0(Dead)" - }); - if (!(id = quote.match(/\d+$/))) { - continue; - } - id = id[0]; - if (m = quote.match(/^>>>\/([a-z\d]+)/)) { - board = m[1]; - } else if (postBoard) { - board = postBoard; - } else { - board = postBoard = $('a[title="Highlight this post"]', post.el).pathname.split('/')[1]; - } - if (board === g.BOARD && $.id("p" + id)) { - a.href = "#p" + id; - a.className = 'quotelink'; - } else { - a.href = Redirect.to({ - board: board, - threadID: 0, - postID: id - }); - a.className = 'deadlink'; - a.target = '_blank'; - if (Redirect.post(board, id)) { - $.addClass(a, 'quotelink'); - a.setAttribute('data-board', board); - a.setAttribute('data-id', id); - } - } - $.replace(deadlink, a); - } - } - }; - - Style = { - init: function() { - this.agent = { - 'gecko': '-moz-', - 'webkit': '-webkit-', - 'presto': '-o-' - }[$.engine]; - if (d.head) { - return this.wrapper(); - } - return this.observe(); - }, - cleanup: function() { - delete Style.init; - delete Style.observe; - delete Style.wrapper; - return delete Style.cleanup; - }, - observe: function() { - var onMutationObserver; - - if (MutationObserver) { - Style.observer = new MutationObserver(onMutationObserver = this.wrapper); - return Style.observer.observe(d, { - childList: true, - subtree: true - }); - } else { - return $.on(d, 'DOMNodeInserted', this.wrapper); - } - }, - wrapper: function() { - if (d.head) { - Style.addStyle(); - if (Style.observer) { - Style.observer.disconnect(); - } else { - $.off(d, 'DOMNodeInserted', Style.wrapper); - } - return Style.cleanup(); - } - }, - emoji: function(position) { - var css, icon, margin, name, _conf, _i, _len, _ref; - - _conf = Conf; - css = []; - margin = "margin-" + (position === "before" ? "right" : "left") + ": 5px;"; - _ref = Emoji.icons; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - icon = _ref[_i]; - name = icon[0]; - css[css.length] = "a.useremail[href*='" + name + "']:last-of-type::" + position + ",\na.useremail[href*='" + (name.toLowerCase()) + "']:last-of-type::" + position + ",\na.useremail[href*='" + (name.toUpperCase()) + "']:last-of-type::" + position + " {\ncontent: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA" + icon[1] + "');\nvertical-align: top;\n" + margin + "\n}\n"; - } - return css.join(""); - }, - addStyle: function() { - var agent; - - agent = Style.agent; - return Style.css = $.addStyle("/* dialog styling */\nhr.abovePostForm {\n width: 100% !important;\n}\n.dialog.reply {\n display: block;\n border: 1px solid rgba(0,0,0,.25);\n padding: 0;\n}\n.move {\n cursor: move;\n}\nlabel, .favicon, .export, .import {\n cursor: pointer;\n}\na[href=\"javascript:;\"] {\n text-decoration: none;\n}\n.warning:not(:empty) {\n color: rgb(185, 74, 72);\n background: rgb(242, 222, 222);\n border: 1px solid rgba(238, 50, 50,0.3);\n padding: 3px;\n text-align: center;\n}\n\n#options .warning {\n width: 98%;\n border-radius: 4px;\n}\n\n.warning>code {\n border: 1px solid #E5D3D3;\n}\n\n.hide_thread_button:not(.hidden_thread) {\n float: left;\n}\n\n.thread > .hidden_thread ~ *,\n.hidden .sideArrows,\n[hidden],\n#globalMessage.hidden,\n#content > [name=tab]:not(:checked) + div,\n#updater:not(:hover) > :not(.move),\n.autohide:not(:hover) > form,\n#qp input, .forwarded,\n.fappeTyme > #delform .noFile {\n display: none !important;\n}\n\n.menu_button {\n display: inline-block;\n}\n.menu_button > span {\n border-top: .5em solid;\n border-right: .3em solid transparent;\n border-left: .3em solid transparent;\n display: inline-block;\n margin: 2px;\n vertical-align: middle;\n}\n#menu {\n position: absolute;\n outline: none;\n}\n.entry {\n border-bottom: 1px solid rgba(0, 0, 0, .25);\n cursor: pointer;\n display: block;\n outline: none;\n padding: 3px 7px;\n position: relative;\n text-decoration: none;\n white-space: nowrap;\n}\n.entry:last-child {\n border: none;\n}\n.focused.entry {\n background: rgba(255, 255, 255, .33);\n}\n.entry.hasSubMenu {\n padding-right: 1.5em;\n}\n.hasSubMenu::after {\n content: \"\";\n border-left: .5em solid;\n border-top: .3em solid transparent;\n border-bottom: .3em solid transparent;\n display: inline-block;\n margin: .3em;\n position: absolute;\n right: 3px;\n}\n.hasSubMenu:not(.focused) > .subMenu {\n display: none;\n}\n.subMenu {\n position: absolute;\n left: 100%;\n top: 0;\n margin-top: -1px;\n}\nh1,\nh2 {\n text-align: center;\n}\n#qr > .move {\n min-width: 300px;\n overflow: hidden;\n box-sizing: border-box;\n " + agent + "box-sizing: border-box;\n padding: 0 2px;\n}\n#threadselect,\n#qr > .move > span {\n float: right;\n padding: 0 2px;\n}\n#autohide, .close, #qr select, #dump, .remove, .captchaimg, #qr div.warning {\n cursor: pointer;\n}\n#qr select,\n#qr > form {\n margin: 0;\n}\n#dump {\n background: " + agent + "linear-gradient(#EEE, #CCC);\n background: linear-gradient(#EEE, #CCC);\n width: 10%;\n}\n.gecko #dump {\n padding: 1px 0 2px;\n}\n#dump:hover, #dump:focus {\n background: " + agent + "linear-gradient(#FFF, #DDD);\n background: linear-gradient(#FFF, #DDD);\n}\n#dump:active, .dump #dump:not(:hover):not(:focus) {\n background: " + agent + "linear-gradient(#CCC, #DDD);\n background: linear-gradient(#CCC, #DDD);\n}\n#qp:empty,\n#qr:not(.dump) #replies, .dump > form > label {\n display: none;\n}\n#replies {\n display: block;\n height: 100px;\n position: relative;\n " + agent + "user-select: none;\n user-select: none;\n}\n#replies > div {\n counter-reset: thumbnails;\n top: 0; right: 0; bottom: 0; left: 0;\n margin: 0; padding: 0;\n overflow: hidden;\n position: absolute;\n white-space: pre;\n}\n#replies > div:hover {\n bottom: -10px;\n overflow-x: auto;\n z-index: 1;\n}\n.thumbnail {\n background-color: rgba(0,0,0,.2) !important;\n background-position: 50% 20% !important;\n background-size: cover !important;\n border: 1px solid #666;\n box-sizing: border-box;\n " + agent + "box-sizing: border-box;\n cursor: move;\n display: inline-block;\n height: 90px; width: 90px;\n margin: 5px; padding: 2px;\n opacity: .5;\n outline: none;\n overflow: hidden;\n position: relative;\n text-shadow: 0 1px 1px #000;\n " + agent + "transition: opacity .25s ease-in-out;\n transition: opacity .25s ease-in-out;\n vertical-align: top;\n}\n.thumbnail:hover, .thumbnail:focus {\n opacity: .9;\n}\n.thumbnail#selected {\n opacity: 1;\n}\n.thumbnail::before {\n counter-increment: thumbnails;\n content: counter(thumbnails);\n color: #FFF;\n font-weight: 700;\n padding: 3px;\n position: absolute;\n top: 0;\n right: 0;\n text-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.thumbnail.drag {\n box-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.thumbnail.over {\n border-color: #FFF;\n}\n.thumbnail > span {\n color: #FFF;\n}\n.remove {\n background: none;\n color: #E00;\n font-weight: 700;\n padding: 3px;\n}\n.remove:hover::after {\n content: \" Remove\";\n}\n.thumbnail > label {\n background: rgba(0,0,0,.5);\n color: #FFF;\n right: 0; bottom: 0; left: 0;\n position: absolute;\n text-align: center;\n}\n.thumbnail > label > input {\n margin: 0;\n}\n#addReply {\n color: #333;\n font-size: 3.5em;\n line-height: 100px;\n}\n#addReply:hover, #addReply:focus {\n color: #000;\n}\n.field {\n border: 1px solid #CCC;\n box-sizing: border-box;\n " + agent + "box-sizing: border-box;\n color: #333;\n font: 13px sans-serif;\n margin: 0;\n padding: 2px 4px 3px;\n " + agent + "transition: color .25s, border .25s;\n transition: color .25s, border .25s;\n}\n.field:" + agent + "placeholder,\n.field:hover:" + agent + "placeholder {\n color: #AAA;\n}\n.field:hover, .field:focus {\n border-color: #999;\n color: #000;\n outline: none;\n}\n.userInfo > .field:not(#dump) {\n width: 95px;\n min-width: 30%;\n max-width: 30%;\n}\n#qr textarea.field {\n display: " + agent + "box;\n min-height: 160px;\n min-width: 100%;\n}\n#qr.captcha textarea.field {\n min-height: 120px;\n}\n.textarea {\n position: relative;\n}\n#charCount {\n color: #000;\n background: hsla(0, 0%, 100%, .5);\n font-size: 8pt;\n margin: 1px;\n position: absolute;\n bottom: 0;\n right: 0;\n pointer-events: none;\n}\n#charCount.warning {\n color: red;\n}\n.captchainput > .field {\n min-width: 100%;\n}\n.captchaimg {\n background: #FFF;\n outline: 1px solid #CCC;\n outline-offset: -1px;\n text-align: center;\n}\n.captchaimg > img {\n display: block;\n height: 57px;\n width: 300px;\n}\n#qr [type=file] {\n margin: 1px 0;\n width: 70%;\n}\n#qr [type=submit] {\n margin: 1px 0;\n padding: 1px; /* not Gecko */\n width: 30%;\n}\n.gecko #qr [type=submit] {\n padding: 0 1px; /* Gecko does not respect box-sizing: border-box */\n}\n#spoilerLabel:not([hidden]) {\n display: block;\n}\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull {\n display: none;\n}\n.fitwidth img[data-md5] + img {\n max-width: 100%;\n}\n.gecko .fitwidth img[data-md5] + img,\n.presto .fitwidth img[data-md5] + img {\n width: 100%;\n}\n#qr, #qp, #updater, #stats, #ihover, #overlay, #navlinks, #mouseover {\n position: fixed;\n}\n#ihover {\n max-height: 97%;\n max-width: 75%;\n padding-bottom: 18px;\n}\n#navlinks {\n font-size: 16px;\n top: 25px;\n right: 5px;\n}\nbody {\n box-sizing: border-box;\n " + agent + "box-sizing: border-box;\n}\nbody.unscroll {\n overflow: hidden;\n}\n#mouseover {\n z-index: 2;\n}\n#overlay {\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n text-align: center;\n background: none repeat scroll 0% 0% rgba(25, 25, 25, 0.6);\n z-index: 1;\n}\n#overlay::after {\n content: \"\";\n display: inline-block;\n height: 100%;\n vertical-align: middle;\n}\n#options {\n box-sizing: border-box;\n " + agent + "box-sizing: border-box;\n display: inline-block;\n padding: 5px;\n position: relative;\n text-align: left;\n vertical-align: middle;\n width: 900px;\n max-width: 100%;\n height: 600px;\n max-height: 100%;\n box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.4); \n border-radius: 4px;\n}\n\n#credits {\n float: right;\n}\n#options ul {\n padding: 0;\n}\n#options fieldset {\n border: 1px solid rgb(150,150,150);\n border-radius: 3px;\n}\n#options legend {\n font-weight: 700;\n}\n#options article li {\n margin: 10px 0 10px 2em;\n}\n#options code {\n background: hsla(0, 0%, 100%, .5);\n color: #000;\n padding: 0 2px;\n}\n#selected_tab {\n font-weight: 700;\n}\n.rice_tab, .main_tab {\n margin-right: 5px;\n}\n.rice_tab {\n margin-top: -15px;\n}\n#content {\n overflow: auto;\n position: absolute;\n top: 2.5em;\n right: 5px;\n bottom: 5px;\n left: 5px;\n}\n#content textarea {\n font-family: monospace;\n min-height: 350px;\n resize: vertical;\n width: 100%;\n}\n.imp-exp .placeholder:not(:empty) {\n position: absolute;\n top:5px;\n right:0px;\n left:0px;\n text-align:center;\n width: 200px;\n margin: auto;\n}\n.imp-exp-result:empty {\n display: none;\n}\n.imp-exp-result {\n position: absolute;\n top:5px;\n right:0px;\n left:0px;\n width:200px;\n margin:auto;\n text-align: center;\n color:red;\n}\n\n#updater {\n text-align: right;\n}\n#updater:not(:hover) {\n border: none;\n background: transparent;\n}\n#updater input[type=number] {\n width: 4em;\n}\n.new {\n background: lime;\n}\n\n#watcher {\n padding-bottom: 5px;\n position: absolute;\n overflow: hidden;\n white-space: nowrap;\n}\n#watcher:not(:hover) {\n max-height: 220px;\n}\n#watcher > div {\n max-width: 200px;\n overflow: hidden;\n padding-left: 5px;\n padding-right: 5px;\n text-overflow: ellipsis;\n}\n#watcher > .move {\n padding-top: 5px;\n text-decoration: underline;\n}\n\n#qp {\n padding: 2px 2px 5px;\n}\n#qp .post {\n border: none;\n margin: 0;\n padding: 0;\n}\n#qp img {\n max-height: 300px;\n max-width: 500px;\n}\n.qphl {\n box-shadow: 0 0 0 2px rgba(216, 94, 49, .7);\n}\n.quotelink.deadlink {\n text-decoration: underline !important;\n}\n.deadlink:not(.quotelink) {\n text-decoration: none !important;\n}\n.inlined {\n opacity: .5;\n}\n.inline {\n background-color: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(128, 128, 128, 0.5);\n display: table;\n margin: 2px;\n padding: 2px;\n}\n.inline .post {\n background: none;\n border: none;\n margin: 0;\n padding: 0;\n}\ndiv.opContainer {\n display: block !important;\n}\n.opContainer.filter_highlight {\n box-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.opContainer.filter_highlight.qphl {\n box-shadow: inset 5px 0 rgba(255, 0, 0, .5),\n 0 0 0 2px rgba(216, 94, 49, .7);\n}\n.filter_highlight > .reply {\n box-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n.filter_highlight > .reply.qphl {\n box-shadow: -5px 0 rgba(255, 0, 0, .5),\n 0 0 0 2px rgba(216, 94, 49, .7)\n}\n.filtered,\n.quotelink.filtered {\n text-decoration: underline;\n text-decoration: line-through !important;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\n text-decoration: none;\n border-bottom: 1px dashed;\n}\n.threadContainer {\n margin-left: 20px;\n border-left: 1px solid black;\n}\n.postContainer iframe {\n display: block !important;\n}\n#toggleMsgButton {\n width: 200px;\n display: block;\n text-align: center;\n margin: 0 auto 0;\n}\n.redButton {\n background-color: rgb(255, 173, 173);\n background-image: url(\"http://static.4chan.org/image/buttonfade-red.png\");\n border: 1px solid rgb(196, 88, 88);\n color: rgb(136, 0, 0) !important;\n border-radius: 3px 3px 3px 3px;\n padding: 6px 10px 5px;\n font-weight: bold;\n background-repeat: repeat-x;\n text-decoration: none;\n}\n.updateAlert {\n width: 400px;\n height: 150px;\n text-align: center;\n margin: auto;\n position: absolute;\n left: 0px;\n right: 0px;\n top: 0px;\n bottom: 0px;\n border-radius: 3px;\n padding: 10px;\n box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.4); \n height: 100px !important;\n width: 300px !important;\n padding: 25px !important;\n}\n.updateAlert>span {\n display: block;\n}\n.updateAlert>.dismiss {\n font-size: 14px;\n position: absolute;\n bottom: 0px;\n right: 0px;\n left: 0px;\n}\n.updateAlert>.dismiss:hover {\n cursor:pointer;\n}\n.authors {\n font-size: 12px;\n text-align: right;\n}\n.dear {\n text-align: left;\n font-size: 12px;\n}\n.dismissMessage {\n font-size: 12px;\n opacity: 0.4;\n}\n.alertMessage {\n font-size: 15px;\n text-align: center;\n}\n" + (Conf["Announcement Hiding"] ? '#globalMessage.hidden { display: none; }' : '') + "\n" + (Conf["Custom CSS"] ? Conf["customCSS"] : "") + "\n" + (Conf['Emoji'] ? Style.emoji(Conf['emojiPos']) : '') + " \n" + (Conf['Quick Reply'] && Conf['Hide Original Post Form'] ? '#postForm { display: none; }' : '')); - } - }; - - Get = { - post: function(board, threadID, postID, root, cb, cb2) { - var post, url; - - if (board === g.BOARD && (post = $.id("pc" + postID))) { - post = Get.cleanPost(post.cloneNode(true)); - if (cb2) { - cb2(Main.preParse(post)); - } - $.add(root, post); - return; - } - root.innerHTML = "
Loading post No." + postID + "...
"; - if (threadID) { - return $.cache("//api.4chan.org/" + board + "/res/" + threadID + ".json", function() { - return Get.parsePost(this, board, threadID, postID, root, cb); - }); - } else if (url = Redirect.post(board, postID)) { - return $.cache(url, function() { - return Get.parseArchivedPost(this, board, postID, root, cb); - }); - } - }, - parsePost: function(req, board, threadID, postID, root, cb) { - var post, postNode, posts, spoilerRange, status, url, _i, _len; - - status = req.status; - if (status !== 200) { - if (url = Redirect.post(board, postID)) { - $.cache(url, function() { - return Get.parseArchivedPost(this, board, postID, root, cb); - }); - } else { - $.addClass(root, 'warning'); - root.innerHTML = status === 404 ? "
Thread No." + threadID + " 404'd.
" : "
Error " + req.status + ": " + req.statusText + ".
"; - } - return; - } - posts = JSON.parse(req.response).posts; - if (spoilerRange = posts[0].custom_spoiler) { - Build.spoilerRange[board] = spoilerRange; - } - postID = +postID; - for (_i = 0, _len = posts.length; _i < _len; _i++) { - post = posts[_i]; - if (post.no === postID) { - break; - } - if (post.no > postID) { - if (url = Redirect.post(board, postID)) { - $.cache(url, function() { - return Get.parseArchivedPost(this, board, postID, root, cb); - }); - } else { - $.addClass(root, 'warning'); - root.textContent = "Post No." + postID + " was not found."; - } - return; - } - } - post = Main.preParse(postNode = Get.cleanPost(Build.postFromObject(post, board))); - if (cb) { - cb(post, root); - } - return $.replace(root.firstChild, postNode); - }, - parseArchivedPost: function(req, board, postID, root, cb) { - var bq, comment, data, o, post, postNode, _ref; - - data = JSON.parse(req.response); - if (data.error) { - $.addClass(root, 'warning'); - root.textContent = data.error; - return; - } - bq = $.el('blockquote', { - textContent: data.comment - }); - bq.innerHTML = bq.innerHTML.replace(/\n|\[\/?b\]|\[\/?spoiler\]|\[\/?code\]|\[\/?moot\]|\[\/?banned\]/g, function(text) { - switch (text) { - case '\n': - return '
'; - case '[b]': - return ''; - case '[/b]': - return ''; - case '[spoiler]': - return ''; - case '[/spoiler]': - return ''; - case '[code]': - return '
';
-          case '[/code]':
-            return '
'; - case '[moot]': - return '
'; - case '[/moot]': - return '
'; - case '[banned]': - return ''; - case '[/banned]': - return ''; - } - }); - comment = bq.innerHTML.replace(/(^|>)(>[^<$]*)(<|$)/g, '$1$2$3'); - o = { - postID: postID, - threadID: data.thread_num, - board: board, - name: data.name_processed, - capcode: (function() { - switch (data.capcode) { - case 'M': - return 'mod'; - case 'A': - return 'admin'; - case 'D': - return 'developer'; - } - })(), - tripcode: data.trip, - uniqueID: data.poster_hash, - email: data.email ? encodeURI(data.email.replace(/"/g, '"')) : '', - subject: data.title_processed, - flagCode: data.poster_country, - flagName: data.poster_country_name_processed, - date: data.fourchan_date, - dateUTC: data.timestamp, - comment: comment - }; - if ((_ref = data.media) != null ? _ref.media_filename : void 0) { - o.file = { - name: data.media.media_filename_processed, - timestamp: data.media.media_orig, - url: data.media.media_link || data.media.remote_media_link, - height: data.media.media_h, - width: data.media.media_w, - MD5: data.media.media_hash, - size: data.media.media_size, - turl: data.media.thumb_link || ("//thumbs.4chan.org/" + board + "/thumb/" + data.media.preview_orig), - theight: data.media.preview_h, - twidth: data.media.preview_w, - isSpoiler: data.media.spoiler === '1' - }; - } - post = Main.preParse(postNode = Get.cleanPost(Build.post(o, true))); - if (cb) { - cb(post, root); - } - return $.replace(root.firstChild, postNode); - }, - cleanPost: function(root) { - var child, el, els, inline, inlined, now, post, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2; - - post = $('.post', root); - _ref = __slice.call(root.childNodes); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - child = _ref[_i]; - if (child !== post) { - $.rm(child); - } - } - _ref1 = $$('.inline', post); - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - inline = _ref1[_j]; - $.rm(inline); - } - _ref2 = $$('.inlined', post); - for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { - inlined = _ref2[_k]; - $.rmClass(inlined, 'inlined'); - } - now = Date.now(); - els = $$('[id]', root); - els.push(root); - for (_l = 0, _len3 = els.length; _l < _len3; _l++) { - el = els[_l]; - el.id = "" + now + "_" + el.id; - } - $.rmClass(root, 'forwarded'); - $.rmClass(root, 'qphl'); - $.rmClass(post, 'highlight'); - $.rmClass(post, 'qphl'); - root.hidden = post.hidden = false; - return root; - }, - title: function(thread) { - var el, op, span; - - op = $('.op', thread); - el = $('.postInfo .subject', op); - if (!el.textContent) { - el = $('blockquote', op); - if (!el.textContent) { - el = $('.nameBlock', op); - } - } - span = $.el('span', { - innerHTML: el.innerHTML.replace(/
/g, ' ') - }); - return "/" + g.BOARD + "/ - " + (span.textContent.trim()); - } - }; - - Build = { - spoilerRange: {}, - shortFilename: function(filename, isOP) { - var threshold; - - threshold = isOP ? 40 : 30; - if (filename.length - 4 > threshold) { - return "" + filename.slice(0, threshold - 5) + "(...)." + filename.slice(-3); - } else { - return filename; - } - }, - postFromObject: function(data, board) { - var o; - - o = { - postID: data.no, - threadID: data.resto || data.no, - board: board, - name: data.name, - capcode: data.capcode, - tripcode: data.trip, - uniqueID: data.id, - email: data.email ? encodeURI(data.email.replace(/"/g, '"')) : '', - subject: data.sub, - flagCode: data.country, - flagName: data.country_name, - date: data.now, - dateUTC: data.time, - comment: data.com, - isSticky: !!data.sticky, - isClosed: !!data.closed - }; - if (data.ext || data.filedeleted) { - o.file = { - name: data.filename + data.ext, - timestamp: "" + data.tim + data.ext, - url: "//images.4chan.org/" + board + "/src/" + data.tim + data.ext, - height: data.h, - width: data.w, - MD5: data.md5, - size: data.fsize, - turl: "//thumbs.4chan.org/" + board + "/thumb/" + data.tim + "s.jpg", - theight: data.tn_h, - twidth: data.tn_w, - isSpoiler: !!data.spoiler, - isDeleted: !!data.filedeleted - }; - } - return Build.post(o); - }, - post: function(o, isArchived) { - /* - This function contains code from 4chan-JS (https://github.com/4chan/4chan-JS). - @license: https://github.com/4chan/4chan-JS/blob/master/LICENSE - */ - - var a, board, capcode, capcodeClass, capcodeStart, closed, comment, container, date, dateUTC, email, emailEnd, emailStart, ext, file, fileDims, fileHTML, fileInfo, fileSize, fileThumb, filename, flag, flagCode, flagName, href, imgSrc, isClosed, isOP, isSticky, name, postID, quote, shortFilename, spoilerRange, staticPath, sticky, subject, threadID, tripcode, uniqueID, userID, _i, _len, _ref; - - postID = o.postID, threadID = o.threadID, board = o.board, name = o.name, capcode = o.capcode, tripcode = o.tripcode, uniqueID = o.uniqueID, email = o.email, subject = o.subject, flagCode = o.flagCode, flagName = o.flagName, date = o.date, dateUTC = o.dateUTC, isSticky = o.isSticky, isClosed = o.isClosed, comment = o.comment, file = o.file; - isOP = postID === threadID; - staticPath = '//static.4chan.org'; - if (email) { - emailStart = ''; - emailEnd = ''; - } else { - emailStart = ''; - emailEnd = ''; - } - subject = "" + (subject || '') + ""; - userID = !capcode && uniqueID ? (" (ID: ") + ("" + uniqueID + ") ") : ''; - switch (capcode) { - case 'admin': - case 'admin_highlight': - capcodeClass = " capcodeAdmin"; - capcodeStart = " ## Admin"; - capcode = (" "; - break; - case 'mod': - capcodeClass = " capcodeMod"; - capcodeStart = " ## Mod"; - capcode = (" "; - break; - case 'developer': - capcodeClass = " capcodeDeveloper"; - capcodeStart = " ## Developer"; - capcode = (" "; - break; - default: - capcodeClass = ''; - capcodeStart = ''; - capcode = ''; - } - flag = flagCode ? ("  + flagCode + ") : ''; - if (file != null ? file.isDeleted : void 0) { - fileHTML = isOP ? ("
") + ("File deleted.") + "
" : ("
") + ("File deleted.") + "
"; - } else if (file) { - ext = file.name.slice(-3); - if (!file.twidth && !file.theight && ext === 'gif') { - file.twidth = file.width; - file.theight = file.height; - } - fileSize = $.bytesToString(file.size); - fileThumb = file.turl; - if (file.isSpoiler) { - fileSize = "Spoiler Image, " + fileSize; - if (!isArchived) { - fileThumb = '//static.4chan.org/image/spoiler'; - if (spoilerRange = Build.spoilerRange[board]) { - fileThumb += ("-" + board) + Math.floor(1 + spoilerRange * Math.random()); - } - fileThumb += '.png'; - file.twidth = file.theight = 100; - } - } - imgSrc = ("") + ("" + fileSize + ""); - a = $.el('a', { - innerHTML: file.name - }); - filename = a.textContent.replace(/%22/g, '"'); - a.textContent = Build.shortFilename(filename); - shortFilename = a.innerHTML; - a.textContent = filename; - filename = a.innerHTML.replace(/'/g, '''); - fileDims = ext === 'pdf' ? 'PDF' : "" + file.width + "x" + file.height; - fileInfo = ("File: " + file.timestamp + "") + ("-(" + fileSize + ", " + fileDims + (file.isSpoiler ? '' : ", " + shortFilename + "")) + ")"; - fileHTML = "
" + fileInfo + "
" + imgSrc + "
"; - } else { - fileHTML = ''; - } - tripcode = tripcode ? " " + tripcode + "" : ''; - sticky = isSticky ? ' Sticky' : ''; - closed = isClosed ? ' Closed' : ''; - container = $.el('div', { - id: "pc" + postID, - className: "postContainer " + (isOP ? 'op' : 'reply') + "Container", - innerHTML: (isOP ? '' : "
>>
") + ("
") + (isOP ? fileHTML : '') + ("' + (isOP ? '' : fileHTML) + ("
" + (comment || '') + "
") + '
' - }); - _ref = $$('.quotelink', container); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - quote = _ref[_i]; - href = quote.getAttribute('href'); - if (href[0] === '/') { - continue; - } - quote.href = "/" + board + "/res/" + href; - } - return container; - } - }; - - Main = { - init: function() { - var key, now, path, pathname, settings, temp, val, _conf; - - Main.flatten(null, Config); - for (key in Conf) { - val = Conf[key]; - Conf[key] = $.get(key, val); - } - path = location.pathname; - pathname = path.slice(1).split('/'); - g.BOARD = pathname[0], temp = pathname[1]; - switch (temp) { - case 'res': - g.REPLY = true; - g.THREAD_ID = pathname[2]; - break; - case 'catalog': - g.CATALOG = true; - } - if (['b', 'd', 'e', 'gif', 'h', 'hc', 'hm', 'hr', 'pol', 'r', 'r9k', 'rs', 's', 's4s', 'soc', 't', 'u', 'y'].contains(g.BOARD)) { - g.TYPE = 'nsfw'; - } - _conf = Conf; - if (_conf["Interval per board"]) { - Conf["Interval_" + g.BOARD] = $.get("Interval_" + g.BOARD, Conf["Interval"]); - Conf["BGInterval_" + g.BOARD] = $.get("BGInterval_" + g.BOARD, Conf["BGInteval"]); - } - switch (location.hostname) { - case 'sys.4chan.org': - if (/report/.test(location.search)) { - $.ready(function() { - var field, form; - - form = $('form'); - field = $.id('recaptcha_response_field'); - $.on(field, 'keydown', function(e) { - if (e.keyCode === 8 && !e.target.value) { - return $.globalEval('Recaptcha.reload()'); - } - }); - return $.on(form, 'submit', function(e) { - var response; - - e.preventDefault(); - response = field.value.trim(); - if (!/\s/.test(response)) { - field.value = "" + response + " " + response; - } - return form.submit(); - }); - }); - } - return; - case 'images.4chan.org': - $.ready(function() { - var url; - - if (/^4chan - 404/.test(d.title) && _conf['404 Redirect']) { - path = location.pathname.split('/'); - url = Redirect.image(path[1], path[3]); - if (url) { - return location.href = url; - } - } - }); - return; - } - userNavigation = $.get("userNavigation", Navigation); - Main.prune(); - now = Date.now(); - if (_conf['Check for Updates'] && $.get('lastUpdate', 0) < now - 18 * $.HOUR) { - $.ready(function() { - $.on(window, 'message', Main.message); - $.set('lastUpdate', now); - return $.add(d.head, $.el('script', { - src: 'https://github.com/zixaphir/appchan-x/raw/4chanX/latest.js' - })); - }); - } - settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; - settings.disableAll = true; - localStorage.setItem('4chan-settings', JSON.stringify(settings)); - Main.polyfill(); - if (g.CATALOG) { - return $.ready(Main.catalog); - } else { - return Main.features(); - } - }, - polyfill: function() { - var event, prefix, property; - - if (!('visibilityState' in document)) { - prefix = 'mozVisibilityState' in document ? 'moz' : 'webkitVisibilityState' in document ? 'webkit' : 'o'; - property = prefix + 'VisibilityState'; - event = prefix + 'visibilitychange'; - d.visibilityState = d[property]; - d.hidden = d.visibilityState === 'hidden'; - return $.on(d, event, function() { - d.visibilityState = d[property]; - d.hidden = d.visibilityState === 'hidden'; - return $.event(d, new CustomEvent('visibilitychange')); - }); - } - }, - catalog: function() { - var _conf; - - _conf = Conf; - if (_conf['Catalog Links']) { - CatalogLinks.init(); - } - if (_conf['Thread Hiding']) { - ThreadHiding.init(); - } - return $.ready(function() { - var a, nav, _i, _len, _ref; - - if (_conf['Custom Navigation']) { - CustomNavigation.init(); - } - _ref = ['boardNavDesktop', 'boardNavDesktopFoot']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - nav = _ref[_i]; - if (a = $("a[href*='/" + g.BOARD + "/']", $.id(nav))) { - $.addClass(a, 'current'); - } - } - }); - }, - features: function() { - var _conf; - - _conf = Conf; - Emoji.init(); - Style.init(); - if (_conf['Filter']) { - Filter.init(); - } - if (_conf['Reply Hiding']) { - ReplyHiding.init(); - } - if (_conf['Reply Hiding'] || _conf['Reply Hiding Link'] || _conf['Filter']) { - StrikethroughQuotes.init(); - QuotePreview.callbacks.push(ReplyHiding.unhide); - QuoteInline.callbacks.push(ReplyHiding.unhide); - } - if (_conf['Anonymize']) { - Anonymize.init(); - } - if (_conf['Time Formatting']) { - Time.init(); - } - if (Conf['Relative Post Dates']) { - RelativeDates.init(); - } - if (_conf['File Info Formatting']) { - FileInfo.init(); - } - if (_conf['Sauce']) { - Sauce.init(); - } - if (_conf['Reveal Spoilers']) { - RevealSpoilers.init(); - } - if (_conf['Image Auto-Gif']) { - AutoGif.init(); - } - if (_conf['Png Thumbnail Fix']) { - PngFix.init(); - } - if (_conf['Image Hover']) { - ImageHover.init(); - } - if (_conf['Menu']) { - Menu.init(); - if (_conf['Report Link']) { - ReportLink.init(); - } - if (_conf['Delete Link']) { - DeleteLink.init(); - } - if (_conf['Filter']) { - Filter.menuInit(); - } - if (_conf['Archive Link']) { - ArchiveLink.init(); - } - if (_conf['Download Link']) { - DownloadLink.init(); - } - if (_conf['Embed Link']) { - EmbedLink.init(); - } - if (_conf['Thread Hiding Link']) { - ThreadHideLink.init(); - } - if (_conf['Reply Hiding Link']) { - ReplyHideLink.init(); - } - } - if (_conf['Linkify']) { - Linkify.init(); - } - if (_conf['Resurrect Quotes']) { - Quotify.init(); - } - if (_conf['Remove Spoilers']) { - RemoveSpoilers.init(); - } - if (_conf['Quote Inline']) { - QuoteInline.init(); - } - if (_conf['Quote Preview']) { - QuotePreview.init(); - } - if (_conf['Quote Backlinks']) { - QuoteBacklink.init(); - } - if (_conf['Indicate Own Posts']) { - MarkOwn.init(); - } - if (_conf['Indicate OP quote']) { - QuoteOP.init(); - } - if (_conf['Indicate Cross-thread Quotes']) { - QuoteCT.init(); - } - if (_conf['Color user IDs']) { - IDColor.init(); - } - if (_conf['Replace GIF'] || _conf['Replace PNG'] || _conf['Replace JPG']) { - ImageReplace.init(); - } - return $.ready(Main.featuresReady); - }, - featuresReady: function() { - var a, board, nav, node, nodes, now, ready, _conf, _i, _j, _len, _len1, _ref, _ref1; - - _conf = Conf; - if (/^4chan - 404/.test(d.title)) { - if (_conf['404 Redirect'] && /^\d+$/.test(g.THREAD_ID)) { - location.href = Redirect.to({ - board: g.BOARD, - threadID: g.THREAD_ID, - postID: location.hash - }); - } - return; - } - if (!$.id('navtopright')) { - return; - } - $.addClass(d.body, $.engine); - $.addClass(d.body, 'fourchan_x'); - if (_conf['Custom Navigation']) { - CustomNavigation.init(); - } - _ref = ['boardNavDesktop', 'boardNavDesktopFoot']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - nav = _ref[_i]; - if (a = $("a[href*='/" + g.BOARD + "/']", $.id(nav))) { - $.addClass(a, 'current'); - } - } - now = Date.now(); - UpdateAlert.init(); - Favicon.init(); - Options.init(); - if (_conf['Quick Reply']) { - QR.init(); - } - if (_conf['Image Expansion']) { - ImageExpand.init(); - } - if (_conf['Catalog Links']) { - CatalogLinks.init(); - } - if (_conf['Thread Watcher']) { - Watcher.init(); - } - if (_conf['Keybinds']) { - Keybinds.init(); - } - if (_conf['Fappe Tyme']) { - FappeTyme.init(); - } - if (_conf['Announcement Hiding']) { - AnnouncementHiding.init(); - } - if (g.REPLY) { - if (_conf['Prefetch']) { - Prefetch.init(); - } - if (_conf['Thread Updater']) { - Updater.init(); - } - if (_conf['Thread Stats']) { - ThreadStats.init(); - } - if (_conf['Reply Navigation']) { - Nav.init(); - } - if (_conf['Post in Title']) { - TitlePost.init(); - } - if (_conf['Unread Count'] || _conf['Unread Favicon']) { - Unread.init(); - } - } else { - if (_conf['Thread Hiding']) { - ThreadHiding.init(); - } - if (_conf['Thread Expansion']) { - ExpandThread.init(); - } - if (_conf['Comment Expansion']) { - ExpandComment.init(); - } - if (_conf['Index Navigation']) { - Nav.init(); - } - } - board = $('.board'); - nodes = []; - ready = function() { - if (d.readyState === "complete") { - return true; - } - return false; - }; - _ref1 = $$('.postContainer', board); - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - node = _ref1[_j]; - Main.node(Main.preParse(node), ready); - } - if (MutationObserver) { - Main.observer = new MutationObserver(Main.observe); - Main.observer.observe(board, { - childList: true, - subtree: true - }); - $.ready(function() { - return Main.observer.disconnect(); - }); - } else { - $.on(board, 'DOMNodeInserted', Main.listener); - $.ready(function() { - return $.off(board, 'DOMNodeInserted', Main.listener); - }); - } - }, - prune: function() { - var cutoff, hiddenThreads, id, now, ownedPosts, timestamp, titles, _ref; - - now = Date.now(); - g.hiddenReplies = $.get("hiddenReplies/" + g.BOARD + "/", {}); - if ($.get('lastChecked', 0) < now - 1 * $.DAY) { - $.set('lastChecked', now); - cutoff = now - 7 * $.DAY; - hiddenThreads = $.get("hiddenThreads/" + g.BOARD + "/", {}); - ownedPosts = $.get('ownedPosts', {}); - titles = $.get('CachedTitles', {}); - for (id in hiddenThreads) { - timestamp = hiddenThreads[id]; - if (timestamp < cutoff) { - delete hiddenThreads[id]; - } - } - _ref = g.hiddenReplies; - for (id in _ref) { - timestamp = _ref[id]; - if (timestamp < cutoff) { - delete g.hiddenReplies[id]; - } - } - for (id in ownedPosts) { - timestamp = ownedPosts[id]; - if (timestamp < cutoff) { - delete ownedPosts[id]; - } - } - for (id in titles) { - if (titles[id][1] < cutoff) { - delete titles[id]; - } - } - $.set("hiddenThreads/" + g.BOARD + "/", hiddenThreads); - $.set("hiddenReplies/" + g.BOARD + "/", g.hiddenReplies); - $.set('CachedTitles', titles); - return $.set('ownedPosts', ownedPosts); - } - }, - flatten: function(parent, obj) { - var key, val; - - if (obj instanceof Array) { - Conf[parent] = obj[0]; - } else if (typeof obj === 'object') { - for (key in obj) { - val = obj[key]; - Main.flatten(key, val); - } - } else { - Conf[parent] = obj; - } - }, - message: function(e) { - var version, xupdate; - - version = e.data.version; - if (version && version !== Main.version) { - xupdate = $.el('div', { - id: 'xupdater', - className: 'reply', - innerHTML: "An updated version of Appchan X (v" + version + ") is available. dismiss" - }); - $.on($('#dismiss_xupdate', xupdate), 'click', function() { - return $.rm(xupdate); - }); - return $.prepend($.id('delform'), xupdate); - } - }, - preParse: function(node) { - var el, img, imgParent, parent, parentClass, post; - - parentClass = (parent = node.parentElement) ? parent.className : ""; - el = $('.post', node); - post = { - root: node, - el: el, - "class": el.className, - ID: el.id.match(/\d+$/)[0], - threadID: g.THREAD_ID || (parent ? $.x('ancestor::div[parent::div[@class="board"]]', node).id.match(/\d+$/)[0] : void 0), - isArchived: parentClass.contains('archivedPost'), - isInlined: /\binline\b/.test(parentClass), - isCrosspost: parentClass.contains('crosspost'), - blockquote: el.lastElementChild, - quotes: el.getElementsByClassName('quotelink'), - backlinks: el.getElementsByClassName('backlink'), - fileInfo: false, - img: false - }; - if (img = $('img[data-md5]', el)) { - imgParent = img.parentNode; - post.img = img; - post.fileInfo = imgParent.previousElementSibling; - post.hasPdf = /\.pdf$/.test(imgParent.href); - } - Main.prettify(post.blockquote); - return post; - }, - node: function(node, notify) { - var callback, err, _i, _len, _ref; - - _ref = Main.callbacks; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - callback = _ref[_i]; - try { - callback(node); - } catch (_error) { - err = _error; - if (notify) { - alert("4chan X has experienced an error. You can help by sending this snippet to:\nhttps://github.com/zixaphir/appchan-x/issues\n\n" + Main.version + "\n" + window.location + "\n" + navigator.userAgent + "\n\n" + err + "\n" + err.stack); - } - } - } - }, - observe: function(mutations) { - var addedNode, mutation, nodes, _i, _len, _results; - - nodes = []; - _results = []; - for (_i = 0, _len = mutations.length; _i < _len; _i++) { - mutation = mutations[_i]; - _results.push((function() { - var _j, _len1, _ref, _results1; - - _ref = mutation.addedNodes; - _results1 = []; - for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { - addedNode = _ref[_j]; - if (/\bpostContainer\b/.test(addedNode.className)) { - _results1.push(Main.node(Main.preParse(addedNode))); - } - } - return _results1; - })()); - } - return _results; - }, - listener: function(e) { - var target; - - target = e.target; - if (/\bpostContainer\b/.test(target.className)) { - return Main.node(Main.preParse(target)); - } - }, - prettify: function(bq) { - var code; - - if (!Main.hasCodeTags) { - return; - } - switch (g.BOARD) { - case 'g': - code = function() { - var pre, _i, _len, _ref; - - _ref = document.getElementById('_id_').getElementsByClassName('prettyprint'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - pre = _ref[_i]; - pre.innerHTML = prettyPrintOne(pre.innerHTML.replace(/\s/g, ' ')); - } - }; - break; - case 'sci': - code = function() { - jsMath.Process(document.getElementById('_id_')); - }; - break; - default: - return; - } - return $.globalEval(("" + code).replace('_id_', bq.id)); - }, - namespace: '4chan_x.', - version: '1.0.11', - callbacks: [] - }; - - Main.init(); - -}).call(this);